#include <stdbool.h>
#include <stddef.h>
#include "debug.h"
+#include "interrupt.h"
#include "lib.h"
#include "serial.h"
#include "vga.h"
void *
-memset (void *dst_, int value, size_t cnt)
+memset (void *dst_, int value, size_t size)
{
- uint8_t *dst = dst_;
+ unsigned char *dst = dst_;
+
+ ASSERT (dst != NULL || size == 0);
- while (cnt-- > 0)
+ while (size-- > 0)
*dst++ = value;
return dst_;
}
void *
-memcpy (void *dst_, const void *src_, size_t cnt)
+memcpy (void *dst_, const void *src_, size_t size)
{
- uint8_t *dst = dst_;
- const uint8_t *src = src_;
+ unsigned char *dst = dst_;
+ const unsigned char *src = src_;
- while (cnt-- > 0)
+ ASSERT (dst != NULL || size == 0);
+ ASSERT (src != NULL || size == 0);
+
+ while (size-- > 0)
*dst++ = *src++;
return dst_;
}
void *
-memmove (void *dst_, const void *src_, size_t cnt)
+memmove (void *dst_, const void *src_, size_t size)
{
- uint8_t *dst = dst_;
- const uint8_t *src = src_;
+ unsigned char *dst = dst_;
+ const unsigned char *src = src_;
+
+ ASSERT (dst != NULL || size == 0);
+ ASSERT (src != NULL || size == 0);
if (dst < src)
{
- while (cnt-- > 0)
+ while (size-- > 0)
*dst++ = *src++;
}
else
{
- dst += cnt;
- src += cnt;
- while (cnt-- > 0)
+ dst += size;
+ src += size;
+ while (size-- > 0)
*--dst = *--src;
}
void *
memchr (const void *block_, int ch_, size_t size)
{
- const uint8_t *block = block_;
- uint8_t ch = ch_;
+ const unsigned char *block = block_;
+ unsigned char ch = ch_;
+
+ ASSERT (block != NULL || size == 0);
for (; size-- > 0; block++)
if (*block == ch)
return NULL;
}
+int
+memcmp (const void *a_, const void *b_, size_t size)
+{
+ const unsigned char *a = a_;
+ const unsigned char *b = b_;
+
+ ASSERT (a != NULL || size == 0);
+ ASSERT (b != NULL || size == 0);
+
+ for (; size-- > 0; a++, b++)
+ if (*a != *b)
+ return *a > *b ? +1 : -1;
+ return 0;
+}
+
size_t
strlcpy (char *dst, const char *src, size_t size)
{
- size_t src_len = strlen (src);
+ size_t src_len;
+
+ ASSERT (dst != NULL);
+ ASSERT (src != NULL);
+
+ src_len = strlen (src);
if (size > 0)
{
size_t dst_len_max = size - 1;
{
const char *p;
+ ASSERT (string != NULL);
+
for (p = string; *p != '\0'; p++)
continue;
return p - string;
{
char c = c_;
+ ASSERT (string != NULL);
+
for (;;)
if (*string == c)
return (char *) string;
else if (*string == '\0')
return NULL;
- else string++;
+ else
+ string++;
+}
+
+int
+strcmp (const char *a_, const char *b_)
+{
+ const unsigned char *a = (const unsigned char *) a_;
+ const unsigned char *b = (const unsigned char *) b_;
+
+ ASSERT (a != NULL);
+ ASSERT (b != NULL);
+
+ while (*a != '\0' && *a == *b)
+ {
+ a++;
+ b++;
+ }
+
+ return *a < *b ? -1 : *a > *b;
}
+char *
+strtok_r (char *s, const char *delimiters, char **save_ptr)
+{
+ char *token;
+
+ ASSERT (delimiters != NULL);
+ ASSERT (save_ptr != NULL);
+
+ /* If S is nonnull, start from it.
+ If S is null, start from saved position. */
+ if (s == NULL)
+ s = *save_ptr;
+ ASSERT (s != NULL);
+
+ /* Skip any DELIMITERS at our current position. */
+ while (strchr (delimiters, *s) != NULL)
+ {
+ /* strchr() will always return nonnull if we're searching
+ for a null byte, because every string contains a null
+ byte (at the end). */
+ if (*s == '\0')
+ {
+ *save_ptr = s;
+ return NULL;
+ }
+
+ s++;
+ }
+
+ /* Skip any non-DELIMITERS up to the end of the string. */
+ token = s;
+ while (strchr (delimiters, *s) == NULL)
+ s++;
+ if (*s != '\0')
+ {
+ *s = '\0';
+ *save_ptr = s + 1;
+ }
+ else
+ *save_ptr = s;
+ return token;
+}
+
+int
+atoi (const char *s)
+{
+ bool negative;
+ int value;
+
+ /* Skip white space. */
+ while (isspace (*s))
+ s++;
+
+ /* Parse sign. */
+ negative = false;
+ if (*s == '+')
+ s++;
+ else if (*s == '-')
+ {
+ negative = true;
+ s++;
+ }
+
+ /* Parse digits. We always initially parse the value as
+ negative, and then make it positive later, because the
+ negative range of an int is bigger than the positive range
+ on a 2's complement system. */
+ for (value = 0; isdigit (*s); s++)
+ value = value * 10 - (*s - '0');
+ if (!negative)
+ value = -value;
+
+ return value;
+}
+\f
static void
vprintf_core (const char *format, va_list args,
void (*output) (char, void *), void *aux);
static void
-output_console (char ch, void *aux __attribute__ ((unused)))
+vprintk_helper (char ch, void *aux UNUSED)
{
vga_putc (ch);
serial_outb (ch);
void
vprintk (const char *format, va_list args)
{
- vprintf_core (format, args, output_console, NULL);
+ enum intr_level old_level = intr_disable ();
+ vprintf_core (format, args, vprintk_helper, NULL);
+ intr_set_level (old_level);
}
void
va_end (args);
}
\f
+struct vsnprintf_aux
+ {
+ char *p;
+ int length;
+ int max_length;
+ };
+
+static void
+vsnprintf_helper (char ch, void *aux_)
+{
+ struct vsnprintf_aux *aux = aux_;
+
+ if (aux->length++ < aux->max_length)
+ *aux->p++ = ch;
+}
+
+int
+vsnprintf (char *buffer, size_t buf_size,
+ const char *format, va_list args)
+{
+ struct vsnprintf_aux aux;
+ aux.p = buffer;
+ aux.length = 0;
+ aux.max_length = buf_size > 0 ? buf_size - 1 : 0;
+
+ vprintf_core (format, args, vsnprintf_helper, &aux);
+
+ if (buf_size > 0)
+ *aux.p = '\0';
+
+ return aux.length;
+}
+
+int
+snprintf (char *buffer, size_t buf_size,
+ const char *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = vsnprintf (buffer, buf_size, format, args);
+ va_end (args);
+
+ return retval;
+}
+\f
/* printf() and friends internals. You do not need to understand
this code. */
PLUS = 1 << 1,
SPACE = 1 << 2,
POUND = 1 << 3,
- ZERO = 1 << 4
+ ZERO = 1 << 4,
+ GROUP = 1 << 5
}
flags;
};
static const char *
-parse_conversion (const char *format, struct printf_conversion *c, va_list *args)
+parse_conversion (const char *format, struct printf_conversion *c,
+ va_list *args)
{
/* Parse flag characters. */
c->flags = 0;
case '0':
c->flags |= ZERO;
break;
+ case '\'':
+ c->flags |= GROUP;
+ break;
default:
format--;
goto not_a_flag;
void (*output) (char, void *), void *aux)
{
- int base = strlen (digits);
+ char buf[64], *cp;
+ int base;
+ const char *base_name;
+ int pad_cnt, group_cnt;
- char buf[64];
- char *const buf_end = buf + sizeof buf;
- char *bp;
-
- int pad;
+ base = strlen (digits);
/* Accumulate digits into buffer.
- This algorithm produces digits in reverse order, so we count
- backward from the end of the array. */
- bp = buf_end;
+ This algorithm produces digits in reverse order, so later we
+ will output the buffer's content in reverse. This is also
+ the reason that later we append zeros and the sign. */
+ cp = buf;
+ group_cnt = 0;
while (value > 0)
{
- *--bp = digits[value % base];
+ if ((c->flags & GROUP) && group_cnt++ == 3)
+ {
+ *cp++ = ',';
+ group_cnt = 0;
+ }
+ *cp++ = digits[value % base];
value /= base;
}
- /* Prepend enough zeros to match precision.
+ /* Append enough zeros to match precision.
If precision is 0, then a value of zero is rendered as a
null string. Otherwise at least one digit is presented. */
if (c->precision < 0)
c->precision = 1;
- while (buf_end - bp < c->precision && bp > buf + 3)
- *--bp = '0';
+ while (cp - buf < c->precision && cp - buf < (int) sizeof buf - 8)
+ *cp++ = '0';
- /* Prepend sign. */
+ /* Append sign. */
if (c->flags & PLUS)
- *--bp = negative ? '-' : '+';
+ *cp++ = negative ? '-' : '+';
else if (c->flags & SPACE)
- *--bp = negative ? '-' : ' ';
+ *cp++ = negative ? '-' : ' ';
else if (negative)
- *--bp = '-';
+ *cp++ = '-';
- /* Prepend base. */
- if ((c->flags & POUND) && base != 10)
+ /* Get name of base. */
+ base_name = "";
+ if (c->flags & POUND)
{
- *--bp = digits[0xa] == 'a' ? 'x' : 'X';
- *--bp = '0';
+ if (base == 8)
+ base_name = "0";
+ else if (base == 16)
+ base_name = digits[0xa] == 'a' ? "0x" : "0X";
}
/* Calculate number of pad characters to fill field width. */
- pad = c->width - (buf_end - bp);
- if (pad < 0)
- pad = 0;
+ pad_cnt = c->width - (cp - buf) - strlen (base_name);
+ if (pad_cnt < 0)
+ pad_cnt = 0;
/* Do output. */
if ((c->flags & (MINUS | ZERO)) == 0)
- output_dup (' ', pad, output, aux);
- if (bp < buf_end && strchr (digits, *bp) == NULL)
- output (*bp++, aux);
+ output_dup (' ', pad_cnt, output, aux);
+ while (*base_name != '\0')
+ output (*base_name++, aux);
if (c->flags & ZERO)
- output_dup ('0', pad, output, aux);
- while (bp < buf_end)
- output (*bp++, aux);
+ output_dup ('0', pad_cnt, output, aux);
+ while (cp > buf)
+ output (*--cp, aux);
if (c->flags & MINUS)
- output_dup (' ', pad, output, aux);
+ output_dup (' ', pad_cnt, output, aux);
}
static void
}
}
}
+\f
+void
+hex_dump (const void *buffer, size_t size, bool ascii)
+{
+ const size_t n_per_line = 16;
+ const uint8_t *p = buffer;
+ size_t ofs = 0;
+
+ while (size > 0)
+ {
+ size_t n, i;
+
+ printk ("%08zx", ofs);
+ n = size >= n_per_line ? n_per_line : size;
+ for (i = 0; i < n; i++)
+ printk ("%c%02x", i == n_per_line / 2 ? '-' : ' ', (unsigned) p[i]);
+
+ if (ascii)
+ {
+ for (; i < n_per_line; i++)
+ printk (" ");
+ printk (" |");
+ for (i = 0; i < n; i++)
+ printk ("%c", isprint (p[i]) ? p[i] : '.');
+ for (; i < n_per_line; i++)
+ printk (" ");
+ printk ("|");
+ }
+ printk ("\n");
+
+ p += n;
+ ofs += n;
+ size -= n;
+ }
+}