diff options
Diffstat (limited to 'lib/printf.c')
| -rw-r--r-- | lib/printf.c | 200 |
1 files changed, 112 insertions, 88 deletions
diff --git a/lib/printf.c b/lib/printf.c index 4e64d7b..b96c616 100644 --- a/lib/printf.c +++ b/lib/printf.c @@ -22,7 +22,6 @@ convert_as_int( char *str, size_t size, int stri, - int field_width, uintmax_t value, int radix, int unsign) @@ -37,17 +36,79 @@ convert_as_int( for(uintmax_t i = value; i != 0; i /= radix) digits++; if(value == 0) digits++; - if(field_width < digits) field_width = digits; for(uintmax_t i = value, digiti = 0; digiti < digits; i /= radix) { char i_mod = (char)(i % radix); - int stri_digiti = stri + (field_width - digiti) - 1; + int stri_digiti = stri + (digits - digiti) - 1; SPRINTF_PUTC(str, size, stri_digiti, (i_mod > 9 ? (i_mod + 'a' - 10) : (i_mod + '0'))); digiti++; } - return field_width + (stri - ostri) + 1; + return digits; +} + +enum printf_state +{ + FSTATE_DIRECT = 0, + FSTATE_CONVERT +}; + +static int +s_convert_string(char *str, size_t size, va_list ap, size_t stri) +{ + const char *strarg = va_arg(ap, const char*); + for(const char *strargc = strarg; *strargc; strargc++) { + SPRINTF_PUTC(str, size, stri, *strargc); + } + return stri; +} + +static int +s_convert_int(char *str, size_t size, va_list ap, size_t stri, + int fw, char fp, int typelen, int radix, int usign, int caps) +{ + char num_buf[64]; + uintmax_t value = 0; + switch(typelen) { + case 1: value = (uintmax_t)(int8_t)va_arg(ap, int); break; + case 2: value = (uintmax_t)(int16_t)va_arg(ap, int); break; + default: + case 4: value = (uintmax_t)va_arg(ap, unsigned int); break; + case 8: value = (uintmax_t)va_arg(ap, uintmax_t); break; + } + size_t pad_stri = stri; + + int advance = convert_as_int(num_buf, 64, 0, value, radix, usign); + if(caps) { + for(int i = 0; i < advance; i++) { + num_buf[i] = c_toupper(num_buf[i]); + } + } + + int pad_diff = fw - advance; + for(int i = 0; i < pad_diff; i++) { + SPRINTF_PUTC(str, size, stri, fp); + } + for(int i = 0; i < advance; i++) { + SPRINTF_PUTC(str, size, stri, num_buf[i]); + } + + return stri; +} + +int +s_convert_path(char *str, size_t size, va_list ap, size_t stri) +{ + uint16_t *obj_path = va_arg(ap, uint16_t*); + size_t obj_pathlen = va_arg(ap, size_t); + for(size_t i = 0; i < obj_pathlen; i++) { + uint16_t subdir = obj_path[i]; + int advance = convert_as_int(str, size, stri, subdir, 10, 1); + stri += advance; + SPRINTF_PUTC(str, size, stri, '/'); + } + return stri; } int @@ -56,97 +117,60 @@ vsnprintf( const char *fmt, va_list ap) { int stri = 0; + int state = FSTATE_DIRECT; + for(const char *fmtc = fmt; *fmtc; fmtc++) { - if(*fmtc != '%') { + if(state == FSTATE_DIRECT) { + if(*fmtc == '%') { + state = FSTATE_CONVERT; + continue; + } SPRINTF_PUTC(str, size, stri, *fmtc); - continue; - } - fmtc++; - - //TODO: other format specifiers. - int field_width = 0; - char field_pad = ' '; + }else { + int field_width = 0; + char field_pad = ' '; - int lenspec = 4; + int lenspec = 4; - int radix = 10; - int unsign = 0; - int caps = 0; - switch(*fmtc) { - case 's': - goto string_conversion; - case 'b': - radix = 2; - goto int_conversion; - break; - case 'o': - radix = 8; - goto int_conversion; - break; - case 'p': - lenspec = sizeof(uintptr_t); - field_width = lenspec * 2; - field_pad = '0'; - case 'X': - caps = 1; - case 'x': - unsign = 1; - radix = 16; - goto int_conversion; - break; - case 'u': - unsign = 1; - case 'd': - case 'i': - goto int_conversion; - break; - /*custom formatters for jove.*/ - case 'P': - goto path_conversion; - break; - } -string_conversion: - { - const char *strarg = va_arg(ap, const char*); - for(const char *strargc = strarg; *strargc; strargc++) { - SPRINTF_PUTC(str, size, stri, *strargc); - } - } continue; -int_conversion: - { - uintmax_t value = 0; - switch(lenspec) { - case 1: value = (uintmax_t)(int8_t)va_arg(ap, int); break; - case 2: value = (uintmax_t)(int16_t)va_arg(ap, int); break; - default: - case 4: value = (uintmax_t)va_arg(ap, unsigned int); break; - case 8: value = (uintmax_t)va_arg(ap, uintmax_t); break; - } - size_t pad_stri = stri; - for(size_t i = 0; i < field_width; i++) { - SPRINTF_PUTC(str, size, pad_stri, field_pad); - } + int radix = 10; + int unsign = 0; + int caps = 0; - int advance = convert_as_int(str, size, stri, field_width, value, radix, unsign); - if(caps && str) { - for(int i = 0; i < advance; i++) { - int stra = stri + i; - if(stra < size) str[stra] = c_toupper(str[stra]); + if(state == FSTATE_CONVERT) { + switch(*fmtc) { + case 's': + stri = s_convert_string(str, size, ap, stri); + break; + case 'b': + stri = s_convert_int(str, size, ap, stri, field_width, field_pad, lenspec, 2, 1, 0); + break; + case 'o': + stri = s_convert_int(str, size, ap, stri, field_width, field_pad, lenspec, 8, 0, 0); + break; + case 'p': + lenspec = sizeof(uintptr_t); + field_width = lenspec * 2; + field_pad = '0'; + case 'X': + caps = 1; + case 'x': + unsign = 1; + stri = s_convert_int(str, size, ap, stri, field_width, field_pad, lenspec, 16, unsign, caps); + break; + case 'u': + unsign = 1; + case 'd': + case 'i': + stri = s_convert_int(str, size, ap, stri, field_width, field_pad, lenspec, 10, unsign, caps); + break; + /*custom formatters for jove.*/ + case 'P': + stri = s_convert_path(str, size, ap, stri); + break; } } - stri += advance; - } continue; -path_conversion: - { - uint16_t *obj_path = va_arg(ap, uint16_t*); - size_t obj_pathlen = va_arg(ap, size_t); - for(size_t i = 0; i < obj_pathlen; i++) { - uint16_t subdir = obj_path[i]; - int advance = convert_as_int(str, size, stri, 3, subdir, 10, 1); - stri += advance; - SPRINTF_PUTC(str, size, stri, '/'); - } - } continue; + state = FSTATE_DIRECT; + } } if(str && stri < size) str[stri] = 0; return stri; |
