(add_tabstop): Give correct size when reallocating tab_list buffer.
[platform/upstream/coreutils.git] / src / echo.c
1 /* echo.c, taken from Bash.
2    Copyright (C) 87, 89, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
3
4 This file is part of GNU Bash, the Bourne Again SHell.
5
6 Bash is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with Bash; see the file COPYING.  If not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include "system.h"
24 #include "version.h"
25 #include "long-options.h"
26
27 /* echo [-neE] [arg ...]
28 Output the ARGs.  If -n is specified, the trailing newline is
29 suppressed.  If the -e option is given, interpretation of the
30 following backslash-escaped characters is turned on:
31         \a      alert (bell)
32         \b      backspace
33         \c      suppress trailing newline
34         \f      form feed
35         \n      new line
36         \r      carriage return
37         \t      horizontal tab
38         \v      vertical tab
39         \\      backslash
40         \num    the character whose ASCII code is NUM (octal).
41
42 You can explicitly turn off the interpretation of the above characters
43 on System V systems with the -E option.
44 */
45
46 /* If defined, interpret backslash escapes if -e is given.  */
47 #define V9_ECHO
48
49 /* If defined, interpret backslash escapes unless -E is given.
50    V9_ECHO must also be defined.  */
51 #define V9_DEFAULT
52
53 #if defined (V9_ECHO)
54 #  if defined (V9_DEFAULT)
55 #    define VALID_ECHO_OPTIONS "neE"
56 #  else
57 #    define VALID_ECHO_OPTIONS "ne"
58 #  endif /* !V9_DEFAULT */
59 #else /* !V9_ECHO */
60 #  define VALID_ECHO_OPTIONS "n"
61 #endif /* !V9_ECHO */
62
63 /* The name this program was run with. */
64 char *program_name;
65
66 static void
67 usage (status)
68      int status;
69 {
70   if (status != 0)
71     fprintf (stderr, "Try `%s --help' for more information.\n",
72              program_name);
73   else
74     {
75       printf ("Usage: %s [OPTION]... [STRING]...\n", program_name);
76       printf ("\
77 \n\
78   -n              do not output the trailing newline\n\
79   -e              (unused)\n\
80   -E              disable interpolation of some sequences in STRINGs\n\
81       --help      display this help and exit (should be alone)\n\
82       --version   output version information and exit (should be alone)\n\
83 \n\
84 Without -E, the following sequences are recognized and interpolated:\n\
85 \n\
86   \\NNN   the character whose ASCII code is NNN (octal)\n\
87   \\\\     backslash\n\
88   \\a     alert (BEL)\n\
89   \\b     backspace\n\
90   \\c     suppress trailing newline\n\
91   \\f     form feed\n\
92   \\n     new line\n\
93   \\r     carriage return\n\
94   \\t     horizontal tab\n\
95   \\v     vertical tab\n\
96 ");
97     }
98   exit (status);
99 }
100
101 /* Print the words in LIST to standard output.  If the first word is
102    `-n', then don't print a trailing newline.  We also support the
103    echo syntax from Version 9 unix systems. */
104 void
105 main (argc, argv)
106      int argc;
107      char **argv;
108 {
109   int display_return = 1, do_v9 = 0;
110
111   program_name = argv[0];
112
113   parse_long_options (argc, argv, "echo", version_string, usage);
114
115 /* System V machines already have a /bin/sh with a v9 behaviour.  We
116    use the identical behaviour for these machines so that the
117    existing system shell scripts won't barf. */
118 #if defined (V9_ECHO) && defined (V9_DEFAULT)
119   do_v9 = 1;
120 #endif
121
122   --argc;
123   ++argv;
124
125   while (argc > 0 && *argv[0] == '-')
126     {
127       register char *temp;
128       register int i;
129
130       /* If it appears that we are handling options, then make sure that
131          all of the options specified are actually valid.  Otherwise, the
132          string should just be echoed. */
133       temp = argv[0] + 1;
134
135       for (i = 0; temp[i]; i++)
136         {
137           if (strrchr (VALID_ECHO_OPTIONS, temp[i]) == 0)
138             goto just_echo;
139         }
140
141       if (!*temp)
142         goto just_echo;
143
144       /* All of the options in TEMP are valid options to ECHO.
145          Handle them. */
146       while (*temp)
147         {
148           if (*temp == 'n')
149             display_return = 0;
150 #if defined (V9_ECHO)
151           else if (*temp == 'e')
152             do_v9 = 1;
153 #if defined (V9_DEFAULT)
154           else if (*temp == 'E')
155             do_v9 = 0;
156 #endif /* V9_DEFAULT */
157 #endif /* V9_ECHO */
158           else
159             goto just_echo;
160
161           temp++;
162         }
163       argc--;
164       argv++;
165     }
166
167 just_echo:
168
169   if (argc > 0)
170     {
171 #if defined (V9_ECHO)
172       if (do_v9)
173         {
174           while (argc > 0)
175             {
176               register char *s = argv[0];
177               register int c;
178
179               while ((c = *s++))
180                 {
181                   if (c == '\\' && *s)
182                     {
183                       switch (c = *s++)
184                         {
185                         case 'a': c = '\007'; break;
186                         case 'b': c = '\b'; break;
187                         case 'c': display_return = 0; continue;
188                         case 'f': c = '\f'; break;
189                         case 'n': c = '\n'; break;
190                         case 'r': c = '\r'; break;
191                         case 't': c = '\t'; break;
192                         case 'v': c = (int) 0x0B; break;
193                         case '0': case '1': case '2': case '3':
194                         case '4': case '5': case '6': case '7':
195                           c -= '0';
196                           if (*s >= '0' && *s <= '7')
197                             c = c * 8 + (*s++ - '0');
198                           if (*s >= '0' && *s <= '7')
199                             c = c * 8 + (*s++ - '0');
200                           break;
201                         case '\\': break;
202                         default:  putchar ('\\'); break;
203                         }
204                     }
205                   putchar(c);
206                 }
207               argc--;
208               argv++;
209               if (argc > 0)
210                 putchar(' ');
211             }
212         }
213       else
214 #endif /* V9_ECHO */
215         {
216           while (argc > 0)
217             {
218               fputs (argv[0], stdout);
219               argc--;
220               argv++;
221               if (argc > 0)
222                 putchar (' ');
223             }
224         }
225     }
226   if (display_return)
227     putchar ('\n');
228   exit (0);
229 }