Download src/echo.c from AryaWu/coreutils: direct link, hf CLI and curl.
- Browser
- Download file 7.93 kB
-
https://huggingface.co/AryaWu/coreutils/resolve/main/src/echo.c
- Command line
-
hf download hf://AryaWu/coreutils/src/echo.c
-
curl -L -o echo.c https://huggingface.co/AryaWu/coreutils/resolve/main/src/echo.c
7.93 kB
| /* echo.c, derived from code echo.c in Bash. | |
| Copyright (C) 1987-2025 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 <https://www.gnu.org/licenses/>. */ | |
| /* The official name of this program (e.g., no 'g' prefix). */ | |
| /* If true, interpret backslash escapes by default. */ | |
| enum { DEFAULT_ECHO_TO_XPG = false }; | |
| void | |
| usage (int status) | |
| { | |
| /* STATUS should always be EXIT_SUCCESS (unlike in most other | |
| utilities which would call emit_try_help otherwise). */ | |
| affirm (status == EXIT_SUCCESS); | |
| 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\ | |
| "), stdout); | |
| fputs (_("\ | |
| \\\\ backslash\n\ | |
| \\a alert (BEL)\n\ | |
| \\b backspace\n\ | |
| \\c produce no further output\n\ | |
| \\e escape\n\ | |
| \\f form feed\n\ | |
| \\n new line\n\ | |
| \\r carriage return\n\ | |
| \\t horizontal tab\n\ | |
| \\v vertical tab\n\ | |
| "), stdout); | |
| fputs (_("\ | |
| \\0NNN byte with octal value NNN (1 to 3 digits)\n\ | |
| \\xHH byte with hexadecimal value HH (1 to 2 digits)\n\ | |
| "), stdout); | |
| printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME); | |
| fputs (_("\n\ | |
| Consider using the printf(1) command instead,\n\ | |
| as it avoids problems when outputting option-like strings.\n\ | |
| "), stdout); | |
| emit_ancillary_info (PROGRAM_NAME); | |
| 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 posixly_correct = !!getenv ("POSIXLY_CORRECT"); | |
| bool allow_options = | |
| (! 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 *) nullptr); | |
| return 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 || posixly_correct) | |
| { | |
| 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': return EXIT_SUCCESS; | |
| case 'e': c = '\x1B'; break; | |
| 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 (! c_isxdigit (ch)) | |
| goto not_an_escape; | |
| s++; | |
| c = hextobin (ch); | |
| ch = *s; | |
| if (c_isxdigit (ch)) | |
| { | |
| s++; | |
| c = c * 16 + hextobin (ch); | |
| } | |
| } | |
| break; | |
| case '0': | |
| c = 0; | |
| if (! ('0' <= *s && *s <= '7')) | |
| break; | |
| c = *s++; | |
| FALLTHROUGH; | |
| 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'); | |
| return EXIT_SUCCESS; | |
| } | |