Drop main() prototype. Syncs with NetBSD-8
[minix.git] / sys / lib / libsa / subr_prf.c
bloba6170fc911157536b16ade644b667ea5977c8ee7
1 /* $NetBSD: subr_prf.c,v 1.27 2014/08/30 14:24:02 tsutsui Exp $ */
3 /*-
4 * Copyright (c) 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
31 * @(#)printf.c 8.1 (Berkeley) 6/11/93
35 * Scaled down version of printf(3).
38 #include <sys/cdefs.h>
39 #include <sys/types.h>
40 #include <sys/stdint.h> /* XXX: for intptr_t */
42 #include "stand.h"
44 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
45 #define INTMAX_T longlong_t
46 #define UINTMAX_T u_longlong_t
47 #else
48 #define INTMAX_T long
49 #define UINTMAX_T u_long
50 #endif
52 #if 0 /* XXX: abuse intptr_t until the situation with ptrdiff_t is clear */
53 #define PTRDIFF_T ptrdiff_t
54 #else
55 #define PTRDIFF_T intptr_t
56 #endif
58 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
59 static void kprintn(void (*)(int), UINTMAX_T, int, int, int);
60 #else
61 static void kprintn(void (*)(int), UINTMAX_T, int);
62 #endif
63 static void sputchar(int);
64 static void kdoprnt(void (*)(int), const char *, va_list);
66 static char *sbuf, *ebuf;
67 #if defined(__minix)
68 /* vsnprintf: add support for returning the amount of characters that would have been
69 * written if the buffer was large enough */
70 static int scount;
71 #endif /* defined(__minix) */
73 const char hexdigits[16] = "0123456789abcdef";
75 #define LONG 0x01
76 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
77 #define LLONG 0x02
78 #endif
80 #if defined(__minix)
81 #define HEXCAP 0x100
82 #endif /* defined(__minix) */
84 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
85 #define ALT 0x04
86 #define SPACE 0x08
87 #define LADJUST 0x10
88 #define SIGN 0x20
89 #define ZEROPAD 0x40
90 #define NEGATIVE 0x80
91 #define KPRINTN(base) kprintn(put, ul, base, lflag, width)
92 #define RADJUSTZEROPAD() \
93 do { \
94 if ((lflag & (ZEROPAD|LADJUST)) == ZEROPAD) { \
95 while (width-- > 0) \
96 put('0'); \
97 } \
98 } while (/*CONSTCOND*/0)
99 #define LADJUSTPAD() \
100 do { \
101 if (lflag & LADJUST) { \
102 while (width-- > 0) \
103 put(' '); \
105 } while (/*CONSTCOND*/0)
106 #define RADJUSTPAD() \
107 do { \
108 if ((lflag & (ZEROPAD|LADJUST)) == 0) { \
109 while (width-- > 0) \
110 put(' '); \
112 } while (/*CONSTCOND*/0)
113 #else /* LIBSA_PRINTF_WIDTH_SUPPORT */
114 #define KPRINTN(base) kprintn(put, ul, base)
115 #define RADJUSTZEROPAD() /**/
116 #define LADJUSTPAD() /**/
117 #define RADJUSTPAD() /**/
118 #endif /* LIBSA_PRINTF_WIDTH_SUPPORT */
120 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
121 #define KPRINT(base) \
122 do { \
123 ul = (lflag & LLONG) \
124 ? va_arg(ap, u_longlong_t) \
125 : (lflag & LONG) \
126 ? va_arg(ap, u_long) \
127 : va_arg(ap, u_int); \
128 KPRINTN(base); \
129 } while (/*CONSTCOND*/0)
130 #else /* LIBSA_PRINTF_LONGLONG_SUPPORT */
131 #define KPRINT(base) \
132 do { \
133 ul = (lflag & LONG) \
134 ? va_arg(ap, u_long) : va_arg(ap, u_int); \
135 KPRINTN(base); \
136 } while (/*CONSTCOND*/0)
137 #endif /* LIBSA_PRINTF_LONGLONG_SUPPORT */
139 static void
140 sputchar(int c)
142 #if defined(__minix)
143 scount++; /* increase scount regardless */
144 if (!sbuf) return; /* hanlde NULL sbuf */
145 #endif /* defined(__minix) */
147 if (sbuf < ebuf)
148 *sbuf++ = c;
151 void
152 vprintf(const char *fmt, va_list ap)
155 kdoprnt(putchar, fmt, ap);
156 #if defined(__minix) && defined(LIBSA_PRINTF_WIDTH_SUPPORT)
157 /* BJG: our libminc kputc() relies on a 0 to flush the diag buffer. */
158 putchar(0);
159 #endif /* defined(__minix) && defined(LIBSA_PRINTF_WIDTH_SUPPORT) */
163 vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
166 sbuf = buf;
167 ebuf = buf + size - 1;
168 #if defined(__minix)
169 scount = 0; /* use scount to keep track of written items */
170 #endif /* defined(__minix) */
172 kdoprnt(sputchar, fmt, ap);
174 #if defined(__minix)
175 if (sbuf){ /* handle case where sbuf == NULL */
176 *sbuf = '\0';
178 #if defined(_MINIX_MAGIC)
179 sbuf = ebuf = NULL; /* leave no dangling pointers */
180 #endif
181 return scount;
182 #else /* __minix is not defined */
183 *sbuf = '\0';
184 return sbuf - buf;
185 #endif /* defined(__minix) */
188 static void
189 kdoprnt(void (*put)(int), const char *fmt, va_list ap)
191 char *p;
192 int ch;
193 UINTMAX_T ul;
194 int lflag;
195 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
196 int width;
197 char *q;
198 #if defined(__minix)
199 int max;
200 #endif /* defined(__minix) */
201 #endif
203 for (;;) {
204 while ((ch = *fmt++) != '%') {
205 if (ch == '\0')
206 return;
207 put(ch);
209 lflag = 0;
210 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
211 width = 0;
212 #if defined(__minix)
213 max = -1;
214 #endif /* defined(__minix) */
215 #endif
216 reswitch:
217 switch (ch = *fmt++) {
218 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
219 #if defined(__minix)
220 case '.':
221 if (*fmt == '*') {
222 max = va_arg(ap, int);
223 fmt++;
224 } else for (max = 0; *fmt >= '0' && *fmt <= '9'; fmt++)
225 max = max * 10 + *fmt - '0';
226 goto reswitch;
227 #endif /* defined(__minix) */
228 case '#':
229 lflag |= ALT;
230 goto reswitch;
231 case ' ':
232 lflag |= SPACE;
233 goto reswitch;
234 case '-':
235 lflag |= LADJUST;
236 goto reswitch;
237 case '+':
238 lflag |= SIGN;
239 goto reswitch;
240 case '0':
241 lflag |= ZEROPAD;
242 goto reswitch;
243 case '1': case '2': case '3': case '4': case '5':
244 case '6': case '7': case '8': case '9':
245 for (;;) {
246 width *= 10;
247 width += ch - '0';
248 ch = *fmt;
249 if ((unsigned)ch - '0' > 9)
250 break;
251 ++fmt;
253 #endif
254 goto reswitch;
255 case 'l':
256 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
257 if (*fmt == 'l') {
258 ++fmt;
259 lflag |= LLONG;
260 } else
261 #endif
262 lflag |= LONG;
263 goto reswitch;
264 case 'j':
265 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
266 if (sizeof(intmax_t) == sizeof(long long))
267 lflag |= LLONG;
268 else
269 #endif
270 if (sizeof(intmax_t) == sizeof(long))
271 lflag |= LONG;
272 goto reswitch;
273 case 't':
274 if (sizeof(PTRDIFF_T) == sizeof(long))
275 lflag |= LONG;
276 goto reswitch;
277 case 'z':
278 if (sizeof(ssize_t) == sizeof(long))
279 lflag |= LONG;
280 goto reswitch;
281 case 'c':
282 ch = va_arg(ap, int);
283 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
284 --width;
285 #endif
286 RADJUSTPAD();
287 put(ch & 0xFF);
288 LADJUSTPAD();
289 break;
290 case 's':
291 p = va_arg(ap, char *);
292 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
293 for (q = p; *q != '\0'; ++q)
294 continue;
295 #if defined(__minix)
296 if (max >= 0 && q - p > max)
297 q = &p[max];
298 #endif /* defined(__minix) */
299 width -= q - p;
300 #endif
301 RADJUSTPAD();
302 #if defined(LIBSA_PRINTF_WIDTH_SUPPORT) && defined(__minix)
303 while ((max < 0 || max-- > 0) &&
304 (ch = (unsigned char)*p++))
305 #else /* !defined(LIBSA_PRINTF_WIDTH_SUPPORT) || !defined(__minix) */
306 while ((ch = (unsigned char)*p++))
307 #endif /* !defined(LIBSA_PRINTF_WIDTH_SUPPORT) || !defined(__minix) */
308 put(ch);
309 LADJUSTPAD();
310 break;
311 case 'd':
312 ul =
313 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
314 (lflag & LLONG) ? va_arg(ap, longlong_t) :
315 #endif
316 (lflag & LONG) ? va_arg(ap, long) : va_arg(ap, int);
317 if ((INTMAX_T)ul < 0) {
318 ul = -(INTMAX_T)ul;
319 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
320 lflag |= NEGATIVE;
321 #else
322 put('-');
323 #endif
325 KPRINTN(10);
326 break;
327 case 'o':
328 KPRINT(8);
329 break;
330 case 'u':
331 KPRINT(10);
332 break;
333 case 'p':
334 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
335 lflag |= (LONG|ALT);
336 #else
337 put('0');
338 put('x');
339 #endif
340 /* FALLTHROUGH */
341 case 'x':
342 KPRINT(16);
343 break;
344 #if defined(__minix)
345 case 'X':
346 lflag |= HEXCAP;
347 KPRINT(16);
348 break;
349 #endif /* defined(__minix) */
350 default:
351 if (ch == '\0')
352 return;
353 put(ch);
354 break;
359 static void
360 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
361 kprintn(void (*put)(int), UINTMAX_T ul, int base, int lflag, int width)
362 #else
363 kprintn(void (*put)(int), UINTMAX_T ul, int base)
364 #endif
366 /* hold a INTMAX_T in base 8 */
367 char *p, buf[(sizeof(INTMAX_T) * NBBY / 3) + 1 + 2 /* ALT + SIGN */];
368 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
369 char *q;
370 #endif
372 p = buf;
373 do {
374 *p++ = hexdigits[ul % base];
375 #if defined(__minix)
376 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
377 /* LSC: Quick hack to support capital hex printout. */
378 if ((lflag & HEXCAP) && (*(p-1) >= 'a') && (*(p-1) <= 'z')) {
379 *(p-1) -= 32;
381 #endif
382 #endif /* defined(__minix) */
383 } while (ul /= base);
384 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
385 q = p;
386 if (lflag & ALT && *(p - 1) != '0') {
387 if (base == 8) {
388 *p++ = '0';
389 } else if (base == 16) {
390 *p++ = 'x';
391 *p++ = '0';
394 if (lflag & NEGATIVE)
395 *p++ = '-';
396 else if (lflag & SIGN)
397 *p++ = '+';
398 else if (lflag & SPACE)
399 *p++ = ' ';
400 width -= p - buf;
401 if (lflag & ZEROPAD) {
402 while (p > q)
403 put(*--p);
405 #endif
406 RADJUSTPAD();
407 RADJUSTZEROPAD();
408 do {
409 put(*--p);
410 } while (p > buf);
411 LADJUSTPAD();