home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / m4-1.4-src.tgz / tar.out / fsf / m4 / src / format.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  16KB  |  745 lines

  1. /* GNU m4 -- A simple macro processor
  2.    Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
  3.   
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.   
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.   
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /* printf like formatting for m4.  */
  20.  
  21. #include "m4.h"
  22.  
  23. #ifdef HAVE_EFGCVT
  24.  
  25. /* Various constants for floating point formatting.  */
  26. #define MAXFIELD    128    /* size of buffer for formatted text */
  27. /* The following two are hardware dependant.  */
  28. #define ECVTMAX        18    /* max number of significant digits for %e */
  29. #define FCVTMAX        (18+38+4) /* max number of significant digits for %f */
  30.  
  31. /* Externs used herein.  */
  32. #if HAVE_EFGCVT <= 1
  33. extern char *ecvt (), *fcvt (), *gcvt ();
  34. #endif
  35.  
  36. #ifndef STDC_HEADERS
  37. extern int atoi ();
  38. extern long atol ();
  39. extern double atof ();
  40. #endif /* STDC_HEADERS */
  41.  
  42. #define min(a, b)    ((a) < (b) ? (a) : (b))
  43.  
  44. static char const digits[] = "0123456789abcdef";
  45. static char const Digits[] = "0123456789ABCDEF";
  46.  
  47. /* STR has dimension MAXFIELD (?).  */
  48.  
  49. static char *
  50. ulong_to_str (register unsigned long val, char *str, int base,
  51.           const char *digits)
  52. {
  53.   register char *s = &str[MAXFIELD];
  54.  
  55.   *--s = '\0';
  56.   do
  57.     {
  58.       *--s = digits[val % base];
  59.       val /= base;
  60.     }
  61.   while (val > 0);
  62.  
  63.   return s;
  64. }
  65.  
  66. /*-----------------------------------------.
  67. | Clear trailing zeroes, return argument.  |
  68. `-----------------------------------------*/
  69.  
  70. static char *
  71. clr0 (char *s)
  72. {
  73.   register char *t;
  74.  
  75.   for (t = s + strlen (s); *--t == '0' && t > s;)
  76.     *t = '\0';
  77.   return s;
  78. }
  79.  
  80. #endif /* HAVE_EFGCVT */
  81.  
  82. /* Simple varargs substitute.  */
  83.  
  84. #define ARG_INT(argc, argv) \
  85.     ((argc == 0) ? 0 : \
  86.      (--argc, argv++, atoi (TOKEN_DATA_TEXT (argv[-1]))))
  87.  
  88. #define ARG_UINT(argc, argv) \
  89.     ((argc == 0) ? 0 : \
  90.      (--argc, argv++, (unsigned int) atoi (TOKEN_DATA_TEXT (argv[-1]))))
  91.  
  92. #define ARG_LONG(argc, argv) \
  93.     ((argc == 0) ? 0 : \
  94.      (--argc, argv++, atol (TOKEN_DATA_TEXT (argv[-1]))))
  95.  
  96. #define ARG_ULONG(argc, argv) \
  97.     ((argc == 0) ? 0 : \
  98.      (--argc, argv++, (unsigned long) atol (TOKEN_DATA_TEXT (argv[-1]))))
  99.  
  100. #define ARG_STR(argc, argv) \
  101.     ((argc == 0) ? "" : \
  102.      (--argc, argv++, TOKEN_DATA_TEXT (argv[-1])))
  103.  
  104. #define ARG_DOUBLE(argc, argv) \
  105.     ((argc == 0) ? 0 : \
  106.      (--argc, argv++, atof (TOKEN_DATA_TEXT (argv[-1]))))
  107.  
  108.  
  109. /*------------------------------------------------------------------------.
  110. | The main formatting function.  Output is placed on the obstack OBS, the |
  111. | first argument in ARGV is the formatting string, and the rest is      |
  112. | arguments for the string.                          |
  113. `------------------------------------------------------------------------*/
  114.  
  115. void
  116. format (struct obstack *obs, int argc, token_data **argv)
  117. {
  118. #ifdef HAVE_EFGCVT
  119.  
  120.   const char *fmt;        /* format control string */
  121.   int c;            /* a simple character */
  122.   char fc;            /* format code */
  123.  
  124.   /* Flags.  */
  125.   char flags;            /* 1 iff treating flags */
  126.   char ljust;            /* left justification */
  127.   char mandsign;        /* mandatory sign */
  128.   char noplus;            /* use space if no sign */
  129.   char alternate;        /* use alternate form */
  130.   char zeropad;            /* do zero padding */
  131.   char plus;            /* plus-sign, according to mandatory and noplus */
  132.  
  133.   /* Precision specifiers.  */
  134.   int width;            /* minimum field width */
  135.   int prec;            /* precision */
  136.   int maxch;            /* maximum no. of chars to print */
  137.   char lflag;            /* long flag */
  138.   char hflag;            /* short flag */
  139.  
  140.   /* Different parts of each specification.  */
  141.   char sign;            /* wanted sign, iff any */
  142.   int ppad;            /* pre-prefix zero padding */
  143.   const char *prefix;        /* value prefix */
  144.   int lpad;            /* zero padding on the left */
  145.   register char *s;        /* ptr to formatted text */
  146.   int rpad;            /* zero padding on the rigth*/
  147.   const char *suffix;        /* value suffix */
  148.  
  149.   /* Buffer and stuff.  */
  150.   char str[MAXFIELD];        /* buffer for formatted text */
  151.   int length;            /* length of str */
  152.   int padding;            /* padding at the left or rigth */
  153.   register int i;        /* an index */
  154.  
  155. /* Length of trailing string in str.  */
  156. #define LENGTH(s)    (&str[MAXFIELD-1] - (s))
  157. #define HAS_SIGN    (sign != '\0')
  158.  
  159.   fmt = ARG_STR (argc, argv);
  160.   for (;;)
  161.     {
  162.       while ((c = *fmt++) != '%')
  163.     {
  164.       if (c == 0)
  165.         return;
  166.       obstack_1grow (obs, c);
  167.     }
  168.       if (*fmt == '%')
  169.     {
  170.       obstack_1grow (obs, '%');
  171.       fmt++;
  172.       continue;
  173.     }
  174.  
  175.       /* Parse flags.  */
  176.       flags = 1;
  177.       ljust = mandsign = noplus = alternate = zeropad = 0;
  178.       do
  179.     {
  180.       switch (*fmt)
  181.         {
  182.         case '-':        /* left justification */
  183.           ljust = 1;
  184.           break;
  185.  
  186.         case '+':        /* mandatory sign */
  187.           mandsign = 1;
  188.           break;
  189.  
  190.         case ' ':        /* space instead of positive sign */
  191.           noplus = 1;
  192.           break;
  193.  
  194.         case '0':        /* zero padding */
  195.           zeropad = 1;
  196.           break;
  197.  
  198.         case '#':        /* alternate output */
  199.           alternate = 1;
  200.           break;
  201.  
  202.         default:
  203.           flags = 0;
  204.           break;
  205.         }
  206.     }
  207.       while (flags && fmt++);
  208.  
  209.       plus = '\0';        /* what to use as a plus ??? */
  210.       if (mandsign)
  211.     plus = '+';
  212.       else if (noplus)
  213.     plus = ' ';
  214.  
  215.       if (ljust)
  216.     zeropad = 0;
  217.  
  218.       /* Minimum field width.  */
  219.       width = -1;
  220.       if (*fmt == '*')
  221.     {
  222.       width = ARG_INT (argc, argv);
  223.       fmt++;
  224.     }
  225.       else if (isdigit (*fmt))
  226.     {
  227.       width = 0;
  228.       do
  229.         {
  230.           width = width * 10 + *fmt++ - '0';
  231.         }
  232.       while (isdigit (*fmt));
  233.     }
  234.  
  235.       /* Maximum precision.  */
  236.       prec = -1;
  237.       if (*fmt == '.')
  238.     {
  239.       if (*(++fmt) == '*')
  240.         {
  241.           prec = ARG_INT (argc, argv);
  242.           ++fmt;
  243.         }
  244.       else if (isdigit (*fmt))
  245.         {
  246.           prec = 0;
  247.           do
  248.         {
  249.           prec = prec * 10 + *fmt++ - '0';
  250.         }
  251.           while (isdigit (*fmt))
  252.         ;
  253.         }
  254.     }
  255.  
  256.       /* Length modifiers.  */
  257.       lflag = (*fmt == 'l');
  258.       hflag = (*fmt == 'h');
  259.       if (lflag || hflag)
  260.     fmt++;
  261.  
  262.       sign = '\0';
  263.       ppad = lpad = rpad = 0;
  264.       maxch = -1;
  265.       prefix = suffix = "";
  266.  
  267.       switch (fc = *fmt++)
  268.     {
  269.  
  270.     case '\0':
  271.       return;
  272.  
  273.     case 'c':
  274.       c = ARG_INT (argc, argv);
  275.       str[0] = (unsigned char) c;
  276.       str[1] = '\0';
  277.       s = str;
  278.       break;
  279.  
  280.     case 's':
  281.       s = ARG_STR (argc, argv);
  282.       maxch = prec;
  283.       break;
  284.  
  285.     case 'd':
  286.     case 'i':
  287.       if (lflag)
  288.         {
  289.           long val = ARG_LONG (argc, argv);
  290.           if (val < 0)
  291.         {
  292.           val = -val;    /* does not work for MINLONG */
  293.           sign = '-';
  294.         }
  295.           else
  296.         sign = plus;
  297.           s = ulong_to_str ((unsigned long) val, str, 10, digits);
  298.         }
  299.       else
  300.         {
  301.           int val = ARG_INT (argc, argv);
  302.           if (hflag)
  303.         val = (short) val;
  304.           if (val < 0)
  305.         {
  306.           val = -val;    /* does not work for MININT */
  307.           sign = '-';
  308.         }
  309.           else
  310.         sign = plus;
  311.           s = ulong_to_str ((unsigned long) val, str, 10, digits);
  312.         }
  313.       if (zeropad)
  314.         lpad = width - LENGTH (s) - HAS_SIGN;
  315.       break;
  316.  
  317.     case 'o':
  318.       if (lflag)
  319.         {
  320.           unsigned long val = ARG_ULONG (argc, argv);
  321.           s = ulong_to_str ((unsigned long) val, str, 8, digits);
  322.         }
  323.       else
  324.         {
  325.           unsigned int val = ARG_UINT (argc, argv);
  326.           if (hflag)
  327.         val = (unsigned short) val;
  328.           s = ulong_to_str ((unsigned long) val, str, 8, digits);
  329.         }
  330.       if (alternate)
  331.         prefix = "0";
  332.       if (zeropad)
  333.         lpad = width - LENGTH (s) - alternate;
  334.       break;
  335.  
  336.     case 'x':
  337.     case 'X':
  338.       if (lflag)
  339.         {
  340.           unsigned long val = ARG_ULONG (argc, argv);
  341.           s = ulong_to_str ((unsigned long) val, str, 16,
  342.                    (fc == 'x') ? digits : Digits);
  343.         }
  344.       else
  345.         {
  346.           unsigned int val = ARG_UINT (argc, argv);
  347.           if (hflag)
  348.         val = (unsigned short) val;
  349.           s = ulong_to_str ((unsigned long) val, str, 16,
  350.                    (fc == 'x') ? digits : Digits);
  351.         }
  352.       if (alternate)
  353.         prefix = (fc == 'X') ? "0X" : "0x";
  354.       if (zeropad)
  355.         lpad = width - LENGTH (s) - 2*alternate;
  356.       break;
  357.  
  358.     case 'u':
  359.       if (lflag)
  360.         {
  361.           unsigned long val = ARG_ULONG (argc, argv);
  362.           s = ulong_to_str ((unsigned long) val, str, 10, digits);
  363.         }
  364.       else
  365.         {
  366.           unsigned int val = ARG_UINT (argc, argv);
  367.           if (hflag)
  368.         val = (unsigned short) val;
  369.           s = ulong_to_str ((unsigned long) val, str, 10, digits);
  370.         }
  371.       if (zeropad)
  372.         lpad = width - LENGTH (s);
  373.       break;
  374.  
  375.     case 'e':
  376.     case 'E':
  377.       {
  378.         char *t;
  379.         int sgn, decpt, exp, n;
  380.         double val = ARG_DOUBLE (argc, argv);
  381.  
  382.         if (prec < 0)
  383.           prec = 6;
  384.         t = clr0 (ecvt (val, min (prec + 1, ECVTMAX), &decpt, &sgn));
  385.         sign = sgn ? '-' : plus;
  386.  
  387.         n = prec;
  388.         s = str;
  389.         exp = (t[0] == '0' && t[1] == '\0') ? 0 : decpt - 1;
  390.  
  391.         *s++ = *t++;
  392.         if (n > 0 || alternate)
  393.           *s++ = '.';
  394.         while (*t != '\0' && --n >= 0)
  395.           *s++ = *t++;
  396.         *s = '\0';
  397.         rpad = n;
  398.  
  399.         sgn = 0;
  400.         if (exp < 0)
  401.           {
  402.         exp = -exp;
  403.         sgn = 1;
  404.           }
  405.         t = ulong_to_str ((unsigned long) exp, str, 10, digits);
  406.         if (exp < 10)
  407.           *--t = '0';    /* always at least two digits */
  408.         *--t = sgn ? '-' : '+';
  409.         *--t = fc;
  410.  
  411.         if (zeropad)
  412.           {
  413.         lpad = width - HAS_SIGN - (s - str) - LENGTH (t);
  414.         if (rpad > 0)
  415.           lpad -= rpad;
  416.           }
  417.  
  418.         suffix = t;
  419.         s = str;
  420.       }
  421.       break;
  422.  
  423.     case 'f':
  424.       {
  425.         const char *t;
  426.         int sgn, decpt, n;
  427.         double val = ARG_DOUBLE (argc, argv);
  428.  
  429.         if (prec < 0)
  430.           prec = 6;
  431.  
  432.         /* FIXME: For the following line, Dave Anglin reports
  433.            ``warning: passing arg 1 of `clr0' discards `const' from
  434.            pointer target type''.  I suspect fcvt might be declared
  435.            as returning const on some systems.  Pouah!  I should
  436.            revise this whole module, one of these days...  */
  437.  
  438.         t = clr0 (fcvt (val, min (prec, FCVTMAX), &decpt, &sgn));
  439.  
  440.         sign = sgn ? '-' : plus;
  441.  
  442.         n = prec;
  443.         s = str;
  444.  
  445.         if (decpt <= 0)
  446.           {
  447.         prefix = (n > 0 || alternate) ? "0." : "0";
  448.         lpad = min (-decpt, prec);
  449.         n -= lpad;
  450.           }
  451.         else
  452.           {
  453.         while (--decpt >= 0)
  454.           *s++ = *t++;
  455.         if (n > 0 || alternate)
  456.           *s++ = '.';
  457.           }
  458.         while (*t && --n >= 0)
  459.           *s++ = *t++;
  460.  
  461.         *s = '\0';
  462.         rpad = n;
  463.  
  464.         if (zeropad)
  465.           ppad = width - HAS_SIGN - (prefix[1] ? 2 : 1) - lpad -
  466.         (s - str) - rpad;
  467.  
  468.         s = str;
  469.       }
  470.       break;
  471.  
  472.     default:
  473.       continue;
  474.     }
  475.  
  476.       if (lpad < 0)
  477.     lpad = 0;
  478.       if (rpad < 0)
  479.     rpad = 0;
  480.       if (width < 0)
  481.     width = 0;
  482.  
  483.       i = strlen (s);
  484.       if (maxch <= 0 || maxch > i)
  485.     maxch = i;
  486.  
  487.       length = (HAS_SIGN + ppad + strlen (prefix) + lpad + maxch
  488.         + rpad + strlen (suffix));
  489.       padding = 0;
  490.       if (width != 0)
  491.     {
  492.       padding = width - length;
  493.     }
  494.  
  495.       if (ljust == 0)        /* left padding */
  496.     for (i = padding; --i >= 0;)
  497.       obstack_1grow (obs, ' ');
  498.       if (HAS_SIGN)        /* sign */
  499.     obstack_1grow (obs, sign);
  500.       for (i = ppad; --i >= 0;)    /* pre-prefix zero padding */
  501.     obstack_1grow (obs, '0');
  502.       for (; *prefix; ++prefix)    /* prefix */
  503.     obstack_1grow (obs, *prefix);
  504.       for (i = lpad; --i >= 0;)    /* left zero padding */
  505.     obstack_1grow (obs, '0');
  506.       for (i = maxch; --i >= 0; ++s) /* actual text */
  507.     obstack_1grow (obs, *s);
  508.       for (i = rpad; --i >= 0;)    /* right zero padding */
  509.     obstack_1grow (obs, '0');
  510.       for (; *suffix; ++suffix)    /* suffix */
  511.     obstack_1grow (obs, *suffix);
  512.       if (ljust != 0)        /* right padding */
  513.     for (i = padding; --i >= 0;)
  514.       obstack_1grow (obs, ' ');
  515.     }
  516.  
  517. #else /* not HAVE_EFGCVT */
  518.  
  519.   char *fmt;            /* format control string */
  520.   const char *fstart;        /* beginning of current format spec */
  521.   int c;            /* a simple character */
  522.  
  523.   /* Flags.  */
  524.   char flags;            /* 1 iff treating flags */
  525.  
  526.   /* Precision specifiers.  */
  527.   int width;            /* minimum field width */
  528.   int prec;            /* precision */
  529.   char lflag;            /* long flag */
  530.   char hflag;            /* short flag */
  531.  
  532.   /* Buffer and stuff.  */
  533.   char str[256];        /* buffer for formatted text */
  534.   enum {INT, UINT, LONG, ULONG, DOUBLE, STR} datatype;
  535.  
  536.   fmt = ARG_STR (argc, argv);
  537.   for (;;)
  538.     {
  539.       while ((c = *fmt++) != '%')
  540.     {
  541.       if (c == 0)
  542.         return;
  543.       obstack_1grow (obs, c);
  544.     }
  545.  
  546.       fstart = fmt - 1;
  547.  
  548.       if (*fmt == '%')
  549.     {
  550.       obstack_1grow (obs, '%');
  551.       fmt++;
  552.       continue;
  553.     }
  554.  
  555.       /* Parse flags.  */
  556.       flags = 1;
  557.       do
  558.     {
  559.       switch (*fmt)
  560.         {
  561.         case '-':        /* left justification */
  562.         case '+':        /* mandatory sign */
  563.         case ' ':        /* space instead of positive sign */
  564.         case '0':        /* zero padding */
  565.         case '#':        /* alternate output */
  566.           break;
  567.  
  568.         default:
  569.           flags = 0;
  570.           break;
  571.         }
  572.     }
  573.       while (flags && fmt++);
  574.  
  575.       /* Minimum field width.  */
  576.       width = -1;
  577.       if (*fmt == '*')
  578.     {
  579.       width = ARG_INT (argc, argv);
  580.       fmt++;
  581.     }
  582.       else if (isdigit (*fmt))
  583.     {
  584.       do
  585.         {
  586.           fmt++;
  587.         }
  588.       while (isdigit (*fmt));
  589.     }
  590.  
  591.       /* Maximum precision.  */
  592.       prec = -1;
  593.       if (*fmt == '.')
  594.     {
  595.       if (*(++fmt) == '*')
  596.         {
  597.           prec = ARG_INT (argc, argv);
  598.           ++fmt;
  599.         }
  600.       else if (isdigit (*fmt))
  601.         {
  602.           do
  603.         {
  604.           fmt++;
  605.         }
  606.           while (isdigit (*fmt));
  607.         }
  608.     }
  609.  
  610.       /* Length modifiers.  */
  611.       lflag = (*fmt == 'l');
  612.       hflag = (*fmt == 'h');
  613.       if (lflag || hflag)
  614.     fmt++;
  615.  
  616.       switch (*fmt++)
  617.     {
  618.  
  619.     case '\0':
  620.       return;
  621.  
  622.     case 'c':
  623.       datatype = INT;
  624.       break;
  625.  
  626.     case 's':
  627.       datatype = STR;
  628.       break;
  629.  
  630.     case 'd':
  631.     case 'i':
  632.       if (lflag)
  633.         {
  634.           datatype = LONG;
  635.         }
  636.       else
  637.         {
  638.           datatype = INT;
  639.         }
  640.       break;
  641.  
  642.     case 'o':
  643.     case 'x':
  644.     case 'X':
  645.     case 'u':
  646.       if (lflag)
  647.         {
  648.           datatype = ULONG;
  649.         }
  650.       else
  651.         {
  652.           datatype = UINT;
  653.         }
  654.       break;
  655.  
  656.     case 'e':
  657.     case 'E':
  658.     case 'f':
  659.       datatype = DOUBLE;
  660.       break;
  661.  
  662.     default:
  663.       continue;
  664.     }
  665.  
  666.       c = *fmt;
  667.       *fmt = '\0';
  668.  
  669.       switch(datatype) 
  670.     {
  671.     case INT:
  672.       if (width != -1 && prec != -1)
  673.         sprintf (str, fstart, width, prec, ARG_INT(argc, argv));
  674.       else if (width != -1)
  675.         sprintf (str, fstart, width, ARG_INT(argc, argv));
  676.       else if (prec != -1)
  677.         sprintf (str, fstart, prec, ARG_INT(argc, argv));
  678.       else
  679.         sprintf (str, fstart, ARG_INT(argc, argv));
  680.       break;
  681.  
  682.     case UINT:
  683.       if (width != -1 && prec != -1)
  684.         sprintf (str, fstart, width, prec, ARG_UINT(argc, argv));
  685.       else if (width != -1)
  686.         sprintf (str, fstart, width, ARG_UINT(argc, argv));
  687.       else if (prec != -1)
  688.         sprintf (str, fstart, prec, ARG_UINT(argc, argv));
  689.       else
  690.         sprintf (str, fstart, ARG_UINT(argc, argv));
  691.       break;
  692.  
  693.     case LONG:
  694.       if (width != -1 && prec != -1)
  695.         sprintf (str, fstart, width, prec, ARG_LONG(argc, argv));
  696.       else if (width != -1)
  697.         sprintf (str, fstart, width, ARG_LONG(argc, argv));
  698.       else if (prec != -1)
  699.         sprintf (str, fstart, prec, ARG_LONG(argc, argv));
  700.       else
  701.         sprintf (str, fstart, ARG_LONG(argc, argv));
  702.       break;
  703.  
  704.     case ULONG:
  705.       if (width != -1 && prec != -1)
  706.         sprintf (str, fstart, width, prec, ARG_ULONG(argc, argv));
  707.       else if (width != -1)
  708.         sprintf (str, fstart, width, ARG_ULONG(argc, argv));
  709.       else if (prec != -1)
  710.         sprintf (str, fstart, prec, ARG_ULONG(argc, argv));
  711.       else
  712.         sprintf (str, fstart, ARG_ULONG(argc, argv));
  713.       break;
  714.  
  715.     case DOUBLE:
  716.       if (width != -1 && prec != -1)
  717.         sprintf (str, fstart, width, prec, ARG_DOUBLE(argc, argv));
  718.       else if (width != -1)
  719.         sprintf (str, fstart, width, ARG_DOUBLE(argc, argv));
  720.       else if (prec != -1)
  721.         sprintf (str, fstart, prec, ARG_DOUBLE(argc, argv));
  722.       else
  723.         sprintf (str, fstart, ARG_DOUBLE(argc, argv));
  724.       break;
  725.  
  726.     case STR:
  727.       if (width != -1 && prec != -1)
  728.         sprintf (str, fstart, width, prec, ARG_STR(argc, argv));
  729.       else if (width != -1)
  730.         sprintf (str, fstart, width, ARG_STR(argc, argv));
  731.       else if (prec != -1)
  732.         sprintf (str, fstart, prec, ARG_STR(argc, argv));
  733.       else
  734.         sprintf (str, fstart, ARG_STR(argc, argv));
  735.       break;
  736.     }
  737.  
  738.       *fmt = c;
  739.  
  740.       obstack_grow (obs, str, strlen (str));
  741.     }
  742.  
  743. #endif /* not HAVE_EFGCVT */
  744. }
  745.