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