BNX2X: disables TPA
[akaros.git] / kern / src / printfmt.c
index 030df80..8018966 100644 (file)
@@ -7,61 +7,39 @@
 #endif
 
 #include <ros/common.h>
-#include <ros/error.h>
+#include <error.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdarg.h>
+#include <kthread.h>
+#include <ns.h>
 
-/*
- * Print a number (base <= 16) in reverse order,
- * using specified putch function and associated pointer putdat.
- */
-#ifdef __DEPUTY__
-void printnum(void (*putch)(int, TV(t)), TV(t) putdat,
-                        unsigned long long num, unsigned base, int width, int padc)
-#else
+/* Print a number (base <= 16) in reverse order,
+ * using specified putch function and associated pointer putdat. */
 void printnum(void (*putch)(int, void**), void **putdat,
-                        unsigned long long num, unsigned base, int width, int padc)
-#endif
+              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);
+       unsigned long long temp = num;
+       int nr_digits = 1;
+       /* Determine how many leading zeros we need.
+        * For every digit/nibble beyond base, we do one less width padding */
+       while ((temp /= base)) {
+               nr_digits++;
+               width--;
+       }
+       /* And another one less, since we'll always print the last digit */
+       while (--width > 0)
+               putch(padc, putdat);
+       for (int i = nr_digits; i > 0; i--) {
+               temp = num;
+               /* To get digit i, we only div (i-1) times */
+               for (int j = 0; j < i - 1; j++) {
+                       temp /= base;
+               }
+               putch("0123456789abcdef"[temp % base], 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.
 #ifdef __DEPUTY__
 void printfmt(void (*putch)(int, TV(t)), TV(t) putdat, const char *fmt, ...);
@@ -81,6 +59,10 @@ void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_li
        unsigned long long num;
        int base, lflag, width, precision, altflag;
        char padc;
+       uint8_t *mac, *ip, *mask;
+       struct Gas *g;
+       int i;
+       uint32_t *lp;
 
        while (1) {
                while ((ch = *(unsigned char *) fmt) != '%') {
@@ -105,7 +87,7 @@ void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_li
                case '-':
                        padc = '-';
                        goto reswitch;
-                       
+
                // flag to pad with 0's instead of spaces
                case '0':
                        padc = '0';
@@ -152,6 +134,11 @@ void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_li
                        lflag++;
                        goto reswitch;
 
+               // chan
+               case 'C':
+                       printchan(putch, putdat, va_arg(ap, void*));
+                       break;
+
                // character
                case 'c':
                        putch(va_arg(ap, int), putdat);
@@ -163,9 +150,43 @@ void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_li
                        if (err < 0)
                                err = -err;
                        if (err >= NUMERRORS)
-                               printfmt(putch, putdat, "error %d", err);
+                               printfmt(putch, putdat, "error %d(%s)", err, get_cur_errbuf());
                        else
-                               printfmt(putch, putdat, "%s", error_string[err]);
+                               printfmt(putch, putdat, "%s (%s)", error_string[err], get_cur_errbuf());
+                       break;
+
+               case 'E': // ENET MAC
+                       if ((mac = va_arg(ap, uint8_t *)) == NULL){
+                               char *s = "00:00:00:00:00:00";
+                               while(*s)
+                                       putch(*s++, putdat);
+                       }
+                       printemac(putch, putdat, mac);
+                       break;
+               case 'i':
+                       /* what to do if they screw up? */
+                       if ((lp = va_arg(ap, uint32_t *)) != NULL){
+                               uint32_t hostfmt;
+                               for(i = 0; i < 4; i++){
+                                       hnputl(&hostfmt, lp[i]);
+                                       printfmt(putch, putdat, "%08lx", hostfmt);
+                               }
+                       }
+                       break;
+               case 'I':
+                       /* what to do if they screw up? */
+                       if ((ip = va_arg(ap, uint8_t *)) != NULL)
+                               printip(putch, putdat, ip);
+                       break;
+               case 'M':
+                       /* what to do if they screw up? */
+                       if ((mask = va_arg(ap, uint8_t *)) != NULL)
+                               printipmask(putch, putdat, mask);
+                       break;
+               case 'V':
+                       /* what to do if they screw up? */
+                       if ((ip = va_arg(ap, uint8_t *)) != NULL)
+                               printipv4(putch, putdat, ip);
                        break;
 
                // string
@@ -187,9 +208,13 @@ void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_li
                                putch(' ', putdat);
                        break;
 
-               // (signed) decimal
-               case 'd':
-                       num = getint(&ap, lflag);
+               case 'd': /* (signed) decimal */
+                       if (lflag >= 2)
+                               num = va_arg(ap, long long);
+                       else if (lflag)
+                               num = va_arg(ap, long);
+                       else
+                               num = va_arg(ap, int);
                        if ((long long) num < 0) {
                                putch('-', putdat);
                                num = -(long long) num;
@@ -197,32 +222,39 @@ void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_li
                        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;
+               case 'u': /* unsigned decimal */
+               case 'o': /* (unsigned) octal */
+               case 'x': /* (unsigned) hexadecimal */
+                       if (lflag >= 2)
+                               num = va_arg(ap, unsigned long long);
+                       else if (lflag)
+                               num = va_arg(ap, unsigned long);
+                       else
+                               num = va_arg(ap, unsigned int);
+                       if (ch == 'u')
+                               base = 10;
+                       else if (ch == 'o')
+                               base = 8;
+                       else    /* x */
+                               base = 16;
                        goto number;
 
                // pointer
                case 'p':
                        putch('0', putdat);
                        putch('x', putdat);
+                       /* automatically zero-pad pointers, out to the length of a ptr */
+                       padc = '0';
+                       width = sizeof(void*) * 2;      /* 8 bits per byte / 4 bits per char */
                        num = (unsigned long long)
                                (uintptr_t) va_arg(ap, void *);
                        base = 16;
                        goto number;
 
-               // (unsigned) hexadecimal
-               case 'x':
-                       num = getuint(&ap, lflag);
-                       base = 16;
+               // qid
+               case 'Q':
+                       printqid(putch, putdat, va_arg(ap, void*));
+                       break;
                number:
                        printnum(putch, putdat, num, base, width, padc);
                        break;
@@ -231,7 +263,7 @@ void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_li
                case '%':
                        putch(ch, putdat);
                        break;
-                       
+
                // unrecognized escape sequence - just print it literally
                default:
                        putch('%', putdat);
@@ -254,6 +286,7 @@ void printfmt(void (*putch)(int, void**), void **putdat, const char *fmt, ...)
        va_start(ap, fmt);
        vprintfmt(putch, putdat, fmt, ap);
        va_end(ap);
+       check_poison("printfmt");
 }
 
 typedef struct sprintbuf {
@@ -264,9 +297,10 @@ typedef struct sprintbuf {
 
 static void sprintputch(int ch, sprintbuf_t *NONNULL *NONNULL b)
 {
-       (*b)->cnt++;
-       if ((*b)->buf < (*b)->ebuf)
+       if ((*b)->buf < (*b)->ebuf) {
                *((*b)->buf++) = ch;
+               (*b)->cnt++;
+       }
 }
 
 int vsnprintf(char *buf, int n, const char *fmt, va_list ap)
@@ -274,8 +308,9 @@ int vsnprintf(char *buf, int n, const char *fmt, va_list ap)
        sprintbuf_t b;// = {buf, buf+n-1, 0};
        sprintbuf_t *COUNT(1) NONNULL bp = &b;
 
+       /* this isn't quite the snprintf 'spec', but errors aren't helpful */
        if (buf == NULL || n < 1)
-               return -EINVAL;
+               return 0;
 
        b.buf = NULL; // zra : help out the Deputy optimizer a bit
        b.ebuf = buf+n-1;
@@ -304,7 +339,27 @@ int snprintf(char *buf, int n, const char *fmt, ...)
        rc = vsnprintf(buf, n, fmt, ap);
        va_end(ap);
 
+       check_poison("snprintf");
        return rc;
 }
 
+/* convenience function: do a print, return the pointer to the end. */
+char *seprintf(char *buf, char *end, const char *fmt, ...)
+{
+       va_list ap;
+       int rc;
+       int n = end - buf;
+
+       if (n <= 0)
+               return buf;
 
+       va_start(ap, fmt);
+       rc = vsnprintf(buf, n, fmt, ap);
+       va_end(ap);
+       check_poison("seprintf");
+
+       if (rc >= 0)
+               return buf + rc;
+       else
+               return buf;
+}