4a2f673de98593b363639f176c9d2b3545246e20
[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   fprintf (status == 0 ? stdout : stderr, "\
80 Usage: %s [OPTION]... [STRING]...\n\
81 ",
82            program_name);
83
84   if (status != 0)
85     fprintf (stderr, "Try `%s --help' for more information.\n",
86              program_name);
87   else
88
89     printf ("\
90 \n\
91   -n              do not output the trailing newline\n\
92   -e              (unused)\n\
93   -E              disable interpolation of some sequences in STRINGs\n\
94       --help      display this help and exit (should be alone)\n\
95       --version   output version information and exit (should be alone)\n\
96 \n\
97 Without -E, the following sequences are recognized and interpolated:\n\
98 \n\
99   \\NNN   the character whose ASCII code is NNN (octal)\n\
100   \\\\     backslash\n\
101   \\a     alert (BEL)\n\
102   \\b     backspace\n\
103   \\c     suppress trailing newline\n\
104   \\f     form feed\n\
105   \\n     new line\n\
106   \\r     carriage return\n\
107   \\t     horizontal tab\n\
108   \\v     vertical tab\n\
109 ");
110
111   exit (status);
112 }
113
114 /* Print the words in LIST to standard output.  If the first word is
115    `-n', then don't print a trailing newline.  We also support the
116    echo syntax from Version 9 unix systems. */
117 void
118 main (argc, argv)
119      int argc;
120      char **argv;
121 {
122   int display_return = 1, do_v9 = 0;
123
124   program_name = argv[0];
125
126   parse_long_options (argc, argv, usage);
127
128 /* System V machines already have a /bin/sh with a v9 behaviour.  We
129    use the identical behaviour for these machines so that the
130    existing system shell scripts won't barf. */
131 #if defined (V9_ECHO) && defined (V9_DEFAULT)
132   do_v9 = 1;
133 #endif
134
135   --argc;
136   ++argv;
137
138   while (argc > 0 && *argv[0] == '-')
139     {
140       register char *temp;
141       register int i;
142
143       /* If it appears that we are handling options, then make sure that
144          all of the options specified are actually valid.  Otherwise, the
145          string should just be echoed. */
146       temp = argv[0] + 1;
147
148       for (i = 0; temp[i]; i++)
149         {
150           if (rindex (VALID_ECHO_OPTIONS, temp[i]) == 0)
151             goto just_echo;
152         }
153
154       if (!*temp)
155         goto just_echo;
156
157       /* All of the options in TEMP are valid options to ECHO.
158          Handle them. */
159       while (*temp)
160         {
161           if (*temp == 'n')
162             display_return = 0;
163 #if defined (V9_ECHO)
164           else if (*temp == 'e')
165             do_v9 = 1;
166 #if defined (V9_DEFAULT)
167           else if (*temp == 'E')
168             do_v9 = 0;
169 #endif /* V9_DEFAULT */
170 #endif /* V9_ECHO */
171           else
172             goto just_echo;
173
174           temp++;
175         }
176       argc--;
177       argv++;
178     }
179
180 just_echo:
181
182   if (argc > 0)
183     {
184 #if defined (V9_ECHO)
185       if (do_v9)
186         {
187           while (argc > 0)
188             {
189               register char *s = argv[0];
190               register int c;
191
192               while ((c = *s++))
193                 {
194                   if (c == '\\' && *s)
195                     {
196                       switch (c = *s++)
197                         {
198                         case 'a': c = '\007'; break;
199                         case 'b': c = '\b'; break;
200                         case 'c': display_return = 0; continue;
201                         case 'f': c = '\f'; break;
202                         case 'n': c = '\n'; break;
203                         case 'r': c = '\r'; break;
204                         case 't': c = '\t'; break;
205                         case 'v': c = (int) 0x0B; break;
206                         case '0': case '1': case '2': case '3':
207                         case '4': case '5': case '6': case '7':
208                           c -= '0';
209                           if (*s >= '0' && *s <= '7')
210                             c = c * 8 + (*s++ - '0');
211                           if (*s >= '0' && *s <= '7')
212                             c = c * 8 + (*s++ - '0');
213                           break;
214                         case '\\': break;
215                         default:  putchar ('\\'); break;
216                         }
217                     }
218                   putchar(c);
219                 }
220               argc--;
221               argv++;
222               if (argc > 0)
223                 putchar(' ');
224             }
225         }
226       else
227 #endif /* V9_ECHO */
228         {
229           while (argc > 0)
230             {
231               fputs (argv[0], stdout);
232               argc--;
233               argv++;
234               if (argc > 0)
235                 putchar (' ');
236             }
237         }
238     }
239   if (display_return)
240     putchar ('\n');
241   exit (0);
242 }