summaryrefslogtreecommitdiffstats
path: root/lib/support/cstring.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/support/cstring.c')
-rw-r--r--lib/support/cstring.c162
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