vfs/mount/rs/service changes:
[minix3.git] / lib / sysutil / kprintf.c
blob5d8e2196cdf4be0b41e8649682982c296b57d8b9
1 /* printf() - system services printf() Author: Kees J. Bot
2 * 15 Jan 1994
3 */
4 #define nil 0
5 #include <stdarg.h>
6 #include <stddef.h>
7 #include <limits.h>
9 #define isdigit(c) ((unsigned) ((c) - '0') < (unsigned) 10)
11 #if !__STDC__
12 /* Classic C stuff, ignore. */
13 void kputc();
14 int printf(fmt) char *fmt;
15 #else
17 /* Printf() uses kputc() to print characters. */
18 void kputc(int c);
20 #define count_kputc(c) do { charcount++; kputc(c); } while(0)
22 int printf(const char *fmt, ...)
23 #endif
25 int c, charcount = 0;
26 enum { LEFT, RIGHT } adjust;
27 enum { LONG, INT } intsize;
28 int fill;
29 int width, max, len, base;
30 static char X2C_tab[]= "0123456789ABCDEF";
31 static char x2c_tab[]= "0123456789abcdef";
32 char *x2c;
33 char *p;
34 long i;
35 unsigned long u;
36 char temp[8 * sizeof(long) / 3 + 2];
38 va_list argp;
40 va_start(argp, fmt);
42 while ((c= *fmt++) != 0) {
43 if (c != '%') {
44 /* Ordinary character. */
45 count_kputc(c);
46 continue;
49 /* Format specifier of the form:
50 * %[adjust][fill][width][.max]keys
52 c= *fmt++;
54 adjust= RIGHT;
55 if (c == '-') {
56 adjust= LEFT;
57 c= *fmt++;
60 fill= ' ';
61 if (c == '0') {
62 fill= '0';
63 c= *fmt++;
66 width= 0;
67 if (c == '*') {
68 /* Width is specified as an argument, e.g. %*d. */
69 width= va_arg(argp, int);
70 c= *fmt++;
71 } else
72 if (isdigit(c)) {
73 /* A number tells the width, e.g. %10d. */
74 do {
75 width= width * 10 + (c - '0');
76 } while (isdigit(c= *fmt++));
79 max= INT_MAX;
80 if (c == '.') {
81 /* Max field length coming up. */
82 if ((c= *fmt++) == '*') {
83 max= va_arg(argp, int);
84 c= *fmt++;
85 } else
86 if (isdigit(c)) {
87 max= 0;
88 do {
89 max= max * 10 + (c - '0');
90 } while (isdigit(c= *fmt++));
94 /* Set a few flags to the default. */
95 x2c= x2c_tab;
96 i= 0;
97 base= 10;
98 intsize= INT;
99 if (c == 'l' || c == 'L') {
100 /* "Long" key, e.g. %ld. */
101 intsize= LONG;
102 c= *fmt++;
104 if (c == 0) break;
106 switch (c) {
107 /* Decimal. */
108 case 'd':
109 i= intsize == LONG ? va_arg(argp, long)
110 : va_arg(argp, int);
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(int)) intsize= LONG;
123 /* Hexadecimal. %X prints upper case A-F, not %lx. */
124 case 'X':
125 x2c= X2C_tab;
126 case 'x':
127 base= 0x10;
128 goto getint;
130 /* Unsigned decimal. */
131 case 'u':
132 getint:
133 u= intsize == LONG ? va_arg(argp, unsigned long)
134 : va_arg(argp, unsigned int);
135 int2ascii:
136 p= temp + sizeof(temp)-1;
137 *p= 0;
138 do {
139 *--p= x2c[(ptrdiff_t) (u % base)];
140 } while ((u /= base) > 0);
141 goto string_length;
143 /* A character. */
144 case 'c':
145 p= temp;
146 *p= va_arg(argp, int);
147 len= 1;
148 goto string_print;
150 /* Simply a percent. */
151 case '%':
152 p= temp;
153 *p= '%';
154 len= 1;
155 goto string_print;
157 /* A string. The other cases will join in here. */
158 case 's':
159 p= va_arg(argp, char *);
161 string_length:
162 for (len= 0; p[len] != 0 && len < max; len++) {}
164 string_print:
165 width -= len;
166 if (i < 0) width--;
167 if (fill == '0' && i < 0) count_kputc('-');
168 if (adjust == RIGHT) {
169 while (width > 0) { count_kputc(fill); width--; }
171 if (fill == ' ' && i < 0) count_kputc('-');
172 while (len > 0) { count_kputc((unsigned char) *p++); len--; }
173 while (width > 0) { count_kputc(fill); width--; }
174 break;
176 /* Unrecognized format key, echo it back. */
177 default:
178 count_kputc('%');
179 count_kputc(c);
183 /* Mark the end with a null (should be something else, like -1). */
184 kputc(0);
185 va_end(argp);
186 return charcount;
190 * $PchId: kprintf.c,v 1.5 1996/04/11 06:59:05 philip Exp $