[BACK]Return to vsnprintf.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / portab

Annotation of ircnowd/src/portab/vsnprintf.c, Revision 1.1.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