BNX2X: disables TPA
[akaros.git] / kern / src / printfmt.c
index 27947cc..8018966 100644 (file)
 #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);
 }
 
 // Main function to format and print a string.
@@ -56,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) != '%') {
@@ -80,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';
@@ -127,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);
@@ -138,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
@@ -205,6 +251,10 @@ void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_li
                        base = 16;
                        goto number;
 
+               // qid
+               case 'Q':
+                       printqid(putch, putdat, va_arg(ap, void*));
+                       break;
                number:
                        printnum(putch, putdat, num, base, width, padc);
                        break;
@@ -213,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);
@@ -236,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 {
@@ -246,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)
@@ -256,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;
@@ -286,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;
+}