home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 4 / FreshFish_May-June1994.bin / bbs / gnu / m4-1.1-src.lha / src / amiga / m4-1.1 / format.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-02  |  13.9 KB  |  680 lines

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