diff --git a/configure.py b/configure.py index b1766149..b8bbca9e 100644 --- a/configure.py +++ b/configure.py @@ -227,6 +227,7 @@ cflags_thp = [ # Metrowerks library flags cflags_msl = [ *cflags_base, + "-char signed", "-use_lmw_stmw on", "-str reuse,pool,readonly", "-common off", @@ -681,7 +682,7 @@ config.libs = [ "host": False, "objects": [ Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/abort_exit.c"), - Object(NonMatching, "MSL_C.PPCEABI.bare.H/alloc.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/alloc.c"), Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/errno.c"), Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/ansi_files.c"), Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/ansi_fp.c"), @@ -697,8 +698,8 @@ config.libs = [ Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/misc_io.c"), Object(NonMatching, "MSL_C.PPCEABI.bare.H/printf.c"), Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/float.c"), - Object(NonMatching, "MSL_C.PPCEABI.bare.H/signal.c"), - Object(NonMatching, "MSL_C.PPCEABI.bare.H/string.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/signal.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/string.c"), Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/uart_console_io.c"), Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/wchar_io.c"), Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/e_acos.c"), diff --git a/include/PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/ansi_files.h b/include/PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/ansi_files.h index d101a4bb..a1fb6fdc 100644 --- a/include/PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/ansi_files.h +++ b/include/PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/ansi_files.h @@ -85,7 +85,7 @@ typedef struct _FILE { file_modes file_mode; file_states file_state; - char is_dynamically_allocated; + unsigned char is_dynamically_allocated; char char_buffer; char char_buffer_overflow; char ungetc_buffer[2]; diff --git a/include/string.h b/include/string.h index 6ba311ed..863a4f97 100644 --- a/include/string.h +++ b/include/string.h @@ -10,7 +10,7 @@ char* strrchr(const char* str, int c); char* strchr(const char* str, int c); int strncmp(const char* str1, const char* str2, size_t n); int strcmp(const char* str1, const char* str2); -char* strcat(char* dst, const char* src); +char* strcat(char* dst, const char* src, size_t n); char* strncpy(char* dst, const char* src, size_t n); char* strcpy(char* dst, const char* src); size_t strlen(const char* str); diff --git a/src/MSL_C.PPCEABI.bare.H/alloc.c b/src/MSL_C.PPCEABI.bare.H/alloc.c new file mode 100755 index 00000000..ba041356 --- /dev/null +++ b/src/MSL_C.PPCEABI.bare.H/alloc.c @@ -0,0 +1,410 @@ +#include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/alloc.h" + +typedef struct Block { + struct Block* prev; + struct Block* next; + unsigned long max_size; + unsigned long size; +} Block; + +typedef struct SubBlock { + unsigned long size; + Block* block; + struct SubBlock* prev; + struct SubBlock* next; +} SubBlock; + +struct FixSubBlock; + +typedef struct FixBlock { + struct FixBlock* prev_; + struct FixBlock* next_; + unsigned long client_size_; + struct FixSubBlock* start_; + unsigned long n_allocated_; +} FixBlock; + +typedef struct FixSubBlock { + FixBlock* block_; + struct FixSubBlock* next_; +} FixSubBlock; + +typedef struct FixStart { + FixBlock* tail_; + FixBlock* head_; +} FixStart; + +typedef struct __mem_pool_obj { + Block* start_; + FixStart fix_start[6]; +} __mem_pool_obj; + +typedef struct __mem_pool { + void* reserved[14]; +} __mem_pool; + +typedef signed long tag_word; + +typedef struct block_header { + tag_word tag; + struct block_header * prev; + struct block_header * next; +} block_header; + +typedef struct list_header { + block_header * rover; + block_header header; +} list_header; + +typedef struct heap_header { + struct heap_header* prev; + struct heap_header* next; +} heap_header; + +struct mem_pool_obj; +typedef void * (*sys_alloc_ptr)(unsigned long, struct mem_pool_obj*); +typedef void (*sys_free_ptr)(void *, struct mem_pool_obj*); + +typedef struct pool_options{ + sys_alloc_ptr sys_alloc_func; + sys_free_ptr sys_free_func; + unsigned long min_heap_size; + int always_search_first; +} pool_options; + +typedef struct mem_pool_obj { + list_header free_list; + pool_options options; + heap_header* heap_list; + void* userData; + +} mem_pool_obj; + +mem_pool_obj __malloc_pool; +static int initialized = 0; + +static SubBlock* SubBlock_merge_prev(SubBlock*, SubBlock**); +static void SubBlock_merge_next(SubBlock* , SubBlock** ); + +static const unsigned long fix_pool_sizes[] = {4, 12, 20, 36, 52, 68}; + +#define SubBlock_size(ths) ((ths)->size & 0xFFFFFFF8) +#define SubBlock_block(ths) ((Block*)((unsigned long)((ths)->block) & ~0x1)) +#define Block_size(ths) ((ths)->size & 0xFFFFFFF8) +#define Block_start(ths) (*(SubBlock**)((char*)(ths) + Block_size((ths)) - sizeof(unsigned long))) + +#define SubBlock_set_free(ths) \ + unsigned long this_size = SubBlock_size((ths)); \ + (ths)->size &= ~0x2; \ + *(unsigned long*)((char*)(ths) + this_size) &= ~0x4; \ + *(unsigned long*)((char*)(ths) + this_size - sizeof(unsigned long)) = this_size + + +#define SubBlock_is_free(ths) !((ths)->size & 2) +#define SubBlock_set_size(ths, sz) \ + (ths)->size &= ~0xFFFFFFF8; \ + (ths)->size |= (sz) & 0xFFFFFFF8; \ + if (SubBlock_is_free((ths))) \ + *(unsigned long*)((char*)(ths) + (sz) - sizeof(unsigned long)) = (sz) + +#define SubBlock_from_pointer(ptr) ((SubBlock*)((char*)(ptr) - 8)) +#define FixSubBlock_from_pointer(ptr) ((FixSubBlock*)((char*)(ptr) - 4)) + +#define FixBlock_client_size(ths) ((ths)->client_size_) +#define FixSubBlock_size(ths) (FixBlock_client_size((ths)->block_)) + +#define classify(ptr) (*(unsigned long*)((char*)(ptr) - sizeof(unsigned long)) & 1) +#define __msize_inline(ptr) (!classify(ptr) ? FixSubBlock_size(FixSubBlock_from_pointer(ptr)) : SubBlock_size(SubBlock_from_pointer(ptr)) - 8) + +#define Block_empty(ths) \ + (_sb = (SubBlock*)((char*)(ths) + 16)), \ + SubBlock_is_free(_sb) && SubBlock_size(_sb) == Block_size((ths)) - 24 + +//unused +void Block_subBlock(){ +} + +void Block_link(Block* ths, SubBlock* sb) { + SubBlock** st; + SubBlock_set_free(sb); + st = &Block_start(ths); + + if (*st != 0) + { + sb->prev = (*st)->prev; + sb->prev->next = sb; + sb->next = *st; + (*st)->prev = sb; + *st = sb; + *st = SubBlock_merge_prev(*st, st); + SubBlock_merge_next(*st, st); + } + else + { + *st = sb; + sb->prev = sb; + sb->next = sb; + } + if (ths->max_size < SubBlock_size(*st)) + ths->max_size = SubBlock_size(*st); +} + +static SubBlock* SubBlock_merge_prev(SubBlock *ths, SubBlock **start) { + unsigned long prevsz; + SubBlock* p; + + if (!(ths->size & 0x04)) + { + prevsz = *(unsigned long*)((char*)ths - sizeof(unsigned long)); + if (prevsz & 0x2) + return ths; + p = (SubBlock*)((char*)ths - prevsz); + SubBlock_set_size(p, prevsz + SubBlock_size(ths)); + + if (*start == ths) + *start = (*start)->next; + ths->next->prev = ths->prev; + ths->next->prev->next = ths->next; + return p; + } + return ths; +} + + +static void SubBlock_merge_next(SubBlock *pBlock, SubBlock **pStart) { + SubBlock* next_sub_block; + unsigned long this_cur_size; + + next_sub_block = (SubBlock*)((char*)pBlock + (pBlock->size & 0xFFFFFFF8)); + + if (!(next_sub_block->size & 2)) { + this_cur_size = (pBlock->size & 0xFFFFFFF8) + (next_sub_block->size & 0xFFFFFFF8); + + pBlock->size &= ~0xFFFFFFF8; + pBlock->size |= this_cur_size & 0xFFFFFFF8; + + if (!(pBlock->size & 2)) { + *(unsigned long*)((char*)(pBlock) + (this_cur_size) - 4) = (this_cur_size); + } + + if (!(pBlock->size & 2)) { + *(unsigned long *)((char*)pBlock + this_cur_size) &= ~4; + } + else { + *(unsigned long *)((char*)pBlock + this_cur_size) |= 4; + } + + if (*pStart == next_sub_block) { + *pStart = (*pStart)->next; + } + + if (*pStart == next_sub_block) { + *pStart = 0; + } + + next_sub_block->next->prev = next_sub_block->prev; + next_sub_block->prev->next = next_sub_block->next; + } +} + +static Block* __unlink(__mem_pool_obj* pool_obj, Block* bp) { + Block* result = bp->next; + if (result == bp) { + result = 0; + } + + if (pool_obj->start_ == bp) { + pool_obj->start_ = result; + } + + if (result != 0) { + result->prev = bp->prev; + result->prev->next = result; + } + + bp->next = 0; + bp->prev = 0; + return result; +} + +//unused +void allocate_from_var_pools(){ +} + +//unused +void soft_allocate_from_var_pools(){ +} + +static void deallocate_from_var_pools(__mem_pool_obj* pool_obj, void *ptr) { + SubBlock* sb = SubBlock_from_pointer(ptr); + SubBlock* _sb; + + Block* bp = SubBlock_block(sb); + Block_link(bp, sb); + + if (Block_empty(bp)) { + __unlink(pool_obj, bp); + __sys_free(bp); + } +} + +//unused +void FixBlock_construct(){ +} + +void __init_pool_obj(__mem_pool* pool_obj) { + memset(pool_obj, 0, sizeof(__mem_pool_obj)); +} + + +static __mem_pool* get_malloc_pool(void) { + static __mem_pool protopool; + static unsigned char init = 0; + if (!init) { + __init_pool_obj(&protopool); + init = 1; + } + + return &protopool; +} + +//unused +void allocate_from_fixed_pools(){ +} + +void deallocate_from_fixed_pools(__mem_pool_obj* pool_obj, void* ptr, unsigned long size) { + unsigned long i = 0; + FixSubBlock* p; + FixBlock* b; + FixStart* fs; + + while (size > fix_pool_sizes[i]) { + ++i; + } + + fs = &pool_obj->fix_start[i]; + p = FixSubBlock_from_pointer(ptr); + b = p->block_; + + if (b->start_ == 0 && fs->head_ != b) { + if (fs->tail_ == b) { + fs->head_ = fs->head_->prev_; + fs->tail_ = fs->tail_->prev_; + } + else { + b->prev_->next_ = b->next_; + b->next_->prev_ = b->prev_; + b->next_ = fs->head_; + b->prev_ = b->next_->prev_; + b->prev_->next_ = b; + b->next_->prev_ = b; + fs->head_ = b; + } + } + + p->next_ = b->start_; + b->start_ = p; + + if (--b->n_allocated_ == 0) { + if (fs->head_ == b) { + fs->head_ = b->next_; + } + + if (fs->tail_ == b) { + fs->tail_ = b->prev_; + } + + b->prev_->next_ = b->next_; + b->next_->prev_ = b->prev_; + + if (fs->head_ == b) { + fs->head_ = 0; + } + + if (fs->tail_ == b) { + fs->tail_ = 0; + } + + deallocate_from_var_pools(pool_obj, b); + } +} + +//unused +void __pool_allocate_resize(){ +} + +//unused +void __msize(){ +} + +//unused +void __pool_alloc(){ +} + +//unused +void __allocate_size(){ +} + +//unused +void __allocate(){ +} + +//unused +void __allocate_resize(){ +} + +//unused +void __allocate_expand(){ +} + +void __pool_free(__mem_pool *pool, void *ptr) { + __mem_pool_obj* pool_obj; + unsigned long size; + + if (ptr == 0) { + return; + } + + pool_obj = (__mem_pool_obj*)pool; + size = __msize_inline(ptr); + + if (size <= 68) { + deallocate_from_fixed_pools(pool_obj, ptr, size); + } + else { + deallocate_from_var_pools(pool_obj, ptr); + } +} + +//unused +void __pool_realloc(){ +} + +//unused +void __pool_alloc_clear(){ +} + +//unused +void malloc(){ +} + +void free(void *ptr) { + __pool_free(get_malloc_pool(), ptr); +} + + +//unused +void realloc(){ +} + +//unused +void calloc(){ +} + +//unused +void __pool_free_all(){ +} + +//unused +void __malloc_free_all(){ +} diff --git a/src/MSL_C.PPCEABI.bare.H/printf.c b/src/MSL_C.PPCEABI.bare.H/printf.c index 21d248da..9fa17473 100644 --- a/src/MSL_C.PPCEABI.bare.H/printf.c +++ b/src/MSL_C.PPCEABI.bare.H/printf.c @@ -17,1060 +17,1123 @@ extern void __num2dec(const decform*, double, decimal*); #define TARGET_FLOAT_MANT_DIG LDBL_MANT_DIG #define TARGET_FLOAT_IMPLICIT_J_BIT 1 #define TARGET_FLOAT_MANT_BITS \ - (TARGET_FLOAT_MANT_DIG - TARGET_FLOAT_IMPLICIT_J_BIT) + (TARGET_FLOAT_MANT_DIG - TARGET_FLOAT_IMPLICIT_J_BIT) #define TARGET_FLOAT_EXP_BITS (TARGET_FLOAT_BITS - TARGET_FLOAT_MANT_BITS - 1) enum justification_options { - left_justification, - right_justification, - zero_fill + left_justification, + right_justification, + zero_fill }; enum sign_options { only_minus, sign_always, space_holder }; enum argument_options { - normal_argument, - char_argument, - short_argument, - long_argument, - long_long_argument, - long_double_argument, - wchar_argument + normal_argument, + char_argument, + short_argument, + long_argument, + long_long_argument, + long_double_argument, + wchar_argument }; typedef struct { - unsigned char justification_options; - unsigned char sign_options; - unsigned char precision_specified; - unsigned char alternate_form; - unsigned char argument_options; - unsigned char conversion_char; - int field_width; - int precision; + unsigned char justification_options; + unsigned char sign_options; + unsigned char precision_specified; + unsigned char alternate_form; + unsigned char argument_options; + unsigned char conversion_char; + int field_width; + int precision; } print_format; -static const char* parse_format(const char* format_string, va_list* arg, - print_format* format) -{ - print_format f; - const char* s = format_string; - int c; - int flag_found; - f.justification_options = right_justification; - f.sign_options = only_minus; - f.precision_specified = 0; - f.alternate_form = 0; - f.argument_options = normal_argument; - f.field_width = 0; - f.precision = 0; +static const char* parse_format(const char *format_string, va_list *arg, print_format *format) { + print_format f; + const char* s = format_string; + int c; + int flag_found; + f.justification_options = right_justification; + f.sign_options = only_minus; + f.precision_specified = 0; + f.alternate_form = 0; + f.argument_options = normal_argument; + f.field_width = 0; + f.precision = 0; - if ((c = *++s) == '%') { - f.conversion_char = c; - *format = f; - return ((const char*)s + 1); - } + if ((c = *++s) == '%') { + f.conversion_char = c; + *format = f; + return ((const char*)s + 1); + } - for (;;) { - flag_found = 1; + for (;;) { + flag_found = 1; - switch (c) { - case '-': - f.justification_options = left_justification; - break; - case '+': - f.sign_options = sign_always; - break; - case ' ': - if (f.sign_options != sign_always) { - f.sign_options = space_holder; - } - break; - case '#': - f.alternate_form = 1; - break; - case '0': - if (f.justification_options != left_justification) { - f.justification_options = zero_fill; - } - break; - default: - flag_found = 0; - break; - } + switch (c) { + case '-': + f.justification_options = left_justification; + break; + case '+': + f.sign_options = sign_always; + break; + case ' ': + if (f.sign_options != sign_always) { + f.sign_options = space_holder; + } + break; + case '#': + f.alternate_form = 1; + break; + case '0': + if (f.justification_options != left_justification) { + f.justification_options = zero_fill; + } + break; + default: + flag_found = 0; + break; + } - if (flag_found) { - c = *++s; - } else { - break; - } - } + if (flag_found) { + c = *++s; + } + else { + break; + } + } - if (c == '*') { - if ((f.field_width = va_arg(*arg, int)) < 0) { - f.justification_options = left_justification; - f.field_width = -f.field_width; - } + if (c == '*') { + if ((f.field_width = va_arg(*arg, int)) < 0) { + f.justification_options = left_justification; + f.field_width = -f.field_width; + } - c = *++s; - } else { - while (isdigit(c)) { - f.field_width = (f.field_width * 10) + (c - '0'); - c = *++s; - } - } + c = *++s; + } + else { + while (isdigit(c)) { + f.field_width = (f.field_width * 10) + (c - '0'); + c = *++s; + } + } - if (f.field_width > 509) { - f.conversion_char = 0xFF; - *format = f; - return ((const char*)s + 1); - } + if (f.field_width > 509) { + f.conversion_char = 0xFF; + *format = f; + return ((const char*)s + 1); + } - if (c == '.') { - f.precision_specified = 1; + if (c == '.') { + f.precision_specified = 1; - if ((c = *++s) == '*') { - if ((f.precision = va_arg(*arg, int)) < 0) { - f.precision_specified = 0; - } + if ((c = *++s) == '*') { + if ((f.precision = va_arg(*arg, int)) < 0) { + f.precision_specified = 0; + } - c = *++s; - } else { - while (isdigit(c)) { - f.precision = (f.precision * 10) + (c - '0'); - c = *++s; - } - } - } + c = *++s; + } + else { + while (isdigit(c)) { + f.precision = (f.precision * 10) + (c - '0'); + c = *++s; + } + } + } - flag_found = 1; + flag_found = 1; - switch (c) { - case 'h': - f.argument_options = short_argument; + switch (c) { + case 'h': + f.argument_options = short_argument; - if (s[1] == 'h') { - f.argument_options = char_argument; - c = *++s; - } + if (s[1] == 'h') { + f.argument_options = char_argument; + c = *++s; + } - break; + break; - case 'l': - f.argument_options = long_argument; + case 'l': + f.argument_options = long_argument; - if (s[1] == 'l') { - f.argument_options = long_long_argument; - c = *++s; - } + if (s[1] == 'l') { + f.argument_options = long_long_argument; + c = *++s; + } - break; + break; - case 'L': - f.argument_options = long_double_argument; - break; - default: - flag_found = 0; - break; - } + case 'L': + f.argument_options = long_double_argument; + break; + default: + flag_found = 0; + break; + } - if (flag_found) { - c = *++s; - } + if (flag_found) { + c = *++s; + } - f.conversion_char = c; + f.conversion_char = c; - switch (c) { - case 'd': - case 'i': - case 'u': - case 'o': - case 'x': - case 'X': - if (f.argument_options == long_double_argument) { - f.conversion_char = 0xFF; - break; - } + switch (c) { + case 'd': + case 'i': + case 'u': + case 'o': + case 'x': + case 'X': + if (f.argument_options == long_double_argument) { + f.conversion_char = 0xFF; + break; + } - if (!f.precision_specified) { - f.precision = 1; - } else if (f.justification_options == zero_fill) { - f.justification_options = right_justification; - } - break; + if (!f.precision_specified) { + f.precision = 1; + } + else if (f.justification_options == zero_fill) { + f.justification_options = right_justification; + } + break; - case 'f': - if (f.argument_options == short_argument - || f.argument_options == long_long_argument) { - f.conversion_char = 0xFF; - break; - } + case 'f': + case 'F': + if (f.argument_options == short_argument || f.argument_options == long_long_argument) { + f.conversion_char = 0xFF; + break; + } - if (!f.precision_specified) { - f.precision = 6; - } - break; + if (!f.precision_specified) { + f.precision = 6; + } + break; - case 'g': - case 'G': - if (!f.precision) { - f.precision = 1; - } + case 'a': + case 'A': + if (!f.precision_specified) { + f.precision = 0xD; + } - case 'e': - case 'E': - if (f.argument_options == short_argument - || f.argument_options == long_long_argument - || f.argument_options == char_argument) { - f.conversion_char = 0xFF; - break; - } + if (f.argument_options == short_argument || f.argument_options == long_long_argument || f.argument_options == char_argument) { + f.conversion_char = 0xFF; + } - if (!f.precision_specified) { - f.precision = 6; - } - break; + break; - case 'p': - f.conversion_char = 'x'; - f.alternate_form = 1; - f.argument_options = long_argument; - f.precision = 8; - break; + case 'g': + case 'G': + if (!f.precision) { + f.precision = 1; + } - case 'c': - if (f.argument_options == long_argument) { - f.argument_options = wchar_argument; - } else { - if (f.precision_specified - || f.argument_options != normal_argument) { - f.conversion_char = 0xFF; - } - } + case 'e': + case 'E': + if (f.argument_options == short_argument || f.argument_options == long_long_argument || f.argument_options == char_argument) { + f.conversion_char = 0xFF; + break; + } - break; + if (!f.precision_specified) { + f.precision = 6; + } + break; - case 's': - if (f.argument_options == long_argument) { - f.argument_options = wchar_argument; - } else { - if (f.argument_options != normal_argument) { - f.conversion_char = 0xFF; - } - } + case 'p': + f.conversion_char = 'x'; + f.alternate_form = 1; + f.argument_options = long_argument; + f.precision = 8; + break; - break; + case 'c': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } + else { + if (f.precision_specified || f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } - case 'n': - if (f.argument_options == long_double_argument) { - f.conversion_char = 0xFF; - } + break; - break; + case 's': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } + else { + if (f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } - default: - f.conversion_char = 0xFF; - break; - } + break; - *format = f; - return ((const char*)s + 1); + case 'n': + if (f.argument_options == long_double_argument) { + f.conversion_char = 0xFF; + } + + break; + + default: + f.conversion_char = 0xFF; + break; + } + + *format = f; + return ((const char*)s + 1); } -static char* long2str(signed long num, char* buff, print_format* format) +static char* long2str(long num, char* buff, print_format format) { - unsigned long unsigned_num, base; - char* p; - int n, digits; - int minus = 0; - unsigned_num = num; - minus = 0; + unsigned long unsigned_num, base; + char* p; + int n, digits; + int minus = 0; + unsigned_num = num; + minus = 0; - p = buff; - *--p = 0; - digits = 0; + p = buff; + *--p = 0; + digits = 0; - if (!num && !format->precision - && !(format->alternate_form && format->conversion_char == 'o')) { - return p; - } + if (!num && !format.precision + && !(format.alternate_form && format.conversion_char == 'o')) { + return p; + } - switch (format->conversion_char) { - case 'd': - case 'i': - base = 10; + switch (format.conversion_char) { + case 'd': + case 'i': + base = 10; - if (num < 0) { - unsigned_num = -unsigned_num; - minus = 1; - } - break; + if (num < 0) { + unsigned_num = -unsigned_num; + minus = 1; + } + break; - case 'o': - base = 8; - format->sign_options = only_minus; - break; + case 'o': + base = 8; + format.sign_options = only_minus; + break; - case 'u': - base = 10; - format->sign_options = only_minus; - break; + case 'u': + base = 10; + format.sign_options = only_minus; + break; - case 'x': - case 'X': - base = 16; - format->sign_options = only_minus; - break; - } + case 'x': + case 'X': + base = 16; + format.sign_options = only_minus; + break; + } - do { - n = unsigned_num % base; - unsigned_num /= base; + do { + n = unsigned_num % base; + unsigned_num /= base; - if (n < 10) { - n += '0'; - } else { - n -= 10; + if (n < 10) { + n += '0'; + } else { + n -= 10; - if (format->conversion_char == 'x') { - n += 'a'; - } else { - n += 'A'; - } - } + if (format.conversion_char == 'x') { + n += 'a'; + } else { + n += 'A'; + } + } - *--p = n; - ++digits; - } while (unsigned_num != 0); + *--p = n; + ++digits; + } while (unsigned_num != 0); - if (base == 8 && format->alternate_form && *p != '0') { - *--p = '0'; - ++digits; - } + if (base == 8 && format.alternate_form && *p != '0') { + *--p = '0'; + ++digits; + } - if (format->justification_options == zero_fill) { - format->precision = format->field_width; + if (format.justification_options == zero_fill) { + format.precision = format.field_width; - if (minus || format->sign_options != only_minus) - --format->precision; + if (minus || format.sign_options != only_minus) + --format.precision; - if (base == 16 && format->alternate_form) - format->precision -= 2; - } + if (base == 16 && format.alternate_form) + format.precision -= 2; + } - if (buff - p + format->precision > 509) - return (0); + if (buff - p + format.precision > 509) + return (0); - while (digits < format->precision) { - *--p = '0'; - ++digits; - } + while (digits < format.precision) { + *--p = '0'; + ++digits; + } - if (base == 16 && format->alternate_form) { - *--p = format->conversion_char; - *--p = '0'; - } + if (base == 16 && format.alternate_form) { + *--p = format.conversion_char; + *--p = '0'; + } - if (minus) { - *--p = '-'; - } else if (format->sign_options == sign_always) { - *--p = '+'; - } else if (format->sign_options == space_holder) { - *--p = ' '; - } + if (minus) { + *--p = '-'; + } else if (format.sign_options == sign_always) { + *--p = '+'; + } else if (format.sign_options == space_holder) { + *--p = ' '; + } - return p; + return p; } -static char* longlong2str(signed long long num, char* pBuf, print_format* fmt) +static char* longlong2str(long long num, char* pBuf, print_format fmt) { - unsigned long long unsigned_num, base; - char* p; - int n, digits; - int minus = 0; - unsigned_num = num; - minus = 0; - p = pBuf; - *--p = 0; - digits = 0; + unsigned long long unsigned_num, base; + char* p; + int n, digits; + int minus = 0; + unsigned_num = num; + minus = 0; + p = pBuf; + *--p = 0; + digits = 0; - if (!num && !fmt->precision - && !(fmt->alternate_form && fmt->conversion_char == 'o')) { - return p; - } + if (!num && !fmt.precision + && !(fmt.alternate_form && fmt.conversion_char == 'o')) { + return p; + } - switch (fmt->conversion_char) { - case 'd': - case 'i': - base = 10; + switch (fmt.conversion_char) { + case 'd': + case 'i': + base = 10; - if (num < 0) { - unsigned_num = -unsigned_num; - minus = 1; - } - break; - case 'o': - base = 8; - fmt->sign_options = only_minus; - break; - case 'u': - base = 10; - fmt->sign_options = only_minus; - break; - case 'x': - case 'X': - base = 16; - fmt->sign_options = only_minus; - break; - } + if (num < 0) { + unsigned_num = -unsigned_num; + minus = 1; + } + break; + case 'o': + base = 8; + fmt.sign_options = only_minus; + break; + case 'u': + base = 10; + fmt.sign_options = only_minus; + break; + case 'x': + case 'X': + base = 16; + fmt.sign_options = only_minus; + break; + } - do { - n = unsigned_num % base; - unsigned_num /= base; + do { + n = unsigned_num % base; + unsigned_num /= base; - if (n < 10) { - n += '0'; - } else { - n -= 10; - if (fmt->conversion_char == 'x') { - n += 'a'; - } else { - n += 'A'; - } - } + if (n < 10) { + n += '0'; + } else { + n -= 10; + if (fmt.conversion_char == 'x') { + n += 'a'; + } else { + n += 'A'; + } + } - *--p = n; - ++digits; - } while (unsigned_num != 0); + *--p = n; + ++digits; + } while (unsigned_num != 0); - if (base == 8 && fmt->alternate_form && *p != '0') { - *--p = '0'; - ++digits; - } + if (base == 8 && fmt.alternate_form && *p != '0') { + *--p = '0'; + ++digits; + } - if (fmt->justification_options == zero_fill) { - fmt->precision = fmt->field_width; + if (fmt.justification_options == zero_fill) { + fmt.precision = fmt.field_width; - if (minus || fmt->sign_options != only_minus) { - --fmt->precision; - } + if (minus || fmt.sign_options != only_minus) { + --fmt.precision; + } - if (base == 16 && fmt->alternate_form) { - fmt->precision -= 2; - } - } + if (base == 16 && fmt.alternate_form) { + fmt.precision -= 2; + } + } - if (pBuf - p + fmt->precision > 509) { - return 0; - } + if (pBuf - p + fmt.precision > 509) { + return 0; + } - while (digits < fmt->precision) { - *--p = '0'; - ++digits; - } + while (digits < fmt.precision) { + *--p = '0'; + ++digits; + } - if (base == 16 && fmt->alternate_form) { - *--p = fmt->conversion_char; - *--p = '0'; - } + if (base == 16 && fmt.alternate_form) { + *--p = fmt.conversion_char; + *--p = '0'; + } - if (minus) { - *--p = '-'; - } else if (fmt->sign_options == sign_always) { - *--p = '+'; - } else if (fmt->sign_options == space_holder) { - *--p = ' '; - } + if (minus) { + *--p = '-'; + } else if (fmt.sign_options == sign_always) { + *--p = '+'; + } else if (fmt.sign_options == space_holder) { + *--p = ' '; + } - return p; + return p; } +static char * double2hex(long double num, char * buff, print_format format); + static void round_decimal(decimal* dec, int new_length) { - char c; - char* p; - int carry; + char c; + char* p; + int carry; - if (new_length < 0) { - return_zero: - dec->sign = 0; - dec->exp = 0; - dec->sig.length = 1; - *dec->sig.text = '0'; - return; - } + if (new_length < 0) { + return_zero: + dec->exp = 0; + dec->sig.length = 1; + *dec->sig.text = '0'; + return; + } - if (new_length >= dec->sig.length) { - return; - } + if (new_length >= dec->sig.length) { + return; + } - p = (char*)dec->sig.text + new_length + 1; - c = *--p - '0'; + p = (char*)dec->sig.text + new_length + 1; + c = *--p - '0'; - if (c == 5) { - char* q = &((char*)dec->sig.text)[dec->sig.length]; + if (c == 5) { + char* q = &((char*)dec->sig.text)[dec->sig.length]; - while (--q > p && *q == '0') - ; - carry = (q == p) ? p[-1] & 1 : 1; - } else { - carry = (c > 5); - } + while (--q > p && *q == '0') + ; + carry = (q == p) ? p[-1] & 1 : 1; + } else { + carry = (c > 5); + } - while (new_length != 0) { - c = *--p - '0' + carry; + while (new_length != 0) { + c = *--p - '0' + carry; - if ((carry = (c > 9)) != 0 || c == 0) { - --new_length; - } else { - *p = c + '0'; - break; - } - } + if ((carry = (c > 9)) != 0 || c == 0) { + --new_length; + } else { + *p = c + '0'; + break; + } + } - if (carry != 0) { - dec->exp += 1; - dec->sig.length = 1; - *dec->sig.text = '1'; - return; - } else if (new_length == 0) { - goto return_zero; - } + if (carry != 0) { + dec->exp += 1; + dec->sig.length = 1; + *dec->sig.text = '1'; + return; + } else if (new_length == 0) { + goto return_zero; + } - dec->sig.length = new_length; + dec->sig.length = new_length; } -static char* float2str(va_list arg, char* buff, print_format* format, - int vecIndex) -{ - decimal dec; - decform form; - char* p; - char* q; - int n, digits, sign; - int int_digits, frac_digits; - long double num; +static char* float2str(long double num, char *buff, print_format format) { + decimal dec; + decform form; + char* p; + char* q; + int n, digits, sign; + int int_digits, frac_digits; - if (format->argument_options == long_double_argument) { - num = va_arg(arg, long double); - } else { - num = va_arg(arg, double); - } + if (format.precision > 509) { + return 0; + } - if (format->precision > 509) { - return 0; - } + form.style = 0; + form.digits = 0x20; + __num2dec(&form, num, &dec); + p = (char*)dec.sig.text + dec.sig.length; - form.style = 0; - form.digits = 0x20; - __num2dec(&form, num, &dec); - p = (char*)dec.sig.text + dec.sig.length; + while (dec.sig.length > 1 && *--p == '0') { + --dec.sig.length; + ++dec.exp; + } - while (dec.sig.length > 1 && *--p == '0') { - --dec.sig.length; - ++dec.exp; - } + switch (*dec.sig.text) { + case '0': + dec.exp = 0; + break; + case 'I': + if (num < 0) { + p = buff - 5; - switch (*dec.sig.text) { - case '0': - dec.exp = 0; - break; - case 'I': - if (num < 0) { - p = buff - 5; - strcpy(p, "-Inf"); - } else { - p = buff - 4; - strcpy(p, "Inf"); - } + if (isupper(format.conversion_char)) { + strcpy(p, "-INF"); + } + else { + strcpy(p, "-inf"); + } + } + else { + p = buff - 4; + if (isupper(format.conversion_char)) { + strcpy(p, "INF"); + } + else { + strcpy(p, "inf"); + } + } - return p; + return p; - case 'N': - p = buff - 4; - strcpy(p, "NaN"); - return p; - } + case 'N': + if (dec.sign) { + p = buff - 5; - dec.exp += dec.sig.length - 1; - p = buff; - *--p = 0; + if (isupper(format.conversion_char)) { + strcpy(p, "-NAN"); + } + else { + strcpy(p, "-nan"); + } + } + else { + p = buff - 4; + if (isupper(format.conversion_char)) { + strcpy(p, "NAN"); + } + else { + strcpy(p, "nan"); + } + } - switch (format->conversion_char) { - case 'g': - case 'G': + return p; + } - if (dec.sig.length > format->precision) { - round_decimal(&dec, format->precision); - } + dec.exp += dec.sig.length - 1; + p = buff; + *--p = 0; - if (dec.exp < -4 || dec.exp >= format->precision) { - if (format->alternate_form) { - --format->precision; - } else { - format->precision = dec.sig.length - 1; - } + switch (format.conversion_char) + { + case 'g': + case 'G': - if (format->conversion_char == 'g') { - format->conversion_char = 'e'; - } else { - format->conversion_char = 'E'; - } + if (dec.sig.length > format.precision) { + round_decimal(&dec, format.precision); + } - goto e_format; - } + if (dec.exp < -4 || dec.exp >= format.precision) + { + if (format.alternate_form) { + --format.precision; + } + else { + format.precision = dec.sig.length - 1; + } - if (format->alternate_form) { - format->precision -= dec.exp + 1; - } else { - if ((format->precision = dec.sig.length - (dec.exp + 1)) < 0) { - format->precision = 0; - } - } + if (format.conversion_char == 'g') { + format.conversion_char = 'e'; + } + else { + format.conversion_char = 'E'; + } - goto f_format; + goto e_format; + } - case 'e': - case 'E': - e_format: + if (format.alternate_form) { + format.precision -= dec.exp + 1; + } + else { + if ((format.precision = dec.sig.length - (dec.exp + 1)) < 0) { + format.precision = 0; + } + } - if (dec.sig.length > format->precision + 1) { - round_decimal(&dec, format->precision + 1); - } + goto f_format; - n = dec.exp; - sign = '+'; + case 'e': + case 'E': + e_format: - if (n < 0) { - n = -n; - sign = '-'; - } + if (dec.sig.length > format.precision + 1) { + round_decimal(&dec, format.precision + 1); + } - for (digits = 0; n || digits < 2; ++digits) { - *--p = n % 10 + '0'; - n /= 10; - } + n = dec.exp; + sign = '+'; - *--p = sign; - *--p = format->conversion_char; + if (n < 0) { + n = -n; + sign = '-'; + } - if (buff - p + format->precision > 509) { - return 0; - } + for (digits = 0; n || digits < 2; ++digits) { + *--p = n % 10 + '0'; + n /= 10; + } - if (dec.sig.length < format->precision + 1) { - for (n = format->precision + 1 - dec.sig.length + 1; --n;) { - *--p = '0'; - } - } + *--p = sign; + *--p = format.conversion_char; - for (n = dec.sig.length, q = (char*)dec.sig.text + dec.sig.length; - --n;) { - *--p = *--q; - } + if (buff - p + format.precision > 509) { + return 0; + } - if (format->precision || format->alternate_form) { - *--p = '.'; - } + if (dec.sig.length < format.precision + 1) { + for (n = format.precision + 1 - dec.sig.length + 1; --n;) { + *--p = '0'; + } + } - *--p = *dec.sig.text; + for (n = dec.sig.length, q = (char*)dec.sig.text + dec.sig.length; --n;) { + *--p = *--q; + } - if (dec.sign) - *--p = '-'; - else if (format->sign_options == sign_always) - *--p = '+'; - else if (format->sign_options == space_holder) - *--p = ' '; + if (format.precision || format.alternate_form) { + *--p = '.'; + } - break; + *--p = *dec.sig.text; - case 'f': - f_format: + if (dec.sign) + *--p = '-'; + else if (format.sign_options == sign_always) + *--p = '+'; + else if (format.sign_options == space_holder) + *--p = ' '; - if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0) - frac_digits = 0; + break; - if (frac_digits > format->precision) { - round_decimal(&dec, - dec.sig.length - (frac_digits - format->precision)); + case 'f': + case 'F': + f_format: - if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0) - frac_digits = 0; - } + if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0) + frac_digits = 0; - if ((int_digits = dec.exp + 1) < 0) - int_digits = 0; + if (frac_digits > format.precision) { + round_decimal(&dec, dec.sig.length - (frac_digits - format.precision)); - if (int_digits + frac_digits > 509) - return 0; + if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0) + frac_digits = 0; + } - q = (char*)dec.sig.text + dec.sig.length; + if ((int_digits = dec.exp + 1) < 0) + int_digits = 0; - for (digits = 0; digits < (format->precision - frac_digits); ++digits) - *--p = '0'; + if (int_digits + frac_digits > 509) + return 0; - for (digits = 0; digits < frac_digits && digits < dec.sig.length; - ++digits) - *--p = *--q; + q = (char *) dec.sig.text + dec.sig.length; - for (; digits < frac_digits; ++digits) - *--p = '0'; + for (digits = 0; digits < (format.precision - frac_digits); ++digits) + *--p = '0'; - if (format->precision || format->alternate_form) - *--p = '.'; + for (digits = 0; digits < frac_digits && digits < dec.sig.length; ++digits) + *--p = *--q; - if (int_digits) { - for (digits = 0; digits < int_digits - dec.sig.length; ++digits) { - *--p = '0'; - } + for (; digits < frac_digits; ++digits) + *--p = '0'; - for (; digits < int_digits; ++digits) { - *--p = *--q; - } - } else { - *--p = '0'; - } + if (format.precision || format.alternate_form) + *--p = '.'; - if (dec.sign) { - *--p = '-'; - } else if (format->sign_options == sign_always) { - *--p = '+'; - } else if (format->sign_options == space_holder) { - *--p = ' '; - } + if (int_digits) { + for (digits = 0; digits < int_digits - dec.sig.length; ++digits) { + *--p = '0'; + } - break; - } + for (; digits < int_digits; ++digits) { + *--p = *--q; + } + } + else { + *--p = '0'; + } - return p; + if (dec.sign) { + *--p = '-'; + } + else if (format.sign_options == sign_always) { + *--p = '+'; + } + else if (format.sign_options == space_holder) { + *--p = ' '; + } + + break; + } + + return p; } -static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), - void* WriteProcArg, const char* format_str, va_list arg) -{ - int num_chars, chars_written, field_width; - const char* format_ptr; - const char* curr_format; - print_format format; - signed long long_num; - signed long long long_long_num; - char buff[512]; - char* buff_ptr; - char* string_end; - char fill_char = ' '; +static int __pformatter(void *(*WriteProc)(void *, const char *, size_t), void *WriteProcArg, const char * format_str, va_list arg) { + int num_chars, chars_written, field_width; + const char* format_ptr; + const char* curr_format; + print_format format; + long long_num; + long long long_long_num; + long double long_double_num; + char buff[512]; + char* buff_ptr; + char* string_end; + char fill_char = ' '; - format_ptr = format_str; - chars_written = 0; + format_ptr = format_str; + chars_written = 0; - while (*format_ptr) { - if (!(curr_format = strchr(format_ptr, '%'))) { - num_chars = strlen(format_ptr); - chars_written += num_chars; + while (*format_ptr) { + if (!(curr_format = strchr(format_ptr, '%'))) { + num_chars = strlen(format_ptr); + chars_written += num_chars; - if (num_chars - && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) { - return -1; - } + if (num_chars && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) { + return -1; + } - break; - } + break; + } - num_chars = curr_format - format_ptr; - chars_written += num_chars; + num_chars = curr_format - format_ptr; + chars_written += num_chars; - if (num_chars && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) { - return -1; - } + if (num_chars && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) { + return -1; + } - format_ptr = curr_format; - format_ptr = parse_format(format_ptr, (va_list*)arg, &format); + format_ptr = curr_format; + format_ptr = parse_format(format_ptr, (va_list*)arg, &format); - switch (format.conversion_char) { - case 'd': - case 'i': - if (format.argument_options == long_argument) { - long_num = va_arg(arg, signed long); - } else if (format.argument_options == long_long_argument) { - long_long_num = va_arg(arg, signed long long); - } else { - long_num = va_arg(arg, int); - } + switch (format.conversion_char) { + case 'd': + case 'i': + if (format.argument_options == long_argument) { + long_num = va_arg(arg, long); + } + else if (format.argument_options == long_long_argument) { + long_long_num = va_arg(arg, long long); + } + else { + long_num = va_arg(arg, int); + } - if (format.argument_options == short_argument) { - long_num = (signed short)long_num; - } + if (format.argument_options == short_argument) { + long_num = (short)long_num; + } - if (format.argument_options == char_argument) { - long_num = (signed char)long_num; - } + if (format.argument_options == char_argument) { + long_num = (signed char)long_num; + } - if (format.argument_options == long_long_argument) { - if (!(buff_ptr - = longlong2str(long_long_num, buff + 512, &format))) { - goto conversion_error; - } - } else { - if (!(buff_ptr = long2str(long_num, buff + 512, &format))) { - goto conversion_error; - } - } + if (format.argument_options == long_long_argument) { + if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) { + goto conversion_error; + } + } + else { + if (!(buff_ptr = long2str(long_num, buff + 512, format))) { + goto conversion_error; + } + } - num_chars = buff + 512 - 1 - buff_ptr; - break; + num_chars = buff + 512 - 1 - buff_ptr; + break; - case 'o': - case 'u': - case 'x': - case 'X': - if (format.argument_options == long_argument) { - long_num = va_arg(arg, unsigned long); - } else if (format.argument_options == long_long_argument) { - long_long_num = va_arg(arg, signed long long); - } else { - long_num = va_arg(arg, unsigned int); - } + case 'o': + case 'u': + case 'x': + case 'X': + if (format.argument_options == long_argument) { + long_num = va_arg(arg, unsigned long); + } + else if (format.argument_options == long_long_argument) { + long_long_num = va_arg(arg, long long); + } + else { + long_num = va_arg(arg, unsigned int); + } - if (format.argument_options == short_argument) { - long_num = (unsigned short)long_num; - } + if (format.argument_options == short_argument) { + long_num = (unsigned short)long_num; + } - if (format.argument_options == char_argument) { - long_num = (unsigned char)long_num; - } + if (format.argument_options == char_argument) { + long_num = (unsigned char)long_num; + } - if (format.argument_options == long_long_argument) { - if (!(buff_ptr - = longlong2str(long_long_num, buff + 512, &format))) { - goto conversion_error; - } - } else { - if (!(buff_ptr = long2str(long_num, buff + 512, &format))) { - goto conversion_error; - } - } + if (format.argument_options == long_long_argument) { + if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) { + goto conversion_error; + } + } + else { + if (!(buff_ptr = long2str(long_num, buff + 512, format))) { + goto conversion_error; + } + } - num_chars = buff + 512 - 1 - buff_ptr; - break; + num_chars = buff + 512 - 1 - buff_ptr; + break; - case 'f': - case 'e': - case 'E': - case 'g': - case 'G': - if (!(buff_ptr = float2str(arg, buff + 512, &format, 0))) { - goto conversion_error; - } + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + if (format.argument_options == long_double_argument) { + long_double_num = va_arg(arg, long double); + } + else { + long_double_num = va_arg(arg, double); + } - num_chars = buff + 512 - 1 - buff_ptr; - break; + if (!(buff_ptr = float2str(long_double_num, buff + 512, format))) { + goto conversion_error; + } - case 's': - if (format.argument_options == wchar_argument) { - wchar_t* wcs_ptr = va_arg(arg, wchar_t*); + num_chars = buff + 512 - 1 - buff_ptr; + break; - if (wcs_ptr == NULL) { - wcs_ptr = L""; - } + case 'a': + case 'A': + if (format.argument_options == long_double_argument) { + long_double_num = va_arg(arg, long double); + } + else { + long_double_num = va_arg(arg, double); + } - if ((num_chars = wcstombs(buff, wcs_ptr, sizeof(buff))) < 0) { - goto conversion_error; - } + if (!(buff_ptr = double2hex(long_double_num, buff + 512, format))) { + goto conversion_error; + } - buff_ptr = &buff[0]; - } else { - buff_ptr = va_arg(arg, char*); - } + num_chars = buff + 512 - 1 - buff_ptr; + break; - if (buff_ptr == NULL) { - buff_ptr = ""; - } + case 's': + if (format.argument_options == wchar_argument) { + wchar_t* wcs_ptr = va_arg(arg, wchar_t*); - if (format.alternate_form) { - num_chars = (unsigned char)*buff_ptr++; + if(wcs_ptr == NULL){ + wcs_ptr = L""; + } - if (format.precision_specified - && num_chars > format.precision) { - num_chars = format.precision; - } - } else if (format.precision_specified) { - num_chars = format.precision; + if ((num_chars = wcstombs(buff, wcs_ptr, sizeof(buff))) < 0) { + goto conversion_error; + } - if ((string_end - = (char*)memchr((unsigned char*)buff_ptr, 0, num_chars)) - != 0) { - num_chars = string_end - buff_ptr; - } - } else { - num_chars = strlen(buff_ptr); - } + buff_ptr = &buff[0]; + } + else { + buff_ptr = va_arg(arg, char *); + } - break; + if (buff_ptr == NULL) { + buff_ptr = ""; + } - case 'n': - buff_ptr = va_arg(arg, char*); + if (format.alternate_form) { + num_chars = (unsigned char)*buff_ptr++; - switch (format.argument_options) { - case normal_argument: - *(int*)buff_ptr = chars_written; - break; - case short_argument: - *(signed short*)buff_ptr = chars_written; - break; - case long_argument: - *(signed long*)buff_ptr = chars_written; - break; - case long_long_argument: - *(signed long long*)buff_ptr = chars_written; - break; - } + if (format.precision_specified && num_chars > format.precision) { + num_chars = format.precision; + } + } + else if (format.precision_specified) { + num_chars = format.precision; - continue; + if ((string_end = (char*)memchr((unsigned char*)buff_ptr, 0, num_chars)) != 0) { + num_chars = string_end - buff_ptr; + } + } + else { + num_chars = strlen(buff_ptr); + } - case 'c': - buff_ptr = buff; - *buff_ptr = va_arg(arg, int); - num_chars = 1; - break; + break; - case '%': - buff_ptr = buff; - *buff_ptr = '%'; - num_chars = 1; - break; + case 'n': + buff_ptr = va_arg(arg, char *); - case 0xFF: - default: - conversion_error: - num_chars = strlen(curr_format); - chars_written += num_chars; + switch (format.argument_options) { + case normal_argument: + *(int*)buff_ptr = chars_written; + break; + case short_argument: + *(short*)buff_ptr = chars_written; + break; + case long_argument: + *(long*)buff_ptr = chars_written; + break; + case long_long_argument: + *(long long*)buff_ptr = chars_written; + break; + } - if (num_chars - && !(*WriteProc)(WriteProcArg, curr_format, num_chars)) { - return -1; - } + continue; - return chars_written; - break; - } + case 'c': + buff_ptr = buff; + *buff_ptr = va_arg(arg, int); + num_chars = 1; + break; - field_width = num_chars; + case '%': + buff_ptr = buff; + *buff_ptr = '%'; + num_chars = 1; + break; - if (format.justification_options != left_justification) { - fill_char = (format.justification_options == zero_fill) ? '0' : ' '; + case 0xFF: + default: + conversion_error: + num_chars = strlen(curr_format); + chars_written += num_chars; - if (((*buff_ptr == '+') || (*buff_ptr == '-')) - && (fill_char == '0')) { - if ((*WriteProc)(WriteProcArg, buff_ptr, 1) == 0) { - return -1; - } + if (num_chars && !(*WriteProc)(WriteProcArg, curr_format, num_chars)) { + return -1; + } - ++buff_ptr; - num_chars--; - } + return chars_written; + break; + } - while (field_width < format.field_width) { - if ((*WriteProc)(WriteProcArg, &fill_char, 1) == 0) { - return -1; - } + field_width = num_chars; - ++field_width; - } - } + if (format.justification_options != left_justification) { + fill_char = (format.justification_options == zero_fill) ? '0' : ' '; - if (num_chars && !(*WriteProc)(WriteProcArg, buff_ptr, num_chars)) { - return -1; - } + if (((*buff_ptr == '+') || (*buff_ptr == '-') || (*buff_ptr == ' ')) && (fill_char == '0')) { + if ((*WriteProc)(WriteProcArg, buff_ptr, 1) == 0) { + return -1; + } - if (format.justification_options == left_justification) { - while (field_width < format.field_width) { - char blank = ' '; + ++buff_ptr; + num_chars--; + } - if ((*WriteProc)(WriteProcArg, &blank, 1) == 0) { - return -1; - } + while (field_width < format.field_width) { + if ((*WriteProc)(WriteProcArg, &fill_char, 1) == 0) { + return -1; + } - ++field_width; - } - } + ++field_width; + } + } - chars_written += field_width; - } + if (num_chars && !(*WriteProc)(WriteProcArg, buff_ptr, num_chars)) { + return -1; + } - return chars_written; + if (format.justification_options == left_justification) { + while (field_width < format.field_width) { + char blank = ' '; + + if ((*WriteProc)(WriteProcArg, &blank, 1) == 0) { + return -1; + } + + ++field_width; + } + } + + chars_written += field_width; + } + + return chars_written; } -static void* __FileWrite(void* pFile, const char* pBuffer, size_t char_num) +void* __FileWrite(void* pFile, const char* pBuffer, size_t char_num) { - return (fwrite(pBuffer, 1, char_num, (FILE*)pFile) == char_num ? pFile : 0); + return (fwrite(pBuffer, 1, char_num, (FILE*)pFile) == char_num ? pFile : 0); } -static void* __StringWrite(void* pCtrl, const char* pBuffer, size_t char_num) +void* __StringWrite(void* pCtrl, const char* pBuffer, size_t char_num) { - size_t chars; - __OutStrCtrl* ctrl = (__OutStrCtrl*)pCtrl; - void* res; + size_t chars; + __OutStrCtrl* ctrl = (__OutStrCtrl*)pCtrl; - chars = ((ctrl->CharsWritten + char_num) <= ctrl->MaxCharCount) - ? char_num - : ctrl->MaxCharCount - ctrl->CharsWritten; - res = memcpy(ctrl->CharStr + ctrl->CharsWritten, pBuffer, chars); - ctrl->CharsWritten += chars; - return res; + chars = ((ctrl->CharsWritten + char_num) <= ctrl->MaxCharCount) + ? char_num + : ctrl->MaxCharCount - ctrl->CharsWritten; + memcpy(ctrl->CharStr + ctrl->CharsWritten, pBuffer, chars); + ctrl->CharsWritten += chars; + return (void*) 1; } int printf(const char* format, ...) { - int res; + int res; - if (fwide(stdout, -1) >= 0) { - return -1; - } + if (fwide(stdout, -1) >= 0) { + return -1; + } - { - va_list args; - va_start(args, format); - res = __pformatter(&__FileWrite, (void*)stdout, format, args); - } + { + va_list args; + va_start(args, format); + res = __pformatter(&__FileWrite, (void*)stdout, format, args); + } - return res; + return res; } int vprintf(const char* format, va_list arg) { - int ret; + int ret; - if (fwide(stdout, -1) >= 0) { - return -1; - } + if (fwide(stdout, -1) >= 0) { + return -1; + } - ret = __pformatter(&__FileWrite, (void*)stdout, format, arg); - return ret; + ret = __pformatter(&__FileWrite, (void*)stdout, format, arg); + return ret; } int vsnprintf(char* s, size_t n, const char* format, va_list arg) { - int end; - __OutStrCtrl osc; - osc.CharStr = s; - osc.MaxCharCount = n; - osc.CharsWritten = 0; + int end; + __OutStrCtrl osc; + osc.CharStr = s; + osc.MaxCharCount = n; + osc.CharsWritten = 0; - end = __pformatter(&__StringWrite, &osc, format, arg); + end = __pformatter(&__StringWrite, &osc, format, arg); - s[(end < n) ? end : n - 1] = '\0'; + if (s) { + s[(end < n) ? end : n - 1] = '\0'; + } - return end; + return end; } -int snprintf(char* s, size_t n, const char* format, ...) -{ - va_list args; - va_start(args, format); - return vsnprintf(s, n, format, args); +int vsprintf(char *s, const char *format, va_list arg) { + return vsnprintf(s, 0xFFFFFFFF, format, arg); } int sprintf(char* s, const char* format, ...) { - va_list args; - va_start(args, format); - return vsnprintf(s, 0xFFFFFFFF, format, args); + va_list args; + va_start(args, format); + return vsnprintf(s, 0xFFFFFFFF, format, args); } diff --git a/src/MSL_C.PPCEABI.bare.H/signal.c b/src/MSL_C.PPCEABI.bare.H/signal.c index 9d5da4ee..3967650d 100755 --- a/src/MSL_C.PPCEABI.bare.H/signal.c +++ b/src/MSL_C.PPCEABI.bare.H/signal.c @@ -1,26 +1,24 @@ #include +#include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/signal.h" -void* signal_funcs[6]; +__signal_func_ptr signal_funcs[6]; -// regalloc: https://decomp.me/scratch/ufAYK -int raise(int arg0) { - void (*temp_r31)(int); - void** temp_r3; +int raise(int sig) { + __signal_func_ptr temp_r31; - if (arg0 < 1 || arg0 > 6) { + if (sig < 1 || sig > 6) { return -1; } - temp_r3 = &signal_funcs[arg0]; - temp_r31 = *(--temp_r3); + temp_r31 = signal_funcs[sig - 1]; if ((unsigned long) temp_r31 != 1) { - *temp_r3 = NULL; + signal_funcs[sig - 1] = NULL; } - if ((unsigned long) temp_r31 == 1 || (temp_r31 == NULL && arg0 == 1)) { + if ((unsigned long) temp_r31 == 1 || (temp_r31 == NULL && sig == 1)) { return 0; } if (temp_r31 == NULL) { exit(0); } - temp_r31(arg0); + temp_r31(sig); return 0; } diff --git a/src/MSL_C.PPCEABI.bare.H/string.c b/src/MSL_C.PPCEABI.bare.H/string.c index 4fbb776f..895f6662 100644 --- a/src/MSL_C.PPCEABI.bare.H/string.c +++ b/src/MSL_C.PPCEABI.bare.H/string.c @@ -1,8 +1,8 @@ #include "string.h" #include "stddef.h" -static int K1 = 0x80808080; -static int K2 = 0xFEFEFEFF; +#define K1 0x80808080 +#define K2 0xFEFEFEFF size_t strlen(const char* str) { @@ -20,8 +20,6 @@ char* strcpy(char* dst, const char* src) { register unsigned char *destb, *fromb; register unsigned long w, t, align; - register unsigned int k1; - register unsigned int k2; fromb = (unsigned char*)src; destb = (unsigned char*)dst; @@ -44,14 +42,11 @@ char* strcpy(char* dst, const char* src) ++fromb; } - k1 = K1; - k2 = K2; - w = *((int*)(fromb)); - t = w + k2; + t = w + K2; - t &= k1; + t &= K1; if (t) { goto bytecopy; } @@ -61,8 +56,8 @@ char* strcpy(char* dst, const char* src) *(++((int*)(destb))) = w; w = *(++((int*)(fromb))); - t = w + k2; - t &= k1; + t = w + K2; + t &= K1; if (t) { goto adjust; } @@ -103,16 +98,21 @@ char* strncpy(char* dst, const char* src, size_t n) return dst; } -char* strcat(char* dst, const char* src) +// TODO: same implementation as strncpy? +char* strcat(char* dst, const char* src, size_t n) { - const unsigned char* p = (unsigned char*)src - 1; + const unsigned char* p = (const unsigned char*)src - 1; unsigned char* q = (unsigned char*)dst - 1; - while (*++q) { } - - q--; - - while (*++q = *++p) { } + n++; + while (--n) { + if (!(*++q = *++p)) { + while (--n) { + *++q = 0; + } + break; + } + } return dst; } @@ -196,6 +196,22 @@ bytecopy: } while (1); } +int strncmp(const char* str1, const char* str2, size_t n) +{ + const unsigned char* p1 = (unsigned char*)str1 - 1; + const unsigned char* p2 = (unsigned char*)str2 - 1; + unsigned long c1, c2; + + n++; + + while (--n) + if ((c1 = *++p1) != (c2 = *++p2)) + return (c1 - c2); + else if (!c1) + break; + return 0; +} + char* strchr(const char* str, int c) { const unsigned char* p = (unsigned char*)str - 1;