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);
143 void perror(const char *s)
145 printf("%s: %s\n", s, strerror(errno));
149 /* intern_printf provides all the functionality needed by all the printf
151 * - buf: optional buffer onto which the formatted results are written. If null
152 * then the output goes to the terminal through putchar calls. This is used
153 * by the (v)sprintf variants which write to an array of char.
154 * - sz: optional maximum size of the output, 0 means unlimited. This is used
155 * by the (v)snprintf variants to avoid buffer overflows.
156 * The rest are obvious, format string and variable argument list.
158 static char *convc = "dioxXucsfeEgGpn%";
160 #define IS_CONV(c) strchr(convc, c)
162 #define BUF(x) ((x) ? (x) + cnum : (x))
163 #define SZ(x) ((x) ? (x) - cnum : (x))
165 static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap)
170 const char *fstart = 0;
201 bwrite(out, BUF(buf), SZ(sz), "0x", 2);
213 bwrite(out, BUF(buf), SZ(sz), "0", 1);
221 unum = va_arg(ap, unsigned int);
222 utoa(unum, conv_buf, base);
224 num = va_arg(ap, int);
225 itoa(num, conv_buf, base);
228 for(i=0; conv_buf[i]; i++) {
229 conv_buf[i] = toupper(conv_buf[i]);
233 slen = strlen(conv_buf);
236 if(!unsig && sign && num >= 0) {
237 bwrite(out, BUF(buf), SZ(sz), "+", 1);
240 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
244 for(i=slen; i<fwidth; i++) {
245 bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
249 if(!unsig && sign && num >= 0) {
250 bwrite(out, BUF(buf), SZ(sz), "+", 1);
253 bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
260 char c = va_arg(ap, int);
261 bwrite(out, BUF(buf), SZ(sz), &c, 1);
267 str = va_arg(ap, char*);
271 bwrite(out, BUF(buf), SZ(sz), str, slen);
275 for(i=slen; i<fwidth; i++) {
276 bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
280 bwrite(out, BUF(buf), SZ(sz), str, slen);
286 *va_arg(ap, int*) = cnum;
293 /* restore default conversion state */
326 const char *fw = fmt;
327 while(*fmt && isdigit(*fmt)) fmt++;
336 bwrite(out, BUF(buf), SZ(sz), (char*)fmt++, 1);
346 static char *sconvc = "diouxcsefg%";
348 #define IS_SCONV(c) strchr(sconvc, c)
350 static int intern_scanf(const char *instr, FILE *infile, const char *fmt, va_list ap)
352 return -1; /* TODO */
357 /* bwrite is called by intern_printf to transparently handle writing into a
358 * buffer or to the terminal
360 static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz)
365 if(buf_sz && buf_sz <= sz) sz = buf_sz;
367 memcpy(buf, str, sz);
371 for(i=0; i<sz; i++) {
377 for(i=0; i<sz; i++) {
390 static int readchar(const char *str, FILE *fp)
392 static const char *orig_str;
393 static const char *sptr;
396 if(str == orig_str) {
397 if(!*sptr) return -1;
400 orig_str = sptr = str;
401 return readchar(str, fp);