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