LCOV - code coverage report
Current view: top level - src - echo.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 93 114 81.6 %
Date: 2018-01-30 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /* echo.c, derived from code echo.c in Bash.
       2             :    Copyright (C) 87,89, 1991-1997, 1999-2005, 2007 Free Software
       3             :    Foundation, Inc.
       4             : 
       5             :    This program is free software: you can redistribute it and/or modify
       6             :    it under the terms of the GNU General Public License as published by
       7             :    the Free Software Foundation, either version 3 of the License, or
       8             :    (at your option) any later version.
       9             : 
      10             :    This program is distributed in the hope that it will be useful,
      11             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :    GNU General Public License for more details.
      14             : 
      15             :    You should have received a copy of the GNU General Public License
      16             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      17             : 
      18             : #include <config.h>
      19             : #include <stdio.h>
      20             : #include <sys/types.h>
      21             : #include "system.h"
      22             : #include "long-options.h"
      23             : 
      24             : /* The official name of this program (e.g., no `g' prefix).  */
      25             : #define PROGRAM_NAME "echo"
      26             : 
      27             : #define AUTHORS "FIXME unknown"
      28             : 
      29             : /* echo [-neE] [arg ...]
      30             : Output the ARGs.  If -n is specified, the trailing newline is
      31             : suppressed.  If the -e option is given, interpretation of the
      32             : following backslash-escaped characters is turned on:
      33             :         \a      alert (bell)
      34             :         \b      backspace
      35             :         \c      suppress trailing newline
      36             :         \f      form feed
      37             :         \n      new line
      38             :         \r      carriage return
      39             :         \t      horizontal tab
      40             :         \v      vertical tab
      41             :         \\      backslash
      42             :         \0NNN   the character whose ASCII code is NNN (octal).
      43             : 
      44             : You can explicitly turn off the interpretation of the above characters
      45             : on System V systems with the -E option.
      46             : */
      47             : 
      48             : /* If true, interpret backslash escapes by default.  */
      49             : #ifndef DEFAULT_ECHO_TO_XPG
      50             : enum { DEFAULT_ECHO_TO_XPG = false };
      51             : #endif
      52             : 
      53             : /* The name this program was run with. */
      54             : char *program_name;
      55             : 
      56             : void
      57           2 : usage (int status)
      58             : {
      59           2 :   if (status != EXIT_SUCCESS)
      60           0 :     fprintf (stderr, _("Try `%s --help' for more information.\n"),
      61             :              program_name);
      62             :   else
      63             :     {
      64           2 :       printf (_("Usage: %s [OPTION]... [STRING]...\n"), program_name);
      65           2 :       fputs (_("\
      66             : Echo the STRING(s) to standard output.\n\
      67             : \n\
      68             :   -n             do not output the trailing newline\n\
      69             : "), stdout);
      70           2 :       fputs (_(DEFAULT_ECHO_TO_XPG
      71             :                ? "\
      72             :   -e             enable interpretation of backslash escapes (default)\n\
      73             :   -E             disable interpretation of backslash escapes\n"
      74             :                : "\
      75             :   -e             enable interpretation of backslash escapes\n\
      76             :   -E             disable interpretation of backslash escapes (default)\n"),
      77             :              stdout);
      78           2 :       fputs (HELP_OPTION_DESCRIPTION, stdout);
      79           2 :       fputs (VERSION_OPTION_DESCRIPTION, stdout);
      80           2 :       fputs (_("\
      81             : \n\
      82             : If -e is in effect, the following sequences are recognized:\n\
      83             : \n\
      84             :   \\0NNN   the character whose ASCII code is NNN (octal)\n\
      85             :   \\\\     backslash\n\
      86             :   \\a     alert (BEL)\n\
      87             :   \\b     backspace\n\
      88             : "), stdout);
      89           2 :       fputs (_("\
      90             :   \\c     suppress trailing newline\n\
      91             :   \\f     form feed\n\
      92             :   \\n     new line\n\
      93             :   \\r     carriage return\n\
      94             :   \\t     horizontal tab\n\
      95             :   \\v     vertical tab\n\
      96             : "), stdout);
      97           2 :       printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
      98           2 :       emit_bug_reporting_address ();
      99             :     }
     100           2 :   exit (status);
     101             : }
     102             : 
     103             : /* Convert C from hexadecimal character to integer.  */
     104             : static int
     105           0 : hextobin (unsigned char c)
     106             : {
     107           0 :   switch (c)
     108             :     {
     109           0 :     default: return c - '0';
     110           0 :     case 'a': case 'A': return 10;
     111           0 :     case 'b': case 'B': return 11;
     112           0 :     case 'c': case 'C': return 12;
     113           0 :     case 'd': case 'D': return 13;
     114           0 :     case 'e': case 'E': return 14;
     115           0 :     case 'f': case 'F': return 15;
     116             :     }
     117             : }
     118             : 
     119             : /* Print the words in LIST to standard output.  If the first word is
     120             :    `-n', then don't print a trailing newline.  We also support the
     121             :    echo syntax from Version 9 unix systems. */
     122             : 
     123             : int
     124          35 : main (int argc, char **argv)
     125             : {
     126          35 :   bool display_return = true;
     127          35 :   bool allow_options =
     128          35 :     (! getenv ("POSIXLY_CORRECT")
     129          35 :      || (! DEFAULT_ECHO_TO_XPG && 1 < argc && STREQ (argv[1], "-n")));
     130             : 
     131             :   /* System V machines already have a /bin/sh with a v9 behavior.
     132             :      Use the identical behavior for these machines so that the
     133             :      existing system shell scripts won't barf.  */
     134          35 :   bool do_v9 = DEFAULT_ECHO_TO_XPG;
     135             : 
     136             :   initialize_main (&argc, &argv);
     137          35 :   program_name = argv[0];
     138          35 :   setlocale (LC_ALL, "");
     139             :   bindtextdomain (PACKAGE, LOCALEDIR);
     140             :   textdomain (PACKAGE);
     141             : 
     142          35 :   atexit (close_stdout);
     143             : 
     144          35 :   if (allow_options)
     145          35 :     parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, VERSION,
     146             :                         usage, AUTHORS, (char const *) NULL);
     147             : 
     148          32 :   --argc;
     149          32 :   ++argv;
     150             : 
     151          32 :   if (allow_options)
     152         132 :     while (argc > 0 && *argv[0] == '-')
     153             :       {
     154          38 :         char const *temp = argv[0] + 1;
     155             :         size_t i;
     156             : 
     157             :         /* If it appears that we are handling options, then make sure that
     158             :            all of the options specified are actually valid.  Otherwise, the
     159             :            string should just be echoed.  */
     160             : 
     161          66 :         for (i = 0; temp[i]; i++)
     162          32 :           switch (temp[i])
     163             :             {
     164          28 :             case 'e': case 'E': case 'n':
     165          28 :               break;
     166           4 :             default:
     167           4 :               goto just_echo;
     168             :             }
     169             : 
     170          34 :         if (i == 0)
     171          14 :           goto just_echo;
     172             : 
     173             :         /* All of the options in TEMP are valid options to ECHO.
     174             :            Handle them. */
     175          68 :         while (*temp)
     176          28 :           switch (*temp++)
     177             :             {
     178          25 :             case 'e':
     179          25 :               do_v9 = true;
     180          25 :               break;
     181             : 
     182           1 :             case 'E':
     183           1 :               do_v9 = false;
     184           1 :               break;
     185             : 
     186           2 :             case 'n':
     187           2 :               display_return = false;
     188           2 :               break;
     189             :             }
     190             : 
     191          20 :         argc--;
     192          20 :         argv++;
     193             :       }
     194             : 
     195          14 : just_echo:
     196             : 
     197          32 :   if (do_v9)
     198             :     {
     199          58 :       while (argc > 0)
     200             :         {
     201          25 :           char const *s = argv[0];
     202             :           unsigned char c;
     203             : 
     204          70 :           while ((c = *s++))
     205             :             {
     206          34 :               if (c == '\\' && *s)
     207             :                 {
     208          12 :                   switch (c = *s++)
     209             :                     {
     210           1 :                     case 'a': c = '\a'; break;
     211           1 :                     case 'b': c = '\b'; break;
     212           1 :                     case 'c': exit (EXIT_SUCCESS);
     213           1 :                     case 'f': c = '\f'; break;
     214           1 :                     case 'n': c = '\n'; break;
     215           1 :                     case 'r': c = '\r'; break;
     216           1 :                     case 't': c = '\t'; break;
     217           1 :                     case 'v': c = '\v'; break;
     218           1 :                     case 'x':
     219             :                       {
     220           1 :                         unsigned char ch = *s;
     221           1 :                         if (! isxdigit (ch))
     222           1 :                           goto not_an_escape;
     223           0 :                         s++;
     224           0 :                         c = hextobin (ch);
     225           0 :                         ch = *s;
     226           0 :                         if (isxdigit (ch))
     227             :                           {
     228           0 :                             s++;
     229           0 :                             c = c * 16 + hextobin (ch);
     230             :                           }
     231             :                       }
     232           0 :                       break;
     233           1 :                     case '0':
     234           1 :                       c = 0;
     235           1 :                       if (! ('0' <= *s && *s <= '7'))
     236             :                         break;
     237           0 :                       c = *s++;
     238             :                       /* Fall through.  */
     239           2 :                     case '1': case '2': case '3':
     240             :                     case '4': case '5': case '6': case '7':
     241           2 :                       c -= '0';
     242           2 :                       if ('0' <= *s && *s <= '7')
     243           0 :                         c = c * 8 + (*s++ - '0');
     244           2 :                       if ('0' <= *s && *s <= '7')
     245           0 :                         c = c * 8 + (*s++ - '0');
     246           2 :                       break;
     247           0 :                     case '\\': break;
     248             : 
     249           1 :                     not_an_escape:
     250           1 :                     default:  putchar ('\\'); break;
     251             :                     }
     252          10 :                 }
     253          20 :               putchar (c);
     254             :             }
     255          24 :           argc--;
     256          24 :           argv++;
     257          24 :           if (argc > 0)
     258          10 :             putchar (' ');
     259             :         }
     260             :     }
     261             :   else
     262             :     {
     263          52 :       while (argc > 0)
     264             :         {
     265          22 :           fputs (argv[0], stdout);
     266          22 :           argc--;
     267          22 :           argv++;
     268          22 :           if (argc > 0)
     269           9 :             putchar (' ');
     270             :         }
     271             :     }
     272             : 
     273          31 :   if (display_return)
     274          29 :     putchar ('\n');
     275          31 :   exit (EXIT_SUCCESS);
     276             : }

Generated by: LCOV version 1.10