]> rtime.felk.cvut.cz Git - arc.git/blobdiff - common/printf.c
merge with osek-ctest
[arc.git] / common / printf.c
index c754d0d3589f45031e7d19cd3b5733aacbe72d6b..e14b2ff8b382827a1ab74a7abf57b5143c6c886f 100644 (file)
-/*\r
- * Copyright ArcCore AB\r
- *\r
- * A simple implementation of all formatted xxprintf functionallity.\r
- *\r
- * DESIGN CRITERIA:\r
- *  - Reentrant\r
- *  - Use little stack\r
- *\r
- *  What you normally would do is to print to a buffer of some kind and then\r
- *  call write(). However little stack indicates that we can't place buffers\r
- *  on the stack and reentrant tells us that we can't have a static buffer.\r
- *  That leaves us with printing characters as it is ready. From a speed\r
- *  point of view that is less than optimal, but that the way it's got to be.\r
- *  (Could make a 16 long char buffer??)\r
- *\r
- *  This is just intended to be used as a replacement for newlibs implementation.\r
- *  Newlib porting interface have the following API:\r
- *    int write(  int fd, char *buf, int nbytes)\r
- *\r
- *\r
- *  Note that puts(), putc() are still the newlib variants....\r
- *\r
- *    printf()       -> vfprintf(stdout,) -> vsnprintf(buf,)\r
- *                                           write()\r
- *    vprintf()      -> vfprintf(stdout,) -> vsnprintf(buf,)\r
- *                                           write()\r
- *    sprintf(buf,)  ->                      vsnprintf(buf,)\r
- *    snprintf(buf,) ->                      vsnprintf(buf,)\r
- *\r
- * IMPLEMENTATION NOTE:\r
- *  If printing more than the limit, e.g. using vsnprintf() then\r
- *  the emit function will only stop printing, but not interrupted\r
- *  (The code will get more complicated that way)\r
- */\r
-\r
-#include <unistd.h>\r
-#include <stdio.h>\r
-#include <stdarg.h>\r
-#include <assert.h>\r
-#include <string.h>\r
-\r
-//#define HOST_TEST    1\r
-\r
-#ifdef HOST_TEST\r
-#define _STDOUT        stdout\r
-#define _STDIN         stdin\r
-#define _STDERR        stderr\r
-#else\r
-#define _STDOUT        (FILE *)STDOUT_FILENO\r
-#define _STDINT        STDIN_FILENO\r
-#define _STDERR        (FILE *)STDERR_FILENO\r
-#endif\r
-\r
-\r
-int arc_putchar(int fd, int c);\r
-int print(FILE *file, char **buffer, size_t n, const char *format, va_list ap);\r
-\r
-int printf(const char *format, ...) {\r
-       va_list ap;\r
-       int rv;\r
-\r
-       va_start(ap, format);\r
-       rv = vfprintf(_STDOUT, format, ap);\r
-       va_end(ap);\r
-       return rv;\r
-}\r
-\r
-int fprintf(FILE *file, const char *format, ...) {\r
-       va_list ap;\r
-       int rv;\r
-\r
-       va_start(ap, format);\r
-       rv = vfprintf(file, format, ap);\r
-       va_end(ap);\r
-       return rv;\r
-}\r
-\r
-int sprintf(char *buffer, const char *format, ...) {\r
-       va_list ap;\r
-       int rv;\r
-\r
-       va_start(ap, format);\r
-       rv = vsnprintf(buffer, ~(size_t)0, format, ap);\r
-       va_end(ap);\r
-\r
-       return rv;\r
-}\r
-\r
-int snprintf(char *buffer, size_t n, const char *format, ...) {\r
-       va_list ap;\r
-       int rv;\r
-\r
-       va_start(ap, format);\r
-       rv = vsnprintf(buffer, n, format, ap);\r
-       va_end(ap);\r
-       return rv;\r
-}\r
-\r
-int vprintf(const char *format, va_list ap) {\r
-       return vfprintf(_STDOUT, format, ap);\r
-}\r
-\r
-int vsprintf(char *buffer, const char *format, va_list ap) {\r
-       return vsnprintf(buffer, ~(size_t)0, format, ap);\r
-}\r
-\r
-int vfprintf(FILE *file, const char *format, va_list ap) {\r
-       int rv;\r
-       /* Just print to _STDOUT */\r
-       rv = print(file,NULL,~(size_t)0, format,ap);\r
-       return rv;\r
-}\r
-\r
-int vfiprintf(FILE *file, const char *format, va_list ap) {\r
-       return vfprintf(file,format,ap);\r
-}\r
-\r
-int vsnprintf(char *buffer, size_t n, const char *format, va_list ap) {\r
-       int rv;\r
-\r
-       rv = print(NULL, &buffer, n, format,ap);\r
-       return rv;\r
-}\r
-\r
-\r
-/**\r
- *\r
- * @param file  The file to print to\r
- * @param buf   The buffer to print to\r
- * @param c            The char to print\r
- * @return\r
- */\r
-static inline int emitChar( FILE *file, char **buf, char c, int *left ) {\r
-       if( (*left) == 1 ) {\r
-               return 1;\r
-       }\r
-       --(*left);\r
-       if( buf == NULL ) {\r
-#if HOST_TEST\r
-               putc(c, _STDOUT);\r
-               fflush(_STDOUT);\r
-#else\r
-               arc_putchar((int)file, c);\r
-#endif\r
-       } else {\r
-               **buf = c;\r
-               (*buf)++;\r
-       }\r
-       return 1;\r
-}\r
-\r
-\r
-#if defined(HOST_TEST)\r
-/**\r
- * Convert a number to a string\r
- *\r
- * @param val          The value to convert\r
- * @param str          Pointer to a space where to put the string\r
- * @param base         The base\r
- * @param negative     If negative or not.\r
- */\r
-void xtoa( unsigned long val, char* str, int base, int negative) {\r
-       int i;\r
-       char *oStr = str;\r
-       char c;\r
-\r
-       if (negative) {\r
-               val = -val;\r
-       }\r
-\r
-       if( base < 10 && base > 16 ) {\r
-               *str = '0';\r
-               return;\r
-       }\r
-    i = 0;\r
-\r
-    do {\r
-      str[i++] = "0123456789abcdef"[ val % base ];\r
-       } while ((val /= base) > 0);\r
-\r
-\r
-    if (negative) {\r
-        str[i++] = '-';\r
-    }\r
-\r
-    str[i] = '\0';\r
-    str = &str[i]-1;\r
-    while(str > oStr) {\r
-       c = *str;\r
-       *str-- = *oStr;\r
-       *oStr++=c;\r
-    }\r
-}\r
-#else\r
-extern void xtoa( unsigned long val, char* str, int base, int negative);\r
-#endif\r
-\r
-\r
-#define FL_NONE                                        (0<<0)\r
-#define FL_ZERO                                        (1<<1)\r
-#define FL_HASH                                        (1<<2)\r
-#define FL_SPACE                               (1<<3)\r
-#define FL_ALIGN_LEFT                  (1<<4)\r
-#define FL_TYPE_SIGNED_INT             (1<<5)\r
-#define FL_TYPE_UNSIGNED_INT   (1<<6)\r
-\r
-\r
-static void emitString( FILE *file, char **buffer, char *string, int width, int flags, int *left) {\r
-       char pad;\r
-       char *str = string;\r
-       int i;\r
-       int strLen;\r
-       /* padding: FL_ZERO or normal ' '\r
-        * align: FL_ALIGN_LEFT (left) or normal (right)\r
-        */\r
-       pad = (flags & FL_ZERO) ? '0' : ' ';\r
-\r
-\r
-       if( flags & FL_ALIGN_LEFT ) {\r
-               for(i=0;str[i]; i++) {\r
-                       emitChar(file,buffer,str[i],left);\r
-               }\r
-\r
-               /* Pad the rest */\r
-               for(;i<width;i++) {\r
-                       emitChar(file,buffer,pad,left);\r
-               }\r
-       } else {\r
-\r
-               strLen = strlen(string);\r
-\r
-               /* Pad first  */\r
-               if( width > strLen ) {\r
-                       for(i=0;i<(width-strLen);i++) {\r
-                               emitChar(file,buffer,pad,left);\r
-                       }\r
-               }\r
-\r
-               for(i=0;i<strLen; i++) {\r
-                       emitChar(file,buffer,string[i],left);\r
-               }\r
-       }\r
-}\r
-\r
-void emitInt( FILE *file, char **buffer, int val, int base, int width, int flags, int *left )\r
-{\r
-       char lBuf[12];  // longest is base 10, 2^32\r
-       char *str = lBuf;\r
-\r
-       if( flags & FL_TYPE_SIGNED_INT ) {\r
-               xtoa(val,str,base ,(val < 0));\r
-       } else {\r
-               xtoa((unsigned)val,str,base ,0);\r
-       }\r
-\r
-       emitString(file,buffer,str,width,flags,left);\r
-}\r
-\r
-#define PRINT_CHAR(_c)  *buffer++= (_c);\r
-\r
-\r
-/**\r
- * Write formatted output to an array with a maximum number of characters.\r
- *\r
- * This is the mother of the formatted print family. The main goal here\r
- * is to be very small and memory efficient.\r
- *\r
- * Support:\r
- *   Parameter: None\r
- *   Flags    : '-' and '0'\r
- *   Width    : Normal padding is supported, '*' is not.\r
- *   Precision: None\r
- *   Length   : None\r
- *   C99      : None\r
- *   Type     : d,u,x,s,and c\r
- *\r
- * @param file    The file descriptor\r
- * @param buffer  A pointer to the place to store the output\r
- *                If NULL the output is instead\r
- * @param n       The maximum number of characters to write\r
- * @param format  The format string\r
- * @param ap      The va list\r
- * @return\r
- */\r
-int print(FILE *file, char **buffer, size_t n, const char *format, va_list ap)\r
-{\r
-       char ch;\r
-       int flags;\r
-       char *str;\r
-       int width;\r
-       int left = n;\r
-\r
-       while ( (ch = *format++) ) {\r
-\r
-               if (ch == '%') {\r
-                       ch = *format++;\r
-\r
-                       if( ch == '%') {\r
-                               emitChar(file,buffer,ch,&left);\r
-                               continue;\r
-                       }\r
-\r
-                       /* Find flags */\r
-                       switch (ch) {\r
-                       case '0':\r
-                               flags = FL_ZERO;\r
-                               break;\r
-                       case ' ':\r
-                               flags = FL_SPACE;\r
-                               break;\r
-                       case '-':\r
-                               flags = FL_ALIGN_LEFT;\r
-                               break;\r
-                       default:\r
-                               /* Not supported or no flag */\r
-                               flags = FL_NONE;\r
-                               format--;\r
-                               break;\r
-                       }\r
-\r
-                       ch = *format++;\r
-\r
-                       /* Width */\r
-                       if( (ch >= '0')  && (ch <= '9') ) {\r
-                               width = ch -'0';\r
-                               ch = *format++;\r
-                       } else {\r
-                               width = 0;\r
-                       }\r
-\r
-                       /* Find type */\r
-                       switch (ch) {\r
-                       case 'c':\r
-                               emitChar(file,buffer,(char )va_arg( ap, int ),&left);\r
-                               break;\r
-                       case 'd':\r
-                               flags |= FL_TYPE_SIGNED_INT;\r
-                               emitInt(file,buffer,va_arg( ap, int ),10,width,flags,&left);\r
-                               break;\r
-                       case 'u':\r
-                               flags |= FL_TYPE_UNSIGNED_INT;\r
-                               emitInt(file,buffer,va_arg( ap, int ),10,width,flags,&left);\r
-                               break;\r
-                       case 'x':\r
-                               flags |= FL_TYPE_UNSIGNED_INT;\r
-                               emitInt(file,buffer,va_arg( ap, int ),16,width,flags,&left);\r
-                               break;\r
-                       case 's':\r
-                               str = (char *)va_arg( ap, int );\r
-\r
-                               if( str == NULL ) {\r
-                                       str = "(null)";\r
-                               }\r
-\r
-                               emitString(file,buffer,str,width,flags,&left);\r
-                               break;\r
-                       default:\r
-                               assert(0); // oops\r
-                               break;\r
-                       }\r
-\r
-               } else {\r
-                       flags = FL_NONE;\r
-                       emitChar(file,buffer,ch,&left);\r
-               }\r
-       }\r
-//     va_end(ap);             // Removed, TODO: Check the va_start/va_end handling (used in calling functions also).\r
-       if(buffer!=0) {\r
-               left = 0;\r
-               emitChar(file,buffer,'\0',&left);\r
-       }\r
-       return 0; // Wrong.. but for now.\r
-}\r
-\r
-#if defined(HOST_TEST)\r
-int main(void) {\r
-       char *ptr = NULL;\r
-       char buff[30];\r
-\r
-       printf("char: %c %c = a B\n", 'a', 66);\r
-\r
-       printf("string: %s = (null)\n", (char *)ptr);\r
-\r
-       printf("string: %s = foobar \n", "foobar");\r
-\r
-       printf("string: %2s = foobar \n", "foobar");\r
-       printf("string: \"%8s\" = \"  foobar\" \n", "foobar");\r
-       /* Left justify */\r
-       printf("string: \"%-8s\" = \"foobar  \" \n", "foobar");\r
-\r
-       printf("decimal:  23 = %d \n", 23);\r
-       printf("hex:     c23 = %x \n", 0xc23);\r
-       printf("hex:    0c23 = %04x \n", 0xc23);\r
-       printf("decimal with blanks:     23 = %6d  \n", 23);\r
-       printf("decimal with zero:   000023 = %06d \n", 23);\r
-\r
-       /* negative and large numbers */\r
-       printf("decimal:  -23 = %d \n", -23);\r
-       printf("decimal:  4294967273 = %u \n", -23);\r
-       printf("decimal:  c0000000   = %x \n", 0xc0000000);\r
-\r
-       printf("decimal:  00c000   = %06x \n", 0xc000);\r
-\r
-       fprintf(_STDOUT, "string: %s = foobar \n", "foobar");\r
-       sprintf(buff, "string: %s = foobar \n", "foobar");\r
-       printf("%s",buff);\r
-\r
-       snprintf(buff,10, "%s\n", "12345678901234567");\r
-       printf("\"123456789\" = \"%s\"\n",buff);\r
-\r
-       snprintf(buff,12, "%s\n", "abcdefghijklmn");\r
-       printf("\"abcdefghijkl\" = \"%s\"\n",buff);\r
-\r
-       return 0;\r
-}\r
-#endif\r
-\r
-\r
+/*
+ * Copyright ArcCore AB
+ *
+ * A simple implementation of all formatted xxprintf functionallity.
+ *
+ * DESIGN CRITERIA:
+ *  - Reentrant
+ *  - Use little stack
+ *
+ *  What you normally would do is to print to a buffer of some kind and then
+ *  call write(). However little stack indicates that we can't place buffers
+ *  on the stack and reentrant tells us that we can't have a static buffer.
+ *  That leaves us with printing characters as it is ready. From a speed
+ *  point of view that is less than optimal, but that the way it's got to be.
+ *  (Could make a 16 long char buffer??)
+ *
+ *  This is just intended to be used as a replacement for newlibs implementation.
+ *  Newlib porting interface have the following API:
+ *    int write(  int fd, char *buf, int nbytes)
+ *
+ *
+ *  Note that puts(), putc() are still the newlib variants....
+ *
+ *    printf()       -> vfprintf(stdout,) -> vsnprintf(buf,)
+ *                                           write()
+ *    vprintf()      -> vfprintf(stdout,) -> vsnprintf(buf,)
+ *                                           write()
+ *    sprintf(buf,)  ->                      vsnprintf(buf,)
+ *    snprintf(buf,) ->                      vsnprintf(buf,)
+ *
+ * IMPLEMENTATION NOTE:
+ *  If printing more than the limit, e.g. using vsnprintf() then
+ *  the emit function will only stop printing, but not interrupted
+ *  (The code will get more complicated that way)
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+
+//#define HOST_TEST    1
+
+#ifdef HOST_TEST
+#define _STDOUT        stdout
+#define _STDIN         stdin
+#define _STDERR        stderr
+#else
+#define _STDOUT        (FILE *)STDOUT_FILENO
+#define _STDINT        STDIN_FILENO
+#define _STDERR        (FILE *)STDERR_FILENO
+#endif
+
+
+int arc_putchar(int fd, int c);
+int print(FILE *file, char **buffer, size_t n, const char *format, va_list ap);
+
+int printf(const char *format, ...) {
+       va_list ap;
+       int rv;
+
+       va_start(ap, format);
+       rv = vfprintf(_STDOUT, format, ap);
+       va_end(ap);
+       return rv;
+}
+
+int fprintf(FILE *file, const char *format, ...) {
+       va_list ap;
+       int rv;
+
+       va_start(ap, format);
+       rv = vfprintf(file, format, ap);
+       va_end(ap);
+       return rv;
+}
+
+int sprintf(char *buffer, const char *format, ...) {
+       va_list ap;
+       int rv;
+
+       va_start(ap, format);
+       rv = vsnprintf(buffer, ~(size_t)0, format, ap);
+       va_end(ap);
+
+       return rv;
+}
+
+int snprintf(char *buffer, size_t n, const char *format, ...) {
+       va_list ap;
+       int rv;
+
+       va_start(ap, format);
+       rv = vsnprintf(buffer, n, format, ap);
+       va_end(ap);
+       return rv;
+}
+
+int vprintf(const char *format, va_list ap) {
+       return vfprintf(_STDOUT, format, ap);
+}
+
+int vsprintf(char *buffer, const char *format, va_list ap) {
+       return vsnprintf(buffer, ~(size_t)0, format, ap);
+}
+
+int vfprintf(FILE *file, const char *format, va_list ap) {
+       int rv;
+       /* Just print to _STDOUT */
+       rv = print(file,NULL,~(size_t)0, format,ap);
+       return rv;
+}
+
+
+int vsnprintf(char *buffer, size_t n, const char *format, va_list ap) {
+       int rv;
+
+       rv = print(NULL, &buffer, n, format,ap);
+       return rv;
+}
+
+
+/*
+ * The integer only counterpart
+ */
+int iprintf(const char *format, ...) {
+       va_list ap;
+       int rv;
+
+       va_start(ap, format);
+       rv = vfprintf(_STDOUT, format, ap);
+       va_end(ap);
+       return rv;
+}
+
+int fiprintf(FILE *file, const char *format, ...) {
+       va_list ap;
+       int rv;
+
+       va_start(ap, format);
+       rv = vfprintf(file, format, ap);
+       va_end(ap);
+       return rv;
+}
+
+
+int siprintf(char *buffer, const char *format, ...) {
+       va_list ap;
+       int rv;
+
+       va_start(ap, format);
+       rv = vsnprintf(buffer, ~(size_t)0, format, ap);
+       va_end(ap);
+
+       return rv;
+}
+
+int sniprintf(char *buffer, size_t n, const char *format, ...) {
+       va_list ap;
+       int rv;
+
+       va_start(ap, format);
+       rv = vsnprintf(buffer, n, format, ap);
+       va_end(ap);
+       return rv;
+}
+
+int viprintf(const char *format, va_list ap) {
+       return vfprintf(_STDOUT, format, ap);
+}
+
+int vsiprintf(char *buffer, const char *format, va_list ap) {
+       return vsnprintf(buffer, ~(size_t)0, format, ap);
+}
+
+
+int vfiprintf(FILE *file, const char *format, va_list ap) {
+       int rv;
+       /* Just print to _STDOUT */
+       rv = print(file,NULL,~(size_t)0, format,ap);
+       return rv;
+}
+
+int vsniprintf(char *buffer, size_t n, const char *format, va_list ap) {
+       int rv;
+
+       rv = print(NULL, &buffer, n, format,ap);
+       return rv;
+}
+
+
+
+/**
+ *
+ * @param file  The file to print to
+ * @param buf   The buffer to print to
+ * @param c            The char to print
+ * @return
+ */
+static inline int emitChar( FILE *file, char **buf, char c, int *left ) {
+       if( (*left) == 1 ) {
+               return 1;
+       }
+       --(*left);
+       if( buf == NULL ) {
+#if HOST_TEST
+               putc(c, _STDOUT);
+               fflush(_STDOUT);
+#else
+               arc_putchar((int)file, c);
+#endif
+       } else {
+               **buf = c;
+               (*buf)++;
+       }
+       return 1;
+}
+
+
+#if defined(HOST_TEST)
+/**
+ * Convert a number to a string
+ *
+ * @param val          The value to convert
+ * @param str          Pointer to a space where to put the string
+ * @param base         The base
+ * @param negative     If negative or not.
+ */
+void xtoa( unsigned long val, char* str, int base, int negative) {
+       int i;
+       char *oStr = str;
+       char c;
+
+       if (negative) {
+               val = -val;
+       }
+
+       if( base < 10 && base > 16 ) {
+               *str = '0';
+               return;
+       }
+    i = 0;
+
+    do {
+      str[i++] = "0123456789abcdef"[ val % base ];
+       } while ((val /= base) > 0);
+
+
+    if (negative) {
+        str[i++] = '-';
+    }
+
+    str[i] = '\0';
+    str = &str[i]-1;
+    while(str > oStr) {
+       c = *str;
+       *str-- = *oStr;
+       *oStr++=c;
+    }
+}
+#else
+extern void xtoa( unsigned long val, char* str, int base, int negative);
+#endif
+
+
+#define FL_NONE                                        (0<<0)
+#define FL_ZERO                                        (1<<1)
+#define FL_HASH                                        (1<<2)
+#define FL_SPACE                               (1<<3)
+#define FL_ALIGN_LEFT                  (1<<4)
+#define FL_TYPE_SIGNED_INT             (1<<5)
+#define FL_TYPE_UNSIGNED_INT   (1<<6)
+
+
+static void emitString( FILE *file, char **buffer, char *string, int width, int flags, int *left) {
+       char pad;
+       char *str = string;
+       int i;
+       int strLen;
+       /* padding: FL_ZERO or normal ' '
+        * align: FL_ALIGN_LEFT (left) or normal (right)
+        */
+       pad = (flags & FL_ZERO) ? '0' : ' ';
+
+
+       if( flags & FL_ALIGN_LEFT ) {
+               for(i=0;str[i]; i++) {
+                       emitChar(file,buffer,str[i],left);
+               }
+
+               /* Pad the rest */
+               for(;i<width;i++) {
+                       emitChar(file,buffer,pad,left);
+               }
+       } else {
+
+               strLen = strlen(string);
+
+               /* Pad first  */
+               if( width > strLen ) {
+                       for(i=0;i<(width-strLen);i++) {
+                               emitChar(file,buffer,pad,left);
+                       }
+               }
+
+               for(i=0;i<strLen; i++) {
+                       emitChar(file,buffer,string[i],left);
+               }
+       }
+}
+
+void emitInt( FILE *file, char **buffer, int val, int base, int width, int flags, int *left )
+{
+       char lBuf[12];  // longest is base 10, 2^32
+       char *str = lBuf;
+
+       if( flags & FL_TYPE_SIGNED_INT ) {
+               xtoa(val,str,base ,(val < 0));
+       } else {
+               xtoa((unsigned)val,str,base ,0);
+       }
+
+       emitString(file,buffer,str,width,flags,left);
+}
+
+#define PRINT_CHAR(_c)  *buffer++= (_c);
+
+
+/**
+ * Write formatted output to an array with a maximum number of characters.
+ *
+ * This is the mother of the formatted print family. The main goal here
+ * is to be very small and memory efficient.
+ *
+ * Support:
+ *   Parameter: None
+ *   Flags    : '-' and '0'
+ *   Width    : Normal padding is supported, '*' is not.
+ *   Precision: None
+ *   Length   : None
+ *   C99      : None
+ *   Type     : d,u,x,s,and c
+ *
+ * @param file    The file descriptor
+ * @param buffer  A pointer to the place to store the output
+ *                If NULL the output is instead
+ * @param n       The maximum number of characters to write
+ * @param format  The format string
+ * @param ap      The va list
+ * @return
+ */
+int print(FILE *file, char **buffer, size_t n, const char *format, va_list ap)
+{
+       char ch;
+       int flags;
+       char *str;
+       int width;
+       int left = n;
+
+       while ( (ch = *format++) ) {
+
+               if (ch == '%') {
+                       ch = *format++;
+
+                       if( ch == '%') {
+                               emitChar(file,buffer,ch,&left);
+                               continue;
+                       }
+
+                       /* Find flags */
+                       switch (ch) {
+                       case '0':
+                               flags = FL_ZERO;
+                               break;
+                       case ' ':
+                               flags = FL_SPACE;
+                               break;
+                       case '-':
+                               flags = FL_ALIGN_LEFT;
+                               break;
+                       default:
+                               /* Not supported or no flag */
+                               flags = FL_NONE;
+                               format--;
+                               break;
+                       }
+
+                       ch = *format++;
+
+                       /* Width */
+                       if( (ch >= '0')  && (ch <= '9') ) {
+                               width = ch -'0';
+                               ch = *format++;
+                       } else {
+                               width = 0;
+                       }
+
+                       /* Find type */
+                       switch (ch) {
+                       case 'c':
+                               emitChar(file,buffer,(char )va_arg( ap, int ),&left);
+                               break;
+                       case 'd':
+                               flags |= FL_TYPE_SIGNED_INT;
+                               emitInt(file,buffer,va_arg( ap, int ),10,width,flags,&left);
+                               break;
+                       case 'u':
+                               flags |= FL_TYPE_UNSIGNED_INT;
+                               emitInt(file,buffer,va_arg( ap, int ),10,width,flags,&left);
+                               break;
+                       case 'x':
+                               flags |= FL_TYPE_UNSIGNED_INT;
+                               emitInt(file,buffer,va_arg( ap, int ),16,width,flags,&left);
+                               break;
+                       case 's':
+                               str = (char *)va_arg( ap, int );
+
+                               if( str == NULL ) {
+                                       str = "(null)";
+                               }
+
+                               emitString(file,buffer,str,width,flags,&left);
+                               break;
+                       default:
+                               assert(0); // oops
+                               break;
+                       }
+
+               } else {
+                       flags = FL_NONE;
+                       emitChar(file,buffer,ch,&left);
+               }
+       }
+//     va_end(ap);             // Removed, TODO: Check the va_start/va_end handling (used in calling functions also).
+       if(buffer!=0) {
+               left = 0;
+               emitChar(file,buffer,'\0',&left);
+       }
+       return 0; // Wrong.. but for now.
+}
+
+#if defined(HOST_TEST)
+int main(void) {
+       char *ptr = NULL;
+       char buff[30];
+
+       printf("char: %c %c = a B\n", 'a', 66);
+
+       printf("string: %s = (null)\n", (char *)ptr);
+
+       printf("string: %s = foobar \n", "foobar");
+
+       printf("string: %2s = foobar \n", "foobar");
+       printf("string: \"%8s\" = \"  foobar\" \n", "foobar");
+       /* Left justify */
+       printf("string: \"%-8s\" = \"foobar  \" \n", "foobar");
+
+       printf("decimal:  23 = %d \n", 23);
+       printf("hex:     c23 = %x \n", 0xc23);
+       printf("hex:    0c23 = %04x \n", 0xc23);
+       printf("decimal with blanks:     23 = %6d  \n", 23);
+       printf("decimal with zero:   000023 = %06d \n", 23);
+
+       /* negative and large numbers */
+       printf("decimal:  -23 = %d \n", -23);
+       printf("decimal:  4294967273 = %u \n", -23);
+       printf("decimal:  c0000000   = %x \n", 0xc0000000);
+
+       printf("decimal:  00c000   = %06x \n", 0xc000);
+
+       fprintf(_STDOUT, "string: %s = foobar \n", "foobar");
+       sprintf(buff, "string: %s = foobar \n", "foobar");
+       printf("%s",buff);
+
+       snprintf(buff,10, "%s\n", "12345678901234567");
+       printf("\"123456789\" = \"%s\"\n",buff);
+
+       snprintf(buff,12, "%s\n", "abcdefghijklmn");
+       printf("\"abcdefghijkl\" = \"%s\"\n",buff);
+
+       return 0;
+}
+#endif
+
+