* src/Makefile.am (m4_LDADD): Add any gnulib dependent libraries.
[m4/ericb.git] / src / format.c
blobb3138c7c53bb17a16a6186a845b3cb0993607884
1 /* GNU m4 -- A simple macro processor
3 Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006
4 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA
22 /* printf like formatting for m4. */
24 #include "m4.h"
25 #include "xvasprintf.h"
27 /* Simple varargs substitute. */
29 #define ARG_INT(argc, argv) \
30 ((argc == 0) ? 0 : \
31 (--argc, argv++, atoi (TOKEN_DATA_TEXT (argv[-1]))))
33 #define ARG_UINT(argc, argv) \
34 ((argc == 0) ? 0 : \
35 (--argc, argv++, (unsigned int) atoi (TOKEN_DATA_TEXT (argv[-1]))))
37 #define ARG_LONG(argc, argv) \
38 ((argc == 0) ? 0 : \
39 (--argc, argv++, atol (TOKEN_DATA_TEXT (argv[-1]))))
41 #define ARG_ULONG(argc, argv) \
42 ((argc == 0) ? 0 : \
43 (--argc, argv++, (unsigned long) atol (TOKEN_DATA_TEXT (argv[-1]))))
45 #define ARG_STR(argc, argv) \
46 ((argc == 0) ? "" : \
47 (--argc, argv++, TOKEN_DATA_TEXT (argv[-1])))
49 #define ARG_DOUBLE(argc, argv) \
50 ((argc == 0) ? 0 : \
51 (--argc, argv++, atof (TOKEN_DATA_TEXT (argv[-1]))))
54 /*------------------------------------------------------------------------.
55 | The main formatting function. Output is placed on the obstack OBS, the |
56 | first argument in ARGV is the formatting string, and the rest is |
57 | arguments for the string. |
58 `------------------------------------------------------------------------*/
60 void
61 format (struct obstack *obs, int argc, token_data **argv)
63 char *fmt; /* format control string */
64 const char *fstart; /* beginning of current format spec */
65 int c; /* a simple character */
67 /* Flags. */
68 char flags; /* 1 iff treating flags */
70 /* Precision specifiers. */
71 int width; /* minimum field width */
72 int prec; /* precision */
73 char lflag; /* long flag */
74 char hflag; /* short flag */
76 /* Buffer and stuff. */
77 char *str; /* malloc'd buffer of formatted text */
78 enum {INT, UINT, LONG, ULONG, DOUBLE, STR} datatype;
80 fmt = ARG_STR (argc, argv);
81 for (;;)
83 while ((c = *fmt++) != '%')
85 if (c == 0)
86 return;
87 obstack_1grow (obs, c);
90 fstart = fmt - 1;
92 if (*fmt == '%')
94 obstack_1grow (obs, '%');
95 fmt++;
96 continue;
99 /* Parse flags. */
100 flags = 1;
103 switch (*fmt)
105 case '-': /* left justification */
106 case '+': /* mandatory sign */
107 case ' ': /* space instead of positive sign */
108 case '0': /* zero padding */
109 case '#': /* alternate output */
110 break;
112 default:
113 flags = 0;
114 break;
117 while (flags && fmt++);
119 /* Minimum field width. */
120 width = -1;
121 if (*fmt == '*')
123 width = ARG_INT (argc, argv);
124 fmt++;
126 else if (isdigit (to_uchar (*fmt)))
130 fmt++;
132 while (isdigit (to_uchar (*fmt)));
135 /* Maximum precision. */
136 prec = -1;
137 if (*fmt == '.')
139 if (*(++fmt) == '*')
141 prec = ARG_INT (argc, argv);
142 ++fmt;
144 else if (isdigit (to_uchar (*fmt)))
148 fmt++;
150 while (isdigit (to_uchar (*fmt)));
154 /* Length modifiers. */
155 lflag = (*fmt == 'l');
156 hflag = (*fmt == 'h');
157 if (lflag || hflag)
158 fmt++;
160 switch (*fmt++)
163 case '\0':
164 return;
166 case 'c':
167 datatype = INT;
168 break;
170 case 's':
171 datatype = STR;
172 break;
174 case 'd':
175 case 'i':
176 if (lflag)
178 datatype = LONG;
180 else
182 datatype = INT;
184 break;
186 case 'o':
187 case 'x':
188 case 'X':
189 case 'u':
190 if (lflag)
192 datatype = ULONG;
194 else
196 datatype = UINT;
198 break;
200 case 'e':
201 case 'E':
202 case 'f':
203 case 'F':
204 case 'g':
205 case 'G':
206 datatype = DOUBLE;
207 break;
209 default:
210 continue;
213 c = *fmt;
214 *fmt = '\0';
216 switch(datatype)
218 case INT:
219 if (width != -1 && prec != -1)
220 str = xasprintf (fstart, width, prec, ARG_INT(argc, argv));
221 else if (width != -1)
222 str = xasprintf (fstart, width, ARG_INT(argc, argv));
223 else if (prec != -1)
224 str = xasprintf (fstart, prec, ARG_INT(argc, argv));
225 else
226 str = xasprintf (fstart, ARG_INT(argc, argv));
227 break;
229 case UINT:
230 if (width != -1 && prec != -1)
231 str = xasprintf (fstart, width, prec, ARG_UINT(argc, argv));
232 else if (width != -1)
233 str = xasprintf (fstart, width, ARG_UINT(argc, argv));
234 else if (prec != -1)
235 str = xasprintf (fstart, prec, ARG_UINT(argc, argv));
236 else
237 str = xasprintf (fstart, ARG_UINT(argc, argv));
238 break;
240 case LONG:
241 if (width != -1 && prec != -1)
242 str = xasprintf (fstart, width, prec, ARG_LONG(argc, argv));
243 else if (width != -1)
244 str = xasprintf (fstart, width, ARG_LONG(argc, argv));
245 else if (prec != -1)
246 str = xasprintf (fstart, prec, ARG_LONG(argc, argv));
247 else
248 str = xasprintf (fstart, ARG_LONG(argc, argv));
249 break;
251 case ULONG:
252 if (width != -1 && prec != -1)
253 str = xasprintf (fstart, width, prec, ARG_ULONG(argc, argv));
254 else if (width != -1)
255 str = xasprintf (fstart, width, ARG_ULONG(argc, argv));
256 else if (prec != -1)
257 str = xasprintf (fstart, prec, ARG_ULONG(argc, argv));
258 else
259 str = xasprintf (fstart, ARG_ULONG(argc, argv));
260 break;
262 case DOUBLE:
263 if (width != -1 && prec != -1)
264 str = xasprintf (fstart, width, prec, ARG_DOUBLE(argc, argv));
265 else if (width != -1)
266 str = xasprintf (fstart, width, ARG_DOUBLE(argc, argv));
267 else if (prec != -1)
268 str = xasprintf (fstart, prec, ARG_DOUBLE(argc, argv));
269 else
270 str = xasprintf (fstart, ARG_DOUBLE(argc, argv));
271 break;
273 case STR:
274 if (width != -1 && prec != -1)
275 str = xasprintf (fstart, width, prec, ARG_STR(argc, argv));
276 else if (width != -1)
277 str = xasprintf (fstart, width, ARG_STR(argc, argv));
278 else if (prec != -1)
279 str = xasprintf (fstart, prec, ARG_STR(argc, argv));
280 else
281 str = xasprintf (fstart, ARG_STR(argc, argv));
282 break;
284 default:
285 abort();
288 *fmt = c;
290 /* NULL was returned on failure, such as invalid format string. For
291 now, just silently ignore that bad specifier. */
292 if (str == NULL)
293 continue;
295 obstack_grow (obs, str, strlen (str));
296 free (str);