1 /*
2 * cstring.c -- parse and print strings using the C escape sequences
3 */
4
5 #include "config.h"
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <ctype.h>
9 #ifdef HAVE_GETOPT_H
10 #include <getopt.h>
11 #endif
12 #include <string.h>
13
14 #include "cstring.h"
15
parse_c_string(char * str)16 int parse_c_string(char *str)
17 {
18 char *to, *from, ch;
19 int v;
20
21 to = from = str;
22
23 for (to = from = (char *) str;
24 *from && *from != '"'; to++, from++) {
25 if (*from == '\\') {
26 ch = *(++from);
27 switch (ch) {
28 case 'a':
29 *to = '\a';
30 break;
31 case 'b':
32 *to = '\b';
33 break;
34 case 'f':
35 *to = '\f';
36 break;
37 case 'n':
38 *to = '\n';
39 break;
40 case 't':
41 *to = '\t';
42 break;
43 case 'v':
44 *to = '\v';
45 break;
46 case 'x':
47 ch = *(from + 1);
48 if (ch >= 'a' && ch <= 'f')
49 ch = ch - 'a' + 'A';
50 if (ch >= '0' && ch <= '9')
51 v = ch - '0';
52 else if (ch >= 'A' && ch <= 'F')
53 v = ch + 10 - 'A';
54 else {
55 *to = 'x';
56 break;
57 }
58 from++;
59 ch = *(from + 1);
60 if (ch >= 'a' && ch <= 'f')
61 ch = ch - 'a' + 'A';
62 if (ch >= '0' && ch <= '9')
63 v = (v * 16) + (ch - '0');
64 else if (ch >= 'A' && ch <= 'F')
65 v = (v * 16) + (ch + 10 - 'A');
66 else {
67 *to = 'x';
68 from--;
69 break;
70 }
71 from++;
72 *to = v;
73 break;
74 default:
75 if (ch >= '0' && ch <= '9') {
76 v = ch - '0';
77 ch = *(from + 1);
78 if (ch >= '0' && ch <= '9') {
79 from++;
80 v = (8 * v) + (ch - '0');
81 ch = *(from + 1);
82 if (ch >= '0' && ch <= '9') {
83 from++;
84 v = (8 * v) + (ch - '0');
85 }
86 }
87 ch = v;
88 }
89 *to = ch;
90 }
91 continue;
92 }
93 *to = *from;
94 }
95 *to = '\0';
96 return to - (char *) str;
97 }
98
print_c_string(FILE * f,const char * cp,int len)99 void print_c_string(FILE *f, const char *cp, int len)
100 {
101 unsigned char ch;
102
103 if (len < 0)
104 len = strlen(cp);
105
106 while (len--) {
107 ch = *cp++;
108 if (ch == '\a')
109 fputs("\\a", f);
110 else if (ch == '\b')
111 fputs("\\b", f);
112 else if (ch == '\f')
113 fputs("\\f", f);
114 else if (ch == '\n')
115 fputs("\\n", f);
116 else if (ch == '\t')
117 fputs("\\t", f);
118 else if (ch == '\v')
119 fputs("\\v", f);
120 else if (ch == '\\')
121 fputs("\\\\", f);
122 else if (ch == '\'')
123 fputs("\\\'", f);
124 else if (ch == '\"')
125 fputs("\\\"", f);
126 else if ((ch < 32) || (ch > 126))
127 fprintf(f, "\\%03o", ch);
128 else
129 fputc(ch, f);
130 }
131 }
132
133 #ifdef DEBUG_PROGRAM
main(int argc,char ** argv)134 int main(int argc, char **argv)
135 {
136 char buf[4096];
137 int c, raw = 0;
138
139 while ((c = getopt(argc, argv, "r")) != EOF) {
140 switch (c) {
141 case 'r':
142 raw++;
143 break;
144 default:
145 fprintf(stderr, "Usage: %s [-r]\n", argv[0]);
146 exit(1);
147 }
148 }
149
150 while (!feof(stdin)) {
151 if (fgets(buf, sizeof(buf), stdin) == NULL)
152 break;
153 c = parse_c_string(buf);
154 if (raw)
155 fputs(buf, stdout);
156 else {
157 print_c_string(stdout, buf, c);
158 printf(" <%d>\n", c);
159 }
160 }
161 }
162 #endif
163