Logo Search packages:      
Sourcecode: coreutils version File versions  Download package

echo.c

/* echo.c, derived from code echo.c in Bash.
   Copyright (C) 87,89, 1991-1997, 1999-2005, 2007-2009 Free Software
   Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include "system.h"

/* The official name of this program (e.g., no `g' prefix).  */
#define PROGRAM_NAME "echo"

#define AUTHORS \
  proper_name ("Brian Fox"), \
  proper_name ("Chet Ramey")

/* If true, interpret backslash escapes by default.  */
#ifndef DEFAULT_ECHO_TO_XPG
enum { DEFAULT_ECHO_TO_XPG = false };
#endif

void
usage (int status)
{
  if (status != EXIT_SUCCESS)
    fprintf (stderr, _("Try `%s --help' for more information.\n"),
           program_name);
  else
    {
      printf (_("\
Usage: %s [SHORT-OPTION]... [STRING]...\n\
  or:  %s LONG-OPTION\n\
"), program_name, program_name);
      fputs (_("\
Echo the STRING(s) to standard output.\n\
\n\
  -n             do not output the trailing newline\n\
"), stdout);
      fputs (_(DEFAULT_ECHO_TO_XPG
             ? N_("\
  -e             enable interpretation of backslash escapes (default)\n\
  -E             disable interpretation of backslash escapes\n")
             : N_("\
  -e             enable interpretation of backslash escapes\n\
  -E             disable interpretation of backslash escapes (default)\n")),
           stdout);
      fputs (HELP_OPTION_DESCRIPTION, stdout);
      fputs (VERSION_OPTION_DESCRIPTION, stdout);
      fputs (_("\
\n\
If -e is in effect, the following sequences are recognized:\n\
\n\
  \\0NNN   the character whose ASCII code is NNN (octal)\n\
  \\\\     backslash\n\
  \\a     alert (BEL)\n\
  \\b     backspace\n\
"), stdout);
      fputs (_("\
  \\c     produce no further output\n\
  \\f     form feed\n\
  \\n     new line\n\
  \\r     carriage return\n\
  \\t     horizontal tab\n\
  \\v     vertical tab\n\
"), stdout);
      printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
      emit_bug_reporting_address ();
    }
  exit (status);
}

/* Convert C from hexadecimal character to integer.  */
static int
hextobin (unsigned char c)
{
  switch (c)
    {
    default: return c - '0';
    case 'a': case 'A': return 10;
    case 'b': case 'B': return 11;
    case 'c': case 'C': return 12;
    case 'd': case 'D': return 13;
    case 'e': case 'E': return 14;
    case 'f': case 'F': return 15;
    }
}

/* Print the words in LIST to standard output.  If the first word is
   `-n', then don't print a trailing newline.  We also support the
   echo syntax from Version 9 unix systems. */

int
main (int argc, char **argv)
{
  bool display_return = true;
  bool allow_options =
    (! getenv ("POSIXLY_CORRECT")
     || (! DEFAULT_ECHO_TO_XPG && 1 < argc && STREQ (argv[1], "-n")));

  /* System V machines already have a /bin/sh with a v9 behavior.
     Use the identical behavior for these machines so that the
     existing system shell scripts won't barf.  */
  bool do_v9 = DEFAULT_ECHO_TO_XPG;

  initialize_main (&argc, &argv);
  set_program_name (argv[0]);
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  atexit (close_stdout);

  /* We directly parse options, rather than use parse_long_options, in
     order to avoid accepting abbreviations.  */
  if (allow_options && argc == 2)
    {
      if (STREQ (argv[1], "--help"))
      usage (EXIT_SUCCESS);

      if (STREQ (argv[1], "--version"))
      {
        version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS,
                   (char *) NULL);
        exit (EXIT_SUCCESS);
      }
    }

  --argc;
  ++argv;

  if (allow_options)
    while (argc > 0 && *argv[0] == '-')
      {
      char const *temp = argv[0] + 1;
      size_t i;

      /* If it appears that we are handling options, then make sure that
         all of the options specified are actually valid.  Otherwise, the
         string should just be echoed.  */

      for (i = 0; temp[i]; i++)
        switch (temp[i])
          {
          case 'e': case 'E': case 'n':
            break;
          default:
            goto just_echo;
          }

      if (i == 0)
        goto just_echo;

      /* All of the options in TEMP are valid options to ECHO.
         Handle them. */
      while (*temp)
        switch (*temp++)
          {
          case 'e':
            do_v9 = true;
            break;

          case 'E':
            do_v9 = false;
            break;

          case 'n':
            display_return = false;
            break;
          }

      argc--;
      argv++;
      }

just_echo:

  if (do_v9)
    {
      while (argc > 0)
      {
        char const *s = argv[0];
        unsigned char c;

        while ((c = *s++))
          {
            if (c == '\\' && *s)
            {
              switch (c = *s++)
                {
                case 'a': c = '\a'; break;
                case 'b': c = '\b'; break;
                case 'c': exit (EXIT_SUCCESS);
                case 'f': c = '\f'; break;
                case 'n': c = '\n'; break;
                case 'r': c = '\r'; break;
                case 't': c = '\t'; break;
                case 'v': c = '\v'; break;
                case 'x':
                  {
                  unsigned char ch = *s;
                  if (! isxdigit (ch))
                    goto not_an_escape;
                  s++;
                  c = hextobin (ch);
                  ch = *s;
                  if (isxdigit (ch))
                    {
                      s++;
                      c = c * 16 + hextobin (ch);
                    }
                  }
                  break;
                case '0':
                  c = 0;
                  if (! ('0' <= *s && *s <= '7'))
                  break;
                  c = *s++;
                  /* Fall through.  */
                case '1': case '2': case '3':
                case '4': case '5': case '6': case '7':
                  c -= '0';
                  if ('0' <= *s && *s <= '7')
                  c = c * 8 + (*s++ - '0');
                  if ('0' <= *s && *s <= '7')
                  c = c * 8 + (*s++ - '0');
                  break;
                case '\\': break;

                not_an_escape:
                default:  putchar ('\\'); break;
                }
            }
            putchar (c);
          }
        argc--;
        argv++;
        if (argc > 0)
          putchar (' ');
      }
    }
  else
    {
      while (argc > 0)
      {
        fputs (argv[0], stdout);
        argc--;
        argv++;
        if (argc > 0)
          putchar (' ');
      }
    }

  if (display_return)
    putchar ('\n');
  exit (EXIT_SUCCESS);
}

Generated by  Doxygen 1.6.0   Back to index