12 memset (void *dst_, int value, size_t cnt)
14 unsigned char *dst = dst_;
23 memcpy (void *dst_, const void *src_, size_t cnt)
25 unsigned char *dst = dst_;
26 const unsigned char *src = src_;
35 memmove (void *dst_, const void *src_, size_t cnt)
37 unsigned char *dst = dst_;
38 const unsigned char *src = src_;
57 memchr (const void *block_, int ch_, size_t size)
59 const unsigned char *block = block_;
60 unsigned char ch = ch_;
62 for (; size-- > 0; block++)
64 return (void *) block;
70 memcmp (const void *a_, const void *b_, size_t size)
72 const unsigned char *a = a_;
73 const unsigned char *b = b_;
75 for (; size-- > 0; a++, b++)
77 return *a > *b ? +1 : -1;
82 strlcpy (char *dst, const char *src, size_t size)
84 size_t src_len = strlen (src);
87 size_t dst_len_max = size - 1;
88 size_t dst_len = src_len < dst_len_max ? src_len : dst_len_max;
89 memcpy (dst, src, dst_len);
96 strlen (const char *string)
100 for (p = string; *p != '\0'; p++)
106 strchr (const char *string, int c_)
112 return (char *) string;
113 else if (*string == '\0')
119 vprintf_core (const char *format, va_list args,
120 void (*output) (char, void *), void *aux);
123 output_console (char ch, void *aux __attribute__ ((unused)))
130 vprintk (const char *format, va_list args)
132 enum if_level old_level = intr_disable ();
133 vprintf_core (format, args, output_console, NULL);
134 intr_set_level (old_level);
138 printk (const char *format, ...)
142 va_start (args, format);
143 vprintk (format, args);
147 /* printf() and friends internals. You do not need to understand
150 struct printf_conversion
180 parse_conversion (const char *format, struct printf_conversion *c, va_list *args)
182 /* Parse flag characters. */
209 if (c->flags & MINUS)
214 /* Parse field width. */
219 c->width = va_arg (*args, int);
223 for (; isdigit (*format); format++)
224 c->width = c->width * 10 + *format - '0';
228 c->width = -c->width;
232 /* Parse precision. */
240 c->precision = va_arg (*args, int);
245 for (; isdigit (*format); format++)
246 c->precision = c->precision * 10 + *format - '0';
248 if (c->precision < 0)
251 if (c->precision >= 0)
305 output_dup (char ch, size_t cnt, void (*output) (char, void *), void *aux)
312 printf_integer (uintmax_t value, bool negative, const char *digits,
313 struct printf_conversion *c,
314 void (*output) (char, void *), void *aux)
319 const char *base_name;
322 base = strlen (digits);
324 /* Accumulate digits into buffer.
325 This algorithm produces digits in reverse order, so later we
326 will output the buffer's content in reverse. This is also
327 the reason that later we append zeros and the sign. */
331 *cp++ = digits[value % base];
335 /* Append enough zeros to match precision.
336 If precision is 0, then a value of zero is rendered as a
337 null string. Otherwise at least one digit is presented. */
338 if (c->precision < 0)
340 while (cp - buf < c->precision && cp - buf < (int) sizeof buf - 8)
345 *cp++ = negative ? '-' : '+';
346 else if (c->flags & SPACE)
347 *cp++ = negative ? '-' : ' ';
351 /* Get name of base. */
353 if (c->flags & POUND)
358 base_name = digits[0xa] == 'a' ? "0x" : "0X";
361 /* Calculate number of pad characters to fill field width. */
362 pad_cnt = c->width - (cp - buf) - strlen (base_name);
367 if ((c->flags & (MINUS | ZERO)) == 0)
368 output_dup (' ', pad_cnt, output, aux);
369 while (*base_name != '\0')
370 output (*base_name++, aux);
372 output_dup ('0', pad_cnt, output, aux);
375 if (c->flags & MINUS)
376 output_dup (' ', pad_cnt, output, aux);
380 printf_string (const char *string, size_t length,
381 struct printf_conversion *c,
382 void (*output) (char, void *), void *aux)
384 if (c->width > 1 && (c->flags & MINUS) == 0)
385 output_dup (' ', c->width - 1, output, aux);
387 output (*string++, aux);
388 if (c->width > 1 && (c->flags & MINUS) != 0)
389 output_dup (' ', c->width - 1, output, aux);
393 printf_core (const char *format,
394 void (*output) (char, void *), void *aux, ...)
398 va_start (args, aux);
399 vprintf_core (format, args, output, aux);
404 vprintf_core (const char *format, va_list args,
405 void (*output) (char, void *), void *aux)
407 for (; *format != '\0'; format++)
409 struct printf_conversion c;
411 /* Literally copy non-conversions to output. */
414 output (*format, aux);
426 format = parse_conversion (format, &c, &args);
434 bool negative = false;
439 value = (signed char) va_arg (args, int);
442 value = (short) va_arg (args, int);
445 value = va_arg (args, int);
448 value = va_arg (args, long);
451 value = va_arg (args, long long);
454 value = va_arg (args, ptrdiff_t);
457 value = va_arg (args, size_t);
471 printf_integer (abs_value, negative, "0123456789",
487 value = (unsigned char) va_arg (args, unsigned);
490 value = (unsigned short) va_arg (args, unsigned);
493 value = va_arg (args, unsigned);
496 value = va_arg (args, unsigned long);
499 value = va_arg (args, unsigned long long);
502 value = va_arg (args, ptrdiff_t);
505 value = va_arg (args, size_t);
517 digits = "0123456789";
520 digits = "0123456789abcdef";
523 digits = "0123456789ABCDEF";
529 printf_integer (value, false, digits, &c, output, aux);
535 char ch = va_arg (args, int);
536 printf_string (&ch, 1, &c, output, aux);
545 s = va_arg (args, char *);
549 if (c.precision >= 0)
551 const char *zero = memchr (s, '\0', c.precision);
555 length = c.precision;
560 printf_string (s, length, &c, output, aux);
566 void *p = va_arg (args, void *);
570 printf_integer ((uintptr_t) p,
571 false, "0123456789abcdef", &c,
574 printf_string ("(nil)", 5, &c, output, aux);
584 printf_core ("<<no %%%c in kernel>>", output, aux, *format);
588 printf_core ("<<no %%%c conversion>>", output, aux, *format);