toybox/toys/posix/echo.c
<<
>>
Prefs
   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 * Deviations from posix: we parse command line options, as Linux has
   8 * consistently done since 1992. Posix defaults -e to on, we require -e.
   9 * We also honor -- to _stop_ option parsing (bash doesn't, we go with
  10 * consistency over compatibility here).
  11
  12USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK))
  13
  14config ECHO
  15  bool "echo"
  16  default y
  17  help
  18    usage: echo [-neE] [args...]
  19
  20    Write each argument to stdout, with one space between each, followed
  21    by a newline.
  22
  23    -n  No trailing newline
  24    -E  Print escape sequences literally (default)
  25    -e  Process the following escape sequences:
  26        \\      Backslash
  27        \0NNN   Octal values (1 to 3 digits)
  28        \a      Alert (beep/flash)
  29        \b      Backspace
  30        \c      Stop output here (avoids trailing newline)
  31        \f      Form feed
  32        \n      Newline
  33        \r      Carriage return
  34        \t      Horizontal tab
  35        \v      Vertical tab
  36        \xHH    Hexadecimal values (1 to 2 digits)
  37*/
  38
  39#define FOR_echo
  40#include "toys.h"
  41
  42void echo_main(void)
  43{
  44  int i = 0, out;
  45  char *arg, *c;
  46
  47  for (;;) {
  48    arg = toys.optargs[i];
  49    if (!arg) break;
  50    if (i++) putchar(' ');
  51
  52    // Should we output arg verbatim?
  53
  54    if (!FLAG(e)) {
  55      xprintf("%s", arg);
  56      continue;
  57    }
  58
  59    // Handle -e
  60
  61    for (c = arg;;) {
  62      if (!(out = *(c++))) break;
  63
  64      // handle \escapes
  65      if (out == '\\' && *c) {
  66        int slash = *(c++), n = unescape(slash);
  67
  68        if (n) out = n;
  69        else if (slash=='c') return;
  70        else if (slash=='0') {
  71          out = 0;
  72          while (*c>='0' && *c<='7' && n++<3) out = (out*8)+*(c++)-'0';
  73        } else if (slash=='x') {
  74          out = 0;
  75          while (n++<2) {
  76            if (*c>='0' && *c<='9') out = (out*16)+*(c++)-'0';
  77            else {
  78              int temp = tolower(*c);
  79              if (temp>='a' && temp<='f') {
  80                out = (out*16)+temp-'a'+10;
  81                c++;
  82              } else {
  83                if (n==1) {
  84                  --c;
  85                  out = '\\';
  86                }
  87                break;
  88              }
  89            }
  90          }
  91        // Slash in front of unknown character, print literal.
  92        } else c--;
  93      }
  94      putchar(out);
  95    }
  96  }
  97
  98  // Output "\n" if no -n
  99  if (!FLAG(n)) putchar('\n');
 100}
 101