Improve error message.
[pintos-anon] / src / lib / lib.c
index d439f5d7b81793dc78c865f80870ce6c9ba8f77e..17b0a8086e174a65595bcc11c879fe531a69ae15 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #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++;
 }
-
+\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 __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);
 }
 \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. */
 
@@ -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,
         }
     }
 }
+\f
+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;
+    }
+}