ralink: update patches
[openwrt.git] / target / linux / ramips / image / lzma-loader / src / printf.c
diff --git a/target/linux/ramips/image/lzma-loader/src/printf.c b/target/linux/ramips/image/lzma-loader/src/printf.c
new file mode 100644 (file)
index 0000000..7bb5a86
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include       "printf.h"
+
+extern void board_putc(int ch);
+
+/* this is the maximum width for a variable */
+#define                LP_MAX_BUF      256
+
+/* macros */
+#define                IsDigit(x)      ( ((x) >= '0') && ((x) <= '9') )
+#define                Ctod(x)         ( (x) - '0')
+
+/* forward declaration */
+static int PrintChar(char *, char, int, int);
+static int PrintString(char *, char *, int, int);
+static int PrintNum(char *, unsigned long, int, int, int, int, char, int);
+
+/* private variable */
+static const char theFatalMsg[] = "fatal error in lp_Print!";
+
+/* -*-
+ * A low level printf() function.
+ */
+static void
+lp_Print(void (*output)(void *, char *, int),
+        void * arg,
+        char *fmt,
+        va_list ap)
+{
+
+#define        OUTPUT(arg, s, l)  \
+  { if (((l) < 0) || ((l) > LP_MAX_BUF)) { \
+       (*output)(arg, (char*)theFatalMsg, sizeof(theFatalMsg)-1); for(;;); \
+    } else { \
+      (*output)(arg, s, l); \
+    } \
+  }
+
+    char buf[LP_MAX_BUF];
+
+    char c;
+    char *s;
+    long int num;
+
+    int longFlag;
+    int negFlag;
+    int width;
+    int prec;
+    int ladjust;
+    char padc;
+
+    int length;
+
+    for(;;) {
+       {
+           /* scan for the next '%' */
+           char *fmtStart = fmt;
+           while ( (*fmt != '\0') && (*fmt != '%')) {
+               fmt ++;
+           }
+
+           /* flush the string found so far */
+           OUTPUT(arg, fmtStart, fmt-fmtStart);
+
+           /* are we hitting the end? */
+           if (*fmt == '\0') break;
+       }
+
+       /* we found a '%' */
+       fmt ++;
+
+       /* check for long */
+       if (*fmt == 'l') {
+           longFlag = 1;
+           fmt ++;
+       } else {
+           longFlag = 0;
+       }
+
+       /* check for other prefixes */
+       width = 0;
+       prec = -1;
+       ladjust = 0;
+       padc = ' ';
+
+       if (*fmt == '-') {
+           ladjust = 1;
+           fmt ++;
+       }
+
+       if (*fmt == '0') {
+           padc = '0';
+           fmt++;
+       }
+
+       if (IsDigit(*fmt)) {
+           while (IsDigit(*fmt)) {
+               width = 10 * width + Ctod(*fmt++);
+           }
+       }
+
+       if (*fmt == '.') {
+           fmt ++;
+           if (IsDigit(*fmt)) {
+               prec = 0;
+               while (IsDigit(*fmt)) {
+                   prec = prec*10 + Ctod(*fmt++);
+               }
+           }
+       }
+
+
+       /* check format flag */
+       negFlag = 0;
+       switch (*fmt) {
+        case 'b':
+           if (longFlag) {
+               num = va_arg(ap, long int);
+           } else {
+               num = va_arg(ap, int);
+           }
+           length = PrintNum(buf, num, 2, 0, width, ladjust, padc, 0);
+           OUTPUT(arg, buf, length);
+           break;
+
+        case 'd':
+        case 'D':
+           if (longFlag) {
+               num = va_arg(ap, long int);
+           } else {
+               num = va_arg(ap, int);
+           }
+           if (num < 0) {
+               num = - num;
+               negFlag = 1;
+           }
+           length = PrintNum(buf, num, 10, negFlag, width, ladjust, padc, 0);
+           OUTPUT(arg, buf, length);
+           break;
+
+        case 'o':
+        case 'O':
+           if (longFlag) {
+               num = va_arg(ap, long int);
+           } else {
+               num = va_arg(ap, int);
+           }
+           length = PrintNum(buf, num, 8, 0, width, ladjust, padc, 0);
+           OUTPUT(arg, buf, length);
+           break;
+
+        case 'u':
+        case 'U':
+           if (longFlag) {
+               num = va_arg(ap, long int);
+           } else {
+               num = va_arg(ap, int);
+           }
+           length = PrintNum(buf, num, 10, 0, width, ladjust, padc, 0);
+           OUTPUT(arg, buf, length);
+           break;
+
+        case 'x':
+           if (longFlag) {
+               num = va_arg(ap, long int);
+           } else {
+               num = va_arg(ap, int);
+           }
+           length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 0);
+           OUTPUT(arg, buf, length);
+           break;
+
+        case 'X':
+           if (longFlag) {
+               num = va_arg(ap, long int);
+           } else {
+               num = va_arg(ap, int);
+           }
+           length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 1);
+           OUTPUT(arg, buf, length);
+           break;
+
+        case 'c':
+           c = (char)va_arg(ap, int);
+           length = PrintChar(buf, c, width, ladjust);
+           OUTPUT(arg, buf, length);
+           break;
+
+        case 's':
+           s = (char*)va_arg(ap, char *);
+           length = PrintString(buf, s, width, ladjust);
+           OUTPUT(arg, buf, length);
+           break;
+
+        case '\0':
+           fmt --;
+           break;
+
+        default:
+           /* output this char as it is */
+           OUTPUT(arg, fmt, 1);
+       }       /* switch (*fmt) */
+
+       fmt ++;
+    }          /* for(;;) */
+
+    /* special termination call */
+    OUTPUT(arg, "\0", 1);
+}
+
+
+/* --------------- local help functions --------------------- */
+static int
+PrintChar(char * buf, char c, int length, int ladjust)
+{
+    int i;
+
+    if (length < 1) length = 1;
+    if (ladjust) {
+       *buf = c;
+       for (i=1; i< length; i++) buf[i] = ' ';
+    } else {
+       for (i=0; i< length-1; i++) buf[i] = ' ';
+       buf[length - 1] = c;
+    }
+    return length;
+}
+
+static int
+PrintString(char * buf, char* s, int length, int ladjust)
+{
+    int i;
+    int len=0;
+    char* s1 = s;
+    while (*s1++) len++;
+    if (length < len) length = len;
+
+    if (ladjust) {
+       for (i=0; i< len; i++) buf[i] = s[i];
+       for (i=len; i< length; i++) buf[i] = ' ';
+    } else {
+       for (i=0; i< length-len; i++) buf[i] = ' ';
+       for (i=length-len; i < length; i++) buf[i] = s[i-length+len];
+    }
+    return length;
+}
+
+static int
+PrintNum(char * buf, unsigned long u, int base, int negFlag,
+        int length, int ladjust, char padc, int upcase)
+{
+    /* algorithm :
+     *  1. prints the number from left to right in reverse form.
+     *  2. fill the remaining spaces with padc if length is longer than
+     *     the actual length
+     *     TRICKY : if left adjusted, no "0" padding.
+     *             if negtive, insert  "0" padding between "0" and number.
+     *  3. if (!ladjust) we reverse the whole string including paddings
+     *  4. otherwise we only reverse the actual string representing the num.
+     */
+
+    int actualLength =0;
+    char *p = buf;
+    int i;
+
+    do {
+       int tmp = u %base;
+       if (tmp <= 9) {
+           *p++ = '0' + tmp;
+       } else if (upcase) {
+           *p++ = 'A' + tmp - 10;
+       } else {
+           *p++ = 'a' + tmp - 10;
+       }
+       u /= base;
+    } while (u != 0);
+
+    if (negFlag) {
+       *p++ = '-';
+    }
+
+    /* figure out actual length and adjust the maximum length */
+    actualLength = p - buf;
+    if (length < actualLength) length = actualLength;
+
+    /* add padding */
+    if (ladjust) {
+       padc = ' ';
+    }
+    if (negFlag && !ladjust && (padc == '0')) {
+       for (i = actualLength-1; i< length-1; i++) buf[i] = padc;
+       buf[length -1] = '-';
+    } else {
+       for (i = actualLength; i< length; i++) buf[i] = padc;
+    }
+
+
+    /* prepare to reverse the string */
+    {
+       int begin = 0;
+       int end;
+       if (ladjust) {
+           end = actualLength - 1;
+       } else {
+           end = length -1;
+       }
+
+       while (end > begin) {
+           char tmp = buf[begin];
+           buf[begin] = buf[end];
+           buf[end] = tmp;
+           begin ++;
+           end --;
+       }
+    }
+
+    /* adjust the string pointer */
+    return length;
+}
+
+static void printf_output(void *arg, char *s, int l)
+{
+    int i;
+
+    // special termination call
+    if ((l==1) && (s[0] == '\0')) return;
+
+    for (i=0; i< l; i++) {
+       board_putc(s[i]);
+       if (s[i] == '\n') board_putc('\r');
+    }
+}
+
+void printf(char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    lp_Print(printf_output, 0, fmt, ap);
+    va_end(ap);
+}