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