#include "printf.h" #include "string.h" #include "init.h" #include "hal/obj.h" #include int kprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); int r = kvprintf(fmt, ap); va_end(ap); return r; } #define SPRINTF_PUTC(str, size, i, c) \ if(str && i < size) str[i] = (c); \ i++ static int convert_as_int( char *str, size_t size, int stri, uintmax_t value, int radix, int unsign) { unsigned digits = 0; int ostri = stri; if((intmax_t)value < 0 && !unsign) { SPRINTF_PUTC(str, size, stri, '-'); value = 0 - (intmax_t)value; } for(uintmax_t i = value; i != 0; i /= radix) digits++; if(value == 0) digits++; for(uintmax_t i = value, digiti = 0; digiti < digits; i /= radix) { char i_mod = (char)(i % radix); 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 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 vsnprintf( char *str, size_t size, const char *fmt, va_list ap) { int stri = 0; int state = FSTATE_DIRECT; for(const char *fmtc = fmt; *fmtc; fmtc++) { if(state == FSTATE_DIRECT) { if(*fmtc == '%') { state = FSTATE_CONVERT; continue; } SPRINTF_PUTC(str, size, stri, *fmtc); }else { int field_width = 0; char field_pad = ' '; int lenspec = 4; int radix = 10; int unsign = 0; int caps = 0; 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; } } state = FSTATE_DIRECT; } } if(str && stri < size) str[stri] = 0; return stri; }