VM: full munmap
[minix.git] / lib / libsys / vprintf.c
blobe66908966bd70bd448fa5573163f45845abb6742
2 #include <stdarg.h>
3 #include <stddef.h>
4 #include <ctype.h>
5 #include <limits.h>
6 #include <string.h>
8 /* vprintf() uses kputc() to print characters. */
9 void kputc(int c);
11 #ifdef __NBSD_LIBC
12 #define count_kputc(c) do { charcount++; putf((c), farg); } while(0)
14 int __fvprintf(void (*putf)(int, void *), const char *fmt, va_list argp, void *farg)
15 #else /* !NBSD_LIBC */
16 #define count_kputc(c) do { charcount++; kputc(c); } while(0)
18 int vprintf(const char *fmt, va_list argp)
19 #endif /* NBSD_LIBC */
21 int c, charcount = 0;
22 enum { LEFT, RIGHT } adjust;
23 enum { LLONG, LONG, INT } intsize;
24 int fill;
25 int width, max, len, base;
26 static char X2C_tab[]= "0123456789ABCDEF";
27 static char x2c_tab[]= "0123456789abcdef";
28 char *x2c;
29 char *p;
30 long long i;
31 unsigned long long u;
32 char temp[8 * sizeof(long long) / 3 + 2];
34 while ((c= *fmt++) != 0) {
35 if (c != '%') {
36 /* Ordinary character. */
37 count_kputc(c);
38 continue;
41 /* Format specifier of the form:
42 * %[adjust][fill][width][.max]keys
44 c= *fmt++;
46 adjust= RIGHT;
47 if (c == '-') {
48 adjust= LEFT;
49 c= *fmt++;
52 fill= ' ';
53 if (c == '0') {
54 fill= '0';
55 c= *fmt++;
58 width= 0;
59 if (c == '*') {
60 /* Width is specified as an argument, e.g. %*d. */
61 width= va_arg(argp, int);
62 c= *fmt++;
63 } else
64 if (isdigit(c)) {
65 /* A number tells the width, e.g. %10d. */
66 do {
67 width= width * 10 + (c - '0');
68 } while (isdigit(c= *fmt++));
71 max= INT_MAX;
72 if (c == '.') {
73 /* Max field length coming up. */
74 if ((c= *fmt++) == '*') {
75 max= va_arg(argp, int);
76 c= *fmt++;
77 } else
78 if (isdigit(c)) {
79 max= 0;
80 do {
81 max= max * 10 + (c - '0');
82 } while (isdigit(c= *fmt++));
86 /* Set a few flags to the default. */
87 x2c= x2c_tab;
88 i= 0;
89 base= 10;
90 intsize= INT;
91 if (c == 'l' || c == 'L') {
92 /* "Long" key, e.g. %ld. */
93 intsize= LONG;
94 c= *fmt++;
96 if (c == 'l' || c == 'L') {
97 /* "Long long" key, e.g. %lld. */
98 intsize= LLONG;
99 c= *fmt++;
101 if (c == 0) break;
103 switch (c) {
104 /* Decimal. */
105 case 'd':
106 switch (intsize) {
107 case LLONG: i= va_arg(argp, long long); break;
108 case LONG: i= va_arg(argp, long); break;
109 case INT: i= va_arg(argp, int); break;
111 u= i < 0 ? -i : i;
112 goto int2ascii;
114 /* Octal. */
115 case 'o':
116 base= 010;
117 goto getint;
119 /* Pointer, interpret as %X or %lX. */
120 case 'p':
121 if (sizeof(char *) > sizeof(long)) intsize= LLONG;
122 else if (sizeof(char *) > sizeof(int)) intsize= LONG;
124 /* Hexadecimal. %X prints upper case A-F, not %lx. */
125 case 'X':
126 x2c= X2C_tab;
127 case 'x':
128 base= 0x10;
129 goto getint;
131 /* Unsigned decimal. */
132 case 'u':
133 getint:
134 switch (intsize) {
135 case LLONG: u= va_arg(argp, unsigned long long); break;
136 case LONG: u= va_arg(argp, unsigned long); break;
137 case INT: u= va_arg(argp, unsigned int); break;
139 int2ascii:
140 p= temp + sizeof(temp)-1;
141 *p= 0;
142 do {
143 *--p= x2c[(ptrdiff_t) (u % base)];
144 } while ((u /= base) > 0);
145 goto string_length;
147 /* A character. */
148 case 'c':
149 p= temp;
150 *p= va_arg(argp, int);
151 len= 1;
152 goto string_print;
154 /* Simply a percent. */
155 case '%':
156 p= temp;
157 *p= '%';
158 len= 1;
159 goto string_print;
161 /* A string. The other cases will join in here. */
162 case 's':
163 p= va_arg(argp, char *);
164 if (!p) p = "(null)";
166 string_length:
167 for (len= 0; p[len] != 0 && len < max; len++) {}
169 string_print:
170 width -= len;
171 if (i < 0) width--;
172 if (fill == '0' && i < 0) count_kputc('-');
173 if (adjust == RIGHT) {
174 while (width > 0) { count_kputc(fill); width--; }
176 if (fill == ' ' && i < 0) count_kputc('-');
177 while (len > 0) { count_kputc((unsigned char) *p++); len--; }
178 while (width > 0) { count_kputc(fill); width--; }
179 break;
181 /* Unrecognized format key, echo it back. */
182 default:
183 count_kputc('%');
184 count_kputc(c);
188 /* Mark the end with a null (should be something else, like -1). */
189 #ifdef __NBDS_LIBC
190 putf(0, farg);
191 #else
192 kputc(0);
193 #endif
194 return charcount;
197 #ifdef __NBSD_LIBC
198 #include <sys/cdefs.h>
199 #include <assert.h>
200 #include <unistd.h>
201 #include <stdio.h>
203 __weak_alias(vprintf, _vprintf)
204 __weak_alias(vfprintf, _vfprintf)
205 __strong_alias(__vfprintf_unlocked, _vfprintf)
207 static void
208 __xfputc(int c, void *arg)
210 FILE *fp = (FILE *)arg;
211 if (fp->_flags & __SSTR) {
212 /* Write to a string. */
213 if (fp->_w == 0)
214 return;
215 memset(fp->_p++, c, 1);
216 fp->_w -= 1;
217 return;
220 /* Not a string. Print it. */
221 kputc(c);
224 int _vprintf(const char *fmt, va_list argp)
226 return __fvprintf(__xfputc, fmt, argp, stdout);
229 int _vfprintf(FILE *fp, const char *fmt, va_list argp)
231 return __fvprintf(__xfputc, fmt, argp, fp);
233 #endif
236 * $PchId: kprintf.c,v 1.5 1996/04/11 06:59:05 philip Exp $