nuclear@1: #include nuclear@5: #include nuclear@5: #include nuclear@5: nuclear@5: static void bwrite(char *buf, size_t buf_sz, char *str, int sz); nuclear@5: static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap); nuclear@1: nuclear@1: /* putchar is defined in term.c */ nuclear@1: nuclear@1: int puts(const char *s) nuclear@1: { nuclear@1: while(*s) { nuclear@1: putchar(*s++); nuclear@1: } nuclear@2: putchar('\n'); nuclear@1: return 0; nuclear@1: } nuclear@5: nuclear@5: /* -- printf and friends -- */ nuclear@5: nuclear@5: static char *convc = "dioxXucsfeEgGpn%"; nuclear@5: nuclear@5: #define IS_CONV(c) strchr(convc, c) nuclear@5: nuclear@5: int printf(const char *fmt, ...) nuclear@5: { nuclear@5: int res; nuclear@5: va_list ap; nuclear@5: nuclear@5: va_start(ap, fmt); nuclear@5: res = intern_printf(0, 0, fmt, ap); nuclear@5: va_end(ap); nuclear@5: return res; nuclear@5: } nuclear@5: nuclear@5: int vprintf(const char *fmt, va_list ap) nuclear@5: { nuclear@5: return intern_printf(0, 0, fmt, ap); nuclear@5: } nuclear@5: nuclear@5: int sprintf(char *buf, const char *fmt, ...) nuclear@5: { nuclear@5: int res; nuclear@5: va_list ap; nuclear@5: nuclear@5: va_start(ap, fmt); nuclear@5: res = intern_printf(buf, 0, fmt, ap); nuclear@5: va_end(ap); nuclear@5: return res; nuclear@5: } nuclear@5: nuclear@5: int vsprintf(char *buf, const char *fmt, va_list ap) nuclear@5: { nuclear@5: return intern_printf(buf, 0, fmt, ap); nuclear@5: } nuclear@5: nuclear@5: int snprintf(char *buf, size_t sz, const char *fmt, ...) nuclear@5: { nuclear@5: int res; nuclear@5: va_list ap; nuclear@5: nuclear@5: va_start(ap, fmt); nuclear@5: res = intern_printf(buf, sz, fmt, ap); nuclear@5: va_end(ap); nuclear@5: return res; nuclear@5: } nuclear@5: nuclear@5: int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap) nuclear@5: { nuclear@5: return intern_printf(buf, sz, fmt, ap); nuclear@5: } nuclear@5: nuclear@5: nuclear@5: /* intern_printf provides all the functionality needed by all the printf nuclear@5: * variants. nuclear@5: * - buf: optional buffer onto which the formatted results are written. If null nuclear@5: * then the output goes to the terminal through putchar calls. This is used nuclear@5: * by the (v)sprintf variants which write to an array of char. nuclear@5: * - sz: optional maximum size of the output, 0 means unlimited. This is used nuclear@5: * by the (v)snprintf variants to avoid buffer overflows. nuclear@5: * The rest are obvious, format string and variable argument list. nuclear@5: */ nuclear@5: nuclear@5: #define BUF(x) ((x) ? (x) + cnum : (x)) nuclear@5: #define SZ(x) ((x) ? (x) - cnum : (x)) nuclear@5: nuclear@5: static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap) nuclear@5: { nuclear@5: char conv_buf[32]; nuclear@5: char *str; nuclear@5: int i, slen; nuclear@5: const char *fstart = 0; nuclear@5: nuclear@5: /* state */ nuclear@5: int cnum = 0; nuclear@5: int base = 10; nuclear@5: int alt = 0; nuclear@5: int fwidth = 0; nuclear@5: int padc = ' '; nuclear@5: int sign = 0; nuclear@5: int left_align = 0; /* not implemented yet */ nuclear@5: int hex_caps = 0; nuclear@5: int unsig = 0; nuclear@5: nuclear@5: while(*fmt) { nuclear@5: if(*fmt == '%') { nuclear@5: fstart = fmt++; nuclear@5: continue; nuclear@5: } nuclear@5: nuclear@5: if(fstart) { nuclear@5: if(IS_CONV(*fmt)) { nuclear@5: switch(*fmt) { nuclear@5: case 'X': nuclear@5: hex_caps = 1; nuclear@5: nuclear@5: case 'x': nuclear@5: case 'p': nuclear@5: base = 16; nuclear@5: nuclear@5: if(alt) { nuclear@5: bwrite(BUF(buf), SZ(sz), "0x", 2); nuclear@5: } nuclear@5: nuclear@5: case 'u': nuclear@5: unsig = 1; nuclear@5: nuclear@5: if(0) { nuclear@5: case 'o': nuclear@5: base = 8; nuclear@5: nuclear@5: if(alt) { nuclear@5: bwrite(BUF(buf), SZ(sz), "0", 1); nuclear@5: } nuclear@5: } nuclear@5: nuclear@5: case 'd': nuclear@5: case 'i': nuclear@5: if(unsig) { nuclear@5: utoa(va_arg(ap, unsigned int), conv_buf, base); nuclear@5: } else { nuclear@5: itoa(va_arg(ap, int), conv_buf, base); nuclear@5: } nuclear@5: if(hex_caps) { nuclear@5: for(i=0; conv_buf[i]; i++) { nuclear@5: conv_buf[i] = toupper(conv_buf[i]); nuclear@5: } nuclear@5: } nuclear@5: nuclear@5: slen = strlen(conv_buf); nuclear@5: for(i=slen; i