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. */
79 printf (const char *format, ...)
84 va_start (args, format);
85 retval = vprintf (format, args);
91 /* printf() formatting internals. */
93 /* A printf() conversion. */
94 struct printf_conversion
99 MINUS = 1 << 0, /* '-' */
100 PLUS = 1 << 1, /* '+' */
101 SPACE = 1 << 2, /* ' ' */
102 POUND = 1 << 3, /* '#' */
103 ZERO = 1 << 4, /* '0' */
104 GROUP = 1 << 5 /* '\'' */
108 /* Minimum field width. */
111 /* Numeric precision.
112 -1 indicates no precision was specified. */
115 /* Type of argument to format. */
120 INT = 3, /* (none) */
123 LONGLONG = 6, /* ll */
124 PTRDIFFT = 7, /* t */
132 int base; /* Base. */
133 const char *digits; /* Collection of digits. */
134 int x; /* `x' character to use, for base 16 only. */
135 int group; /* Number of digits to group with ' flag. */
138 static const struct integer_base base_d = {10, "0123456789", 0, 3};
139 static const struct integer_base base_o = {8, "01234567", 0, 3};
140 static const struct integer_base base_x = {16, "0123456789abcdef", 'x', 4};
141 static const struct integer_base base_X = {16, "0123456789ABCDEF", 'X', 4};
143 static const char *parse_conversion (const char *format,
144 struct printf_conversion *,
146 static void format_integer (uintmax_t value, bool is_signed, bool negative,
147 const struct integer_base *,
148 const struct printf_conversion *,
149 void (*output) (char, void *), void *aux);
150 static void output_dup (char ch, size_t cnt,
151 void (*output) (char, void *), void *aux);
152 static void format_string (const char *string, int length,
153 struct printf_conversion *,
154 void (*output) (char, void *), void *aux);
157 __vprintf (const char *format, va_list args,
158 void (*output) (char, void *), void *aux)
160 for (; *format != '\0'; format++)
162 struct printf_conversion c;
164 /* Literally copy non-conversions to output. */
167 output (*format, aux);
179 /* Parse conversion specifiers. */
180 format = parse_conversion (format, &c, &args);
188 /* Signed integer conversions. */
194 value = (signed char) va_arg (args, int);
197 value = (short) va_arg (args, int);
200 value = va_arg (args, int);
203 value = va_arg (args, intmax_t);
206 value = va_arg (args, long);
209 value = va_arg (args, long long);
212 value = va_arg (args, ptrdiff_t);
215 value = va_arg (args, size_t);
216 if (value > SIZE_MAX / 2)
217 value = value - SIZE_MAX - 1;
223 format_integer (value < 0 ? -value : value,
224 true, value < 0, &base_d, &c, output, aux);
233 /* Unsigned integer conversions. */
235 const struct integer_base *b;
240 value = (unsigned char) va_arg (args, unsigned);
243 value = (unsigned short) va_arg (args, unsigned);
246 value = va_arg (args, unsigned);
249 value = va_arg (args, uintmax_t);
252 value = va_arg (args, unsigned long);
255 value = va_arg (args, unsigned long long);
258 value = va_arg (args, ptrdiff_t);
259 #if UINTMAX_MAX != PTRDIFF_MAX
260 value &= ((uintmax_t) PTRDIFF_MAX << 1) | 1;
264 value = va_arg (args, size_t);
272 case 'o': b = &base_o; break;
273 case 'u': b = &base_d; break;
274 case 'x': b = &base_x; break;
275 case 'X': b = &base_X; break;
276 default: NOT_REACHED ();
279 format_integer (value, false, false, b, &c, output, aux);
285 /* Treat character as single-character string. */
286 char ch = va_arg (args, int);
287 format_string (&ch, 1, &c, output, aux);
293 /* String conversion. */
294 const char *s = va_arg (args, char *);
298 /* Limit string length according to precision.
299 Note: if c.precision == -1 then strnlen() will get
300 SIZE_MAX for MAXLEN, which is just what we want. */
301 format_string (s, strnlen (s, c.precision), &c, output, aux);
307 /* Pointer conversion.
308 Format pointers as %#x. */
309 void *p = va_arg (args, void *);
312 format_integer ((uintptr_t) p, false, false,
313 &base_x, &c, output, aux);
323 /* We don't support floating-point arithmetic,
324 and %n can be part of a security hole. */
325 __printf ("<<no %%%c in kernel>>", output, aux, *format);
329 __printf ("<<no %%%c conversion>>", output, aux, *format);
335 /* Parses conversion option characters starting at FORMAT and
336 initializes C appropriately. Returns the character in FORMAT
337 that indicates the conversion (e.g. the `d' in `%d'). Uses
338 *ARGS for `*' field widths and precisions. */
340 parse_conversion (const char *format, struct printf_conversion *c,
343 /* Parse flag characters. */
373 if (c->flags & MINUS)
378 /* Parse field width. */
383 c->width = va_arg (*args, int);
387 for (; isdigit (*format); format++)
388 c->width = c->width * 10 + *format - '0';
392 c->width = -c->width;
396 /* Parse precision. */
404 c->precision = va_arg (*args, int);
409 for (; isdigit (*format); format++)
410 c->precision = c->precision * 10 + *format - '0';
412 if (c->precision < 0)
415 if (c->precision >= 0)
462 /* Performs an integer conversion, writing output to OUTPUT with
463 auxiliary data AUX. The integer converted has absolute value
464 VALUE. If IS_SIGNED is true, does a signed conversion with
465 NEGATIVE indicating a negative value; otherwise does an
466 unsigned conversion and ignores NEGATIVE. The output is done
467 according to the provided base B. Details of the conversion
470 format_integer (uintmax_t value, bool is_signed, bool negative,
471 const struct integer_base *b,
472 const struct printf_conversion *c,
473 void (*output) (char, void *), void *aux)
475 char buf[64], *cp; /* Buffer and current position. */
476 int x; /* `x' character to use or 0 if none. */
477 int sign; /* Sign character or 0 if none. */
478 int precision; /* Rendered precision. */
479 int pad_cnt; /* # of pad characters to fill field width. */
480 int digit_cnt; /* # of digits output so far. */
482 /* Determine sign character, if any.
483 An unsigned conversion will never have a sign character,
484 even if one of the flags requests one. */
489 sign = negative ? '-' : '+';
490 else if (c->flags & SPACE)
491 sign = negative ? '-' : ' ';
496 /* Determine whether to include `0x' or `0X'.
497 It will only be included with a hexadecimal conversion of a
498 nonzero value with the # flag. */
499 x = (c->flags & POUND) && value ? b->x : 0;
501 /* Accumulate digits into buffer.
502 This algorithm produces digits in reverse order, so later we
503 will output the buffer's content in reverse. */
508 if ((c->flags & GROUP) && digit_cnt > 0 && digit_cnt % b->group == 0)
510 *cp++ = b->digits[value % b->base];
515 /* Append enough zeros to match precision.
516 If requested precision is 0, then a value of zero is
517 rendered as a null string, otherwise as "0".
518 If the # flag is used with base 8, the result must always
519 begin with a zero. */
520 precision = c->precision < 0 ? 1 : c->precision;
521 while (cp - buf < precision && cp < buf + sizeof buf - 1)
523 if ((c->flags & POUND) && b->base == 8 && (cp == buf || cp[-1] != '0'))
526 /* Calculate number of pad characters to fill field width. */
527 pad_cnt = c->width - (cp - buf) - (x ? 2 : 0) - (sign != 0);
532 if ((c->flags & (MINUS | ZERO)) == 0)
533 output_dup (' ', pad_cnt, output, aux);
542 output_dup ('0', pad_cnt, output, aux);
545 if (c->flags & MINUS)
546 output_dup (' ', pad_cnt, output, aux);
549 /* Writes CH to OUTPUT with auxiliary data AUX, CNT times. */
551 output_dup (char ch, size_t cnt, void (*output) (char, void *), void *aux)
557 /* Formats the LENGTH characters starting at STRING according to
558 the conversion specified in C. Writes output to OUTPUT with
559 auxiliary data AUX. */
561 format_string (const char *string, int length,
562 struct printf_conversion *c,
563 void (*output) (char, void *), void *aux)
566 if (c->width > length && (c->flags & MINUS) == 0)
567 output_dup (' ', c->width - length, output, aux);
568 for (i = 0; i < length; i++)
569 output (string[i], aux);
570 if (c->width > length && (c->flags & MINUS) != 0)
571 output_dup (' ', c->width - length, output, aux);
574 /* Wrapper for __vprintf() that converts varargs into a
577 __printf (const char *format,
578 void (*output) (char, void *), void *aux, ...)
582 va_start (args, aux);
583 __vprintf (format, args, output, aux);
587 /* Dumps the SIZE bytes in BUF to the console as hex bytes
588 arranged 16 per line. Numeric offsets are also included,
589 starting at OFS for the first byte in BUF. If ASCII is true
590 then the corresponding ASCII characters are also rendered
593 hex_dump (uintptr_t ofs, const void *buf_, size_t size, bool ascii)
595 const uint8_t *buf = buf_;
596 const size_t per_line = 16; /* Maximum bytes per line. */
600 size_t start, end, n;
603 /* Number of bytes on this line. */
604 start = ofs % per_line;
606 if (end - start > size)
611 printf ("%08jx ", (uintmax_t) ROUND_DOWN (ofs, per_line));
612 for (i = 0; i < start; i++)
616 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
619 for (; i < per_line; i++)
622 for (i = 0; i < start; i++)
626 isprint (buf[i - start]) ? buf[i - start] : '.');
627 for (; i < per_line; i++)