8 /* Auxiliary data for vsnprintf_helper(). */
11 char *p; /* Current output position. */
12 int length; /* Length of output string. */
13 int max_length; /* Max length of output string. */
16 static void vsnprintf_helper (char, void *);
18 /* Like vprintf(), except that output is stored into BUFFER,
19 which must have space for BUF_SIZE characters. Writes at most
20 BUF_SIZE - 1 characters to BUFFER, followed by a null
21 terminator. BUFFER will always be null-terminated unless
22 BUF_SIZE is zero. Returns the number of characters that would
23 have been written to BUFFER, not including a null terminator,
24 had there been enough room. */
26 vsnprintf (char *buffer, size_t buf_size, const char *format, va_list args)
28 /* Set up aux data for vsnprintf_helper(). */
29 struct vsnprintf_aux aux;
32 aux.max_length = buf_size > 0 ? buf_size - 1 : 0;
34 /* Do most of the work. */
35 __vprintf (format, args, vsnprintf_helper, &aux);
37 /* Add null terminator. */
44 /* Helper function for vsnprintf(). */
46 vsnprintf_helper (char ch, void *aux_)
48 struct vsnprintf_aux *aux = aux_;
50 if (aux->length++ < aux->max_length)
54 /* Like printf(), except that output is stored into BUFFER,
55 which must have space for BUF_SIZE characters. Writes at most
56 BUF_SIZE - 1 characters to BUFFER, followed by a null
57 terminator. BUFFER will always be null-terminated unless
58 BUF_SIZE is zero. Returns the number of characters that would
59 have been written to BUFFER, not including a null terminator,
60 had there been enough room. */
62 snprintf (char *buffer, size_t buf_size, const char *format, ...)
67 va_start (args, format);
68 retval = vsnprintf (buffer, buf_size, format, args);
74 /* Writes formatted output to the console.
75 In the kernel, the console is both the video display and first
77 In userspace, the console is file descriptor 1.
80 printf (const char *format, ...)
85 va_start (args, format);
86 retval = vprintf (format, args);
92 /* printf() formatting internals. */
94 /* A printf() conversion. */
95 struct printf_conversion
100 MINUS = 1 << 0, /* '-' */
101 PLUS = 1 << 1, /* '+' */
102 SPACE = 1 << 2, /* ' ' */
103 POUND = 1 << 3, /* '#' */
104 ZERO = 1 << 4, /* '0' */
105 GROUP = 1 << 5 /* '\'' */
109 /* Minimum field width. */
112 /* Numeric precision.
113 -1 indicates no precision was specified. */
116 /* Type of argument to format. */
121 INT = 3, /* (none) */
124 LONGLONG = 6, /* ll */
125 PTRDIFFT = 7, /* t */
133 int base; /* Base. */
134 const char *digits; /* Collection of digits. */
135 const char *signifier; /* Prefix used with # flag. */
136 int group; /* Number of digits to group with ' flag. */
139 static const struct integer_base base_d = {10, "0123456789", "", 3};
140 static const struct integer_base base_o = {8, "01234567", "0", 3};
141 static const struct integer_base base_x = {16, "0123456789abcdef", "0x", 4};
142 static const struct integer_base base_X = {16, "0123456789ABCDEF", "0X", 4};
144 static const char *parse_conversion (const char *format,
145 struct printf_conversion *,
147 static void format_integer (uintmax_t value, bool negative,
148 const struct integer_base *,
149 const struct printf_conversion *,
150 void (*output) (char, void *), void *aux);
151 static void output_dup (char ch, size_t cnt,
152 void (*output) (char, void *), void *aux);
153 static void format_string (const char *string, size_t length,
154 struct printf_conversion *,
155 void (*output) (char, void *), void *aux);
158 __vprintf (const char *format, va_list args,
159 void (*output) (char, void *), void *aux)
161 for (; *format != '\0'; format++)
163 struct printf_conversion c;
165 /* Literally copy non-conversions to output. */
168 output (*format, aux);
180 /* Parse conversion specifiers. */
181 format = parse_conversion (format, &c, &args);
189 /* Signed integer conversions. */
195 value = (signed char) va_arg (args, int);
198 value = (short) va_arg (args, int);
201 value = va_arg (args, int);
204 value = va_arg (args, intmax_t);
207 value = va_arg (args, long);
210 value = va_arg (args, long long);
213 value = va_arg (args, ptrdiff_t);
216 value = va_arg (args, size_t);
222 format_integer (value < 0 ? -value : value,
223 value < 0, &base_d, &c, output, aux);
232 /* Unsigned integer conversions. */
234 const struct integer_base *b;
239 value = (unsigned char) va_arg (args, unsigned);
242 value = (unsigned short) va_arg (args, unsigned);
245 value = va_arg (args, unsigned);
248 value = va_arg (args, uintmax_t);
251 value = va_arg (args, unsigned long);
254 value = va_arg (args, unsigned long long);
257 value = va_arg (args, ptrdiff_t);
260 value = va_arg (args, size_t);
268 case 'o': b = &base_o; break;
269 case 'u': b = &base_d; break;
270 case 'x': b = &base_x; break;
271 case 'X': b = &base_X; break;
272 default: NOT_REACHED ();
275 format_integer (value, false, b, &c, output, aux);
281 /* Treat character as single-character string. */
282 char ch = va_arg (args, int);
283 format_string (&ch, 1, &c, output, aux);
289 /* String conversion. */
290 const char *s = va_arg (args, char *);
294 /* Limit string length according to precision.
295 Note: if c.precision == -1 then strnlen() will get
296 SIZE_MAX for MAXLEN, which is just what we want. */
297 format_string (s, strnlen (s, c.precision), &c, output, aux);
303 /* Pointer conversion.
304 Format pointers as %#x. */
305 void *p = va_arg (args, void *);
308 format_integer ((uintptr_t) p, false, &base_x, &c, output, aux);
318 /* We don't support floating-point arithmetic,
319 and %n can be part of a security hole. */
320 __printf ("<<no %%%c in kernel>>", output, aux, *format);
324 __printf ("<<no %%%c conversion>>", output, aux, *format);
330 /* Parses conversion option characters starting at FORMAT and
331 initializes C appropriately. Returns the character in FORMAT
332 that indicates the conversion (e.g. the `d' in `%d'). Uses
333 *ARGS for `*' field widths and precisions. */
335 parse_conversion (const char *format, struct printf_conversion *c,
338 /* Parse flag characters. */
368 if (c->flags & MINUS)
373 /* Parse field width. */
378 c->width = va_arg (*args, int);
382 for (; isdigit (*format); format++)
383 c->width = c->width * 10 + *format - '0';
387 c->width = -c->width;
391 /* Parse precision. */
399 c->precision = va_arg (*args, int);
404 for (; isdigit (*format); format++)
405 c->precision = c->precision * 10 + *format - '0';
407 if (c->precision < 0)
410 if (c->precision >= 0)
457 /* Performs an integer conversion, writing output to OUTPUT with
458 auxiliary data AUX. The integer converted has absolute value
459 VALUE. If NEGATIVE is true the value is negative, otherwise
460 positive. The output will use the given DIGITS, with
461 strlen(DIGITS) indicating the output base. Details of the
462 conversion are in C. */
464 format_integer (uintmax_t value, bool negative, const struct integer_base *b,
465 const struct printf_conversion *c,
466 void (*output) (char, void *), void *aux)
468 char buf[64], *cp; /* Buffer and current position. */
469 const char *signifier; /* b->signifier or "". */
470 int precision; /* Rendered precision. */
471 int pad_cnt; /* # of pad characters to fill field width. */
472 int group_cnt; /* # of digits grouped so far. */
474 /* Accumulate digits into buffer.
475 This algorithm produces digits in reverse order, so later we
476 will output the buffer's content in reverse. This is also
477 the reason that later we append zeros and the sign. */
482 if ((c->flags & GROUP) && group_cnt++ == b->group)
487 *cp++ = b->digits[value % b->base];
491 /* Append enough zeros to match precision.
492 If requested precision is 0, then a value of zero is
493 rendered as a null string, otherwise as "0". */
494 precision = c->precision < 0 ? 1 : c->precision;
497 while (cp - buf < precision && cp - buf < (int) sizeof buf - 8)
502 *cp++ = negative ? '-' : '+';
503 else if (c->flags & SPACE)
504 *cp++ = negative ? '-' : ' ';
508 /* Calculate number of pad characters to fill field width. */
509 signifier = c->flags & POUND ? b->signifier : "";
510 pad_cnt = c->width - (cp - buf) - strlen (signifier);
515 if ((c->flags & (MINUS | ZERO)) == 0)
516 output_dup (' ', pad_cnt, output, aux);
517 while (*signifier != '\0')
518 output (*signifier++, aux);
520 output_dup ('0', pad_cnt, output, aux);
523 if (c->flags & MINUS)
524 output_dup (' ', pad_cnt, output, aux);
527 /* Writes CH to OUTPUT with auxiliary data AUX, CNT times. */
529 output_dup (char ch, size_t cnt, void (*output) (char, void *), void *aux)
535 /* Formats the LENGTH characters starting at STRING according to
536 the conversion specified in C. Writes output to OUTPUT with
537 auxiliary data AUX. */
539 format_string (const char *string, size_t length,
540 struct printf_conversion *c,
541 void (*output) (char, void *), void *aux)
543 if (c->width > 1 && (c->flags & MINUS) == 0)
544 output_dup (' ', c->width - 1, output, aux);
546 output (*string++, aux);
547 if (c->width > 1 && (c->flags & MINUS) != 0)
548 output_dup (' ', c->width - 1, output, aux);
551 /* Wrapper for __vprintf() that converts varargs into a
554 __printf (const char *format,
555 void (*output) (char, void *), void *aux, ...)
559 va_start (args, aux);
560 __vprintf (format, args, output, aux);
564 /* Dumps the SIZE bytes in BUF to the console as hex bytes
565 arranged 16 per line, plus offsets listed starting at OFS for
566 the first byte in BU. If ASCII is true then the corresponding
567 ASCII characters are also rendered alongside. */
569 hex_dump (uintptr_t ofs, const void *buf_, size_t size, bool ascii)
571 const uint8_t *buf = buf_;
572 const size_t per_line = 16; /* Maximum bytes per line. */
576 size_t start, end, n;
579 /* Number of bytes on this line. */
580 start = ofs % per_line;
582 if (end - start > size)
587 printf ("%08jx ", (uintmax_t) ROUND_DOWN (ofs, per_line));
588 for (i = 0; i < start; i++)
592 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
595 for (; i < per_line; i++)
598 for (i = 0; i < start; i++)
602 isprint (buf[i - start]) ? buf[i - start] : '.');
603 for (; i < per_line; i++)