diff options
author | Manuel Novoa III <mjn3@codepoet.org> | 2001-01-27 23:50:02 +0000 |
---|---|---|
committer | Manuel Novoa III <mjn3@codepoet.org> | 2001-01-27 23:50:02 +0000 |
commit | fdfb85cbcaae9dc06e6576235f120fdcf8f88066 (patch) | |
tree | 292fb0df74cf3ca718798b9434bd49bce75f48c8 | |
parent | 8b15b45ecc58d84f9d4a6bd91fc0675b446103b8 (diff) |
Fixed (hopefully) 0-pad bug in printf. Added asprintf function. Reworked
the *s*printf functions to no longer use a static fake file.
-rw-r--r-- | include/stdio.h | 4 | ||||
-rw-r--r-- | libc/stdio/Makefile | 2 | ||||
-rw-r--r-- | libc/stdio/printf.c | 100 |
3 files changed, 75 insertions, 31 deletions
diff --git a/include/stdio.h b/include/stdio.h index 61c178308..945e353a9 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -210,6 +210,10 @@ extern int printf __P ((__const char *__restrict __format, ...)); extern int sprintf __P ((char *__restrict __s, __const char *__restrict __format, ...)); +/* Write formatted output to a buffer S dynamically allocated by asprintf. */ +extern int asprintf __P ((char **__restrict __s, + __const char *__restrict __format, ...)); + /* Write formatted output to S from argument list ARG. */ extern int vfprintf __P ((FILE *__restrict __s, __const char *__restrict __format, diff --git a/libc/stdio/Makefile b/libc/stdio/Makefile index 5314af07b..3801fce2c 100644 --- a/libc/stdio/Makefile +++ b/libc/stdio/Makefile @@ -32,7 +32,7 @@ MOBJ=_stdio_init.o fputc.o fgetc.o fflush.o fgets.o gets.o fputs.o \ MSRC2=printf.c MOBJ2=printf.o sprintf.o fprintf.o vprintf.o vsprintf.o vfprintf.o snprintf.o \ - vsnprintf.o _sprintf_fake_file.o vfnprintf.o + vsnprintf.o asprintf.o vfnprintf.o MSRC3=scanf.c MOBJ3=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o diff --git a/libc/stdio/printf.c b/libc/stdio/printf.c index c1271d72d..8d62278ff 100644 --- a/libc/stdio/printf.c +++ b/libc/stdio/printf.c @@ -56,6 +56,18 @@ * Modified sprintf, snprintf, vsprintf, vsnprintf to share on fake-file. */ +/* + * Manuel Novoa III Jan 2000 + * + * Removed fake file from *s*printf functions because of possible problems + * if called recursively. Instead, have sprintf, snprintf, and vsprintf + * call vsnprintf which allocates a fake file on the stack. + * + * Added asprintf. + * + * Hopefully fixed 0-pad prefixing bug. + */ + /*****************************************************************************/ /* OPTIONS */ /*****************************************************************************/ @@ -90,6 +102,8 @@ /* * Use fputc instead of macro putc. Slower but saves about 36 bytes. + * WARNING! This may cause problems the the *s*printf functions! + * Don't enable at this time. Manuel */ #define WANT_FPUTC 0 @@ -124,15 +138,6 @@ extern int vfnprintf(FILE * op, size_t max_size, register __const char *fmt, register va_list ap); -extern FILE __sprintf_fake_file[1]; - -#ifdef L__sprintf_fake_file -FILE __sprintf_fake_file[1] = { - {0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1, - _IOFBF | __MODE_WRITE} -}; -#endif - #ifdef L_printf int printf(const char *fmt, ...) { @@ -146,6 +151,34 @@ int printf(const char *fmt, ...) } #endif +#ifdef L_asprintf +int asprintf(char **app, const char *fmt, ...) +{ + va_list ptr; + int rv, i; + char *p; /* unitialized warning is ok here */ + /* + * First iteration - find out size of buffer required and allocate it. + * Second iteration - actually produce output. + */ + rv = 0; + for (i=0 ; i<2 ; i++) { + va_strt(ptr, fmt); + rv = vsnprintf(p, rv, fmt, ptr); + va_end(ptr); + + if (i==0) { /* first time through so */ + p = malloc(++rv); /* allocate the buffer */ + *app = p; + if (!p) { + return -1; + } + } + } + return rv; +} +#endif + #ifdef L_sprintf int sprintf(char *sp, const char *fmt, ...) { @@ -153,10 +186,8 @@ int sprintf(char *sp, const char *fmt, ...) int rv; va_strt(ptr, fmt); - __sprintf_fake_file->bufpos = sp; - rv = vfnprintf(__sprintf_fake_file, -1, fmt, ptr); + rv = vsnprintf(sp, -1, fmt, ptr); va_end(ptr); - *(__sprintf_fake_file->bufpos) = 0; return rv; } #endif @@ -169,10 +200,8 @@ int snprintf(char *sp, size_t size, const char *fmt, ...) int rv; va_strt(ptr, fmt); - __sprintf_fake_file->bufpos = sp; - rv = vfnprintf(__sprintf_fake_file, size, fmt, ptr); + rv = vsnprintf(sp, size, fmt, ptr); va_end(ptr); - *(__sprintf_fake_file->bufpos) = 0; return rv; } #endif @@ -200,12 +229,7 @@ int vprintf(const char *fmt, va_list ap) #ifdef L_vsprintf int vsprintf(char *sp, __const char *fmt, va_list ap) { - int rv; - - __sprintf_fake_file->bufpos = sp; - rv = vfnprintf(__sprintf_fake_file, -1, fmt, ap); - *(__sprintf_fake_file->bufpos) = 0; - return rv; + return vsnprintf(sp, -1, fmt, ap); } #endif @@ -213,10 +237,23 @@ int vsprintf(char *sp, __const char *fmt, va_list ap) int vsnprintf(char *sp, size_t size, __const char *fmt, va_list ap) { int rv; +#if 0 + FILE f = {0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1, + _IOFBF | __MODE_WRITE}; +#else + /* As we're only using the putc macro in vfnprintf, we don't need to + initialize all FILE fields. */ + FILE f; + + f.bufwrite = (char *) (unsigned) -1; + f.bufpos = sp; + f.mode = _IOFBF | __MODE_WRITE; +#endif - __sprintf_fake_file->bufpos = sp; - rv = vfnprintf(__sprintf_fake_file, size, fmt, ap); - *(__sprintf_fake_file->bufpos) = 0; + rv = vfnprintf(&f, size, fmt, ap); + if (size) { + *(f.bufpos) = 0; + } return rv; } #endif @@ -523,7 +560,7 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap) /* right padding || left padding */ if ((!len && !preci) || (width && !flag[FLAG_MINUS_LJUSTIFY])) { - ch = ' '; + ch = flag[FLAG_0_PAD]; --width; } else if (flag[FLAG_PLUS]) { ch = flag[FLAG_PLUS]; /* sign */ @@ -533,12 +570,15 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap) flag[FLAG_PLUS] = '\0'; } --len; - } else if (preci) { - ch = '0'; - --preci; } else { - ch = *p++; /* main field */ - --len; + flag[FLAG_0_PAD]=' '; + if (preci) { + ch = '0'; + --preci; + } else { + ch = *p++; /* main field */ + --len; + } } if (++cnt < max_size) { |