10 static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap);
11 static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz);
12 /*static int readchar(const char *str, FILE *fp);*/
20 int puts(const char *s)
29 /* -- printf and friends -- */
31 int printf(const char *fmt, ...)
37 res = intern_printf(OUT_DEF, 0, 0, fmt, ap);
42 int vprintf(const char *fmt, va_list ap)
44 return intern_printf(OUT_DEF, 0, 0, fmt, ap);
47 int sprintf(char *buf, const char *fmt, ...)
53 res = intern_printf(OUT_BUF, buf, 0, fmt, ap);
58 int vsprintf(char *buf, const char *fmt, va_list ap)
60 return intern_printf(OUT_BUF, buf, 0, fmt, ap);
63 int snprintf(char *buf, size_t sz, const char *fmt, ...)
69 res = intern_printf(OUT_BUF, buf, sz, fmt, ap);
74 int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap)
76 return intern_printf(OUT_BUF, buf, sz, fmt, ap);
79 /* intern_printf provides all the functionality needed by all the printf
81 * - buf: optional buffer onto which the formatted results are written. If null
82 * then the output goes to the terminal through putchar calls. This is used
83 * by the (v)sprintf variants which write to an array of char.
84 * - sz: optional maximum size of the output, 0 means unlimited. This is used
85 * by the (v)snprintf variants to avoid buffer overflows.
86 * The rest are obvious, format string and variable argument list.
88 static char *convc = "dioxXucsfeEgGpn%";
90 #define IS_CONV(c) strchr(convc, c)
92 #define BUF(x) ((x) ? (x) + cnum : (x))
93 #define SZ(x) ((x) ? (x) - cnum : (x))
95 static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap)
100 const char *fstart = 0;
131 bwrite(out, BUF(buf), SZ(sz), "0x", 2);
143 bwrite(out, BUF(buf), SZ(sz), "0", 1);
151 unum = va_arg(ap, unsigned int);
152 utoa(unum, conv_buf, base);
154 num = va_arg(ap, int);
155 itoa(num, conv_buf, base);
158 for(i=0; conv_buf[i]; i++) {
159 conv_buf[i] = toupper(conv_buf[i]);
163 slen = strlen(conv_buf);
166 if(!unsig && sign && num >= 0) {
167 bwrite(out, BUF(buf), SZ(sz), "+", 1);
170 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
174 for(i=slen; i<fwidth; i++) {
175 bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
179 if(!unsig && sign && num >= 0) {
180 bwrite(out, BUF(buf), SZ(sz), "+", 1);
183 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
190 char c = va_arg(ap, int);
191 bwrite(out, BUF(buf), SZ(sz), &c, 1);
197 str = va_arg(ap, char*);
201 bwrite(out, BUF(buf), SZ(sz), str, slen);
205 for(i=slen; i<fwidth; i++) {
206 bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
210 bwrite(out, BUF(buf), SZ(sz), str, slen);
216 *va_arg(ap, int*) = cnum;
223 /* restore default conversion state */
256 const char *fw = fmt;
257 while(*fmt && isdigit(*fmt)) fmt++;
266 bwrite(out, BUF(buf), SZ(sz), (char*)fmt++, 1);
275 /* bwrite is called by intern_printf to transparently handle writing into a
276 * buffer or to the terminal
278 static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz)
283 if(buf_sz && buf_sz <= sz) sz = buf_sz;
285 memcpy(buf, str, sz);
289 for(i=0; i<sz; i++) {
301 static int readchar(const char *str, FILE *fp)
303 static const char *orig_str;
304 static const char *sptr;
307 if(str == orig_str) {
308 if(!*sptr) return -1;
311 orig_str = sptr = str;
312 return readchar(str, fp);