]> rtime.felk.cvut.cz Git - arc.git/blobdiff - common/printf.c
Merge branch 'mikulka' of git@rtime.felk.cvut.cz:arc into mikulka
[arc.git] / common / printf.c
index 6d434ee0bb7c34cacaf8c6c03473344fd0748b49..be39635ab039acdcbebb8f9952fdf4f5c5818e5f 100644 (file)
-/*
- * 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>
-
-//#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 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;
-}
-
-
-/**
- *
- * @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(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 base, int width, int flags, va_list ap, int *left )
-{
-       char lBuf[12];  // longest is base 10, 2^32
-       char *str = lBuf;
-       int val;
-
-       if( flags & FL_TYPE_SIGNED_INT ) {
-               val = (int )va_arg( ap, int );
-               xtoa(val,str,base ,(val < 0));
-       } else {
-               xtoa((unsigned)va_arg( ap, int ),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,10,width,flags,ap,&left);
-                               break;
-                       case 'u':
-                               flags |= FL_TYPE_UNSIGNED_INT;
-                               emitInt(file,buffer,10,width,flags,ap,&left);
-                               break;
-                       case 'x':
-                               flags |= FL_TYPE_UNSIGNED_INT;
-                               emitInt(file,buffer,16,width,flags,ap,&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);
-       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
-
-
+/*\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
+ *  - ANSI-C and POSIX, streams and POSIX filenumbers.\r
+ *    POSIX file-numbers exist in unistd.h and are only to be used by the porting\r
+ *    newlib interface i.e. newlib_port.c.\r
+ *\r
+ *\r
+ * NEWLIB: File handles vs files\r
+ *   This printf() family of functions does not use newlib at all.\r
+ *   At this point the following can have happend:\r
+ *   1. A call to any of the file functions in newlib have been called.\r
+ *      This then calls a number of functions (sbrk, __sinit(_impure_ptr), etc ).\r
+ *      __sinit(_impure_ptr) initializes the standard files, stdin, stdout, stderr.\r
+ *      file->_file is the actual posix file number (stdin=0, stdout=1, stderr=2)\r
+ *   2. No calls is done to newlib file functions. The impure_data is then empty and\r
+ *      all fields are 0.\r
+ *\r
+ *  Code for checking if the newlib have initialized (or we have explicitly called __sinit(_impure_ptr)\r
+ *     if( _impure_ptr->__sdidinit == 1 ) {\r
+ *       // We use the real filenumber\r
+ *       arc_putchar((int)(file->_file), c);\r
+ *     )\r
+ *\r
+ */\r
+\r
+#include <unistd.h>\r
+#include <stdio.h>\r
+#include <stdarg.h>\r
+#include <assert.h>\r
+#include <string.h>\r
+#if defined(USE_NEWLIB) && defined(__GNUC__)\r
+#include "reent.h"\r
+#endif\r
+//#define HOST_TEST    1\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
+static inline int emitChar( FILE *file, char **buf, char c, int *left );\r
+\r
+int fputs( const char *s, FILE *file ) {\r
+       int left = ~(size_t)0;\r
+       while(*s) {\r
+               emitChar(file,NULL,*s++,&left);\r
+       }\r
+       return 0;\r
+}\r
+\r
+\r
+int printf(const char *format, ...) {\r
+       va_list ap;\r
+       int rv;\r
+\r
+       va_start(ap, format);\r
+       rv = vfprintf((FILE *)STDOUT_FILENO, 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((FILE *)STDOUT_FILENO, 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
+\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
+ * The integer only counterpart\r
+ */\r
+int iprintf(const char *format, ...) __attribute__ ((alias("printf")));\r
+int fiprintf(FILE *file, const char *format, ...) __attribute__ ((alias("fprintf")));\r
+int siprintf(char *buffer, const char *format, ...) __attribute__ ((alias("sprintf")));\r
+int sniprintf(char *buffer, size_t n, const char *format, ...) __attribute__ ((alias("snprintf")));\r
+int viprintf(const char *format, va_list ap) __attribute__ ((alias("vprintf")));\r
+int vsiprintf(char *buffer, const char *format, va_list ap) __attribute__ ((alias("vsprintf")));\r
+int vfiprintf(FILE *file, const char *format, va_list ap) __attribute__ ((alias("vfprintf")));\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
+#if 0\r
+#if defined(USE_NEWLIB) && defined(__GNUC__)\r
+               /* We are trying to print with newlib file descriptor.\r
+                * That's wrong since we are using the POSIX file numbers here instead\r
+                * Check stdout */\r
+               assert( file != _impure_ptr->_stdout );\r
+#endif\r
+#endif\r
+               if( (unsigned )file > 10UL ) {\r
+                       arc_putchar((int)(file->_file), c);\r
+               } else {\r
+                       arc_putchar((int)(file), c);\r
+               }\r
+\r
+#endif /* HOST_TEST */\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
+#define FL_TYPE_POINTER                        (1<<7)\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
+                       if (ch == '0')\r
+                       {\r
+                               flags = FL_ZERO;\r
+                       }\r
+                       else if (ch == ' ')\r
+                       {\r
+                               flags = FL_SPACE;\r
+                       }\r
+                       else if (ch == '-')\r
+                       {\r
+                               flags = FL_ALIGN_LEFT;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Not supported or no flag */\r
+                               flags = FL_NONE;\r
+                               format--;\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
+                       if (ch =='c')\r
+                       {\r
+                               emitChar(file,buffer,(char )va_arg( ap, int ),&left);\r
+                       }\r
+                       else if (ch == 'd')\r
+                       {\r
+                               flags |= FL_TYPE_SIGNED_INT;\r
+                               emitInt(file,buffer,va_arg( ap, int ),10,width,flags,&left);\r
+                       }\r
+                       else if (ch == 'u')\r
+                       {\r
+                               flags |= FL_TYPE_UNSIGNED_INT;\r
+                               emitInt(file,buffer,va_arg( ap, int ),10,width,flags,&left);\r
+                       }\r
+                       else if (ch == 'x')\r
+                       {\r
+                               flags |= FL_TYPE_UNSIGNED_INT;\r
+                               emitInt(file,buffer,va_arg( ap, int ),16,width,flags,&left);\r
+                       }\r
+                       else if (ch == 'p')\r
+                       {\r
+                               flags |= FL_TYPE_POINTER;\r
+                               emitInt(file,buffer,va_arg( ap, int ),16,width,flags,&left);\r
+                       }\r
+                       else if (ch == 's')\r
+                       {\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
+                       }\r
+                       else\r
+                       {\r
+                               assert(0); // oops\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 0\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