MSL: match alloc/signal/string and most of printf
This commit is contained in:
parent
6347294c14
commit
b353af7d23
7 changed files with 1346 additions and 858 deletions
|
|
@ -227,6 +227,7 @@ cflags_thp = [
|
||||||
# Metrowerks library flags
|
# Metrowerks library flags
|
||||||
cflags_msl = [
|
cflags_msl = [
|
||||||
*cflags_base,
|
*cflags_base,
|
||||||
|
"-char signed",
|
||||||
"-use_lmw_stmw on",
|
"-use_lmw_stmw on",
|
||||||
"-str reuse,pool,readonly",
|
"-str reuse,pool,readonly",
|
||||||
"-common off",
|
"-common off",
|
||||||
|
|
@ -681,7 +682,7 @@ config.libs = [
|
||||||
"host": False,
|
"host": False,
|
||||||
"objects": [
|
"objects": [
|
||||||
Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/abort_exit.c"),
|
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/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_files.c"),
|
||||||
Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/ansi_fp.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(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/misc_io.c"),
|
||||||
Object(NonMatching, "MSL_C.PPCEABI.bare.H/printf.c"),
|
Object(NonMatching, "MSL_C.PPCEABI.bare.H/printf.c"),
|
||||||
Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/float.c"),
|
Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/float.c"),
|
||||||
Object(NonMatching, "MSL_C.PPCEABI.bare.H/signal.c"),
|
Object(MatchingFor("GMPE01_00", "GMPE01_01"), "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/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/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/wchar_io.c"),
|
||||||
Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/e_acos.c"),
|
Object(MatchingFor("GMPE01_00", "GMPE01_01"), "MSL_C.PPCEABI.bare.H/e_acos.c"),
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ typedef struct _FILE {
|
||||||
file_modes file_mode;
|
file_modes file_mode;
|
||||||
file_states file_state;
|
file_states file_state;
|
||||||
|
|
||||||
char is_dynamically_allocated;
|
unsigned char is_dynamically_allocated;
|
||||||
char char_buffer;
|
char char_buffer;
|
||||||
char char_buffer_overflow;
|
char char_buffer_overflow;
|
||||||
char ungetc_buffer[2];
|
char ungetc_buffer[2];
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ char* strrchr(const char* str, int c);
|
||||||
char* strchr(const char* str, int c);
|
char* strchr(const char* str, int c);
|
||||||
int strncmp(const char* str1, const char* str2, size_t n);
|
int strncmp(const char* str1, const char* str2, size_t n);
|
||||||
int strcmp(const char* str1, const char* str2);
|
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* strncpy(char* dst, const char* src, size_t n);
|
||||||
char* strcpy(char* dst, const char* src);
|
char* strcpy(char* dst, const char* src);
|
||||||
size_t strlen(const char* str);
|
size_t strlen(const char* str);
|
||||||
|
|
|
||||||
410
src/MSL_C.PPCEABI.bare.H/alloc.c
Executable file
410
src/MSL_C.PPCEABI.bare.H/alloc.c
Executable file
|
|
@ -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(){
|
||||||
|
}
|
||||||
|
|
@ -49,9 +49,7 @@ typedef struct {
|
||||||
int precision;
|
int precision;
|
||||||
} print_format;
|
} print_format;
|
||||||
|
|
||||||
static const char* parse_format(const char* format_string, va_list* arg,
|
static const char* parse_format(const char *format_string, va_list *arg, print_format *format) {
|
||||||
print_format* format)
|
|
||||||
{
|
|
||||||
print_format f;
|
print_format f;
|
||||||
const char* s = format_string;
|
const char* s = format_string;
|
||||||
int c;
|
int c;
|
||||||
|
|
@ -100,7 +98,8 @@ static const char* parse_format(const char* format_string, va_list* arg,
|
||||||
|
|
||||||
if (flag_found) {
|
if (flag_found) {
|
||||||
c = *++s;
|
c = *++s;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -112,7 +111,8 @@ static const char* parse_format(const char* format_string, va_list* arg,
|
||||||
}
|
}
|
||||||
|
|
||||||
c = *++s;
|
c = *++s;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
while (isdigit(c)) {
|
while (isdigit(c)) {
|
||||||
f.field_width = (f.field_width * 10) + (c - '0');
|
f.field_width = (f.field_width * 10) + (c - '0');
|
||||||
c = *++s;
|
c = *++s;
|
||||||
|
|
@ -134,7 +134,8 @@ static const char* parse_format(const char* format_string, va_list* arg,
|
||||||
}
|
}
|
||||||
|
|
||||||
c = *++s;
|
c = *++s;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
while (isdigit(c)) {
|
while (isdigit(c)) {
|
||||||
f.precision = (f.precision * 10) + (c - '0');
|
f.precision = (f.precision * 10) + (c - '0');
|
||||||
c = *++s;
|
c = *++s;
|
||||||
|
|
@ -193,14 +194,15 @@ static const char* parse_format(const char* format_string, va_list* arg,
|
||||||
|
|
||||||
if (!f.precision_specified) {
|
if (!f.precision_specified) {
|
||||||
f.precision = 1;
|
f.precision = 1;
|
||||||
} else if (f.justification_options == zero_fill) {
|
}
|
||||||
|
else if (f.justification_options == zero_fill) {
|
||||||
f.justification_options = right_justification;
|
f.justification_options = right_justification;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
if (f.argument_options == short_argument
|
case 'F':
|
||||||
|| f.argument_options == long_long_argument) {
|
if (f.argument_options == short_argument || f.argument_options == long_long_argument) {
|
||||||
f.conversion_char = 0xFF;
|
f.conversion_char = 0xFF;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -210,6 +212,18 @@ static const char* parse_format(const char* format_string, va_list* arg,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
if (!f.precision_specified) {
|
||||||
|
f.precision = 0xD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f.argument_options == short_argument || f.argument_options == long_long_argument || f.argument_options == char_argument) {
|
||||||
|
f.conversion_char = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
if (!f.precision) {
|
if (!f.precision) {
|
||||||
|
|
@ -218,9 +232,7 @@ static const char* parse_format(const char* format_string, va_list* arg,
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
if (f.argument_options == short_argument
|
if (f.argument_options == short_argument || f.argument_options == long_long_argument || f.argument_options == char_argument) {
|
||||||
|| f.argument_options == long_long_argument
|
|
||||||
|| f.argument_options == char_argument) {
|
|
||||||
f.conversion_char = 0xFF;
|
f.conversion_char = 0xFF;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -240,9 +252,9 @@ static const char* parse_format(const char* format_string, va_list* arg,
|
||||||
case 'c':
|
case 'c':
|
||||||
if (f.argument_options == long_argument) {
|
if (f.argument_options == long_argument) {
|
||||||
f.argument_options = wchar_argument;
|
f.argument_options = wchar_argument;
|
||||||
} else {
|
}
|
||||||
if (f.precision_specified
|
else {
|
||||||
|| f.argument_options != normal_argument) {
|
if (f.precision_specified || f.argument_options != normal_argument) {
|
||||||
f.conversion_char = 0xFF;
|
f.conversion_char = 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -252,7 +264,8 @@ static const char* parse_format(const char* format_string, va_list* arg,
|
||||||
case 's':
|
case 's':
|
||||||
if (f.argument_options == long_argument) {
|
if (f.argument_options == long_argument) {
|
||||||
f.argument_options = wchar_argument;
|
f.argument_options = wchar_argument;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (f.argument_options != normal_argument) {
|
if (f.argument_options != normal_argument) {
|
||||||
f.conversion_char = 0xFF;
|
f.conversion_char = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +289,7 @@ static const char* parse_format(const char* format_string, va_list* arg,
|
||||||
return ((const char*)s + 1);
|
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;
|
unsigned long unsigned_num, base;
|
||||||
char* p;
|
char* p;
|
||||||
|
|
@ -289,12 +302,12 @@ static char* long2str(signed long num, char* buff, print_format* format)
|
||||||
*--p = 0;
|
*--p = 0;
|
||||||
digits = 0;
|
digits = 0;
|
||||||
|
|
||||||
if (!num && !format->precision
|
if (!num && !format.precision
|
||||||
&& !(format->alternate_form && format->conversion_char == 'o')) {
|
&& !(format.alternate_form && format.conversion_char == 'o')) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (format->conversion_char) {
|
switch (format.conversion_char) {
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
case 'i':
|
||||||
base = 10;
|
base = 10;
|
||||||
|
|
@ -307,18 +320,18 @@ static char* long2str(signed long num, char* buff, print_format* format)
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
base = 8;
|
base = 8;
|
||||||
format->sign_options = only_minus;
|
format.sign_options = only_minus;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
base = 10;
|
base = 10;
|
||||||
format->sign_options = only_minus;
|
format.sign_options = only_minus;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
base = 16;
|
base = 16;
|
||||||
format->sign_options = only_minus;
|
format.sign_options = only_minus;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,7 +344,7 @@ static char* long2str(signed long num, char* buff, print_format* format)
|
||||||
} else {
|
} else {
|
||||||
n -= 10;
|
n -= 10;
|
||||||
|
|
||||||
if (format->conversion_char == 'x') {
|
if (format.conversion_char == 'x') {
|
||||||
n += 'a';
|
n += 'a';
|
||||||
} else {
|
} else {
|
||||||
n += 'A';
|
n += 'A';
|
||||||
|
|
@ -342,46 +355,46 @@ static char* long2str(signed long num, char* buff, print_format* format)
|
||||||
++digits;
|
++digits;
|
||||||
} while (unsigned_num != 0);
|
} while (unsigned_num != 0);
|
||||||
|
|
||||||
if (base == 8 && format->alternate_form && *p != '0') {
|
if (base == 8 && format.alternate_form && *p != '0') {
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
++digits;
|
++digits;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format->justification_options == zero_fill) {
|
if (format.justification_options == zero_fill) {
|
||||||
format->precision = format->field_width;
|
format.precision = format.field_width;
|
||||||
|
|
||||||
if (minus || format->sign_options != only_minus)
|
if (minus || format.sign_options != only_minus)
|
||||||
--format->precision;
|
--format.precision;
|
||||||
|
|
||||||
if (base == 16 && format->alternate_form)
|
if (base == 16 && format.alternate_form)
|
||||||
format->precision -= 2;
|
format.precision -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buff - p + format->precision > 509)
|
if (buff - p + format.precision > 509)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
while (digits < format->precision) {
|
while (digits < format.precision) {
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
++digits;
|
++digits;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base == 16 && format->alternate_form) {
|
if (base == 16 && format.alternate_form) {
|
||||||
*--p = format->conversion_char;
|
*--p = format.conversion_char;
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minus) {
|
if (minus) {
|
||||||
*--p = '-';
|
*--p = '-';
|
||||||
} else if (format->sign_options == sign_always) {
|
} else if (format.sign_options == sign_always) {
|
||||||
*--p = '+';
|
*--p = '+';
|
||||||
} else if (format->sign_options == space_holder) {
|
} else if (format.sign_options == space_holder) {
|
||||||
*--p = ' ';
|
*--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;
|
unsigned long long unsigned_num, base;
|
||||||
char* p;
|
char* p;
|
||||||
|
|
@ -393,12 +406,12 @@ static char* longlong2str(signed long long num, char* pBuf, print_format* fmt)
|
||||||
*--p = 0;
|
*--p = 0;
|
||||||
digits = 0;
|
digits = 0;
|
||||||
|
|
||||||
if (!num && !fmt->precision
|
if (!num && !fmt.precision
|
||||||
&& !(fmt->alternate_form && fmt->conversion_char == 'o')) {
|
&& !(fmt.alternate_form && fmt.conversion_char == 'o')) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (fmt->conversion_char) {
|
switch (fmt.conversion_char) {
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
case 'i':
|
||||||
base = 10;
|
base = 10;
|
||||||
|
|
@ -410,16 +423,16 @@ static char* longlong2str(signed long long num, char* pBuf, print_format* fmt)
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
base = 8;
|
base = 8;
|
||||||
fmt->sign_options = only_minus;
|
fmt.sign_options = only_minus;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
base = 10;
|
base = 10;
|
||||||
fmt->sign_options = only_minus;
|
fmt.sign_options = only_minus;
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
base = 16;
|
base = 16;
|
||||||
fmt->sign_options = only_minus;
|
fmt.sign_options = only_minus;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,7 +444,7 @@ static char* longlong2str(signed long long num, char* pBuf, print_format* fmt)
|
||||||
n += '0';
|
n += '0';
|
||||||
} else {
|
} else {
|
||||||
n -= 10;
|
n -= 10;
|
||||||
if (fmt->conversion_char == 'x') {
|
if (fmt.conversion_char == 'x') {
|
||||||
n += 'a';
|
n += 'a';
|
||||||
} else {
|
} else {
|
||||||
n += 'A';
|
n += 'A';
|
||||||
|
|
@ -442,48 +455,50 @@ static char* longlong2str(signed long long num, char* pBuf, print_format* fmt)
|
||||||
++digits;
|
++digits;
|
||||||
} while (unsigned_num != 0);
|
} while (unsigned_num != 0);
|
||||||
|
|
||||||
if (base == 8 && fmt->alternate_form && *p != '0') {
|
if (base == 8 && fmt.alternate_form && *p != '0') {
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
++digits;
|
++digits;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmt->justification_options == zero_fill) {
|
if (fmt.justification_options == zero_fill) {
|
||||||
fmt->precision = fmt->field_width;
|
fmt.precision = fmt.field_width;
|
||||||
|
|
||||||
if (minus || fmt->sign_options != only_minus) {
|
if (minus || fmt.sign_options != only_minus) {
|
||||||
--fmt->precision;
|
--fmt.precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base == 16 && fmt->alternate_form) {
|
if (base == 16 && fmt.alternate_form) {
|
||||||
fmt->precision -= 2;
|
fmt.precision -= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pBuf - p + fmt->precision > 509) {
|
if (pBuf - p + fmt.precision > 509) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (digits < fmt->precision) {
|
while (digits < fmt.precision) {
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
++digits;
|
++digits;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base == 16 && fmt->alternate_form) {
|
if (base == 16 && fmt.alternate_form) {
|
||||||
*--p = fmt->conversion_char;
|
*--p = fmt.conversion_char;
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minus) {
|
if (minus) {
|
||||||
*--p = '-';
|
*--p = '-';
|
||||||
} else if (fmt->sign_options == sign_always) {
|
} else if (fmt.sign_options == sign_always) {
|
||||||
*--p = '+';
|
*--p = '+';
|
||||||
} else if (fmt->sign_options == space_holder) {
|
} else if (fmt.sign_options == space_holder) {
|
||||||
*--p = ' ';
|
*--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)
|
static void round_decimal(decimal* dec, int new_length)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
|
@ -492,7 +507,6 @@ static void round_decimal(decimal* dec, int new_length)
|
||||||
|
|
||||||
if (new_length < 0) {
|
if (new_length < 0) {
|
||||||
return_zero:
|
return_zero:
|
||||||
dec->sign = 0;
|
|
||||||
dec->exp = 0;
|
dec->exp = 0;
|
||||||
dec->sig.length = 1;
|
dec->sig.length = 1;
|
||||||
*dec->sig.text = '0';
|
*dec->sig.text = '0';
|
||||||
|
|
@ -539,24 +553,15 @@ static void round_decimal(decimal* dec, int new_length)
|
||||||
dec->sig.length = new_length;
|
dec->sig.length = new_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* float2str(va_list arg, char* buff, print_format* format,
|
static char* float2str(long double num, char *buff, print_format format) {
|
||||||
int vecIndex)
|
|
||||||
{
|
|
||||||
decimal dec;
|
decimal dec;
|
||||||
decform form;
|
decform form;
|
||||||
char* p;
|
char* p;
|
||||||
char* q;
|
char* q;
|
||||||
int n, digits, sign;
|
int n, digits, sign;
|
||||||
int int_digits, frac_digits;
|
int int_digits, frac_digits;
|
||||||
long double num;
|
|
||||||
|
|
||||||
if (format->argument_options == long_double_argument) {
|
if (format.precision > 509) {
|
||||||
num = va_arg(arg, long double);
|
|
||||||
} else {
|
|
||||||
num = va_arg(arg, double);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format->precision > 509) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -577,17 +582,47 @@ static char* float2str(va_list arg, char* buff, print_format* format,
|
||||||
case 'I':
|
case 'I':
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
p = buff - 5;
|
p = buff - 5;
|
||||||
strcpy(p, "-Inf");
|
|
||||||
} else {
|
if (isupper(format.conversion_char)) {
|
||||||
|
strcpy(p, "-INF");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strcpy(p, "-inf");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
p = buff - 4;
|
p = buff - 4;
|
||||||
strcpy(p, "Inf");
|
if (isupper(format.conversion_char)) {
|
||||||
|
strcpy(p, "INF");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strcpy(p, "inf");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
case 'N':
|
case 'N':
|
||||||
|
if (dec.sign) {
|
||||||
|
p = buff - 5;
|
||||||
|
|
||||||
|
if (isupper(format.conversion_char)) {
|
||||||
|
strcpy(p, "-NAN");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strcpy(p, "-nan");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
p = buff - 4;
|
p = buff - 4;
|
||||||
strcpy(p, "NaN");
|
if (isupper(format.conversion_char)) {
|
||||||
|
strcpy(p, "NAN");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strcpy(p, "nan");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -595,35 +630,40 @@ static char* float2str(va_list arg, char* buff, print_format* format,
|
||||||
p = buff;
|
p = buff;
|
||||||
*--p = 0;
|
*--p = 0;
|
||||||
|
|
||||||
switch (format->conversion_char) {
|
switch (format.conversion_char)
|
||||||
|
{
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
|
|
||||||
if (dec.sig.length > format->precision) {
|
if (dec.sig.length > format.precision) {
|
||||||
round_decimal(&dec, format->precision);
|
round_decimal(&dec, format.precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dec.exp < -4 || dec.exp >= format->precision) {
|
if (dec.exp < -4 || dec.exp >= format.precision)
|
||||||
if (format->alternate_form) {
|
{
|
||||||
--format->precision;
|
if (format.alternate_form) {
|
||||||
} else {
|
--format.precision;
|
||||||
format->precision = dec.sig.length - 1;
|
}
|
||||||
|
else {
|
||||||
|
format.precision = dec.sig.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format->conversion_char == 'g') {
|
if (format.conversion_char == 'g') {
|
||||||
format->conversion_char = 'e';
|
format.conversion_char = 'e';
|
||||||
} else {
|
}
|
||||||
format->conversion_char = 'E';
|
else {
|
||||||
|
format.conversion_char = 'E';
|
||||||
}
|
}
|
||||||
|
|
||||||
goto e_format;
|
goto e_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format->alternate_form) {
|
if (format.alternate_form) {
|
||||||
format->precision -= dec.exp + 1;
|
format.precision -= dec.exp + 1;
|
||||||
} else {
|
}
|
||||||
if ((format->precision = dec.sig.length - (dec.exp + 1)) < 0) {
|
else {
|
||||||
format->precision = 0;
|
if ((format.precision = dec.sig.length - (dec.exp + 1)) < 0) {
|
||||||
|
format.precision = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -633,8 +673,8 @@ static char* float2str(va_list arg, char* buff, print_format* format,
|
||||||
case 'E':
|
case 'E':
|
||||||
e_format:
|
e_format:
|
||||||
|
|
||||||
if (dec.sig.length > format->precision + 1) {
|
if (dec.sig.length > format.precision + 1) {
|
||||||
round_decimal(&dec, format->precision + 1);
|
round_decimal(&dec, format.precision + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
n = dec.exp;
|
n = dec.exp;
|
||||||
|
|
@ -651,24 +691,23 @@ static char* float2str(va_list arg, char* buff, print_format* format,
|
||||||
}
|
}
|
||||||
|
|
||||||
*--p = sign;
|
*--p = sign;
|
||||||
*--p = format->conversion_char;
|
*--p = format.conversion_char;
|
||||||
|
|
||||||
if (buff - p + format->precision > 509) {
|
if (buff - p + format.precision > 509) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dec.sig.length < format->precision + 1) {
|
if (dec.sig.length < format.precision + 1) {
|
||||||
for (n = format->precision + 1 - dec.sig.length + 1; --n;) {
|
for (n = format.precision + 1 - dec.sig.length + 1; --n;) {
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = dec.sig.length, q = (char*)dec.sig.text + dec.sig.length;
|
for (n = dec.sig.length, q = (char*)dec.sig.text + dec.sig.length; --n;) {
|
||||||
--n;) {
|
|
||||||
*--p = *--q;
|
*--p = *--q;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format->precision || format->alternate_form) {
|
if (format.precision || format.alternate_form) {
|
||||||
*--p = '.';
|
*--p = '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -676,22 +715,22 @@ static char* float2str(va_list arg, char* buff, print_format* format,
|
||||||
|
|
||||||
if (dec.sign)
|
if (dec.sign)
|
||||||
*--p = '-';
|
*--p = '-';
|
||||||
else if (format->sign_options == sign_always)
|
else if (format.sign_options == sign_always)
|
||||||
*--p = '+';
|
*--p = '+';
|
||||||
else if (format->sign_options == space_holder)
|
else if (format.sign_options == space_holder)
|
||||||
*--p = ' ';
|
*--p = ' ';
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
|
case 'F':
|
||||||
f_format:
|
f_format:
|
||||||
|
|
||||||
if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0)
|
if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0)
|
||||||
frac_digits = 0;
|
frac_digits = 0;
|
||||||
|
|
||||||
if (frac_digits > format->precision) {
|
if (frac_digits > format.precision) {
|
||||||
round_decimal(&dec,
|
round_decimal(&dec, dec.sig.length - (frac_digits - format.precision));
|
||||||
dec.sig.length - (frac_digits - format->precision));
|
|
||||||
|
|
||||||
if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0)
|
if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0)
|
||||||
frac_digits = 0;
|
frac_digits = 0;
|
||||||
|
|
@ -703,19 +742,18 @@ static char* float2str(va_list arg, char* buff, print_format* format,
|
||||||
if (int_digits + frac_digits > 509)
|
if (int_digits + frac_digits > 509)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
q = (char*)dec.sig.text + dec.sig.length;
|
q = (char *) dec.sig.text + dec.sig.length;
|
||||||
|
|
||||||
for (digits = 0; digits < (format->precision - frac_digits); ++digits)
|
for (digits = 0; digits < (format.precision - frac_digits); ++digits)
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
|
|
||||||
for (digits = 0; digits < frac_digits && digits < dec.sig.length;
|
for (digits = 0; digits < frac_digits && digits < dec.sig.length; ++digits)
|
||||||
++digits)
|
|
||||||
*--p = *--q;
|
*--p = *--q;
|
||||||
|
|
||||||
for (; digits < frac_digits; ++digits)
|
for (; digits < frac_digits; ++digits)
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
|
|
||||||
if (format->precision || format->alternate_form)
|
if (format.precision || format.alternate_form)
|
||||||
*--p = '.';
|
*--p = '.';
|
||||||
|
|
||||||
if (int_digits) {
|
if (int_digits) {
|
||||||
|
|
@ -726,15 +764,18 @@ static char* float2str(va_list arg, char* buff, print_format* format,
|
||||||
for (; digits < int_digits; ++digits) {
|
for (; digits < int_digits; ++digits) {
|
||||||
*--p = *--q;
|
*--p = *--q;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dec.sign) {
|
if (dec.sign) {
|
||||||
*--p = '-';
|
*--p = '-';
|
||||||
} else if (format->sign_options == sign_always) {
|
}
|
||||||
|
else if (format.sign_options == sign_always) {
|
||||||
*--p = '+';
|
*--p = '+';
|
||||||
} else if (format->sign_options == space_holder) {
|
}
|
||||||
|
else if (format.sign_options == space_holder) {
|
||||||
*--p = ' ';
|
*--p = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -744,15 +785,14 @@ static char* float2str(va_list arg, char* buff, print_format* format,
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
static int __pformatter(void *(*WriteProc)(void *, const char *, size_t), void *WriteProcArg, const char * format_str, va_list arg) {
|
||||||
void* WriteProcArg, const char* format_str, va_list arg)
|
|
||||||
{
|
|
||||||
int num_chars, chars_written, field_width;
|
int num_chars, chars_written, field_width;
|
||||||
const char* format_ptr;
|
const char* format_ptr;
|
||||||
const char* curr_format;
|
const char* curr_format;
|
||||||
print_format format;
|
print_format format;
|
||||||
signed long long_num;
|
long long_num;
|
||||||
signed long long long_long_num;
|
long long long_long_num;
|
||||||
|
long double long_double_num;
|
||||||
char buff[512];
|
char buff[512];
|
||||||
char* buff_ptr;
|
char* buff_ptr;
|
||||||
char* string_end;
|
char* string_end;
|
||||||
|
|
@ -766,8 +806,7 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
num_chars = strlen(format_ptr);
|
num_chars = strlen(format_ptr);
|
||||||
chars_written += num_chars;
|
chars_written += num_chars;
|
||||||
|
|
||||||
if (num_chars
|
if (num_chars && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) {
|
||||||
&& !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -788,15 +827,17 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
case 'i':
|
||||||
if (format.argument_options == long_argument) {
|
if (format.argument_options == long_argument) {
|
||||||
long_num = va_arg(arg, signed long);
|
long_num = va_arg(arg, long);
|
||||||
} else if (format.argument_options == long_long_argument) {
|
}
|
||||||
long_long_num = va_arg(arg, signed long long);
|
else if (format.argument_options == long_long_argument) {
|
||||||
} else {
|
long_long_num = va_arg(arg, long long);
|
||||||
|
}
|
||||||
|
else {
|
||||||
long_num = va_arg(arg, int);
|
long_num = va_arg(arg, int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format.argument_options == short_argument) {
|
if (format.argument_options == short_argument) {
|
||||||
long_num = (signed short)long_num;
|
long_num = (short)long_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format.argument_options == char_argument) {
|
if (format.argument_options == char_argument) {
|
||||||
|
|
@ -804,12 +845,12 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format.argument_options == long_long_argument) {
|
if (format.argument_options == long_long_argument) {
|
||||||
if (!(buff_ptr
|
if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) {
|
||||||
= longlong2str(long_long_num, buff + 512, &format))) {
|
|
||||||
goto conversion_error;
|
goto conversion_error;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if (!(buff_ptr = long2str(long_num, buff + 512, &format))) {
|
else {
|
||||||
|
if (!(buff_ptr = long2str(long_num, buff + 512, format))) {
|
||||||
goto conversion_error;
|
goto conversion_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -823,9 +864,11 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
case 'X':
|
case 'X':
|
||||||
if (format.argument_options == long_argument) {
|
if (format.argument_options == long_argument) {
|
||||||
long_num = va_arg(arg, unsigned long);
|
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 if (format.argument_options == long_long_argument) {
|
||||||
} else {
|
long_long_num = va_arg(arg, long long);
|
||||||
|
}
|
||||||
|
else {
|
||||||
long_num = va_arg(arg, unsigned int);
|
long_num = va_arg(arg, unsigned int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -838,12 +881,12 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format.argument_options == long_long_argument) {
|
if (format.argument_options == long_long_argument) {
|
||||||
if (!(buff_ptr
|
if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) {
|
||||||
= longlong2str(long_long_num, buff + 512, &format))) {
|
|
||||||
goto conversion_error;
|
goto conversion_error;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if (!(buff_ptr = long2str(long_num, buff + 512, &format))) {
|
else {
|
||||||
|
if (!(buff_ptr = long2str(long_num, buff + 512, format))) {
|
||||||
goto conversion_error;
|
goto conversion_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -852,11 +895,35 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
|
case 'F':
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
if (!(buff_ptr = float2str(arg, buff + 512, &format, 0))) {
|
if (format.argument_options == long_double_argument) {
|
||||||
|
long_double_num = va_arg(arg, long double);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
long_double_num = va_arg(arg, double);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(buff_ptr = float2str(long_double_num, buff + 512, format))) {
|
||||||
|
goto conversion_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_chars = buff + 512 - 1 - buff_ptr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
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 (!(buff_ptr = double2hex(long_double_num, buff + 512, format))) {
|
||||||
goto conversion_error;
|
goto conversion_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -867,7 +934,7 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
if (format.argument_options == wchar_argument) {
|
if (format.argument_options == wchar_argument) {
|
||||||
wchar_t* wcs_ptr = va_arg(arg, wchar_t*);
|
wchar_t* wcs_ptr = va_arg(arg, wchar_t*);
|
||||||
|
|
||||||
if (wcs_ptr == NULL) {
|
if(wcs_ptr == NULL){
|
||||||
wcs_ptr = L"";
|
wcs_ptr = L"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -876,8 +943,9 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
}
|
}
|
||||||
|
|
||||||
buff_ptr = &buff[0];
|
buff_ptr = &buff[0];
|
||||||
} else {
|
}
|
||||||
buff_ptr = va_arg(arg, char*);
|
else {
|
||||||
|
buff_ptr = va_arg(arg, char *);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buff_ptr == NULL) {
|
if (buff_ptr == NULL) {
|
||||||
|
|
@ -887,39 +955,38 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
if (format.alternate_form) {
|
if (format.alternate_form) {
|
||||||
num_chars = (unsigned char)*buff_ptr++;
|
num_chars = (unsigned char)*buff_ptr++;
|
||||||
|
|
||||||
if (format.precision_specified
|
if (format.precision_specified && num_chars > format.precision) {
|
||||||
&& num_chars > format.precision) {
|
|
||||||
num_chars = format.precision;
|
num_chars = format.precision;
|
||||||
}
|
}
|
||||||
} else if (format.precision_specified) {
|
}
|
||||||
|
else if (format.precision_specified) {
|
||||||
num_chars = format.precision;
|
num_chars = format.precision;
|
||||||
|
|
||||||
if ((string_end
|
if ((string_end = (char*)memchr((unsigned char*)buff_ptr, 0, num_chars)) != 0) {
|
||||||
= (char*)memchr((unsigned char*)buff_ptr, 0, num_chars))
|
|
||||||
!= 0) {
|
|
||||||
num_chars = string_end - buff_ptr;
|
num_chars = string_end - buff_ptr;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
num_chars = strlen(buff_ptr);
|
num_chars = strlen(buff_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
buff_ptr = va_arg(arg, char*);
|
buff_ptr = va_arg(arg, char *);
|
||||||
|
|
||||||
switch (format.argument_options) {
|
switch (format.argument_options) {
|
||||||
case normal_argument:
|
case normal_argument:
|
||||||
*(int*)buff_ptr = chars_written;
|
*(int*)buff_ptr = chars_written;
|
||||||
break;
|
break;
|
||||||
case short_argument:
|
case short_argument:
|
||||||
*(signed short*)buff_ptr = chars_written;
|
*(short*)buff_ptr = chars_written;
|
||||||
break;
|
break;
|
||||||
case long_argument:
|
case long_argument:
|
||||||
*(signed long*)buff_ptr = chars_written;
|
*(long*)buff_ptr = chars_written;
|
||||||
break;
|
break;
|
||||||
case long_long_argument:
|
case long_long_argument:
|
||||||
*(signed long long*)buff_ptr = chars_written;
|
*(long long*)buff_ptr = chars_written;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -943,8 +1010,7 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
num_chars = strlen(curr_format);
|
num_chars = strlen(curr_format);
|
||||||
chars_written += num_chars;
|
chars_written += num_chars;
|
||||||
|
|
||||||
if (num_chars
|
if (num_chars && !(*WriteProc)(WriteProcArg, curr_format, num_chars)) {
|
||||||
&& !(*WriteProc)(WriteProcArg, curr_format, num_chars)) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -957,8 +1023,7 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
if (format.justification_options != left_justification) {
|
if (format.justification_options != left_justification) {
|
||||||
fill_char = (format.justification_options == zero_fill) ? '0' : ' ';
|
fill_char = (format.justification_options == zero_fill) ? '0' : ' ';
|
||||||
|
|
||||||
if (((*buff_ptr == '+') || (*buff_ptr == '-'))
|
if (((*buff_ptr == '+') || (*buff_ptr == '-') || (*buff_ptr == ' ')) && (fill_char == '0')) {
|
||||||
&& (fill_char == '0')) {
|
|
||||||
if ((*WriteProc)(WriteProcArg, buff_ptr, 1) == 0) {
|
if ((*WriteProc)(WriteProcArg, buff_ptr, 1) == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -998,23 +1063,22 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t),
|
||||||
return chars_written;
|
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;
|
size_t chars;
|
||||||
__OutStrCtrl* ctrl = (__OutStrCtrl*)pCtrl;
|
__OutStrCtrl* ctrl = (__OutStrCtrl*)pCtrl;
|
||||||
void* res;
|
|
||||||
|
|
||||||
chars = ((ctrl->CharsWritten + char_num) <= ctrl->MaxCharCount)
|
chars = ((ctrl->CharsWritten + char_num) <= ctrl->MaxCharCount)
|
||||||
? char_num
|
? char_num
|
||||||
: ctrl->MaxCharCount - ctrl->CharsWritten;
|
: ctrl->MaxCharCount - ctrl->CharsWritten;
|
||||||
res = memcpy(ctrl->CharStr + ctrl->CharsWritten, pBuffer, chars);
|
memcpy(ctrl->CharStr + ctrl->CharsWritten, pBuffer, chars);
|
||||||
ctrl->CharsWritten += chars;
|
ctrl->CharsWritten += chars;
|
||||||
return res;
|
return (void*) 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int printf(const char* format, ...)
|
int printf(const char* format, ...)
|
||||||
|
|
@ -1056,16 +1120,15 @@ int vsnprintf(char* s, size_t n, const char* format, va_list arg)
|
||||||
|
|
||||||
end = __pformatter(&__StringWrite, &osc, format, arg);
|
end = __pformatter(&__StringWrite, &osc, format, arg);
|
||||||
|
|
||||||
|
if (s) {
|
||||||
s[(end < n) ? end : n - 1] = '\0';
|
s[(end < n) ? end : n - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
int snprintf(char* s, size_t n, const char* format, ...)
|
int vsprintf(char *s, const char *format, va_list arg) {
|
||||||
{
|
return vsnprintf(s, 0xFFFFFFFF, format, arg);
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
return vsnprintf(s, n, format, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int sprintf(char* s, const char* format, ...)
|
int sprintf(char* s, const char* format, ...)
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,24 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#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 sig) {
|
||||||
int raise(int arg0) {
|
__signal_func_ptr temp_r31;
|
||||||
void (*temp_r31)(int);
|
|
||||||
void** temp_r3;
|
|
||||||
|
|
||||||
if (arg0 < 1 || arg0 > 6) {
|
if (sig < 1 || sig > 6) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
temp_r3 = &signal_funcs[arg0];
|
temp_r31 = signal_funcs[sig - 1];
|
||||||
temp_r31 = *(--temp_r3);
|
|
||||||
if ((unsigned long) temp_r31 != 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;
|
return 0;
|
||||||
}
|
}
|
||||||
if (temp_r31 == NULL) {
|
if (temp_r31 == NULL) {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
temp_r31(arg0);
|
temp_r31(sig);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "stddef.h"
|
#include "stddef.h"
|
||||||
|
|
||||||
static int K1 = 0x80808080;
|
#define K1 0x80808080
|
||||||
static int K2 = 0xFEFEFEFF;
|
#define K2 0xFEFEFEFF
|
||||||
|
|
||||||
size_t strlen(const char* str)
|
size_t strlen(const char* str)
|
||||||
{
|
{
|
||||||
|
|
@ -20,8 +20,6 @@ char* strcpy(char* dst, const char* src)
|
||||||
{
|
{
|
||||||
register unsigned char *destb, *fromb;
|
register unsigned char *destb, *fromb;
|
||||||
register unsigned long w, t, align;
|
register unsigned long w, t, align;
|
||||||
register unsigned int k1;
|
|
||||||
register unsigned int k2;
|
|
||||||
|
|
||||||
fromb = (unsigned char*)src;
|
fromb = (unsigned char*)src;
|
||||||
destb = (unsigned char*)dst;
|
destb = (unsigned char*)dst;
|
||||||
|
|
@ -44,14 +42,11 @@ char* strcpy(char* dst, const char* src)
|
||||||
++fromb;
|
++fromb;
|
||||||
}
|
}
|
||||||
|
|
||||||
k1 = K1;
|
|
||||||
k2 = K2;
|
|
||||||
|
|
||||||
w = *((int*)(fromb));
|
w = *((int*)(fromb));
|
||||||
|
|
||||||
t = w + k2;
|
t = w + K2;
|
||||||
|
|
||||||
t &= k1;
|
t &= K1;
|
||||||
if (t) {
|
if (t) {
|
||||||
goto bytecopy;
|
goto bytecopy;
|
||||||
}
|
}
|
||||||
|
|
@ -61,8 +56,8 @@ char* strcpy(char* dst, const char* src)
|
||||||
*(++((int*)(destb))) = w;
|
*(++((int*)(destb))) = w;
|
||||||
w = *(++((int*)(fromb)));
|
w = *(++((int*)(fromb)));
|
||||||
|
|
||||||
t = w + k2;
|
t = w + K2;
|
||||||
t &= k1;
|
t &= K1;
|
||||||
if (t) {
|
if (t) {
|
||||||
goto adjust;
|
goto adjust;
|
||||||
}
|
}
|
||||||
|
|
@ -103,16 +98,21 @@ char* strncpy(char* dst, const char* src, size_t n)
|
||||||
return dst;
|
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;
|
unsigned char* q = (unsigned char*)dst - 1;
|
||||||
|
|
||||||
while (*++q) { }
|
n++;
|
||||||
|
while (--n) {
|
||||||
q--;
|
if (!(*++q = *++p)) {
|
||||||
|
while (--n) {
|
||||||
while (*++q = *++p) { }
|
*++q = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
@ -196,6 +196,22 @@ bytecopy:
|
||||||
} while (1);
|
} 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)
|
char* strchr(const char* str, int c)
|
||||||
{
|
{
|
||||||
const unsigned char* p = (unsigned char*)str - 1;
|
const unsigned char* p = (unsigned char*)str - 1;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue