custom message type for VM_INFO
[minix3.git] / sys / lib / libsa / subr_prf.c
blob93f101728985d7a49123693e76c5761f022ec2dc
1 /* $NetBSD: subr_prf.c,v 1.21 2011/07/17 20:54:52 joerg 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 RZERO() \
93 do { \
94 if ((lflag & (ZEROPAD|LADJUST)) == ZEROPAD) { \
95 while (width-- > 0) \
96 put('0'); \
97 } \
98 } while (/*CONSTCOND*/0)
99 #define RPAD() \
100 do { \
101 if (lflag & LADJUST) { \
102 while (width-- > 0) \
103 put(' '); \
105 } while (/*CONSTCOND*/0)
106 #define LPAD() \
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 RZERO() /**/
116 #define RPAD() /**/
117 #define LPAD() /**/
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) */
146 if (sbuf < ebuf)
147 *sbuf++ = c;
150 void
151 vprintf(const char *fmt, va_list ap)
154 kdoprnt(putchar, fmt, ap);
155 #if defined(__minix) && defined(LIBSA_PRINTF_WIDTH_SUPPORT)
156 /* BJG: our libminc kputc() relies on a 0 to flush the diag buffer. */
157 putchar(0);
158 #endif /* defined(__minix) && defined(LIBSA_PRINTF_WIDTH_SUPPORT) */
162 vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
165 sbuf = buf;
166 ebuf = buf + size - 1;
167 #if defined(__minix)
168 scount = 0; /* use scount to keep track of written items */
169 #endif /* defined(__minix) */
171 kdoprnt(sputchar, fmt, ap);
173 #if defined(__minix)
174 if (sbuf){ /* handle case where sbuf == NULL */
175 *sbuf = '\0';
177 return scount;
178 #else /* __minix is not defined */
179 *sbuf = '\0';
180 return sbuf - buf;
181 #endif /* defined(__minix) */
184 static void
185 kdoprnt(void (*put)(int), const char *fmt, va_list ap)
187 char *p;
188 int ch;
189 UINTMAX_T ul;
190 int lflag;
191 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
192 int width;
193 char *q;
194 #endif
196 for (;;) {
197 while ((ch = *fmt++) != '%') {
198 if (ch == '\0')
199 return;
200 put(ch);
202 lflag = 0;
203 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
204 width = 0;
205 #endif
206 reswitch:
207 switch (ch = *fmt++) {
208 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
209 #if defined(__minix)
210 /* LSC: FIXME: this is a simple hack which ignores the thing for now. */
211 case '.':
212 /* eat up digits */
213 while( ((('1' >= *fmt) && ( *fmt <= '9'))
214 || (*fmt == '*')) )
215 fmt++;
216 fmt++;
217 goto reswitch;
218 #endif /* defined(__minix) */
219 case '#':
220 lflag |= ALT;
221 goto reswitch;
222 case ' ':
223 lflag |= SPACE;
224 goto reswitch;
225 case '-':
226 lflag |= LADJUST;
227 goto reswitch;
228 case '+':
229 lflag |= SIGN;
230 goto reswitch;
231 case '0':
232 lflag |= ZEROPAD;
233 goto reswitch;
234 case '1': case '2': case '3': case '4': case '5':
235 case '6': case '7': case '8': case '9':
236 for (;;) {
237 width *= 10;
238 width += ch - '0';
239 ch = *fmt;
240 if ((unsigned)ch - '0' > 9)
241 break;
242 ++fmt;
244 #endif
245 goto reswitch;
246 case 'l':
247 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
248 if (*fmt == 'l') {
249 ++fmt;
250 lflag |= LLONG;
251 } else
252 #endif
253 lflag |= LONG;
254 goto reswitch;
255 case 't':
256 if (sizeof(PTRDIFF_T) == sizeof(long))
257 lflag |= LONG;
258 goto reswitch;
259 case 'z':
260 if (sizeof(ssize_t) == sizeof(long))
261 lflag |= LONG;
262 goto reswitch;
263 case 'c':
264 ch = va_arg(ap, int);
265 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
266 --width;
267 #endif
268 RPAD();
269 put(ch & 0xFF);
270 LPAD();
271 break;
272 case 's':
273 p = va_arg(ap, char *);
274 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
275 for (q = p; *q != '\0'; ++q)
276 continue;
277 width -= q - p;
278 #endif
279 RPAD();
280 while ((ch = (unsigned char)*p++))
281 put(ch);
282 LPAD();
283 break;
284 case 'd':
285 ul =
286 #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
287 (lflag & LLONG) ? va_arg(ap, longlong_t) :
288 #endif
289 (lflag & LONG) ? va_arg(ap, long) : va_arg(ap, int);
290 if ((INTMAX_T)ul < 0) {
291 ul = -(INTMAX_T)ul;
292 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
293 lflag |= NEGATIVE;
294 #else
295 put('-');
296 #endif
298 KPRINTN(10);
299 break;
300 case 'o':
301 KPRINT(8);
302 break;
303 case 'u':
304 KPRINT(10);
305 break;
306 case 'p':
307 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
308 lflag |= (LONG|ALT);
309 #else
310 put('0');
311 put('x');
312 #endif
313 /* FALLTHROUGH */
314 case 'x':
315 KPRINT(16);
316 break;
317 #if defined(__minix)
318 case 'X':
319 lflag |= HEXCAP;
320 KPRINT(16);
321 break;
322 #endif /* defined(__minix) */
323 default:
324 if (ch == '\0')
325 return;
326 put(ch);
327 break;
332 static void
333 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
334 kprintn(void (*put)(int), UINTMAX_T ul, int base, int lflag, int width)
335 #else
336 kprintn(void (*put)(int), UINTMAX_T ul, int base)
337 #endif
339 /* hold a INTMAX_T in base 8 */
340 char *p, buf[(sizeof(INTMAX_T) * NBBY / 3) + 1 + 2 /* ALT + SIGN */];
341 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
342 char *q;
343 #endif
345 p = buf;
346 do {
347 *p++ = hexdigits[ul % base];
348 #if defined(__minix)
349 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
350 /* LSC: Quick hack to support capital hex printout. */
351 if ((lflag & HEXCAP) && (*(p-1) >= 'a') && (*(p-1) <= 'z')) {
352 *(p-1) -= 32;
354 #endif
355 #endif /* defined(__minix) */
356 } while (ul /= base);
357 #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
358 q = p;
359 if (lflag & ALT && *(p - 1) != '0') {
360 if (base == 8) {
361 *p++ = '0';
362 } else if (base == 16) {
363 *p++ = 'x';
364 *p++ = '0';
367 if (lflag & NEGATIVE)
368 *p++ = '-';
369 else if (lflag & SIGN)
370 *p++ = '+';
371 else if (lflag & SPACE)
372 *p++ = ' ';
373 width -= p - buf;
374 if ((lflag & LADJUST) == 0) {
375 while (p > q)
376 put(*--p);
378 #endif
379 RPAD();
380 RZERO();
381 do {
382 put(*--p);
383 } while (p > buf);
384 LPAD();