Force the Qcoalesce flag on pipe fds
[akaros.git] / kern / src / printfmt.c
index 030df80..4badcd7 100644 (file)
@@ -7,61 +7,40 @@
 #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>
+#include <acpi.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 +60,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 +88,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';
@@ -168,6 +151,40 @@ void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_li
                                printfmt(putch, putdat, "%s", error_string[err]);
                        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
                case 's':
                        if ((p = va_arg(ap, char *)) == NULL)
@@ -187,9 +204,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 +218,35 @@ 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;
                number:
                        printnum(putch, putdat, num, base, width, padc);
                        break;
@@ -231,7 +255,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 +278,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 {
@@ -304,7 +329,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;
+}