source: trunk/essentials/app-shells/bash/builtins/printf.def@ 3951

Last change on this file since 3951 was 3228, checked in by bird, 19 years ago

bash 3.1

File size: 20.1 KB
Line 
1This file is printf.def, from which is created printf.c.
2It implements the builtin "printf" in Bash.
3
4Copyright (C) 1997-2005 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
20Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
21
22$PRODUCES printf.c
23
24$BUILTIN printf
25$FUNCTION printf_builtin
26$SHORT_DOC printf [-v var] format [arguments]
27printf formats and prints ARGUMENTS under control of the FORMAT. FORMAT
28is a character string which contains three types of objects: plain
29characters, which are simply copied to standard output, character escape
30sequences which are converted and copied to the standard output, and
31format specifications, each of which causes printing of the next successive
32argument. In addition to the standard printf(1) formats, %b means to
33expand backslash escape sequences in the corresponding argument, and %q
34means to quote the argument in a way that can be reused as shell input.
35If the -v option is supplied, the output is placed into the value of the
36shell variable VAR rather than being sent to the standard output.
37$END
38
39#include <config.h>
40
41#include "../bashtypes.h"
42
43#include <errno.h>
44#if defined (HAVE_LIMITS_H)
45# include <limits.h>
46#else
47 /* Assume 32-bit ints. */
48# define INT_MAX 2147483647
49# define INT_MIN (-2147483647-1)
50#endif
51
52#include <stdio.h>
53#include <chartypes.h>
54
55#ifdef HAVE_INTTYPES_H
56# include <inttypes.h>
57#endif
58
59#include "../bashansi.h"
60#include "../bashintl.h"
61
62#include "../shell.h"
63#include "stdc.h"
64#include "bashgetopt.h"
65#include "common.h"
66
67#if !defined (PRIdMAX)
68# if HAVE_LONG_LONG
69# define PRIdMAX "lld"
70# else
71# define PRIdMAX "ld"
72# endif
73#endif
74
75#if !defined (errno)
76extern int errno;
77#endif
78
79#define PC(c) \
80 do { \
81 char b[2]; \
82 tw++; \
83 b[0] = c; b[1] = '\0'; \
84 if (vflag) \
85 vbadd (b, 1); \
86 else \
87 putchar (c); \
88 } while (0)
89
90#define PF(f, func) \
91 do { \
92 char *b = 0; \
93 int nw; \
94 if (have_fieldwidth && have_precision) \
95 nw = asprintf(&b, f, fieldwidth, precision, func); \
96 else if (have_fieldwidth) \
97 nw = asprintf(&b, f, fieldwidth, func); \
98 else if (have_precision) \
99 nw = asprintf(&b, f, precision, func); \
100 else \
101 nw = asprintf(&b, f, func); \
102 tw += nw; \
103 if (b) \
104 { \
105 if (vflag) \
106 (void)vbadd (b, nw); \
107 else \
108 (void)fputs (b, stdout); \
109 free (b); \
110 } \
111 } while (0)
112
113/* We free the buffer used by mklong() if it's `too big'. */
114#define PRETURN(value) \
115 do \
116 { \
117 if (vflag) \
118 { \
119 bind_variable (vname, vbuf, 0); \
120 stupidly_hack_special_variables (vname); \
121 } \
122 if (conv_bufsize > 4096 ) \
123 { \
124 free (conv_buf); \
125 conv_bufsize = 0; \
126 conv_buf = 0; \
127 } \
128 if (vbsize > 4096) \
129 { \
130 free (vbuf); \
131 vbsize = 0; \
132 vbuf = 0; \
133 } \
134 fflush (stdout); \
135 return (value); \
136 } \
137 while (0)
138
139#define SKIP1 "#'-+ 0"
140#define LENMODS "hjlLtz"
141
142static void printf_erange __P((char *));
143static int printstr __P((char *, char *, int, int, int));
144static int tescape __P((char *, char *, int *));
145static char *bexpand __P((char *, int, int *, int *));
146static char *vbadd __P((char *, int));
147static char *mklong __P((char *, char *, size_t));
148static int getchr __P((void));
149static char *getstr __P((void));
150static int getint __P((void));
151static intmax_t getintmax __P((void));
152static uintmax_t getuintmax __P((void));
153
154#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
155typedef long double floatmax_t;
156# define FLOATMAX_CONV "L"
157# define strtofltmax strtold
158#else
159typedef double floatmax_t;
160# define FLOATMAX_CONV ""
161# define strtofltmax strtod
162#endif
163static floatmax_t getfloatmax __P((void));
164
165static int asciicode __P((void));
166
167static WORD_LIST *garglist;
168static int retval;
169static int conversion_error;
170
171/* printf -v var support */
172static int vflag = 0;
173static char *vbuf, *vname;
174static size_t vbsize;
175static int vblen;
176
177static intmax_t tw;
178
179static char *conv_buf;
180static size_t conv_bufsize;
181
182int
183printf_builtin (list)
184 WORD_LIST *list;
185{
186 int ch, fieldwidth, precision;
187 int have_fieldwidth, have_precision;
188 char convch, thisch, nextch, *format, *modstart, *fmt, *start;
189
190 conversion_error = 0;
191 retval = EXECUTION_SUCCESS;
192
193 vflag = 0;
194
195 reset_internal_getopt ();
196 while ((ch = internal_getopt (list, "v:")) != -1)
197 {
198 switch (ch)
199 {
200 case 'v':
201 if (legal_identifier (vname = list_optarg))
202 {
203 vflag = 1;
204 vblen = 0;
205 }
206 else
207 {
208 sh_invalidid (vname);
209 return (EX_USAGE);
210 }
211 break;
212 default:
213 builtin_usage ();
214 return (EX_USAGE);
215 }
216 }
217 list = loptend; /* skip over possible `--' */
218
219 if (list == 0)
220 {
221 builtin_usage ();
222 return (EX_USAGE);
223 }
224
225 if (list->word->word == 0 || list->word->word[0] == '\0')
226 return (EXECUTION_SUCCESS);
227
228 format = list->word->word;
229 tw = 0;
230
231 garglist = list->next;
232
233 /* If the format string is empty after preprocessing, return immediately. */
234 if (format == 0 || *format == 0)
235 return (EXECUTION_SUCCESS);
236
237 /* Basic algorithm is to scan the format string for conversion
238 specifications -- once one is found, find out if the field
239 width or precision is a '*'; if it is, gather up value. Note,
240 format strings are reused as necessary to use up the provided
241 arguments, arguments of zero/null string are provided to use
242 up the format string. */
243 do
244 {
245 tw = 0;
246 /* find next format specification */
247 for (fmt = format; *fmt; fmt++)
248 {
249 precision = fieldwidth = 0;
250 have_fieldwidth = have_precision = 0;
251
252 if (*fmt == '\\')
253 {
254 fmt++;
255 /* A NULL third argument to tescape means to bypass the
256 special processing for arguments to %b. */
257 fmt += tescape (fmt, &nextch, (int *)NULL);
258 PC (nextch);
259 fmt--; /* for loop will increment it for us again */
260 continue;
261 }
262
263 if (*fmt != '%')
264 {
265 PC (*fmt);
266 continue;
267 }
268
269 /* ASSERT(*fmt == '%') */
270 start = fmt++;
271
272 if (*fmt == '%') /* %% prints a % */
273 {
274 PC ('%');
275 continue;
276 }
277
278 /* found format specification, skip to field width */
279 for (; *fmt && strchr(SKIP1, *fmt); ++fmt)