00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "curl_setup.h"
00039 #include <curl/mprintf.h>
00040
00041 #include "curl_memory.h"
00042
00043 #include "memdebug.h"
00044
00045 #ifndef SIZEOF_LONG_DOUBLE
00046 #define SIZEOF_LONG_DOUBLE 0
00047 #endif
00048
00049
00050
00051
00052
00053 #ifndef SIZEOF_SIZE_T
00054 # define SIZEOF_SIZE_T CURL_SIZEOF_LONG
00055 #endif
00056
00057 #ifdef HAVE_LONGLONG
00058 # define LONG_LONG_TYPE long long
00059 # define HAVE_LONG_LONG_TYPE
00060 #else
00061 # if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
00062 # define LONG_LONG_TYPE __int64
00063 # define HAVE_LONG_LONG_TYPE
00064 # else
00065 # undef LONG_LONG_TYPE
00066 # undef HAVE_LONG_LONG_TYPE
00067 # endif
00068 #endif
00069
00070
00071
00072
00073
00074 #if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \
00075 (defined(__WATCOMC__) && defined(__386__)) || \
00076 (defined(__POCC__) && defined(_MSC_VER)) || \
00077 (defined(_WIN32_WCE)) || \
00078 (defined(__MINGW32__)) || \
00079 (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
00080 # define MP_HAVE_INT_EXTENSIONS
00081 #endif
00082
00083
00084
00085
00086
00087 #ifdef HAVE_LONG_LONG_TYPE
00088 # define mp_intmax_t LONG_LONG_TYPE
00089 # define mp_uintmax_t unsigned LONG_LONG_TYPE
00090 #else
00091 # define mp_intmax_t long
00092 # define mp_uintmax_t unsigned long
00093 #endif
00094
00095 #define BUFFSIZE 326
00096
00097 #define MAX_PARAMETERS 128
00098
00099 #ifdef __AMIGA__
00100 # undef FORMAT_INT
00101 #endif
00102
00103
00104 static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
00105
00106
00107 static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00108
00109 #define OUTCHAR(x) \
00110 do{ \
00111 if(stream((unsigned char)(x), (FILE *)data) != -1) \
00112 done++; \
00113 else \
00114 return done; \
00115 } WHILE_FALSE
00116
00117
00118 typedef enum {
00119 FORMAT_UNKNOWN = 0,
00120 FORMAT_STRING,
00121 FORMAT_PTR,
00122 FORMAT_INT,
00123 FORMAT_INTPTR,
00124 FORMAT_LONG,
00125 FORMAT_LONGLONG,
00126 FORMAT_DOUBLE,
00127 FORMAT_LONGDOUBLE,
00128 FORMAT_WIDTH
00129 } FormatType;
00130
00131
00132 enum {
00133 FLAGS_NEW = 0,
00134 FLAGS_SPACE = 1<<0,
00135 FLAGS_SHOWSIGN = 1<<1,
00136 FLAGS_LEFT = 1<<2,
00137 FLAGS_ALT = 1<<3,
00138 FLAGS_SHORT = 1<<4,
00139 FLAGS_LONG = 1<<5,
00140 FLAGS_LONGLONG = 1<<6,
00141 FLAGS_LONGDOUBLE = 1<<7,
00142 FLAGS_PAD_NIL = 1<<8,
00143 FLAGS_UNSIGNED = 1<<9,
00144 FLAGS_OCTAL = 1<<10,
00145 FLAGS_HEX = 1<<11,
00146 FLAGS_UPPER = 1<<12,
00147 FLAGS_WIDTH = 1<<13,
00148 FLAGS_WIDTHPARAM = 1<<14,
00149 FLAGS_PREC = 1<<15,
00150 FLAGS_PRECPARAM = 1<<16,
00151 FLAGS_CHAR = 1<<17,
00152 FLAGS_FLOATE = 1<<18,
00153 FLAGS_FLOATG = 1<<19
00154 };
00155
00156 typedef struct {
00157 FormatType type;
00158 int flags;
00159 long width;
00160 long precision;
00161 union {
00162 char *str;
00163 void *ptr;
00164 union {
00165 mp_intmax_t as_signed;
00166 mp_uintmax_t as_unsigned;
00167 } num;
00168 double dnum;
00169 } data;
00170 } va_stack_t;
00171
00172 struct nsprintf {
00173 char *buffer;
00174 size_t length;
00175 size_t max;
00176 };
00177
00178 struct asprintf {
00179 char *buffer;
00180 size_t len;
00181 size_t alloc;
00182 int fail;
00183
00184 };
00185
00186 static long dprintf_DollarString(char *input, char **end)
00187 {
00188 int number=0;
00189 while(ISDIGIT(*input)) {
00190 number *= 10;
00191 number += *input-'0';
00192 input++;
00193 }
00194 if(number && ('$'==*input++)) {
00195 *end = input;
00196 return number;
00197 }
00198 return 0;
00199 }
00200
00201 static bool dprintf_IsQualifierNoDollar(const char *fmt)
00202 {
00203 #if defined(MP_HAVE_INT_EXTENSIONS)
00204 if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) {
00205 return TRUE;
00206 }
00207 #endif
00208
00209 switch(*fmt) {
00210 case '-': case '+': case ' ': case '#': case '.':
00211 case '0': case '1': case '2': case '3': case '4':
00212 case '5': case '6': case '7': case '8': case '9':
00213 case 'h': case 'l': case 'L': case 'z': case 'q':
00214 case '*': case 'O':
00215 #if defined(MP_HAVE_INT_EXTENSIONS)
00216 case 'I':
00217 #endif
00218 return TRUE;
00219
00220 default:
00221 return FALSE;
00222 }
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
00236 va_list arglist)
00237 {
00238 char *fmt = (char *)format;
00239 int param_num = 0;
00240 long this_param;
00241 long width;
00242 long precision;
00243 int flags;
00244 long max_param=0;
00245 long i;
00246
00247 while(*fmt) {
00248 if(*fmt++ == '%') {
00249 if(*fmt == '%') {
00250 fmt++;
00251 continue;
00252 }
00253
00254 flags = FLAGS_NEW;
00255
00256
00257
00258 param_num++;
00259
00260 this_param = dprintf_DollarString(fmt, &fmt);
00261 if(0 == this_param)
00262
00263 this_param = param_num;
00264
00265 if(this_param > max_param)
00266 max_param = this_param;
00267
00268
00269
00270
00271
00272
00273
00274 width = 0;
00275 precision = 0;
00276
00277
00278
00279 while(dprintf_IsQualifierNoDollar(fmt)) {
00280 #if defined(MP_HAVE_INT_EXTENSIONS)
00281 if(!strncmp(fmt, "I32", 3)) {
00282 flags |= FLAGS_LONG;
00283 fmt += 3;
00284 }
00285 else if(!strncmp(fmt, "I64", 3)) {
00286 flags |= FLAGS_LONGLONG;
00287 fmt += 3;
00288 }
00289 else
00290 #endif
00291
00292 switch(*fmt++) {
00293 case ' ':
00294 flags |= FLAGS_SPACE;
00295 break;
00296 case '+':
00297 flags |= FLAGS_SHOWSIGN;
00298 break;
00299 case '-':
00300 flags |= FLAGS_LEFT;
00301 flags &= ~FLAGS_PAD_NIL;
00302 break;
00303 case '#':
00304 flags |= FLAGS_ALT;
00305 break;
00306 case '.':
00307 if('*' == *fmt) {
00308
00309
00310 flags |= FLAGS_PRECPARAM;
00311 fmt++;
00312 param_num++;
00313
00314 i = dprintf_DollarString(fmt, &fmt);
00315 if(i)
00316 precision = i;
00317 else
00318 precision = param_num;
00319
00320 if(precision > max_param)
00321 max_param = precision;
00322 }
00323 else {
00324 flags |= FLAGS_PREC;
00325 precision = strtol(fmt, &fmt, 10);
00326 }
00327 break;
00328 case 'h':
00329 flags |= FLAGS_SHORT;
00330 break;
00331 #if defined(MP_HAVE_INT_EXTENSIONS)
00332 case 'I':
00333 #if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
00334 flags |= FLAGS_LONGLONG;
00335 #else
00336 flags |= FLAGS_LONG;
00337 #endif
00338 break;
00339 #endif
00340 case 'l':
00341 if(flags & FLAGS_LONG)
00342 flags |= FLAGS_LONGLONG;
00343 else
00344 flags |= FLAGS_LONG;
00345 break;
00346 case 'L':
00347 flags |= FLAGS_LONGDOUBLE;
00348 break;
00349 case 'q':
00350 flags |= FLAGS_LONGLONG;
00351 break;
00352 case 'z':
00353
00354
00355 #if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG)
00356 flags |= FLAGS_LONGLONG;
00357 #else
00358 flags |= FLAGS_LONG;
00359 #endif
00360 break;
00361 case 'O':
00362 #if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
00363 flags |= FLAGS_LONGLONG;
00364 #else
00365 flags |= FLAGS_LONG;
00366 #endif
00367 break;
00368 case '0':
00369 if(!(flags & FLAGS_LEFT))
00370 flags |= FLAGS_PAD_NIL;
00371
00372 case '1': case '2': case '3': case '4':
00373 case '5': case '6': case '7': case '8': case '9':
00374 flags |= FLAGS_WIDTH;
00375 width = strtol(fmt-1, &fmt, 10);
00376 break;
00377 case '*':
00378 flags |= FLAGS_WIDTHPARAM;
00379 param_num++;
00380
00381 i = dprintf_DollarString(fmt, &fmt);
00382 if(i)
00383 width = i;
00384 else
00385 width = param_num;
00386 if(width > max_param)
00387 max_param=width;
00388 break;
00389 default:
00390 break;
00391 }
00392 }
00393
00394
00395
00396 i = this_param - 1;
00397
00398 if((i < 0) || (i >= MAX_PARAMETERS))
00399
00400 return 1;
00401
00402 switch (*fmt) {
00403 case 'S':
00404 flags |= FLAGS_ALT;
00405
00406 case 's':
00407 vto[i].type = FORMAT_STRING;
00408 break;
00409 case 'n':
00410 vto[i].type = FORMAT_INTPTR;
00411 break;
00412 case 'p':
00413 vto[i].type = FORMAT_PTR;
00414 break;
00415 case 'd': case 'i':
00416 vto[i].type = FORMAT_INT;
00417 break;
00418 case 'u':
00419 vto[i].type = FORMAT_INT;
00420 flags |= FLAGS_UNSIGNED;
00421 break;
00422 case 'o':
00423 vto[i].type = FORMAT_INT;
00424 flags |= FLAGS_OCTAL;
00425 break;
00426 case 'x':
00427 vto[i].type = FORMAT_INT;
00428 flags |= FLAGS_HEX|FLAGS_UNSIGNED;
00429 break;
00430 case 'X':
00431 vto[i].type = FORMAT_INT;
00432 flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
00433 break;
00434 case 'c':
00435 vto[i].type = FORMAT_INT;
00436 flags |= FLAGS_CHAR;
00437 break;
00438 case 'f':
00439 vto[i].type = FORMAT_DOUBLE;
00440 break;
00441 case 'e':
00442 vto[i].type = FORMAT_DOUBLE;
00443 flags |= FLAGS_FLOATE;
00444 break;
00445 case 'E':
00446 vto[i].type = FORMAT_DOUBLE;
00447 flags |= FLAGS_FLOATE|FLAGS_UPPER;
00448 break;
00449 case 'g':
00450 vto[i].type = FORMAT_DOUBLE;
00451 flags |= FLAGS_FLOATG;
00452 break;
00453 case 'G':
00454 vto[i].type = FORMAT_DOUBLE;
00455 flags |= FLAGS_FLOATG|FLAGS_UPPER;
00456 break;
00457 default:
00458 vto[i].type = FORMAT_UNKNOWN;
00459 break;
00460 }
00461
00462 vto[i].flags = flags;
00463 vto[i].width = width;
00464 vto[i].precision = precision;
00465
00466 if(flags & FLAGS_WIDTHPARAM) {
00467
00468
00469 long k = width - 1;
00470 vto[i].width = k;
00471 vto[k].type = FORMAT_WIDTH;
00472 vto[k].flags = FLAGS_NEW;
00473
00474 vto[k].width = 0;
00475 vto[k].precision = 0;
00476 }
00477 if(flags & FLAGS_PRECPARAM) {
00478
00479
00480 long k = precision - 1;
00481 vto[i].precision = k;
00482 vto[k].type = FORMAT_WIDTH;
00483 vto[k].flags = FLAGS_NEW;
00484
00485 vto[k].width = 0;
00486 vto[k].precision = 0;
00487 }
00488 *endpos++ = fmt + 1;
00489 }
00490 }
00491
00492
00493 for(i=0; i<max_param; i++) {
00494
00495
00496 if(vto[i].flags & FLAGS_WIDTHPARAM) {
00497 vto[vto[i].width].data.num.as_signed =
00498 (mp_intmax_t)va_arg(arglist, int);
00499 }
00500 if(vto[i].flags & FLAGS_PRECPARAM) {
00501 vto[vto[i].precision].data.num.as_signed =
00502 (mp_intmax_t)va_arg(arglist, int);
00503 }
00504
00505 switch(vto[i].type) {
00506 case FORMAT_STRING:
00507 vto[i].data.str = va_arg(arglist, char *);
00508 break;
00509
00510 case FORMAT_INTPTR:
00511 case FORMAT_UNKNOWN:
00512 case FORMAT_PTR:
00513 vto[i].data.ptr = va_arg(arglist, void *);
00514 break;
00515
00516 case FORMAT_INT:
00517 #ifdef HAVE_LONG_LONG_TYPE
00518 if((vto[i].flags & FLAGS_LONGLONG) && (vto[i].flags & FLAGS_UNSIGNED))
00519 vto[i].data.num.as_unsigned =
00520 (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
00521 else if(vto[i].flags & FLAGS_LONGLONG)
00522 vto[i].data.num.as_signed =
00523 (mp_intmax_t)va_arg(arglist, mp_intmax_t);
00524 else
00525 #endif
00526 {
00527 if((vto[i].flags & FLAGS_LONG) && (vto[i].flags & FLAGS_UNSIGNED))
00528 vto[i].data.num.as_unsigned =
00529 (mp_uintmax_t)va_arg(arglist, unsigned long);
00530 else if(vto[i].flags & FLAGS_LONG)
00531 vto[i].data.num.as_signed =
00532 (mp_intmax_t)va_arg(arglist, long);
00533 else if(vto[i].flags & FLAGS_UNSIGNED)
00534 vto[i].data.num.as_unsigned =
00535 (mp_uintmax_t)va_arg(arglist, unsigned int);
00536 else
00537 vto[i].data.num.as_signed =
00538 (mp_intmax_t)va_arg(arglist, int);
00539 }
00540 break;
00541
00542 case FORMAT_DOUBLE:
00543 vto[i].data.dnum = va_arg(arglist, double);
00544 break;
00545
00546 case FORMAT_WIDTH:
00547
00548
00549
00550 vto[i].type = FORMAT_INT;
00551 break;
00552
00553 default:
00554 break;
00555 }
00556 }
00557
00558 return 0;
00559
00560 }
00561
00562 static int dprintf_formatf(
00563 void *data,
00564
00565
00566 int (*stream)(int, FILE *),
00567 const char *format,
00568 va_list ap_save)
00569 {
00570
00571 const char *digits = lower_digits;
00572
00573
00574 char *f;
00575
00576
00577 int done = 0;
00578
00579 long param;
00580 long param_num=0;
00581
00582 va_stack_t vto[MAX_PARAMETERS];
00583 char *endpos[MAX_PARAMETERS];
00584 char **end;
00585
00586 char work[BUFFSIZE];
00587
00588 va_stack_t *p;
00589
00590
00591
00592
00593 char *workend = &work[sizeof(work) - 2];
00594
00595
00596 if(dprintf_Pass1(format, vto, endpos, ap_save))
00597 return -1;
00598
00599 end = &endpos[0];
00600
00601
00602 f = (char *)format;
00603 while(*f != '\0') {
00604
00605 int is_alt;
00606
00607
00608 long width;
00609
00610
00611 long prec;
00612
00613
00614 int is_neg;
00615
00616
00617 long base;
00618
00619
00620 mp_uintmax_t num;
00621
00622
00623 mp_intmax_t signed_num;
00624
00625 char *w;
00626
00627 if(*f != '%') {
00628
00629
00630 do {
00631 OUTCHAR(*f);
00632 } while(*++f && ('%' != *f));
00633 continue;
00634 }
00635
00636 ++f;
00637
00638
00639
00640
00641
00642 if(*f == '%') {
00643 ++f;
00644 OUTCHAR('%');
00645 continue;
00646 }
00647
00648
00649
00650 param=dprintf_DollarString(f, &f);
00651
00652 if(!param)
00653 param = param_num;
00654 else
00655 --param;
00656
00657 param_num++;
00658
00659
00660 p = &vto[param];
00661
00662
00663 if(p->flags & FLAGS_WIDTHPARAM) {
00664 width = (long)vto[p->width].data.num.as_signed;
00665 param_num++;
00666
00667 if(width < 0) {
00668
00669
00670 width = -width;
00671 p->flags |= FLAGS_LEFT;
00672 p->flags &= ~FLAGS_PAD_NIL;
00673 }
00674 }
00675 else
00676 width = p->width;
00677
00678
00679 if(p->flags & FLAGS_PRECPARAM) {
00680 prec = (long)vto[p->precision].data.num.as_signed;
00681 param_num++;
00682
00683 if(prec < 0)
00684
00685
00686 prec = -1;
00687 }
00688 else if(p->flags & FLAGS_PREC)
00689 prec = p->precision;
00690 else
00691 prec = -1;
00692
00693 is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
00694
00695 switch(p->type) {
00696 case FORMAT_INT:
00697 num = p->data.num.as_unsigned;
00698 if(p->flags & FLAGS_CHAR) {
00699
00700 if(!(p->flags & FLAGS_LEFT))
00701 while(--width > 0)
00702 OUTCHAR(' ');
00703 OUTCHAR((char) num);
00704 if(p->flags & FLAGS_LEFT)
00705 while(--width > 0)
00706 OUTCHAR(' ');
00707 break;
00708 }
00709 if(p->flags & FLAGS_OCTAL) {
00710
00711 base = 8;
00712 goto unsigned_number;
00713 }
00714 else if(p->flags & FLAGS_HEX) {
00715
00716
00717 digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
00718 base = 16;
00719 goto unsigned_number;
00720 }
00721 else if(p->flags & FLAGS_UNSIGNED) {
00722
00723 base = 10;
00724 goto unsigned_number;
00725 }
00726
00727
00728 base = 10;
00729
00730 is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0;
00731 if(is_neg) {
00732
00733 signed_num = p->data.num.as_signed + (mp_intmax_t)1;
00734 signed_num = -signed_num;
00735 num = (mp_uintmax_t)signed_num;
00736 num += (mp_uintmax_t)1;
00737 }
00738
00739 goto number;
00740
00741 unsigned_number:
00742
00743 is_neg = 0;
00744
00745 number:
00746
00747
00748
00749 if(prec == -1)
00750 prec = 1;
00751
00752
00753 w = workend;
00754 while(num > 0) {
00755 *w-- = digits[num % base];
00756 num /= base;
00757 }
00758 width -= (long)(workend - w);
00759 prec -= (long)(workend - w);
00760
00761 if(is_alt && base == 8 && prec <= 0) {
00762 *w-- = '0';
00763 --width;
00764 }
00765
00766 if(prec > 0) {
00767 width -= prec;
00768 while(prec-- > 0)
00769 *w-- = '0';
00770 }
00771
00772 if(is_alt && base == 16)
00773 width -= 2;
00774
00775 if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
00776 --width;
00777
00778 if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
00779 while(width-- > 0)
00780 OUTCHAR(' ');
00781
00782 if(is_neg)
00783 OUTCHAR('-');
00784 else if(p->flags & FLAGS_SHOWSIGN)
00785 OUTCHAR('+');
00786 else if(p->flags & FLAGS_SPACE)
00787 OUTCHAR(' ');
00788
00789 if(is_alt && base == 16) {
00790 OUTCHAR('0');
00791 if(p->flags & FLAGS_UPPER)
00792 OUTCHAR('X');
00793 else
00794 OUTCHAR('x');
00795 }
00796
00797 if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
00798 while(width-- > 0)
00799 OUTCHAR('0');
00800
00801
00802 while(++w <= workend) {
00803 OUTCHAR(*w);
00804 }
00805
00806 if(p->flags & FLAGS_LEFT)
00807 while(width-- > 0)
00808 OUTCHAR(' ');
00809 break;
00810
00811 case FORMAT_STRING:
00812
00813 {
00814 static const char null[] = "(nil)";
00815 const char *str;
00816 size_t len;
00817
00818 str = (char *) p->data.str;
00819 if(str == NULL) {
00820
00821 if(prec == -1 || prec >= (long) sizeof(null) - 1) {
00822 str = null;
00823 len = sizeof(null) - 1;
00824
00825 p->flags &= (~FLAGS_ALT);
00826 }
00827 else {
00828 str = "";
00829 len = 0;
00830 }
00831 }
00832 else if(prec != -1)
00833 len = (size_t)prec;
00834 else
00835 len = strlen(str);
00836
00837 width -= (len > LONG_MAX) ? LONG_MAX : (long)len;
00838
00839 if(p->flags & FLAGS_ALT)
00840 OUTCHAR('"');
00841
00842 if(!(p->flags&FLAGS_LEFT))
00843 while(width-- > 0)
00844 OUTCHAR(' ');
00845
00846 while((len-- > 0) && *str)
00847 OUTCHAR(*str++);
00848 if(p->flags&FLAGS_LEFT)
00849 while(width-- > 0)
00850 OUTCHAR(' ');
00851
00852 if(p->flags & FLAGS_ALT)
00853 OUTCHAR('"');
00854 }
00855 break;
00856
00857 case FORMAT_PTR:
00858
00859 {
00860 void *ptr;
00861 ptr = (void *) p->data.ptr;
00862 if(ptr != NULL) {
00863
00864 base = 16;
00865 digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
00866 is_alt = 1;
00867 num = (size_t) ptr;
00868 is_neg = 0;
00869 goto number;
00870 }
00871 else {
00872
00873 static const char strnil[] = "(nil)";
00874 const char *point;
00875
00876 width -= (long)(sizeof(strnil) - 1);
00877 if(p->flags & FLAGS_LEFT)
00878 while(width-- > 0)
00879 OUTCHAR(' ');
00880 for(point = strnil; *point != '\0'; ++point)
00881 OUTCHAR(*point);
00882 if(! (p->flags & FLAGS_LEFT))
00883 while(width-- > 0)
00884 OUTCHAR(' ');
00885 }
00886 }
00887 break;
00888
00889 case FORMAT_DOUBLE:
00890 {
00891 char formatbuf[32]="%";
00892 char *fptr = &formatbuf[1];
00893 size_t left = sizeof(formatbuf)-strlen(formatbuf);
00894 int len;
00895
00896 width = -1;
00897 if(p->flags & FLAGS_WIDTH)
00898 width = p->width;
00899 else if(p->flags & FLAGS_WIDTHPARAM)
00900 width = (long)vto[p->width].data.num.as_signed;
00901
00902 prec = -1;
00903 if(p->flags & FLAGS_PREC)
00904 prec = p->precision;
00905 else if(p->flags & FLAGS_PRECPARAM)
00906 prec = (long)vto[p->precision].data.num.as_signed;
00907
00908 if(p->flags & FLAGS_LEFT)
00909 *fptr++ = '-';
00910 if(p->flags & FLAGS_SHOWSIGN)
00911 *fptr++ = '+';
00912 if(p->flags & FLAGS_SPACE)
00913 *fptr++ = ' ';
00914 if(p->flags & FLAGS_ALT)
00915 *fptr++ = '#';
00916
00917 *fptr = 0;
00918
00919 if(width >= 0) {
00920 if(width >= (long)sizeof(work))
00921 width = sizeof(work)-1;
00922
00923 len = curl_msnprintf(fptr, left, "%ld", width);
00924 fptr += len;
00925 left -= len;
00926 }
00927 if(prec >= 0) {
00928
00929
00930 size_t maxprec = sizeof(work) - 2;
00931 double val = p->data.dnum;
00932 while(val >= 10.0) {
00933 val /= 10;
00934 maxprec--;
00935 }
00936
00937 if(prec > (long)maxprec)
00938 prec = (long)maxprec-1;
00939
00940 len = curl_msnprintf(fptr, left, ".%ld", prec);
00941 fptr += len;
00942 }
00943 if(p->flags & FLAGS_LONG)
00944 *fptr++ = 'l';
00945
00946 if(p->flags & FLAGS_FLOATE)
00947 *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e');
00948 else if(p->flags & FLAGS_FLOATG)
00949 *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g');
00950 else
00951 *fptr++ = 'f';
00952
00953 *fptr = 0;
00954
00955
00956
00957 (sprintf)(work, formatbuf, p->data.dnum);
00958 #ifdef CURLDEBUG
00959 assert(strlen(work) <= sizeof(work));
00960 #endif
00961 for(fptr=work; *fptr; fptr++)
00962 OUTCHAR(*fptr);
00963 }
00964 break;
00965
00966 case FORMAT_INTPTR:
00967
00968 #ifdef HAVE_LONG_LONG_TYPE
00969 if(p->flags & FLAGS_LONGLONG)
00970 *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done;
00971 else
00972 #endif
00973 if(p->flags & FLAGS_LONG)
00974 *(long *) p->data.ptr = (long)done;
00975 else if(!(p->flags & FLAGS_SHORT))
00976 *(int *) p->data.ptr = (int)done;
00977 else
00978 *(short *) p->data.ptr = (short)done;
00979 break;
00980
00981 default:
00982 break;
00983 }
00984 f = *end++;
00985
00986 }
00987 return done;
00988 }
00989
00990
00991 static int addbyter(int output, FILE *data)
00992 {
00993 struct nsprintf *infop=(struct nsprintf *)data;
00994 unsigned char outc = (unsigned char)output;
00995
00996 if(infop->length < infop->max) {
00997
00998 infop->buffer[0] = outc;
00999 infop->buffer++;
01000 infop->length++;
01001 return outc;
01002 }
01003 return -1;
01004 }
01005
01006 int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
01007 va_list ap_save)
01008 {
01009 int retcode;
01010 struct nsprintf info;
01011
01012 info.buffer = buffer;
01013 info.length = 0;
01014 info.max = maxlength;
01015
01016 retcode = dprintf_formatf(&info, addbyter, format, ap_save);
01017 if((retcode != -1) && info.max) {
01018
01019 if(info.max == info.length)
01020
01021 info.buffer[-1] = 0;
01022 else
01023 info.buffer[0] = 0;
01024 }
01025 return retcode;
01026 }
01027
01028 int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
01029 {
01030 int retcode;
01031 va_list ap_save;
01032 va_start(ap_save, format);
01033 retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save);
01034 va_end(ap_save);
01035 return retcode;
01036 }
01037
01038
01039 static int alloc_addbyter(int output, FILE *data)
01040 {
01041 struct asprintf *infop=(struct asprintf *)data;
01042 unsigned char outc = (unsigned char)output;
01043
01044 if(!infop->buffer) {
01045 infop->buffer = malloc(32);
01046 if(!infop->buffer) {
01047 infop->fail = 1;
01048 return -1;
01049 }
01050 infop->alloc = 32;
01051 infop->len =0;
01052 }
01053 else if(infop->len+1 >= infop->alloc) {
01054 char *newptr = NULL;
01055 size_t newsize = infop->alloc*2;
01056
01057
01058 if(newsize > infop->alloc)
01059 newptr = realloc(infop->buffer, newsize);
01060
01061 if(!newptr) {
01062 infop->fail = 1;
01063 return -1;
01064 }
01065 infop->buffer = newptr;
01066 infop->alloc = newsize;
01067 }
01068
01069 infop->buffer[ infop->len ] = outc;
01070
01071 infop->len++;
01072
01073 return outc;
01074 }
01075
01076 char *curl_maprintf(const char *format, ...)
01077 {
01078 va_list ap_save;
01079 int retcode;
01080 struct asprintf info;
01081
01082 info.buffer = NULL;
01083 info.len = 0;
01084 info.alloc = 0;
01085 info.fail = 0;
01086
01087 va_start(ap_save, format);
01088 retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
01089 va_end(ap_save);
01090 if((-1 == retcode) || info.fail) {
01091 if(info.alloc)
01092 free(info.buffer);
01093 return NULL;
01094 }
01095 if(info.alloc) {
01096 info.buffer[info.len] = 0;
01097 return info.buffer;
01098 }
01099 else
01100 return strdup("");
01101 }
01102
01103 char *curl_mvaprintf(const char *format, va_list ap_save)
01104 {
01105 int retcode;
01106 struct asprintf info;
01107
01108 info.buffer = NULL;
01109 info.len = 0;
01110 info.alloc = 0;
01111 info.fail = 0;
01112
01113 retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
01114 if((-1 == retcode) || info.fail) {
01115 if(info.alloc)
01116 free(info.buffer);
01117 return NULL;
01118 }
01119
01120 if(info.alloc) {
01121 info.buffer[info.len] = 0;
01122 return info.buffer;
01123 }
01124 else
01125 return strdup("");
01126 }
01127
01128 static int storebuffer(int output, FILE *data)
01129 {
01130 char **buffer = (char **)data;
01131 unsigned char outc = (unsigned char)output;
01132 **buffer = outc;
01133 (*buffer)++;
01134 return outc;
01135 }
01136
01137 int curl_msprintf(char *buffer, const char *format, ...)
01138 {
01139 va_list ap_save;
01140 int retcode;
01141 va_start(ap_save, format);
01142 retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
01143 va_end(ap_save);
01144 *buffer=0;
01145 return retcode;
01146 }
01147
01148 int curl_mprintf(const char *format, ...)
01149 {
01150 int retcode;
01151 va_list ap_save;
01152 va_start(ap_save, format);
01153
01154 retcode = dprintf_formatf(stdout, fputc, format, ap_save);
01155 va_end(ap_save);
01156 return retcode;
01157 }
01158
01159 int curl_mfprintf(FILE *whereto, const char *format, ...)
01160 {
01161 int retcode;
01162 va_list ap_save;
01163 va_start(ap_save, format);
01164 retcode = dprintf_formatf(whereto, fputc, format, ap_save);
01165 va_end(ap_save);
01166 return retcode;
01167 }
01168
01169 int curl_mvsprintf(char *buffer, const char *format, va_list ap_save)
01170 {
01171 int retcode;
01172 retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
01173 *buffer=0;
01174 return retcode;
01175 }
01176
01177 int curl_mvprintf(const char *format, va_list ap_save)
01178 {
01179 return dprintf_formatf(stdout, fputc, format, ap_save);
01180 }
01181
01182 int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save)
01183 {
01184 return dprintf_formatf(whereto, fputc, format, ap_save);
01185 }