Created
October 26, 2014 16:05
-
-
Save clausecker/a374850ed3c869731c14 to your computer and use it in GitHub Desktop.
My implementation of echo(1)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /*- | |
| * Copyright (c) 2014 Robert Clausecker <[email protected]> | |
| */ | |
| #define _POSIX_C_SOURCE 200809L | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include "err.h" | |
| extern int main(int, char*[]); | |
| static const char *escape(const char*); | |
| static void put(int); | |
| /* | |
| * Implementation of echo(1) according to IEEE Std 1003.1, 2013 edition. | |
| * This implementation implements the behavior for -n an \ as specified for | |
| * XSI-conformant systems and outputs unrecognized escape sequences unchanged. | |
| */ | |
| extern int | |
| main(int argc, char *argv[]) | |
| { | |
| int i; | |
| const char *arg; | |
| setprogname(argv[0]); | |
| for (i = 1; i < argc; i++) { | |
| if (i > 1) | |
| put(' '); | |
| for (arg = argv[i]; *arg != '\0'; arg++) | |
| if (*arg == '\\') { | |
| if ((arg = escape(arg)) == NULL) | |
| goto printing_done; | |
| } else | |
| put(*arg); | |
| } | |
| put('\n'); | |
| printing_done: | |
| if (fflush(stdout) == EOF) | |
| /* LOCALIZE */ | |
| err(1, "Error writing to stdout"); | |
| return (0); | |
| } | |
| /* | |
| * expand the first escape sequence that makes up the beginning of arg and | |
| * print the expansion onto stdout. Return a pointer to the last character in | |
| * the escape sequence, or NULL if the escape sequence is \c. | |
| */ | |
| static const char* | |
| escape(const char *arg) | |
| { | |
| /* lookup table for escape sequences */ | |
| static const char esctab[] = { | |
| ['\\' - '\\'] = '\\', | |
| ['a' - '\\'] = '\a', | |
| ['b' - '\\'] = '\b', | |
| ['f' - '\\'] = '\f', | |
| ['n' - '\\'] = '\n', | |
| ['r' - '\\'] = '\r', | |
| ['v' - '\\'] = '\v', | |
| }; | |
| int i, codepoint = 0; | |
| ++arg; /* assume *arg == '\\' */ | |
| /* *arg in esctab? */ | |
| if (*arg >= '\\' && *arg <= 'v' && esctab[*arg - '\\'] != 0) { | |
| put(esctab[*arg - '\\']); | |
| return (arg); | |
| } | |
| /* octal escape? */ | |
| if (*arg == '0') { | |
| for (i = 0; i < 3; i++) { | |
| ++arg; | |
| if ('0' <= *arg && *arg <= '7') | |
| codepoint = codepoint * 8 + (*arg - '0'); | |
| else | |
| break; | |
| } | |
| put(codepoint); | |
| return (arg); | |
| } | |
| /* end of input? */ | |
| if (*arg == 'c') | |
| return (NULL); | |
| /* unknown escape */ | |
| put('\\'); | |
| put(*arg); | |
| return (arg); | |
| } | |
| /* | |
| * putchar() wrapped to exit the program on IO-error. | |
| */ | |
| static void | |
| put(int c) | |
| { | |
| if (putchar(c) == EOF) | |
| /* LOCALIZE */ | |
| err(1, "Error writing to stdout"); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment