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 #include <sys/types.h>
44 #include "bashgetopt.h"
50 #define PF(f, func) { \
53 (void)fprintf(ofp, f, fieldwidth, precision, func); \
55 (void)fprintf(ofp, f, fieldwidth, func); \
57 (void)fprintf(ofp, f, precision, func); \
59 (void)fprintf(ofp, f, func); \
62 static int asciicode __P((void));
63 static void escape __P((char *));
64 static int getchr __P((void));
65 static double getdouble __P((void));
66 static int getint __P((int *));
67 static int getlong __P((long *));
68 static char *getstr __P((void));
69 static char *mklong __P((char *, int));
70 static void usage __P((void));
75 static int printf_main ();
76 static int printargs ();
80 extern char *ansicstr ();
81 extern char *single_quote ();
82 extern char **make_builtin_argv ();
84 extern char *this_command_name;
88 static char *print_doc[] = {
89 "Output the arguments. The -f option means to use the argument as a",
90 "format string as would be supplied to printf(1). The rest of the",
91 "options are as in ksh.",
95 struct builtin print_struct = {
100 "print [-Rnprs] [-u unit] [-f format] [arguments]",
105 #define ISOPTION(s, c) (s[0] == '-' && s[2] == '\0' && s[1] == c)
112 int c, r, nflag, raw, ofd, sflag;
113 char **v, *pfmt, *arg;
116 nflag = raw = sflag = 0;
120 reset_internal_getopt ();
121 while ((c = internal_getopt (list, "Rnprsu:f:")) != -1)
128 if (loptend && ISOPTION (loptend->word->word, 'n'))
130 loptend = loptend->next;
146 if (all_digits (list_optarg))
147 ofd = atoi (list_optarg);
150 for (l = list; l->next && l->next != lcurrent; l = l->next);
151 lcurrent = loptend = l;
167 ofp = (ofd == 1) ? stdout : fdopen (dup (ofd), "w");
171 v = word_list_to_argv (list, 0, 2, &c);
172 v[0] = this_command_name;
174 r = printf_main (c, v);
181 for (l = list; l; l = l->next)
183 fprintf (ofp, "%s", l->word->word);
193 r = printargs (list, ofp);
201 static int printargs (list, ofp)
209 for (sawc = 0, l = list; l; l = l->next)
211 ostr = ansicstr (l->word->word, strlen (l->word->word), &sawc);
212 fprintf (ofp, "%s", ostr);
223 printf_main(argc, argv)
227 static char *skip1, *skip2;
228 int ch, end, fieldwidth, precision;
229 char convch, nextch, *format, *fmt, *start;
231 while ((ch = getopt(argc, argv, "")) != EOF)
247 * Basic algorithm is to scan the format string for conversion
248 * specifications -- once one is found, find out if the field
249 * width or precision is a '*'; if it is, gather up value. Note,
250 * format strings are reused as necessary to use up the provided
251 * arguments, arguments of zero/null string are provided to use
252 * up the format string.
255 skip2 = "*0123456789";
257 escape(fmt = format = *argv); /* backslash interpretation */
261 /* find next format specification */
262 next: for (start = fmt;; ++fmt) {
264 /* avoid infinite loop */
266 warnx("missing format character",
272 (void)printf("%s", start);
283 (void)printf("%s", start);
288 /* skip to field width */
289 for (; strchr(skip1, *fmt); ++fmt);
291 if (getint(&fieldwidth))
296 /* skip to possible '.', get following precision */
297 for (; strchr(skip2, *fmt); ++fmt);
301 if (getint(&precision))
306 /* skip to conversion char */
307 for (; strchr(skip2, *fmt); ++fmt);
309 warnx("missing format character", NULL, NULL);
331 case 'b': { /* expand escapes in argument */
339 case 'q': { /* print with shell single quoting */
343 p2 = single_quote(p);
348 case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
352 if ((f = mklong(start, convch)) == NULL)
359 case 'e': case 'E': case 'f': case 'g': case 'G': {
367 warnx("illegal format character", NULL, NULL);
380 static char copy[64];
383 len = strlen(str) + 2;
384 memmove(copy, str, len - 3);
387 copy[len - 1] = '\0';
395 register char *store;
396 register int value, c;
398 for (store = fmt; c = *fmt; ++fmt, ++store) {
404 case '\0': /* EOS, user error */
408 case '\\': /* backslash */
409 case '\'': /* single quote */
412 case 'a': /* bell/alert */
415 case 'b': /* backspace */
424 case 'f': /* form-feed */
427 case 'n': /* newline */
430 case 'r': /* carriage-return */
433 case 't': /* horizontal tab */
436 case 'v': /* vertical tab */
440 case '0': case '1': case '2': case '3':
441 case '4': case '5': case '6': case '7':
442 for (c = 3, value = 0;
443 c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
463 return ((int)**gargv++);
474 static char *Number = "+-.0123456789";
484 warnx("%s: %s", *gargv, strerror(ERANGE));
502 if (strchr(Number, **gargv)) {
504 val = strtol(*gargv, &ep, 0);
506 warnx("%s: illegal number", *gargv, NULL);
510 if (val == LONG_MAX) {
511 warnx("%s: %s", *gargv, strerror(ERANGE));
514 if (val == LONG_MIN) {
515 warnx("%s: %s", *gargv, strerror(ERANGE));
523 *lp = (long)asciicode();
532 if (strchr(Number, **gargv))
533 return (atof(*gargv++));
534 return ((double)asciicode());
543 if (ch == '\'' || ch == '"')
552 (void)fprintf(stderr, "usage: print [-Rnprs] [-u unit] [-f format] [arg ...]\n");