<Merge branch 'master' of git-server:jerry

This commit is contained in:
e.gavrin 2014-08-06 15:11:08 +04:00
commit 8dcafe6239
7 changed files with 812 additions and 197 deletions

View File

@ -45,8 +45,7 @@ export TARGET_MODES = debug debug_release release
export TARGET_PC_SYSTEMS = linux
export TARGET_MCU_SYSTEMS = $(addprefix stm32f,4) # now only stm32f4 is supported, to add, for example, to stm32f3, change to $(addprefix stm32f,3 4)
export TARGET_PC_MODS = libc_raw musl sanitize valgrind \
libc_raw-sanitize libc_raw-valgrind \
export TARGET_PC_MODS = musl sanitize valgrind \
musl-valgrind
export TARGET_MCU_MODS =

View File

@ -50,6 +50,13 @@ TARGET_DIR=$(OUT_DIR)/$(TARGET_MODE).$(TARGET_SYSTEM_AND_MODS)
# Options setup
#
# Is MCU target?
ifeq ($(filter-out $(TARGET_MCU_SYSTEMS),$(TARGET_SYSTEM)),)
OPTION_MCU = enable
else
OPTION_MCU = disable
endif
# DWARF version
ifeq ($(dwarf4),1)
OPTION_DWARF4 := enable
@ -79,6 +86,10 @@ endif
# -fdiagnostics-color=always
ifeq ($(color),1)
ifeq ($(OPTION_MCU),enable)
$(error MCU target doesn\'t support coloring compiler's output)
endif
OPTION_COLOR := enable
else
OPTION_COLOR := disable
@ -102,31 +113,18 @@ else
OPTION_OPTIMIZE = disable
endif
# Is MCU target?
ifeq ($(filter-out $(TARGET_MCU_SYSTEMS),$(TARGET_SYSTEM)),)
OPTION_MCU = enable
else
OPTION_MCU = disable
endif
ifeq ($(filter musl,$(TARGET_MODS)), musl)
OPTION_LIBC_MUSL := enable
else
OPTION_LIBC_MUSL := disable
endif
ifeq ($(filter libc_raw,$(TARGET_MODS)), libc_raw)
ifeq ($(OPTION_LIBC_MUSL),enable)
$(error LIBC_RAW and LIBC_MUSL are mutually exclusive)
ifeq ($(OPTION_MCU),enable)
$(error MCU target doesn\'t support LIBC_MUSL)
endif
OPTION_LIBC_RAW := enable
OPTION_LIBC := musl
else
OPTION_LIBC_RAW := disable
OPTION_LIBC := raw
endif
ifeq ($(filter sanitize,$(TARGET_MODS)), sanitize)
ifeq ($(OPTION_LIBC_MUSL),enable)
ifeq ($(OPTION_LIBC),musl)
$(error ASAN and LIBC_MUSL are mutually exclusive)
endif
@ -266,6 +264,21 @@ INCLUDES_JERRY = \
-I src/liboptimizer \
-I src/libcoreint
# libc
ifeq ($(OPTION_LIBC),musl)
CC := musl-$(CC)
DEFINES_JERRY += -DLIBC_MUSL
CFLAGS_COMMON += -static
else
DEFINES_JERRY += -DLIBC_RAW
CFLAGS_COMMON += -nostdlib
ifeq ($(OPTION_SANITIZE),enable)
CFLAGS_COMMON += -fsanitize=address
LDFLAGS += -lasan
endif
endif
ifeq ($(OPTION_NDEBUG),enable)
DEFINES_JERRY += -DJERRY_NDEBUG
endif
@ -273,35 +286,15 @@ endif
ifeq ($(OPTION_MCU),disable)
DEFINES_JERRY += -D__TARGET_HOST_x64 -DJERRY_SOURCE_BUFFER_SIZE=$$((1024*1024))
CFLAGS_COMMON += -fno-stack-protector
ifeq ($(OPTION_LIBC_MUSL),enable)
CC := musl-$(CC)
DEFINES_JERRY += -DLIBC_MUSL
CFLAGS_COMMON += -static
else
ifeq ($(OPTION_SANITIZE),enable)
CFLAGS_COMMON += -fsanitize=address
endif
ifeq ($(OPTION_LIBC_RAW),enable)
DEFINES_JERRY += -DLIBC_RAW
CFLAGS_COMMON += -nostdlib
ifeq ($(OPTION_SANITIZE),enable)
LDFLAGS += -lasan
endif
else
CFLAGS_COMMON += -DLIBC_STD
endif
endif
ifeq ($(OPTION_COLOR),enable)
CFLAGS_COMMON += -fdiagnostics-color=always
endif
else
CFLAGS_COMMON += -ffunction-sections -fdata-sections -nostdlib
DEFINES_JERRY += -D__TARGET_MCU
endif
ifeq ($(OPTION_COLOR),enable)
CFLAGS_COMMON += -fdiagnostics-color=always
endif
ifeq ($(OPTION_TODO),enable)
DEFINES_JERRY += -DJERRY_PRINT_TODO
endif
@ -404,7 +397,7 @@ $(TESTS_TARGET):
@for unit_test in $(SOURCES_UNITTESTS); \
do \
cmd="$(CC) $(DEFINES_JERRY) $(CFLAGS_COMMON) $(CFLAGS_JERRY) \
$(INCLUDES_JERRY) $(INCLUDES_THIRDPARTY) $(TARGET_DIR)/obj/*.o $(UNITTESTS_SRC_DIR)/$$unit_test.c -o $(TARGET_DIR)/$$unit_test"; \
$(INCLUDES_JERRY) $(INCLUDES_THIRDPARTY) $(TARGET_DIR)/obj/*.o $(UNITTESTS_SRC_DIR)/$$unit_test.c -lc -o $(TARGET_DIR)/$$unit_test"; \
if [ "$(OPTION_ECHO)" = "enable" ]; then echo $$cmd; echo; fi; \
$$cmd; \
if [ $$? -ne 0 ]; then echo Failed "'$$cmd'"; exit 1; fi; \

View File

@ -0,0 +1,699 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Jerry printf implementation
*/
#include "globals.h"
#include "jerry-libc.h"
#include <stdarg.h>
/**
* printf's length type
*/
typedef enum
{
LIBC_PRINTF_ARG_LENGTH_TYPE_NONE, /**< (none) */
LIBC_PRINTF_ARG_LENGTH_TYPE_HH, /**< hh */
LIBC_PRINTF_ARG_LENGTH_TYPE_H, /**< h */
LIBC_PRINTF_ARG_LENGTH_TYPE_L, /**< l */
LIBC_PRINTF_ARG_LENGTH_TYPE_LL, /**< ll */
LIBC_PRINTF_ARG_LENGTH_TYPE_J, /**< j */
LIBC_PRINTF_ARG_LENGTH_TYPE_Z, /**< z */
LIBC_PRINTF_ARG_LENGTH_TYPE_T, /**< t */
LIBC_PRINTF_ARG_LENGTH_TYPE_HIGHL /**< L */
} libc_printf_arg_length_type_t;
/**
* printf's flags mask
*/
typedef uint8_t libc_printf_arg_flags_mask_t;
/**
* Left justification of field's contents
*/
#define LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY ( 1 << 0 )
/**
* Force print of number's sign
*/
#define LIBC_PRINTF_ARG_FLAG_PRINT_SIGN ( 1 << 1 )
/**
* If no sign is printed, print space before value
*/
#define LIBC_PRINTF_ARG_FLAG_SPACE ( 1 << 2 )
/**
* For o, x, X preceed value with 0, 0x or 0X for non-zero values.
*/
#define LIBC_PRINTF_ARG_FLAG_SHARP ( 1 << 3 )
/**
* Left-pad field with zeroes instead of spaces
*/
#define LIBC_PRINTF_ARG_FLAG_ZERO_PADDING ( 1 << 4 )
/**
* printf helper function that outputs a char
*/
static void
libc_printf_putchar( _FILE *stream, /**< stream pointer */
char character) /**< character */
{
__fwrite( &character, 1, sizeof(character), stream);
} /* libc_printf_putchar */
/**
* printf helper function that outputs justified string
*/
static void
libc_printf_justified_string_output( _FILE *stream, /**< stream pointer */
const char *string_p, /**< string */
size_t width, /**< minimum field width */
bool is_left_justify, /**< justify to left (true) or right (false) */
bool is_zero_padding) /**< left-pad with zeroes (true) or spaces (false) */
{
const size_t str_length = __strlen( string_p);
size_t outputted_length = 0;
if ( !is_left_justify )
{
char padding_char = is_zero_padding ? '0' : ' ';
while ( outputted_length + str_length < width )
{
libc_printf_putchar( stream, padding_char);
outputted_length++;
}
}
__fwrite( string_p, 1, str_length * sizeof(*string_p), stream);
outputted_length += str_length;
if ( is_left_justify )
{
while( outputted_length < width )
{
libc_printf_putchar( stream, ' ');
outputted_length++;
}
}
} /* libc_printf_justified_string_output */
/**
* printf helper function that converts unsigned integer to string
*/
static char*
libc_printf_uint_to_string( uintmax_t value, /**< integer value */
char *buffer_p, /**< buffer for output string */
size_t buffer_size, /**< buffer size */
const char *alphabet, /**< alphabet used for digits */
uint32_t radix) /**< radix */
{
char *str_buffer_end = buffer_p + buffer_size;
char *str_p = str_buffer_end;
*--str_p = '\0';
JERRY_ASSERT( radix >= 2 );
if ( ( radix & ( radix - 1 ) ) != 0 )
{
/*
* Radix is not power of 2. Only 32-bit numbers are supported in this mode.
*/
JERRY_ASSERT( ( value >> 32 ) == 0 );
uint32_t value_lo = (uint32_t) value;
while ( value_lo != 0 )
{
JERRY_ASSERT ( str_p != buffer_p );
*--str_p = alphabet[ value_lo % radix ];
value_lo /= radix;
}
}
else
{
uint32_t shift = 0;
while ( !( radix & ( 1u << shift ) ) )
{
shift++;
JERRY_ASSERT( shift <= 32 );
}
uint32_t value_lo = (uint32_t) value;
uint32_t value_hi = (uint32_t) ( value >> 32 );
while ( value_lo != 0
|| value_hi != 0 )
{
JERRY_ASSERT ( str_p != buffer_p );
*--str_p = alphabet[ value_lo & ( radix - 1 ) ];
value_lo >>= shift;
value_lo += ( value_hi & ( radix - 1 ) ) << ( 32 - shift );
value_hi >>= shift;
}
}
if ( *str_p == '\0' )
{
*--str_p = '0';
}
JERRY_ASSERT( str_p >= buffer_p && str_p < str_buffer_end );
return str_p;
} /* libc_printf_uint_to_string */
/**
* printf helper function that prints d and i arguments
*
* @return updated va_list
*/
static void
libc_printf_write_d_i( _FILE *stream, /**< stream pointer */
va_list* args_list_p, /**< args' list */
libc_printf_arg_flags_mask_t flags, /**< field's flags */
libc_printf_arg_length_type_t length, /**< field's length type */
uint32_t width) /**< minimum field width to output */
{
JERRY_ASSERT( ( flags & LIBC_PRINTF_ARG_FLAG_SHARP ) == 0 );
bool is_signed = true;
uintmax_t value = 0;
/* true - positive, false - negative */
bool sign = true;
const uintmax_t value_sign_mask = ((uintmax_t)1) << ( sizeof(value) * JERRY_BITSINBYTE - 1 );
switch ( length )
{
case LIBC_PRINTF_ARG_LENGTH_TYPE_NONE:
value = (uintmax_t)va_arg( *args_list_p, int);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_HH:
value = (uintmax_t)va_arg( *args_list_p, int); /* char is promoted to int */
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_H:
value = (uintmax_t)va_arg( *args_list_p, int); /* short int is promoted to int */
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_L:
value = (uintmax_t)va_arg( *args_list_p, long int);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_LL:
value = (uintmax_t)va_arg( *args_list_p, long long int);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_J:
value = (uintmax_t)va_arg( *args_list_p, intmax_t);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_Z:
is_signed = false;
value = (uintmax_t)va_arg( *args_list_p, size_t);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_T:
is_signed = false;
value = (uintmax_t)va_arg( *args_list_p, ptrdiff_t);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_HIGHL:
JERRY_UNREACHABLE();
}
if ( is_signed )
{
sign = ( ( value & value_sign_mask ) == 0 );
if ( !sign )
{
value = (uintmax_t) (-value);
}
}
char str_buffer[ 32 ];
const char *string_p = libc_printf_uint_to_string( value,
str_buffer,
sizeof(str_buffer),
"0123456789",
10);
if ( !sign
|| ( flags & LIBC_PRINTF_ARG_FLAG_PRINT_SIGN ) )
{
/* printing sign */
libc_printf_putchar( stream, sign ? '+' : '-' );
if ( width > 0 )
{
width--;
}
}
else if ( flags & LIBC_PRINTF_ARG_FLAG_SPACE )
{
/* no sign and space flag, printing one space */
libc_printf_putchar( stream, ' ');
if ( width > 0 )
{
width--;
}
}
libc_printf_justified_string_output( stream,
string_p,
width,
flags & LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY,
flags & LIBC_PRINTF_ARG_FLAG_ZERO_PADDING);
} /** libc_printf_write_d_i */
/**
* printf helper function that prints d and i arguments
*
* @return updated va_list
*/
static void
libc_printf_write_u_o_x_X( _FILE *stream, /**< stream pointer */
char specifier, /**< specifier (u, o, x, X) */
va_list* args_list_p, /**< args' list */
libc_printf_arg_flags_mask_t flags, /**< field's flags */
libc_printf_arg_length_type_t length, /**< field's length type */
uint32_t width) /**< minimum field width to output */
{
uintmax_t value = 0;
switch ( length )
{
case LIBC_PRINTF_ARG_LENGTH_TYPE_NONE:
value = (uintmax_t)va_arg( *args_list_p, unsigned int);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_HH:
value = (uintmax_t)va_arg( *args_list_p, unsigned int); /* char is promoted to int */
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_H:
value = (uintmax_t)va_arg( *args_list_p, unsigned int); /* short int is promoted to int */
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_L:
value = (uintmax_t)va_arg( *args_list_p, unsigned long int);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_LL:
value = (uintmax_t)va_arg( *args_list_p, unsigned long long int);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_J:
value = (uintmax_t)va_arg( *args_list_p, uintmax_t);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_Z:
value = (uintmax_t)va_arg( *args_list_p, size_t);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_T:
value = (uintmax_t)va_arg( *args_list_p, ptrdiff_t);
break;
case LIBC_PRINTF_ARG_LENGTH_TYPE_HIGHL:
JERRY_UNREACHABLE();
}
if ( flags & LIBC_PRINTF_ARG_FLAG_SHARP )
{
if ( value != 0 && specifier != 'u' )
{
libc_printf_putchar( stream, '0');
if ( specifier == 'x' )
{
libc_printf_putchar( stream, 'x');
}
else if ( specifier == 'X' )
{
libc_printf_putchar( stream, 'X');
}
else
{
JERRY_ASSERT( specifier == 'o' );
}
}
}
uint32_t radix = 10;
const char *alphabet;
switch ( specifier )
{
case 'u':
alphabet = "0123456789";
radix = 10;
break;
case 'o':
alphabet = "01234567";
radix = 8;
break;
case 'x':
alphabet = "0123456789abcdef";
radix = 16;
break;
case 'X':
alphabet = "0123456789ABCDEF";
radix = 16;
break;
default:
JERRY_UNREACHABLE();
}
char str_buffer[ 32 ];
const char *string_p = libc_printf_uint_to_string( value,
str_buffer,
sizeof(str_buffer),
alphabet,
radix);
if ( flags & LIBC_PRINTF_ARG_FLAG_PRINT_SIGN )
{
/* printing sign */
libc_printf_putchar( stream, '+');
if ( width > 0 )
{
width--;
}
}
else if ( flags & LIBC_PRINTF_ARG_FLAG_SPACE )
{
/* no sign and space flag, printing one space */
libc_printf_putchar( stream, ' ');
if ( width > 0 )
{
width--;
}
}
libc_printf_justified_string_output( stream,
string_p,
width,
flags & LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY,
flags & LIBC_PRINTF_ARG_FLAG_ZERO_PADDING);
} /** libc_printf_write_u_o_x_X */
/**
* vfprintf
*
* @return number of characters printed
*/
static int
__vfprintf( _FILE *stream, /**< stream pointer */
const char *format, /**< format string */
va_list args) /**< arguments */
{
va_list args_copy;
va_copy( args_copy, args);
const char *format_iter_p = format;
while ( *format_iter_p )
{
if ( *format_iter_p != '%' )
{
libc_printf_putchar( stream, *format_iter_p);
}
else
{
libc_printf_arg_flags_mask_t flags = 0;
uint32_t width = 0;
libc_printf_arg_length_type_t length = LIBC_PRINTF_ARG_LENGTH_TYPE_NONE;
while ( true )
{
format_iter_p++;
if ( *format_iter_p == '-' )
{
flags |= LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY;
}
else if ( *format_iter_p == '+' )
{
flags |= LIBC_PRINTF_ARG_FLAG_PRINT_SIGN;
}
else if ( *format_iter_p == ' ' )
{
flags |= LIBC_PRINTF_ARG_FLAG_SPACE;
}
else if ( *format_iter_p == '#' )
{
flags |= LIBC_PRINTF_ARG_FLAG_SHARP;
}
else if ( *format_iter_p == '0' )
{
flags |= LIBC_PRINTF_ARG_FLAG_ZERO_PADDING;
}
else
{
break;
}
}
if ( *format_iter_p == '*' )
{
JERRY_UNIMPLEMENTED();
}
// If there is a number, recognize it as field width
while ( *format_iter_p >= '0' && *format_iter_p <= '9' )
{
width = width * 10u + (uint32_t) (*format_iter_p - '0');
format_iter_p++;
}
if ( *format_iter_p == '.' )
{
JERRY_UNIMPLEMENTED();
}
switch ( *format_iter_p )
{
case 'h':
format_iter_p++;
if ( *format_iter_p == 'h' )
{
format_iter_p++;
length = LIBC_PRINTF_ARG_LENGTH_TYPE_HH;
}
else
{
length = LIBC_PRINTF_ARG_LENGTH_TYPE_H;
}
break;
case 'l':
format_iter_p++;
if ( *format_iter_p == 'l' )
{
format_iter_p++;
length = LIBC_PRINTF_ARG_LENGTH_TYPE_LL;
}
else
{
length = LIBC_PRINTF_ARG_LENGTH_TYPE_L;
}
break;
case 'j':
format_iter_p++;
length = LIBC_PRINTF_ARG_LENGTH_TYPE_J;
break;
case 'z':
format_iter_p++;
length = LIBC_PRINTF_ARG_LENGTH_TYPE_Z;
break;
case 't':
format_iter_p++;
length = LIBC_PRINTF_ARG_LENGTH_TYPE_T;
break;
case 'L':
format_iter_p++;
length = LIBC_PRINTF_ARG_LENGTH_TYPE_HIGHL;
break;
}
switch ( *format_iter_p )
{
case 'd':
case 'i':
libc_printf_write_d_i( stream, &args_copy, flags, length, width);
break;
case 'u':
case 'o':
case 'x':
case 'X':
libc_printf_write_u_o_x_X( stream, *format_iter_p, &args_copy, flags, length, width);
break;
case 'f':
case 'F':
case 'e':
case 'E':
case 'g':
case 'G':
case 'a':
case 'A':
JERRY_UNIMPLEMENTED();
break;
case 'c':
if ( length & LIBC_PRINTF_ARG_LENGTH_TYPE_L )
{
JERRY_UNIMPLEMENTED();
}
else
{
char str[2] =
{
(char)va_arg( args_copy, int), /* char is promoted to int */
'\0'
};
libc_printf_justified_string_output( stream,
str,
width,
flags & LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY,
flags & LIBC_PRINTF_ARG_FLAG_ZERO_PADDING);
}
break;
case 's':
if ( length & LIBC_PRINTF_ARG_LENGTH_TYPE_L )
{
JERRY_UNIMPLEMENTED();
}
else
{
char *str_p = va_arg( args_copy, char*);
libc_printf_justified_string_output( stream,
str_p,
width,
flags & LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY,
flags & LIBC_PRINTF_ARG_FLAG_ZERO_PADDING);
}
break;
case 'p':
{
va_list args_copy2;
va_copy( args_copy2, args_copy);
void *value = va_arg( args_copy2, void*);
va_end( args_copy2);
if ( value == NULL )
{
__printf( "(nil)");
}
else
{
libc_printf_write_u_o_x_X( stream,
'x',
&args_copy,
flags | LIBC_PRINTF_ARG_FLAG_SHARP,
LIBC_PRINTF_ARG_LENGTH_TYPE_Z,
width);
}
}
break;
case 'n':
JERRY_UNIMPLEMENTED();
break;
}
}
format_iter_p++;
}
va_end( args_copy);
return 0;
} /* __vfprintf */
/**
* fprintf
*
* @return number of characters printed
*/
int
__fprintf( _FILE *stream, /**< stream pointer */
const char *format, /**< format string */
...) /**< parameters' values */
{
va_list args;
va_start( args, format);
int ret = __vfprintf( stream, format, args);
va_end( args);
return ret;
} /* __fprintf */
/**
* printf
*
* @return number of characters printed
*/
int
__printf( const char *format, /**< format string */
...) /**< parameters' values */
{
va_list args;
va_start( args, format);
int ret = __vfprintf( LIBC_STDOUT, format, args);
va_end( args);
return ret;
} /* __printf */

View File

@ -23,6 +23,42 @@
typedef void _FILE;
#ifdef LIBC_RAW
/**
* stdin file descriptor
*/
#define LIBC_STDIN (_FILE*)0
/**
* stdout file descriptor
*/
#define LIBC_STDOUT (_FILE*)1
/**
* stderr file descriptor
*/
#define LIBC_STDERR (_FILE*)2
#else /* !LIBC_RAW */
extern const _FILE **libc_stdin;
extern const _FILE **libc_stdout;
extern const _FILE **libc_stderr;
/**
* stdin file descriptor
*/
#define LIBC_STDIN ((_FILE*)*libc_stdin)
/**
* stdout file descriptor
*/
#define LIBC_STDOUT ((_FILE*)*libc_stdout)
/**
* stderr file descriptor
*/
#define LIBC_STDERR ((_FILE*)*libc_stderr)
#endif /* !LIBC_RAW */
extern void* __memset (void *s, int c, size_t n);
extern int __memcmp (const void *s1, const void *s2, size_t n);
extern void* __memcpy (void *s1, const void *s2, size_t n);
@ -62,7 +98,6 @@ extern long __ftell(_FILE *);
extern void __rewind(_FILE *);
extern size_t __fread(void *, size_t, size_t, _FILE *);
extern size_t __fwrite(const void *, size_t, size_t, _FILE *);
extern int __ferror(_FILE *);
extern int __fprintf(_FILE *, const char *, ...);
#define DBL_MANT_DIG ( 52)

View File

@ -23,10 +23,10 @@
* mov %rax -> ret
*/
#define SYSCALL_1( syscall_no, arg1, ret) \
__asm ( "syscall" \
: "=a" ( ret ) \
: "a" (syscall_no), "D" (arg1) \
: "rcx", "r11" );
__asm volatile ( "syscall" \
: "=a" ( ret ) \
: "a" (syscall_no), "D" (arg1) \
: "rcx", "r11" );
/*
* mov syscall_no -> %rax
@ -36,10 +36,10 @@
* mov %rax -> ret
*/
#define SYSCALL_2( syscall_no, arg1, arg2, ret) \
__asm ( "syscall" \
: "=a" ( ret ) \
: "a" (syscall_no), "D" (arg1), "S" (arg2) \
: "rcx", "r11" );
__asm volatile ( "syscall" \
: "=a" ( ret ) \
: "a" (syscall_no), "D" (arg1), "S" (arg2) \
: "rcx", "r11" );
/*
* mov syscall_no -> %rax
@ -50,10 +50,10 @@
* mov %rax -> ret
*/
#define SYSCALL_3( syscall_no, arg1, arg2, arg3, ret) \
__asm ( "syscall" \
: "=a" ( ret ) \
: "a" (syscall_no), "D" (arg1), "S" (arg2), "d" (arg3) \
: "rcx", "r11" );
__asm volatile ( "syscall" \
: "=a" ( ret ) \
: "a" (syscall_no), "D" (arg1), "S" (arg2), "d" (arg3) \
: "rcx", "r11" );
#define _START \
mov (%rsp), %rdi; \

View File

@ -39,21 +39,6 @@ FIXME( Rename __unused )
#include <sys/types.h>
#include <fcntl.h>
/**
* stdin file descriptor
*/
#define LIBC_STDIN 0
/**
* stdout file descriptor
*/
#define LIBC_STDOUT 1
/**
* stderr file descriptor
*/
#define LIBC_STDERR 2
/**
* Exit program with ERR_SYSCALL if syscall_ret_val is negative
*/
@ -124,32 +109,11 @@ syscall_3( long int syscall_no, /**< syscall number */
return ret;
} /* syscall_3 */
/**
* printf
*
* @return number of characters printed
*/
int
__printf(const char *format, /**< format string */
...) /**< parameters' values */
{
va_list args;
va_start( args, format);
FIXME( Implement real printf and move it to common part of libruntime );
long int ret = syscall_3( __NR_write, LIBC_STDOUT, (long int)format, (long int)__strlen(format));
va_end( args);
return (int)ret;
} /* __printf */
/** Output of character. Writes the character c, cast to an unsigned char, to stdout. */
int
__putchar (int c)
{
syscall_3( __NR_write, LIBC_STDOUT, (long int)&c, 1);
__fwrite( &c, 1, sizeof(char), LIBC_STDOUT);
return c;
} /* __putchar */
@ -160,9 +124,9 @@ __putchar (int c)
void __noreturn
__exit (int status) /**< status code */
{
syscall_1( __NR_close, LIBC_STDIN);
syscall_1( __NR_close, LIBC_STDOUT);
syscall_1( __NR_close, LIBC_STDERR);
syscall_1( __NR_close, (long int)LIBC_STDIN);
syscall_1( __NR_close, (long int)LIBC_STDOUT);
syscall_1( __NR_close, (long int)LIBC_STDERR);
syscall_1( __NR_exit_group, status);
@ -363,57 +327,20 @@ __fwrite(const void *ptr, /**< data to write */
return bytes_written;
} /* __fwrite */
/**
* fprintf
*
* @return number of characters printed
*/
int
__fprintf(_FILE *stream, /**< stream pointer */
const char *format, /**< format string */
...) /**< parameters' values */
{
va_list args;
va_start( args, format);
long int ret = syscall_3( __NR_write, (long int)stream, (long int)format, (long int)__strlen(format));
va_end( args);
return (int)ret;
} /* __fprintf */
#elif defined(LIBC_STD) || defined(LIBC_MUSL)
#elif defined(LIBC_MUSL)
#include <stdio.h>
#include <stdlib.h>
/**
* printf
*
* @return number of characters printed
*/
int
__printf(const char *format, /**< format string */
...) /**< parameters' values */
{
va_list args;
va_start( args, format);
int ret = vprintf( format, args);
va_end( args);
return ret;
} /* __printf */
const _FILE **libc_stdin = (void*)&stdin;
const _FILE **libc_stdout = (void*)&stdout;
const _FILE **libc_stderr = (void*)&stderr;
/** Output of character. Writes the character c, cast to an unsigned char, to stdout. */
int
__putchar (int c)
{
return __printf ("%c", c);
return putchar( c);
} /* __putchar */
/** exit - cause normal process termination */
@ -519,34 +446,6 @@ __fwrite(const void *ptr, /**< data to write */
return fwrite(ptr, size, nmemb, stream);
} /* __fwrite */
/**
* ferror
*/
int
__ferror(_FILE * fp) /**< stream pointer */
{
return ferror( fp);
} /* __ferror */
/**
* fprintf
*
* @return number of characters printed
*/
int
__fprintf(_FILE *stream, /**< stream pointer */
const char *format, /**< format string */
...) /**< parameters' values */
{
va_list args;
va_start( args, format);
int ret = vfprintf( stream, format, args);
va_end( args);
return ret;
} /* __fprintf */
#endif /* LIBC_STD || LIBC_MUSL */
#else /* !LIBC_RAW && !LIBC_MUSL */
# error "!LIBC_RAW && !LIBC_MUSL"
#endif /* !LIBC_RAW && !LIBC_MUSL */

View File

@ -23,36 +23,11 @@
extern void __noreturn exit(int status);
/**
* printf
*
* @return number of characters printed
*/
int
__printf(const char *format, /**< format string */
...) /**< parameters' values */
{
va_list args;
va_start( args, format);
/**
* TODO: Call internal vprintf implementation when it appears.
*/
int ret = 0;
JERRY_UNIMPLEMENTED();
va_end( args);
return ret;
} /* __printf */
/** Output of character. Writes the character c, cast to an unsigned char, to stdout. */
int
__putchar (int c)
{
return __printf ("%c", c);
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS(c);
} /* __putchar */
/** exit - cause normal process termination */
@ -65,3 +40,18 @@ __exit (int status __unused)
while(true);
} /* __exit */
/**
* fwrite
*
* @return number of bytes written
*/
size_t
__fwrite(const void *ptr, /**< data to write */
size_t size, /**< size of elements to write */
size_t nmemb, /**< number of elements */
_FILE *stream) /**< stream pointer */
{
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS( ptr, size, nmemb, stream);
} /* __fwrite */