X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Fmprintf.c;h=23070a7649768681d2f64bbe7ae45ef46bff7302;hb=eb3e3833904e5db80c7cfcf940ae76a344ce0840;hp=c653425f9af2271fcb11a2d8c47fc197d988e88e;hpb=5eeaff823506ab8a97801d3d7f9cf7f668681b58;p=platform%2Fupstream%2Fcurl.git diff --git a/lib/mprintf.c b/lib/mprintf.c index c653425..23070a7 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -1,17 +1,23 @@ -/**************************************************************************** +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| * - * $Id$ + * Copyright (C) 1999 - 2014, Daniel Stenberg, , et al. * - ************************************************************************* + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * * Purpose: * A merge of Bjorn Reese's format() function and Daniel's dsprintf() @@ -29,54 +35,74 @@ * page at http://daniel.haxx.se/trio/ */ +#include "curl_setup.h" -#include "setup.h" -#include -#include -#include -#include -#include -#include - -#include /* for the curl_off_t type */ +#if defined(DJGPP) && (DJGPP_MINOR < 4) +#undef _MPRINTF_REPLACE /* don't use x_was_used() here */ +#endif #include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + #ifndef SIZEOF_LONG_DOUBLE #define SIZEOF_LONG_DOUBLE 0 #endif +/* + * If SIZEOF_SIZE_T has not been defined, default to the size of long. + */ + +#ifndef SIZEOF_SIZE_T +# define SIZEOF_SIZE_T CURL_SIZEOF_LONG +#endif + #ifdef HAVE_LONGLONG -#define LONG_LONG long long -#define ENABLE_64BIT +# define LONG_LONG_TYPE long long +# define HAVE_LONG_LONG_TYPE #else -#ifdef _MSC_VER -#define LONG_LONG __int64 -#define ENABLE_64BIT +# if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define LONG_LONG_TYPE __int64 +# define HAVE_LONG_LONG_TYPE +# else +# undef LONG_LONG_TYPE +# undef HAVE_LONG_LONG_TYPE +# endif #endif -#endif /* HAVE_LONGLONG */ -/* The last #include file should be: */ -#ifdef CURLDEBUG -#include "memdebug.h" +/* + * Non-ANSI integer extensions + */ + +#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \ + (defined(__WATCOMC__) && defined(__386__)) || \ + (defined(__POCC__) && defined(_MSC_VER)) || \ + (defined(_WIN32_WCE)) || \ + (defined(__MINGW32__)) || \ + (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)) +# define MP_HAVE_INT_EXTENSIONS #endif -#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */ -#define MAX_PARAMETERS 128 /* lame static limit */ +/* + * Max integer data types that mprintf.c is capable + */ -#undef TRUE -#undef FALSE -#undef BOOL -#ifdef __cplusplus -# define TRUE true -# define FALSE false -# define BOOL bool +#ifdef HAVE_LONG_LONG_TYPE +# define mp_intmax_t LONG_LONG_TYPE +# define mp_uintmax_t unsigned LONG_LONG_TYPE #else -# define TRUE ((char)(1 == 1)) -# define FALSE ((char)(0 == 1)) -# define BOOL char +# define mp_intmax_t long +# define mp_uintmax_t unsigned long #endif +#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */ +#define MAX_PARAMETERS 128 /* lame static limit */ + +#ifdef __AMIGA__ +# undef FORMAT_INT +#endif /* Lower-case digits. */ static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; @@ -84,7 +110,13 @@ static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; /* Upper-case digits. */ static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -#define OUTCHAR(x) done+=(stream(x, (FILE *)data)==-1?0:1) +#define OUTCHAR(x) \ + do{ \ + if(stream((unsigned char)(x), (FILE *)data) != -1) \ + done++; \ + else \ + return done; /* return immediately on failure */ \ + } WHILE_FALSE /* Data type to read from the arglist */ typedef enum { @@ -100,7 +132,7 @@ typedef enum { FORMAT_WIDTH /* For internal use */ } FormatType; -/* convertion and display flags */ +/* conversion and display flags */ enum { FLAGS_NEW = 0, FLAGS_SPACE = 1<<0, @@ -128,19 +160,16 @@ enum { typedef struct { FormatType type; int flags; - int width; /* width OR width parameter number */ - int precision; /* precision OR precision parameter number */ + long width; /* width OR width parameter number */ + long precision; /* precision OR precision parameter number */ union { char *str; void *ptr; - long num; -#ifdef ENABLE_64BIT - LONG_LONG lnum; -#endif + union { + mp_intmax_t as_signed; + mp_uintmax_t as_unsigned; + } num; double dnum; -#if 0 /*SIZEOF_LONG_DOUBLE */ - long double ldnum; -#endif } data; } va_stack_t; @@ -154,14 +183,14 @@ struct asprintf { char *buffer; /* allocated buffer */ size_t len; /* length of string */ size_t alloc; /* length of alloc */ + int fail; /* (!= 0) if an alloc has failed and thus + the output is not the complete data */ }; -int curl_msprintf(char *buffer, const char *format, ...); - -static int dprintf_DollarString(char *input, char **end) +static long dprintf_DollarString(char *input, char **end) { int number=0; - while(isdigit((int)*input)) { + while(ISDIGIT(*input)) { number *= 10; number += *input-'0'; input++; @@ -173,112 +202,30 @@ static int dprintf_DollarString(char *input, char **end) return 0; } -static BOOL dprintf_IsQualifierNoDollar(char c) +static bool dprintf_IsQualifierNoDollar(const char *fmt) { - switch (c) { +#if defined(MP_HAVE_INT_EXTENSIONS) + if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) { + return TRUE; + } +#endif + + switch(*fmt) { case '-': case '+': case ' ': case '#': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'h': case 'l': case 'L': case 'z': case 'q': case '*': case 'O': +#if defined(MP_HAVE_INT_EXTENSIONS) + case 'I': +#endif return TRUE; + default: return FALSE; } } -#ifdef DPRINTF_DEBUG2 -int dprintf_Pass1Report(va_stack_t *vto, int max) -{ - int i; - char buffer[128]; - int bit; - int flags; - - for(i=0; i max_param) - max_param = this_param; + if(this_param > max_param) + max_param = this_param; /* * The parameter with number 'i' should be used. Next, we need @@ -330,99 +278,120 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a /* Handle the flags */ - while (dprintf_IsQualifierNoDollar(*fmt)) { - switch (*fmt++) { - case ' ': - flags |= FLAGS_SPACE; - break; - case '+': - flags |= FLAGS_SHOWSIGN; - break; - case '-': - flags |= FLAGS_LEFT; - flags &= ~FLAGS_PAD_NIL; - break; - case '#': - flags |= FLAGS_ALT; - break; - case '.': - flags |= FLAGS_PREC; - if ('*' == *fmt) { - /* The precision is picked from a specified parameter */ - - flags |= FLAGS_PRECPARAM; - fmt++; - param_num++; - - i = dprintf_DollarString(fmt, &fmt); - if (i) - precision = i; - else - precision = param_num; - - if (precision > max_param) - max_param = precision; - } - else { - flags |= FLAGS_PREC; - precision = strtol(fmt, &fmt, 10); - } - break; - case 'h': - flags |= FLAGS_SHORT; - break; - case 'l': - if (flags & FLAGS_LONG) - flags |= FLAGS_LONGLONG; - else - flags |= FLAGS_LONG; - break; - case 'L': - flags |= FLAGS_LONGDOUBLE; - break; - case 'q': - flags |= FLAGS_LONGLONG; - break; - case 'z': + while(dprintf_IsQualifierNoDollar(fmt)) { +#if defined(MP_HAVE_INT_EXTENSIONS) + if(!strncmp(fmt, "I32", 3)) { + flags |= FLAGS_LONG; + fmt += 3; + } + else if(!strncmp(fmt, "I64", 3)) { + flags |= FLAGS_LONGLONG; + fmt += 3; + } + else +#endif + + switch(*fmt++) { + case ' ': + flags |= FLAGS_SPACE; + break; + case '+': + flags |= FLAGS_SHOWSIGN; + break; + case '-': + flags |= FLAGS_LEFT; + flags &= ~FLAGS_PAD_NIL; + break; + case '#': + flags |= FLAGS_ALT; + break; + case '.': + flags |= FLAGS_PREC; + if('*' == *fmt) { + /* The precision is picked from a specified parameter */ + + flags |= FLAGS_PRECPARAM; + fmt++; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + precision = i; + else + precision = param_num; + + if(precision > max_param) + max_param = precision; + } + else { + flags |= FLAGS_PREC; + precision = strtol(fmt, &fmt, 10); + } + break; + case 'h': + flags |= FLAGS_SHORT; + break; +#if defined(MP_HAVE_INT_EXTENSIONS) + case 'I': +#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; +#endif + case 'l': + if(flags & FLAGS_LONG) + flags |= FLAGS_LONGLONG; + else + flags |= FLAGS_LONG; + break; + case 'L': + flags |= FLAGS_LONGDOUBLE; + break; + case 'q': + flags |= FLAGS_LONGLONG; + break; + case 'z': /* the code below generates a warning if -Wunreachable-code is used */ - if (sizeof(size_t) > sizeof(unsigned long)) - flags |= FLAGS_LONGLONG; - if (sizeof(size_t) > sizeof(unsigned int)) - flags |= FLAGS_LONG; - break; - - case 'O': -#if SIZEOF_CURL_OFF_T > 4 +#if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG) flags |= FLAGS_LONGLONG; #else flags |= FLAGS_LONG; #endif - break; - case '0': - if (!(flags & FLAGS_LEFT)) - flags |= FLAGS_PAD_NIL; - /* FALLTHROUGH */ - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - flags |= FLAGS_WIDTH; - width = strtol(fmt-1, &fmt, 10); - break; - case '*': /* Special case */ - flags |= FLAGS_WIDTHPARAM; - param_num++; - - i = dprintf_DollarString(fmt, &fmt); - if(i) - width = i; - else - width = param_num; - if(width > max_param) - max_param=width; - break; - default: - break; - } + break; + case 'O': +#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; + case '0': + if(!(flags & FLAGS_LEFT)) + flags |= FLAGS_PAD_NIL; + /* FALLTHROUGH */ + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + flags |= FLAGS_WIDTH; + width = strtol(fmt-1, &fmt, 10); + break; + case '*': /* Special case */ + flags |= FLAGS_WIDTHPARAM; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + width = i; + else + width = param_num; + if(width > max_param) + max_param=width; + break; + default: + break; + } } /* switch */ /* Handle the specifier */ @@ -431,141 +400,152 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a switch (*fmt) { case 'S': - flags |= FLAGS_ALT; - /* FALLTHROUGH */ + flags |= FLAGS_ALT; + /* FALLTHROUGH */ case 's': - vto[i].type = FORMAT_STRING; - break; + vto[i].type = FORMAT_STRING; + break; case 'n': - vto[i].type = FORMAT_INTPTR; - break; + vto[i].type = FORMAT_INTPTR; + break; case 'p': - vto[i].type = FORMAT_PTR; - break; + vto[i].type = FORMAT_PTR; + break; case 'd': case 'i': - vto[i].type = FORMAT_INT; - break; + vto[i].type = FORMAT_INT; + break; case 'u': - vto[i].type = FORMAT_INT; - flags |= FLAGS_UNSIGNED; - break; + vto[i].type = FORMAT_INT; + flags |= FLAGS_UNSIGNED; + break; case 'o': - vto[i].type = FORMAT_INT; - flags |= FLAGS_OCTAL; - break; + vto[i].type = FORMAT_INT; + flags |= FLAGS_OCTAL; + break; case 'x': - vto[i].type = FORMAT_INT; - flags |= FLAGS_HEX; - break; + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UNSIGNED; + break; case 'X': - vto[i].type = FORMAT_INT; - flags |= FLAGS_HEX|FLAGS_UPPER; - break; + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED; + break; case 'c': - vto[i].type = FORMAT_INT; - flags |= FLAGS_CHAR; - break; + vto[i].type = FORMAT_INT; + flags |= FLAGS_CHAR; + break; case 'f': - vto[i].type = FORMAT_DOUBLE; - break; - case 'e': case 'E': - vto[i].type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATE| (('E' == *fmt)?FLAGS_UPPER:0); - break; - case 'g': case 'G': - vto[i].type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATG| (('G' == *fmt)?FLAGS_UPPER:0); - break; + vto[i].type = FORMAT_DOUBLE; + break; + case 'e': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE; + break; + case 'E': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE|FLAGS_UPPER; + break; + case 'g': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG; + break; + case 'G': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG|FLAGS_UPPER; + break; default: - vto[i].type = FORMAT_UNKNOWN; - break; + vto[i].type = FORMAT_UNKNOWN; + break; } /* switch */ vto[i].flags = flags; vto[i].width = width; vto[i].precision = precision; - - if (flags & FLAGS_WIDTHPARAM) { - /* we have the width specified from a parameter, so we make that - parameter's info setup properly */ - vto[i].width = width - 1; - i = width - 1; - vto[i].type = FORMAT_WIDTH; - vto[i].flags = FLAGS_NEW; - vto[i].precision = vto[i].width = 0; /* can't use width or precision - of width! */ + + if(flags & FLAGS_WIDTHPARAM) { + /* we have the width specified from a parameter, so we make that + parameter's info setup properly */ + vto[i].width = width - 1; + i = width - 1; + vto[i].type = FORMAT_WIDTH; + vto[i].flags = FLAGS_NEW; + vto[i].precision = vto[i].width = 0; /* can't use width or precision + of width! */ } - if (flags & FLAGS_PRECPARAM) { - /* we have the precision specified from a parameter, so we make that - parameter's info setup properly */ - vto[i].precision = precision - 1; - i = precision - 1; - vto[i].type = FORMAT_WIDTH; - vto[i].flags = FLAGS_NEW; - vto[i].precision = vto[i].width = 0; /* can't use width or precision - of width! */ + if(flags & FLAGS_PRECPARAM) { + /* we have the precision specified from a parameter, so we make that + parameter's info setup properly */ + vto[i].precision = precision - 1; + i = precision - 1; + vto[i].type = FORMAT_WIDTH; + vto[i].flags = FLAGS_NEW; + vto[i].precision = vto[i].width = 0; /* can't use width or precision + of width! */ } *endpos++ = fmt + 1; /* end of this sequence */ } } -#ifdef DPRINTF_DEBUG2 - dprintf_Pass1Report(vto, max_param); -#endif - /* Read the arg list parameters into our data list */ - for (i=0; i$ sequence */ param=dprintf_DollarString(f, &f); @@ -660,305 +638,304 @@ static int dprintf_formatf( param = param_num; else --param; - + param_num++; /* increase this always to allow "%2$s %1$s %s" and then the - third %s will pick the 3rd argument */ + third %s will pick the 3rd argument */ p = &vto[param]; /* pick up the specified width */ if(p->flags & FLAGS_WIDTHPARAM) - width = vto[p->width].data.num; + width = (long)vto[p->width].data.num.as_signed; else width = p->width; /* pick up the specified precision */ - if(p->flags & FLAGS_PRECPARAM) - prec = vto[p->precision].data.num; + if(p->flags & FLAGS_PRECPARAM) { + prec = (long)vto[p->precision].data.num.as_signed; + param_num++; /* since the precision is extraced from a parameter, we + must skip that to get to the next one properly */ + } else if(p->flags & FLAGS_PREC) prec = p->precision; else prec = -1; - alt = p->flags & FLAGS_ALT; - + is_alt = (p->flags & FLAGS_ALT) ? 1 : 0; + switch (p->type) { case FORMAT_INT: - num = p->data.num; + num = p->data.num.as_unsigned; if(p->flags & FLAGS_CHAR) { - /* Character. */ - if (!(p->flags & FLAGS_LEFT)) - while (--width > 0) - OUTCHAR(' '); - OUTCHAR((char) num); - if (p->flags & FLAGS_LEFT) - while (--width > 0) - OUTCHAR(' '); - break; - } - if(p->flags & FLAGS_UNSIGNED) { - /* Decimal unsigned integer. */ - base = 10; - goto unsigned_number; + /* Character. */ + if(!(p->flags & FLAGS_LEFT)) + while(--width > 0) + OUTCHAR(' '); + OUTCHAR((char) num); + if(p->flags & FLAGS_LEFT) + while(--width > 0) + OUTCHAR(' '); + break; } if(p->flags & FLAGS_OCTAL) { - /* Octal unsigned integer. */ - base = 8; - goto unsigned_number; + /* Octal unsigned integer. */ + base = 8; + goto unsigned_number; } - if(p->flags & FLAGS_HEX) { - /* Hexadecimal unsigned integer. */ + else if(p->flags & FLAGS_HEX) { + /* Hexadecimal unsigned integer. */ - digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; - base = 16; - goto unsigned_number; + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + base = 16; + goto unsigned_number; + } + else if(p->flags & FLAGS_UNSIGNED) { + /* Decimal unsigned integer. */ + base = 10; + goto unsigned_number; } /* Decimal integer. */ base = 10; -#ifdef ENABLE_64BIT - if(p->flags & FLAGS_LONGLONG) { - /* long long */ - is_neg = p->data.lnum < 0; - num = is_neg ? (- p->data.lnum) : p->data.lnum; - } - else -#endif - { - signed_num = (long) num; - - is_neg = signed_num < 0; - num = is_neg ? (- signed_num) : signed_num; + is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0; + if(is_neg) { + /* signed_num might fail to hold absolute negative minimum by 1 */ + signed_num = p->data.num.as_signed + (mp_intmax_t)1; + signed_num = -signed_num; + num = (mp_uintmax_t)signed_num; + num += (mp_uintmax_t)1; } + goto number; - - unsigned_number:; + + unsigned_number: /* Unsigned number of base BASE. */ is_neg = 0; - - number:; + + number: /* Number of base BASE. */ { - char *workend = &work[sizeof(work) - 1]; - register char *w; - - /* Supply a default precision if none was given. */ - if (prec == -1) - prec = 1; - - /* Put the number in WORK. */ - w = workend; - while (num > 0) { - *w-- = digits[num % base]; - num /= base; - } - width -= workend - w; - prec -= workend - w; - - if (alt && base == 8 && prec <= 0) { - *w-- = '0'; - --width; - } - - if (prec > 0) { - width -= prec; - while (prec-- > 0) - *w-- = '0'; - } - - if (alt && base == 16) - width -= 2; - - if (is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE)) - --width; - - if (!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL)) - while (width-- > 0) - OUTCHAR(' '); - - if (is_neg) - OUTCHAR('-'); - else if (p->flags & FLAGS_SHOWSIGN) - OUTCHAR('+'); - else if (p->flags & FLAGS_SPACE) - OUTCHAR(' '); - - if (alt && base == 16) { - OUTCHAR('0'); - if(p->flags & FLAGS_UPPER) - OUTCHAR('X'); - else - OUTCHAR('x'); - } - - if (!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL)) - while (width-- > 0) - OUTCHAR('0'); - - /* Write the number. */ - while (++w <= workend) { - OUTCHAR(*w); - } - - if (p->flags & FLAGS_LEFT) - while (width-- > 0) - OUTCHAR(' '); + char *workend = &work[sizeof(work) - 1]; + char *w; + + /* Supply a default precision if none was given. */ + if(prec == -1) + prec = 1; + + /* Put the number in WORK. */ + w = workend; + while(num > 0) { + *w-- = digits[num % base]; + num /= base; + } + width -= (long)(workend - w); + prec -= (long)(workend - w); + + if(is_alt && base == 8 && prec <= 0) { + *w-- = '0'; + --width; + } + + if(prec > 0) { + width -= prec; + while(prec-- > 0) + *w-- = '0'; + } + + if(is_alt && base == 16) + width -= 2; + + if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE)) + --width; + + if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL)) + while(width-- > 0) + OUTCHAR(' '); + + if(is_neg) + OUTCHAR('-'); + else if(p->flags & FLAGS_SHOWSIGN) + OUTCHAR('+'); + else if(p->flags & FLAGS_SPACE) + OUTCHAR(' '); + + if(is_alt && base == 16) { + OUTCHAR('0'); + if(p->flags & FLAGS_UPPER) + OUTCHAR('X'); + else + OUTCHAR('x'); + } + + if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL)) + while(width-- > 0) + OUTCHAR('0'); + + /* Write the number. */ + while(++w <= workend) { + OUTCHAR(*w); + } + + if(p->flags & FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); } break; - + case FORMAT_STRING: - /* String. */ + /* String. */ { - static char null[] = "(nil)"; - char *str; - size_t len; - - str = (char *) p->data.str; - if ( str == NULL) { - /* Write null[] if there's space. */ - if (prec == -1 || prec >= (long) sizeof(null) - 1) { - str = null; - len = sizeof(null) - 1; - /* Disable quotes around (nil) */ - p->flags &= (~FLAGS_ALT); - } - else { - str = (char *)""; - len = 0; - } - } - else - len = strlen(str); - - if (prec != -1 && (size_t) prec < len) - len = prec; - width -= len; - - if (p->flags & FLAGS_ALT) - OUTCHAR('"'); - - if (!(p->flags&FLAGS_LEFT)) - while (width-- > 0) - OUTCHAR(' '); - - while (len-- > 0) - OUTCHAR(*str++); - if (p->flags&FLAGS_LEFT) - while (width-- > 0) - OUTCHAR(' '); - - if (p->flags & FLAGS_ALT) - OUTCHAR('"'); + static const char null[] = "(nil)"; + const char *str; + size_t len; + + str = (char *) p->data.str; + if(str == NULL) { + /* Write null[] if there's space. */ + if(prec == -1 || prec >= (long) sizeof(null) - 1) { + str = null; + len = sizeof(null) - 1; + /* Disable quotes around (nil) */ + p->flags &= (~FLAGS_ALT); + } + else { + str = ""; + len = 0; + } + } + else if(prec != -1) + len = (size_t)prec; + else + len = strlen(str); + + width -= (long)len; + + if(p->flags & FLAGS_ALT) + OUTCHAR('"'); + + if(!(p->flags&FLAGS_LEFT)) + while(width-- > 0) + OUTCHAR(' '); + + while((len-- > 0) && *str) + OUTCHAR(*str++); + if(p->flags&FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + + if(p->flags & FLAGS_ALT) + OUTCHAR('"'); } break; - + case FORMAT_PTR: /* Generic pointer. */ { - void *ptr; - ptr = (void *) p->data.ptr; - if (ptr != NULL) { - /* If the pointer is not NULL, write it as a %#x spec. */ - base = 16; - digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; - alt = 1; - num = (unsigned long) ptr; - is_neg = 0; - goto number; - } - else { - /* Write "(nil)" for a nil pointer. */ - static char strnil[] = "(nil)"; - register char *point; - - width -= sizeof(strnil) - 1; - if (p->flags & FLAGS_LEFT) - while (width-- > 0) - OUTCHAR(' '); - for (point = strnil; *point != '\0'; ++point) - OUTCHAR(*point); - if (! (p->flags & FLAGS_LEFT)) - while (width-- > 0) - OUTCHAR(' '); - } + void *ptr; + ptr = (void *) p->data.ptr; + if(ptr != NULL) { + /* If the pointer is not NULL, write it as a %#x spec. */ + base = 16; + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + is_alt = 1; + num = (size_t) ptr; + is_neg = 0; + goto number; + } + else { + /* Write "(nil)" for a nil pointer. */ + static const char strnil[] = "(nil)"; + const char *point; + + width -= (long)(sizeof(strnil) - 1); + if(p->flags & FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + for(point = strnil; *point != '\0'; ++point) + OUTCHAR(*point); + if(! (p->flags & FLAGS_LEFT)) + while(width-- > 0) + OUTCHAR(' '); + } } break; case FORMAT_DOUBLE: { - char formatbuf[32]="%"; - char *fptr; - - width = -1; - if (p->flags & FLAGS_WIDTH) - width = p->width; - else if (p->flags & FLAGS_WIDTHPARAM) - width = vto[p->width].data.num; - - prec = -1; - if (p->flags & FLAGS_PREC) - prec = p->precision; - else if (p->flags & FLAGS_PRECPARAM) - prec = vto[p->precision].data.num; - - if (p->flags & FLAGS_LEFT) - strcat(formatbuf, "-"); - if (p->flags & FLAGS_SHOWSIGN) - strcat(formatbuf, "+"); - if (p->flags & FLAGS_SPACE) - strcat(formatbuf, " "); - if (p->flags & FLAGS_ALT) - strcat(formatbuf, "#"); - - fptr=&formatbuf[strlen(formatbuf)]; - - if(width >= 0) { - /* RECURSIVE USAGE */ - fptr += curl_msprintf(fptr, "%ld", width); - } - if(prec >= 0) { - /* RECURSIVE USAGE */ - fptr += curl_msprintf(fptr, ".%ld", prec); - } - if (p->flags & FLAGS_LONG) - strcat(fptr, "l"); - - if (p->flags & FLAGS_FLOATE) - strcat(fptr, p->flags&FLAGS_UPPER?"E":"e"); - else if (p->flags & FLAGS_FLOATG) - strcat(fptr, (p->flags & FLAGS_UPPER) ? "G" : "g"); - else - strcat(fptr, "f"); - - /* NOTE NOTE NOTE!! Not all sprintf() implementations returns number - of output characters */ -#if 0 /*SIZEOF_LONG_DOUBLE*/ - if (p->flags & FLAGS_LONG) - /* This is for support of the 'long double' type */ - (sprintf)(work, formatbuf, p->data.ldnum); - else -#endif - (sprintf)(work, formatbuf, p->data.dnum); - - for(fptr=work; *fptr; fptr++) - OUTCHAR(*fptr); + char formatbuf[32]="%"; + char *fptr = &formatbuf[1]; + size_t left = sizeof(formatbuf)-strlen(formatbuf); + int len; + + width = -1; + if(p->flags & FLAGS_WIDTH) + width = p->width; + else if(p->flags & FLAGS_WIDTHPARAM) + width = (long)vto[p->width].data.num.as_signed; + + prec = -1; + if(p->flags & FLAGS_PREC) + prec = p->precision; + else if(p->flags & FLAGS_PRECPARAM) + prec = (long)vto[p->precision].data.num.as_signed; + + if(p->flags & FLAGS_LEFT) + *fptr++ = '-'; + if(p->flags & FLAGS_SHOWSIGN) + *fptr++ = '+'; + if(p->flags & FLAGS_SPACE) + *fptr++ = ' '; + if(p->flags & FLAGS_ALT) + *fptr++ = '#'; + + *fptr = 0; + + if(width >= 0) { + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, "%ld", width); + fptr += len; + left -= len; + } + if(prec >= 0) { + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, ".%ld", prec); + fptr += len; + } + if(p->flags & FLAGS_LONG) + *fptr++ = 'l'; + + if(p->flags & FLAGS_FLOATE) + *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e'); + else if(p->flags & FLAGS_FLOATG) + *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g'); + else + *fptr++ = 'f'; + + *fptr = 0; /* and a final zero termination */ + + /* NOTE NOTE NOTE!! Not all sprintf implementations return number of + output characters */ + (sprintf)(work, formatbuf, p->data.dnum); + + for(fptr=work; *fptr; fptr++) + OUTCHAR(*fptr); } break; case FORMAT_INTPTR: /* Answer the count of characters written. */ -#ifdef ENABLE_64BIT - if (p->flags & FLAGS_LONGLONG) - *(LONG_LONG *) p->data.ptr = (LONG_LONG)done; +#ifdef HAVE_LONG_LONG_TYPE + if(p->flags & FLAGS_LONGLONG) + *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done; else #endif - if (p->flags & FLAGS_LONG) - *(long *) p->data.ptr = (long)done; - else if (!(p->flags & FLAGS_SHORT)) - *(int *) p->data.ptr = (int)done; + if(p->flags & FLAGS_LONG) + *(long *) p->data.ptr = (long)done; + else if(!(p->flags & FLAGS_SHORT)) + *(int *) p->data.ptr = (int)done; else - *(short *) p->data.ptr = (short)done; + *(short *) p->data.ptr = (short)done; break; default: @@ -974,13 +951,14 @@ static int dprintf_formatf( static int addbyter(int output, FILE *data) { struct nsprintf *infop=(struct nsprintf *)data; - + unsigned char outc = (unsigned char)output; + if(infop->length < infop->max) { /* only do this if we haven't reached max length yet */ - infop->buffer[0] = (char)output; /* store */ + infop->buffer[0] = outc; /* store */ infop->buffer++; /* increase pointer */ infop->length++; /* we are now one byte larger */ - return output; /* fputc() returns like this on success */ + return outc; /* fputc() returns like this on success */ } return -1; } @@ -1021,31 +999,35 @@ int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...) static int alloc_addbyter(int output, FILE *data) { struct asprintf *infop=(struct asprintf *)data; - + unsigned char outc = (unsigned char)output; + if(!infop->buffer) { - infop->buffer=(char *)malloc(32); - if(!infop->buffer) + infop->buffer = malloc(32); + if(!infop->buffer) { + infop->fail = 1; return -1; /* fail */ + } infop->alloc = 32; infop->len =0; } else if(infop->len+1 >= infop->alloc) { char *newptr; - newptr = (char *)realloc(infop->buffer, infop->alloc*2); + newptr = realloc(infop->buffer, infop->alloc*2); if(!newptr) { - return -1; + infop->fail = 1; + return -1; /* fail */ } infop->buffer = newptr; infop->alloc *= 2; } - infop->buffer[ infop->len ] = output; + infop->buffer[ infop->len ] = outc; infop->len++; - return output; /* fputc() returns like this on success */ + return outc; /* fputc() returns like this on success */ } char *curl_maprintf(const char *format, ...) @@ -1057,11 +1039,12 @@ char *curl_maprintf(const char *format, ...) info.buffer = NULL; info.len = 0; info.alloc = 0; + info.fail = 0; va_start(ap_save, format); retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); va_end(ap_save); - if(-1 == retcode) { + if((-1 == retcode) || info.fail) { if(info.alloc) free(info.buffer); return NULL; @@ -1082,9 +1065,10 @@ char *curl_mvaprintf(const char *format, va_list ap_save) info.buffer = NULL; info.len = 0; info.alloc = 0; + info.fail = 0; retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); - if(-1 == retcode) { + if((-1 == retcode) || info.fail) { if(info.alloc) free(info.buffer); return NULL; @@ -1101,9 +1085,10 @@ char *curl_mvaprintf(const char *format, va_list ap_save) static int storebuffer(int output, FILE *data) { char **buffer = (char **)data; - **buffer = (char)output; + unsigned char outc = (unsigned char)output; + **buffer = outc; (*buffer)++; - return output; /* act like fputc() ! */ + return outc; /* act like fputc() ! */ } int curl_msprintf(char *buffer, const char *format, ...) @@ -1117,15 +1102,12 @@ int curl_msprintf(char *buffer, const char *format, ...) return retcode; } -#ifndef WIN32 /* not needed on win32 */ -extern int fputc(int, FILE *); -#endif - int curl_mprintf(const char *format, ...) { int retcode; va_list ap_save; /* argument pointer */ va_start(ap_save, format); + retcode = dprintf_formatf(stdout, fputc, format, ap_save); va_end(ap_save); return retcode; @@ -1158,43 +1140,3 @@ int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save) { return dprintf_formatf(whereto, fputc, format, ap_save); } - -#ifdef DPRINTF_DEBUG -int main() -{ - char buffer[129]; - char *ptr; -#ifdef ENABLE_64BIT - LONG_LONG hullo; - dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo, "stenberg", 65); -#endif - - mprintf("%3d %5d\n", 10, 1998); - - ptr=maprintf("test this then baby %s%s%s%s%s%s %d %d %d loser baby get a hit in yer face now!", "", "pretty long string pretty long string pretty long string pretty long string pretty long string", "/", "/", "/", "pretty long string", 1998, 1999, 2001); - - puts(ptr); - - memset(ptr, 55, strlen(ptr)+1); - - free(ptr); - -#if 1 - mprintf(buffer, "%s %s %d", "daniel", "stenberg", 19988); - puts(buffer); - - mfprintf(stderr, "%s %#08x\n", "dummy", 65); - - printf("%s %#08x\n", "dummy", 65); - { - double tryout = 3.14156592; - mprintf(buffer, "%.2g %G %f %e %E", tryout, tryout, tryout, tryout, tryout); - puts(buffer); - printf("%.2g %G %f %e %E\n", tryout, tryout, tryout, tryout, tryout); - } -#endif - - return 0; -} - -#endif