1 /* echo.c - echo supporting -n and -e.
2  *
3  * Copyright 2007 Rob Landley <rob@landley.net>
4  *
5  * See http://opengroup.org/onlinepubs/9699919799/utilities/echo.html
6 
7 USE_ECHO(NEWTOY(echo, "^?en", TOYFLAG_BIN))
8 
9 config ECHO
10   bool "echo"
11   default y
12   help
13     usage: echo [-ne] [args...]
14 
15     Write each argument to stdout, with one space between each, followed
16     by a newline.
17 
18     -n	No trailing newline.
19     -e	Process the following escape sequences:
20     	\\	backslash
21     	\0NNN	octal values (1 to 3 digits)
22     	\a	alert (beep/flash)
23     	\b	backspace
24     	\c	stop output here (avoids trailing newline)
25     	\f	form feed
26     	\n	newline
27     	\r	carriage return
28     	\t	horizontal tab
29     	\v	vertical tab
30     	\xHH	hexadecimal values (1 to 2 digits)
31 */
32 
33 #define FOR_echo
34 #include "toys.h"
35 
echo_main(void)36 void echo_main(void)
37 {
38   int i = 0, out;
39   char *arg, *c;
40 
41   for (;;) {
42     arg = toys.optargs[i];
43     if (!arg) break;
44     if (i++) putchar(' ');
45 
46     // Should we output arg verbatim?
47 
48     if (!(toys.optflags & FLAG_e)) {
49       xprintf("%s", arg);
50       continue;
51     }
52 
53     // Handle -e
54 
55     for (c = arg;;) {
56       if (!(out = *(c++))) break;
57 
58       // handle \escapes
59       if (out == '\\' && *c) {
60         int slash = *(c++), n = unescape(slash);
61 
62         if (n) out = n;
63         else if (slash=='c') goto done;
64         else if (slash=='0') {
65           out = 0;
66           while (*c>='0' && *c<='7' && n++<3) out = (out*8)+*(c++)-'0';
67         } else if (slash=='x') {
68           out = 0;
69           while (n++<2) {
70             if (*c>='0' && *c<='9') out = (out*16)+*(c++)-'0';
71             else {
72               int temp = tolower(*c);
73               if (temp>='a' && temp<='f') {
74                 out = (out*16)+temp-'a'+10;
75                 c++;
76               } else break;
77             }
78           }
79         // Slash in front of unknown character, print literal.
80         } else c--;
81       }
82       putchar(out);
83     }
84   }
85 
86   // Output "\n" if no -n
87   if (!(toys.optflags&FLAG_n)) putchar('\n');
88 done:
89   xflush();
90 }
91