|
1 #include <stdio.h> |
|
2 |
|
3 #include "sreplace.h" |
|
4 |
|
5 /* Complete set of backslash sequences: |
|
6 |
|
7 From K&R, The C Programming Language, Chapter 2, Constants. |
|
8 |
|
9 \b backspace |
|
10 \? question mark |
|
11 \f formfeed |
|
12 \' single quote |
|
13 \n newline |
|
14 \" double quote |
|
15 \r carriage return |
|
16 \ooo octal number |
|
17 \t horizontal tab |
|
18 \xhh hexadecimal number |
|
19 \v vertical tab |
|
20 |
|
21 (\\ backslash) |
|
22 */ |
|
23 |
|
24 /* Returns length */ |
|
25 int parse_backslashes(unsigned char *str) |
|
26 { |
|
27 int was_backslash = 0; |
|
28 int was_octal = 0; /* 0 to 3 */ |
|
29 int was_hex = 0; /* 0 to 2 */ |
|
30 unsigned char *write_str = str; |
|
31 unsigned char *start = str; |
|
32 unsigned char newchar; |
|
33 |
|
34 while (*str != 0) |
|
35 { |
|
36 if (*str == '\\' && !was_backslash) |
|
37 was_backslash = 1; |
|
38 else |
|
39 { |
|
40 if (was_octal) |
|
41 { |
|
42 if (was_octal < 3 && *str >= '0' && *str <= '7') |
|
43 { |
|
44 newchar = (newchar * 8) + (*str - '0'); |
|
45 was_octal += 1; |
|
46 if (was_octal == 3) |
|
47 { |
|
48 *(write_str++) = newchar; |
|
49 was_octal = 0; |
|
50 } |
|
51 } else /* Didn't come octal char. End of oct string. */ |
|
52 { |
|
53 *(write_str++) = newchar; |
|
54 *(write_str++) = *str; |
|
55 was_octal = 0; |
|
56 } |
|
57 } |
|
58 else if (was_hex) |
|
59 { |
|
60 unsigned char base = 0; |
|
61 |
|
62 if (*str >= '0' && *str <= '9') |
|
63 base = '0'; |
|
64 else if (*str >= 'a' && *str <= 'f') |
|
65 base = 'a' - 10; |
|
66 else if (*str >= 'A' && *str <= 'F') |
|
67 base = 'A' - 10; |
|
68 |
|
69 if (base != 0) /* Came hex char */ |
|
70 { |
|
71 newchar = (newchar * 16) + (*str - base); |
|
72 was_hex += 1; |
|
73 |
|
74 if (was_hex == 3) /* End of hex string */ |
|
75 { |
|
76 *(write_str++) = newchar; |
|
77 was_hex = 0; |
|
78 } |
|
79 } |
|
80 else /* Non-hex char came. End of hex string */ |
|
81 { |
|
82 *(write_str++) = newchar; |
|
83 *(write_str++) = *str; |
|
84 was_hex = 0; |
|
85 } |
|
86 } |
|
87 else if (was_backslash) |
|
88 { switch(*str) |
|
89 { |
|
90 case '\\': |
|
91 *(write_str++) = '\\'; |
|
92 break; |
|
93 case 'n': |
|
94 *(write_str++) = '\n'; |
|
95 break; |
|
96 case 't': |
|
97 *(write_str++) = '\t'; |
|
98 break; |
|
99 case 'r': |
|
100 *(write_str++) = '\r'; |
|
101 break; |
|
102 case 'v': |
|
103 *(write_str++) = '\v'; |
|
104 break; |
|
105 case 'f': |
|
106 *(write_str++) = '\f'; |
|
107 break; |
|
108 case 'b': |
|
109 *(write_str++) = '\b'; |
|
110 break; |
|
111 case '0': |
|
112 case '1': |
|
113 case '2': |
|
114 case '3': |
|
115 case '4': |
|
116 case '5': |
|
117 case '6': |
|
118 case '7': |
|
119 was_octal = 1; |
|
120 newchar = 0; |
|
121 break; |
|
122 case 'x': |
|
123 was_hex = 1; |
|
124 newchar = 0; |
|
125 break; |
|
126 default: |
|
127 *(write_str++) = *str; |
|
128 } |
|
129 was_backslash = 0; |
|
130 } |
|
131 else |
|
132 *(write_str++) = *str; |
|
133 } |
|
134 ++str; |
|
135 } |
|
136 *(write_str) = '\0'; |
|
137 |
|
138 /* We calculate length with distance between the last |
|
139 * written char and the start of the string */ |
|
140 return write_str - start; |
|
141 } |
|
142 |
|
143 void print_hex(FILE *out, const struct String *str) |
|
144 { |
|
145 int i; |
|
146 |
|
147 fprintf(out, "Length: %i\n", str->length); |
|
148 for (i = 0; i < str->length; ++i) |
|
149 fprintf(out, "%02hhx", str->ptr[i]); |
|
150 } |