Added a debug statement for debugging stuff in parlib.
authorKevin Klues <klueska@cs.berkeley.edu>
Wed, 27 May 2009 16:40:39 +0000 (09:40 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Fri, 5 Jun 2009 00:58:08 +0000 (17:58 -0700)
Just pulled out printf implementation from roslib and renamed everything debug*.  Also hacked the
menager to only run our one single enviroment and then die.

user/apps/parlib/hello.c
user/parlib/inc/debug.h [new file with mode: 0644]
user/parlib/src/Makefrag
user/parlib/src/debug.c [new file with mode: 0644]
user/parlib/src/debugfmt.c [new file with mode: 0644]
user/parlib/src/parlibmain.c

index f5429d7..db008b1 100644 (file)
@@ -3,6 +3,6 @@
 
 int main(int argc, char** argv)
 {
-//     printf("Hello world from newlib!!\n");
+       printf("Hello world from newlib!!\n");
        return 0;
 }
diff --git a/user/parlib/inc/debug.h b/user/parlib/inc/debug.h
new file mode 100644 (file)
index 0000000..1a82469
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef PARLIB_INC_DEBUG_H
+#define PARLIB_INC_DEBUG_H
+
+typedef void * TRUSTED va_list;
+
+#define __va_size(type) \
+    (((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long))
+
+#define va_start(ap, last) \
+    ((ap) = (va_list)&(last) + __va_size(last))
+
+#define va_arg(ap, type) \
+    (*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))
+
+#define va_end(ap)  ((void)0)
+
+int    strnlen(const char *s, size_t size);
+void debugfmt(void (*putch)(int, void**), void **putdat, const char *NTS fmt, ...);
+void vdebugfmt(void (*putch)(int, void**), void **putdat, const char *NTS fmt, va_list);
+
+int    debug(const char * NTS fmt, ...);
+int    vdebug(const char * NTS fmt, va_list);
+
+#endif /* !PARLIB_INC_DEBUG_H */
index 63a203b..365229b 100644 (file)
@@ -6,6 +6,8 @@ USER_PARLIB_SRC_CFLAGS   := $(USER_CFLAGS) --nopatch \
                             -I$(USER_PARLIB_NEWLIB_DIR)/include
 
 USER_PARLIB_SRC_SRCFILES := $(USER_PARLIB_SRC_DIR)/newlib_backend.c \
+                            $(USER_PARLIB_SRC_DIR)/debug.c \
+                            $(USER_PARLIB_SRC_DIR)/debugfmt.c \
                             $(USER_PARLIB_SRC_DIR)/syscall.c \
                             $(USER_PARLIB_SRC_DIR)/parlibmain.c \
                             $(USER_PARLIB_SRC_DIR)/entry.S  
diff --git a/user/parlib/src/debug.c b/user/parlib/src/debug.c
new file mode 100644 (file)
index 0000000..04fa2bc
--- /dev/null
@@ -0,0 +1,62 @@
+// Implementation of cprintf console output for user environments,
+// based on printfmt() and the sys_cputs() system call.
+//
+// cprintf is a debugging statement, not a generic output statement.
+// It is very important that it always go to the console, especially when
+// debugging file descriptor code!
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <arch/types.h>
+#include <parlib.h>
+#include <debug.h>
+
+// Collect up to BUF_SIZE characters into a buffer
+// and perform ONE system call to print all of them,
+// in order to make the lines output to the console atomic
+// and prevent interrupts from causing context switches
+// in the middle of a console output line and such.
+#define BUF_SIZE 256
+typedef struct debugbuf {
+       int idx;        // current buffer index
+       int cnt;        // total bytes printed so far
+       char buf[BUF_SIZE];
+} debugbuf_t;
+
+
+static void putch(int ch, debugbuf_t **b)
+{
+       (*b)->buf[(*b)->idx++] = ch;
+       if ((*b)->idx == BUF_SIZE) {
+               sys_cputs((*b)->buf, (*b)->idx);
+               (*b)->idx = 0;
+       }
+       (*b)->cnt++;
+}
+
+int vdebug(const char *fmt, va_list ap)
+{
+       debugbuf_t b;
+       debugbuf_t *bp = &b;
+
+       b.idx = 0;
+       b.cnt = 0;
+       vdebugfmt((void*)putch, (void**)&bp, fmt, ap);
+       sys_cputs(b.buf, b.idx);
+
+       return b.cnt;
+}
+
+int debug(const char *fmt, ...)
+{
+       va_list ap;
+       int cnt;
+
+       va_start(ap, fmt);
+       cnt = vdebug(fmt, ap);
+       va_end(ap);
+
+       return cnt;
+}
+
diff --git a/user/parlib/src/debugfmt.c b/user/parlib/src/debugfmt.c
new file mode 100644 (file)
index 0000000..121d1fe
--- /dev/null
@@ -0,0 +1,247 @@
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <arch/types.h>
+#include <ros/error.h>
+#include <debug.h>
+
+/*
+ * Space or zero padding and a field width are supported for the numeric
+ * formats only. 
+ * 
+ * The special format %e takes an integer error code
+ * and prints a string describing the error.
+ * The integer may be positive or negative,
+ * so that -E_NO_MEM and E_NO_MEM are equivalent.
+ */
+
+static const char * const error_string[MAXERROR + 1] =
+{
+       NULL,
+       "unspecified error",
+       "bad environment",
+       "invalid parameter",
+       "out of memory",
+       "out of environments",
+       "segmentation fault",
+};
+
+/*
+ * Print a number (base <= 16) in reverse order,
+ * using specified putch function and associated pointer putdat.
+ */
+static void printnum(void (*putch)(int, void**), void **putdat,
+                        unsigned long long num, unsigned base, int width, int padc)
+{
+       // first recursively print all preceding (more significant) digits
+       if (num >= base) {
+               printnum(putch, putdat, num / base, base, width - 1, padc);
+       } else {
+               // print any needed pad characters before first digit
+               while (--width > 0)
+                       putch(padc, putdat);
+       }
+
+       // then print this (the least significant) digit
+       putch("0123456789abcdef"[num % base], putdat);
+}
+
+// Get an unsigned int of various possible sizes from a varargs list,
+// depending on the lflag parameter.
+static unsigned long long getuint(va_list *ap, int lflag)
+{
+       if (lflag >= 2)
+               return va_arg(*ap, unsigned long long);
+       else if (lflag)
+               return va_arg(*ap, unsigned long);
+       else
+               return va_arg(*ap, unsigned int);
+}
+
+// Same as getuint but signed - can't use getuint
+// because of sign extension
+static long long getint(va_list *ap, int lflag)
+{
+       if (lflag >= 2)
+               return va_arg(*ap, long long);
+       else if (lflag)
+               return va_arg(*ap, long);
+       else
+               return va_arg(*ap, int);
+}
+
+
+// Main function to format and print a string.
+void debugfmt(void (*putch)(int, void**), void **putdat, const char *fmt, ...);
+void vdebugfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap)
+{
+       register const char *p;
+       register int ch, err;
+       unsigned long long num;
+       int base, lflag, width, precision, altflag;
+       char padc;
+
+       while (1) {
+               while ((ch = *(unsigned char *) fmt++) != '%') {
+                       if (ch == '\0')
+                               return;
+                       putch(ch, putdat);
+               }
+
+               // Process a %-escape sequence
+               padc = ' ';
+               width = -1;
+               precision = -1;
+               lflag = 0;
+               altflag = 0;
+       reswitch:
+               switch (ch = *(unsigned char *) fmt++) {
+
+               // flag to pad on the right
+               case '-':
+                       padc = '-';
+                       goto reswitch;
+                       
+               // flag to pad with 0's instead of spaces
+               case '0':
+                       padc = '0';
+                       goto reswitch;
+
+               // width field
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+                       for (precision = 0; ; ++fmt) {
+                               precision = precision * 10 + ch - '0';
+                               ch = *fmt;
+                               if (ch < '0' || ch > '9')
+                                       break;
+                       }
+                       goto process_precision;
+
+               case '*':
+                       precision = va_arg(ap, int);
+                       goto process_precision;
+
+               case '.':
+                       if (width < 0)
+                               width = 0;
+                       goto reswitch;
+
+               case '#':
+                       altflag = 1;
+                       goto reswitch;
+
+               process_precision:
+                       if (width < 0)
+                               width = precision, precision = -1;
+                       goto reswitch;
+
+               // long flag (doubled for long long)
+               case 'l':
+                       lflag++;
+                       goto reswitch;
+
+               // character
+               case 'c':
+                       putch(va_arg(ap, int), putdat);
+                       break;
+
+               // error message
+               case 'e':
+                       err = va_arg(ap, int);
+                       if (err < 0)
+                               err = -err;
+                       if (err > MAXERROR || (p = error_string[err]) == NULL)
+                               debugfmt(putch, putdat, "error %d", err);
+                       else
+                               debugfmt(putch, putdat, "%s", p);
+                       break;
+
+               // string
+               case 's':
+                       if ((p = va_arg(ap, char *)) == NULL)
+                               p = "(null)";
+                       if (width > 0 && padc != '-')
+                               for (width -= strnlen(p, precision); width > 0; width--)
+                                       putch(padc, putdat);
+                       for (; (ch = *p++) != '\0' && (precision < 0 || --precision >= 0); width--)
+                               if (altflag && (ch < ' ' || ch > '~'))
+                                       putch('?', putdat);
+                               else
+                                       putch(ch, putdat);
+                       for (; width > 0; width--)
+                               putch(' ', putdat);
+                       break;
+
+               // (signed) decimal
+               case 'd':
+                       num = getint(&ap, lflag);
+                       if ((long long) num < 0) {
+                               putch('-', putdat);
+                               num = -(long long) num;
+                       }
+                       base = 10;
+                       goto number;
+
+               // unsigned decimal
+               case 'u':
+                       num = getuint(&ap, lflag);
+                       base = 10;
+                       goto number;
+
+               // (unsigned) octal
+               case 'o':
+                       // should do something with padding so it's always 3 octits
+                       num = getuint(&ap, lflag);
+                       base = 8;
+                       goto number;
+
+               // pointer
+               case 'p':
+                       putch('0', putdat);
+                       putch('x', putdat);
+                       num = (unsigned long long)
+                               (uintptr_t) va_arg(ap, void *);
+                       base = 16;
+                       goto number;
+
+               // (unsigned) hexadecimal
+               case 'x':
+                       num = getuint(&ap, lflag);
+                       base = 16;
+               number:
+                       printnum(putch, putdat, num, base, width, padc);
+                       break;
+
+               // escaped '%' character
+               case '%':
+                       putch(ch, putdat);
+                       break;
+                       
+               // unrecognized escape sequence - just print it literally
+               default:
+                       putch('%', putdat);
+                       for (fmt--; fmt[-1] != '%'; fmt--)
+                               /* do nothing */;
+                       break;
+               }
+       }
+}
+
+void debugfmt(void (*putch)(int, void**), void **putdat, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vdebugfmt(putch, putdat, fmt, ap);
+       va_end(ap);
+}
+
index be49a5f..25d9e46 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <parlib.h>
 #include <stdlib.h>
+#include <debug.h>
 
 volatile env_t *env;
 extern int main(int argc, char **argv);
@@ -17,6 +18,7 @@ void parlibmain(int argc, char **argv)
        // procinfo.  When we figure out what we want there, change this.
        env = (env_t*)procinfo; 
 
+       debug("Hello from env %d!\n", env->env_id);
        // call user main routine
        int r = main(argc, argv);