2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018 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 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
23 extern void pcboot_putchar(int c);
25 static void bwrite(char *buf, size_t buf_sz, char *str, int sz);
26 static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap);
34 int puts(const char *s)
43 /* -- printf and friends -- */
45 static char *convc = "dioxXucsfeEgGpn%";
47 #define IS_CONV(c) strchr(convc, c)
49 int printf(const char *fmt, ...)
55 res = intern_printf(0, 0, fmt, ap);
60 int vprintf(const char *fmt, va_list ap)
62 return intern_printf(0, 0, fmt, ap);
65 int sprintf(char *buf, const char *fmt, ...)
71 res = intern_printf(buf, 0, fmt, ap);
76 int vsprintf(char *buf, const char *fmt, va_list ap)
78 return intern_printf(buf, 0, fmt, ap);
81 int snprintf(char *buf, size_t sz, const char *fmt, ...)
87 res = intern_printf(buf, sz, fmt, ap);
92 int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap)
94 return intern_printf(buf, sz, fmt, ap);
98 /* intern_printf provides all the functionality needed by all the printf
100 * - buf: optional buffer onto which the formatted results are written. If null
101 * then the output goes to the terminal through putchar calls. This is used
102 * by the (v)sprintf variants which write to an array of char.
103 * - sz: optional maximum size of the output, 0 means unlimited. This is used
104 * by the (v)snprintf variants to avoid buffer overflows.
105 * The rest are obvious, format string and variable argument list.
108 #define BUF(x) ((x) ? (x) + cnum : (x))
109 #define SZ(x) ((x) ? (x) - cnum : (x))
111 static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap)
116 const char *fstart = 0;
125 int left_align = 0; /* not implemented yet */
146 bwrite(BUF(buf), SZ(sz), "0x", 2);
157 bwrite(BUF(buf), SZ(sz), "0", 1);
164 utoa(va_arg(ap, unsigned int), conv_buf, base);
166 itoa(va_arg(ap, int), conv_buf, base);
169 for(i=0; conv_buf[i]; i++) {
170 conv_buf[i] = toupper(conv_buf[i]);
174 slen = strlen(conv_buf);
175 for(i=slen; i<fwidth; i++) {
176 bwrite(BUF(buf), SZ(sz), (char*)&padc, 1);
180 bwrite(BUF(buf), SZ(sz), conv_buf, strlen(conv_buf));
186 char c = va_arg(ap, int);
187 bwrite(BUF(buf), SZ(sz), &c, 1);
193 str = va_arg(ap, char*);
196 for(i=slen; i<fwidth; i++) {
197 bwrite(BUF(buf), SZ(sz), (char*)&padc, 1);
200 bwrite(BUF(buf), SZ(sz), str, slen);
205 *va_arg(ap, int*) = cnum;
212 /* restore default conversion state */
245 const char *fw = fmt;
246 while(*fmt && isdigit(*fmt)) fmt++;
255 bwrite(BUF(buf), SZ(sz), (char*)fmt++, 1);
264 /* bwrite is called by intern_printf to transparently handle writing into a
265 * buffer (if buf is non-null) or to the terminal (if buf is null).
267 static void bwrite(char *buf, size_t buf_sz, char *str, int sz)
270 if(buf_sz && buf_sz <= sz) sz = buf_sz - 1;
271 memcpy(buf, str, sz);
276 for(i=0; i<sz; i++) {