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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 #include "pipe/p_config.h"
00166
00167 #if HAVE_CONFIG_H
00168 #include <config.h>
00169 #else
00170 #ifdef WIN32
00171 #define vsnprintf util_vsnprintf
00172 #define snprintf util_snprintf
00173 #define HAVE_VSNPRINTF 0
00174 #define HAVE_SNPRINTF 0
00175 #define HAVE_VASPRINTF 1
00176 #define HAVE_ASPRINTF 1
00177 #define HAVE_STDARG_H 1
00178 #define HAVE_STDDEF_H 1
00179 #define HAVE_STDINT_H 0
00180 #define HAVE_STDLIB_H 1
00181 #define HAVE_INTTYPES_H 0
00182 #define HAVE_LOCALE_H 0
00183 #define HAVE_LOCALECONV 0
00184 #define HAVE_LCONV_DECIMAL_POINT 0
00185 #define HAVE_LCONV_THOUSANDS_SEP 0
00186 #define HAVE_LONG_DOUBLE 0
00187 #define HAVE_LONG_LONG_INT 1
00188 #define HAVE_UNSIGNED_LONG_LONG_INT 1
00189 #define HAVE_INTMAX_T 0
00190 #define HAVE_UINTMAX_T 0
00191 #define HAVE_UINTPTR_T 1
00192 #define HAVE_PTRDIFF_T 1
00193 #define HAVE_VA_COPY 0
00194 #define HAVE___VA_COPY 0
00195 #else
00196 #define HAVE_VSNPRINTF 1
00197 #define HAVE_SNPRINTF 1
00198 #define HAVE_VASPRINTF 1
00199 #define HAVE_ASPRINTF 1
00200 #endif
00201 #endif
00202
00203 #if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF
00204 #include <stdio.h>
00205 #ifdef VA_START
00206 #undef VA_START
00207 #endif
00208 #ifdef VA_SHIFT
00209 #undef VA_SHIFT
00210 #endif
00211 #if HAVE_STDARG_H
00212 #include <stdarg.h>
00213 #define VA_START(ap, last) va_start(ap, last)
00214 #define VA_SHIFT(ap, value, type)
00215 #else
00216 #include <varargs.h>
00217 #define VA_START(ap, last) va_start(ap)
00218 #define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
00219 #endif
00220
00221 #if !HAVE_VASPRINTF
00222 #if HAVE_STDLIB_H
00223 #include <stdlib.h>
00224 #endif
00225 #ifdef VA_COPY
00226 #undef VA_COPY
00227 #endif
00228 #ifdef VA_END_COPY
00229 #undef VA_END_COPY
00230 #endif
00231 #if HAVE_VA_COPY
00232 #define VA_COPY(dest, src) va_copy(dest, src)
00233 #define VA_END_COPY(ap) va_end(ap)
00234 #elif HAVE___VA_COPY
00235 #define VA_COPY(dest, src) __va_copy(dest, src)
00236 #define VA_END_COPY(ap) va_end(ap)
00237 #else
00238 #define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list))
00239 #define VA_END_COPY(ap)
00240 #define NEED_MYMEMCPY 1
00241 static void *mymemcpy(void *, void *, size_t);
00242 #endif
00243 #endif
00244
00245 #if !HAVE_VSNPRINTF
00246 #include <limits.h>
00247 #if HAVE_INTTYPES_H
00248 #include <inttypes.h>
00249 #endif
00250 #if HAVE_LOCALE_H
00251 #include <locale.h>
00252 #endif
00253 #if HAVE_STDDEF_H
00254 #include <stddef.h>
00255 #endif
00256 #if HAVE_STDINT_H
00257 #include <stdint.h>
00258 #endif
00259
00260
00261 #ifndef ULONG_MAX
00262 #ifdef UINT_MAX
00263 #define ULONG_MAX UINT_MAX
00264 #else
00265 #define ULONG_MAX INT_MAX
00266 #endif
00267 #endif
00268 #ifdef ULLONG
00269 #undef ULLONG
00270 #endif
00271 #if HAVE_UNSIGNED_LONG_LONG_INT
00272 #define ULLONG unsigned long long int
00273 #ifndef ULLONG_MAX
00274 #define ULLONG_MAX ULONG_MAX
00275 #endif
00276 #else
00277 #define ULLONG unsigned long int
00278 #ifdef ULLONG_MAX
00279 #undef ULLONG_MAX
00280 #endif
00281 #define ULLONG_MAX ULONG_MAX
00282 #endif
00283
00284
00285 #ifdef UINTMAX_T
00286 #undef UINTMAX_T
00287 #endif
00288 #if HAVE_UINTMAX_T || defined(uintmax_t)
00289 #define UINTMAX_T uintmax_t
00290 #ifndef UINTMAX_MAX
00291 #define UINTMAX_MAX ULLONG_MAX
00292 #endif
00293 #else
00294 #define UINTMAX_T ULLONG
00295 #ifdef UINTMAX_MAX
00296 #undef UINTMAX_MAX
00297 #endif
00298 #define UINTMAX_MAX ULLONG_MAX
00299 #endif
00300
00301
00302 #ifndef LDOUBLE
00303 #if HAVE_LONG_DOUBLE
00304 #define LDOUBLE long double
00305 #else
00306 #define LDOUBLE double
00307 #endif
00308 #endif
00309
00310
00311 #ifndef LLONG
00312 #if HAVE_LONG_LONG_INT
00313 #define LLONG long long int
00314 #else
00315 #define LLONG long int
00316 #endif
00317 #endif
00318
00319
00320 #ifndef INTMAX_T
00321 #if HAVE_INTMAX_T || defined(intmax_t)
00322 #define INTMAX_T intmax_t
00323 #else
00324 #define INTMAX_T LLONG
00325 #endif
00326 #endif
00327
00328
00329 #ifndef UINTPTR_T
00330 #if HAVE_UINTPTR_T || defined(uintptr_t)
00331 #define UINTPTR_T uintptr_t
00332 #else
00333 #define UINTPTR_T unsigned long int
00334 #endif
00335 #endif
00336
00337
00338 #if (_WIN32_WCE < 600)
00339 #ifdef UINTPTR_T
00340 #undef UINTPTR_T
00341 #endif
00342 #define UINTPTR_T unsigned long int
00343 #endif
00344
00345
00346
00347 #ifndef PTRDIFF_T
00348 #if HAVE_PTRDIFF_T || defined(ptrdiff_t)
00349 #define PTRDIFF_T ptrdiff_t
00350 #else
00351 #define PTRDIFF_T long int
00352 #endif
00353 #endif
00354
00355
00356
00357
00358
00359
00360 #ifndef UPTRDIFF_T
00361 #define UPTRDIFF_T PTRDIFF_T
00362 #endif
00363
00364
00365
00366
00367
00368
00369 #ifndef SSIZE_T
00370 #define SSIZE_T size_t
00371 #endif
00372
00373
00374 #ifndef ERANGE
00375 #define ERANGE E2BIG
00376 #endif
00377 #ifndef EOVERFLOW
00378 #define EOVERFLOW ERANGE
00379 #endif
00380
00381
00382
00383
00384
00385 #ifdef MAX_CONVERT_LENGTH
00386 #undef MAX_CONVERT_LENGTH
00387 #endif
00388 #define MAX_CONVERT_LENGTH 43
00389
00390
00391 #define PRINT_S_DEFAULT 0
00392 #define PRINT_S_FLAGS 1
00393 #define PRINT_S_WIDTH 2
00394 #define PRINT_S_DOT 3
00395 #define PRINT_S_PRECISION 4
00396 #define PRINT_S_MOD 5
00397 #define PRINT_S_CONV 6
00398
00399
00400 #define PRINT_F_MINUS (1 << 0)
00401 #define PRINT_F_PLUS (1 << 1)
00402 #define PRINT_F_SPACE (1 << 2)
00403 #define PRINT_F_NUM (1 << 3)
00404 #define PRINT_F_ZERO (1 << 4)
00405 #define PRINT_F_QUOTE (1 << 5)
00406 #define PRINT_F_UP (1 << 6)
00407 #define PRINT_F_UNSIGNED (1 << 7)
00408 #define PRINT_F_TYPE_G (1 << 8)
00409 #define PRINT_F_TYPE_E (1 << 9)
00410
00411
00412 #define PRINT_C_CHAR 1
00413 #define PRINT_C_SHORT 2
00414 #define PRINT_C_LONG 3
00415 #define PRINT_C_LLONG 4
00416 #define PRINT_C_LDOUBLE 5
00417 #define PRINT_C_SIZE 6
00418 #define PRINT_C_PTRDIFF 7
00419 #define PRINT_C_INTMAX 8
00420
00421 #ifndef MAX
00422 #define MAX(x, y) ((x >= y) ? x : y)
00423 #endif
00424 #ifndef CHARTOINT
00425 #define CHARTOINT(ch) (ch - '0')
00426 #endif
00427 #ifndef ISDIGIT
00428 #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
00429 #endif
00430 #ifndef ISNAN
00431 #define ISNAN(x) (x != x)
00432 #endif
00433 #ifndef ISINF
00434 #define ISINF(x) (x != 0.0 && x + x == x)
00435 #endif
00436
00437 #ifdef OUTCHAR
00438 #undef OUTCHAR
00439 #endif
00440 #define OUTCHAR(str, len, size, ch) \
00441 do { \
00442 if (len + 1 < size) \
00443 str[len] = ch; \
00444 (len)++; \
00445 } while ( 0)
00446
00447 static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
00448 static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
00449 static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
00450 static void printsep(char *, size_t *, size_t);
00451 static int getnumsep(int);
00452 static int getexponent(LDOUBLE);
00453 static int convert(UINTMAX_T, char *, size_t, int, int);
00454 static UINTMAX_T cast(LDOUBLE);
00455 static UINTMAX_T myround(LDOUBLE);
00456 static LDOUBLE mypow10(int);
00457
00458 int
00459 util_vsnprintf(char *str, size_t size, const char *format, va_list args)
00460 {
00461 LDOUBLE fvalue;
00462 INTMAX_T value;
00463 unsigned char cvalue;
00464 const char *strvalue;
00465 INTMAX_T *intmaxptr;
00466 PTRDIFF_T *ptrdiffptr;
00467 SSIZE_T *sizeptr;
00468 LLONG *llongptr;
00469 long int *longptr;
00470 int *intptr;
00471 short int *shortptr;
00472 signed char *charptr;
00473 size_t len = 0;
00474 int overflow = 0;
00475 int base = 0;
00476 int cflags = 0;
00477 int flags = 0;
00478 int width = 0;
00479 int precision = -1;
00480 int state = PRINT_S_DEFAULT;
00481 char ch = *format++;
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 if (str == NULL && size != 0)
00492 size = 0;
00493
00494 while (ch != '\0')
00495 switch (state) {
00496 case PRINT_S_DEFAULT:
00497 if (ch == '%')
00498 state = PRINT_S_FLAGS;
00499 else
00500 OUTCHAR(str, len, size, ch);
00501 ch = *format++;
00502 break;
00503 case PRINT_S_FLAGS:
00504 switch (ch) {
00505 case '-':
00506 flags |= PRINT_F_MINUS;
00507 ch = *format++;
00508 break;
00509 case '+':
00510 flags |= PRINT_F_PLUS;
00511 ch = *format++;
00512 break;
00513 case ' ':
00514 flags |= PRINT_F_SPACE;
00515 ch = *format++;
00516 break;
00517 case '#':
00518 flags |= PRINT_F_NUM;
00519 ch = *format++;
00520 break;
00521 case '0':
00522 flags |= PRINT_F_ZERO;
00523 ch = *format++;
00524 break;
00525 case '\'':
00526 flags |= PRINT_F_QUOTE;
00527 ch = *format++;
00528 break;
00529 default:
00530 state = PRINT_S_WIDTH;
00531 break;
00532 }
00533 break;
00534 case PRINT_S_WIDTH:
00535 if (ISDIGIT(ch)) {
00536 ch = CHARTOINT(ch);
00537 if (width > (INT_MAX - ch) / 10) {
00538 overflow = 1;
00539 goto out;
00540 }
00541 width = 10 * width + ch;
00542 ch = *format++;
00543 } else if (ch == '*') {
00544
00545
00546
00547
00548
00549 if ((width = va_arg(args, int)) < 0) {
00550 flags |= PRINT_F_MINUS;
00551 width = -width;
00552 }
00553 ch = *format++;
00554 state = PRINT_S_DOT;
00555 } else
00556 state = PRINT_S_DOT;
00557 break;
00558 case PRINT_S_DOT:
00559 if (ch == '.') {
00560 state = PRINT_S_PRECISION;
00561 ch = *format++;
00562 } else
00563 state = PRINT_S_MOD;
00564 break;
00565 case PRINT_S_PRECISION:
00566 if (precision == -1)
00567 precision = 0;
00568 if (ISDIGIT(ch)) {
00569 ch = CHARTOINT(ch);
00570 if (precision > (INT_MAX - ch) / 10) {
00571 overflow = 1;
00572 goto out;
00573 }
00574 precision = 10 * precision + ch;
00575 ch = *format++;
00576 } else if (ch == '*') {
00577
00578
00579
00580
00581
00582 if ((precision = va_arg(args, int)) < 0)
00583 precision = -1;
00584 ch = *format++;
00585 state = PRINT_S_MOD;
00586 } else
00587 state = PRINT_S_MOD;
00588 break;
00589 case PRINT_S_MOD:
00590 switch (ch) {
00591 case 'h':
00592 ch = *format++;
00593 if (ch == 'h') {
00594 ch = *format++;
00595 cflags = PRINT_C_CHAR;
00596 } else
00597 cflags = PRINT_C_SHORT;
00598 break;
00599 case 'l':
00600 ch = *format++;
00601 if (ch == 'l') {
00602 ch = *format++;
00603 cflags = PRINT_C_LLONG;
00604 } else
00605 cflags = PRINT_C_LONG;
00606 break;
00607 case 'L':
00608 cflags = PRINT_C_LDOUBLE;
00609 ch = *format++;
00610 break;
00611 case 'j':
00612 cflags = PRINT_C_INTMAX;
00613 ch = *format++;
00614 break;
00615 case 't':
00616 cflags = PRINT_C_PTRDIFF;
00617 ch = *format++;
00618 break;
00619 case 'z':
00620 cflags = PRINT_C_SIZE;
00621 ch = *format++;
00622 break;
00623 }
00624 state = PRINT_S_CONV;
00625 break;
00626 case PRINT_S_CONV:
00627 switch (ch) {
00628 case 'd':
00629
00630 case 'i':
00631 switch (cflags) {
00632 case PRINT_C_CHAR:
00633 value = (signed char)va_arg(args, int);
00634 break;
00635 case PRINT_C_SHORT:
00636 value = (short int)va_arg(args, int);
00637 break;
00638 case PRINT_C_LONG:
00639 value = va_arg(args, long int);
00640 break;
00641 case PRINT_C_LLONG:
00642 value = va_arg(args, LLONG);
00643 break;
00644 case PRINT_C_SIZE:
00645 value = va_arg(args, SSIZE_T);
00646 break;
00647 case PRINT_C_INTMAX:
00648 value = va_arg(args, INTMAX_T);
00649 break;
00650 case PRINT_C_PTRDIFF:
00651 value = va_arg(args, PTRDIFF_T);
00652 break;
00653 default:
00654 value = va_arg(args, int);
00655 break;
00656 }
00657 fmtint(str, &len, size, value, 10, width,
00658 precision, flags);
00659 break;
00660 case 'X':
00661 flags |= PRINT_F_UP;
00662
00663 case 'x':
00664 base = 16;
00665
00666 case 'o':
00667 if (base == 0)
00668 base = 8;
00669
00670 case 'u':
00671 if (base == 0)
00672 base = 10;
00673 flags |= PRINT_F_UNSIGNED;
00674 switch (cflags) {
00675 case PRINT_C_CHAR:
00676 value = (unsigned char)va_arg(args,
00677 unsigned int);
00678 break;
00679 case PRINT_C_SHORT:
00680 value = (unsigned short int)va_arg(args,
00681 unsigned int);
00682 break;
00683 case PRINT_C_LONG:
00684 value = va_arg(args, unsigned long int);
00685 break;
00686 case PRINT_C_LLONG:
00687 value = va_arg(args, ULLONG);
00688 break;
00689 case PRINT_C_SIZE:
00690 value = va_arg(args, size_t);
00691 break;
00692 case PRINT_C_INTMAX:
00693 value = va_arg(args, UINTMAX_T);
00694 break;
00695 case PRINT_C_PTRDIFF:
00696 value = va_arg(args, UPTRDIFF_T);
00697 break;
00698 default:
00699 value = va_arg(args, unsigned int);
00700 break;
00701 }
00702 fmtint(str, &len, size, value, base, width,
00703 precision, flags);
00704 break;
00705 case 'A':
00706
00707
00708 case 'F':
00709 flags |= PRINT_F_UP;
00710 case 'a':
00711
00712
00713 case 'f':
00714 if (cflags == PRINT_C_LDOUBLE)
00715 fvalue = va_arg(args, LDOUBLE);
00716 else
00717 fvalue = va_arg(args, double);
00718 fmtflt(str, &len, size, fvalue, width,
00719 precision, flags, &overflow);
00720 if (overflow)
00721 goto out;
00722 break;
00723 case 'E':
00724 flags |= PRINT_F_UP;
00725
00726 case 'e':
00727 flags |= PRINT_F_TYPE_E;
00728 if (cflags == PRINT_C_LDOUBLE)
00729 fvalue = va_arg(args, LDOUBLE);
00730 else
00731 fvalue = va_arg(args, double);
00732 fmtflt(str, &len, size, fvalue, width,
00733 precision, flags, &overflow);
00734 if (overflow)
00735 goto out;
00736 break;
00737 case 'G':
00738 flags |= PRINT_F_UP;
00739
00740 case 'g':
00741 flags |= PRINT_F_TYPE_G;
00742 if (cflags == PRINT_C_LDOUBLE)
00743 fvalue = va_arg(args, LDOUBLE);
00744 else
00745 fvalue = va_arg(args, double);
00746
00747
00748
00749
00750 if (precision == 0)
00751 precision = 1;
00752 fmtflt(str, &len, size, fvalue, width,
00753 precision, flags, &overflow);
00754 if (overflow)
00755 goto out;
00756 break;
00757 case 'c':
00758 cvalue = (unsigned char)va_arg(args, int);
00759 OUTCHAR(str, len, size, cvalue);
00760 break;
00761 case 's':
00762 strvalue = va_arg(args, char *);
00763 fmtstr(str, &len, size, strvalue, width,
00764 precision, flags);
00765 break;
00766 case 'p':
00767
00768
00769
00770
00771
00772
00773 if ((strvalue = va_arg(args, void *)) == NULL)
00774
00775
00776
00777
00778 fmtstr(str, &len, size, "(nil)", width,
00779 -1, flags);
00780 else {
00781
00782
00783
00784
00785
00786 flags |= PRINT_F_NUM;
00787 flags |= PRINT_F_UNSIGNED;
00788 fmtint(str, &len, size,
00789 (UINTPTR_T)strvalue, 16, width,
00790 precision, flags);
00791 }
00792 break;
00793 case 'n':
00794 switch (cflags) {
00795 case PRINT_C_CHAR:
00796 charptr = va_arg(args, signed char *);
00797 *charptr = (signed char)len;
00798 break;
00799 case PRINT_C_SHORT:
00800 shortptr = va_arg(args, short int *);
00801 *shortptr = (short int)len;
00802 break;
00803 case PRINT_C_LONG:
00804 longptr = va_arg(args, long int *);
00805 *longptr = (long int)len;
00806 break;
00807 case PRINT_C_LLONG:
00808 llongptr = va_arg(args, LLONG *);
00809 *llongptr = (LLONG)len;
00810 break;
00811 case PRINT_C_SIZE:
00812
00813
00814
00815
00816
00817
00818
00819 sizeptr = va_arg(args, SSIZE_T *);
00820 *sizeptr = len;
00821 break;
00822 case PRINT_C_INTMAX:
00823 intmaxptr = va_arg(args, INTMAX_T *);
00824 *intmaxptr = len;
00825 break;
00826 case PRINT_C_PTRDIFF:
00827 ptrdiffptr = va_arg(args, PTRDIFF_T *);
00828 *ptrdiffptr = len;
00829 break;
00830 default:
00831 intptr = va_arg(args, int *);
00832 *intptr = len;
00833 break;
00834 }
00835 break;
00836 case '%':
00837 OUTCHAR(str, len, size, ch);
00838 break;
00839 default:
00840 break;
00841 }
00842 ch = *format++;
00843 state = PRINT_S_DEFAULT;
00844 base = cflags = flags = width = 0;
00845 precision = -1;
00846 break;
00847 }
00848 out:
00849 if (len < size)
00850 str[len] = '\0';
00851 else if (size > 0)
00852 str[size - 1] = '\0';
00853
00854 if (overflow || len >= INT_MAX) {
00855 return -1;
00856 }
00857 return (int)len;
00858 }
00859
00860 static void
00861 fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
00862 int precision, int flags)
00863 {
00864 int padlen, strln;
00865 int noprecision = (precision == -1);
00866
00867 if (value == NULL)
00868 value = "(null)";
00869
00870
00871 for (strln = 0; value[strln] != '\0' &&
00872 (noprecision || strln < precision); strln++)
00873 continue;
00874
00875 if ((padlen = width - strln) < 0)
00876 padlen = 0;
00877 if (flags & PRINT_F_MINUS)
00878 padlen = -padlen;
00879
00880 while (padlen > 0) {
00881 OUTCHAR(str, *len, size, ' ');
00882 padlen--;
00883 }
00884 while (*value != '\0' && (noprecision || precision-- > 0)) {
00885 OUTCHAR(str, *len, size, *value);
00886 value++;
00887 }
00888 while (padlen < 0) {
00889 OUTCHAR(str, *len, size, ' ');
00890 padlen++;
00891 }
00892 }
00893
00894 static void
00895 fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
00896 int precision, int flags)
00897 {
00898 UINTMAX_T uvalue;
00899 char iconvert[MAX_CONVERT_LENGTH];
00900 char sign = 0;
00901 char hexprefix = 0;
00902 int spadlen = 0;
00903 int zpadlen = 0;
00904 int pos;
00905 int separators = (flags & PRINT_F_QUOTE);
00906 int noprecision = (precision == -1);
00907
00908 if (flags & PRINT_F_UNSIGNED)
00909 uvalue = value;
00910 else {
00911 uvalue = (value >= 0) ? value : -value;
00912 if (value < 0)
00913 sign = '-';
00914 else if (flags & PRINT_F_PLUS)
00915 sign = '+';
00916 else if (flags & PRINT_F_SPACE)
00917 sign = ' ';
00918 }
00919
00920 pos = convert(uvalue, iconvert, sizeof(iconvert), base,
00921 flags & PRINT_F_UP);
00922
00923 if (flags & PRINT_F_NUM && uvalue != 0) {
00924
00925
00926
00927
00928
00929
00930
00931
00932 switch (base) {
00933 case 8:
00934 if (precision <= pos)
00935 precision = pos + 1;
00936 break;
00937 case 16:
00938 hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
00939 break;
00940 }
00941 }
00942
00943 if (separators)
00944 separators = getnumsep(pos);
00945
00946 zpadlen = precision - pos - separators;
00947 spadlen = width
00948 - separators
00949 - MAX(precision, pos)
00950 - ((sign != 0) ? 1 : 0)
00951 - ((hexprefix != 0) ? 2 : 0);
00952
00953 if (zpadlen < 0)
00954 zpadlen = 0;
00955 if (spadlen < 0)
00956 spadlen = 0;
00957
00958
00959
00960
00961
00962
00963 if (flags & PRINT_F_MINUS)
00964 spadlen = -spadlen;
00965 else if (flags & PRINT_F_ZERO && noprecision) {
00966 zpadlen += spadlen;
00967 spadlen = 0;
00968 }
00969 while (spadlen > 0) {
00970 OUTCHAR(str, *len, size, ' ');
00971 spadlen--;
00972 }
00973 if (sign != 0)
00974 OUTCHAR(str, *len, size, sign);
00975 if (hexprefix != 0) {
00976 OUTCHAR(str, *len, size, '0');
00977 OUTCHAR(str, *len, size, hexprefix);
00978 }
00979 while (zpadlen > 0) {
00980 OUTCHAR(str, *len, size, '0');
00981 zpadlen--;
00982 }
00983 while (pos > 0) {
00984 pos--;
00985 OUTCHAR(str, *len, size, iconvert[pos]);
00986 if (separators > 0 && pos > 0 && pos % 3 == 0)
00987 printsep(str, len, size);
00988 }
00989 while (spadlen < 0) {
00990 OUTCHAR(str, *len, size, ' ');
00991 spadlen++;
00992 }
00993 }
00994
00995 static void
00996 fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
00997 int precision, int flags, int *overflow)
00998 {
00999 LDOUBLE ufvalue;
01000 UINTMAX_T intpart;
01001 UINTMAX_T fracpart;
01002 UINTMAX_T mask;
01003 const char *infnan = NULL;
01004 char iconvert[MAX_CONVERT_LENGTH];
01005 char fconvert[MAX_CONVERT_LENGTH];
01006 char econvert[4];
01007 char esign = 0;
01008 char sign = 0;
01009 int leadfraczeros = 0;
01010 int exponent = 0;
01011 int emitpoint = 0;
01012 int omitzeros = 0;
01013 int omitcount = 0;
01014 int padlen = 0;
01015 int epos = 0;
01016 int fpos = 0;
01017 int ipos = 0;
01018 int separators = (flags & PRINT_F_QUOTE);
01019 int estyle = (flags & PRINT_F_TYPE_E);
01020 #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
01021 struct lconv *lc = localeconv();
01022 #endif
01023
01024
01025
01026
01027
01028
01029 if (precision == -1)
01030 precision = 6;
01031
01032 if (fvalue < 0.0)
01033 sign = '-';
01034 else if (flags & PRINT_F_PLUS)
01035 sign = '+';
01036 else if (flags & PRINT_F_SPACE)
01037 sign = ' ';
01038
01039 if (ISNAN(fvalue))
01040 infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
01041 else if (ISINF(fvalue))
01042 infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
01043
01044 if (infnan != NULL) {
01045 if (sign != 0)
01046 iconvert[ipos++] = sign;
01047 while (*infnan != '\0')
01048 iconvert[ipos++] = *infnan++;
01049 fmtstr(str, len, size, iconvert, width, ipos, flags);
01050 return;
01051 }
01052
01053
01054 if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
01055 if (flags & PRINT_F_TYPE_G) {
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 precision--;
01070
01071
01072
01073
01074
01075 if (!(flags & PRINT_F_NUM))
01076 omitzeros = 1;
01077 }
01078 exponent = getexponent(fvalue);
01079 estyle = 1;
01080 }
01081
01082 again:
01083
01084
01085
01086
01087
01088 switch (sizeof(UINTMAX_T)) {
01089 case 16:
01090 if (precision > 38)
01091 precision = 38;
01092 break;
01093 case 8:
01094 if (precision > 19)
01095 precision = 19;
01096 break;
01097 default:
01098 if (precision > 9)
01099 precision = 9;
01100 break;
01101 }
01102
01103 ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
01104 if (estyle)
01105 ufvalue /= mypow10(exponent);
01106
01107 if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
01108 *overflow = 1;
01109 return;
01110 }
01111
01112
01113
01114
01115
01116 #if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
01117 mask = (unsigned long)mypow10(precision);
01118 #else
01119 mask = (UINTMAX_T)mypow10(precision);
01120 #endif
01121
01122
01123
01124
01125 if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
01126
01127
01128
01129
01130
01131
01132 intpart++;
01133 fracpart = 0;
01134 if (estyle && intpart == 10) {
01135
01136
01137
01138
01139
01140
01141 intpart = 1;
01142 exponent++;
01143 }
01144 }
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164 if (flags & PRINT_F_TYPE_G && estyle &&
01165 precision + 1 > exponent && exponent >= -4) {
01166 precision -= exponent;
01167 estyle = 0;
01168 goto again;
01169 }
01170
01171 if (estyle) {
01172 if (exponent < 0) {
01173 exponent = -exponent;
01174 esign = '-';
01175 } else
01176 esign = '+';
01177
01178
01179
01180
01181
01182
01183
01184 epos = convert(exponent, econvert, 2, 10, 0);
01185
01186
01187
01188
01189
01190 if (epos == 1)
01191 econvert[epos++] = '0';
01192 econvert[epos++] = esign;
01193 econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
01194 }
01195
01196
01197 ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
01198 if (fracpart != 0)
01199 fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
01200
01201 leadfraczeros = precision - fpos;
01202
01203 if (omitzeros) {
01204 if (fpos > 0)
01205 while (omitcount < fpos && fconvert[omitcount] == '0')
01206 omitcount++;
01207 else {
01208 omitcount = precision;
01209 leadfraczeros = 0;
01210 }
01211 precision -= omitcount;
01212 }
01213
01214
01215
01216
01217
01218 if (precision > 0 || flags & PRINT_F_NUM)
01219 emitpoint = 1;
01220 if (separators)
01221 separators = getnumsep(ipos);
01222
01223 padlen = width
01224 - ipos
01225 - epos
01226 - precision
01227 - separators
01228 - (emitpoint ? 1 : 0)
01229 - ((sign != 0) ? 1 : 0);
01230
01231 if (padlen < 0)
01232 padlen = 0;
01233
01234
01235
01236
01237
01238 if (flags & PRINT_F_MINUS)
01239 padlen = -padlen;
01240 else if (flags & PRINT_F_ZERO && padlen > 0) {
01241 if (sign != 0) {
01242 OUTCHAR(str, *len, size, sign);
01243 sign = 0;
01244 }
01245 while (padlen > 0) {
01246 OUTCHAR(str, *len, size, '0');
01247 padlen--;
01248 }
01249 }
01250 while (padlen > 0) {
01251 OUTCHAR(str, *len, size, ' ');
01252 padlen--;
01253 }
01254 if (sign != 0)
01255 OUTCHAR(str, *len, size, sign);
01256 while (ipos > 0) {
01257 ipos--;
01258 OUTCHAR(str, *len, size, iconvert[ipos]);
01259 if (separators > 0 && ipos > 0 && ipos % 3 == 0)
01260 printsep(str, len, size);
01261 }
01262 if (emitpoint) {
01263 #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
01264 if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
01265 OUTCHAR(str, *len, size, *lc->decimal_point);
01266 else
01267 #endif
01268 OUTCHAR(str, *len, size, '.');
01269 }
01270 while (leadfraczeros > 0) {
01271 OUTCHAR(str, *len, size, '0');
01272 leadfraczeros--;
01273 }
01274 while (fpos > omitcount) {
01275 fpos--;
01276 OUTCHAR(str, *len, size, fconvert[fpos]);
01277 }
01278 while (epos > 0) {
01279 epos--;
01280 OUTCHAR(str, *len, size, econvert[epos]);
01281 }
01282 while (padlen < 0) {
01283 OUTCHAR(str, *len, size, ' ');
01284 padlen++;
01285 }
01286 }
01287
01288 static void
01289 printsep(char *str, size_t *len, size_t size)
01290 {
01291 #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
01292 struct lconv *lc = localeconv();
01293 int i;
01294
01295 if (lc->thousands_sep != NULL)
01296 for (i = 0; lc->thousands_sep[i] != '\0'; i++)
01297 OUTCHAR(str, *len, size, lc->thousands_sep[i]);
01298 else
01299 #endif
01300 OUTCHAR(str, *len, size, ',');
01301 }
01302
01303 static int
01304 getnumsep(int digits)
01305 {
01306 int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
01307 #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
01308 int strln;
01309 struct lconv *lc = localeconv();
01310
01311
01312 if (lc->thousands_sep != NULL) {
01313 for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
01314 continue;
01315 separators *= strln;
01316 }
01317 #endif
01318 return separators;
01319 }
01320
01321 static int
01322 getexponent(LDOUBLE value)
01323 {
01324 LDOUBLE tmp = (value >= 0.0) ? value : -value;
01325 int exponent = 0;
01326
01327
01328
01329
01330
01331
01332
01333
01334 while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
01335 tmp *= 10;
01336 while (tmp >= 10.0 && ++exponent < 99)
01337 tmp /= 10;
01338
01339 return exponent;
01340 }
01341
01342 static int
01343 convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
01344 {
01345 const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
01346 size_t pos = 0;
01347
01348
01349 do {
01350 buf[pos++] = digits[value % base];
01351 value /= base;
01352 } while (value != 0 && pos < size);
01353
01354 return (int)pos;
01355 }
01356
01357 static UINTMAX_T
01358 cast(LDOUBLE value)
01359 {
01360 UINTMAX_T result;
01361
01362
01363
01364
01365
01366
01367
01368
01369 if (value >= UINTMAX_MAX)
01370 return UINTMAX_MAX;
01371
01372 #if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
01373 result = (unsigned long)value;
01374 #else
01375 result = (UINTMAX_T)value;
01376 #endif
01377
01378
01379
01380
01381
01382 return (result <= value) ? result : result - 1;
01383 }
01384
01385 static UINTMAX_T
01386 myround(LDOUBLE value)
01387 {
01388 UINTMAX_T intpart = cast(value);
01389
01390 return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
01391 }
01392
01393 static LDOUBLE
01394 mypow10(int exponent)
01395 {
01396 LDOUBLE result = 1;
01397
01398 while (exponent > 0) {
01399 result *= 10;
01400 exponent--;
01401 }
01402 while (exponent < 0) {
01403 result /= 10;
01404 exponent++;
01405 }
01406 return result;
01407 }
01408 #endif
01409
01410 #if !HAVE_VASPRINTF
01411 #if NEED_MYMEMCPY
01412 void *
01413 mymemcpy(void *dst, void *src, size_t len)
01414 {
01415 const char *from = src;
01416 char *to = dst;
01417
01418
01419 while (len-- > 0)
01420 *to++ = *from++;
01421 return dst;
01422 }
01423 #endif
01424
01425 int
01426 util_vasprintf(char **ret, const char *format, va_list ap)
01427 {
01428 size_t size;
01429 int len;
01430 va_list aq;
01431
01432 VA_COPY(aq, ap);
01433 len = vsnprintf(NULL, 0, format, aq);
01434 VA_END_COPY(aq);
01435 if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
01436 return -1;
01437 return vsnprintf(*ret, size, format, ap);
01438 }
01439 #endif
01440
01441 #if !HAVE_SNPRINTF
01442 #if HAVE_STDARG_H
01443 int
01444 util_snprintf(char *str, size_t size, const char *format, ...)
01445 #else
01446 int
01447 util_snprintf(va_alist) va_dcl
01448 #endif
01449 {
01450 #if !HAVE_STDARG_H
01451 char *str;
01452 size_t size;
01453 char *format;
01454 #endif
01455 va_list ap;
01456 int len;
01457
01458 VA_START(ap, format);
01459 VA_SHIFT(ap, str, char *);
01460 VA_SHIFT(ap, size, size_t);
01461 VA_SHIFT(ap, format, const char *);
01462 len = vsnprintf(str, size, format, ap);
01463 va_end(ap);
01464 return len;
01465 }
01466 #endif
01467
01468 #if !HAVE_ASPRINTF
01469 #if HAVE_STDARG_H
01470 int
01471 util_asprintf(char **ret, const char *format, ...)
01472 #else
01473 int
01474 util_asprintf(va_alist) va_dcl
01475 #endif
01476 {
01477 #if !HAVE_STDARG_H
01478 char **ret;
01479 char *format;
01480 #endif
01481 va_list ap;
01482 int len;
01483
01484 VA_START(ap, format);
01485 VA_SHIFT(ap, ret, char **);
01486 VA_SHIFT(ap, format, const char *);
01487 len = vasprintf(ret, format, ap);
01488 va_end(ap);
01489 return len;
01490 }
01491 #endif
01492 #else
01493 int main(void);
01494 #endif
01495
01496
01497