1bfd67e9cSitohy /*
2bfd67e9cSitohy * minimal printf for Human68k DOS
3bfd67e9cSitohy *
4*ed461fc1Sitohy * written by ITOH Yasufumi
5bfd67e9cSitohy * public domain
6bfd67e9cSitohy *
7*ed461fc1Sitohy * $NetBSD: xprintf.c,v 1.5 2011/02/21 02:31:58 itohy Exp $
8bfd67e9cSitohy */
9bfd67e9cSitohy
10bfd67e9cSitohy #include <sys/types.h>
11bfd67e9cSitohy #ifdef __STDC__
12bfd67e9cSitohy # include <stdarg.h>
13bfd67e9cSitohy #else
14bfd67e9cSitohy # include <varargs.h>
15bfd67e9cSitohy #endif
16bfd67e9cSitohy
17bfd67e9cSitohy #include <dos.h>
18bfd67e9cSitohy #include <dos_errno.h>
19bfd67e9cSitohy
20bfd67e9cSitohy #include "xprintf.h"
21bfd67e9cSitohy
22bfd67e9cSitohy /*
23bfd67e9cSitohy * From ISO/IEC 9899:1990
24bfd67e9cSitohy * 7.9.6.1 The fprintf function
25bfd67e9cSitohy * ...
26bfd67e9cSitohy * Environment limit
27bfd67e9cSitohy * The minimum value for the maximum number of characters
28bfd67e9cSitohy * produced by any single conversion shall be 509.
29bfd67e9cSitohy *
30bfd67e9cSitohy * so the following value shall not be smaller than 510
31bfd67e9cSitohy * if you want to conform ANSI C (it is only a guideline
32bfd67e9cSitohy * and maybe no sense on this code, of course :-).
33bfd67e9cSitohy */
34bfd67e9cSitohy #define PRINTF_BUFSZ 4096
35bfd67e9cSitohy
36bfd67e9cSitohy /*
37bfd67e9cSitohy * Shift-JIS kanji support
38bfd67e9cSitohy * (No special handling needed for EUC)
39bfd67e9cSitohy */
40bfd67e9cSitohy #define SJIS
41bfd67e9cSitohy
42bfd67e9cSitohy #ifdef SJIS
43bfd67e9cSitohy #define UC(c) ((unsigned char) (c))
44bfd67e9cSitohy #define IS_SJIS1(c) ((UC(c) > 0x80 && UC(c) < 0xa0) || \
45bfd67e9cSitohy (UC(c) >= 0xe0 && UC(c) <= 0xfc))
46bfd67e9cSitohy #define IS_SJIS2(c) (UC(c) >= 0x40 && UC(c) <= 0xfc && UC(c) != 0x7f)
47bfd67e9cSitohy #endif
48bfd67e9cSitohy
49bfd67e9cSitohy #if !defined(__STDC__) && !defined(const)
50bfd67e9cSitohy #define const
51bfd67e9cSitohy #endif
52bfd67e9cSitohy
53bfd67e9cSitohy extern const char *const __progname;
54bfd67e9cSitohy
5502cdf4d2Sdsl static char * numstr(char *buf, long val, int base, int sign);
56bfd67e9cSitohy
57bfd67e9cSitohy /*
58bfd67e9cSitohy * convert number to string
59bfd67e9cSitohy * buf must have enough space
60bfd67e9cSitohy */
61bfd67e9cSitohy static char *
numstr(char * buf,long val,int base,int sign)6282357f6dSdsl numstr(char *buf, long val, int base, int sign)
63bfd67e9cSitohy {
64bfd67e9cSitohy unsigned long v;
65bfd67e9cSitohy char rev[32];
66bfd67e9cSitohy char *r = rev, *b = buf;
67bfd67e9cSitohy
68bfd67e9cSitohy /* negative? */
69bfd67e9cSitohy if (sign && val < 0) {
70bfd67e9cSitohy v = -val;
71bfd67e9cSitohy *b++ = '-';
72bfd67e9cSitohy } else {
73bfd67e9cSitohy v = val;
74bfd67e9cSitohy }
75bfd67e9cSitohy
76bfd67e9cSitohy /* inverse order */
77bfd67e9cSitohy do {
78bfd67e9cSitohy *r++ = "0123456789abcdef"[v % base];
79bfd67e9cSitohy v /= base;
80bfd67e9cSitohy } while (v);
81bfd67e9cSitohy
82bfd67e9cSitohy /* reverse string */
83bfd67e9cSitohy while (r > rev)
84bfd67e9cSitohy *b++ = *--r;
85bfd67e9cSitohy
86bfd67e9cSitohy *b = '\0';
87bfd67e9cSitohy return buf;
88bfd67e9cSitohy }
89bfd67e9cSitohy
90bfd67e9cSitohy /*
91bfd67e9cSitohy * supported format: %x, %p, %s, %c, %d, %u, %o
92bfd67e9cSitohy * \n is converted to \r\n
93bfd67e9cSitohy *
94bfd67e9cSitohy * XXX argument/parameter types are not strictly handled
95bfd67e9cSitohy */
96bfd67e9cSitohy size_t
xvsnprintf(char * buf,size_t len,const char * fmt,va_list ap)97454af1c0Sdsl xvsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
98bfd67e9cSitohy {
99bfd67e9cSitohy char *b = buf;
100bfd67e9cSitohy const char *s;
101bfd67e9cSitohy char numbuf[32];
102bfd67e9cSitohy
103bfd67e9cSitohy while (*fmt && len > 1) {
104bfd67e9cSitohy if (*fmt != '%') {
105bfd67e9cSitohy #ifdef SJIS
106bfd67e9cSitohy if (IS_SJIS1(*fmt) && IS_SJIS2(fmt[1])) {
107bfd67e9cSitohy if (len <= 2)
108bfd67e9cSitohy break; /* not enough space */
109bfd67e9cSitohy *b++ = *fmt++;
110bfd67e9cSitohy len--;
111bfd67e9cSitohy }
112bfd67e9cSitohy #endif
113bfd67e9cSitohy if (*fmt == '\n' && (b == buf || b[-1] != '\r')) {
114bfd67e9cSitohy if (len <= 2)
115bfd67e9cSitohy break;
116bfd67e9cSitohy *b++ = '\r';
117bfd67e9cSitohy len--;
118bfd67e9cSitohy }
119bfd67e9cSitohy *b++ = *fmt++;
120bfd67e9cSitohy len--;
121bfd67e9cSitohy continue;
122bfd67e9cSitohy }
123bfd67e9cSitohy
124bfd67e9cSitohy /* %? */
125bfd67e9cSitohy fmt++;
126bfd67e9cSitohy switch (*fmt++) {
127bfd67e9cSitohy case '%': /* "%%" -> literal % */
128bfd67e9cSitohy *b++ = '%';
129bfd67e9cSitohy len--;
130bfd67e9cSitohy break;
131bfd67e9cSitohy
132bfd67e9cSitohy case 'd':
133bfd67e9cSitohy s = numstr(numbuf, va_arg(ap, long), 10, 1);
134bfd67e9cSitohy copy_string:
135bfd67e9cSitohy for ( ; *s && len > 1; len--)
136bfd67e9cSitohy *b++ = *s++;
137bfd67e9cSitohy break;
138bfd67e9cSitohy
139bfd67e9cSitohy case 'u':
140bfd67e9cSitohy s = numstr(numbuf, va_arg(ap, long), 10, 0);
141bfd67e9cSitohy goto copy_string;
142bfd67e9cSitohy
143bfd67e9cSitohy case 'p':
144bfd67e9cSitohy *b++ = '0';
145bfd67e9cSitohy len--;
146bfd67e9cSitohy if (len > 1) {
147bfd67e9cSitohy *b++ = 'x';
148bfd67e9cSitohy len--;
149bfd67e9cSitohy }
150bfd67e9cSitohy /* FALLTHROUGH */
151bfd67e9cSitohy case 'x':
152bfd67e9cSitohy s = numstr(numbuf, va_arg(ap, long), 16, 0);
153bfd67e9cSitohy goto copy_string;
154bfd67e9cSitohy
155bfd67e9cSitohy case 'o':
156bfd67e9cSitohy s = numstr(numbuf, va_arg(ap, long), 8, 0);
157bfd67e9cSitohy goto copy_string;
158bfd67e9cSitohy
159bfd67e9cSitohy case 's':
160bfd67e9cSitohy s = va_arg(ap, char *);
161bfd67e9cSitohy while (*s && len > 1) {
162bfd67e9cSitohy #ifdef SJIS
163bfd67e9cSitohy if (IS_SJIS1(*s) && IS_SJIS2(s[1])) {
164bfd67e9cSitohy if (len <= 2)
165bfd67e9cSitohy goto break_loop;
166bfd67e9cSitohy *b++ = *s++;
167bfd67e9cSitohy len--;
168bfd67e9cSitohy }
169bfd67e9cSitohy #endif
170bfd67e9cSitohy if (*s == '\n' && (b == buf || b[-1] != '\r')) {
171bfd67e9cSitohy if (len <= 2)
172bfd67e9cSitohy goto break_loop;
173bfd67e9cSitohy *b++ = '\r';
174bfd67e9cSitohy len--;
175bfd67e9cSitohy }
176bfd67e9cSitohy *b++ = *s++;
177bfd67e9cSitohy len--;
178bfd67e9cSitohy }
179bfd67e9cSitohy break;
180bfd67e9cSitohy
181bfd67e9cSitohy case 'c':
182bfd67e9cSitohy *b++ = va_arg(ap, int);
183bfd67e9cSitohy len--;
184bfd67e9cSitohy break;
185bfd67e9cSitohy }
186bfd67e9cSitohy }
187bfd67e9cSitohy break_loop:
188bfd67e9cSitohy
189bfd67e9cSitohy *b = '\0';
190bfd67e9cSitohy return (char *)b - buf;
191bfd67e9cSitohy }
192bfd67e9cSitohy
193bfd67e9cSitohy #ifdef __STDC__
194bfd67e9cSitohy #define VA_START(a, v) va_start(a, v)
195bfd67e9cSitohy #else
196bfd67e9cSitohy #define VA_START(a, v) va_start(a)
197bfd67e9cSitohy #endif
198bfd67e9cSitohy
199bfd67e9cSitohy #ifdef __STDC__
200bfd67e9cSitohy size_t
xsnprintf(char * buf,size_t len,const char * fmt,...)201bfd67e9cSitohy xsnprintf(char *buf, size_t len, const char *fmt, ...)
202bfd67e9cSitohy #else
203bfd67e9cSitohy size_t
204bfd67e9cSitohy xsnprintf(buf, len, fmt, va_alist)
205bfd67e9cSitohy char *buf;
206bfd67e9cSitohy size_t len;
207bfd67e9cSitohy const char *fmt;
208bfd67e9cSitohy va_dcl
209bfd67e9cSitohy #endif
210bfd67e9cSitohy {
211bfd67e9cSitohy va_list ap;
212bfd67e9cSitohy size_t ret;
213bfd67e9cSitohy
214bfd67e9cSitohy VA_START(ap, fmt);
215bfd67e9cSitohy ret = xvsnprintf(buf, len, fmt, ap);
216bfd67e9cSitohy va_end(ap);
217bfd67e9cSitohy
218bfd67e9cSitohy return ret;
219bfd67e9cSitohy }
220bfd67e9cSitohy
221bfd67e9cSitohy size_t
xvfdprintf(int fd,const char * fmt,va_list ap)222454af1c0Sdsl xvfdprintf(int fd, const char *fmt, va_list ap)
223bfd67e9cSitohy {
224bfd67e9cSitohy char buf[PRINTF_BUFSZ];
225bfd67e9cSitohy size_t ret;
226bfd67e9cSitohy
227bfd67e9cSitohy ret = xvsnprintf(buf, sizeof buf, fmt, ap);
228bfd67e9cSitohy if (ret)
229bfd67e9cSitohy ret = DOS_WRITE(fd, buf, ret);
230bfd67e9cSitohy
231bfd67e9cSitohy return ret;
232bfd67e9cSitohy }
233bfd67e9cSitohy
234bfd67e9cSitohy #ifdef __STDC__
235bfd67e9cSitohy size_t
xprintf(const char * fmt,...)236bfd67e9cSitohy xprintf(const char *fmt, ...)
237bfd67e9cSitohy #else
238bfd67e9cSitohy size_t
239bfd67e9cSitohy xprintf(fmt, va_alist)
240bfd67e9cSitohy const char *fmt;
241bfd67e9cSitohy va_dcl
242bfd67e9cSitohy #endif
243bfd67e9cSitohy {
244bfd67e9cSitohy va_list ap;
245bfd67e9cSitohy size_t ret;
246bfd67e9cSitohy
247bfd67e9cSitohy VA_START(ap, fmt);
248bfd67e9cSitohy ret = xvfdprintf(1, fmt, ap);
249bfd67e9cSitohy va_end(ap);
250bfd67e9cSitohy
251bfd67e9cSitohy return ret;
252bfd67e9cSitohy }
253bfd67e9cSitohy
254bfd67e9cSitohy #ifdef __STDC__
255bfd67e9cSitohy size_t
xerrprintf(const char * fmt,...)256bfd67e9cSitohy xerrprintf(const char *fmt, ...)
257bfd67e9cSitohy #else
258bfd67e9cSitohy size_t
259bfd67e9cSitohy xerrprintf(fmt, va_alist)
260bfd67e9cSitohy const char *fmt;
261bfd67e9cSitohy va_dcl
262bfd67e9cSitohy #endif
263bfd67e9cSitohy {
264bfd67e9cSitohy va_list ap;
265bfd67e9cSitohy size_t ret;
266bfd67e9cSitohy
267bfd67e9cSitohy VA_START(ap, fmt);
268bfd67e9cSitohy ret = xvfdprintf(2, fmt, ap);
269bfd67e9cSitohy va_end(ap);
270bfd67e9cSitohy
271bfd67e9cSitohy return ret;
272bfd67e9cSitohy }
273bfd67e9cSitohy
274bfd67e9cSitohy __dead void
275bfd67e9cSitohy #ifdef __STDC__
xerr(int eval,const char * fmt,...)276bfd67e9cSitohy xerr(int eval, const char *fmt, ...)
277bfd67e9cSitohy #else
278bfd67e9cSitohy xerr(eval, fmt, va_alist)
279bfd67e9cSitohy int eval;
280bfd67e9cSitohy const char *fmt;
281bfd67e9cSitohy va_dcl
282bfd67e9cSitohy #endif
283bfd67e9cSitohy {
284bfd67e9cSitohy int e = dos_errno;
285bfd67e9cSitohy va_list ap;
286bfd67e9cSitohy
287bfd67e9cSitohy xerrprintf("%s: ", __progname);
288bfd67e9cSitohy if (fmt) {
289bfd67e9cSitohy VA_START(ap, fmt);
290bfd67e9cSitohy xvfdprintf(2, fmt, ap);
291bfd67e9cSitohy va_end(ap);
292bfd67e9cSitohy xerrprintf(": ");
293bfd67e9cSitohy }
294bfd67e9cSitohy xerrprintf("%s\n", dos_strerror(e));
295bfd67e9cSitohy DOS_EXIT2(eval);
296bfd67e9cSitohy }
297bfd67e9cSitohy
298bfd67e9cSitohy __dead void
299bfd67e9cSitohy #ifdef __STDC__
xerrx(int eval,const char * fmt,...)300bfd67e9cSitohy xerrx(int eval, const char *fmt, ...)
301bfd67e9cSitohy #else
302bfd67e9cSitohy xerrx(eval, fmt, va_alist)
303bfd67e9cSitohy int eval;
304bfd67e9cSitohy const char *fmt;
305bfd67e9cSitohy va_dcl
306bfd67e9cSitohy #endif
307bfd67e9cSitohy {
308bfd67e9cSitohy va_list ap;
309bfd67e9cSitohy
310bfd67e9cSitohy xerrprintf("%s: ", __progname);
311bfd67e9cSitohy if (fmt) {
312bfd67e9cSitohy VA_START(ap, fmt);
313bfd67e9cSitohy xvfdprintf(2, fmt, ap);
314bfd67e9cSitohy va_end(ap);
315bfd67e9cSitohy }
316bfd67e9cSitohy xerrprintf("\n");
317bfd67e9cSitohy DOS_EXIT2(eval);
318bfd67e9cSitohy }
319bfd67e9cSitohy
320bfd67e9cSitohy void
321bfd67e9cSitohy #ifdef __STDC__
xwarn(const char * fmt,...)322bfd67e9cSitohy xwarn(const char *fmt, ...)
323bfd67e9cSitohy #else
324bfd67e9cSitohy xwarn(fmt, va_alist)
325bfd67e9cSitohy const char *fmt;
326bfd67e9cSitohy va_dcl
327bfd67e9cSitohy #endif
328bfd67e9cSitohy {
329bfd67e9cSitohy int e = dos_errno;
330bfd67e9cSitohy va_list ap;
331bfd67e9cSitohy
332bfd67e9cSitohy xerrprintf("%s: ", __progname);
333bfd67e9cSitohy if (fmt) {
334bfd67e9cSitohy VA_START(ap, fmt);
335bfd67e9cSitohy xvfdprintf(2, fmt, ap);
336bfd67e9cSitohy va_end(ap);
337bfd67e9cSitohy xerrprintf(": ");
338bfd67e9cSitohy }
339bfd67e9cSitohy xerrprintf("%s\n", dos_strerror(e));
340bfd67e9cSitohy }
341bfd67e9cSitohy
342bfd67e9cSitohy void
343bfd67e9cSitohy #ifdef __STDC__
xwarnx(const char * fmt,...)344bfd67e9cSitohy xwarnx(const char *fmt, ...)
345bfd67e9cSitohy #else
346bfd67e9cSitohy xwarnx(fmt, va_alist)
347bfd67e9cSitohy const char *fmt;
348bfd67e9cSitohy va_dcl
349bfd67e9cSitohy #endif
350bfd67e9cSitohy {
351bfd67e9cSitohy va_list ap;
352bfd67e9cSitohy
353bfd67e9cSitohy xerrprintf("%s: ", __progname);
354bfd67e9cSitohy if (fmt) {
355bfd67e9cSitohy VA_START(ap, fmt);
356bfd67e9cSitohy xvfdprintf(2, fmt, ap);
357bfd67e9cSitohy va_end(ap);
358bfd67e9cSitohy }
359bfd67e9cSitohy xerrprintf("\n");
360bfd67e9cSitohy }
361