14 static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap);
15 static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz);
23 int puts(const char *s)
32 /* -- printf and friends -- */
34 int printf(const char *fmt, ...)
40 res = intern_printf(OUT_DEF, 0, 0, fmt, ap);
45 int vprintf(const char *fmt, va_list ap)
47 return intern_printf(OUT_DEF, 0, 0, fmt, ap);
50 int sprintf(char *buf, const char *fmt, ...)
56 res = intern_printf(OUT_BUF, buf, 0, fmt, ap);
61 int vsprintf(char *buf, const char *fmt, va_list ap)
63 return intern_printf(OUT_BUF, buf, 0, fmt, ap);
66 int snprintf(char *buf, size_t sz, const char *fmt, ...)
72 res = intern_printf(OUT_BUF, buf, sz, fmt, ap);
77 int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap)
79 return intern_printf(OUT_BUF, buf, sz, fmt, ap);
82 /* intern_printf provides all the functionality needed by all the printf
84 * - buf: optional buffer onto which the formatted results are written. If null
85 * then the output goes to the terminal through putchar calls. This is used
86 * by the (v)sprintf variants which write to an array of char.
87 * - sz: optional maximum size of the output, 0 means unlimited. This is used
88 * by the (v)snprintf variants to avoid buffer overflows.
89 * The rest are obvious, format string and variable argument list.
91 static char *convc = "dioxXucsfeEgGpn%";
93 #define IS_CONV(c) strchr(convc, c)
95 #define BUF(x) ((x) ? (x) + cnum : (x))
96 #define SZ(x) ((x) ? (x) - cnum : (x))
98 static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap)
103 const char *fstart = 0;
134 bwrite(out, BUF(buf), SZ(sz), "0x", 2);
146 bwrite(out, BUF(buf), SZ(sz), "0", 1);
154 unum = va_arg(ap, unsigned int);
155 utoa(unum, conv_buf, base);
157 num = va_arg(ap, int);
158 itoa(num, conv_buf, base);
161 for(i=0; conv_buf[i]; i++) {
162 conv_buf[i] = toupper(conv_buf[i]);
166 slen = strlen(conv_buf);
169 if(!unsig && sign && num >= 0) {
170 bwrite(out, BUF(buf), SZ(sz), "+", 1);
173 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
177 for(i=slen; i<fwidth; i++) {
178 bwrite(out, BUF(buf), SZ(sz), &padc, 1);
182 if(!unsig && sign && num >= 0) {
183 bwrite(out, BUF(buf), SZ(sz), "+", 1);
186 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
193 char c = va_arg(ap, int);
194 bwrite(out, BUF(buf), SZ(sz), &c, 1);
200 str = va_arg(ap, char*);
204 bwrite(out, BUF(buf), SZ(sz), str, slen);
208 for(i=slen; i<fwidth; i++) {
209 bwrite(out, BUF(buf), SZ(sz), &padc, 1);
213 bwrite(out, BUF(buf), SZ(sz), str, slen);
219 *va_arg(ap, int*) = cnum;
226 /* restore default conversion state */
259 const char *fw = fmt;
260 while(*fmt && isdigit(*fmt)) fmt++;
269 bwrite(out, BUF(buf), SZ(sz), (char*)fmt++, 1);
278 /* bwrite is called by intern_printf to transparently handle writing into a
279 * buffer or to the terminal
281 static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz)
286 if(buf_sz && buf_sz <= sz) sz = buf_sz;
288 memcpy(buf, str, sz);
292 for(i=0; i<sz; i++) {