Annotation of ircnowd/src/portab/vsnprintf.c, Revision 1.1
1.1 ! tomglok 1: /*
! 2: * ngIRCd -- The Next Generation IRC Daemon
! 3: * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify
! 6: * it under the terms of the GNU General Public License as published by
! 7: * the Free Software Foundation; either version 2 of the License, or
! 8: * (at your option) any later version.
! 9: * Please read the file COPYING, README and AUTHORS for more information.
! 10: */
! 11:
! 12: #include "portab.h"
! 13:
! 14: /**
! 15: * @file
! 16: * snprintf() and vsnprintf() replacement functions
! 17: */
! 18:
! 19: /*
! 20: * snprintf.c: Copyright Patrick Powell 1995
! 21: * This code is based on code written by Patrick Powell (papowell@astart.com)
! 22: * It may be used for any purpose as long as this notice remains intact
! 23: * on all source code distributions
! 24: *
! 25: * Original: Patrick Powell Tue Apr 11 09:48:21 PDT 1995
! 26: * A bombproof version of doprnt (dopr) included.
! 27: * Sigh. This sort of thing is always nasty do deal with. Note that
! 28: * the version here does not include floating point...
! 29: *
! 30: * snprintf() is used instead of sprintf() as it does limit checks
! 31: * for string length. This covers a nasty loophole.
! 32: *
! 33: * The other functions are there to prevent NULL pointers from
! 34: * causing nast effects.
! 35: *
! 36: * More Recently:
! 37: * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
! 38: * This was ugly. It is still ugly. I opted out of floating point
! 39: * numbers, but the formatter understands just about everything
! 40: * from the normal C string format, at least as far as I can tell from
! 41: * the Solaris 2.5 printf(3S) man page.
! 42: *
! 43: * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
! 44: * Ok, added some minimal floating point support, which means this
! 45: * probably requires libm on most operating systems. Don't yet
! 46: * support the exponent (e,E) and sigfig (g,G). Also, fmtint()
! 47: * was pretty badly broken, it just wasn't being exercised in ways
! 48: * which showed it, so that's been fixed. Also, formated the code
! 49: * to mutt conventions, and removed dead code left over from the
! 50: * original. Also, there is now a builtin-test, just compile with:
! 51: * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
! 52: * and run snprintf for results.
! 53: *
! 54: * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
! 55: * The PGP code was using unsigned hexadecimal formats.
! 56: * Unfortunately, unsigned formats simply didn't work.
! 57: *
! 58: * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
! 59: * The original code assumed that both snprintf() and vsnprintf() were
! 60: * missing. Some systems only have snprintf() but not vsnprintf(), so
! 61: * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
! 62: *
! 63: * Andrew Tridgell <tridge@samba.org>, October 1998
! 64: * fixed handling of %.0f
! 65: * added test for HAVE_LONG_DOUBLE
! 66: *
! 67: * tridge@samba.org, idra@samba.org, April 2001
! 68: * got rid of fcvt code (twas buggy and made testing harder)
! 69: * added C99 semantics
! 70: *
! 71: * Alexander Barton, <alex@barton.de>, 2002-05-19
! 72: * removed [v]asprintf() and C99 tests: not needed by ngIRCd.
! 73: */
! 74:
! 75: #ifdef HAVE_STRING_H
! 76: #include <string.h>
! 77: #endif
! 78: #ifdef HAVE_STRINGS_H
! 79: #include <strings.h>
! 80: #endif
! 81: #ifdef HAVE_CTYPE_H
! 82: #include <ctype.h>
! 83: #endif
! 84: #include <sys/types.h>
! 85: #include <stdarg.h>
! 86: #ifdef HAVE_STDLIB_H
! 87: #include <stdlib.h>
! 88: #endif
! 89:
! 90: #if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF)
! 91: /* only include stdio.h if we are not re-defining snprintf or vsnprintf */
! 92: #include <stdio.h>
! 93: /* make the compiler happy with an empty file */
! 94: void dummy_snprintf PARAMS(( void ));
! 95: void dummy_snprintf PARAMS(( void )) { }
! 96: #else
! 97:
! 98: #ifdef HAVE_LONG_DOUBLE
! 99: #define LDOUBLE long double
! 100: #else
! 101: #define LDOUBLE double
! 102: #endif
! 103:
! 104: #ifdef HAVE_LONG_LONG
! 105: #define LLONG long long
! 106: #else
! 107: #define LLONG long
! 108: #endif
! 109:
! 110: static size_t dopr PARAMS((char *buffer, size_t maxlen, const char *format,
! 111: va_list args));
! 112: static void fmtstr PARAMS((char *buffer, size_t *currlen, size_t maxlen,
! 113: char *value, int flags, int min, int max));
! 114: static void fmtint PARAMS((char *buffer, size_t *currlen, size_t maxlen,
! 115: long value, int base, int min, int max, int flags));
! 116: static void fmtfp PARAMS((char *buffer, size_t *currlen, size_t maxlen,
! 117: LDOUBLE fvalue, int min, int max, int flags));
! 118: static void dopr_outch PARAMS((char *buffer, size_t *currlen, size_t maxlen,
! 119: char c));
! 120:
! 121: /*
! 122: * dopr(): poor man's version of doprintf
! 123: */
! 124:
! 125: /* format read states */
! 126: #define DP_S_DEFAULT 0
! 127: #define DP_S_FLAGS 1
! 128: #define DP_S_MIN 2
! 129: #define DP_S_DOT 3
! 130: #define DP_S_MAX 4
! 131: #define DP_S_MOD 5
! 132: #define DP_S_CONV 6
! 133: #define DP_S_DONE 7
! 134:
! 135: /* format flags - Bits */
! 136: #define DP_F_MINUS (1 << 0)
! 137: #define DP_F_PLUS (1 << 1)
! 138: #define DP_F_SPACE (1 << 2)
! 139: #define DP_F_NUM (1 << 3)
! 140: #define DP_F_ZERO (1 << 4)
! 141: #define DP_F_UP (1 << 5)
! 142: #define DP_F_UNSIGNED (1 << 6)
! 143:
! 144: /* Conversion Flags */
! 145: #define DP_C_SHORT 1
! 146: #define DP_C_LONG 2
! 147: #define DP_C_LDOUBLE 3
! 148: #define DP_C_LLONG 4
! 149:
! 150: #define char_to_int(p) ((p)- '0')
! 151: #ifndef MAX
! 152: #define MAX(p,q) (((p) >= (q)) ? (p) : (q))
! 153: #endif
! 154:
! 155: static size_t
! 156: dopr(char *buffer, size_t maxlen, const char *format, va_list args)
! 157: {
! 158: char ch;
! 159: LLONG value;
! 160: LDOUBLE fvalue;
! 161: char *strvalue;
! 162: int min;
! 163: int max;
! 164: int state;
! 165: int flags;
! 166: int cflags;
! 167: size_t currlen;
! 168:
! 169: state = DP_S_DEFAULT;
! 170: currlen = flags = cflags = min = 0;
! 171: max = -1;
! 172: ch = *format++;
! 173:
! 174: while (state != DP_S_DONE) {
! 175: if (ch == '\0')
! 176: state = DP_S_DONE;
! 177:
! 178: switch(state) {
! 179: case DP_S_DEFAULT:
! 180: if (ch == '%')
! 181: state = DP_S_FLAGS;
! 182: else
! 183: dopr_outch (buffer, &currlen, maxlen, ch);
! 184: ch = *format++;
! 185: break;
! 186: case DP_S_FLAGS:
! 187: switch (ch) {
! 188: case '-':
! 189: flags |= DP_F_MINUS;
! 190: ch = *format++;
! 191: break;
! 192: case '+':
! 193: flags |= DP_F_PLUS;
! 194: ch = *format++;
! 195: break;
! 196: case ' ':
! 197: flags |= DP_F_SPACE;
! 198: ch = *format++;
! 199: break;
! 200: case '#':
! 201: flags |= DP_F_NUM;
! 202: ch = *format++;
! 203: break;
! 204: case '0':
! 205: flags |= DP_F_ZERO;
! 206: ch = *format++;
! 207: break;
! 208: default:
! 209: state = DP_S_MIN;
! 210: break;
! 211: }
! 212: break;
! 213: case DP_S_MIN:
! 214: if (isdigit((unsigned char)ch)) {
! 215: min = 10*min + char_to_int (ch);
! 216: ch = *format++;
! 217: } else if (ch == '*') {
! 218: min = va_arg (args, int);
! 219: ch = *format++;
! 220: state = DP_S_DOT;
! 221: } else {
! 222: state = DP_S_DOT;
! 223: }
! 224: break;
! 225: case DP_S_DOT:
! 226: if (ch == '.') {
! 227: state = DP_S_MAX;
! 228: ch = *format++;
! 229: } else {
! 230: state = DP_S_MOD;
! 231: }
! 232: break;
! 233: case DP_S_MAX:
! 234: if (isdigit((unsigned char)ch)) {
! 235: if (max < 0)
! 236: max = 0;
! 237: max = 10*max + char_to_int (ch);
! 238: ch = *format++;
! 239: } else if (ch == '*') {
! 240: max = va_arg (args, int);
! 241: ch = *format++;
! 242: state = DP_S_MOD;
! 243: } else {
! 244: state = DP_S_MOD;
! 245: }
! 246: break;
! 247: case DP_S_MOD:
! 248: switch (ch) {
! 249: case 'h':
! 250: cflags = DP_C_SHORT;
! 251: ch = *format++;
! 252: break;
! 253: case 'l':
! 254: cflags = DP_C_LONG;
! 255: ch = *format++;
! 256: if (ch == 'l') { /* It's a long long */
! 257: cflags = DP_C_LLONG;
! 258: ch = *format++;
! 259: }
! 260: break;
! 261: case 'L':
! 262: cflags = DP_C_LDOUBLE;
! 263: ch = *format++;
! 264: break;
! 265: default:
! 266: break;
! 267: }
! 268: state = DP_S_CONV;
! 269: break;
! 270: case DP_S_CONV:
! 271: switch (ch) {
! 272: case 'd':
! 273: case 'i':
! 274: if (cflags == DP_C_SHORT)
! 275: value = va_arg (args, int);
! 276: else if (cflags == DP_C_LONG)
! 277: value = va_arg (args, long int);
! 278: else if (cflags == DP_C_LLONG)
! 279: value = va_arg (args, LLONG);
! 280: else
! 281: value = va_arg (args, int);
! 282: fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
! 283: break;
! 284: case 'o':
! 285: flags |= DP_F_UNSIGNED;
! 286: if (cflags == DP_C_SHORT)
! 287: value = va_arg (args, unsigned int);
! 288: else if (cflags == DP_C_LONG)
! 289: value = (long)va_arg (args, unsigned long int);
! 290: else if (cflags == DP_C_LLONG)
! 291: value = (long)va_arg (args, unsigned LLONG);
! 292: else
! 293: value = (long)va_arg (args, unsigned int);
! 294: fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
! 295: break;
! 296: case 'u':
! 297: flags |= DP_F_UNSIGNED;
! 298: if (cflags == DP_C_SHORT)
! 299: value = va_arg (args, unsigned int);
! 300: else if (cflags == DP_C_LONG)
! 301: value = (long)va_arg (args, unsigned long int);
! 302: else if (cflags == DP_C_LLONG)
! 303: value = (LLONG)va_arg (args, unsigned LLONG);
! 304: else
! 305: value = (long)va_arg (args, unsigned int);
! 306: fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
! 307: break;
! 308: case 'X':
! 309: flags |= DP_F_UP;
! 310: case 'x':
! 311: flags |= DP_F_UNSIGNED;
! 312: if (cflags == DP_C_SHORT)
! 313: value = va_arg (args, unsigned int);
! 314: else if (cflags == DP_C_LONG)
! 315: value = (long)va_arg (args, unsigned long int);
! 316: else if (cflags == DP_C_LLONG)
! 317: value = (LLONG)va_arg (args, unsigned LLONG);
! 318: else
! 319: value = (long)va_arg (args, unsigned int);
! 320: fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
! 321: break;
! 322: case 'f':
! 323: if (cflags == DP_C_LDOUBLE)
! 324: fvalue = va_arg (args, LDOUBLE);
! 325: else
! 326: fvalue = va_arg (args, double);
! 327: /* um, floating point? */
! 328: fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
! 329: break;
! 330: case 'E':
! 331: flags |= DP_F_UP;
! 332: case 'e':
! 333: if (cflags == DP_C_LDOUBLE)
! 334: fvalue = va_arg (args, LDOUBLE);
! 335: else
! 336: fvalue = va_arg (args, double);
! 337: break;
! 338: case 'G':
! 339: flags |= DP_F_UP;
! 340: case 'g':
! 341: if (cflags == DP_C_LDOUBLE)
! 342: fvalue = va_arg (args, LDOUBLE);
! 343: else
! 344: fvalue = va_arg (args, double);
! 345: break;
! 346: case 'c':
! 347: dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
! 348: break;
! 349: case 's':
! 350: strvalue = va_arg (args, char *);
! 351: if (max == -1) {
! 352: max = strlen(strvalue);
! 353: }
! 354: if (min > 0 && max >= 0 && min > max) max = min;
! 355: fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
! 356: break;
! 357: case 'p':
! 358: strvalue = va_arg (args, void *);
! 359: fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
! 360: break;
! 361: case 'n':
! 362: if (cflags == DP_C_SHORT) {
! 363: short int *num;
! 364: num = va_arg (args, short int *);
! 365: *num = currlen;
! 366: } else if (cflags == DP_C_LONG) {
! 367: long int *num;
! 368: num = va_arg (args, long int *);
! 369: *num = (long int)currlen;
! 370: } else if (cflags == DP_C_LLONG) {
! 371: LLONG *num;
! 372: num = va_arg (args, LLONG *);
! 373: *num = (LLONG)currlen;
! 374: } else {
! 375: int *num;
! 376: num = va_arg (args, int *);
! 377: *num = currlen;
! 378: }
! 379: break;
! 380: case '%':
! 381: dopr_outch (buffer, &currlen, maxlen, ch);
! 382: break;
! 383: case 'w':
! 384: /* not supported yet, treat as next char */
! 385: ch = *format++;
! 386: break;
! 387: default:
! 388: /* Unknown, skip */
! 389: break;
! 390: }
! 391: ch = *format++;
! 392: state = DP_S_DEFAULT;
! 393: flags = cflags = min = 0;
! 394: max = -1;
! 395: break;
! 396: case DP_S_DONE:
! 397: break;
! 398: default:
! 399: /* hmm? */
! 400: break; /* some picky compilers need this */
! 401: }
! 402: }
! 403: if (maxlen != 0) {
! 404: if (currlen < maxlen - 1)
! 405: buffer[currlen] = '\0';
! 406: else if (maxlen > 0)
! 407: buffer[maxlen - 1] = '\0';
! 408: }
! 409:
! 410: return currlen;
! 411: }
! 412:
! 413: static void
! 414: fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags,
! 415: int min, int max)
! 416: {
! 417: int padlen, strln; /* amount to pad */
! 418: int cnt = 0;
! 419:
! 420: #ifdef DEBUG_SNPRINTF
! 421: printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
! 422: #endif
! 423: if (value == 0) {
! 424: value = "<NULL>";
! 425: }
! 426:
! 427: for (strln = 0; value[strln]; ++strln); /* strlen */
! 428: padlen = min - strln;
! 429: if (padlen < 0)
! 430: padlen = 0;
! 431: if (flags & DP_F_MINUS)
! 432: padlen = -padlen; /* Left Justify */
! 433:
! 434: while ((padlen > 0) && (cnt < max)) {
! 435: dopr_outch (buffer, currlen, maxlen, ' ');
! 436: --padlen;
! 437: ++cnt;
! 438: }
! 439: while (*value && (cnt < max)) {
! 440: dopr_outch (buffer, currlen, maxlen, *value++);
! 441: ++cnt;
! 442: }
! 443: while ((padlen < 0) && (cnt < max)) {
! 444: dopr_outch (buffer, currlen, maxlen, ' ');
! 445: ++padlen;
! 446: ++cnt;
! 447: }
! 448: }
! 449:
! 450: /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
! 451:
! 452: static void
! 453: fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,
! 454: int min, int max, int flags)
! 455: {
! 456: int signvalue = 0;
! 457: unsigned long uvalue;
! 458: char convert[20];
! 459: int place = 0;
! 460: int spadlen = 0; /* amount to space pad */
! 461: int zpadlen = 0; /* amount to zero pad */
! 462: int caps = 0;
! 463:
! 464: if (max < 0)
! 465: max = 0;
! 466:
! 467: uvalue = value;
! 468:
! 469: if(!(flags & DP_F_UNSIGNED)) {
! 470: if( value < 0 ) {
! 471: signvalue = '-';
! 472: uvalue = -value;
! 473: } else {
! 474: if (flags & DP_F_PLUS) /* Do a sign (+/i) */
! 475: signvalue = '+';
! 476: else if (flags & DP_F_SPACE)
! 477: signvalue = ' ';
! 478: }
! 479: }
! 480:
! 481: if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
! 482:
! 483: do {
! 484: convert[place++] =
! 485: (caps? "0123456789ABCDEF":"0123456789abcdef")
! 486: [uvalue % (unsigned)base ];
! 487: uvalue = (uvalue / (unsigned)base );
! 488: } while(uvalue && (place < 20));
! 489: if (place == 20) place--;
! 490: convert[place] = 0;
! 491:
! 492: zpadlen = max - place;
! 493: spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
! 494: if (zpadlen < 0) zpadlen = 0;
! 495: if (spadlen < 0) spadlen = 0;
! 496: if (flags & DP_F_ZERO) {
! 497: zpadlen = MAX(zpadlen, spadlen);
! 498: spadlen = 0;
! 499: }
! 500: if (flags & DP_F_MINUS)
! 501: spadlen = -spadlen; /* Left Justifty */
! 502:
! 503: #ifdef DEBUG_SNPRINTF
! 504: printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
! 505: zpadlen, spadlen, min, max, place);
! 506: #endif
! 507:
! 508: /* Spaces */
! 509: while (spadlen > 0) {
! 510: dopr_outch (buffer, currlen, maxlen, ' ');
! 511: --spadlen;
! 512: }
! 513:
! 514: /* Sign */
! 515: if (signvalue)
! 516: dopr_outch (buffer, currlen, maxlen, signvalue);
! 517:
! 518: /* Zeros */
! 519: if (zpadlen > 0) {
! 520: while (zpadlen > 0) {
! 521: dopr_outch (buffer, currlen, maxlen, '0');
! 522: --zpadlen;
! 523: }
! 524: }
! 525:
! 526: /* Digits */
! 527: while (place > 0)
! 528: dopr_outch (buffer, currlen, maxlen, convert[--place]);
! 529:
! 530: /* Left Justified spaces */
! 531: while (spadlen < 0) {
! 532: dopr_outch (buffer, currlen, maxlen, ' ');
! 533: ++spadlen;
! 534: }
! 535: }
! 536:
! 537: static LDOUBLE
! 538: abs_val(LDOUBLE value)
! 539: {
! 540: LDOUBLE result = value;
! 541:
! 542: if (value < 0)
! 543: result = -value;
! 544:
! 545: return result;
! 546: }
! 547:
! 548: static LDOUBLE
! 549: POW10(int exp)
! 550: {
! 551: LDOUBLE result = 1;
! 552:
! 553: while (exp) {
! 554: result *= 10;
! 555: exp--;
! 556: }
! 557:
! 558: return result;
! 559: }
! 560:
! 561: static LLONG
! 562: ROUND(LDOUBLE value)
! 563: {
! 564: LLONG intpart;
! 565:
! 566: intpart = (LLONG)value;
! 567: value = value - intpart;
! 568: if (value >= 0.5) intpart++;
! 569:
! 570: return intpart;
! 571: }
! 572:
! 573: /* a replacement for modf that doesn't need the math library. Should
! 574: be portable, but slow */
! 575: static double
! 576: my_modf(double x0, double *iptr)
! 577: {
! 578: int i;
! 579: long l;
! 580: double x = x0;
! 581: double f = 1.0;
! 582:
! 583: for (i=0;i<100;i++) {
! 584: l = (long)x;
! 585: if (l <= (x+1) && l >= (x-1)) break;
! 586: x *= 0.1;
! 587: f *= 10.0;
! 588: }
! 589:
! 590: if (i == 100) {
! 591: /* yikes! the number is beyond what we can handle. What do we do? */
! 592: (*iptr) = 0;
! 593: return 0;
! 594: }
! 595:
! 596: if (i != 0) {
! 597: double i2;
! 598: double ret;
! 599:
! 600: ret = my_modf(x0-l*f, &i2);
! 601: (*iptr) = l*f + i2;
! 602: return ret;
! 603: }
! 604:
! 605: (*iptr) = l;
! 606: return x - (*iptr);
! 607: }
! 608:
! 609:
! 610: static void
! 611: fmtfp (char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue,
! 612: int min, int max, int flags)
! 613: {
! 614: int signvalue = 0;
! 615: double ufvalue;
! 616: char iconvert[311];
! 617: char fconvert[311];
! 618: int iplace = 0;
! 619: int fplace = 0;
! 620: int padlen = 0; /* amount to pad */
! 621: int zpadlen = 0;
! 622: int caps = 0;
! 623: int index;
! 624: double intpart;
! 625: double fracpart;
! 626: double temp;
! 627:
! 628: /*
! 629: * AIX manpage says the default is 0, but Solaris says the default
! 630: * is 6, and sprintf on AIX defaults to 6
! 631: */
! 632: if (max < 0)
! 633: max = 6;
! 634:
! 635: ufvalue = abs_val (fvalue);
! 636:
! 637: if (fvalue < 0) {
! 638: signvalue = '-';
! 639: } else {
! 640: if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
! 641: signvalue = '+';
! 642: } else {
! 643: if (flags & DP_F_SPACE)
! 644: signvalue = ' ';
! 645: }
! 646: }
! 647:
! 648: /*
! 649: * Sorry, we only support 16 digits past the decimal because of our
! 650: * conversion method
! 651: */
! 652: if (max > 16)
! 653: max = 16;
! 654:
! 655: /* We "cheat" by converting the fractional part to integer by
! 656: * multiplying by a factor of 10
! 657: */
! 658:
! 659: temp = ufvalue;
! 660: my_modf(temp, &intpart);
! 661:
! 662: fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
! 663:
! 664: if (fracpart >= POW10(max)) {
! 665: intpart++;
! 666: fracpart -= POW10(max);
! 667: }
! 668:
! 669:
! 670: /* Convert integer part */
! 671: do {
! 672: temp = intpart;
! 673: my_modf(intpart*0.1, &intpart);
! 674: temp = temp*0.1;
! 675: index = (int) ((temp -intpart +0.05)* 10.0);
! 676: /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
! 677: /* printf ("%llf, %f, %x\n", temp, intpart, index); */
! 678: iconvert[iplace++] =
! 679: (caps? "0123456789ABCDEF":"0123456789abcdef")[index];
! 680: } while (intpart && (iplace < 311));
! 681: if (iplace == 311) iplace--;
! 682: iconvert[iplace] = 0;
! 683:
! 684: /* Convert fractional part */
! 685: if (fracpart)
! 686: {
! 687: do {
! 688: temp = fracpart;
! 689: my_modf(fracpart*0.1, &fracpart);
! 690: temp = temp*0.1;
! 691: index = (int) ((temp -fracpart +0.05)* 10.0);
! 692: /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */
! 693: /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */
! 694: fconvert[fplace++] =
! 695: (caps? "0123456789ABCDEF":"0123456789abcdef")[index];
! 696: } while(fracpart && (fplace < 311));
! 697: if (fplace == 311) fplace--;
! 698: }
! 699: fconvert[fplace] = 0;
! 700:
! 701: /* -1 for decimal point, another -1 if we are printing a sign */
! 702: padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
! 703: zpadlen = max - fplace;
! 704: if (zpadlen < 0) zpadlen = 0;
! 705: if (padlen < 0)
! 706: padlen = 0;
! 707: if (flags & DP_F_MINUS)
! 708: padlen = -padlen; /* Left Justifty */
! 709:
! 710: if ((flags & DP_F_ZERO) && (padlen > 0)) {
! 711: if (signvalue) {
! 712: dopr_outch (buffer, currlen, maxlen, signvalue);
! 713: --padlen;
! 714: signvalue = 0;
! 715: }
! 716: while (padlen > 0) {
! 717: dopr_outch (buffer, currlen, maxlen, '0');
! 718: --padlen;
! 719: }
! 720: }
! 721: while (padlen > 0) {
! 722: dopr_outch (buffer, currlen, maxlen, ' ');
! 723: --padlen;
! 724: }
! 725: if (signvalue)
! 726: dopr_outch (buffer, currlen, maxlen, signvalue);
! 727:
! 728: while (iplace > 0)
! 729: dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
! 730:
! 731: #ifdef DEBUG_SNPRINTF
! 732: printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
! 733: #endif
! 734:
! 735: /*
! 736: * Decimal point. This should probably use locale to find the correct
! 737: * char to print out.
! 738: */
! 739: if (max > 0) {
! 740: dopr_outch (buffer, currlen, maxlen, '.');
! 741:
! 742: while (fplace > 0)
! 743: dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
! 744: }
! 745:
! 746: while (zpadlen > 0) {
! 747: dopr_outch (buffer, currlen, maxlen, '0');
! 748: --zpadlen;
! 749: }
! 750:
! 751: while (padlen < 0) {
! 752: dopr_outch (buffer, currlen, maxlen, ' ');
! 753: ++padlen;
! 754: }
! 755: }
! 756:
! 757: static void
! 758: dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
! 759: {
! 760: if (*currlen < maxlen) {
! 761: buffer[(*currlen)] = c;
! 762: }
! 763: (*currlen)++;
! 764: }
! 765:
! 766: #if !defined(HAVE_VSNPRINTF)
! 767: int
! 768: vsnprintf (char *str, size_t count, const char *fmt, va_list args)
! 769: {
! 770: return dopr(str, count, fmt, args);
! 771: }
! 772: #endif
! 773:
! 774: #if !defined(HAVE_SNPRINTF)
! 775: #ifdef PROTOTYPES
! 776: int
! 777: snprintf(char *str, size_t count, const char *fmt, ...)
! 778: #else
! 779: int
! 780: snprintf(str, count, fmt, va_alist)
! 781: char *str;
! 782: size_t count;
! 783: const char *fmt;
! 784: va_dcl
! 785: #endif
! 786: {
! 787: size_t ret;
! 788: va_list ap;
! 789:
! 790: va_start(ap, fmt);
! 791: ret = vsnprintf(str, count, fmt, ap);
! 792: va_end(ap);
! 793: return ret;
! 794: }
! 795: #endif
! 796:
! 797: #endif
! 798:
! 799: /* -eof- */
CVSweb