diff options
Diffstat (limited to 'lib/support/cstring.c')
-rw-r--r-- | lib/support/cstring.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/lib/support/cstring.c b/lib/support/cstring.c new file mode 100644 index 0000000..57f4522 --- /dev/null +++ b/lib/support/cstring.c @@ -0,0 +1,162 @@ +/* + * cstring.c -- parse and print strings using the C escape sequences + */ + +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#endif +#include <string.h> + +#include "cstring.h" + +int parse_c_string(char *str) +{ + char *to, *from, ch; + int v; + + to = from = str; + + for (to = from = (char *) str; + *from && *from != '"'; to++, from++) { + if (*from == '\\') { + ch = *(++from); + switch (ch) { + case 'a': + *to = '\a'; + break; + case 'b': + *to = '\b'; + break; + case 'f': + *to = '\f'; + break; + case 'n': + *to = '\n'; + break; + case 't': + *to = '\t'; + break; + case 'v': + *to = '\v'; + break; + case 'x': + ch = *(from + 1); + if (ch >= 'a' && ch <= 'f') + ch = ch - 'a' + 'A'; + if (ch >= '0' && ch <= '9') + v = ch - '0'; + else if (ch >= 'A' && ch <= 'F') + v = ch + 10 - 'A'; + else { + *to = 'x'; + break; + } + from++; + ch = *(from + 1); + if (ch >= 'a' && ch <= 'f') + ch = ch - 'a' + 'A'; + if (ch >= '0' && ch <= '9') + v = (v * 16) + (ch - '0'); + else if (ch >= 'A' && ch <= 'F') + v = (v * 16) + (ch + 10 - 'A'); + else { + *to = 'x'; + from--; + break; + } + from++; + *to = v; + break; + default: + if (ch >= '0' && ch <= '9') { + v = ch - '0'; + ch = *(from + 1); + if (ch >= '0' && ch <= '9') { + from++; + v = (8 * v) + (ch - '0'); + ch = *(from + 1); + if (ch >= '0' && ch <= '9') { + from++; + v = (8 * v) + (ch - '0'); + } + } + ch = v; + } + *to = ch; + } + continue; + } + *to = *from; + } + *to = '\0'; + return to - (char *) str; +} + +void print_c_string(FILE *f, const char *cp, int len) +{ + unsigned char ch; + + if (len < 0) + len = strlen(cp); + + while (len--) { + ch = *cp++; + if (ch == '\a') + fputs("\\a", f); + else if (ch == '\b') + fputs("\\b", f); + else if (ch == '\f') + fputs("\\f", f); + else if (ch == '\n') + fputs("\\n", f); + else if (ch == '\t') + fputs("\\t", f); + else if (ch == '\v') + fputs("\\v", f); + else if (ch == '\\') + fputs("\\\\", f); + else if (ch == '\'') + fputs("\\\'", f); + else if (ch == '\"') + fputs("\\\"", f); + else if ((ch < 32) || (ch > 126)) + fprintf(f, "\\%03o", ch); + else + fputc(ch, f); + } +} + +#ifdef DEBUG_PROGRAM +int main(int argc, char **argv) +{ + char buf[4096]; + int c, raw = 0; + + while ((c = getopt(argc, argv, "r")) != EOF) { + switch (c) { + case 'r': + raw++; + break; + default: + fprintf(stderr, "Usage: %s [-r]\n", argv[0]); + exit(1); + } + } + + while (!feof(stdin)) { + if (fgets(buf, sizeof(buf), stdin) == NULL) + break; + c = parse_c_string(buf); + if (raw) + fputs(buf, stdout); + else { + print_c_string(stdout, buf, c); + printf(" <%d>\n", c); + } + } +} +#endif |