2 visor - lightweight system-independent embeddable text editor framework
3 Copyright (C) 2019 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
24 static int intern_printf(int out, char *buf, unsigned long sz, const char *fmt, va_list ap);
25 static void bwrite(int out, char *buf, unsigned long buf_sz, char *str, int sz);
26 static void utoa(unsigned int val, char *buf, int base);
27 static void itoa(int val, char *buf, int base);
29 int sprintf(char *buf, const char *fmt, ...)
35 res = intern_printf(OUT_BUF, buf, 0, fmt, ap);
40 int vsprintf(char *buf, const char *fmt, va_list ap)
42 return intern_printf(OUT_BUF, buf, 0, fmt, ap);
45 int snprintf(char *buf, unsigned long sz, const char *fmt, ...)
51 res = intern_printf(OUT_BUF, buf, sz, fmt, ap);
56 int vsnprintf(char *buf, unsigned long sz, const char *fmt, va_list ap)
58 return intern_printf(OUT_BUF, buf, sz, fmt, ap);
61 /* intern_printf provides all the functionality needed by all the printf
63 * - buf: optional buffer onto which the formatted results are written. If null
64 * then the output goes to the terminal through putchar calls. This is used
65 * by the (v)sprintf variants which write to an array of char.
66 * - sz: optional maximum size of the output, 0 means unlimited. This is used
67 * by the (v)snprintf variants to avoid buffer overflows.
68 * The rest are obvious, format string and variable argument list.
70 static char *convc = "dioxXucsfeEgGpn%";
72 #define IS_CONV(c) strchr(convc, c)
74 #define BUF(x) ((x) ? (x) + cnum : (x))
75 #define SZ(x) ((x) ? (x) - cnum : (x))
77 static int intern_printf(int out, char *buf, unsigned long sz, const char *fmt, va_list ap)
82 const char *fstart = 0;
113 bwrite(out, BUF(buf), SZ(sz), "0x", 2);
125 bwrite(out, BUF(buf), SZ(sz), "0", 1);
133 unum = va_arg(ap, unsigned int);
134 utoa(unum, conv_buf, base);
136 num = va_arg(ap, int);
137 itoa(num, conv_buf, base);
140 for(i=0; conv_buf[i]; i++) {
141 conv_buf[i] = toupper(conv_buf[i]);
145 slen = strlen(conv_buf);
148 if(!unsig && sign && num >= 0) {
149 bwrite(out, BUF(buf), SZ(sz), "+", 1);
152 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
156 for(i=slen; i<fwidth; i++) {
157 bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
161 if(!unsig && sign && num >= 0) {
162 bwrite(out, BUF(buf), SZ(sz), "+", 1);
165 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
172 char c = va_arg(ap, int);
173 bwrite(out, BUF(buf), SZ(sz), &c, 1);
179 str = va_arg(ap, char*);
183 bwrite(out, BUF(buf), SZ(sz), str, slen);
187 for(i=slen; i<fwidth; i++) {
188 bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
192 bwrite(out, BUF(buf), SZ(sz), str, slen);
198 *va_arg(ap, int*) = cnum;
205 /* restore default conversion state */
238 const char *fw = fmt;
239 while(*fmt && isdigit(*fmt)) fmt++;
248 bwrite(out, BUF(buf), SZ(sz), (char*)fmt++, 1);
256 /* bwrite is called by intern_printf to transparently handle writing into a
257 * buffer or to the terminal
259 static void bwrite(int out, char *buf, unsigned long buf_sz, char *str, int sz)
262 if(buf_sz && buf_sz <= sz) sz = buf_sz;
264 memcpy(buf, str, sz);
268 static void utoa(unsigned int val, char *buf, int base)
270 static char rbuf[16];
278 unsigned int digit = val % base;
279 *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a');
291 static void itoa(int val, char *buf, int base)
293 static char rbuf[16];
307 int digit = val % base;
308 *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a');