mbr/Makefile: run checksize on the proper binaries...
[syslinux.git] / sample / printf.c
blob23aa1446d5fc05f79ccc728ef84569f55d6da60d
1 /*
2 * Oh, it's a waste of space, but oh-so-yummy for debugging. It's just
3 * initialization code anyway, so it doesn't take up space when we're
4 * actually running. This version of printf() does not include 64-bit
5 * support. "Live with it."
7 * Most of this code was shamelessly snarfed from the Linux kernel, then
8 * modified.
10 * FIX THIS: Replace printf() implementation with BSD/MIT-licensed one
11 * from klibc
14 #include <stdarg.h>
16 int puts(const char *);
18 static inline int
19 isdigit(int ch)
21 return (ch >= '0') && (ch <= '9');
24 unsigned int skip_atou(const char **s);
25 unsigned int atou(const char *s);
27 static int strnlen(const char *s, int maxlen)
29 const char *es = s;
30 while ( *es && maxlen ) {
31 es++; maxlen--;
34 return (es-s);
37 #define ZEROPAD 1 /* pad with zero */
38 #define SIGN 2 /* unsigned/signed long */
39 #define PLUS 4 /* show plus */
40 #define SPACE 8 /* space if plus */
41 #define LEFT 16 /* left justified */
42 #define SPECIAL 32 /* 0x */
43 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
45 #define do_div(n,base) ({ \
46 int __res; \
47 __res = ((unsigned long) n) % (unsigned) base; \
48 n = ((unsigned long) n) / (unsigned) base; \
49 __res; })
51 static char * number(char * str, long num, int base, int size, int precision
52 ,int type)
54 char c,sign,tmp[66];
55 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
56 int i;
58 if (type & LARGE)
59 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
60 if (type & LEFT)
61 type &= ~ZEROPAD;
62 if (base < 2 || base > 36)
63 return 0;
64 c = (type & ZEROPAD) ? '0' : ' ';
65 sign = 0;
66 if (type & SIGN) {
67 if (num < 0) {
68 sign = '-';
69 num = -num;
70 size--;
71 } else if (type & PLUS) {
72 sign = '+';
73 size--;
74 } else if (type & SPACE) {
75 sign = ' ';
76 size--;
79 if (type & SPECIAL) {
80 if (base == 16)
81 size -= 2;
82 else if (base == 8)
83 size--;
85 i = 0;
86 if (num == 0)
87 tmp[i++]='0';
88 else while (num != 0)
89 tmp[i++] = digits[do_div(num,base)];
90 if (i > precision)
91 precision = i;
92 size -= precision;
93 if (!(type&(ZEROPAD+LEFT)))
94 while(size-->0)
95 *str++ = ' ';
96 if (sign)
97 *str++ = sign;
98 if (type & SPECIAL) {
99 if (base==8)
100 *str++ = '0';
101 else if (base==16) {
102 *str++ = '0';
103 *str++ = digits[33];
106 if (!(type & LEFT))
107 while (size-- > 0)
108 *str++ = c;
109 while (i < precision--)
110 *str++ = '0';
111 while (i-- > 0)
112 *str++ = tmp[i];
113 while (size-- > 0)
114 *str++ = ' ';
115 return str;
118 /* Forward decl. needed for IP address printing stuff... */
119 int sprintf(char * buf, const char *fmt, ...);
121 int vsprintf(char *buf, const char *fmt, va_list args)
123 int len;
124 unsigned long num;
125 int i, base;
126 char * str;
127 const char *s;
129 int flags; /* flags to number() */
131 int field_width; /* width of output field */
132 int precision; /* min. # of digits for integers; max
133 number of chars for from string */
134 int qualifier; /* 'h', 'l', or 'L' for integer fields */
136 for (str=buf ; *fmt ; ++fmt) {
137 if (*fmt != '%') {
138 *str++ = *fmt;
139 continue;
142 /* process flags */
143 flags = 0;
144 repeat:
145 ++fmt; /* this also skips first '%' */
146 switch (*fmt) {
147 case '-': flags |= LEFT; goto repeat;
148 case '+': flags |= PLUS; goto repeat;
149 case ' ': flags |= SPACE; goto repeat;
150 case '#': flags |= SPECIAL; goto repeat;
151 case '0': flags |= ZEROPAD; goto repeat;
154 /* get field width */
155 field_width = -1;
156 if (isdigit(*fmt))
157 field_width = skip_atou(&fmt);
158 else if (*fmt == '*') {
159 ++fmt;
160 /* it's the next argument */
161 field_width = va_arg(args, int);
162 if (field_width < 0) {
163 field_width = -field_width;
164 flags |= LEFT;
168 /* get the precision */
169 precision = -1;
170 if (*fmt == '.') {
171 ++fmt;
172 if (isdigit(*fmt))
173 precision = skip_atou(&fmt);
174 else if (*fmt == '*') {
175 ++fmt;
176 /* it's the next argument */
177 precision = va_arg(args, int);
179 if (precision < 0)
180 precision = 0;
183 /* get the conversion qualifier */
184 qualifier = -1;
185 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
186 qualifier = *fmt;
187 ++fmt;
190 /* default base */
191 base = 10;
193 switch (*fmt) {
194 case 'c':
195 if (!(flags & LEFT))
196 while (--field_width > 0)
197 *str++ = ' ';
198 *str++ = (unsigned char) va_arg(args, int);
199 while (--field_width > 0)
200 *str++ = ' ';
201 continue;
203 case 's':
204 s = va_arg(args, char *);
205 len = strnlen(s, precision);
207 if (!(flags & LEFT))
208 while (len < field_width--)
209 *str++ = ' ';
210 for (i = 0; i < len; ++i)
211 *str++ = *s++;
212 while (len < field_width--)
213 *str++ = ' ';
214 continue;
216 case 'p':
217 if (field_width == -1) {
218 field_width = 2*sizeof(void *);
219 flags |= ZEROPAD;
221 str = number(str,
222 (unsigned long) va_arg(args, void *), 16,
223 field_width, precision, flags);
224 continue;
227 case 'n':
228 if (qualifier == 'l') {
229 long * ip = va_arg(args, long *);
230 *ip = (str - buf);
231 } else {
232 int * ip = va_arg(args, int *);
233 *ip = (str - buf);
235 continue;
237 case '%':
238 *str++ = '%';
239 continue;
241 /* integer number formats - set up the flags and "break" */
242 case 'o':
243 base = 8;
244 break;
246 case 'X':
247 flags |= LARGE;
248 case 'x':
249 base = 16;
250 break;
252 case 'd':
253 case 'i':
254 flags |= SIGN;
255 case 'u':
256 break;
258 default:
259 *str++ = '%';
260 if (*fmt)
261 *str++ = *fmt;
262 else
263 --fmt;
264 continue;
266 if (qualifier == 'l')
267 num = va_arg(args, unsigned long);
268 else if (qualifier == 'h') {
269 num = (unsigned short) va_arg(args, int);
270 if (flags & SIGN)
271 num = (short) num;
272 } else if (flags & SIGN)
273 num = va_arg(args, int);
274 else
275 num = va_arg(args, unsigned int);
276 str = number(str, num, base, field_width, precision, flags);
278 *str = '\0';
279 return str-buf;
282 int sprintf(char * buf, const char *fmt, ...)
284 va_list args;
285 int i;
287 va_start(args, fmt);
288 i=vsprintf(buf,fmt,args);
289 va_end(args);
290 return i;
293 int printf(const char *fmt, ...)
295 char printf_buf[1024];
296 va_list args;
297 int printed;
299 va_start(args, fmt);
300 printed = vsprintf(printf_buf, fmt, args);
301 va_end(args);
303 puts(printf_buf);
305 return printed;