Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / x68k / stand / common / xprintf.c
blob3222817463b3715b860dd8ea0f6feb587d78cd6d
1 /*
2 * minimal printf for Human68k DOS
4 * written by Yasha (ITOH Yasufumi)
5 * public domain
7 * $NetBSD: xprintf.c,v 1.3 2009/03/14 15:36:15 dsl Exp $
8 */
10 #include <sys/types.h>
11 #ifdef __STDC__
12 # include <stdarg.h>
13 #else
14 # include <varargs.h>
15 #endif
17 #include <dos.h>
18 #include <dos_errno.h>
20 #include "xprintf.h"
23 * From ISO/IEC 9899:1990
24 * 7.9.6.1 The fprintf function
25 * ...
26 * Environment limit
27 * The minimum value for the maximum number of characters
28 * produced by any single conversion shall be 509.
30 * so the following value shall not be smaller than 510
31 * if you want to conform ANSI C (it is only a guideline
32 * and maybe no sense on this code, of course :-).
34 #define PRINTF_BUFSZ 4096
37 * Shift-JIS kanji support
38 * (No special handling needed for EUC)
40 #define SJIS
42 #ifdef SJIS
43 #define UC(c) ((unsigned char) (c))
44 #define IS_SJIS1(c) ((UC(c) > 0x80 && UC(c) < 0xa0) || \
45 (UC(c) >= 0xe0 && UC(c) <= 0xfc))
46 #define IS_SJIS2(c) (UC(c) >= 0x40 && UC(c) <= 0xfc && UC(c) != 0x7f)
47 #endif
49 #if !defined(__STDC__) && !defined(const)
50 #define const
51 #endif
53 extern const char *const __progname;
55 static char * numstr(char *buf, long val, int base, int sign);
58 * convert number to string
59 * buf must have enough space
61 static char *
62 numstr(char *buf, long val, int base, int sign)
64 unsigned long v;
65 char rev[32];
66 char *r = rev, *b = buf;
68 /* negative? */
69 if (sign && val < 0) {
70 v = -val;
71 *b++ = '-';
72 } else {
73 v = val;
76 /* inverse order */
77 do {
78 *r++ = "0123456789abcdef"[v % base];
79 v /= base;
80 } while (v);
82 /* reverse string */
83 while (r > rev)
84 *b++ = *--r;
86 *b = '\0';
87 return buf;
91 * supported format: %x, %p, %s, %c, %d, %u, %o
92 * \n is converted to \r\n
94 * XXX argument/parameter types are not strictly handled
96 size_t
97 xvsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
99 char *b = buf;
100 const char *s;
101 char numbuf[32];
103 while (*fmt && len > 1) {
104 if (*fmt != '%') {
105 #ifdef SJIS
106 if (IS_SJIS1(*fmt) && IS_SJIS2(fmt[1])) {
107 if (len <= 2)
108 break; /* not enough space */
109 *b++ = *fmt++;
110 len--;
112 #endif
113 if (*fmt == '\n' && (b == buf || b[-1] != '\r')) {
114 if (len <= 2)
115 break;
116 *b++ = '\r';
117 len--;
119 *b++ = *fmt++;
120 len--;
121 continue;
124 /* %? */
125 fmt++;
126 switch (*fmt++) {
127 case '%': /* "%%" -> literal % */
128 *b++ = '%';
129 len--;
130 break;
132 case 'd':
133 s = numstr(numbuf, va_arg(ap, long), 10, 1);
134 copy_string:
135 for ( ; *s && len > 1; len--)
136 *b++ = *s++;
137 break;
139 case 'u':
140 s = numstr(numbuf, va_arg(ap, long), 10, 0);
141 goto copy_string;
143 case 'p':
144 *b++ = '0';
145 len--;
146 if (len > 1) {
147 *b++ = 'x';
148 len--;
150 /* FALLTHROUGH */
151 case 'x':
152 s = numstr(numbuf, va_arg(ap, long), 16, 0);
153 goto copy_string;
155 case 'o':
156 s = numstr(numbuf, va_arg(ap, long), 8, 0);
157 goto copy_string;
159 case 's':
160 s = va_arg(ap, char *);
161 while (*s && len > 1) {
162 #ifdef SJIS
163 if (IS_SJIS1(*s) && IS_SJIS2(s[1])) {
164 if (len <= 2)
165 goto break_loop;
166 *b++ = *s++;
167 len--;
169 #endif
170 if (*s == '\n' && (b == buf || b[-1] != '\r')) {
171 if (len <= 2)
172 goto break_loop;
173 *b++ = '\r';
174 len--;
176 *b++ = *s++;
177 len--;
179 break;
181 case 'c':
182 *b++ = va_arg(ap, int);
183 len--;
184 break;
187 break_loop:
189 *b = '\0';
190 return (char *)b - buf;
193 #ifdef __STDC__
194 #define VA_START(a, v) va_start(a, v)
195 #else
196 #define VA_START(a, v) va_start(a)
197 #endif
199 #ifdef __STDC__
200 size_t
201 xsnprintf(char *buf, size_t len, const char *fmt, ...)
202 #else
203 size_t
204 xsnprintf(buf, len, fmt, va_alist)
205 char *buf;
206 size_t len;
207 const char *fmt;
208 va_dcl
209 #endif
211 va_list ap;
212 size_t ret;
214 VA_START(ap, fmt);
215 ret = xvsnprintf(buf, len, fmt, ap);
216 va_end(ap);
218 return ret;
221 size_t
222 xvfdprintf(int fd, const char *fmt, va_list ap)
224 char buf[PRINTF_BUFSZ];
225 size_t ret;
227 ret = xvsnprintf(buf, sizeof buf, fmt, ap);
228 if (ret)
229 ret = DOS_WRITE(fd, buf, ret);
231 return ret;
234 #ifdef __STDC__
235 size_t
236 xprintf(const char *fmt, ...)
237 #else
238 size_t
239 xprintf(fmt, va_alist)
240 const char *fmt;
241 va_dcl
242 #endif
244 va_list ap;
245 size_t ret;
247 VA_START(ap, fmt);
248 ret = xvfdprintf(1, fmt, ap);
249 va_end(ap);
251 return ret;
254 #ifdef __STDC__
255 size_t
256 xerrprintf(const char *fmt, ...)
257 #else
258 size_t
259 xerrprintf(fmt, va_alist)
260 const char *fmt;
261 va_dcl
262 #endif
264 va_list ap;
265 size_t ret;
267 VA_START(ap, fmt);
268 ret = xvfdprintf(2, fmt, ap);
269 va_end(ap);
271 return ret;
274 __dead void
275 #ifdef __STDC__
276 xerr(int eval, const char *fmt, ...)
277 #else
278 xerr(eval, fmt, va_alist)
279 int eval;
280 const char *fmt;
281 va_dcl
282 #endif
284 int e = dos_errno;
285 va_list ap;
287 xerrprintf("%s: ", __progname);
288 if (fmt) {
289 VA_START(ap, fmt);
290 xvfdprintf(2, fmt, ap);
291 va_end(ap);
292 xerrprintf(": ");
294 xerrprintf("%s\n", dos_strerror(e));
295 DOS_EXIT2(eval);
298 __dead void
299 #ifdef __STDC__
300 xerrx(int eval, const char *fmt, ...)
301 #else
302 xerrx(eval, fmt, va_alist)
303 int eval;
304 const char *fmt;
305 va_dcl
306 #endif
308 va_list ap;
310 xerrprintf("%s: ", __progname);
311 if (fmt) {
312 VA_START(ap, fmt);
313 xvfdprintf(2, fmt, ap);
314 va_end(ap);
316 xerrprintf("\n");
317 DOS_EXIT2(eval);
320 void
321 #ifdef __STDC__
322 xwarn(const char *fmt, ...)
323 #else
324 xwarn(fmt, va_alist)
325 const char *fmt;
326 va_dcl
327 #endif
329 int e = dos_errno;
330 va_list ap;
332 xerrprintf("%s: ", __progname);
333 if (fmt) {
334 VA_START(ap, fmt);
335 xvfdprintf(2, fmt, ap);
336 va_end(ap);
337 xerrprintf(": ");
339 xerrprintf("%s\n", dos_strerror(e));
342 void
343 #ifdef __STDC__
344 xwarnx(const char *fmt, ...)
345 #else
346 xwarnx(fmt, va_alist)
347 const char *fmt;
348 va_dcl
349 #endif
351 va_list ap;
353 xerrprintf("%s: ", __progname);
354 if (fmt) {
355 VA_START(ap, fmt);
356 xvfdprintf(2, fmt, ap);
357 va_end(ap);
359 xerrprintf("\n");