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 int x; /* `x' character to use, for base 16 only. */
136 int group; /* Number of digits to group with ' flag. */
139 static const struct integer_base base_d = {10, "0123456789", 0, 3};
140 static const struct integer_base base_o = {8, "01234567", 0, 3};
141 static const struct integer_base base_x = {16, "0123456789abcdef", 'x', 4};
142 static const struct integer_base base_X = {16, "0123456789ABCDEF", 'X', 4};
144 static const char *parse_conversion (const char *format,
145 struct printf_conversion *,
147 static void format_integer (uintmax_t value, bool is_signed, 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, int 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);
217 if (value > SIZE_MAX / 2)
218 value = value - SIZE_MAX - 1;
224 format_integer (value < 0 ? -value : value,
225 true, value < 0, &base_d, &c, output, aux);
234 /* Unsigned integer conversions. */
236 const struct integer_base *b;
241 value = (unsigned char) va_arg (args, unsigned);
244 value = (unsigned short) va_arg (args, unsigned);
247 value = va_arg (args, unsigned);
250 value = va_arg (args, uintmax_t);
253 value = va_arg (args, unsigned long);
256 value = va_arg (args, unsigned long long);
259 value = va_arg (args, ptrdiff_t);
260 #if UINTMAX_MAX != PTRDIFF_MAX
261 value &= ((uintmax_t) PTRDIFF_MAX << 1) | 1;
265 value = va_arg (args, size_t);
273 case 'o': b = &base_o; break;
274 case 'u': b = &base_d; break;
275 case 'x': b = &base_x; break;
276 case 'X': b = &base_X; break;
277 default: NOT_REACHED ();
280 format_integer (value, false, false, b, &c, output, aux);
286 /* Treat character as single-character string. */
287 char ch = va_arg (args, int);
288 format_string (&ch, 1, &c, output, aux);
294 /* String conversion. */
295 const char *s = va_arg (args, char *);
299 /* Limit string length according to precision.
300 Note: if c.precision == -1 then strnlen() will get
301 SIZE_MAX for MAXLEN, which is just what we want. */
302 format_string (s, strnlen (s, c.precision), &c, output, aux);
308 /* Pointer conversion.
309 Format pointers as %#x. */
310 void *p = va_arg (args, void *);
313 format_integer ((uintptr_t) p, false, false,
314 &base_x, &c, output, aux);
324 /* We don't support floating-point arithmetic,
325 and %n can be part of a security hole. */
326 __printf ("<<no %%%c in kernel>>", output, aux, *format);
330 __printf ("<<no %%%c conversion>>", output, aux, *format);
336 /* Parses conversion option characters starting at FORMAT and
337 initializes C appropriately. Returns the character in FORMAT
338 that indicates the conversion (e.g. the `d' in `%d'). Uses
339 *ARGS for `*' field widths and precisions. */
341 parse_conversion (const char *format, struct printf_conversion *c,
344 /* Parse flag characters. */
374 if (c->flags & MINUS)
379 /* Parse field width. */
384 c->width = va_arg (*args, int);
388 for (; isdigit (*format); format++)
389 c->width = c->width * 10 + *format - '0';
393 c->width = -c->width;
397 /* Parse precision. */
405 c->precision = va_arg (*args, int);
410 for (; isdigit (*format); format++)
411 c->precision = c->precision * 10 + *format - '0';
413 if (c->precision < 0)
416 if (c->precision >= 0)
463 /* Performs an integer conversion, writing output to OUTPUT with
464 auxiliary data AUX. The integer converted has absolute value
465 VALUE. If IS_SIGNED is true, does a signed conversion with
466 NEGATIVE indicating a negative value; otherwise does an
467 unsigned conversion and ignores IS_SIGNED. The output is done
468 according to the provided base B. Details of the conversion
471 format_integer (uintmax_t value, bool is_signed, bool negative,
472 const struct integer_base *b,
473 const struct printf_conversion *c,
474 void (*output) (char, void *), void *aux)
476 char buf[64], *cp; /* Buffer and current position. */
477 int x; /* `x' character to use or 0 if none. */
478 int sign; /* Sign character or 0 if none. */
479 int precision; /* Rendered precision. */
480 int pad_cnt; /* # of pad characters to fill field width. */
481 int digit_cnt; /* # of digits output so far. */
483 /* Determine sign character, if any.
484 An unsigned conversion will never have a sign character,
485 even if one of the flags requests one. */
490 sign = negative ? '-' : '+';
491 else if (c->flags & SPACE)
492 sign = negative ? '-' : ' ';
497 /* Determine whether to include `0x' or `0X'.
498 It will only be included with a hexadecimal conversion of a
499 nonzero value with the # flag. */
500 x = (c->flags & POUND) && value ? b->x : 0;
502 /* Accumulate digits into buffer.
503 This algorithm produces digits in reverse order, so later we
504 will output the buffer's content in reverse. */
509 if ((c->flags & GROUP) && digit_cnt > 0 && digit_cnt % b->group == 0)
511 *cp++ = b->digits[value % b->base];
516 /* Append enough zeros to match precision.
517 If requested precision is 0, then a value of zero is
518 rendered as a null string, otherwise as "0".
519 If the # flag is used with base 0, the result must always
520 begin with a zero. */
521 precision = c->precision < 0 ? 1 : c->precision;
522 while (cp - buf < precision && cp < buf + sizeof buf - 1)
524 if ((c->flags & POUND) && b->base == 8 && (cp == buf || cp[-1] != '0'))
527 /* Calculate number of pad characters to fill field width. */
528 pad_cnt = c->width - (cp - buf) - (x ? 2 : 0) - (sign != 0);
533 if ((c->flags & (MINUS | ZERO)) == 0)
534 output_dup (' ', pad_cnt, output, aux);
543 output_dup ('0', pad_cnt, output, aux);
546 if (c->flags & MINUS)
547 output_dup (' ', pad_cnt, output, aux);
550 /* Writes CH to OUTPUT with auxiliary data AUX, CNT times. */
552 output_dup (char ch, size_t cnt, void (*output) (char, void *), void *aux)
558 /* Formats the LENGTH characters starting at STRING according to
559 the conversion specified in C. Writes output to OUTPUT with
560 auxiliary data AUX. */
562 format_string (const char *string, int length,
563 struct printf_conversion *c,
564 void (*output) (char, void *), void *aux)
567 if (c->width > length && (c->flags & MINUS) == 0)
568 output_dup (' ', c->width - length, output, aux);
569 for (i = 0; i < length; i++)
570 output (string[i], aux);
571 if (c->width > length && (c->flags & MINUS) != 0)
572 output_dup (' ', c->width - length, output, aux);
575 /* Wrapper for __vprintf() that converts varargs into a
578 __printf (const char *format,
579 void (*output) (char, void *), void *aux, ...)
583 va_start (args, aux);
584 __vprintf (format, args, output, aux);
588 /* Dumps the SIZE bytes in BUF to the console as hex bytes
589 arranged 16 per line. Numeric offsets are also included,
590 starting at OFS for the first byte in BUF. If ASCII is true
591 then the corresponding ASCII characters are also rendered
594 hex_dump (uintptr_t ofs, const void *buf_, size_t size, bool ascii)
596 const uint8_t *buf = buf_;
597 const size_t per_line = 16; /* Maximum bytes per line. */
601 size_t start, end, n;
604 /* Number of bytes on this line. */
605 start = ofs % per_line;
607 if (end - start > size)
612 printf ("%08jx ", (uintmax_t) ROUND_DOWN (ofs, per_line));
613 for (i = 0; i < start; i++)
617 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
620 for (; i < per_line; i++)
623 for (i = 0; i < start; i++)
627 isprint (buf[i - start]) ? buf[i - start] : '.');
628 for (; i < per_line; i++)