Annotation of researchv10no/libc/stdio/vfprintf.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * pANS stdio -- vfprintf
                      3:  */
                      4: #include "iolib.h"
                      5: #include <stdarg.h>
                      6: #include <math.h>
                      7: #include <stdlib.h>
                      8: #include <string.h>
                      9: /*
                     10:  * Leading flags
                     11:  */
                     12: #define        SPACE   1               /* ' ' prepend space if no sign printed */
                     13: #define        ALT     2               /* '#' use alternate conversion */
                     14: #define        SIGN    4               /* '+' prepend sign, even if positive */
                     15: #define        LEFT    8               /* '-' left-justify */
                     16: #define        ZPAD    16              /* '0' zero-pad */
                     17: /*
                     18:  * Trailing flags
                     19:  */
                     20: #define        SHORT   32              /* 'h' convert a short integer */
                     21: #define        LONG    64              /* 'l' convert a long integer */
                     22: #define        LDBL    128             /* 'L' convert a long double */
                     23: #define        PTR     256             /*     convert a void * (%p) */
                     24: 
                     25: static int lflag[] = { /* leading flags */
                     26: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^@ ^A ^B ^C ^D ^E ^F ^G */
                     27: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^H ^I ^J ^K ^L ^M ^N ^O */
                     28: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^P ^Q ^R ^S ^T ^U ^V ^W */
                     29: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
                     30: SPACE, 0,      0,      ALT,    0,      0,      0,      0,      /* sp  !  "  #  $  %  &  ' */
                     31: 0,     0,      0,      SIGN,   0,      LEFT,   0,      0,      /*  (  )  *  +  ,  -  .  / */
                     32: ZPAD,  0,      0,      0,      0,      0,      0,      0,      /*  0  1  2  3  4  5  6  7 */
                     33: 0,     0,      0,      0,      0,      0,      0,      0,      /*  8  9  :  ;  <  =  >  ? */
                     34: 0,     0,      0,      0,      0,      0,      0,      0,      /*  @  A  B  C  D  E  F  G */
                     35: 0,     0,      0,      0,      0,      0,      0,      0,      /*  H  I  J  K  L  M  N  O */
                     36: 0,     0,      0,      0,      0,      0,      0,      0,      /*  P  Q  R  S  T  U  V  W */
                     37: 0,     0,      0,      0,      0,      0,      0,      0,      /*  X  Y  Z  [  \  ]  ^  _ */
                     38: 0,     0,      0,      0,      0,      0,      0,      0,      /*  `  a  b  c  d  e  f  g */
                     39: 0,     0,      0,      0,      0,      0,      0,      0,      /*  h  i  j  k  l  m  n  o */
                     40: 0,     0,      0,      0,      0,      0,      0,      0,      /*  p  q  r  s  t  u  v  w */
                     41: 0,     0,      0,      0,      0,      0,      0,      0,      /*  x  y  z  {  |  }  ~ ^? */
                     42: 
                     43: 0,     0,      0,      0,      0,      0,      0,      0,
                     44: 0,     0,      0,      0,      0,      0,      0,      0,
                     45: 0,     0,      0,      0,      0,      0,      0,      0,
                     46: 0,     0,      0,      0,      0,      0,      0,      0,
                     47: 0,     0,      0,      0,      0,      0,      0,      0,
                     48: 0,     0,      0,      0,      0,      0,      0,      0,
                     49: 0,     0,      0,      0,      0,      0,      0,      0,
                     50: 0,     0,      0,      0,      0,      0,      0,      0,
                     51: 0,     0,      0,      0,      0,      0,      0,      0,
                     52: 0,     0,      0,      0,      0,      0,      0,      0,
                     53: 0,     0,      0,      0,      0,      0,      0,      0,
                     54: 0,     0,      0,      0,      0,      0,      0,      0,
                     55: 0,     0,      0,      0,      0,      0,      0,      0,
                     56: 0,     0,      0,      0,      0,      0,      0,      0,
                     57: 0,     0,      0,      0,      0,      0,      0,      0,
                     58: 0,     0,      0,      0,      0,      0,      0,      0,
                     59: };
                     60: 
                     61: static int tflag[] = { /* trailing flags */
                     62: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^@ ^A ^B ^C ^D ^E ^F ^G */
                     63: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^H ^I ^J ^K ^L ^M ^N ^O */
                     64: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^P ^Q ^R ^S ^T ^U ^V ^W */
                     65: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
                     66: 0,     0,      0,      0,      0,      0,      0,      0,      /* sp  !  "  #  $  %  &  ' */
                     67: 0,     0,      0,      0,      0,      0,      0,      0,      /*  (  )  *  +  ,  -  .  / */
                     68: 0,     0,      0,      0,      0,      0,      0,      0,      /*  0  1  2  3  4  5  6  7 */
                     69: 0,     0,      0,      0,      0,      0,      0,      0,      /*  8  9  :  ;  <  =  >  ? */
                     70: 0,     0,      0,      0,      0,      0,      0,      0,      /*  @  A  B  C  D  E  F  G */
                     71: 0,     0,      0,      0,      LDBL,   0,      0,      0,      /*  H  I  J  K  L  M  N  O */
                     72: 0,     0,      0,      0,      0,      0,      0,      0,      /*  P  Q  R  S  T  U  V  W */
                     73: 0,     0,      0,      0,      0,      0,      0,      0,      /*  X  Y  Z  [  \  ]  ^  _ */
                     74: 0,     0,      0,      0,      0,      0,      0,      0,      /*  `  a  b  c  d  e  f  g */
                     75: SHORT, 0,      0,      0,      LONG,   0,      0,      0,      /*  h  i  j  k  l  m  n  o */
                     76: 0,     0,      0,      0,      0,      0,      0,      0,      /*  p  q  r  s  t  u  v  w */
                     77: 0,     0,      0,      0,      0,      0,      0,      0,      /*  x  y  z  {  |  }  ~ ^? */
                     78: 
                     79: 0,     0,      0,      0,      0,      0,      0,      0,
                     80: 0,     0,      0,      0,      0,      0,      0,      0,
                     81: 0,     0,      0,      0,      0,      0,      0,      0,
                     82: 0,     0,      0,      0,      0,      0,      0,      0,
                     83: 0,     0,      0,      0,      0,      0,      0,      0,
                     84: 0,     0,      0,      0,      0,      0,      0,      0,
                     85: 0,     0,      0,      0,      0,      0,      0,      0,
                     86: 0,     0,      0,      0,      0,      0,      0,      0,
                     87: 0,     0,      0,      0,      0,      0,      0,      0,
                     88: 0,     0,      0,      0,      0,      0,      0,      0,
                     89: 0,     0,      0,      0,      0,      0,      0,      0,
                     90: 0,     0,      0,      0,      0,      0,      0,      0,
                     91: 0,     0,      0,      0,      0,      0,      0,      0,
                     92: 0,     0,      0,      0,      0,      0,      0,      0,
                     93: 0,     0,      0,      0,      0,      0,      0,      0,
                     94: 0,     0,      0,      0,      0,      0,      0,      0,
                     95: };
                     96: 
                     97: static int ocvt_E(FILE *, va_list *, int, int, int);
                     98: static int ocvt_G(FILE *, va_list *, int, int, int);
                     99: static int ocvt_X(FILE *, va_list *, int, int, int);
                    100: static int ocvt_c(FILE *, va_list *, int, int, int);
                    101: static int ocvt_d(FILE *, va_list *, int, int, int);
                    102: static int ocvt_e(FILE *, va_list *, int, int, int);
                    103: static int ocvt_f(FILE *, va_list *, int, int, int);
                    104: static int ocvt_g(FILE *, va_list *, int, int, int);
                    105: static int ocvt_n(FILE *, va_list *, int, int, int);
                    106: static int ocvt_o(FILE *, va_list *, int, int, int);
                    107: static int ocvt_p(FILE *, va_list *, int, int, int);
                    108: static int ocvt_s(FILE *, va_list *, int, int, int);
                    109: static int ocvt_u(FILE *, va_list *, int, int, int);
                    110: static int ocvt_x(FILE *, va_list *, int, int, int);
                    111: 
                    112: static int(*ocvt[])(FILE *, va_list *, int, int, int) = {
                    113: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^@ ^A ^B ^C ^D ^E ^F ^G */
                    114: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^H ^I ^J ^K ^L ^M ^N ^O */
                    115: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^P ^Q ^R ^S ^T ^U ^V ^W */
                    116: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
                    117: 0,     0,      0,      0,      0,      0,      0,      0,      /* sp  !  "  #  $  %  &  ' */
                    118: 0,     0,      0,      0,      0,      0,      0,      0,      /*  (  )  *  +  ,  -  .  / */
                    119: 0,     0,      0,      0,      0,      0,      0,      0,      /*  0  1  2  3  4  5  6  7 */
                    120: 0,     0,      0,      0,      0,      0,      0,      0,      /*  8  9  :  ;  <  =  >  ? */
                    121: 0,     0,      0,      0,      0,      ocvt_E, 0,      ocvt_G, /*  @  A  B  C  D  E  F  G */
                    122: 0,     0,      0,      0,      0,      0,      0,      0,      /*  H  I  J  K  L  M  N  O */
                    123: 0,     0,      0,      0,      0,      0,      0,      0,      /*  P  Q  R  S  T  U  V  W */
                    124: ocvt_X,        0,      0,      0,      0,      0,      0,      0,      /*  X  Y  Z  [  \  ]  ^  _ */
                    125: 0,     0,      0,      ocvt_c, ocvt_d, ocvt_e, ocvt_f, ocvt_g, /*  `  a  b  c  d  e  f  g */
                    126: 0,     ocvt_d, 0,      0,      0,      0,      ocvt_n, ocvt_o, /*  h  i  j  k  l  m  n  o */
                    127: ocvt_p,        0,      0,      ocvt_s, 0,      ocvt_u, 0,      0,      /*  p  q  r  s  t  u  v  w */
                    128: ocvt_x,        0,      0,      0,      0,      0,      0,      0,      /*  x  y  z  {  |  }  ~ ^? */
                    129: 
                    130: 0,     0,      0,      0,      0,      0,      0,      0,
                    131: 0,     0,      0,      0,      0,      0,      0,      0,
                    132: 0,     0,      0,      0,      0,      0,      0,      0,
                    133: 0,     0,      0,      0,      0,      0,      0,      0,
                    134: 0,     0,      0,      0,      0,      0,      0,      0,
                    135: 0,     0,      0,      0,      0,      0,      0,      0,
                    136: 0,     0,      0,      0,      0,      0,      0,      0,
                    137: 0,     0,      0,      0,      0,      0,      0,      0,
                    138: 0,     0,      0,      0,      0,      0,      0,      0,
                    139: 0,     0,      0,      0,      0,      0,      0,      0,
                    140: 0,     0,      0,      0,      0,      0,      0,      0,
                    141: 0,     0,      0,      0,      0,      0,      0,      0,
                    142: 0,     0,      0,      0,      0,      0,      0,      0,
                    143: 0,     0,      0,      0,      0,      0,      0,      0,
                    144: 0,     0,      0,      0,      0,      0,      0,      0,
                    145: 0,     0,      0,      0,      0,      0,      0,      0,
                    146: };
                    147: 
                    148: static int nprint;
                    149: 
                    150: int
                    151: vfprintf(FILE *f, const char *s, va_list args)
                    152: {
                    153:        int flags, width, precision;
                    154: 
                    155:        nprint = 0;
                    156:        while(*s){
                    157:                if(*s != '%'){
                    158:                        putc(*s++, f);
                    159:                        nprint++;
                    160:                        continue;
                    161:                }
                    162:                s++;
                    163:                flags = 0;
                    164:                while(lflag[*s&_IO_CHMASK]) flags |= lflag[*s++&_IO_CHMASK];
                    165:                if(*s == '*'){
                    166:                        width = va_arg(args, int);
                    167:                        s++;
                    168:                        if(width<0){
                    169:                                flags |= LEFT;
                    170:                                width = -width;
                    171:                        }
                    172:                }
                    173:                else{
                    174:                        width = 0;
                    175:                        while('0'<=*s && *s<='9') width = width*10 + *s++ - '0';
                    176:                }
                    177:                if(*s == '.'){
                    178:                        s++;
                    179:                        if(*s == '*'){
                    180:                                precision = va_arg(args, int);
                    181:                                s++;
                    182:                        }
                    183:                        else{
                    184:                                precision = 0;
                    185:                                while('0'<=*s && *s<='9') precision = precision*10 + *s++ - '0';
                    186:                        }
                    187:                }
                    188:                else
                    189:                        precision = -1;
                    190:                while(tflag[*s&_IO_CHMASK]) flags |= tflag[*s++&_IO_CHMASK];
                    191:                if(ocvt[*s]) nprint += (*ocvt[*s++])(f, &args, flags, width, precision);
                    192:                else if(*s){
                    193:                        putc(*s++, f);
                    194:                        nprint++;
                    195:                }
                    196:        }
                    197:        return ferror(f)? -1: nprint;   /* previous errors */
                    198:                                        /* will be re-reported */
                    199: }
                    200: 
                    201: static int
                    202: ocvt_c(FILE *f, va_list *args, int flags, int width, int precision)
                    203: {
                    204: #pragma ref precision
                    205:        int i;
                    206: 
                    207:        if(!(flags&LEFT)) for(i=1; i<width; i++) putc(' ', f);
                    208:        putc((unsigned char)va_arg(*args, int), f);
                    209:        if(flags&LEFT) for(i=1; i<width; i++) putc(' ', f);
                    210:        return width<1 ? 1 : width;
                    211: }
                    212: 
                    213: static int
                    214: ocvt_s(FILE *f, va_list *args, int flags, int width, int precision)
                    215: {
                    216:        int i, n = 0;
                    217:        char *s;
                    218: 
                    219:        s = va_arg(*args, char *);
                    220:        if(!(flags&LEFT)){
                    221:                if(precision >= 0)
                    222:                        for(i=0; i!=precision && s[i]; i++);
                    223:                else
                    224:                        for(i=0; s[i]; i++);
                    225:                for(; i<width; i++){
                    226:                        putc(' ', f);
                    227:                        n++;
                    228:                }
                    229:        }
                    230:        if(precision >= 0){
                    231:                for(i=0; i!=precision && *s; i++){
                    232:                        putc(*s++, f);
                    233:                        n++;
                    234:                }
                    235:        } else{
                    236:                for(i=0;*s;i++){
                    237:                        putc(*s++, f);
                    238:                        n++;
                    239:                }
                    240:        }
                    241:        if(flags&LEFT){
                    242:                for(; i<width; i++){
                    243:                        putc(' ', f);
                    244:                        n++;
                    245:                }
                    246:        }
                    247:        return n;
                    248: }
                    249: 
                    250: static int
                    251: ocvt_n(FILE *f, va_list *args, int flags, int width, int precision)
                    252: {
                    253: #pragma ref f
                    254: #pragma ref width
                    255: #pragma ref precision
                    256:        if(flags&SHORT)
                    257:                *va_arg(*args, short *) = nprint;
                    258:        else if(flags&LONG)
                    259:                *va_arg(*args, long *) = nprint;
                    260:        else
                    261:                *va_arg(*args, int *) = nprint;
                    262:        return 0;
                    263: }
                    264: 
                    265: /*
                    266:  * Generic fixed-point conversion
                    267:  *     f is the output FILE *;
                    268:  *     args is the va_list * from which to get the number;
                    269:  *     flags, width and precision are the results of printf-cracking;
                    270:  *     radix is the number base to print in;
                    271:  *     alphabet is the set of digits to use;
                    272:  *     prefix is the prefix to print before non-zero numbers when
                    273:  *     using ``alternate form.''
                    274:  */
                    275: static int
                    276: ocvt_fixed(FILE *f, va_list *args, int flags, int width, int precision,
                    277:        int radix, int sgned, char alphabet[], char *prefix)
                    278: {
                    279:        char digits[128];       /* no reasonable machine will ever overflow this */
                    280:        char *sign;
                    281:        char *dp;
                    282:        long snum;
                    283:        unsigned long num;
                    284:        int c, nout, npad, nlzero;
                    285: 
                    286:        if(sgned){
                    287:                if(flags&PTR) snum = (long)va_arg(*args, void *);
                    288:                else if(flags&SHORT) snum = va_arg(*args, short);
                    289:                else if(flags&LONG) snum = va_arg(*args, long);
                    290:                else snum = va_arg(*args, int);
                    291:                if(snum < 0){
                    292:                        sign = "-";
                    293:                        num = -snum;
                    294:                } else{
                    295:                        if(flags&SIGN) sign = "+";
                    296:                        else if(flags&SPACE) sign = " ";
                    297:                        else sign = "";
                    298:                        num = snum;
                    299:                }
                    300:        } else {
                    301:                sign = "";
                    302:                if(flags&PTR) num = (long)va_arg(*args, void *);
                    303:                else if(flags&SHORT) num = va_arg(*args, unsigned short);
                    304:                else if(flags&LONG) num = va_arg(*args, unsigned long);
                    305:                else num = va_arg(*args, unsigned int);
                    306:        }
                    307:        if(num == 0) prefix = "";
                    308:        dp = digits;
                    309:        do{
                    310:                *dp++ = alphabet[num%radix];
                    311:                num /= radix;
                    312:        }while(num);
                    313:        if(precision==0 && dp-digits==1 && dp[-1]=='0')
                    314:                dp--;
                    315:        nlzero = precision-(dp-digits);
                    316:        if(nlzero < 0) nlzero = 0;
                    317:        if(flags&ALT){
                    318:                if(radix == 8) if(dp[-1]=='0' || nlzero) prefix = "";
                    319:        }
                    320:        else prefix = "";
                    321:        nout = dp-digits+nlzero+strlen(prefix)+strlen(sign);
                    322:        npad = width-nout;
                    323:        if(npad < 0) npad = 0;
                    324:        nout += npad;
                    325:        if(!(flags&LEFT)){
                    326:                if(flags&ZPAD && precision <= 0){
                    327:                        /* for sgi, we get a loop if we invoke puts here */
                    328:                        while(c = *sign++)
                    329:                                putc(c, f);
                    330:                        while(c = *prefix++)
                    331:                                putc(c, f);
                    332:                        while(npad){
                    333:                                putc('0', f);
                    334:                                --npad;
                    335:                        }
                    336:                } else{
                    337:                        while(npad){
                    338:                                putc(' ', f);
                    339:                                --npad;
                    340:                        }
                    341:                        while(c = *sign++)
                    342:                                putc(c, f);
                    343:                        while(c = *prefix++)
                    344:                                putc(c, f);
                    345:                }
                    346:                while(nlzero){
                    347:                        putc('0', f);
                    348:                        --nlzero;
                    349:                }
                    350:                while(dp!=digits) putc(*--dp, f);
                    351:        }
                    352:        else{
                    353:                while(c = *sign++)
                    354:                        putc(c, f);
                    355:                while(c = *prefix++)
                    356:                        putc(c, f);
                    357:                while(nlzero){
                    358:                        putc('0', f);
                    359:                        --nlzero;
                    360:                }
                    361:                while(dp != digits) putc(*--dp, f);
                    362:                while(npad){
                    363:                        putc(' ', f);
                    364:                        --npad;
                    365:                }
                    366:        }
                    367:        return nout;    
                    368: }
                    369: 
                    370: static int
                    371: ocvt_X(FILE *f, va_list *args, int flags, int width, int precision)
                    372: {
                    373:        return ocvt_fixed(f, args, flags, width, precision, 16, 0, "0123456789ABCDEF", "0X");
                    374: }
                    375: 
                    376: static int
                    377: ocvt_d(FILE *f, va_list *args, int flags, int width, int precision)
                    378: {
                    379:        return ocvt_fixed(f, args, flags, width, precision, 10, 1, "0123456789", "");
                    380: }
                    381: 
                    382: static int
                    383: ocvt_o(FILE *f, va_list *args, int flags, int width, int precision)
                    384: {
                    385:        return ocvt_fixed(f, args, flags, width, precision, 8, 0, "01234567", "0");
                    386: }
                    387: 
                    388: static int
                    389: ocvt_p(FILE *f, va_list *args, int flags, int width, int precision)
                    390: {
                    391:        return ocvt_fixed(f, args, flags|PTR|ALT, width, precision, 16, 0,
                    392:                "0123456789ABCDEF", "0X");
                    393: }
                    394: 
                    395: static int
                    396: ocvt_u(FILE *f, va_list *args, int flags, int width, int precision)
                    397: {
                    398:        return ocvt_fixed(f, args, flags, width, precision, 10, 0, "0123456789", "");
                    399: }
                    400: 
                    401: static int
                    402: ocvt_x(FILE *f, va_list *args, int flags, int width, int precision)
                    403: {
                    404:        return ocvt_fixed(f, args, flags, width, precision, 16, 0, "0123456789abcdef", "0x");
                    405: }
                    406: 
                    407: static int ocvt_flt(FILE *, va_list *, int, int, int, char);
                    408: 
                    409: static int
                    410: ocvt_E(FILE *f, va_list *args, int flags, int width, int precision)
                    411: {
                    412:        return ocvt_flt(f, args, flags, width, precision, 'E');
                    413: }
                    414: 
                    415: static int
                    416: ocvt_G(FILE *f, va_list *args, int flags, int width, int precision)
                    417: {
                    418:        return ocvt_flt(f, args, flags, width, precision, 'G');
                    419: }
                    420: 
                    421: static int
                    422: ocvt_e(FILE *f, va_list *args, int flags, int width, int precision)
                    423: {
                    424:        return ocvt_flt(f, args, flags, width, precision, 'e');
                    425: }
                    426: 
                    427: static int
                    428: ocvt_f(FILE *f, va_list *args, int flags, int width, int precision)
                    429: {
                    430:        return ocvt_flt(f, args, flags, width, precision, 'f');
                    431: }
                    432: 
                    433: static int
                    434: ocvt_g(FILE *f, va_list *args, int flags, int width, int precision)
                    435: {
                    436:        return ocvt_flt(f, args, flags, width, precision, 'g');
                    437: }
                    438: 
                    439: static int
                    440: ocvt_flt(FILE *f, va_list *args, int flags, int width, int precision, char afmt)
                    441: {
                    442:        extern char *_dtoa(double, int, int, int*, int*, char **);
                    443:        int echr;
                    444:        char *digits, *edigits;
                    445:        int exponent;
                    446:        char fmt;
                    447:        int sign;
                    448:        int ndig;
                    449:        int nout, i;
                    450:        char ebuf[20];  /* no sensible machine will overflow this */
                    451:        char *eptr;
                    452:        double d;
                    453: 
                    454:        echr = 'e';
                    455:        fmt = afmt;
                    456:        d = va_arg(*args, double);
                    457:        if(precision < 0) precision = 6;
                    458:        switch(fmt){
                    459:        case 'f':
                    460:                digits = _dtoa(d, 3, precision, &exponent, &sign, &edigits);
                    461:                break;
                    462:        case 'E':
                    463:                echr = 'E';
                    464:                fmt = 'e';
                    465:                /* fall through */
                    466:        case 'e':
                    467:                digits = _dtoa(d, 2, 1+precision, &exponent, &sign, &edigits);
                    468:                break;
                    469:        case 'G':
                    470:                echr = 'E';
                    471:                /* fall through */
                    472:        case 'g':
                    473:                if (precision > 0)
                    474:                        digits = _dtoa(d, 2, precision, &exponent, &sign, &edigits);
                    475:                else {
                    476:                        digits = _dtoa(d, 0, precision, &exponent, &sign, &edigits);
                    477:                        precision = edigits - digits;
                    478:                        if (exponent > precision && exponent <= precision + 4)
                    479:                                precision = exponent;
                    480:                        }
                    481:                if(exponent >= -3 && exponent <= precision){
                    482:                        fmt = 'f';
                    483:                        precision -= exponent;
                    484:                }else{
                    485:                        fmt = 'e';
                    486:                        --precision;
                    487:                }
                    488:                break;
                    489:        }
                    490:        if (exponent == 9999) {
                    491:                /* Infinity or Nan */
                    492:                precision = 0;
                    493:                exponent = edigits - digits;
                    494:                fmt = 'f';
                    495:        }
                    496:        ndig = edigits-digits;
                    497:        if((afmt=='g' || afmt=='G') && !(flags&ALT)){   /* knock off trailing zeros */
                    498:                if(fmt == 'f'){
                    499:                        if(precision+exponent > ndig) {
                    500:                                precision = ndig - exponent;
                    501:                                if(precision < 0)
                    502:                                        precision = 0;
                    503:                        }
                    504:                }
                    505:                else{
                    506:                        if(precision > ndig-1) precision = ndig-1;
                    507:                }
                    508:        }
                    509:        nout = precision;                               /* digits after decimal point */
                    510:        if(precision!=0 || flags&ALT) nout++;           /* decimal point */
                    511:        if(fmt=='f' && exponent>0) nout += exponent;    /* digits before decimal point */
                    512:        else nout++;                                    /* there's always at least one */
                    513:        if(sign || flags&(SPACE|SIGN)) nout++;          /* sign */
                    514:        if(fmt != 'f'){                                 /* exponent */
                    515:                eptr = ebuf;
                    516:                for(i=exponent<=0?1-exponent:exponent-1; i; i/=10)
                    517:                        *eptr++ = '0' + i%10;
                    518:                while(eptr<ebuf+2) *eptr++ = '0';
                    519:                nout += eptr-ebuf+2;                    /* e+99 */
                    520:        }
                    521:        if(!(flags&ZPAD) && !(flags&LEFT))
                    522:                while(nout < width){
                    523:                        putc(' ', f);
                    524:                        nout++;
                    525:                }
                    526:        if(sign) putc('-', f);
                    527:        else if(flags&SIGN) putc('+', f);
                    528:        else if(flags&SPACE) putc(' ', f);
                    529:        if(flags&ZPAD)
                    530:                while(nout < width){
                    531:                        putc('0', f);
                    532:                        nout++;
                    533:                }
                    534:        if(fmt == 'f'){
                    535:                for(i=0; i<exponent; i++) putc(i<ndig?digits[i]:'0', f);
                    536:                if(i == 0) putc('0', f);
                    537:                if(precision>0 || flags&ALT) putc('.', f);
                    538:                for(i=0; i!=precision; i++)
                    539:                        putc(0<=i+exponent && i+exponent<ndig?digits[i+exponent]:'0', f);
                    540:        }
                    541:        else{
                    542:                putc(digits[0], f);
                    543:                if(precision>0 || flags&ALT) putc('.', f);
                    544:                for(i=0; i!=precision; i++) putc(i<ndig-1?digits[i+1]:'0', f);
                    545:        }
                    546:        if(fmt != 'f'){
                    547:                putc(echr, f);
                    548:                putc(exponent<=0?'-':'+', f);
                    549:                while(eptr>ebuf) putc(*--eptr, f);
                    550:        }
                    551:        while(nout < width){
                    552:                putc(' ', f);
                    553:                nout++;
                    554:        }
                    555:        return nout;
                    556: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.