summaryrefslogtreecommitdiff
path: root/src/echo.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2004-06-01 12:43:41 +0000
committerJim Meyering <jim@meyering.net>2004-06-01 12:43:41 +0000
commit97a6ce40ed4a34c9fb5eba5b50572f81bb839930 (patch)
tree7ddaea1f4c1e717f51d3c6a079f542ec55e440ac /src/echo.c
parenta805d1df2944399783c3ee504732e6bfa82bb393 (diff)
downloadcoreutils-97a6ce40ed4a34c9fb5eba5b50572f81bb839930.tar.xz
(V9_ECHO): Remove; always enabled.
(DEFAULT_ECHO_TO_XPG): Renamed from V9_DEFAULT, so that we use the same naming convention as bash. Now an enum, not a macro. (usage): Reword to mention -e/-E more accurately. Mention \0NNN (the POSIX syntax) rather than \NNN (nonstandard). (hextobin): New function. (main): Use bool rather than int for local vars when appropriate. Do not allow options if POSIXLY_CORRECT, unless we are using BSD semantics and the first argument is "-n". Don't pass unnecessary extra arg to parse_long_options. do_v9 now defaults to DEFAULT_ECHO_TO_XPG, not to allow_options. Do not look for options if !allow_options. Use size_t rather than int when appropriate. Open-code option test rather than using strrchr. Use faster test for "-". Avoid redundant argc test. Add support for \x, for Bash compatibility. Use e.g. '\a' rather than '\007', for portability to EBCDIC hosts. When '\c' is encountered, stop printing immediately, as POSIX requires. Add support for \xhh syntax. Add support for \0ooo syntax; POSIX requires this.
Diffstat (limited to 'src/echo.c')
-rw-r--r--src/echo.c252
1 files changed, 137 insertions, 115 deletions
diff --git a/src/echo.c b/src/echo.c
index d9ae62032..9467af345 100644
--- a/src/echo.c
+++ b/src/echo.c
@@ -39,28 +39,16 @@ following backslash-escaped characters is turned on:
\t horizontal tab
\v vertical tab
\\ backslash
- \num the character whose ASCII code is NUM (octal).
+ \0NNN the character whose ASCII code is NNN (octal).
You can explicitly turn off the interpretation of the above characters
on System V systems with the -E option.
*/
-/* If defined, interpret backslash escapes if -e is given. */
-#define V9_ECHO
-
-/* If defined, interpret backslash escapes unless -E is given.
- V9_ECHO must also be defined. */
-/* #define V9_DEFAULT */
-
-#if defined (V9_ECHO)
-# if defined (V9_DEFAULT)
-# define VALID_ECHO_OPTIONS "neE"
-# else
-# define VALID_ECHO_OPTIONS "ne"
-# endif /* !V9_DEFAULT */
-#else /* !V9_ECHO */
-# define VALID_ECHO_OPTIONS "n"
-#endif /* !V9_ECHO */
+/* If true, interpret backslash escapes by default. */
+#ifndef DEFAULT_ECHO_TO_XPG
+enum { DEFAULT_ECHO_TO_XPG = false };
+#endif
/* The name this program was run with. */
char *program_name;
@@ -86,9 +74,9 @@ Echo the STRING(s) to standard output.\n\
fputs (VERSION_OPTION_DESCRIPTION, stdout);
fputs (_("\
\n\
-Without -E, the following sequences are recognized and interpolated:\n\
+If -e is in effect, the following sequences are recognized:\n\
\n\
- \\NNN the character whose ASCII code is NNN (octal)\n\
+ \\0NNN the character whose ASCII code is NNN (octal)\n\
\\\\ backslash\n\
\\a alert (BEL)\n\
\\b backspace\n\
@@ -106,6 +94,22 @@ Without -E, the following sequences are recognized and interpolated:\n\
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. */
@@ -113,8 +117,15 @@ Without -E, the following sequences are recognized and interpolated:\n\
int
main (int argc, char **argv)
{
- int display_return = 1, do_v9 = 0;
- int allow_options = 1;
+ bool display_return = true;
+ bool allow_options =
+ (! getenv ("POSIXLY_CORRECT")
+ || (! DEFAULT_ECHO_TO_XPG && 0 < 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);
program_name = argv[0];
@@ -124,124 +135,135 @@ main (int argc, char **argv)
atexit (close_stdout);
- /* Don't recognize --help or --version if POSIXLY_CORRECT is set. */
- if (getenv ("POSIXLY_CORRECT") == NULL)
+ if (allow_options)
parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
- usage, AUTHORS, (char const *) NULL, NULL);
- else
- allow_options = 0;
-
-/* System V machines already have a /bin/sh with a v9 behaviour. We
- use the identical behaviour for these machines so that the
- existing system shell scripts won't barf. */
-#if defined (V9_ECHO) && defined (V9_DEFAULT)
- do_v9 = allow_options;
-#endif
+ usage, AUTHORS, (char const *) NULL);
--argc;
++argv;
- while (argc > 0 && *argv[0] == '-')
- {
- register char *temp;
- register int i;
+ 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. */
- temp = argv[0] + 1;
+ /* 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++)
- {
- if (strrchr (VALID_ECHO_OPTIONS, temp[i]) == 0)
- goto just_echo;
- }
+ for (i = 0; temp[i]; i++)
+ switch (temp[i])
+ {
+ case 'e': case 'E': case 'n':
+ break;
+ default:
+ goto just_echo;
+ }
- if (!*temp)
- goto just_echo;
+ if (i == 0)
+ goto just_echo;
- /* All of the options in TEMP are valid options to ECHO.
- Handle them. */
- while (*temp)
- {
- if (allow_options && *temp == 'n')
- display_return = 0;
-#if defined (V9_ECHO)
- else if (allow_options && *temp == 'e')
- do_v9 = 1;
-# if defined (V9_DEFAULT)
- else if (allow_options && *temp == 'E')
- do_v9 = 0;
-# endif /* V9_DEFAULT */
-#endif /* V9_ECHO */
- else
- goto just_echo;
-
- temp++;
- }
- argc--;
- argv++;
- }
+ /* 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 (argc > 0)
+ if (do_v9)
{
-#if defined (V9_ECHO)
- if (do_v9)
+ while (argc > 0)
{
- while (argc > 0)
- {
- register char *s = argv[0];
- register int c;
+ char const *s = argv[0];
+ unsigned char c;
- while ((c = *s++))
+ while ((c = *s++))
+ {
+ if (c == '\\' && *s)
{
- if (c == '\\' && *s)
+ switch (c = *s++)
{
- switch (c = *s++)
- {
- case 'a': c = '\007'; break;
- case 'b': c = '\b'; break;
- case 'c': display_return = 0; continue;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- case 'v': c = (int) 0x0B; break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- c -= '0';
- if (*s >= '0' && *s <= '7')
- c = c * 8 + (*s++ - '0');
- if (*s >= '0' && *s <= '7')
- c = c * 8 + (*s++ - '0');
- break;
- case '\\': break;
- default: putchar ('\\'); break;
- }
+ 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(' ');
+ putchar (c);
}
+ argc--;
+ argv++;
+ if (argc > 0)
+ putchar (' ');
}
- else
-#endif /* V9_ECHO */
+ }
+ else
+ {
+ while (argc > 0)
{
- while (argc > 0)
- {
- fputs (argv[0], stdout);
- argc--;
- argv++;
- if (argc > 0)
- putchar (' ');
- }
+ fputs (argv[0], stdout);
+ argc--;
+ argv++;
+ if (argc > 0)
+ putchar (' ');
}
}
+
if (display_return)
putchar ('\n');
exit (EXIT_SUCCESS);