]>
git.ipfire.org Git - thirdparty/bash.git/blob - examples/loadables/printf.c
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #if !defined(BUILTIN) && !defined(SHELL)
36 static char copyright
[] =
37 "@(#) Copyright (c) 1989, 1993\n\
38 The Regents of the University of California. All rights reserved.\n";
43 static char sccsid
[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93";
46 #include <sys/types.h>
61 #define PF(f, func) { \
64 (void)printf(f, fieldwidth, precision, func); \
66 (void)printf(f, fieldwidth, func); \
68 (void)printf(f, precision, func); \
70 (void)printf(f, func); \
73 static int asciicode
__P((void));
74 static void escape
__P((char *));
75 static int getchr
__P((void));
76 static double getdouble
__P((void));
77 static int getint
__P((int *));
78 static int getlong
__P((long *));
79 static char *getstr
__P((void));
80 static char *mklong
__P((char *, int));
81 static void usage
__P((void));
85 int printf_builtin ();
86 static int printf_main ();
87 extern char *this_command_name
;
88 extern char *single_quote ();
89 extern char **make_builtin_argv ();
91 static char *printf_doc
[] = {
92 "printf formats and prints its arguments, after the first, under control",
93 "of the format. The format is a character string which contains three",
94 "types of objects: plain characters, which are simply copied to standard",
95 "output, character escape sequences which are converted and copied to the",
96 "standard output, and format specifications, each of which causes printing",
97 "of the next successive argument. In addition to the standard printf(1)",
98 "formats, %%b means to expand escapes in the corresponding argument, and",
99 "%%q means to quote the argument in a way that can be reused as shell input.",
103 struct builtin printf_struct
= {
108 "printf format [arguments]",
113 printf_builtin (list
)
120 v
= make_builtin_argv (list
, &c
);
121 r
= printf_main (c
, v
);
129 printf_main(argc
, argv
)
134 static char *skip1
, *skip2
;
135 int ch
, end
, fieldwidth
, precision
;
136 char convch
, nextch
, *format
, *fmt
, *start
;
138 while ((ch
= getopt(argc
, argv
, "")) != EOF
)
154 * Basic algorithm is to scan the format string for conversion
155 * specifications -- once one is found, find out if the field
156 * width or precision is a '*'; if it is, gather up value. Note,
157 * format strings are reused as necessary to use up the provided
158 * arguments, arguments of zero/null string are provided to use
159 * up the format string.
162 skip2
= "*0123456789";
164 escape(fmt
= format
= *argv
); /* backslash interpretation */
168 /* find next format specification */
169 next
: for (start
= fmt
;; ++fmt
) {
171 /* avoid infinite loop */
173 warnx("missing format character",
179 (void)printf("%s", start
);
190 (void)printf("%s", start
);
195 /* skip to field width */
196 for (; strchr(skip1
, *fmt
); ++fmt
);
198 if (getint(&fieldwidth
))
203 /* skip to possible '.', get following precision */
204 for (; strchr(skip2
, *fmt
); ++fmt
);
208 if (getint(&precision
))
213 /* skip to conversion char */
214 for (; strchr(skip2
, *fmt
); ++fmt
);
216 warnx("missing format character", NULL
, NULL
);
238 case 'b': { /* expand escapes in argument */
246 case 'q': { /* print with shell single quoting */
250 p2
= single_quote(p
);
255 case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
259 if ((f
= mklong(start
, convch
)) == NULL
)
266 case 'e': case 'E': case 'f': case 'g': case 'G': {
274 warnx("illegal format character", NULL
, NULL
);
287 static char copy
[64];
290 len
= strlen(str
) + 2;
291 memmove(copy
, str
, len
- 3);
294 copy
[len
- 1] = '\0';
302 register char *store
;
303 register int value
, c
;
305 for (store
= fmt
; c
= *fmt
; ++fmt
, ++store
) {
311 case '\0': /* EOS, user error */
315 case '\\': /* backslash */
316 case '\'': /* single quote */
319 case 'a': /* bell/alert */
322 case 'b': /* backspace */
331 case 'f': /* form-feed */
334 case 'n': /* newline */
337 case 'r': /* carriage-return */
340 case 't': /* horizontal tab */
343 case 'v': /* vertical tab */
347 case '0': case '1': case '2': case '3':
348 case '4': case '5': case '6': case '7':
349 for (c
= 3, value
= 0;
350 c
-- && *fmt
>= '0' && *fmt
<= '7'; ++fmt
) {
370 return ((int)**gargv
++);
381 static char *Number
= "+-.0123456789";
391 warnx("%s: %s", *gargv
, strerror(ERANGE
));
409 if (strchr(Number
, **gargv
)) {
411 val
= strtol(*gargv
, &ep
, 0);
413 warnx("%s: illegal number", *gargv
, NULL
);
417 if (val
== LONG_MAX
) {
418 warnx("%s: %s", *gargv
, strerror(ERANGE
));
421 if (val
== LONG_MIN
) {
422 warnx("%s: %s", *gargv
, strerror(ERANGE
));
430 *lp
= (long)asciicode();
439 if (strchr(Number
, **gargv
))
440 return (atof(*gargv
++));
441 return ((double)asciicode());
450 if (ch
== '\'' || ch
== '"')
459 (void)fprintf(stderr
, "usage: printf format [arg ...]\n");