X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flib%2Flib.c;h=17b0a8086e174a65595bcc11c879fe531a69ae15;hb=04a688940693c2286530386c05f2c8465da1a6a9;hp=d439f5d7b81793dc78c865f80870ce6c9ba8f77e;hpb=750d21936d284127e265d050ccbce76fca1ece1a;p=pintos-anon diff --git a/src/lib/lib.c b/src/lib/lib.c index d439f5d..17b0a80 100644 --- a/src/lib/lib.c +++ b/src/lib/lib.c @@ -3,6 +3,7 @@ #include #include #include "debug.h" +#include "interrupt.h" #include "lib.h" #include "serial.h" #include "vga.h" @@ -10,7 +11,7 @@ void * memset (void *dst_, int value, size_t cnt) { - uint8_t *dst = dst_; + unsigned char *dst = dst_; while (cnt-- > 0) *dst++ = value; @@ -21,8 +22,8 @@ memset (void *dst_, int value, size_t cnt) void * memcpy (void *dst_, const void *src_, size_t cnt) { - uint8_t *dst = dst_; - const uint8_t *src = src_; + unsigned char *dst = dst_; + const unsigned char *src = src_; while (cnt-- > 0) *dst++ = *src++; @@ -33,8 +34,8 @@ memcpy (void *dst_, const void *src_, size_t cnt) void * memmove (void *dst_, const void *src_, size_t cnt) { - uint8_t *dst = dst_; - const uint8_t *src = src_; + unsigned char *dst = dst_; + const unsigned char *src = src_; if (dst < src) { @@ -55,8 +56,8 @@ memmove (void *dst_, const void *src_, size_t cnt) 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_; for (; size-- > 0; block++) if (*block == ch) @@ -65,6 +66,18 @@ memchr (const void *block_, int ch_, size_t size) return NULL; } +int +memcmp (const void *a_, const void *b_, size_t size) +{ + const unsigned char *a = a_; + const unsigned char *b = b_; + + 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) { @@ -101,13 +114,13 @@ strchr (const char *string, int c_) return NULL; else string++; } - + 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 __attribute__ ((unused))) { vga_putc (ch); serial_outb (ch); @@ -116,7 +129,9 @@ output_console (char ch, void *aux __attribute__ ((unused))) void vprintk (const char *format, va_list args) { - vprintf_core (format, args, output_console, NULL); + enum if_level old_level = intr_disable (); + vprintf_core (format, args, vprintk_helper, NULL); + intr_set_level (old_level); } void @@ -129,6 +144,53 @@ printk (const char *format, ...) va_end (args); } +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; +} + /* printf() and friends internals. You do not need to understand this code. */ @@ -140,7 +202,8 @@ struct printf_conversion PLUS = 1 << 1, SPACE = 1 << 2, POUND = 1 << 3, - ZERO = 1 << 4 + ZERO = 1 << 4, + GROUP = 1 << 5 } flags; @@ -162,7 +225,8 @@ struct printf_conversion }; 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; @@ -185,6 +249,9 @@ parse_conversion (const char *format, struct printf_conversion *c, va_list *args case '0': c->flags |= ZERO; break; + case '\'': + c->flags |= GROUP; + break; default: format--; goto not_a_flag; @@ -299,63 +366,72 @@ printf_integer (uintmax_t value, bool negative, const char *digits, void (*output) (char, void *), void *aux) { - int base = strlen (digits); - - char buf[64]; - char *const buf_end = buf + sizeof buf; - char *bp; + char buf[64], *cp; + int base; + const char *base_name; + int pad_cnt, group_cnt; - 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 @@ -572,3 +648,33 @@ vprintf_core (const char *format, va_list args, } } } + +void +hex_dump (const void *buffer, size_t size) +{ + 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 / 2 ? '-' : ' ', (unsigned) p[i]); + 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 ("|\n"); + + p += n; + ofs += n; + size -= n; + } +}