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 vprintk_helper (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, vprintk_helper, NULL);
134 intr_set_level (old_level);
138 printk (const char *format, ...)
142 va_start (args, format);
143 vprintk (format, args);
155 vsnprintf_helper (char ch, void *aux_)
157 struct vsnprintf_aux *aux = aux_;
159 if (aux->length++ < aux->max_length)
164 vsnprintf (char *buffer, size_t buf_size,
165 const char *format, va_list args)
167 struct vsnprintf_aux aux;
170 aux.max_length = buf_size > 0 ? buf_size - 1 : 0;
172 vprintf_core (format, args, vsnprintf_helper, &aux);
181 snprintf (char *buffer, size_t buf_size,
182 const char *format, ...)
186 va_start (args, format);
187 vsnprintf (buffer, buf_size, format, args);
191 /* printf() and friends internals. You do not need to understand
194 struct printf_conversion
224 parse_conversion (const char *format, struct printf_conversion *c,
227 /* Parse flag characters. */
254 if (c->flags & MINUS)
259 /* Parse field width. */
264 c->width = va_arg (*args, int);
268 for (; isdigit (*format); format++)
269 c->width = c->width * 10 + *format - '0';
273 c->width = -c->width;
277 /* Parse precision. */
285 c->precision = va_arg (*args, int);
290 for (; isdigit (*format); format++)
291 c->precision = c->precision * 10 + *format - '0';
293 if (c->precision < 0)
296 if (c->precision >= 0)
350 output_dup (char ch, size_t cnt, void (*output) (char, void *), void *aux)
357 printf_integer (uintmax_t value, bool negative, const char *digits,
358 struct printf_conversion *c,
359 void (*output) (char, void *), void *aux)
364 const char *base_name;
367 base = strlen (digits);
369 /* Accumulate digits into buffer.
370 This algorithm produces digits in reverse order, so later we
371 will output the buffer's content in reverse. This is also
372 the reason that later we append zeros and the sign. */
376 *cp++ = digits[value % base];
380 /* Append enough zeros to match precision.
381 If precision is 0, then a value of zero is rendered as a
382 null string. Otherwise at least one digit is presented. */
383 if (c->precision < 0)
385 while (cp - buf < c->precision && cp - buf < (int) sizeof buf - 8)
390 *cp++ = negative ? '-' : '+';
391 else if (c->flags & SPACE)
392 *cp++ = negative ? '-' : ' ';
396 /* Get name of base. */
398 if (c->flags & POUND)
403 base_name = digits[0xa] == 'a' ? "0x" : "0X";
406 /* Calculate number of pad characters to fill field width. */
407 pad_cnt = c->width - (cp - buf) - strlen (base_name);
412 if ((c->flags & (MINUS | ZERO)) == 0)
413 output_dup (' ', pad_cnt, output, aux);
414 while (*base_name != '\0')
415 output (*base_name++, aux);
417 output_dup ('0', pad_cnt, output, aux);
420 if (c->flags & MINUS)
421 output_dup (' ', pad_cnt, output, aux);
425 printf_string (const char *string, size_t length,
426 struct printf_conversion *c,
427 void (*output) (char, void *), void *aux)
429 if (c->width > 1 && (c->flags & MINUS) == 0)
430 output_dup (' ', c->width - 1, output, aux);
432 output (*string++, aux);
433 if (c->width > 1 && (c->flags & MINUS) != 0)
434 output_dup (' ', c->width - 1, output, aux);
438 printf_core (const char *format,
439 void (*output) (char, void *), void *aux, ...)
443 va_start (args, aux);
444 vprintf_core (format, args, output, aux);
449 vprintf_core (const char *format, va_list args,
450 void (*output) (char, void *), void *aux)
452 for (; *format != '\0'; format++)
454 struct printf_conversion c;
456 /* Literally copy non-conversions to output. */
459 output (*format, aux);
471 format = parse_conversion (format, &c, &args);
479 bool negative = false;
484 value = (signed char) va_arg (args, int);
487 value = (short) va_arg (args, int);
490 value = va_arg (args, int);
493 value = va_arg (args, long);
496 value = va_arg (args, long long);
499 value = va_arg (args, ptrdiff_t);
502 value = va_arg (args, size_t);
516 printf_integer (abs_value, negative, "0123456789",
532 value = (unsigned char) va_arg (args, unsigned);
535 value = (unsigned short) va_arg (args, unsigned);
538 value = va_arg (args, unsigned);
541 value = va_arg (args, unsigned long);
544 value = va_arg (args, unsigned long long);
547 value = va_arg (args, ptrdiff_t);
550 value = va_arg (args, size_t);
562 digits = "0123456789";
565 digits = "0123456789abcdef";
568 digits = "0123456789ABCDEF";
574 printf_integer (value, false, digits, &c, output, aux);
580 char ch = va_arg (args, int);
581 printf_string (&ch, 1, &c, output, aux);
590 s = va_arg (args, char *);
594 if (c.precision >= 0)
596 const char *zero = memchr (s, '\0', c.precision);
600 length = c.precision;
605 printf_string (s, length, &c, output, aux);
611 void *p = va_arg (args, void *);
615 printf_integer ((uintptr_t) p,
616 false, "0123456789abcdef", &c,
619 printf_string ("(nil)", 5, &c, output, aux);
629 printf_core ("<<no %%%c in kernel>>", output, aux, *format);
633 printf_core ("<<no %%%c conversion>>", output, aux, *format);