Whamcloud - gitweb
Merge branch 'maint' into next
[tools/e2fsprogs.git] / lib / support / cstring.c
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
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
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
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