#include #include enum TYPE { TYPE_INT = 1, TYPE_UINT = 2, TYPE_HEX = 3, TYPE_STRING = 4 }; enum FLAGS { FL_ZERO = 1, /* zero padded */ }; static void hex(char **str, char flags, int fwidth, int size, int x) { int i, y, len; char c; char *s = "0x"; while(*s) *(*str)++ = *s++; /* calculate the number of digits */ len = 0; y = x; for(i = 0; i < sizeof(y) << 1; i++) { c = ((unsigned int) y >> 28); if(c) len++; y = y << 4; } /* print the padding characters (if any) */ c = ' '; if(flags & FL_ZERO) c = '0'; for(i = 0; i < fwidth - len; i++) *(*str)++ = c; /* actually print the digits */ for(i = 0; i < sizeof(x) << 1; i++) { c = ((unsigned int) x >> 28) + '0'; if(c > '9') c += 7; if(c != '0') *(*str)++ = c; x = x << 4; } } int vsprintf(char *str, char *fmt, va_list ap) { int x, fwidth; char flags; char *s; char *start = str; uint8_t type; while(*fmt) { if(*fmt != '%') { *str++ = *fmt++; continue; } type = 0; flags = 0; fwidth = 0; fmt++; while(1) { switch(*fmt) { case 's': if(type) goto done; type = TYPE_STRING; break; case 'x': if(type) goto done; type = TYPE_HEX; break; default: /* the first zero enables zero-padding */ if(*fmt == '0' && !fwidth) { flags |= FL_ZERO; goto next;; } /* subsequent numbers indicate field width */ if(*fmt >= '0' && *fmt <= '9') { fwidth = (fwidth * 10) + (*fmt - '0'); goto next;; } goto done; break; } next: fmt++; } done: switch(type) { case TYPE_STRING: s = va_arg(ap, char*); while(*s) *str++ = *s++; break; case TYPE_HEX: x = va_arg(ap, int); hex(&str, flags, fwidth, 4, x); break; } } *str = 0; return (str - start); }