9a72b553a66cb3c862d0d6d3cc9f49a97b3c3c15
[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 (int status)
68 {
69   if (status != 0)
70     fprintf (stderr, _("Try `%s --help' for more information.\n"),
71              program_name);
72   else
73     {
74       printf (_("Usage: %s [OPTION]... [STRING]...\n"), program_name);
75       printf (_("\
76 Echo the STRING(s) to standard output.\n\
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 (int argc, char **argv)
106 {
107   int display_return = 1, do_v9 = 0;
108
109   program_name = argv[0];
110
111   parse_long_options (argc, argv, "echo", version_string, usage);
112
113 /* System V machines already have a /bin/sh with a v9 behaviour.  We
114    use the identical behaviour for these machines so that the
115    existing system shell scripts won't barf. */
116 #if defined (V9_ECHO) && defined (V9_DEFAULT)
117   do_v9 = 1;
118 #endif
119
120   --argc;
121   ++argv;
122
123   while (argc > 0 && *argv[0] == '-')
124     {
125       register char *temp;
126       register int i;
127
128       /* If it appears that we are handling options, then make sure that
129          all of the options specified are actually valid.  Otherwise, the
130          string should just be echoed. */
131       temp = argv[0] + 1;
132
133       for (i = 0; temp[i]; i++)
134         {
135           if (strrchr (VALID_ECHO_OPTIONS, temp[i]) == 0)
136             goto just_echo;
137         }
138
139       if (!*temp)
140         goto just_echo;
141
142       /* All of the options in TEMP are valid options to ECHO.
143          Handle them. */
144       while (*temp)
145         {
146           if (*temp == 'n')
147             display_return = 0;
148 #if defined (V9_ECHO)
149           else if (*temp == 'e')
150             do_v9 = 1;
151 #if defined (V9_DEFAULT)
152           else if (*temp == 'E')
153             do_v9 = 0;
154 #endif /* V9_DEFAULT */
155 #endif /* V9_ECHO */
156           else
157             goto just_echo;
158
159           temp++;
160         }
161       argc--;
162       argv++;
163     }
164
165 just_echo:
166
167   if (argc > 0)
168     {
169 #if defined (V9_ECHO)
170       if (do_v9)
171         {
172           while (argc > 0)
173             {
174               register char *s = argv[0];
175               register int c;
176
177               while ((c = *s++))
178                 {
179                   if (c == '\\' && *s)
180                     {
181                       switch (c = *s++)
182                         {
183                         case 'a': c = '\007'; break;
184                         case 'b': c = '\b'; break;
185                         case 'c': display_return = 0; continue;
186                         case 'f': c = '\f'; break;
187                         case 'n': c = '\n'; break;
188                         case 'r': c = '\r'; break;
189                         case 't': c = '\t'; break;
190                         case 'v': c = (int) 0x0B; break;
191                         case '0': case '1': case '2': case '3':
192                         case '4': case '5': case '6': case '7':
193                           c -= '0';
194                           if (*s >= '0' && *s <= '7')
195                             c = c * 8 + (*s++ - '0');
196                           if (*s >= '0' && *s <= '7')
197                             c = c * 8 + (*s++ - '0');
198                           break;
199                         case '\\': break;
200                         default:  putchar ('\\'); break;
201                         }
202                     }
203                   putchar(c);
204                 }
205               argc--;
206               argv++;
207               if (argc > 0)
208                 putchar(' ');
209             }
210         }
211       else
212 #endif /* V9_ECHO */
213         {
214           while (argc > 0)
215             {
216               fputs (argv[0], stdout);
217               argc--;
218               argv++;
219               if (argc > 0)
220                 putchar (' ');
221             }
222         }
223     }
224   if (display_return)
225     putchar ('\n');
226   exit (0);
227 }