fmt.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       fmt.c (65393B)
       ---
            1 /*
            2  * The authors of this software are Rob Pike and Ken Thompson,
            3  * with contributions from Mike Burrows and Sean Dorward.
            4  *
            5  *     Copyright (c) 2002-2006 by Lucent Technologies.
            6  *     Portions Copyright (c) 2004 Google Inc.
            7  * 
            8  * Permission to use, copy, modify, and distribute this software for any
            9  * purpose without fee is hereby granted, provided that this entire notice
           10  * is included in all copies of any software which is or includes a copy
           11  * or modification of this software and in all copies of the supporting
           12  * documentation for such software.
           13  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
           14  * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
           15  * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
           16  * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
           17  */
           18 #include <stdio.h>
           19 #include <math.h>
           20 #include <float.h>
           21 #include <string.h>
           22 #include <stdlib.h>
           23 #include <errno.h>
           24 #include <stdarg.h>
           25 #include <assert.h>
           26 #include <ctype.h>
           27 #include <unistd.h>
           28 #include "u.h"
           29 #include "utf.h"
           30 #include "fmt.h"
           31 
           32 #define PLAN9PORT /* Get Plan 9 verbs */
           33 
           34 /*
           35  * compiler directive on Plan 9
           36  */
           37 #ifndef USED
           38 #define USED(x) if(x);else
           39 #endif
           40 
           41 /*
           42  * nil cannot be ((void*)0) on ANSI C,
           43  * because it is used for function pointers
           44  */
           45 #undef        nil
           46 #define        nil        0
           47 
           48 #undef        nelem
           49 #define        nelem(x)        (sizeof (x)/sizeof (x)[0])
           50 
           51 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
           52 
           53 /*
           54  * dofmt -- format to a buffer
           55  * the number of characters formatted is returned,
           56  * or -1 if there was an error.
           57  * if the buffer is ever filled, flush is called.
           58  * it should reset the buffer and return whether formatting should continue.
           59  */
           60 
           61 typedef int (*Fmts)(Fmt*);
           62 
           63 typedef struct Quoteinfo Quoteinfo;
           64 struct Quoteinfo
           65 {
           66         int        quoted;                /* if set, string must be quoted */
           67         int        nrunesin;        /* number of input runes that can be accepted */
           68         int        nbytesin;        /* number of input bytes that can be accepted */
           69         int        nrunesout;        /* number of runes that will be generated */
           70         int        nbytesout;        /* number of bytes that will be generated */
           71 };
           72 
           73 /* Edit .+1,/^$/ |cfn |grep -v static | grep __ */
           74 double       __Inf(int sign);
           75 double       __NaN(void);
           76 int          __badfmt(Fmt *f);
           77 int          __charfmt(Fmt *f);
           78 int          __countfmt(Fmt *f);
           79 int          __efgfmt(Fmt *fmt);
           80 int          __errfmt(Fmt *f);
           81 int          __flagfmt(Fmt *f);
           82 int          __fmtFdFlush(Fmt *f);
           83 int          __fmtcpy(Fmt *f, const void *vm, int n, int sz);
           84 void*        __fmtdispatch(Fmt *f, void *fmt, int isrunes);
           85 void *       __fmtflush(Fmt *f, void *t, int len);
           86 void         __fmtlock(void);
           87 int          __fmtpad(Fmt *f, int n);
           88 double       __fmtpow10(int n);
           89 int          __fmtrcpy(Fmt *f, const void *vm, int n);
           90 void         __fmtunlock(void);
           91 int          __ifmt(Fmt *f);
           92 int          __isInf(double d, int sign);
           93 int          __isNaN(double d);
           94 int          __needsep(int*, char**);
           95 int          __needsquotes(char *s, int *quotelenp);
           96 int          __percentfmt(Fmt *f);
           97 void         __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout);
           98 int          __quotestrfmt(int runesin, Fmt *f);
           99 int          __rfmtpad(Fmt *f, int n);
          100 int          __runefmt(Fmt *f);
          101 int          __runeneedsquotes(Rune *r, int *quotelenp);
          102 int          __runesfmt(Fmt *f);
          103 int          __strfmt(Fmt *f);
          104 
          105 #define FMTCHAR(f, t, s, c)\
          106         do{\
          107         if(t + 1 > (char*)s){\
          108                 t = (char*)__fmtflush(f, t, 1);\
          109                 if(t != nil)\
          110                         s = (char*)f->stop;\
          111                 else\
          112                         return -1;\
          113         }\
          114         *t++ = c;\
          115         }while(0)
          116 
          117 #define FMTRCHAR(f, t, s, c)\
          118         do{\
          119         if(t + 1 > (Rune*)s){\
          120                 t = (Rune*)__fmtflush(f, t, sizeof(Rune));\
          121                 if(t != nil)\
          122                         s = (Rune*)f->stop;\
          123                 else\
          124                         return -1;\
          125         }\
          126         *t++ = c;\
          127         }while(0)
          128 
          129 #define FMTRUNE(f, t, s, r)\
          130         do{\
          131         Rune _rune;\
          132         int _runelen;\
          133         if(t + UTFmax > (char*)s && t + (_runelen = runelen(r)) > (char*)s){\
          134                 t = (char*)__fmtflush(f, t, _runelen);\
          135                 if(t != nil)\
          136                         s = (char*)f->stop;\
          137                 else\
          138                         return -1;\
          139         }\
          140         if(r < Runeself)\
          141                 *t++ = r;\
          142         else{\
          143                 _rune = r;\
          144                 t += runetochar(t, &_rune);\
          145         }\
          146         }while(0)
          147 
          148 #ifdef va_copy
          149 #        define VA_COPY(a,b) va_copy(a,b)
          150 #        define VA_END(a) va_end(a)
          151 #else
          152 #        define VA_COPY(a,b) (a) = (b)
          153 #        define VA_END(a)
          154 #endif
          155 
          156 
          157 /* ---------- end preamble -------- */
          158 
          159 /* -------------- charstod.c --------------- */
          160 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
          161 // #include <stdarg.h>
          162 // #include <string.h>
          163 // #include "plan9.h"
          164 // #include "fmt.h"
          165 // #include "fmtdef.h"
          166 
          167 /*
          168  * Reads a floating-point number by interpreting successive characters
          169  * returned by (*f)(vp).  The last call it makes to f terminates the
          170  * scan, so is not a character in the number.  It may therefore be
          171  * necessary to back up the input stream up one byte after calling charstod.
          172  */
          173 
          174 double
          175 fmtcharstod(int(*f)(void*), void *vp)
          176 {
          177         double num, dem;
          178         int neg, eneg, dig, exp, c;
          179 
          180         num = 0;
          181         neg = 0;
          182         dig = 0;
          183         exp = 0;
          184         eneg = 0;
          185 
          186         c = (*f)(vp);
          187         while(c == ' ' || c == '\t')
          188                 c = (*f)(vp);
          189         if(c == '-' || c == '+'){
          190                 if(c == '-')
          191                         neg = 1;
          192                 c = (*f)(vp);
          193         }
          194         while(c >= '0' && c <= '9'){
          195                 num = num*10 + c-'0';
          196                 c = (*f)(vp);
          197         }
          198         if(c == '.')
          199                 c = (*f)(vp);
          200         while(c >= '0' && c <= '9'){
          201                 num = num*10 + c-'0';
          202                 dig++;
          203                 c = (*f)(vp);
          204         }
          205         if(c == 'e' || c == 'E'){
          206                 c = (*f)(vp);
          207                 if(c == '-' || c == '+'){
          208                         if(c == '-'){
          209                                 dig = -dig;
          210                                 eneg = 1;
          211                         }
          212                         c = (*f)(vp);
          213                 }
          214                 while(c >= '0' && c <= '9'){
          215                         exp = exp*10 + c-'0';
          216                         c = (*f)(vp);
          217                 }
          218         }
          219         exp -= dig;
          220         if(exp < 0){
          221                 exp = -exp;
          222                 eneg = !eneg;
          223         }
          224         dem = __fmtpow10(exp);
          225         if(eneg)
          226                 num /= dem;
          227         else
          228                 num *= dem;
          229         if(neg)
          230                 return -num;
          231         return num;
          232 }
          233 /* -------------- dofmt.c --------------- */
          234 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
          235 /* Copyright (c) 2004 Google Inc.; see LICENSE */
          236 
          237 // #include <stdarg.h>
          238 // #include <string.h>
          239 // #include "plan9.h"
          240 // #include "fmt.h"
          241 // #include "fmtdef.h"
          242 
          243 /* format the output into f->to and return the number of characters fmted  */
          244 int
          245 dofmt(Fmt *f, char *fmt)
          246 {
          247         Rune rune, *rt, *rs;
          248         int r;
          249         char *t, *s;
          250         int n, nfmt;
          251 
          252         nfmt = f->nfmt;
          253         for(;;){
          254                 if(f->runes){
          255                         rt = (Rune*)f->to;
          256                         rs = (Rune*)f->stop;
          257                         while((r = *(uchar*)fmt) && r != '%'){
          258                                 if(r < Runeself)
          259                                         fmt++;
          260                                 else{
          261                                         fmt += chartorune(&rune, fmt);
          262                                         r = rune;
          263                                 }
          264                                 FMTRCHAR(f, rt, rs, r);
          265                         }
          266                         fmt++;
          267                         f->nfmt += rt - (Rune *)f->to;
          268                         f->to = rt;
          269                         if(!r)
          270                                 return f->nfmt - nfmt;
          271                         f->stop = rs;
          272                 }else{
          273                         t = (char*)f->to;
          274                         s = (char*)f->stop;
          275                         while((r = *(uchar*)fmt) && r != '%'){
          276                                 if(r < Runeself){
          277                                         FMTCHAR(f, t, s, r);
          278                                         fmt++;
          279                                 }else{
          280                                         n = chartorune(&rune, fmt);
          281                                         if(t + n > s){
          282                                                 t = (char*)__fmtflush(f, t, n);
          283                                                 if(t != nil)
          284                                                         s = (char*)f->stop;
          285                                                 else
          286                                                         return -1;
          287                                         }
          288                                         while(n--)
          289                                                 *t++ = *fmt++;
          290                                 }
          291                         }
          292                         fmt++;
          293                         f->nfmt += t - (char *)f->to;
          294                         f->to = t;
          295                         if(!r)
          296                                 return f->nfmt - nfmt;
          297                         f->stop = s;
          298                 }
          299 
          300                 fmt = (char*)__fmtdispatch(f, fmt, 0);
          301                 if(fmt == nil)
          302                         return -1;
          303         }
          304 }
          305 
          306 void *
          307 __fmtflush(Fmt *f, void *t, int len)
          308 {
          309         if(f->runes)
          310                 f->nfmt += (Rune*)t - (Rune*)f->to;
          311         else
          312                 f->nfmt += (char*)t - (char *)f->to;
          313         f->to = t;
          314         if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
          315                 f->stop = f->to;
          316                 return nil;
          317         }
          318         return f->to;
          319 }
          320 
          321 /*
          322  * put a formatted block of memory sz bytes long of n runes into the output buffer,
          323  * left/right justified in a field of at least f->width characters (if FmtWidth is set)
          324  */
          325 int
          326 __fmtpad(Fmt *f, int n)
          327 {
          328         char *t, *s;
          329         int i;
          330 
          331         t = (char*)f->to;
          332         s = (char*)f->stop;
          333         for(i = 0; i < n; i++)
          334                 FMTCHAR(f, t, s, ' ');
          335         f->nfmt += t - (char *)f->to;
          336         f->to = t;
          337         return 0;
          338 }
          339 
          340 int
          341 __rfmtpad(Fmt *f, int n)
          342 {
          343         Rune *t, *s;
          344         int i;
          345 
          346         t = (Rune*)f->to;
          347         s = (Rune*)f->stop;
          348         for(i = 0; i < n; i++)
          349                 FMTRCHAR(f, t, s, ' ');
          350         f->nfmt += t - (Rune *)f->to;
          351         f->to = t;
          352         return 0;
          353 }
          354 
          355 int
          356 __fmtcpy(Fmt *f, const void *vm, int n, int sz)
          357 {
          358         Rune *rt, *rs, r;
          359         char *t, *s, *m, *me;
          360         ulong fl;
          361         int nc, w;
          362 
          363         m = (char*)vm;
          364         me = m + sz;
          365         fl = f->flags;
          366         w = 0;
          367         if(fl & FmtWidth)
          368                 w = f->width;
          369         if((fl & FmtPrec) && n > f->prec)
          370                 n = f->prec;
          371         if(f->runes){
          372                 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
          373                         return -1;
          374                 rt = (Rune*)f->to;
          375                 rs = (Rune*)f->stop;
          376                 for(nc = n; nc > 0; nc--){
          377                         r = *(uchar*)m;
          378                         if(r < Runeself)
          379                                 m++;
          380                         else if((me - m) >= UTFmax || fullrune(m, me-m))
          381                                 m += chartorune(&r, m);
          382                         else
          383                                 break;
          384                         FMTRCHAR(f, rt, rs, r);
          385                 }
          386                 f->nfmt += rt - (Rune *)f->to;
          387                 f->to = rt;
          388                 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
          389                         return -1;
          390         }else{
          391                 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
          392                         return -1;
          393                 t = (char*)f->to;
          394                 s = (char*)f->stop;
          395                 for(nc = n; nc > 0; nc--){
          396                         r = *(uchar*)m;
          397                         if(r < Runeself)
          398                                 m++;
          399                         else if((me - m) >= UTFmax || fullrune(m, me-m))
          400                                 m += chartorune(&r, m);
          401                         else
          402                                 break;
          403                         FMTRUNE(f, t, s, r);
          404                 }
          405                 f->nfmt += t - (char *)f->to;
          406                 f->to = t;
          407                 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
          408                         return -1;
          409         }
          410         return 0;
          411 }
          412 
          413 int
          414 __fmtrcpy(Fmt *f, const void *vm, int n)
          415 {
          416         Rune r, *m, *me, *rt, *rs;
          417         char *t, *s;
          418         ulong fl;
          419         int w;
          420 
          421         m = (Rune*)vm;
          422         fl = f->flags;
          423         w = 0;
          424         if(fl & FmtWidth)
          425                 w = f->width;
          426         if((fl & FmtPrec) && n > f->prec)
          427                 n = f->prec;
          428         if(f->runes){
          429                 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
          430                         return -1;
          431                 rt = (Rune*)f->to;
          432                 rs = (Rune*)f->stop;
          433                 for(me = m + n; m < me; m++)
          434                         FMTRCHAR(f, rt, rs, *m);
          435                 f->nfmt += rt - (Rune *)f->to;
          436                 f->to = rt;
          437                 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
          438                         return -1;
          439         }else{
          440                 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
          441                         return -1;
          442                 t = (char*)f->to;
          443                 s = (char*)f->stop;
          444                 for(me = m + n; m < me; m++){
          445                         r = *m;
          446                         FMTRUNE(f, t, s, r);
          447                 }
          448                 f->nfmt += t - (char *)f->to;
          449                 f->to = t;
          450                 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
          451                         return -1;
          452         }
          453         return 0;
          454 }
          455 
          456 /* fmt out one character */
          457 int
          458 __charfmt(Fmt *f)
          459 {
          460         char x[1];
          461 
          462         x[0] = va_arg(f->args, int);
          463         f->prec = 1;
          464         return __fmtcpy(f, (const char*)x, 1, 1);
          465 }
          466 
          467 /* fmt out one rune */
          468 int
          469 __runefmt(Fmt *f)
          470 {
          471         Rune x[1];
          472 
          473         x[0] = va_arg(f->args, int);
          474         return __fmtrcpy(f, (const void*)x, 1);
          475 }
          476 
          477 /* public helper routine: fmt out a null terminated string already in hand */
          478 int
          479 fmtstrcpy(Fmt *f, char *s)
          480 {
          481         int i, j;
          482 
          483         if(!s)
          484                 return __fmtcpy(f, "<nil>", 5, 5);
          485         /* if precision is specified, make sure we don't wander off the end */
          486         if(f->flags & FmtPrec){
          487 #ifdef PLAN9PORT
          488                 Rune r;
          489                 i = 0;
          490                 for(j=0; j<f->prec && s[i]; j++)
          491                         i += chartorune(&r, s+i);
          492 #else
          493                 /* ANSI requires precision in bytes, not Runes */
          494                 for(i=0; i<f->prec; i++)
          495                         if(s[i] == 0)
          496                                 break;
          497                 j = utfnlen(s, i);        /* won't print partial at end */
          498 #endif
          499                 return __fmtcpy(f, s, j, i);
          500         }
          501         return __fmtcpy(f, s, utflen(s), strlen(s));
          502 }
          503 
          504 /* fmt out a null terminated utf string */
          505 int
          506 __strfmt(Fmt *f)
          507 {
          508         char *s;
          509 
          510         s = va_arg(f->args, char *);
          511         return fmtstrcpy(f, s);
          512 }
          513 
          514 /* public helper routine: fmt out a null terminated rune string already in hand */
          515 int
          516 fmtrunestrcpy(Fmt *f, Rune *s)
          517 {
          518         Rune *e;
          519         int n, p;
          520 
          521         if(!s)
          522                 return __fmtcpy(f, "<nil>", 5, 5);
          523         /* if precision is specified, make sure we don't wander off the end */
          524         if(f->flags & FmtPrec){
          525                 p = f->prec;
          526                 for(n = 0; n < p; n++)
          527                         if(s[n] == 0)
          528                                 break;
          529         }else{
          530                 for(e = s; *e; e++)
          531                         ;
          532                 n = e - s;
          533         }
          534         return __fmtrcpy(f, s, n);
          535 }
          536 
          537 /* fmt out a null terminated rune string */
          538 int
          539 __runesfmt(Fmt *f)
          540 {
          541         Rune *s;
          542 
          543         s = va_arg(f->args, Rune *);
          544         return fmtrunestrcpy(f, s);
          545 }
          546 
          547 /* fmt a % */
          548 int
          549 __percentfmt(Fmt *f)
          550 {
          551         Rune x[1];
          552 
          553         x[0] = f->r;
          554         f->prec = 1;
          555         return __fmtrcpy(f, (const void*)x, 1);
          556 }
          557 
          558 /* fmt an integer */
          559 int
          560 __ifmt(Fmt *f)
          561 {
          562         char buf[140], *p, *conv;
          563         /* 140: for 64 bits of binary + 3-byte sep every 4 digits */
          564         uvlong vu;
          565         ulong u;
          566         int neg, base, i, n, fl, w, isv;
          567         int ndig, len, excess, bytelen;
          568         char *grouping;
          569         char *thousands;
          570 
          571         neg = 0;
          572         fl = f->flags;
          573         isv = 0;
          574         vu = 0;
          575         u = 0;
          576 #ifndef PLAN9PORT
          577         /*
          578          * Unsigned verbs for ANSI C
          579          */
          580         switch(f->r){
          581         case 'o':
          582         case 'p':
          583         case 'u':
          584         case 'x':
          585         case 'X':
          586                 fl |= FmtUnsigned;
          587                 fl &= ~(FmtSign|FmtSpace);
          588                 break;
          589         }
          590 #endif
          591         if(f->r == 'p'){
          592                 u = (ulong)va_arg(f->args, void*);
          593                 f->r = 'x';
          594                 fl |= FmtUnsigned;
          595         }else if(fl & FmtVLong){
          596                 isv = 1;
          597                 if(fl & FmtUnsigned)
          598                         vu = va_arg(f->args, uvlong);
          599                 else
          600                         vu = va_arg(f->args, vlong);
          601         }else if(fl & FmtLong){
          602                 if(fl & FmtUnsigned)
          603                         u = va_arg(f->args, ulong);
          604                 else
          605                         u = va_arg(f->args, long);
          606         }else if(fl & FmtByte){
          607                 if(fl & FmtUnsigned)
          608                         u = (uchar)va_arg(f->args, int);
          609                 else
          610                         u = (char)va_arg(f->args, int);
          611         }else if(fl & FmtShort){
          612                 if(fl & FmtUnsigned)
          613                         u = (ushort)va_arg(f->args, int);
          614                 else
          615                         u = (short)va_arg(f->args, int);
          616         }else{
          617                 if(fl & FmtUnsigned)
          618                         u = va_arg(f->args, uint);
          619                 else
          620                         u = va_arg(f->args, int);
          621         }
          622         conv = "0123456789abcdef";
          623         grouping = "\4";        /* for hex, octal etc. (undefined by spec but nice) */
          624         thousands = f->thousands;
          625         switch(f->r){
          626         case 'd':
          627         case 'i':
          628         case 'u':
          629                 base = 10;
          630                 grouping = f->grouping;
          631                 break;
          632         case 'X':
          633                 conv = "0123456789ABCDEF";
          634                 /* fall through */
          635         case 'x':
          636                 base = 16;
          637                 thousands = ":";
          638                 break;
          639         case 'b':
          640                 base = 2;
          641                 thousands = ":";
          642                 break;
          643         case 'o':
          644                 base = 8;
          645                 break;
          646         default:
          647                 return -1;
          648         }
          649         if(!(fl & FmtUnsigned)){
          650                 if(isv && (vlong)vu < 0){
          651                         vu = -(vlong)vu;
          652                         neg = 1;
          653                 }else if(!isv && (long)u < 0){
          654                         u = -(long)u;
          655                         neg = 1;
          656                 }
          657         }
          658         p = buf + sizeof buf - 1;
          659         n = 0;        /* in runes */
          660         excess = 0;        /* number of bytes > number runes */
          661         ndig = 0;
          662         len = utflen(thousands);
          663         bytelen = strlen(thousands);
          664         if(isv){
          665                 while(vu){
          666                         i = vu % base;
          667                         vu /= base;
          668                         if((fl & FmtComma) && n % 4 == 3){
          669                                 *p-- = ',';
          670                                 n++;
          671                         }
          672                         if((fl & FmtApost) && __needsep(&ndig, &grouping)){
          673                                 n += len;
          674                                 excess += bytelen - len;
          675                                 p -= bytelen;
          676                                 memmove(p+1, thousands, bytelen);
          677                         }
          678                         *p-- = conv[i];
          679                         n++;
          680                 }
          681         }else{
          682                 while(u){
          683                         i = u % base;
          684                         u /= base;
          685                         if((fl & FmtComma) && n % 4 == 3){
          686                                 *p-- = ',';
          687                                 n++;
          688                         }
          689                         if((fl & FmtApost) && __needsep(&ndig, &grouping)){
          690                                 n += len;
          691                                 excess += bytelen - len;
          692                                 p -= bytelen;
          693                                 memmove(p+1, thousands, bytelen);
          694                         }
          695                         *p-- = conv[i];
          696                         n++;
          697                 }
          698         }
          699         if(n == 0){
          700                 /*
          701                  * "The result of converting a zero value with
          702                  * a precision of zero is no characters."  - ANSI
          703                  *
          704                  * "For o conversion, # increases the precision, if and only if
          705                  * necessary, to force the first digit of the result to be a zero
          706                  * (if the value and precision are both 0, a single 0 is printed)." - ANSI
          707                  */
          708                 if(!(fl & FmtPrec) || f->prec != 0 || (f->r == 'o' && (fl & FmtSharp))){
          709                         *p-- = '0';
          710                         n = 1;
          711                         if(fl & FmtApost)
          712                                 __needsep(&ndig, &grouping);
          713                 }
          714                 
          715                 /*
          716                  * Zero values don't get 0x.
          717                  */
          718                 if(f->r == 'x' || f->r == 'X')
          719                         fl &= ~FmtSharp;
          720         }
          721         for(w = f->prec; n < w && p > buf+3; n++){
          722                 if((fl & FmtApost) && __needsep(&ndig, &grouping)){
          723                         n += len;
          724                         excess += bytelen - len;
          725                         p -= bytelen;
          726                         memmove(p+1, thousands, bytelen);
          727                 }
          728                 *p-- = '0';
          729         }
          730         if(neg || (fl & (FmtSign|FmtSpace)))
          731                 n++;
          732         if(fl & FmtSharp){
          733                 if(base == 16)
          734                         n += 2;
          735                 else if(base == 8){
          736                         if(p[1] == '0')
          737                                 fl &= ~FmtSharp;
          738                         else
          739                                 n++;
          740                 }
          741         }
          742         if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
          743                 w = 0;
          744                 if(fl & FmtWidth)
          745                         w = f->width;
          746                 for(; n < w && p > buf+3; n++){
          747                         if((fl & FmtApost) && __needsep(&ndig, &grouping)){
          748                                 n += len;
          749                                 excess += bytelen - len;
          750                                 p -= bytelen;
          751                                 memmove(p+1, thousands, bytelen);
          752                         }
          753                         *p-- = '0';
          754                 }
          755                 f->flags &= ~FmtWidth;
          756         }
          757         if(fl & FmtSharp){
          758                 if(base == 16)
          759                         *p-- = f->r;
          760                 if(base == 16 || base == 8)
          761                         *p-- = '0';
          762         }
          763         if(neg)
          764                 *p-- = '-';
          765         else if(fl & FmtSign)
          766                 *p-- = '+';
          767         else if(fl & FmtSpace)
          768                 *p-- = ' ';
          769         f->flags &= ~FmtPrec;
          770         return __fmtcpy(f, p + 1, n, n + excess);
          771 }
          772 
          773 int
          774 __countfmt(Fmt *f)
          775 {
          776         void *p;
          777         ulong fl;
          778 
          779         fl = f->flags;
          780         p = va_arg(f->args, void*);
          781         if(fl & FmtVLong){
          782                 *(vlong*)p = f->nfmt;
          783         }else if(fl & FmtLong){
          784                 *(long*)p = f->nfmt;
          785         }else if(fl & FmtByte){
          786                 *(char*)p = f->nfmt;
          787         }else if(fl & FmtShort){
          788                 *(short*)p = f->nfmt;
          789         }else{
          790                 *(int*)p = f->nfmt;
          791         }
          792         return 0;
          793 }
          794 
          795 int
          796 __flagfmt(Fmt *f)
          797 {
          798         switch(f->r){
          799         case ',':
          800                 f->flags |= FmtComma;
          801                 break;
          802         case '-':
          803                 f->flags |= FmtLeft;
          804                 break;
          805         case '+':
          806                 f->flags |= FmtSign;
          807                 break;
          808         case '#':
          809                 f->flags |= FmtSharp;
          810                 break;
          811         case '\'':
          812                 f->flags |= FmtApost;
          813                 break;
          814         case ' ':
          815                 f->flags |= FmtSpace;
          816                 break;
          817         case 'u':
          818                 f->flags |= FmtUnsigned;
          819                 break;
          820         case 'h':
          821                 if(f->flags & FmtShort)
          822                         f->flags |= FmtByte;
          823                 f->flags |= FmtShort;
          824                 break;
          825         case 'L':
          826                 f->flags |= FmtLDouble;
          827                 break;
          828         case 'l':
          829                 if(f->flags & FmtLong)
          830                         f->flags |= FmtVLong;
          831                 f->flags |= FmtLong;
          832                 break;
          833         }
          834         return 1;
          835 }
          836 
          837 /* default error format */
          838 int
          839 __badfmt(Fmt *f)
          840 {
          841         char x[3];
          842 
          843         x[0] = '%';
          844         x[1] = f->r;
          845         x[2] = '%';
          846         f->prec = 3;
          847         __fmtcpy(f, (const void*)x, 3, 3);
          848         return 0;
          849 }
          850 /* -------------- fltfmt.c --------------- */
          851 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
          852 // #include <stdio.h>
          853 // #include <math.h>
          854 // #include <float.h>
          855 // #include <string.h>
          856 // #include <stdlib.h>
          857 // #include <errno.h>
          858 // #include <stdarg.h>
          859 // #include <fmt.h>
          860 // #include <assert.h>
          861 // #include "plan9.h"
          862 // #include "fmt.h"
          863 // #include "fmtdef.h"
          864 // #include "nan.h"
          865 
          866 enum
          867 {
          868         FDIGIT        = 30,
          869         FDEFLT        = 6,
          870         NSIGNIF        = 17
          871 };
          872 
          873 /*
          874  * first few powers of 10, enough for about 1/2 of the
          875  * total space for doubles.
          876  */
          877 static double pows10[] =
          878 {
          879           1e0,   1e1,   1e2,   1e3,   1e4,   1e5,   1e6,   1e7,   1e8,   1e9,  
          880          1e10,  1e11,  1e12,  1e13,  1e14,  1e15,  1e16,  1e17,  1e18,  1e19,  
          881          1e20,  1e21,  1e22,  1e23,  1e24,  1e25,  1e26,  1e27,  1e28,  1e29,  
          882          1e30,  1e31,  1e32,  1e33,  1e34,  1e35,  1e36,  1e37,  1e38,  1e39,  
          883          1e40,  1e41,  1e42,  1e43,  1e44,  1e45,  1e46,  1e47,  1e48,  1e49,  
          884          1e50,  1e51,  1e52,  1e53,  1e54,  1e55,  1e56,  1e57,  1e58,  1e59,  
          885          1e60,  1e61,  1e62,  1e63,  1e64,  1e65,  1e66,  1e67,  1e68,  1e69,  
          886          1e70,  1e71,  1e72,  1e73,  1e74,  1e75,  1e76,  1e77,  1e78,  1e79,  
          887          1e80,  1e81,  1e82,  1e83,  1e84,  1e85,  1e86,  1e87,  1e88,  1e89,  
          888          1e90,  1e91,  1e92,  1e93,  1e94,  1e95,  1e96,  1e97,  1e98,  1e99,  
          889         1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, 
          890         1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, 
          891         1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, 
          892         1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, 
          893         1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, 
          894         1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, 
          895 };
          896 #define        npows10 ((int)(sizeof(pows10)/sizeof(pows10[0])))
          897 #define        pow10(x)  fmtpow10(x)
          898 
          899 static double
          900 pow10(int n)
          901 {
          902         double d;
          903         int neg;
          904 
          905         neg = 0;
          906         if(n < 0){
          907                 if(n < DBL_MIN_10_EXP)
          908                         return 0.;
          909                 neg = 1;
          910                 n = -n;
          911         }else if(n > DBL_MAX_10_EXP)
          912                 return HUGE_VAL;
          913 
          914         if(n < npows10)
          915                 d = pows10[n];
          916         else{
          917                 d = pows10[npows10-1];
          918                 for(;;){
          919                         n -= npows10 - 1;
          920                         if(n < npows10){
          921                                 d *= pows10[n];
          922                                 break;
          923                         }
          924                         d *= pows10[npows10 - 1];
          925                 }
          926         }
          927         if(neg)
          928                 return 1./d;
          929         return d;
          930 }
          931 
          932 /*
          933  * add 1 to the decimal integer string a of length n.
          934  * if 99999 overflows into 10000, return 1 to tell caller
          935  * to move the virtual decimal point.
          936  */
          937 static int
          938 xadd1(char *a, int n)
          939 {
          940         char *b;
          941         int c;
          942 
          943         if(n < 0 || n > NSIGNIF)
          944                 return 0;
          945         for(b = a+n-1; b >= a; b--) {
          946                 c = *b + 1;
          947                 if(c <= '9') {
          948                         *b = c;
          949                         return 0;
          950                 }
          951                 *b = '0';
          952         }
          953         /*
          954          * need to overflow adding digit.
          955          * shift number down and insert 1 at beginning.
          956          * decimal is known to be 0s or we wouldn't
          957          * have gotten this far.  (e.g., 99999+1 => 00000)
          958          */
          959         a[0] = '1';
          960         return 1;
          961 }
          962 
          963 /*
          964  * subtract 1 from the decimal integer string a.
          965  * if 10000 underflows into 09999, make it 99999
          966  * and return 1 to tell caller to move the virtual 
          967  * decimal point.  this way, xsub1 is inverse of xadd1.
          968  */
          969 static int
          970 xsub1(char *a, int n)
          971 {
          972         char *b;
          973         int c;
          974 
          975         if(n < 0 || n > NSIGNIF)
          976                 return 0;
          977         for(b = a+n-1; b >= a; b--) {
          978                 c = *b - 1;
          979                 if(c >= '0') {
          980                         if(c == '0' && b == a) {
          981                                 /*
          982                                  * just zeroed the top digit; shift everyone up.
          983                                  * decimal is known to be 9s or we wouldn't
          984                                  * have gotten this far.  (e.g., 10000-1 => 09999)
          985                                  */
          986                                 *b = '9';
          987                                 return 1;
          988                         }
          989                         *b = c;
          990                         return 0;
          991                 }
          992                 *b = '9';
          993         }
          994         /*
          995          * can't get here.  the number a is always normalized
          996          * so that it has a nonzero first digit.
          997          */
          998         abort();
          999 }
         1000 
         1001 /*
         1002  * format exponent like sprintf(p, "e%+02d", e)
         1003  */
         1004 static void
         1005 xfmtexp(char *p, int e, int ucase)
         1006 {
         1007         char se[9];
         1008         int i;
         1009 
         1010         *p++ = ucase ? 'E' : 'e';
         1011         if(e < 0) {
         1012                 *p++ = '-';
         1013                 e = -e;
         1014         } else
         1015                 *p++ = '+';
         1016         i = 0;
         1017         while(e) {
         1018                 se[i++] = e % 10 + '0';
         1019                 e /= 10;
         1020         }
         1021         while(i < 2)
         1022                 se[i++] = '0';
         1023         while(i > 0)
         1024                 *p++ = se[--i];
         1025         *p++ = '\0';
         1026 }
         1027 
         1028 /*
         1029  * compute decimal integer m, exp such that:
         1030  *        f = m*10^exp
         1031  *        m is as short as possible with losing exactness
         1032  * assumes special cases (NaN, +Inf, -Inf) have been handled.
         1033  */
         1034 static void
         1035 xdtoa(double f, char *s, int *exp, int *neg, int *ns)
         1036 {
         1037         int c, d, e2, e, ee, i, ndigit, oerrno;
         1038         char tmp[NSIGNIF+10];
         1039         double g;
         1040 
         1041         oerrno = errno; /* in case strtod smashes errno */
         1042 
         1043         /*
         1044          * make f non-negative.
         1045          */
         1046         *neg = 0;
         1047         if(f < 0) {
         1048                 f = -f;
         1049                 *neg = 1;
         1050         }
         1051 
         1052         /*
         1053          * must handle zero specially.
         1054          */
         1055         if(f == 0){
         1056                 *exp = 0;
         1057                 s[0] = '0';
         1058                 s[1] = '\0';
         1059                 *ns = 1;
         1060                 return;
         1061         }
         1062                 
         1063         /*
         1064          * find g,e such that f = g*10^e.
         1065          * guess 10-exponent using 2-exponent, then fine tune.
         1066          */
         1067         frexp(f, &e2);
         1068         e = (int)(e2 * .301029995664);
         1069         g = f * pow10(-e);
         1070         while(g < 1) {
         1071                 e--;
         1072                 g = f * pow10(-e);
         1073         }
         1074         while(g >= 10) {
         1075                 e++;
         1076                 g = f * pow10(-e);
         1077         }
         1078 
         1079         /*
         1080          * convert NSIGNIF digits as a first approximation.
         1081          */
         1082         for(i=0; i<NSIGNIF; i++) {
         1083                 d = (int)g;
         1084                 s[i] = d+'0';
         1085                 g = (g-d) * 10;
         1086         }
         1087         s[i] = 0;
         1088 
         1089         /*
         1090          * adjust e because s is 314159... not 3.14159...
         1091          */
         1092         e -= NSIGNIF-1;
         1093         xfmtexp(s+NSIGNIF, e, 0);
         1094 
         1095         /*
         1096          * adjust conversion until strtod(s) == f exactly.
         1097          */
         1098         for(i=0; i<10; i++) {
         1099                 g = strtod(s, nil);
         1100                 if(f > g) {
         1101                         if(xadd1(s, NSIGNIF)) {
         1102                                 /* gained a digit */
         1103                                 e--;
         1104                                 xfmtexp(s+NSIGNIF, e, 0);
         1105                         }
         1106                         continue;
         1107                 }
         1108                 if(f < g) {
         1109                         if(xsub1(s, NSIGNIF)) {
         1110                                 /* lost a digit */
         1111                                 e++;
         1112                                 xfmtexp(s+NSIGNIF, e, 0);
         1113                         }
         1114                         continue;
         1115                 }
         1116                 break;
         1117         }
         1118 
         1119         /*
         1120          * play with the decimal to try to simplify.
         1121          */
         1122 
         1123         /*
         1124          * bump last few digits up to 9 if we can
         1125          */
         1126         for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {
         1127                 c = s[i];
         1128                 if(c != '9') {
         1129                         s[i] = '9';
         1130                         g = strtod(s, nil);
         1131                         if(g != f) {
         1132                                 s[i] = c;
         1133                                 break;
         1134                         }
         1135                 }
         1136         }
         1137 
         1138         /*
         1139          * add 1 in hopes of turning 9s to 0s
         1140          */
         1141         if(s[NSIGNIF-1] == '9') {
         1142                 strcpy(tmp, s);
         1143                 ee = e;
         1144                 if(xadd1(tmp, NSIGNIF)) {
         1145                         ee--;
         1146                         xfmtexp(tmp+NSIGNIF, ee, 0);
         1147                 }
         1148                 g = strtod(tmp, nil);
         1149                 if(g == f) {
         1150                         strcpy(s, tmp);
         1151                         e = ee;
         1152                 }
         1153         }
         1154         
         1155         /*
         1156          * bump last few digits down to 0 as we can.
         1157          */
         1158         for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {
         1159                 c = s[i];
         1160                 if(c != '0') {
         1161                         s[i] = '0';
         1162                         g = strtod(s, nil);
         1163                         if(g != f) {
         1164                                 s[i] = c;
         1165                                 break;
         1166                         }
         1167                 }
         1168         }
         1169 
         1170         /*
         1171          * remove trailing zeros.
         1172          */
         1173         ndigit = NSIGNIF;
         1174         while(ndigit > 1 && s[ndigit-1] == '0'){
         1175                 e++;
         1176                 --ndigit;
         1177         }
         1178         s[ndigit] = 0;
         1179         *exp = e;
         1180         *ns = ndigit;
         1181         errno = oerrno;
         1182 }
         1183 
         1184 #ifdef PLAN9PORT
         1185 static char *special[] = { "NaN", "NaN", "+Inf", "+Inf", "-Inf", "-Inf" };
         1186 #else
         1187 static char *special[] = { "nan", "NAN", "inf", "INF", "-inf", "-INF" };
         1188 #endif
         1189 
         1190 int
         1191 __efgfmt(Fmt *fmt)
         1192 {
         1193         char buf[NSIGNIF+10], *dot, *digits, *p, *s, suf[10], *t;
         1194         double f;
         1195         int c, chr, dotwid, e, exp, fl, ndigits, neg, newndigits;
         1196         int pad, point, prec, realchr, sign, sufwid, ucase, wid, z1, z2;
         1197         Rune r, *rs, *rt;
         1198         
         1199         f = va_arg(fmt->args, double);
         1200         
         1201         /* 
         1202          * extract formatting flags
         1203          */
         1204         fl = fmt->flags;
         1205         fmt->flags = 0;
         1206         prec = FDEFLT;
         1207         if(fl & FmtPrec)
         1208                 prec = fmt->prec;
         1209         chr = fmt->r;
         1210         ucase = 0;
         1211         switch(chr) {
         1212         case 'A':
         1213         case 'E':
         1214         case 'F':
         1215         case 'G':
         1216                 chr += 'a'-'A';
         1217                 ucase = 1;
         1218                 break;
         1219         }
         1220 
         1221         /*
         1222          * pick off special numbers.
         1223          */
         1224         if(__isNaN(f)) {
         1225                 s = special[0+ucase];
         1226         special:
         1227                 fmt->flags = fl & (FmtWidth|FmtLeft);
         1228                 return __fmtcpy(fmt, s, strlen(s), strlen(s));
         1229         }
         1230         if(__isInf(f, 1)) {
         1231                 s = special[2+ucase];
         1232                 goto special;
         1233         }
         1234         if(__isInf(f, -1)) {
         1235                 s = special[4+ucase];
         1236                 goto special;
         1237         }
         1238 
         1239         /*
         1240          * get exact representation.
         1241          */
         1242         digits = buf;
         1243         xdtoa(f, digits, &exp, &neg, &ndigits);
         1244 
         1245         /*
         1246          * get locale's decimal point.
         1247          */
         1248         dot = fmt->decimal;
         1249         if(dot == nil)
         1250                 dot = ".";
         1251         dotwid = utflen(dot);
         1252 
         1253         /*
         1254          * now the formatting fun begins.
         1255          * compute parameters for actual fmt:
         1256          *
         1257          *        pad: number of spaces to insert before/after field.
         1258          *        z1: number of zeros to insert before digits
         1259          *        z2: number of zeros to insert after digits
         1260          *        point: number of digits to print before decimal point
         1261          *        ndigits: number of digits to use from digits[]
         1262          *        suf: trailing suffix, like "e-5"
         1263          */
         1264         realchr = chr;
         1265         switch(chr){
         1266         case 'g':
         1267                 /*
         1268                  * convert to at most prec significant digits. (prec=0 means 1)
         1269                  */
         1270                 if(prec == 0)
         1271                         prec = 1;
         1272                 if(ndigits > prec) {
         1273                         if(digits[prec] >= '5' && xadd1(digits, prec))
         1274                                 exp++;
         1275                         exp += ndigits-prec;
         1276                         ndigits = prec;
         1277                 }
         1278                 
         1279                 /*
         1280                  * extra rules for %g (implemented below):
         1281                  *        trailing zeros removed after decimal unless FmtSharp.
         1282                  *        decimal point only if digit follows.
         1283                  */
         1284 
         1285                 /* fall through to %e */
         1286         default:
         1287         case 'e':
         1288                 /* 
         1289                  * one significant digit before decimal, no leading zeros.
         1290                  */
         1291                 point = 1;
         1292                 z1 = 0;
         1293                 
         1294                 /*
         1295                  * decimal point is after ndigits digits right now.
         1296                  * slide to be after first.
         1297                  */
         1298                 e  = exp + (ndigits-1);
         1299 
         1300                 /*
         1301                  * if this is %g, check exponent and convert prec
         1302                  */
         1303                 if(realchr == 'g') {
         1304                         if(-4 <= e && e < prec)
         1305                                 goto casef;
         1306                         prec--;        /* one digit before decimal; rest after */
         1307                 }
         1308 
         1309                 /*
         1310                  * compute trailing zero padding or truncate digits.
         1311                  */
         1312                 if(1+prec >= ndigits)
         1313                         z2 = 1+prec - ndigits;
         1314                 else {
         1315                         /*
         1316                          * truncate digits
         1317                          */
         1318                         assert(realchr != 'g');
         1319                         newndigits = 1+prec;
         1320                         if(digits[newndigits] >= '5' && xadd1(digits, newndigits)) {
         1321                                 /*
         1322                                  * had 999e4, now have 100e5
         1323                                  */
         1324                                 e++;
         1325                         }
         1326                         ndigits = newndigits;
         1327                         z2 = 0;
         1328                 }
         1329                 xfmtexp(suf, e, ucase);
         1330                 sufwid = strlen(suf);
         1331                 break;
         1332 
         1333         casef:
         1334         case 'f':
         1335                 /*
         1336                  * determine where digits go with respect to decimal point
         1337                  */
         1338                 if(ndigits+exp > 0) {
         1339                         point = ndigits+exp;
         1340                         z1 = 0;
         1341                 } else {
         1342                         point = 1;
         1343                         z1 = 1 + -(ndigits+exp);
         1344                 }
         1345 
         1346                 /*
         1347                  * %g specifies prec = number of significant digits
         1348                  * convert to number of digits after decimal point
         1349                  */
         1350                 if(realchr == 'g')
         1351                         prec += z1 - point;
         1352 
         1353                 /*
         1354                  * compute trailing zero padding or truncate digits.
         1355                  */
         1356                 if(point+prec >= z1+ndigits)
         1357                         z2 = point+prec - (z1+ndigits);
         1358                 else {
         1359                         /*
         1360                          * truncate digits
         1361                          */
         1362                         assert(realchr != 'g');
         1363                         newndigits = point+prec - z1;
         1364                         if(newndigits < 0) {
         1365                                 z1 += newndigits;
         1366                                 newndigits = 0;
         1367                         } else if(newndigits == 0) {
         1368                                 /* perhaps round up */
         1369                                 if(digits[0] >= '5'){
         1370                                         digits[0] = '1';
         1371                                         newndigits = 1;
         1372                                         goto newdigit;
         1373                                 }
         1374                         } else if(digits[newndigits] >= '5' && xadd1(digits, newndigits)) {
         1375                                 /*
         1376                                  * digits was 999, is now 100; make it 1000
         1377                                  */
         1378                                 digits[newndigits++] = '0';
         1379                         newdigit:
         1380                                 /*
         1381                                  * account for new digit
         1382                                  */
         1383                                 if(z1)        /* 0.099 => 0.100 or 0.99 => 1.00*/
         1384                                         z1--;
         1385                                 else        /* 9.99 => 10.00 */
         1386                                         point++;
         1387                         }
         1388                         z2 = 0;
         1389                         ndigits = newndigits;
         1390                 }        
         1391                 sufwid = 0;
         1392                 break;
         1393         }
         1394         
         1395         /*
         1396          * if %g is given without FmtSharp, remove trailing zeros.
         1397          * must do after truncation, so that e.g. print %.3g 1.001
         1398          * produces 1, not 1.00.  sorry, but them's the rules.
         1399          */
         1400         if(realchr == 'g' && !(fl & FmtSharp)) {
         1401                 if(z1+ndigits+z2 >= point) {
         1402                         if(z1+ndigits < point)
         1403                                 z2 = point - (z1+ndigits);
         1404                         else{
         1405                                 z2 = 0;
         1406                                 while(z1+ndigits > point && digits[ndigits-1] == '0')
         1407                                         ndigits--;
         1408                         }
         1409                 }
         1410         }
         1411 
         1412         /*
         1413          * compute width of all digits and decimal point and suffix if any
         1414          */
         1415         wid = z1+ndigits+z2;
         1416         if(wid > point)
         1417                 wid += dotwid;
         1418         else if(wid == point){
         1419                 if(fl & FmtSharp)
         1420                         wid += dotwid;
         1421                 else
         1422                         point++;        /* do not print any decimal point */
         1423         }
         1424         wid += sufwid;
         1425 
         1426         /*
         1427          * determine sign
         1428          */
         1429         sign = 0;
         1430         if(neg)
         1431                 sign = '-';
         1432         else if(fl & FmtSign)
         1433                 sign = '+';
         1434         else if(fl & FmtSpace)
         1435                 sign = ' ';
         1436         if(sign)
         1437                 wid++;
         1438 
         1439         /*
         1440          * compute padding
         1441          */
         1442         pad = 0;
         1443         if((fl & FmtWidth) && fmt->width > wid)
         1444                 pad = fmt->width - wid;
         1445         if(pad && !(fl & FmtLeft) && (fl & FmtZero)){
         1446                 z1 += pad;
         1447                 point += pad;
         1448                 pad = 0;
         1449         }
         1450 
         1451         /*
         1452          * format the actual field.  too bad about doing this twice.
         1453          */
         1454         if(fmt->runes){
         1455                 if(pad && !(fl & FmtLeft) && __rfmtpad(fmt, pad) < 0)
         1456                         return -1;
         1457                 rt = (Rune*)fmt->to;
         1458                 rs = (Rune*)fmt->stop;
         1459                 if(sign)
         1460                         FMTRCHAR(fmt, rt, rs, sign);
         1461                 while(z1>0 || ndigits>0 || z2>0) {
         1462                         if(z1 > 0){
         1463                                 z1--;
         1464                                 c = '0';
         1465                         }else if(ndigits > 0){
         1466                                 ndigits--;
         1467                                 c = *digits++;
         1468                         }else{
         1469                                 z2--;
         1470                                 c = '0';
         1471                         }
         1472                         FMTRCHAR(fmt, rt, rs, c);
         1473                         if(--point == 0) {
         1474                                 for(p = dot; *p; ){
         1475                                         p += chartorune(&r, p);
         1476                                         FMTRCHAR(fmt, rt, rs, r);
         1477                                 }
         1478                         }
         1479                 }
         1480                 fmt->nfmt += rt - (Rune*)fmt->to;
         1481                 fmt->to = rt;
         1482                 if(sufwid && __fmtcpy(fmt, suf, sufwid, sufwid) < 0)
         1483                         return -1;
         1484                 if(pad && (fl & FmtLeft) && __rfmtpad(fmt, pad) < 0)
         1485                         return -1;
         1486         }else{
         1487                 if(pad && !(fl & FmtLeft) && __fmtpad(fmt, pad) < 0)
         1488                         return -1;
         1489                 t = (char*)fmt->to;
         1490                 s = (char*)fmt->stop;
         1491                 if(sign)
         1492                         FMTCHAR(fmt, t, s, sign);
         1493                 while(z1>0 || ndigits>0 || z2>0) {
         1494                         if(z1 > 0){
         1495                                 z1--;
         1496                                 c = '0';
         1497                         }else if(ndigits > 0){
         1498                                 ndigits--;
         1499                                 c = *digits++;
         1500                         }else{
         1501                                 z2--;
         1502                                 c = '0';
         1503                         }
         1504                         FMTCHAR(fmt, t, s, c);
         1505                         if(--point == 0)
         1506                                 for(p=dot; *p; p++)
         1507                                         FMTCHAR(fmt, t, s, *p);
         1508                 }
         1509                 fmt->nfmt += t - (char*)fmt->to;
         1510                 fmt->to = t;
         1511                 if(sufwid && __fmtcpy(fmt, suf, sufwid, sufwid) < 0)
         1512                         return -1;
         1513                 if(pad && (fl & FmtLeft) && __fmtpad(fmt, pad) < 0)
         1514                         return -1;
         1515         }
         1516         return 0;
         1517 }
         1518 
         1519 /* -------------- fmt.c --------------- */
         1520 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         1521 // #include <stdarg.h>
         1522 // #include <string.h>
         1523 // #include "plan9.h"
         1524 // #include "fmt.h"
         1525 // #include "fmtdef.h"
         1526 
         1527 enum
         1528 {
         1529         Maxfmt = 64
         1530 };
         1531 
         1532 typedef struct Convfmt Convfmt;
         1533 struct Convfmt
         1534 {
         1535         int        c;
         1536         volatile        Fmts        fmt;        /* for spin lock in fmtfmt; avoids race due to write order */
         1537 };
         1538 
         1539 static struct
         1540 {
         1541         /* lock by calling __fmtlock, __fmtunlock */
         1542         int        nfmt;
         1543         Convfmt        fmt[Maxfmt];
         1544 } fmtalloc;
         1545 
         1546 static Convfmt knownfmt[] = {
         1547         { ' ',        __flagfmt },
         1548         { '#',        __flagfmt },
         1549         { '%',        __percentfmt },
         1550         { '\'',        __flagfmt },
         1551         { '+',        __flagfmt },
         1552         { ',',        __flagfmt },
         1553         { '-',        __flagfmt },
         1554         { 'C',        __runefmt },        /* Plan 9 addition */
         1555         { 'E',        __efgfmt },
         1556 #ifndef PLAN9PORT
         1557         { 'F',        __efgfmt },        /* ANSI only */
         1558 #endif
         1559         { 'G',        __efgfmt },
         1560 #ifndef PLAN9PORT
         1561         { 'L',        __flagfmt },        /* ANSI only */
         1562 #endif
         1563         { 'S',        __runesfmt },        /* Plan 9 addition */
         1564         { 'X',        __ifmt },
         1565         { 'b',        __ifmt },                /* Plan 9 addition */
         1566         { 'c',        __charfmt },
         1567         { 'd',        __ifmt },
         1568         { 'e',        __efgfmt },
         1569         { 'f',        __efgfmt },
         1570         { 'g',        __efgfmt },
         1571         { 'h',        __flagfmt },
         1572 #ifndef PLAN9PORT
         1573         { 'i',        __ifmt },                /* ANSI only */
         1574 #endif
         1575         { 'l',        __flagfmt },
         1576         { 'n',        __countfmt },
         1577         { 'o',        __ifmt },
         1578         { 'p',        __ifmt },
         1579         { 'r',        __errfmt },
         1580         { 's',        __strfmt },
         1581 #ifdef PLAN9PORT
         1582         { 'u',        __flagfmt },
         1583 #else
         1584         { 'u',        __ifmt },
         1585 #endif
         1586         { 'x',        __ifmt },
         1587         { 0,        nil }
         1588 };
         1589 
         1590 
         1591 int        (*fmtdoquote)(int);
         1592 
         1593 /*
         1594  * __fmtlock() must be set
         1595  */
         1596 static int
         1597 __fmtinstall(int c, Fmts f)
         1598 {
         1599         Convfmt *p, *ep;
         1600 
         1601         if(c<=0 || c>=65536)
         1602                 return -1;
         1603         if(!f)
         1604                 f = __badfmt;
         1605 
         1606         ep = &fmtalloc.fmt[fmtalloc.nfmt];
         1607         for(p=fmtalloc.fmt; p<ep; p++)
         1608                 if(p->c == c)
         1609                         break;
         1610 
         1611         if(p == &fmtalloc.fmt[Maxfmt])
         1612                 return -1;
         1613 
         1614         p->fmt = f;
         1615         if(p == ep){        /* installing a new format character */
         1616                 fmtalloc.nfmt++;
         1617                 p->c = c;
         1618         }
         1619 
         1620         return 0;
         1621 }
         1622 
         1623 int
         1624 fmtinstall(int c, int (*f)(Fmt*))
         1625 {
         1626         int ret;
         1627 
         1628         __fmtlock();
         1629         ret = __fmtinstall(c, f);
         1630         __fmtunlock();
         1631         return ret;
         1632 }
         1633 
         1634 static Fmts
         1635 fmtfmt(int c)
         1636 {
         1637         Convfmt *p, *ep;
         1638 
         1639         ep = &fmtalloc.fmt[fmtalloc.nfmt];
         1640         for(p=fmtalloc.fmt; p<ep; p++)
         1641                 if(p->c == c){
         1642                         while(p->fmt == nil)        /* loop until value is updated */
         1643                                 ;
         1644                         return p->fmt;
         1645                 }
         1646 
         1647         /* is this a predefined format char? */
         1648         __fmtlock();
         1649         for(p=knownfmt; p->c; p++)
         1650                 if(p->c == c){
         1651                         __fmtinstall(p->c, p->fmt);
         1652                         __fmtunlock();
         1653                         return p->fmt;
         1654                 }
         1655         __fmtunlock();
         1656 
         1657         return __badfmt;
         1658 }
         1659 
         1660 void*
         1661 __fmtdispatch(Fmt *f, void *fmt, int isrunes)
         1662 {
         1663         Rune rune, r;
         1664         int i, n;
         1665 
         1666         f->flags = 0;
         1667         f->width = f->prec = 0;
         1668 
         1669         for(;;){
         1670                 if(isrunes){
         1671                         r = *(Rune*)fmt;
         1672                         fmt = (Rune*)fmt + 1;
         1673                 }else{
         1674                         fmt = (char*)fmt + chartorune(&rune, (char*)fmt);
         1675                         r = rune;
         1676                 }
         1677                 f->r = r;
         1678                 switch(r){
         1679                 case '\0':
         1680                         return nil;
         1681                 case '.':
         1682                         f->flags |= FmtWidth|FmtPrec;
         1683                         continue;
         1684                 case '0':
         1685                         if(!(f->flags & FmtWidth)){
         1686                                 f->flags |= FmtZero;
         1687                                 continue;
         1688                         }
         1689                         /* fall through */
         1690                 case '1': case '2': case '3': case '4':
         1691                 case '5': case '6': case '7': case '8': case '9':
         1692                         i = 0;
         1693                         while(r >= '0' && r <= '9'){
         1694                                 i = i * 10 + r - '0';
         1695                                 if(isrunes){
         1696                                         r = *(Rune*)fmt;
         1697                                         fmt = (Rune*)fmt + 1;
         1698                                 }else{
         1699                                         r = *(char*)fmt;
         1700                                         fmt = (char*)fmt + 1;
         1701                                 }
         1702                         }
         1703                         if(isrunes)
         1704                                 fmt = (Rune*)fmt - 1;
         1705                         else
         1706                                 fmt = (char*)fmt - 1;
         1707                 numflag:
         1708                         if(f->flags & FmtWidth){
         1709                                 f->flags |= FmtPrec;
         1710                                 f->prec = i;
         1711                         }else{
         1712                                 f->flags |= FmtWidth;
         1713                                 f->width = i;
         1714                         }
         1715                         continue;
         1716                 case '*':
         1717                         i = va_arg(f->args, int);
         1718                         if(i < 0){
         1719                                 /*
         1720                                  * negative precision =>
         1721                                  * ignore the precision.
         1722                                  */
         1723                                 if(f->flags & FmtPrec){
         1724                                         f->flags &= ~FmtPrec;
         1725                                         f->prec = 0;
         1726                                         continue;
         1727                                 }
         1728                                 i = -i;
         1729                                 f->flags |= FmtLeft;
         1730                         }
         1731                         goto numflag;
         1732                 }
         1733                 n = (*fmtfmt(r))(f);
         1734                 if(n < 0)
         1735                         return nil;
         1736                 if(n == 0)
         1737                         return fmt;
         1738         }
         1739 }
         1740 /* -------------- fmtfd.c --------------- */
         1741 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         1742 // #include <stdarg.h>
         1743 // #include <string.h>
         1744 // #include "plan9.h"
         1745 // #include "fmt.h"
         1746 // #include "fmtdef.h"
         1747 
         1748 /*
         1749  * public routine for final flush of a formatting buffer
         1750  * to a file descriptor; returns total char count.
         1751  */
         1752 int
         1753 fmtfdflush(Fmt *f)
         1754 {
         1755         if(__fmtFdFlush(f) <= 0)
         1756                 return -1;
         1757         return f->nfmt;
         1758 }
         1759 
         1760 /*
         1761  * initialize an output buffer for buffered printing
         1762  */
         1763 int
         1764 fmtfdinit(Fmt *f, int fd, char *buf, int size)
         1765 {
         1766         f->runes = 0;
         1767         f->start = buf;
         1768         f->to = buf;
         1769         f->stop = buf + size;
         1770         f->flush = __fmtFdFlush;
         1771         f->farg = (void*)(uintptr_t)fd;
         1772         f->flags = 0;
         1773         f->nfmt = 0;
         1774         fmtlocaleinit(f, nil, nil, nil);
         1775         return 0;
         1776 }
         1777 /* -------------- fmtfdflush.c --------------- */
         1778 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         1779 // #include <stdarg.h>
         1780 // #include <unistd.h>
         1781 // #include "plan9.h"
         1782 // #include "fmt.h"
         1783 // #include "fmtdef.h"
         1784 
         1785 /*
         1786  * generic routine for flushing a formatting buffer
         1787  * to a file descriptor
         1788  */
         1789 int
         1790 __fmtFdFlush(Fmt *f)
         1791 {
         1792         int n;
         1793 
         1794         n = (char*)f->to - (char*)f->start;
         1795         if(n && write((uintptr)f->farg, f->start, n) != n)
         1796                 return 0;
         1797         f->to = f->start;
         1798         return 1;
         1799 }
         1800 /* -------------- fmtlocale.c --------------- */
         1801 /* Copyright (c) 2004 Google Inc.; see LICENSE */
         1802 
         1803 // #include <stdarg.h>
         1804 // #include <string.h>
         1805 // #include "plan9.h"
         1806 // #include "fmt.h"
         1807 // #include "fmtdef.h"
         1808 
         1809 /*
         1810  * Fill in the internationalization stuff in the State structure.
         1811  * For nil arguments, provide the sensible defaults:
         1812  *        decimal is a period
         1813  *        thousands separator is a comma
         1814  *        thousands are marked every three digits
         1815  */
         1816 void
         1817 fmtlocaleinit(Fmt *f, char *decimal, char *thousands, char *grouping)
         1818 {
         1819         if(decimal == nil || decimal[0] == '\0')
         1820                 decimal = ".";
         1821         if(thousands == nil)
         1822                 thousands = ",";
         1823         if(grouping == nil)
         1824                 grouping = "\3";
         1825         f->decimal = decimal;
         1826         f->thousands = thousands;
         1827         f->grouping = grouping;
         1828 }
         1829 
         1830 /*
         1831  * We are about to emit a digit in e.g. %'d.  If that digit would
         1832  * overflow a thousands (e.g.) grouping, tell the caller to emit
         1833  * the thousands separator.  Always advance the digit counter
         1834  * and pointer into the grouping descriptor.
         1835  */
         1836 int
         1837 __needsep(int *ndig, char **grouping)
         1838 {
         1839         int group;
         1840         
         1841         (*ndig)++;
         1842         group = *(unsigned char*)*grouping;
         1843         /* CHAR_MAX means no further grouping. \0 means we got the empty string */
         1844         if(group == 0xFF || group == 0x7f || group == 0x00)
         1845                 return 0;
         1846         if(*ndig > group){
         1847                 /* if we're at end of string, continue with this grouping; else advance */
         1848                 if((*grouping)[1] != '\0')
         1849                         (*grouping)++;
         1850                 *ndig = 1;
         1851                 return 1;
         1852         }
         1853         return 0;
         1854 }
         1855 
         1856 /* -------------- fmtlock.c --------------- */
         1857 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         1858 // #include <stdarg.h>
         1859 // #include "plan9.h"
         1860 // #include "fmt.h"
         1861 // #include "fmtdef.h"
         1862 
         1863 void
         1864 __fmtlock(void)
         1865 {
         1866 }
         1867 
         1868 void
         1869 __fmtunlock(void)
         1870 {
         1871 }
         1872 /* -------------- fmtnull.c --------------- */
         1873 /* Copyright (c) 2004 Google Inc.; see LICENSE */
         1874 // #include <stdarg.h>
         1875 // #include <string.h>
         1876 // #include "plan9.h"
         1877 // #include "fmt.h"
         1878 // #include "fmtdef.h"
         1879 
         1880 /*
         1881  * Absorb output without using resources.
         1882  */
         1883 static Rune nullbuf[32];
         1884 
         1885 static int
         1886 __fmtnullflush(Fmt *f)
         1887 {
         1888         f->to = nullbuf;
         1889         f->nfmt = 0;
         1890         return 0;
         1891 }
         1892 
         1893 int
         1894 fmtnullinit(Fmt *f)
         1895 {
         1896         memset(f, 0, sizeof *f);
         1897         f->runes = 1;
         1898         f->start = nullbuf;
         1899         f->to = nullbuf;
         1900         f->stop = nullbuf+nelem(nullbuf);
         1901         f->flush = __fmtnullflush;
         1902         fmtlocaleinit(f, nil, nil, nil);
         1903         return 0;
         1904 }
         1905 
         1906 /* -------------- fmtprint.c --------------- */
         1907 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         1908 // #include <stdarg.h>
         1909 // #include <string.h>
         1910 // #include "plan9.h"
         1911 // #include "fmt.h"
         1912 // #include "fmtdef.h"
         1913 
         1914 /*
         1915  * format a string into the output buffer
         1916  * designed for formats which themselves call fmt,
         1917  * but ignore any width flags
         1918  */
         1919 int
         1920 fmtprint(Fmt *f, char *fmt, ...)
         1921 {
         1922         va_list va;
         1923         int n;
         1924 
         1925         f->flags = 0;
         1926         f->width = 0;
         1927         f->prec = 0;
         1928         VA_COPY(va, f->args);
         1929         VA_END(f->args);
         1930         va_start(f->args, fmt);
         1931         n = dofmt(f, fmt);
         1932         va_end(f->args);
         1933         f->flags = 0;
         1934         f->width = 0;
         1935         f->prec = 0;
         1936         VA_COPY(f->args,va);
         1937         VA_END(va);
         1938         if(n >= 0)
         1939                 return 0;
         1940         return n;
         1941 }
         1942 
         1943 /* -------------- fmtquote.c --------------- */
         1944 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         1945 // #include <stdarg.h>
         1946 // #include <string.h>
         1947 // #include "plan9.h"
         1948 // #include "fmt.h"
         1949 // #include "fmtdef.h"
         1950 
         1951 /*
         1952  * How many bytes of output UTF will be produced by quoting (if necessary) this string?
         1953  * How many runes? How much of the input will be consumed?
         1954  * The parameter q is filled in by __quotesetup.
         1955  * The string may be UTF or Runes (s or r).
         1956  * Return count does not include NUL.
         1957  * Terminate the scan at the first of:
         1958  *        NUL in input
         1959  *        count exceeded in input
         1960  *        count exceeded on output
         1961  * *ninp is set to number of input bytes accepted.
         1962  * nin may be <0 initially, to avoid checking input by count.
         1963  */
         1964 void
         1965 __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout)
         1966 {
         1967         int w;
         1968         Rune c;
         1969 
         1970         q->quoted = 0;
         1971         q->nbytesout = 0;
         1972         q->nrunesout = 0;
         1973         q->nbytesin = 0;
         1974         q->nrunesin = 0;
         1975         if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){
         1976                 if(nout < 2)
         1977                         return;
         1978                 q->quoted = 1;
         1979                 q->nbytesout = 2;
         1980                 q->nrunesout = 2;
         1981         }
         1982         for(; nin!=0; nin--){
         1983                 if(s)
         1984                         w = chartorune(&c, s);
         1985                 else{
         1986                         c = *r;
         1987                         w = runelen(c);
         1988                 }
         1989 
         1990                 if(c == '\0')
         1991                         break;
         1992                 if(runesout){
         1993                         if(q->nrunesout+1 > nout)
         1994                                 break;
         1995                 }else{
         1996                         if(q->nbytesout+w > nout)
         1997                                 break;
         1998                 }
         1999 
         2000                 if((c <= L' ') || (c == L'\'') || (fmtdoquote!=nil && fmtdoquote(c))){
         2001                         if(!q->quoted){
         2002                                 if(runesout){
         2003                                         if(1+q->nrunesout+1+1 > nout)        /* no room for quotes */
         2004                                                 break;
         2005                                 }else{
         2006                                         if(1+q->nbytesout+w+1 > nout)        /* no room for quotes */
         2007                                                 break;
         2008                                 }
         2009                                 q->nrunesout += 2;        /* include quotes */
         2010                                 q->nbytesout += 2;        /* include quotes */
         2011                                 q->quoted = 1;
         2012                         }
         2013                         if(c == '\'')        {
         2014                                 if(runesout){
         2015                                         if(1+q->nrunesout+1 > nout)        /* no room for quotes */
         2016                                                 break;
         2017                                 }else{
         2018                                         if(1+q->nbytesout+w > nout)        /* no room for quotes */
         2019                                                 break;
         2020                                 }
         2021                                 q->nbytesout++;
         2022                                 q->nrunesout++;        /* quotes reproduce as two characters */
         2023                         }
         2024                 }
         2025 
         2026                 /* advance input */
         2027                 if(s)
         2028                         s += w;
         2029                 else
         2030                         r++;
         2031                 q->nbytesin += w;
         2032                 q->nrunesin++;
         2033 
         2034                 /* advance output */
         2035                 q->nbytesout += w;
         2036                 q->nrunesout++;
         2037 
         2038 #ifndef PLAN9PORT
         2039                 /* ANSI requires precision in bytes, not Runes. */
         2040                 nin-= w-1;        /* and then n-- in the loop */
         2041 #endif
         2042         }
         2043 }
         2044 
         2045 static int
         2046 qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f)
         2047 {
         2048         Rune r, *rm, *rme;
         2049         char *t, *s, *m, *me;
         2050         Rune *rt, *rs;
         2051         ulong fl;
         2052         int nc, w;
         2053 
         2054         m = sin;
         2055         me = m + q->nbytesin;
         2056         rm = rin;
         2057         rme = rm + q->nrunesin;
         2058 
         2059         fl = f->flags;
         2060         w = 0;
         2061         if(fl & FmtWidth)
         2062                 w = f->width;
         2063         if(f->runes){
         2064                 if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0)
         2065                         return -1;
         2066         }else{
         2067                 if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0)
         2068                         return -1;
         2069         }
         2070         t = (char*)f->to;
         2071         s = (char*)f->stop;
         2072         rt = (Rune*)f->to;
         2073         rs = (Rune*)f->stop;
         2074         if(f->runes)
         2075                 FMTRCHAR(f, rt, rs, '\'');
         2076         else
         2077                 FMTRUNE(f, t, s, '\'');
         2078         for(nc = q->nrunesin; nc > 0; nc--){
         2079                 if(sin){
         2080                         r = *(uchar*)m;
         2081                         if(r < Runeself)
         2082                                 m++;
         2083                         else if((me - m) >= UTFmax || fullrune(m, me-m))
         2084                                 m += chartorune(&r, m);
         2085                         else
         2086                                 break;
         2087                 }else{
         2088                         if(rm >= rme)
         2089                                 break;
         2090                         r = *(uchar*)rm++;
         2091                 }
         2092                 if(f->runes){
         2093                         FMTRCHAR(f, rt, rs, r);
         2094                         if(r == '\'')
         2095                                 FMTRCHAR(f, rt, rs, r);
         2096                 }else{
         2097                         FMTRUNE(f, t, s, r);
         2098                         if(r == '\'')
         2099                                 FMTRUNE(f, t, s, r);
         2100                 }
         2101         }
         2102 
         2103         if(f->runes){
         2104                 FMTRCHAR(f, rt, rs, '\'');
         2105                 USED(rs);
         2106                 f->nfmt += rt - (Rune *)f->to;
         2107                 f->to = rt;
         2108                 if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0)
         2109                         return -1;
         2110         }else{
         2111                 FMTRUNE(f, t, s, '\'');
         2112                 USED(s);
         2113                 f->nfmt += t - (char *)f->to;
         2114                 f->to = t;
         2115                 if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0)
         2116                         return -1;
         2117         }
         2118         return 0;
         2119 }
         2120 
         2121 int
         2122 __quotestrfmt(int runesin, Fmt *f)
         2123 {
         2124         int nin, outlen;
         2125         Rune *r;
         2126         char *s;
         2127         Quoteinfo q;
         2128 
         2129         nin = -1;
         2130         if(f->flags&FmtPrec)
         2131                 nin = f->prec;
         2132         if(runesin){
         2133                 r = va_arg(f->args, Rune *);
         2134                 s = nil;
         2135         }else{
         2136                 s = va_arg(f->args, char *);
         2137                 r = nil;
         2138         }
         2139         if(!s && !r)
         2140                 return __fmtcpy(f, (void*)"<nil>", 5, 5);
         2141 
         2142         if(f->flush)
         2143                 outlen = 0x7FFFFFFF;        /* if we can flush, no output limit */
         2144         else if(f->runes)
         2145                 outlen = (Rune*)f->stop - (Rune*)f->to;
         2146         else
         2147                 outlen = (char*)f->stop - (char*)f->to;
         2148 
         2149         __quotesetup(s, r, nin, outlen, &q, f->flags&FmtSharp, f->runes);
         2150 /*print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout); */
         2151 
         2152         if(runesin){
         2153                 if(!q.quoted)
         2154                         return __fmtrcpy(f, r, q.nrunesin);
         2155                 return qstrfmt(nil, r, &q, f);
         2156         }
         2157 
         2158         if(!q.quoted)
         2159                 return __fmtcpy(f, s, q.nrunesin, q.nbytesin);
         2160         return qstrfmt(s, nil, &q, f);
         2161 }
         2162 
         2163 int
         2164 quotestrfmt(Fmt *f)
         2165 {
         2166         return __quotestrfmt(0, f);
         2167 }
         2168 
         2169 int
         2170 quoterunestrfmt(Fmt *f)
         2171 {
         2172         return __quotestrfmt(1, f);
         2173 }
         2174 
         2175 void
         2176 quotefmtinstall(void)
         2177 {
         2178         fmtinstall('q', quotestrfmt);
         2179         fmtinstall('Q', quoterunestrfmt);
         2180 }
         2181 
         2182 int
         2183 __needsquotes(char *s, int *quotelenp)
         2184 {
         2185         Quoteinfo q;
         2186 
         2187         __quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0);
         2188         *quotelenp = q.nbytesout;
         2189 
         2190         return q.quoted;
         2191 }
         2192 
         2193 int
         2194 __runeneedsquotes(Rune *r, int *quotelenp)
         2195 {
         2196         Quoteinfo q;
         2197 
         2198         __quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0);
         2199         *quotelenp = q.nrunesout;
         2200 
         2201         return q.quoted;
         2202 }
         2203 /* -------------- fmtrune.c --------------- */
         2204 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2205 // #include <stdarg.h>
         2206 // #include <string.h>
         2207 // #include "plan9.h"
         2208 // #include "fmt.h"
         2209 // #include "fmtdef.h"
         2210 
         2211 int
         2212 fmtrune(Fmt *f, int r)
         2213 {
         2214         Rune *rt;
         2215         char *t;
         2216         int n;
         2217 
         2218         if(f->runes){
         2219                 rt = (Rune*)f->to;
         2220                 FMTRCHAR(f, rt, f->stop, r);
         2221                 f->to = rt;
         2222                 n = 1;
         2223         }else{
         2224                 t = (char*)f->to;
         2225                 FMTRUNE(f, t, f->stop, r);
         2226                 n = t - (char*)f->to;
         2227                 f->to = t;
         2228         }
         2229         f->nfmt += n;
         2230         return 0;
         2231 }
         2232 /* -------------- fmtstr.c --------------- */
         2233 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2234 // #include <stdlib.h>
         2235 // #include <stdarg.h>
         2236 // #include "plan9.h"
         2237 // #include "fmt.h"
         2238 // #include "fmtdef.h"
         2239 
         2240 char*
         2241 fmtstrflush(Fmt *f)
         2242 {
         2243         if(f->start == nil)
         2244                 return nil;
         2245         *(char*)f->to = '\0';
         2246         f->to = f->start;
         2247         return (char*)f->start;
         2248 }
         2249 /* -------------- fmtvprint.c --------------- */
         2250 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2251 // #include <stdarg.h>
         2252 // #include <string.h>
         2253 // #include "plan9.h"
         2254 // #include "fmt.h"
         2255 // #include "fmtdef.h"
         2256 
         2257 
         2258 /*
         2259  * format a string into the output buffer
         2260  * designed for formats which themselves call fmt,
         2261  * but ignore any width flags
         2262  */
         2263 int
         2264 fmtvprint(Fmt *f, char *fmt, va_list args)
         2265 {
         2266         va_list va;
         2267         int n;
         2268 
         2269         f->flags = 0;
         2270         f->width = 0;
         2271         f->prec = 0;
         2272         VA_COPY(va,f->args);
         2273         VA_END(f->args);
         2274         VA_COPY(f->args,args);
         2275         n = dofmt(f, fmt);
         2276         f->flags = 0;
         2277         f->width = 0;
         2278         f->prec = 0;
         2279         VA_END(f->args);
         2280         VA_COPY(f->args,va);
         2281         VA_END(va);
         2282         if(n >= 0)
         2283                 return 0;
         2284         return n;
         2285 }
         2286 
         2287 /* -------------- fprint.c --------------- */
         2288 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2289 // #include <stdarg.h>
         2290 // #include "plan9.h"
         2291 // #include "fmt.h"
         2292 // #include "fmtdef.h"
         2293 
         2294 int
         2295 fprint(int fd, char *fmt, ...)
         2296 {
         2297         int n;
         2298         va_list args;
         2299 
         2300         va_start(args, fmt);
         2301         n = vfprint(fd, fmt, args);
         2302         va_end(args);
         2303         return n;
         2304 }
         2305 /* -------------- nan64.c --------------- */
         2306 /*
         2307  * 64-bit IEEE not-a-number routines.
         2308  * This is big/little-endian portable assuming that 
         2309  * the 64-bit doubles and 64-bit integers have the
         2310  * same byte ordering.
         2311  */
         2312 
         2313 // #include "plan9.h"
         2314 // #include "fmt.h"
         2315 // #include "fmtdef.h"
         2316 
         2317 #if defined (__APPLE__) || (__powerpc__)
         2318 #define _NEEDLL
         2319 #endif
         2320 
         2321 static uvlong uvnan    = ((uvlong)0x7FF00000<<32)|0x00000001;
         2322 static uvlong uvinf    = ((uvlong)0x7FF00000<<32)|0x00000000;
         2323 static uvlong uvneginf = ((uvlong)0xFFF00000<<32)|0x00000000;
         2324 
         2325 double
         2326 __NaN(void)
         2327 {
         2328         uvlong *p;
         2329 
         2330         /* gcc complains about "return *(double*)&uvnan;" */
         2331         p = &uvnan;
         2332         return *(double*)p;
         2333 }
         2334 
         2335 int
         2336 __isNaN(double d)
         2337 {
         2338         uvlong x;
         2339         double *p;
         2340 
         2341         p = &d;
         2342         x = *(uvlong*)p;
         2343         return (ulong)(x>>32)==0x7FF00000 && !__isInf(d, 0);
         2344 }
         2345 
         2346 double
         2347 __Inf(int sign)
         2348 {
         2349         uvlong *p;
         2350 
         2351         if(sign < 0)
         2352                 p = &uvinf;
         2353         else
         2354                 p = &uvneginf;
         2355         return *(double*)p;
         2356 }
         2357 
         2358 int
         2359 __isInf(double d, int sign)
         2360 {
         2361         uvlong x;
         2362         double *p;
         2363 
         2364         p = &d;
         2365         x = *(uvlong*)p;
         2366         if(sign == 0)
         2367                 return x==uvinf || x==uvneginf;
         2368         else if(sign > 0)
         2369                 return x==uvinf;
         2370         else
         2371                 return x==uvneginf;
         2372 }
         2373 /* -------------- pow10.c --------------- */
         2374 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2375 // #include <stdarg.h>
         2376 // #include <string.h>
         2377 // #include "plan9.h"
         2378 // #include "fmt.h"
         2379 // #include "fmtdef.h"
         2380 
         2381 /*
         2382  * this table might overflow 127-bit exponent representations.
         2383  * in that case, truncate it after 1.0e38.
         2384  * it is important to get all one can from this
         2385  * routine since it is used in atof to scale numbers.
         2386  * the presumption is that C converts fp numbers better
         2387  * than multipication of lower powers of 10.
         2388  */
         2389 
         2390 static
         2391 double        tab[] =
         2392 {
         2393         1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9,
         2394         1.0e10,1.0e11,1.0e12,1.0e13,1.0e14,1.0e15,1.0e16,1.0e17,1.0e18,1.0e19,
         2395         1.0e20,1.0e21,1.0e22,1.0e23,1.0e24,1.0e25,1.0e26,1.0e27,1.0e28,1.0e29,
         2396         1.0e30,1.0e31,1.0e32,1.0e33,1.0e34,1.0e35,1.0e36,1.0e37,1.0e38,1.0e39,
         2397         1.0e40,1.0e41,1.0e42,1.0e43,1.0e44,1.0e45,1.0e46,1.0e47,1.0e48,1.0e49,
         2398         1.0e50,1.0e51,1.0e52,1.0e53,1.0e54,1.0e55,1.0e56,1.0e57,1.0e58,1.0e59,
         2399         1.0e60,1.0e61,1.0e62,1.0e63,1.0e64,1.0e65,1.0e66,1.0e67,1.0e68,1.0e69,
         2400 };
         2401 
         2402 double
         2403 __fmtpow10(int n)
         2404 {
         2405         int m;
         2406 
         2407         if(n < 0) {
         2408                 n = -n;
         2409                 if(n < (int)(sizeof(tab)/sizeof(tab[0])))
         2410                         return 1/tab[n];
         2411                 m = n/2;
         2412                 return __fmtpow10(-m) * __fmtpow10(m-n);
         2413         }
         2414         if(n < (int)(sizeof(tab)/sizeof(tab[0])))
         2415                 return tab[n];
         2416         m = n/2;
         2417         return __fmtpow10(m) * __fmtpow10(n-m);
         2418 }
         2419 /* -------------- print.c --------------- */
         2420 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2421 // #include <stdarg.h>
         2422 // #include "plan9.h"
         2423 // #include "fmt.h"
         2424 // #include "fmtdef.h"
         2425 
         2426 /*
         2427 int
         2428 print(char *fmt, ...)
         2429 {
         2430         int n;
         2431         va_list args;
         2432 
         2433         va_start(args, fmt);
         2434         n = vfprint(1, fmt, args);
         2435         va_end(args);
         2436         return n;
         2437 }
         2438 */
         2439 
         2440 /* -------------- runefmtstr.c --------------- */
         2441 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2442 // #include <stdarg.h>
         2443 // #include <stdlib.h>
         2444 // #include "plan9.h"
         2445 // #include "fmt.h"
         2446 // #include "fmtdef.h"
         2447 
         2448 Rune*
         2449 runefmtstrflush(Fmt *f)
         2450 {
         2451         if(f->start == nil)
         2452                 return nil;
         2453         *(Rune*)f->to = '\0';
         2454         f->to = f->start;
         2455         return f->start;
         2456 }
         2457 /* -------------- runeseprint.c --------------- */
         2458 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2459 // #include <stdarg.h>
         2460 // #include <string.h>
         2461 // #include "plan9.h"
         2462 // #include "fmt.h"
         2463 // #include "fmtdef.h"
         2464 
         2465 Rune*
         2466 runeseprint(Rune *buf, Rune *e, char *fmt, ...)
         2467 {
         2468         Rune *p;
         2469         va_list args;
         2470 
         2471         va_start(args, fmt);
         2472         p = runevseprint(buf, e, fmt, args);
         2473         va_end(args);
         2474         return p;
         2475 }
         2476 /* -------------- runesmprint.c --------------- */
         2477 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2478 // #include <stdarg.h>
         2479 // #include <string.h>
         2480 // #include "plan9.h"
         2481 // #include "fmt.h"
         2482 // #include "fmtdef.h"
         2483 
         2484 Rune*
         2485 runesmprint(char *fmt, ...)
         2486 {
         2487         va_list args;
         2488         Rune *p;
         2489 
         2490         va_start(args, fmt);
         2491         p = runevsmprint(fmt, args);
         2492         va_end(args);
         2493         return p;
         2494 }
         2495 /* -------------- runesnprint.c --------------- */
         2496 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2497 // #include <stdarg.h>
         2498 // #include <string.h>
         2499 // #include "plan9.h"
         2500 // #include "fmt.h"
         2501 // #include "fmtdef.h"
         2502 
         2503 int
         2504 runesnprint(Rune *buf, int len, char *fmt, ...)
         2505 {
         2506         int n;
         2507         va_list args;
         2508 
         2509         va_start(args, fmt);
         2510         n = runevsnprint(buf, len, fmt, args);
         2511         va_end(args);
         2512         return n;
         2513 }
         2514 
         2515 /* -------------- runesprint.c --------------- */
         2516 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2517 // #include <stdarg.h>
         2518 // #include <string.h>
         2519 // #include "plan9.h"
         2520 // #include "fmt.h"
         2521 // #include "fmtdef.h"
         2522 
         2523 int
         2524 runesprint(Rune *buf, char *fmt, ...)
         2525 {
         2526         int n;
         2527         va_list args;
         2528 
         2529         va_start(args, fmt);
         2530         n = runevsnprint(buf, 256, fmt, args);
         2531         va_end(args);
         2532         return n;
         2533 }
         2534 /* -------------- runevseprint.c --------------- */
         2535 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2536 // #include <stdarg.h>
         2537 // #include <string.h>
         2538 // #include "plan9.h"
         2539 // #include "fmt.h"
         2540 // #include "fmtdef.h"
         2541 
         2542 Rune*
         2543 runevseprint(Rune *buf, Rune *e, char *fmt, va_list args)
         2544 {
         2545         Fmt f;
         2546 
         2547         if(e <= buf)
         2548                 return nil;
         2549         f.runes = 1;
         2550         f.start = buf;
         2551         f.to = buf;
         2552         f.stop = e - 1;
         2553         f.flush = nil;
         2554         f.farg = nil;
         2555         f.nfmt = 0;
         2556         VA_COPY(f.args,args);
         2557         fmtlocaleinit(&f, nil, nil, nil);
         2558         dofmt(&f, fmt);
         2559         VA_END(f.args);
         2560         *(Rune*)f.to = '\0';
         2561         return (Rune*)f.to;
         2562 }
         2563 
         2564 /* -------------- runevsmprint.c --------------- */
         2565 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2566 /*
         2567  * Plan 9 port version must include libc.h in order to 
         2568  * get Plan 9 debugging malloc, which sometimes returns
         2569  * different pointers than the standard malloc. 
         2570  */
         2571 #ifdef PLAN9PORT
         2572 // #include <u.h>
         2573 // #include <libc.h>
         2574 // #include "fmtdef.h"
         2575 #else
         2576 // #include <stdlib.h>
         2577 // #include <string.h>
         2578 // #include "plan9.h"
         2579 // #include "fmt.h"
         2580 // #include "fmtdef.h"
         2581 #endif
         2582 
         2583 static int
         2584 runeFmtStrFlush(Fmt *f)
         2585 {
         2586         Rune *s;
         2587         int n;
         2588 
         2589         if(f->start == nil)
         2590                 return 0;
         2591         n = (uintptr)f->farg;
         2592         n *= 2;
         2593         s = (Rune*)f->start;
         2594         f->start = realloc(s, sizeof(Rune)*n);
         2595         if(f->start == nil){
         2596                 f->farg = nil;
         2597                 f->to = nil;
         2598                 f->stop = nil;
         2599                 free(s);
         2600                 return 0;
         2601         }
         2602         f->farg = (void*)(uintptr)n;
         2603         f->to = (Rune*)f->start + ((Rune*)f->to - s);
         2604         f->stop = (Rune*)f->start + n - 1;
         2605         return 1;
         2606 }
         2607 
         2608 int
         2609 runefmtstrinit(Fmt *f)
         2610 {
         2611         int n;
         2612 
         2613         memset(f, 0, sizeof *f);
         2614         f->runes = 1;
         2615         n = 32;
         2616         f->start = malloc(sizeof(Rune)*n);
         2617         if(f->start == nil)
         2618                 return -1;
         2619         f->to = f->start;
         2620         f->stop = (Rune*)f->start + n - 1;
         2621         f->flush = runeFmtStrFlush;
         2622         f->farg = (void*)(uintptr)n;
         2623         f->nfmt = 0;
         2624         fmtlocaleinit(f, nil, nil, nil);
         2625         return 0;
         2626 }
         2627 
         2628 /*
         2629  * print into an allocated string buffer
         2630  */
         2631 Rune*
         2632 runevsmprint(char *fmt, va_list args)
         2633 {
         2634         Fmt f;
         2635         int n;
         2636 
         2637         if(runefmtstrinit(&f) < 0)
         2638                 return nil;
         2639         VA_COPY(f.args,args);
         2640         n = dofmt(&f, fmt);
         2641         VA_END(f.args);
         2642         if(f.start == nil)
         2643                 return nil;
         2644         if(n < 0){
         2645                 free(f.start);
         2646                 return nil;
         2647         }
         2648         *(Rune*)f.to = '\0';
         2649         return (Rune*)f.start;
         2650 }
         2651 /* -------------- runevsnprint.c --------------- */
         2652 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2653 // #include <stdarg.h>
         2654 // #include <string.h>
         2655 // #include "plan9.h"
         2656 // #include "fmt.h"
         2657 // #include "fmtdef.h"
         2658 
         2659 int
         2660 runevsnprint(Rune *buf, int len, char *fmt, va_list args)
         2661 {
         2662         Fmt f;
         2663 
         2664         if(len <= 0)
         2665                 return -1;
         2666         f.runes = 1;
         2667         f.start = buf;
         2668         f.to = buf;
         2669         f.stop = buf + len - 1;
         2670         f.flush = nil;
         2671         f.farg = nil;
         2672         f.nfmt = 0;
         2673         VA_COPY(f.args,args);
         2674         fmtlocaleinit(&f, nil, nil, nil);
         2675         dofmt(&f, fmt);
         2676         VA_END(f.args);
         2677         *(Rune*)f.to = '\0';
         2678         return (Rune*)f.to - buf;
         2679 }
         2680 /* -------------- seprint.c --------------- */
         2681 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2682 // #include <stdarg.h>
         2683 // #include "plan9.h"
         2684 // #include "fmt.h"
         2685 // #include "fmtdef.h"
         2686 
         2687 char*
         2688 seprint(char *buf, char *e, char *fmt, ...)
         2689 {
         2690         char *p;
         2691         va_list args;
         2692 
         2693         va_start(args, fmt);
         2694         p = vseprint(buf, e, fmt, args);
         2695         va_end(args);
         2696         return p;
         2697 }
         2698 /* -------------- smprint.c --------------- */
         2699 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2700 // #include <stdarg.h>
         2701 // #include "plan9.h"
         2702 // #include "fmt.h"
         2703 // #include "fmtdef.h"
         2704 
         2705 char*
         2706 smprint(char *fmt, ...)
         2707 {
         2708         va_list args;
         2709         char *p;
         2710 
         2711         va_start(args, fmt);
         2712         p = vsmprint(fmt, args);
         2713         va_end(args);
         2714         return p;
         2715 }
         2716 /* -------------- snprint.c --------------- */
         2717 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2718 // #include <stdarg.h>
         2719 // #include "plan9.h"
         2720 // #include "fmt.h"
         2721 // #include "fmtdef.h"
         2722 
         2723 int
         2724 snprint(char *buf, int len, char *fmt, ...)
         2725 {
         2726         int n;
         2727         va_list args;
         2728 
         2729         va_start(args, fmt);
         2730         n = vsnprint(buf, len, fmt, args);
         2731         va_end(args);
         2732         return n;
         2733 }
         2734 
         2735 /* -------------- sprint.c --------------- */
         2736 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2737 // #include <stdarg.h>
         2738 // #include <fmt.h>
         2739 // #include "plan9.h"
         2740 // #include "fmt.h"
         2741 // #include "fmtdef.h"
         2742 
         2743 int
         2744 sprint(char *buf, char *fmt, ...)
         2745 {
         2746         int n;
         2747         va_list args;
         2748 
         2749         va_start(args, fmt);
         2750         n = vsnprint(buf, 65536, fmt, args);
         2751         va_end(args);
         2752         return n;
         2753 }
         2754 /* -------------- strtod.c --------------- */
         2755 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         2756 // #include <stdlib.h>
         2757 // #include <math.h>
         2758 // #include <ctype.h>
         2759 // #include <stdlib.h>
         2760 // #include <string.h>
         2761 // #include <errno.h>
         2762 // #include "plan9.h"
         2763 // #include "fmt.h"
         2764 // #include "fmtdef.h"
         2765 
         2766 static ulong
         2767 umuldiv(ulong a, ulong b, ulong c)
         2768 {
         2769         double d;
         2770 
         2771         d = ((double)a * (double)b) / (double)c;
         2772         if(d >= 4294967295.)
         2773                 d = 4294967295.;
         2774         return (ulong)d;
         2775 }
         2776 
         2777 /*
         2778  * This routine will convert to arbitrary precision
         2779  * floating point entirely in multi-precision fixed.
         2780  * The answer is the closest floating point number to
         2781  * the given decimal number. Exactly half way are
         2782  * rounded ala ieee rules.
         2783  * Method is to scale input decimal between .500 and .999...
         2784  * with external power of 2, then binary search for the
         2785  * closest mantissa to this decimal number.
         2786  * Nmant is is the required precision. (53 for ieee dp)
         2787  * Nbits is the max number of bits/word. (must be <= 28)
         2788  * Prec is calculated - the number of words of fixed mantissa.
         2789  */
         2790 enum
         2791 {
         2792         Nbits        = 28,                                /* bits safely represented in a ulong */
         2793         Nmant        = 53,                                /* bits of precision required */
         2794         Prec        = (Nmant+Nbits+1)/Nbits,        /* words of Nbits each to represent mantissa */
         2795         Sigbit        = 1<<(Prec*Nbits-Nmant),        /* first significant bit of Prec-th word */
         2796         Ndig        = 1500,
         2797         One        = (ulong)(1<<Nbits),
         2798         Half        = (ulong)(One>>1),
         2799         Maxe        = 310,
         2800 
         2801         Fsign        = 1<<0,                /* found - */
         2802         Fesign        = 1<<1,                /* found e- */
         2803         Fdpoint        = 1<<2,                /* found . */
         2804 
         2805         S0        = 0,                /* _                _S0        +S1        #S2        .S3 */
         2806         S1,                        /* _+                #S2        .S3 */
         2807         S2,                        /* _+#                #S2        .S4        eS5 */
         2808         S3,                        /* _+.                #S4 */
         2809         S4,                        /* _+#.#        #S4        eS5 */
         2810         S5,                        /* _+#.#e        +S6        #S7 */
         2811         S6,                        /* _+#.#e+        #S7 */
         2812         S7                        /* _+#.#e+#        #S7 */
         2813 };
         2814 
         2815 static        int        xcmp(char*, char*);
         2816 static        int        fpcmp(char*, ulong*);
         2817 static        void        frnorm(ulong*);
         2818 static        void        divascii(char*, int*, int*, int*);
         2819 static        void        mulascii(char*, int*, int*, int*);
         2820 
         2821 typedef        struct        Tab        Tab;
         2822 struct        Tab
         2823 {
         2824         int        bp;
         2825         int        siz;
         2826         char*        cmp;
         2827 };
         2828 
         2829 double
         2830 fmtstrtod(const char *as, char **aas)
         2831 {
         2832         int na, ex, dp, bp, c, i, flag, state;
         2833         ulong low[Prec], hig[Prec], mid[Prec];
         2834         double d;
         2835         char *s, a[Ndig];
         2836 
         2837         flag = 0;        /* Fsign, Fesign, Fdpoint */
         2838         na = 0;                /* number of digits of a[] */
         2839         dp = 0;                /* na of decimal point */
         2840         ex = 0;                /* exonent */
         2841 
         2842         state = S0;
         2843         for(s=(char*)as;; s++) {
         2844                 c = *s;
         2845                 if(c >= '0' && c <= '9') {
         2846                         switch(state) {
         2847                         case S0:
         2848                         case S1:
         2849                         case S2:
         2850                                 state = S2;
         2851                                 break;
         2852                         case S3:
         2853                         case S4:
         2854                                 state = S4;
         2855                                 break;
         2856 
         2857                         case S5:
         2858                         case S6:
         2859                         case S7:
         2860                                 state = S7;
         2861                                 ex = ex*10 + (c-'0');
         2862                                 continue;
         2863                         }
         2864                         if(na == 0 && c == '0') {
         2865                                 dp--;
         2866                                 continue;
         2867                         }
         2868                         if(na < Ndig-50)
         2869                                 a[na++] = c;
         2870                         continue;
         2871                 }
         2872                 switch(c) {
         2873                 case '\t':
         2874                 case '\n':
         2875                 case '\v':
         2876                 case '\f':
         2877                 case '\r':
         2878                 case ' ':
         2879                         if(state == S0)
         2880                                 continue;
         2881                         break;
         2882                 case '-':
         2883                         if(state == S0)
         2884                                 flag |= Fsign;
         2885                         else
         2886                                 flag |= Fesign;
         2887                 case '+':
         2888                         if(state == S0)
         2889                                 state = S1;
         2890                         else
         2891                         if(state == S5)
         2892                                 state = S6;
         2893                         else
         2894                                 break;        /* syntax */
         2895                         continue;
         2896                 case '.':
         2897                         flag |= Fdpoint;
         2898                         dp = na;
         2899                         if(state == S0 || state == S1) {
         2900                                 state = S3;
         2901                                 continue;
         2902                         }
         2903                         if(state == S2) {
         2904                                 state = S4;
         2905                                 continue;
         2906                         }
         2907                         break;
         2908                 case 'e':
         2909                 case 'E':
         2910                         if(state == S2 || state == S4) {
         2911                                 state = S5;
         2912                                 continue;
         2913                         }
         2914                         break;
         2915                 }
         2916                 break;
         2917         }
         2918 
         2919         /*
         2920          * clean up return char-pointer
         2921          */
         2922         switch(state) {
         2923         case S0:
         2924                 if(xcmp(s, "nan") == 0) {
         2925                         if(aas != nil)
         2926                                 *aas = s+3;
         2927                         goto retnan;
         2928                 }
         2929         case S1:
         2930                 if(xcmp(s, "infinity") == 0) {
         2931                         if(aas != nil)
         2932                                 *aas = s+8;
         2933                         goto retinf;
         2934                 }
         2935                 if(xcmp(s, "inf") == 0) {
         2936                         if(aas != nil)
         2937                                 *aas = s+3;
         2938                         goto retinf;
         2939                 }
         2940         case S3:
         2941                 if(aas != nil)
         2942                         *aas = (char*)as;
         2943                 goto ret0;        /* no digits found */
         2944         case S6:
         2945                 s--;                /* back over +- */
         2946         case S5:
         2947                 s--;                /* back over e */
         2948                 break;
         2949         }
         2950         if(aas != nil)
         2951                 *aas = s;
         2952 
         2953         if(flag & Fdpoint)
         2954         while(na > 0 && a[na-1] == '0')
         2955                 na--;
         2956         if(na == 0)
         2957                 goto ret0;        /* zero */
         2958         a[na] = 0;
         2959         if(!(flag & Fdpoint))
         2960                 dp = na;
         2961         if(flag & Fesign)
         2962                 ex = -ex;
         2963         dp += ex;
         2964         if(dp < -Maxe){
         2965                 errno = ERANGE;
         2966                 goto ret0;        /* underflow by exp */
         2967         } else
         2968         if(dp > +Maxe)
         2969                 goto retinf;        /* overflow by exp */
         2970 
         2971         /*
         2972          * normalize the decimal ascii number
         2973          * to range .[5-9][0-9]* e0
         2974          */
         2975         bp = 0;                /* binary exponent */
         2976         while(dp > 0)
         2977                 divascii(a, &na, &dp, &bp);
         2978         while(dp < 0 || a[0] < '5')
         2979                 mulascii(a, &na, &dp, &bp);
         2980 
         2981         /* close approx by naive conversion */
         2982         mid[0] = 0;
         2983         mid[1] = 1;
         2984         for(i=0; (c=a[i]) != '\0'; i++) {
         2985                 mid[0] = mid[0]*10 + (c-'0');
         2986                 mid[1] = mid[1]*10;
         2987                 if(i >= 8)
         2988                         break;
         2989         }
         2990         low[0] = umuldiv(mid[0], One, mid[1]);
         2991         hig[0] = umuldiv(mid[0]+1, One, mid[1]);
         2992         for(i=1; i<Prec; i++) {
         2993                 low[i] = 0;
         2994                 hig[i] = One-1;
         2995         }
         2996 
         2997         /* binary search for closest mantissa */
         2998         for(;;) {
         2999                 /* mid = (hig + low) / 2 */
         3000                 c = 0;
         3001                 for(i=0; i<Prec; i++) {
         3002                         mid[i] = hig[i] + low[i];
         3003                         if(c)
         3004                                 mid[i] += One;
         3005                         c = mid[i] & 1;
         3006                         mid[i] >>= 1;
         3007                 }
         3008                 frnorm(mid);
         3009 
         3010                 /* compare */
         3011                 c = fpcmp(a, mid);
         3012                 if(c > 0) {
         3013                         c = 1;
         3014                         for(i=0; i<Prec; i++)
         3015                                 if(low[i] != mid[i]) {
         3016                                         c = 0;
         3017                                         low[i] = mid[i];
         3018                                 }
         3019                         if(c)
         3020                                 break;        /* between mid and hig */
         3021                         continue;
         3022                 }
         3023                 if(c < 0) {
         3024                         for(i=0; i<Prec; i++)
         3025                                 hig[i] = mid[i];
         3026                         continue;
         3027                 }
         3028 
         3029                 /* only hard part is if even/odd roundings wants to go up */
         3030                 c = mid[Prec-1] & (Sigbit-1);
         3031                 if(c == Sigbit/2 && (mid[Prec-1]&Sigbit) == 0)
         3032                         mid[Prec-1] -= c;
         3033                 break;        /* exactly mid */
         3034         }
         3035 
         3036         /* normal rounding applies */
         3037         c = mid[Prec-1] & (Sigbit-1);
         3038         mid[Prec-1] -= c;
         3039         if(c >= Sigbit/2) {
         3040                 mid[Prec-1] += Sigbit;
         3041                 frnorm(mid);
         3042         }
         3043         goto out;
         3044 
         3045 ret0:
         3046         return 0;
         3047 
         3048 retnan:
         3049         return __NaN();
         3050 
         3051 retinf:
         3052         /*
         3053          * Unix strtod requires these.  Plan 9 would return Inf(0) or Inf(-1). */
         3054         errno = ERANGE;
         3055         if(flag & Fsign)
         3056                 return -HUGE_VAL;
         3057         return HUGE_VAL;
         3058 
         3059 out:
         3060         d = 0;
         3061         for(i=0; i<Prec; i++)
         3062                 d = d*One + mid[i];
         3063         if(flag & Fsign)
         3064                 d = -d;
         3065         d = ldexp(d, bp - Prec*Nbits);
         3066         if(d == 0){        /* underflow */
         3067                 errno = ERANGE;
         3068         }
         3069         return d;
         3070 }
         3071 
         3072 static void
         3073 frnorm(ulong *f)
         3074 {
         3075         int i, c;
         3076 
         3077         c = 0;
         3078         for(i=Prec-1; i>0; i--) {
         3079                 f[i] += c;
         3080                 c = f[i] >> Nbits;
         3081                 f[i] &= One-1;
         3082         }
         3083         f[0] += c;
         3084 }
         3085 
         3086 static int
         3087 fpcmp(char *a, ulong* f)
         3088 {
         3089         ulong tf[Prec];
         3090         int i, d, c;
         3091 
         3092         for(i=0; i<Prec; i++)
         3093                 tf[i] = f[i];
         3094 
         3095         for(;;) {
         3096                 /* tf *= 10 */
         3097                 for(i=0; i<Prec; i++)
         3098                         tf[i] = tf[i]*10;
         3099                 frnorm(tf);
         3100                 d = (tf[0] >> Nbits) + '0';
         3101                 tf[0] &= One-1;
         3102 
         3103                 /* compare next digit */
         3104                 c = *a;
         3105                 if(c == 0) {
         3106                         if('0' < d)
         3107                                 return -1;
         3108                         if(tf[0] != 0)
         3109                                 goto cont;
         3110                         for(i=1; i<Prec; i++)
         3111                                 if(tf[i] != 0)
         3112                                         goto cont;
         3113                         return 0;
         3114                 }
         3115                 if(c > d)
         3116                         return +1;
         3117                 if(c < d)
         3118                         return -1;
         3119                 a++;
         3120         cont:;
         3121         }
         3122 }
         3123 
         3124 static void
         3125 divby(char *a, int *na, int b)
         3126 {
         3127         int n, c;
         3128         char *p;
         3129 
         3130         p = a;
         3131         n = 0;
         3132         while(n>>b == 0) {
         3133                 c = *a++;
         3134                 if(c == 0) {
         3135                         while(n) {
         3136                                 c = n*10;
         3137                                 if(c>>b)
         3138                                         break;
         3139                                 n = c;
         3140                         }
         3141                         goto xx;
         3142                 }
         3143                 n = n*10 + c-'0';
         3144                 (*na)--;
         3145         }
         3146         for(;;) {
         3147                 c = n>>b;
         3148                 n -= c<<b;
         3149                 *p++ = c + '0';
         3150                 c = *a++;
         3151                 if(c == 0)
         3152                         break;
         3153                 n = n*10 + c-'0';
         3154         }
         3155         (*na)++;
         3156 xx:
         3157         while(n) {
         3158                 n = n*10;
         3159                 c = n>>b;
         3160                 n -= c<<b;
         3161                 *p++ = c + '0';
         3162                 (*na)++;
         3163         }
         3164         *p = 0;
         3165 }
         3166 
         3167 static        Tab        tab1[] =
         3168 {
         3169         {  1,  0, "" },
         3170         {  3,  1, "7" },
         3171         {  6,  2, "63" },
         3172         {  9,  3, "511" },
         3173         { 13,  4, "8191" },
         3174         { 16,  5, "65535" },
         3175         { 19,  6, "524287" },
         3176         { 23,  7, "8388607" },
         3177         { 26,  8, "67108863" },
         3178         { 27,  9, "134217727" },
         3179 };
         3180 
         3181 static void
         3182 divascii(char *a, int *na, int *dp, int *bp)
         3183 {
         3184         int b, d;
         3185         Tab *t;
         3186 
         3187         d = *dp;
         3188         if(d >= (int)(nelem(tab1)))
         3189                 d = (int)(nelem(tab1))-1;
         3190         t = tab1 + d;
         3191         b = t->bp;
         3192         if(memcmp(a, t->cmp, t->siz) > 0)
         3193                 d--;
         3194         *dp -= d;
         3195         *bp += b;
         3196         divby(a, na, b);
         3197 }
         3198 
         3199 static void
         3200 mulby(char *a, char *p, char *q, int b)
         3201 {
         3202         int n, c;
         3203 
         3204         n = 0;
         3205         *p = 0;
         3206         for(;;) {
         3207                 q--;
         3208                 if(q < a)
         3209                         break;
         3210                 c = *q - '0';
         3211                 c = (c<<b) + n;
         3212                 n = c/10;
         3213                 c -= n*10;
         3214                 p--;
         3215                 *p = c + '0';
         3216         }
         3217         while(n) {
         3218                 c = n;
         3219                 n = c/10;
         3220                 c -= n*10;
         3221                 p--;
         3222                 *p = c + '0';
         3223         }
         3224 }
         3225 
         3226 static        Tab        tab2[] =
         3227 {
         3228         {  1,  1, "" },                                /* dp = 0-0 */
         3229         {  3,  3, "125" },
         3230         {  6,  5, "15625" },
         3231         {  9,  7, "1953125" },
         3232         { 13, 10, "1220703125" },
         3233         { 16, 12, "152587890625" },
         3234         { 19, 14, "19073486328125" },
         3235         { 23, 17, "11920928955078125" },
         3236         { 26, 19, "1490116119384765625" },
         3237         { 27, 19, "7450580596923828125" },                /* dp 8-9 */
         3238 };
         3239 
         3240 static void
         3241 mulascii(char *a, int *na, int *dp, int *bp)
         3242 {
         3243         char *p;
         3244         int d, b;
         3245         Tab *t;
         3246 
         3247         d = -*dp;
         3248         if(d >= (int)(nelem(tab2)))
         3249                 d = (int)(nelem(tab2))-1;
         3250         t = tab2 + d;
         3251         b = t->bp;
         3252         if(memcmp(a, t->cmp, t->siz) < 0)
         3253                 d--;
         3254         p = a + *na;
         3255         *bp -= b;
         3256         *dp += d;
         3257         *na += d;
         3258         mulby(a, p+d, p, b);
         3259 }
         3260 
         3261 static int
         3262 xcmp(char *a, char *b)
         3263 {
         3264         int c1, c2;
         3265 
         3266         while((c1 = *b++) != '\0') {
         3267                 c2 = *a++;
         3268                 if(isupper(c2))
         3269                         c2 = tolower(c2);
         3270                 if(c1 != c2)
         3271                         return 1;
         3272         }
         3273         return 0;
         3274 }
         3275 /* -------------- vfprint.c --------------- */
         3276 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         3277 // #include <stdarg.h>
         3278 // #include "plan9.h"
         3279 // #include "fmt.h"
         3280 // #include "fmtdef.h"
         3281 
         3282 int
         3283 vfprint(int fd, char *fmt, va_list args)
         3284 {
         3285         Fmt f;
         3286         char buf[256];
         3287         int n;
         3288 
         3289         fmtfdinit(&f, fd, buf, sizeof(buf));
         3290         VA_COPY(f.args,args);
         3291         n = dofmt(&f, fmt);
         3292         VA_END(f.args);
         3293         if(n > 0 && __fmtFdFlush(&f) == 0)
         3294                 return -1;
         3295         return n;
         3296 }
         3297 /* -------------- vseprint.c --------------- */
         3298 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         3299 // #include <stdarg.h>
         3300 // #include "plan9.h"
         3301 // #include "fmt.h"
         3302 // #include "fmtdef.h"
         3303 
         3304 char*
         3305 vseprint(char *buf, char *e, char *fmt, va_list args)
         3306 {
         3307         Fmt f;
         3308 
         3309         if(e <= buf)
         3310                 return nil;
         3311         f.runes = 0;
         3312         f.start = buf;
         3313         f.to = buf;
         3314         f.stop = e - 1;
         3315         f.flush = 0;
         3316         f.farg = nil;
         3317         f.nfmt = 0;
         3318         VA_COPY(f.args,args);
         3319         fmtlocaleinit(&f, nil, nil, nil);
         3320         dofmt(&f, fmt);
         3321         VA_END(f.args);
         3322         *(char*)f.to = '\0';
         3323         return (char*)f.to;
         3324 }
         3325 
         3326 /* -------------- vsmprint.c --------------- */
         3327 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         3328 /*
         3329  * Plan 9 port version must include libc.h in order to 
         3330  * get Plan 9 debugging malloc, which sometimes returns
         3331  * different pointers than the standard malloc. 
         3332  */
         3333 #ifdef PLAN9PORT
         3334 // #include <u.h>
         3335 // #include <libc.h>
         3336 // #include "fmtdef.h"
         3337 #else
         3338 // #include <stdlib.h>
         3339 // #include <string.h>
         3340 // #include "plan9.h"
         3341 // #include "fmt.h"
         3342 // #include "fmtdef.h"
         3343 #endif
         3344 
         3345 static int
         3346 fmtStrFlush(Fmt *f)
         3347 {
         3348         char *s;
         3349         int n;
         3350 
         3351         if(f->start == nil)
         3352                 return 0;
         3353         n = (uintptr)f->farg;
         3354         n *= 2;
         3355         s = (char*)f->start;
         3356         f->start = realloc(s, n);
         3357         if(f->start == nil){
         3358                 f->farg = nil;
         3359                 f->to = nil;
         3360                 f->stop = nil;
         3361                 free(s);
         3362                 return 0;
         3363         }
         3364         f->farg = (void*)(uintptr)n;
         3365         f->to = (char*)f->start + ((char*)f->to - s);
         3366         f->stop = (char*)f->start + n - 1;
         3367         return 1;
         3368 }
         3369 
         3370 int
         3371 fmtstrinit(Fmt *f)
         3372 {
         3373         int n;
         3374 
         3375         memset(f, 0, sizeof *f);
         3376         f->runes = 0;
         3377         n = 32;
         3378         f->start = malloc(n);
         3379         if(f->start == nil)
         3380                 return -1;
         3381         f->to = f->start;
         3382         f->stop = (char*)f->start + n - 1;
         3383         f->flush = fmtStrFlush;
         3384         f->farg = (void*)(uintptr)n;
         3385         f->nfmt = 0;
         3386         fmtlocaleinit(f, nil, nil, nil);
         3387         return 0;
         3388 }
         3389 
         3390 /*
         3391  * print into an allocated string buffer
         3392  */
         3393 char*
         3394 vsmprint(char *fmt, va_list args)
         3395 {
         3396         Fmt f;
         3397         int n;
         3398 
         3399         if(fmtstrinit(&f) < 0)
         3400                 return nil;
         3401         VA_COPY(f.args,args);
         3402         n = dofmt(&f, fmt);
         3403         VA_END(f.args);
         3404         if(n < 0){
         3405                 free(f.start);
         3406                 return nil;
         3407         }
         3408         return fmtstrflush(&f);
         3409 }
         3410 /* -------------- vsnprint.c --------------- */
         3411 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
         3412 // #include <stdlib.h>
         3413 // #include <stdarg.h>
         3414 // #include "plan9.h"
         3415 // #include "fmt.h"
         3416 // #include "fmtdef.h"
         3417 
         3418 int
         3419 vsnprint(char *buf, int len, char *fmt, va_list args)
         3420 {
         3421         Fmt f;
         3422 
         3423         if(len <= 0)
         3424                 return -1;
         3425         f.runes = 0;
         3426         f.start = buf;
         3427         f.to = buf;
         3428         f.stop = buf + len - 1;
         3429         f.flush = 0;
         3430         f.farg = nil;
         3431         f.nfmt = 0;
         3432         VA_COPY(f.args,args);
         3433         fmtlocaleinit(&f, nil, nil, nil);
         3434         dofmt(&f, fmt);
         3435         VA_END(f.args);
         3436         *(char*)f.to = '\0';
         3437         return (char*)f.to - buf;
         3438 }
         3439 
         3440 int
         3441 __errfmt(Fmt *f)
         3442 {
         3443         char *s;
         3444 
         3445         s = strerror(errno);
         3446         return fmtstrcpy(f, s);
         3447 }