7 static int intern_printf(int out, char *buf, unsigned long sz, const char *fmt, va_list ap);
8 static void bwrite(int out, char *buf, unsigned long buf_sz, char *str, int sz);
9 static void utoa(unsigned int val, char *buf, int base);
10 static void itoa(int val, char *buf, int base);
12 int sprintf(char *buf, const char *fmt, ...)
18 res = intern_printf(OUT_BUF, buf, 0, fmt, ap);
23 int vsprintf(char *buf, const char *fmt, va_list ap)
25 return intern_printf(OUT_BUF, buf, 0, fmt, ap);
28 int snprintf(char *buf, unsigned long sz, const char *fmt, ...)
34 res = intern_printf(OUT_BUF, buf, sz, fmt, ap);
39 int vsnprintf(char *buf, unsigned long sz, const char *fmt, va_list ap)
41 return intern_printf(OUT_BUF, buf, sz, fmt, ap);
44 /* intern_printf provides all the functionality needed by all the printf
46 * - buf: optional buffer onto which the formatted results are written. If null
47 * then the output goes to the terminal through putchar calls. This is used
48 * by the (v)sprintf variants which write to an array of char.
49 * - sz: optional maximum size of the output, 0 means unlimited. This is used
50 * by the (v)snprintf variants to avoid buffer overflows.
51 * The rest are obvious, format string and variable argument list.
53 static char *convc = "dioxXucsfeEgGpn%";
55 #define IS_CONV(c) strchr(convc, c)
57 #define BUF(x) ((x) ? (x) + cnum : (x))
58 #define SZ(x) ((x) ? (x) - cnum : (x))
60 static int intern_printf(int out, char *buf, unsigned long sz, const char *fmt, va_list ap)
65 const char *fstart = 0;
96 bwrite(out, BUF(buf), SZ(sz), "0x", 2);
108 bwrite(out, BUF(buf), SZ(sz), "0", 1);
116 unum = va_arg(ap, unsigned int);
117 utoa(unum, conv_buf, base);
119 num = va_arg(ap, int);
120 itoa(num, conv_buf, base);
123 for(i=0; conv_buf[i]; i++) {
124 conv_buf[i] = toupper(conv_buf[i]);
128 slen = strlen(conv_buf);
131 if(!unsig && sign && num >= 0) {
132 bwrite(out, BUF(buf), SZ(sz), "+", 1);
135 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
139 for(i=slen; i<fwidth; i++) {
140 bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
144 if(!unsig && sign && num >= 0) {
145 bwrite(out, BUF(buf), SZ(sz), "+", 1);
148 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
155 char c = va_arg(ap, int);
156 bwrite(out, BUF(buf), SZ(sz), &c, 1);
162 str = va_arg(ap, char*);
166 bwrite(out, BUF(buf), SZ(sz), str, slen);
170 for(i=slen; i<fwidth; i++) {
171 bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
175 bwrite(out, BUF(buf), SZ(sz), str, slen);
181 *va_arg(ap, int*) = cnum;
188 /* restore default conversion state */
221 const char *fw = fmt;
222 while(*fmt && isdigit(*fmt)) fmt++;
231 bwrite(out, BUF(buf), SZ(sz), (char*)fmt++, 1);
239 /* bwrite is called by intern_printf to transparently handle writing into a
240 * buffer or to the terminal
242 static void bwrite(int out, char *buf, unsigned long buf_sz, char *str, int sz)
245 if(buf_sz && buf_sz <= sz) sz = buf_sz;
247 memcpy(buf, str, sz);
251 static void utoa(unsigned int val, char *buf, int base)
253 static char rbuf[16];
261 unsigned int digit = val % base;
262 *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a');
274 static void itoa(int val, char *buf, int base)
276 static char rbuf[16];
290 int digit = val % base;
291 *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a');