1/*
2 * print -- loadable ksh-93 style print builtin
3 */
4
5#ifdef HAVE_CONFIG_H
6#  include <config.h>
7#endif
8
9#include "bashtypes.h"
10
11#include <errno.h>
12#include <limits.h>
13#include <stdio.h>
14
15#include "bashansi.h"
16#include "shell.h"
17#include "builtins.h"
18#include "stdc.h"
19#include "bashgetopt.h"
20
21#if !defined (errno)
22extern int errno;
23#endif
24
25int print_builtin ();
26static int printargs ();
27
28static FILE *ofp;
29
30extern char *this_command_name;
31
32static char *print_doc[] = {
33  "Output the arguments.  The -f option means to use the argument as a",
34  "format string as would be supplied to printf(1).  The rest of the",
35  "options are as in ksh.",
36  (char *)NULL
37};
38
39struct builtin print_struct = {
40	"print",
41	print_builtin,
42	BUILTIN_ENABLED,
43	print_doc,
44	"print [-Rnprs] [-u unit] [-f format] [arguments]",
45	(char *)0
46};
47
48#ifndef ISOPTION
49#define ISOPTION(s, c)	(s[0] == '-' && s[2] == '\0' && s[1] == c)
50#endif
51
52int
53print_builtin (list)
54     WORD_LIST *list;
55{
56  int c, r, nflag, raw, ofd, sflag;
57  intmax_t lfd;
58  char **v, *pfmt, *arg;
59  WORD_LIST *l;
60
61  nflag = raw = sflag = 0;
62  ofd = 1;
63  pfmt = 0;
64
65  reset_internal_getopt ();
66  while ((c = internal_getopt (list, "Rnprsu:f:")) != -1)
67    {
68      switch (c)
69	{
70	case 'R':
71	  raw = 2;
72	  loptend = lcurrent;
73	  if (loptend && ISOPTION (loptend->word->word, 'n'))
74	    {
75	      loptend = loptend->next;
76	      nflag = 1;
77	    }
78	  goto opt_end;
79	case 'r':
80	  raw = 1;
81	  break;
82	case 'n':
83	  nflag = 1;
84	  break;
85	case 's':
86	  sflag = 1;
87	  break;
88	case 'p':
89	  break;	/* NOP */
90	case 'u':
91	  if (all_digits (list_optarg) && legal_number (list_optarg, &lfd) && lfd == (int)lfd)
92	    ofd = lfd;
93	  else
94	    {
95	      for (l = list; l->next && l->next != lcurrent; l = l->next);
96	      lcurrent = loptend = l;
97	      goto opt_end;
98	    }
99	  break;
100	case 'f':
101	  pfmt = list_optarg;
102	  break;
103	default:
104	  builtin_usage ();
105	  return (EX_USAGE);
106	}
107    }
108
109opt_end:
110  list = loptend;
111
112  ofp = (ofd == 1) ? stdout : fdopen (dup (ofd), "w");
113
114  if (pfmt)
115    {
116      WORD_DESC *w;
117      WORD_LIST *nlist;
118
119      w = make_word (pfmt);
120      nlist = make_word_list (w, list);
121      r = printf_builtin (nlist);
122      nlist->next = (WORD_LIST *)NULL;
123      dispose_words (nlist);
124      return (r);
125    }
126
127  if (raw)
128    {
129      for (l = list; l; l = l->next)
130	{
131	  fprintf (ofp, "%s", l->word->word);
132	  if (l->next)
133	    fprintf (ofp, " ");
134	}
135      if (nflag == 0)
136	fprintf (ofp, "\n");
137      fflush (ofp);
138      return (0);
139    }
140
141  r = printargs (list, ofp);
142  if (r && nflag == 0)
143    fprintf (ofp, "\n");
144  if (ofd != 1)
145    fclose (ofp);
146  return 0;
147}
148
149static int
150printargs (list, ofp)
151     WORD_LIST *list;
152     FILE *ofp;
153{
154  WORD_LIST *l;
155  char *ostr;
156  int sawc;
157
158  for (sawc = 0, l = list; l; l = l->next)
159    {
160      ostr = ansicstr (l->word->word, strlen (l->word->word), 0, &sawc, (int *)0);
161      fprintf (ofp, "%s", ostr);
162      free (ostr);
163      if (sawc)
164        return (0);
165      if (l->next)
166        fprintf (ofp, " ");
167    }
168  return (1);
169}
170