10f66f451Sopenharmony_ci/* echo.c - echo supporting -n and -e.
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2007 Rob Landley <rob@landley.net>
40f66f451Sopenharmony_ci *
50f66f451Sopenharmony_ci * See http://opengroup.org/onlinepubs/9699919799/utilities/echo.html
60f66f451Sopenharmony_ci *
70f66f451Sopenharmony_ci * Deviations from posix: we parse command line options, as Linux has
80f66f451Sopenharmony_ci * consistently done since 1992. Posix defaults -e to on, we require -e.
90f66f451Sopenharmony_ci * We also honor -- to _stop_ option parsing (bash doesn't, we go with
100f66f451Sopenharmony_ci * consistency over compatibility here).
110f66f451Sopenharmony_ci
120f66f451Sopenharmony_ciUSE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK))
130f66f451Sopenharmony_ci
140f66f451Sopenharmony_ciconfig ECHO
150f66f451Sopenharmony_ci  bool "echo"
160f66f451Sopenharmony_ci  default y
170f66f451Sopenharmony_ci  help
180f66f451Sopenharmony_ci    usage: echo [-neE] [args...]
190f66f451Sopenharmony_ci
200f66f451Sopenharmony_ci    Write each argument to stdout, with one space between each, followed
210f66f451Sopenharmony_ci    by a newline.
220f66f451Sopenharmony_ci
230f66f451Sopenharmony_ci    -n	No trailing newline
240f66f451Sopenharmony_ci    -E	Print escape sequences literally (default)
250f66f451Sopenharmony_ci    -e	Process the following escape sequences:
260f66f451Sopenharmony_ci    	\\	Backslash
270f66f451Sopenharmony_ci    	\0NNN	Octal values (1 to 3 digits)
280f66f451Sopenharmony_ci    	\a	Alert (beep/flash)
290f66f451Sopenharmony_ci    	\b	Backspace
300f66f451Sopenharmony_ci    	\c	Stop output here (avoids trailing newline)
310f66f451Sopenharmony_ci    	\f	Form feed
320f66f451Sopenharmony_ci    	\n	Newline
330f66f451Sopenharmony_ci    	\r	Carriage return
340f66f451Sopenharmony_ci    	\t	Horizontal tab
350f66f451Sopenharmony_ci    	\v	Vertical tab
360f66f451Sopenharmony_ci    	\xHH	Hexadecimal values (1 to 2 digits)
370f66f451Sopenharmony_ci*/
380f66f451Sopenharmony_ci
390f66f451Sopenharmony_ci#define FOR_echo
400f66f451Sopenharmony_ci#include "toys.h"
410f66f451Sopenharmony_ci
420f66f451Sopenharmony_civoid echo_main(void)
430f66f451Sopenharmony_ci{
440f66f451Sopenharmony_ci  int i = 0, out;
450f66f451Sopenharmony_ci  char *arg, *c;
460f66f451Sopenharmony_ci
470f66f451Sopenharmony_ci  for (;;) {
480f66f451Sopenharmony_ci    arg = toys.optargs[i];
490f66f451Sopenharmony_ci    if (!arg) break;
500f66f451Sopenharmony_ci    if (i++) putchar(' ');
510f66f451Sopenharmony_ci
520f66f451Sopenharmony_ci    // Should we output arg verbatim?
530f66f451Sopenharmony_ci
540f66f451Sopenharmony_ci    if (!FLAG(e)) {
550f66f451Sopenharmony_ci      xprintf("%s", arg);
560f66f451Sopenharmony_ci      continue;
570f66f451Sopenharmony_ci    }
580f66f451Sopenharmony_ci
590f66f451Sopenharmony_ci    // Handle -e
600f66f451Sopenharmony_ci
610f66f451Sopenharmony_ci    for (c = arg;;) {
620f66f451Sopenharmony_ci      if (!(out = *(c++))) break;
630f66f451Sopenharmony_ci
640f66f451Sopenharmony_ci      // handle \escapes
650f66f451Sopenharmony_ci      if (out == '\\' && *c) {
660f66f451Sopenharmony_ci        int slash = *(c++), n = unescape(slash);
670f66f451Sopenharmony_ci
680f66f451Sopenharmony_ci        if (n) out = n;
690f66f451Sopenharmony_ci        else if (slash=='c') return;
700f66f451Sopenharmony_ci        else if (slash=='0') {
710f66f451Sopenharmony_ci          out = 0;
720f66f451Sopenharmony_ci          while (*c>='0' && *c<='7' && n++<3) out = (out*8)+*(c++)-'0';
730f66f451Sopenharmony_ci        } else if (slash=='x') {
740f66f451Sopenharmony_ci          out = 0;
750f66f451Sopenharmony_ci          while (n++<2) {
760f66f451Sopenharmony_ci            if (*c>='0' && *c<='9') out = (out*16)+*(c++)-'0';
770f66f451Sopenharmony_ci            else {
780f66f451Sopenharmony_ci              int temp = tolower(*c);
790f66f451Sopenharmony_ci              if (temp>='a' && temp<='f') {
800f66f451Sopenharmony_ci                out = (out*16)+temp-'a'+10;
810f66f451Sopenharmony_ci                c++;
820f66f451Sopenharmony_ci              } else {
830f66f451Sopenharmony_ci                if (n==1) {
840f66f451Sopenharmony_ci                  --c;
850f66f451Sopenharmony_ci                  out = '\\';
860f66f451Sopenharmony_ci                }
870f66f451Sopenharmony_ci                break;
880f66f451Sopenharmony_ci              }
890f66f451Sopenharmony_ci            }
900f66f451Sopenharmony_ci          }
910f66f451Sopenharmony_ci        // Slash in front of unknown character, print literal.
920f66f451Sopenharmony_ci        } else c--;
930f66f451Sopenharmony_ci      }
940f66f451Sopenharmony_ci      putchar(out);
950f66f451Sopenharmony_ci    }
960f66f451Sopenharmony_ci  }
970f66f451Sopenharmony_ci
980f66f451Sopenharmony_ci  // Output "\n" if no -n
990f66f451Sopenharmony_ci  if (!FLAG(n)) putchar('\n');
1000f66f451Sopenharmony_ci}
101