xref: /netbsd-src/sys/arch/x68k/stand/common/xprintf.c (revision ed461fc193a34ff07bc68b0c28567cb8cfe199e5)
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