6 /* Auxiliary data for vsnprintf_helper(). */
9 char *p; /* Current output position. */
10 int length; /* Length of output string. */
11 int max_length; /* Max length of output string. */
14 static void vsnprintf_helper (char, void *);
16 /* Like vprintf(), except that output is stored into BUFFER,
17 which must have space for BUF_SIZE characters. Writes at most
18 BUF_SIZE - 1 characters to BUFFER, followed by a null
19 terminator. BUFFER will always be null-terminated unless
20 BUF_SIZE is zero. Returns the number of characters that would
21 have been written to BUFFER, not including a null terminator,
22 had there been enough room. */
24 vsnprintf (char *buffer, size_t buf_size, const char *format, va_list args)
26 /* Set up aux data for vsnprintf_helper(). */
27 struct vsnprintf_aux aux;
30 aux.max_length = buf_size > 0 ? buf_size - 1 : 0;
32 /* Do most of the work. */
33 __vprintf (format, args, vsnprintf_helper, &aux);
35 /* Add null terminator. */
42 /* Helper function for vsnprintf(). */
44 vsnprintf_helper (char ch, void *aux_)
46 struct vsnprintf_aux *aux = aux_;
48 if (aux->length++ < aux->max_length)
52 /* Like printf(), except that output is stored into BUFFER,
53 which must have space for BUF_SIZE characters. Writes at most
54 BUF_SIZE - 1 characters to BUFFER, followed by a null
55 terminator. BUFFER will always be null-terminated unless
56 BUF_SIZE is zero. Returns the number of characters that would
57 have been written to BUFFER, not including a null terminator,
58 had there been enough room. */
60 snprintf (char *buffer, size_t buf_size, const char *format, ...)
65 va_start (args, format);
66 retval = vsnprintf (buffer, buf_size, format, args);
72 /* Writes formatted output to the console.
73 In the kernel, the console is both the video display and first
75 In userspace, the console is file descriptor 1.
78 printf (const char *format, ...)
83 va_start (args, format);
84 retval = vprintf (format, args);
90 /* printf() formatting internals. */
92 /* A printf() conversion. */
93 struct printf_conversion
98 MINUS = 1 << 0, /* '-' */
99 PLUS = 1 << 1, /* '+' */
100 SPACE = 1 << 2, /* ' ' */
101 POUND = 1 << 3, /* '#' */
102 ZERO = 1 << 4, /* '0' */
103 GROUP = 1 << 5 /* '\'' */
107 /* Minimum field width. */
110 /* Numeric precision.
111 -1 indicates no precision was specified. */
114 /* Type of argument to format. */
119 INT = 3, /* (none) */
122 LONGLONG = 6, /* ll */
123 PTRDIFFT = 7, /* t */
131 int base; /* Base. */
132 const char *digits; /* Collection of digits. */
133 const char *signifier; /* Prefix used with # flag. */
134 int group; /* Number of digits to group with ' flag. */
137 static const struct integer_base base_d = {10, "0123456789", "", 3};
138 static const struct integer_base base_o = {8, "01234567", "0", 3};
139 static const struct integer_base base_x = {16, "0123456789abcdef", "0x", 4};
140 static const struct integer_base base_X = {16, "0123456789ABCDEF", "0X", 4};
142 static const char *parse_conversion (const char *format,
143 struct printf_conversion *,
145 static void format_integer (uintmax_t value, bool negative,
146 const struct integer_base *,
147 const struct printf_conversion *,
148 void (*output) (char, void *), void *aux);
149 static void output_dup (char ch, size_t cnt,
150 void (*output) (char, void *), void *aux);
151 static void format_string (const char *string, size_t length,
152 struct printf_conversion *,
153 void (*output) (char, void *), void *aux);
156 __vprintf (const char *format, va_list args,
157 void (*output) (char, void *), void *aux)
159 for (; *format != '\0'; format++)
161 struct printf_conversion c;
163 /* Literally copy non-conversions to output. */
166 output (*format, aux);
178 /* Parse conversion specifiers. */
179 format = parse_conversion (format, &c, &args);
187 /* Signed integer conversions. */
193 value = (signed char) va_arg (args, int);
196 value = (short) va_arg (args, int);
199 value = va_arg (args, int);
202 value = va_arg (args, long);
205 value = va_arg (args, long long);
208 value = va_arg (args, ptrdiff_t);
211 value = va_arg (args, size_t);
217 format_integer (value < 0 ? -value : value,
218 value < 0, &base_d, &c, output, aux);
227 /* Unsigned integer conversions. */
229 const struct integer_base *b;
234 value = (unsigned char) va_arg (args, unsigned);
237 value = (unsigned short) va_arg (args, unsigned);
240 value = va_arg (args, unsigned);
243 value = va_arg (args, unsigned long);
246 value = va_arg (args, unsigned long long);
249 value = va_arg (args, ptrdiff_t);
252 value = va_arg (args, size_t);
260 case 'o': b = &base_o; break;
261 case 'u': b = &base_d; break;
262 case 'x': b = &base_x; break;
263 case 'X': b = &base_X; break;
264 default: NOT_REACHED ();
267 format_integer (value, false, b, &c, output, aux);
273 /* Treat character as single-character string. */
274 char ch = va_arg (args, int);
275 format_string (&ch, 1, &c, output, aux);
281 /* String conversion. */
282 const char *s = va_arg (args, char *);
286 /* Limit string length according to precision.
287 Note: if c.precision == -1 then strnlen() will get
288 SIZE_MAX for MAXLEN, which is just what we want. */
289 format_string (s, strnlen (s, c.precision), &c, output, aux);
295 /* Pointer conversion.
296 Format pointers as %#x. */
297 void *p = va_arg (args, void *);
300 format_integer ((uintptr_t) p, false, &base_x, &c, output, aux);
310 /* We don't support floating-point arithmetic,
311 and %n can be part of a security hole. */
312 __printf ("<<no %%%c in kernel>>", output, aux, *format);
316 __printf ("<<no %%%c conversion>>", output, aux, *format);
322 /* Parses conversion option characters starting at FORMAT and
323 initializes C appropriately. Returns the character in FORMAT
324 that indicates the conversion (e.g. the `d' in `%d'). Uses
325 *ARGS for `*' field widths and precisions. */
327 parse_conversion (const char *format, struct printf_conversion *c,
330 /* Parse flag characters. */
360 if (c->flags & MINUS)
365 /* Parse field width. */
370 c->width = va_arg (*args, int);
374 for (; isdigit (*format); format++)
375 c->width = c->width * 10 + *format - '0';
379 c->width = -c->width;
383 /* Parse precision. */
391 c->precision = va_arg (*args, int);
396 for (; isdigit (*format); format++)
397 c->precision = c->precision * 10 + *format - '0';
399 if (c->precision < 0)
402 if (c->precision >= 0)
449 /* Performs an integer conversion, writing output to OUTPUT with
450 auxiliary data AUX. The integer converted has absolute value
451 VALUE. If NEGATIVE is true the value is negative, otherwise
452 positive. The output will use the given DIGITS, with
453 strlen(DIGITS) indicating the output base. Details of the
454 conversion are in C. */
456 format_integer (uintmax_t value, bool negative, const struct integer_base *b,
457 const struct printf_conversion *c,
458 void (*output) (char, void *), void *aux)
460 char buf[64], *cp; /* Buffer and current position. */
461 const char *signifier; /* b->signifier or "". */
462 int precision; /* Rendered precision. */
463 int pad_cnt; /* # of pad characters to fill field width. */
464 int group_cnt; /* # of digits grouped so far. */
466 /* Accumulate digits into buffer.
467 This algorithm produces digits in reverse order, so later we
468 will output the buffer's content in reverse. This is also
469 the reason that later we append zeros and the sign. */
474 if ((c->flags & GROUP) && group_cnt++ == b->group)
479 *cp++ = b->digits[value % b->base];
483 /* Append enough zeros to match precision.
484 If requested precision is 0, then a value of zero is
485 rendered as a null string, otherwise as "0". */
486 precision = c->precision < 0 ? 1 : c->precision;
489 while (cp - buf < precision && cp - buf < (int) sizeof buf - 8)
494 *cp++ = negative ? '-' : '+';
495 else if (c->flags & SPACE)
496 *cp++ = negative ? '-' : ' ';
500 /* Calculate number of pad characters to fill field width. */
501 signifier = c->flags & POUND ? b->signifier : "";
502 pad_cnt = c->width - (cp - buf) - strlen (signifier);
507 if ((c->flags & (MINUS | ZERO)) == 0)
508 output_dup (' ', pad_cnt, output, aux);
509 while (*signifier != '\0')
510 output (*signifier++, aux);
512 output_dup ('0', pad_cnt, output, aux);
515 if (c->flags & MINUS)
516 output_dup (' ', pad_cnt, output, aux);
519 /* Writes CH to OUTPUT with auxiliary data AUX, CNT times. */
521 output_dup (char ch, size_t cnt, void (*output) (char, void *), void *aux)
527 /* Formats the LENGTH characters starting at STRING according to
528 the conversion specified in C. Writes output to OUTPUT with
529 auxiliary data AUX. */
531 format_string (const char *string, size_t length,
532 struct printf_conversion *c,
533 void (*output) (char, void *), void *aux)
535 if (c->width > 1 && (c->flags & MINUS) == 0)
536 output_dup (' ', c->width - 1, output, aux);
538 output (*string++, aux);
539 if (c->width > 1 && (c->flags & MINUS) != 0)
540 output_dup (' ', c->width - 1, output, aux);
543 /* Wrapper for __vprintf() that converts varargs into a
546 __printf (const char *format,
547 void (*output) (char, void *), void *aux, ...)
551 va_start (args, aux);
552 __vprintf (format, args, output, aux);
556 /* Dumps the SIZE bytes in BUFFER to the console as hex bytes
557 arranged 16 per line. If ASCII is true then the corresponding
558 ASCII characters are also rendered alongside. */
560 hex_dump (const void *buffer, size_t size, bool ascii)
562 const size_t n_per_line = 16; /* Maximum bytes per line. */
563 size_t n; /* Number of bytes in this line. */
564 const uint8_t *p; /* Start of current line in buffer. */
566 for (p = buffer; p < (uint8_t *) buffer + size; p += n)
570 /* Number of bytes on this line. */
571 n = (uint8_t *) (buffer + size) - p;
576 for (i = 0; i < n; i++)
577 printf ("%c%02x", i == n_per_line / 2 ? '-' : ' ', (unsigned) p[i]);
580 for (; i < n_per_line; i++)
583 for (i = 0; i < n; i++)
584 printf ("%c", isprint (p[i]) ? p[i] : '.');
585 for (; i < n_per_line; i++)