perl/uts/sprintf_wrap.c
<<
>>
Prefs
   1#include        <stdlib.h>
   2#include        <stdio.h>
   3#include        <assert.h>
   4#include        <string.h>
   5
   6char    *UTS_sprintf_wrap();
   7char    *do_efmt();
   8char    *do_gfmt();
   9char    *Fill();
  10
  11/* main(argc, argv)
  12 * char **argv;
  13 * {
  14 *      double  d;
  15 *      char    *Fmt, *Ret;
  16 *      char    obuf[200];
  17 * 
  18 *      assert(argc > 2);
  19 *      Fmt = argv[1];
  20 *      d = strtod(argv[2], (char **)0);
  21 * 
  22 *      putchar('{');
  23 *      printf(Fmt, d);
  24 *      printf("}\n");
  25 * 
  26 *      Ret = UTS_sprintf_wrap(obuf, Fmt, d);
  27 *      assert(Ret == obuf);
  28 * 
  29 *      printf("{%s}\n", obuf);
  30 * }
  31 */
  32
  33char *
  34UTS_sprintf_wrap(obuf, fmt, d,
  35        a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
  36char    *obuf, *fmt;
  37double  d;
  38{
  39        int     fmtlen, Width=0, Precision=6, Alt=0, Plus=0, Minus=0,
  40                Zero = 0;
  41        int     FmtChar, BaseFmt = 0;
  42        char    *f = fmt, *AfterWidth = 0, *AfterPrecision = 0;
  43        char    *Dot;
  44
  45        if(*f++ != '%') {
  46                return
  47sprintf(obuf, fmt, d, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15);
  48        }
  49        fmtlen = strlen(fmt);
  50        FmtChar = fmt[fmtlen - 1];
  51        switch(FmtChar) {
  52        case 'f':
  53        case 'F':
  54                return
  55sprintf(obuf, fmt, d, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15);
  56        case 'e':
  57        case 'E':
  58                BaseFmt = 'e';
  59                goto BaseFmt_IsSet;
  60        case 'g':
  61        case 'G':
  62                BaseFmt = 'g';
  63BaseFmt_IsSet:
  64                if(*f == '#') { Alt = 1; ++f; }   /* Always has '.' */
  65                if(*f == '+') { Plus = 1; ++f; }  /* Force explicit sign */
  66                if(*f == '-') { Minus = 1; ++f; } /* Left justify */
  67                if(*f == '0') { Zero = 1; ++f;} /* Fill using 0s*/
  68                if(Dot = strchr(f, '.')) {
  69                        Precision = strtol(Dot+1, &AfterPrecision, 0);
  70                }
  71                if(!Dot || (Dot && Dot > f)) { /* Next char=='.' => no width*/
  72                        Width = strtol(f, &AfterWidth, 0);
  73                }
  74                if(Dot) { f = AfterPrecision; }
  75                else if(AfterWidth) { f = AfterWidth; }
  76                if(*f != FmtChar) goto regular_sprintf;
  77                 /* It doesn't look like a f.p. sprintf call */
  78                 /* from Perl_sv_vcatpvfn                    */
  79
  80                if(BaseFmt == 'e') {
  81                        return do_efmt(d, obuf, Width, Precision, Alt,
  82                                Plus, Minus, Zero, FmtChar == 'E');
  83                } else {
  84                        return do_gfmt(d, obuf, Width, Precision, Alt,
  85                                Plus, Minus, Zero, FmtChar == 'G');
  86                }
  87        default:
  88regular_sprintf:
  89                return
  90sprintf(obuf, fmt, d, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15);
  91        }
  92}
  93
  94char    *
  95do_efmt(d, obuf, Width, Precision, Alt, Plus, Minus, Zero, UpperCase)
  96char    *obuf;
  97double  d;
  98{
  99        char    *Ecvt;
 100        char    *ob;
 101        int     decpt, sign, E;
 102        int     len;
 103        int     AllZeroes = 0;
 104
 105        Ecvt = ecvt( d , Precision+1, &decpt, &sign);
 106
 107        /* fprintf(stderr, "decpt=%d, sign=%d\n", decpt, sign); */
 108
 109        len = strlen(Ecvt);
 110        if(strspn(Ecvt, "0") == len) AllZeroes = 1;
 111
 112        ob = obuf;
 113        if(sign)        *ob++ = '-';
 114        else if(Plus)   *ob++ = '+';
 115
 116        *ob++ = Ecvt[0];
 117
 118        if(Precision > 0 || Alt) *ob++ = '.';
 119        strcpy(ob, &Ecvt[1]);
 120
 121        ob += strlen(ob);       /* ADVANCE TO END OF WHAT WE JUST ADDED */
 122        *ob++ = UpperCase ? 'E' : 'e';
 123
 124        if(AllZeroes)   E = 0;
 125        else            E = decpt - 1;
 126
 127        if(E < 0)       { *ob++ = '-'; E = -E; }
 128        else            { *ob++ = '+'; }
 129
 130        sprintf(ob, "%.2d", E); /* Too much horsepower used here */
 131
 132        if(Width > strlen(obuf)) return Fill(obuf, Width, Minus, Zero);
 133        else                     return obuf;
 134}
 135
 136char    *
 137do_gfmt(d, obuf, Width, Precision, Alt, Plus, Minus, Zero, UpperCase)
 138char    *obuf;
 139double  d;
 140{
 141        char    *Ecvt = gcvt(d, Precision ? Precision : 1, obuf);
 142        int     len = strlen(obuf);
 143
 144         /* gcvt fails (maybe give a warning? For now return empty string): */
 145        if(!Ecvt) { *obuf = '\0'; return obuf; }
 146
 147        /* printf("Ecvt='%s'\n", Ecvt); */
 148        if(Plus && (Ecvt[0] != '-')) {
 149                memmove(obuf+1, obuf, len+1); /* "+1" to get '\0' at end */
 150                obuf[0] = '+';
 151                ++len;
 152        }
 153        if(Alt && !strchr(Ecvt, '.')) {
 154                int     LenUpTo_E = strcspn(obuf, "eE");
 155                int     E_etc_len = strlen(&obuf[LenUpTo_E]);
 156                        /* ABOVE: Will be 0 if there's no E/e because */
 157                        /* strcspn will return length of whole string */
 158
 159                if(E_etc_len)
 160                        memmove(obuf+LenUpTo_E+1, obuf+LenUpTo_E, E_etc_len);
 161                obuf[LenUpTo_E] = '.';
 162                obuf[LenUpTo_E + 1 + E_etc_len ] = '\0';
 163        }
 164        { char *E_loc;
 165          if(UpperCase && (E_loc = strchr(obuf, 'e'))) { *E_loc = 'E'; }
 166        }
 167        if(Width > len)
 168                return Fill(obuf, Width, Minus, Zero);
 169        else
 170                return obuf;
 171}
 172
 173char *
 174Fill(obuf, Width, LeftJustify, Zero)
 175char    *obuf;
 176{
 177        int     W = strlen(obuf);
 178        int     diff = Width - W;
 179         /* LeftJustify means there was a '-' flag, and in that case,   */
 180         /* printf man page (UTS4.4) says ignore '0'                    */
 181        char    FillChar = (Zero && !LeftJustify) ? '0' : ' ';
 182        int     i;
 183        int     LeftFill = ! LeftJustify;
 184
 185        if(Width <= W) return obuf;
 186
 187        if(LeftFill) {
 188                memmove(obuf+diff, obuf, W+1); /* "+1" to get '\0' at end */
 189                for(i=0 ; i < diff ; ++i) { obuf[i] = FillChar; }
 190        } else {
 191                for(i=W ; i < Width ; ++i)
 192                        obuf[i] = FillChar;
 193                obuf[Width] = '\0';
 194        }
 195        return obuf;
 196}
 197
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.