1 // Stripped-down primitive printf-style formatting routines,
2 // used in common by printf, sprintf, fprintf, etc.
3 // This code is also used by both the kernel and user programs.
9 #include <ros/common.h>
16 * Print a number (base <= 16) in reverse order,
17 * using specified putch function and associated pointer putdat.
20 void printnum(void (*putch)(int, TV(t)), TV(t) putdat,
21 unsigned long long num, unsigned base, int width, int padc)
23 void printnum(void (*putch)(int, void**), void **putdat,
24 unsigned long long num, unsigned base, int width, int padc)
27 // first recursively print all preceding (more significant) digits
29 printnum(putch, putdat, num / base, base, width - 1, padc);
31 // print any needed pad characters before first digit
36 // then print this (the least significant) digit
37 putch("0123456789abcdef"[num % base], putdat);
40 // Get an unsigned int of various possible sizes from a varargs list,
41 // depending on the lflag parameter.
42 static unsigned long long getuint(va_list *ap, int lflag)
45 return va_arg(*ap, unsigned long long);
47 return va_arg(*ap, unsigned long);
49 return va_arg(*ap, unsigned int);
52 // Same as getuint but signed - can't use getuint
53 // because of sign extension
54 static long long getint(va_list *ap, int lflag)
57 return va_arg(*ap, long long);
59 return va_arg(*ap, long);
61 return va_arg(*ap, int);
65 // Main function to format and print a string.
67 void printfmt(void (*putch)(int, TV(t)), TV(t) putdat, const char *fmt, ...);
69 void printfmt(void (*putch)(int, void**), void **putdat, const char *fmt, ...);
73 void vprintfmt(void (*putch)(int, TV(t)), TV(t) putdat, const char *fmt, va_list ap)
75 void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap)
78 register const char *NTS p;
79 const char *NTS last_fmt;
81 unsigned long long num;
82 int base, lflag, width, precision, altflag;
86 while ((ch = *(unsigned char *) fmt) != '%') {
94 // Process a %-escape sequence
102 switch (ch = *(unsigned char *) fmt++) {
104 // flag to pad on the right
109 // flag to pad with 0's instead of spaces
124 for (precision = 0; ; ++fmt) {
125 precision = precision * 10 + ch - '0';
127 if (ch < '0' || ch > '9')
130 goto process_precision;
133 precision = va_arg(ap, int);
134 goto process_precision;
147 width = precision, precision = -1;
150 // long flag (doubled for long long)
157 putch(va_arg(ap, int), putdat);
162 err = va_arg(ap, int);
165 if (err >= NUMERRORS)
166 printfmt(putch, putdat, "error %d", err);
168 printfmt(putch, putdat, "%s", error_string[err]);
173 if ((p = va_arg(ap, char *)) == NULL)
175 if (width > 0 && padc != '-')
176 for (width -= strnlen(p, precision); width > 0; width--)
178 for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) {
179 if (altflag && (ch < ' ' || ch > '~'))
183 // zra: make sure *p isn't '\0' before inc'ing
186 for (; width > 0; width--)
192 num = getint(&ap, lflag);
193 if ((long long) num < 0) {
195 num = -(long long) num;
202 num = getuint(&ap, lflag);
208 // should do something with padding so it's always 3 octits
209 num = getuint(&ap, lflag);
217 num = (unsigned long long)
218 (uintptr_t) va_arg(ap, void *);
222 // (unsigned) hexadecimal
224 num = getuint(&ap, lflag);
227 printnum(putch, putdat, num, base, width, padc);
230 // escaped '%' character
235 // unrecognized escape sequence - just print it literally
239 //for (fmt--; fmt[-1] != '%'; fmt--)
247 void printfmt(void (*putch)(int, TV(t)), TV(t) putdat, const char *fmt, ...)
249 void printfmt(void (*putch)(int, void**), void **putdat, const char *fmt, ...)
255 vprintfmt(putch, putdat, fmt, ap);
259 typedef struct sprintbuf {
260 char *BND(__this,ebuf) buf;
265 static void sprintputch(int ch, sprintbuf_t *NONNULL *NONNULL b)
268 if ((*b)->buf < (*b)->ebuf)
272 int vsnprintf(char *buf, int n, const char *fmt, va_list ap)
274 sprintbuf_t b;// = {buf, buf+n-1, 0};
275 sprintbuf_t *COUNT(1) NONNULL bp = &b;
277 if (buf == NULL || n < 1)
280 b.buf = NULL; // zra : help out the Deputy optimizer a bit
285 // print the string to the buffer
287 vprintfmt((void*)sprintputch, (sprintbuf_t *NONNULL*NONNULL)&bp, fmt, ap);
289 vprintfmt((void*)sprintputch, (void*)&bp, fmt, ap);
292 // null terminate the buffer
298 int snprintf(char *buf, int n, const char *fmt, ...)
304 rc = vsnprintf(buf, n, fmt, ap);