2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018-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 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/>.
33 extern void pcboot_putchar(int c);
35 static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap);
36 static int intern_scanf(const char *instr, FILE *infile, const char *fmt, va_list ap);
37 static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz);
38 /*static int readchar(const char *str, FILE *fp);*/
46 int puts(const char *s)
55 /* -- printf and friends -- */
57 int printf(const char *fmt, ...)
63 res = intern_printf(OUT_DEF, 0, 0, fmt, ap);
68 int vprintf(const char *fmt, va_list ap)
70 return intern_printf(OUT_DEF, 0, 0, fmt, ap);
73 int sprintf(char *buf, const char *fmt, ...)
79 res = intern_printf(OUT_BUF, buf, 0, fmt, ap);
84 int vsprintf(char *buf, const char *fmt, va_list ap)
86 return intern_printf(OUT_BUF, buf, 0, fmt, ap);
89 int snprintf(char *buf, size_t sz, const char *fmt, ...)
95 res = intern_printf(OUT_BUF, buf, sz, fmt, ap);
100 int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap)
102 return intern_printf(OUT_BUF, buf, sz, fmt, ap);
105 int fprintf(FILE *fp, const char *fmt, ...)
111 res = vfprintf(fp, fmt, ap);
116 int vfprintf(FILE *fp, const char *fmt, va_list ap)
118 if(fp == stdout || fp == stderr) {
119 return vprintf(fmt, ap);
122 panic("*fprintf for anything other than stdout/stderr, not implemented yet\n");
126 int ser_printf(const char *fmt, ...)
132 res = intern_printf(OUT_SER, 0, 0, fmt, ap);
137 int ser_vprintf(const char *fmt, va_list ap)
139 return intern_printf(OUT_SER, 0, 0, fmt, ap);
142 void perror(const char *s)
144 printf("%s: %s\n", s, strerror(errno));
147 /* intern_printf provides all the functionality needed by all the printf
149 * - buf: optional buffer onto which the formatted results are written. If null
150 * then the output goes to the terminal through putchar calls. This is used
151 * by the (v)sprintf variants which write to an array of char.
152 * - sz: optional maximum size of the output, 0 means unlimited. This is used
153 * by the (v)snprintf variants to avoid buffer overflows.
154 * The rest are obvious, format string and variable argument list.
156 static char *convc = "dioxXucsfeEgGpn%";
158 #define IS_CONV(c) strchr(convc, c)
160 #define BUF(x) ((x) ? (x) + cnum : (x))
161 #define SZ(x) ((x) ? (x) - cnum : (x))
163 static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap)
168 const char *fstart = 0;
199 bwrite(out, BUF(buf), SZ(sz), "0x", 2);
211 bwrite(out, BUF(buf), SZ(sz), "0", 1);
219 unum = va_arg(ap, unsigned int);
220 utoa(unum, conv_buf, base);
222 num = va_arg(ap, int);
223 itoa(num, conv_buf, base);
226 for(i=0; conv_buf[i]; i++) {
227 conv_buf[i] = toupper(conv_buf[i]);
231 slen = strlen(conv_buf);
234 if(!unsig && sign && num >= 0) {
235 bwrite(out, BUF(buf), SZ(sz), "+", 1);
238 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
242 for(i=slen; i<fwidth; i++) {
243 bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
247 if(!unsig && sign && num >= 0) {
248 bwrite(out, BUF(buf), SZ(sz), "+", 1);
251 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
258 char c = va_arg(ap, int);
259 bwrite(out, BUF(buf), SZ(sz), &c, 1);
265 str = va_arg(ap, char*);
269 bwrite(out, BUF(buf), SZ(sz), str, slen);
273 for(i=slen; i<fwidth; i++) {
274 bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
278 bwrite(out, BUF(buf), SZ(sz), str, slen);
284 *va_arg(ap, int*) = cnum;
291 /* restore default conversion state */
324 const char *fw = fmt;
325 while(*fmt && isdigit(*fmt)) fmt++;
334 bwrite(out, BUF(buf), SZ(sz), (char*)fmt++, 1);
344 static char *sconvc = "diouxcsefg%";
346 #define IS_SCONV(c) strchr(sconvc, c)
348 static int intern_scanf(const char *instr, FILE *infile, const char *fmt, va_list ap)
350 return -1; /* TODO */
355 /* bwrite is called by intern_printf to transparently handle writing into a
356 * buffer or to the terminal
358 static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz)
363 if(buf_sz && buf_sz <= sz) sz = buf_sz;
365 memcpy(buf, str, sz);
369 for(i=0; i<sz; i++) {
375 for(i=0; i<sz; i++) {
388 static int readchar(const char *str, FILE *fp)
390 static const char *orig_str;
391 static const char *sptr;
394 if(str == orig_str) {
395 if(!*sptr) return -1;
398 orig_str = sptr = str;
399 return readchar(str, fp);