-/*
- * 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 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