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
22 /* printf like formatting for m4. */
25 #include "xvasprintf.h"
27 /* Simple varargs substitute. */
29 #define ARG_INT(argc, argv) \
31 (--argc, argv++, atoi (TOKEN_DATA_TEXT (argv[-1]))))
33 #define ARG_UINT(argc, argv) \
35 (--argc, argv++, (unsigned int) atoi (TOKEN_DATA_TEXT (argv[-1]))))
37 #define ARG_LONG(argc, argv) \
39 (--argc, argv++, atol (TOKEN_DATA_TEXT (argv[-1]))))
41 #define ARG_ULONG(argc, argv) \
43 (--argc, argv++, (unsigned long) atol (TOKEN_DATA_TEXT (argv[-1]))))
45 #define ARG_STR(argc, argv) \
47 (--argc, argv++, TOKEN_DATA_TEXT (argv[-1])))
49 #define ARG_DOUBLE(argc, argv) \
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 `------------------------------------------------------------------------*/
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 */
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
);
83 while ((c
= *fmt
++) != '%')
87 obstack_1grow (obs
, c
);
94 obstack_1grow (obs
, '%');
105 case '-': /* left justification */
106 case '+': /* mandatory sign */
107 case ' ': /* space instead of positive sign */
108 case '0': /* zero padding */
109 case '#': /* alternate output */
117 while (flags
&& fmt
++);
119 /* Minimum field width. */
123 width
= ARG_INT (argc
, argv
);
126 else if (isdigit (to_uchar (*fmt
)))
132 while (isdigit (to_uchar (*fmt
)));
135 /* Maximum precision. */
141 prec
= ARG_INT (argc
, argv
);
144 else if (isdigit (to_uchar (*fmt
)))
150 while (isdigit (to_uchar (*fmt
)));
154 /* Length modifiers. */
155 lflag
= (*fmt
== 'l');
156 hflag
= (*fmt
== 'h');
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
));
224 str
= xasprintf (fstart
, prec
, ARG_INT(argc
, argv
));
226 str
= xasprintf (fstart
, ARG_INT(argc
, argv
));
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
));
235 str
= xasprintf (fstart
, prec
, ARG_UINT(argc
, argv
));
237 str
= xasprintf (fstart
, ARG_UINT(argc
, argv
));
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
));
246 str
= xasprintf (fstart
, prec
, ARG_LONG(argc
, argv
));
248 str
= xasprintf (fstart
, ARG_LONG(argc
, argv
));
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
));
257 str
= xasprintf (fstart
, prec
, ARG_ULONG(argc
, argv
));
259 str
= xasprintf (fstart
, ARG_ULONG(argc
, argv
));
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
));
268 str
= xasprintf (fstart
, prec
, ARG_DOUBLE(argc
, argv
));
270 str
= xasprintf (fstart
, ARG_DOUBLE(argc
, argv
));
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
));
279 str
= xasprintf (fstart
, prec
, ARG_STR(argc
, argv
));
281 str
= xasprintf (fstart
, ARG_STR(argc
, argv
));
290 /* NULL was returned on failure, such as invalid format string. For
291 now, just silently ignore that bad specifier. */
295 obstack_grow (obs
, str
, strlen (str
));