FreeCalypso > hg > freecalypso-reveng
comparison dspanal/charparse.c @ 308:f8344bc4fd61
dspanal: char2coff utility written, compiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 28 Oct 2019 05:20:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
307:8e816bba2ff7 | 308:f8344bc4fd61 |
---|---|
1 /* | |
2 * This module reads C char array files; it will be linked into programs | |
3 * that do further processing. | |
4 */ | |
5 | |
6 #include <sys/types.h> | |
7 #include <ctype.h> | |
8 #include <stdio.h> | |
9 #include <stdlib.h> | |
10 #include <string.h> | |
11 #include <strings.h> | |
12 | |
13 /* lexer tokens */ | |
14 #define WORD 256 | |
15 #define NUMBER 257 | |
16 #define HEXBYTE 258 | |
17 | |
18 /* limits */ | |
19 #define MAXWORD 63 | |
20 #define MAXDIGITS 5 | |
21 | |
22 static char *parser_filename; | |
23 static FILE *parser_readF; | |
24 static int parser_lineno; | |
25 static char parser_read_word[MAXWORD+1]; | |
26 static int parser_read_number; | |
27 | |
28 static void | |
29 parse_error(msg) | |
30 char *msg; | |
31 { | |
32 fprintf(stderr, "%s line %d: %s\n", parser_filename, parser_lineno, | |
33 msg); | |
34 exit(1); | |
35 } | |
36 | |
37 static | |
38 my_getchar() | |
39 { | |
40 register int c; | |
41 | |
42 c = getc(parser_readF); | |
43 if (c < 0) | |
44 return(c); | |
45 if (!isascii(c)) | |
46 parse_error("non-ASCII character"); | |
47 if (iscntrl(c) && c != '\n' && c != '\t') | |
48 parse_error("invalid control character"); | |
49 return(c); | |
50 } | |
51 | |
52 static void | |
53 handle_trad_comment() | |
54 { | |
55 register int c, flag; | |
56 | |
57 for (flag = 0; ; ) { | |
58 c = my_getchar(); | |
59 if (c < 0) | |
60 parse_error("/* comment ends in EOF"); | |
61 if (c == '\n') | |
62 parser_lineno++; | |
63 if (c == '/' && flag) | |
64 return; | |
65 flag = (c == '*'); | |
66 } | |
67 } | |
68 | |
69 static void | |
70 handle_line_comment() | |
71 { | |
72 register int c; | |
73 | |
74 for (;;) { | |
75 c = my_getchar(); | |
76 if (c < 0) | |
77 parse_error("// comment ends in EOF"); | |
78 if (c == '\n') { | |
79 parser_lineno++; | |
80 return; | |
81 } | |
82 } | |
83 } | |
84 | |
85 static void | |
86 handle_comment() | |
87 { | |
88 int c; | |
89 | |
90 c = my_getchar(); | |
91 switch (c) { | |
92 case '*': | |
93 /* traditional C comment style */ | |
94 handle_trad_comment(); | |
95 return; | |
96 case '/': | |
97 /* new-fangled double slash comment style */ | |
98 handle_line_comment(); | |
99 return; | |
100 default: | |
101 parse_error("character after '/' is not '*' or '/'"); | |
102 exit(1); | |
103 } | |
104 } | |
105 | |
106 static void | |
107 handle_num_token(first_digit) | |
108 { | |
109 register int c, n; | |
110 | |
111 parser_read_number = first_digit - '0'; | |
112 for (n = 1; ; n++) { | |
113 c = my_getchar(); | |
114 if (!isdigit(c)) | |
115 break; | |
116 parser_read_number *= 10; | |
117 parser_read_number += c - '0'; | |
118 } | |
119 if (c >= 0) { | |
120 if (isalpha(c) || c == '_') | |
121 parse_error( | |
122 "digits followed by letters: neither word nor number"); | |
123 ungetc(c, parser_readF); | |
124 } | |
125 if (n > MAXDIGITS) | |
126 parse_error("number is too long (MAXDIGITS exceeded)"); | |
127 } | |
128 | |
129 static int | |
130 decode_hex_digit(c) | |
131 register int c; | |
132 { | |
133 if (isdigit(c)) | |
134 return(c - '0'); | |
135 else if (isupper(c)) | |
136 return(c - 'A' + 10); | |
137 else | |
138 return(c - 'a' + 10); | |
139 } | |
140 | |
141 static void | |
142 handle_hex_token() | |
143 { | |
144 register int c, n; | |
145 | |
146 c = my_getchar(); | |
147 if (c != 'x' && c != 'X') | |
148 parse_error("\'0\' not followed by \'x\'"); | |
149 parser_read_number = 0; | |
150 for (n = 0; n < 2; n++) { | |
151 c = my_getchar(); | |
152 if (!isxdigit(c)) | |
153 parse_error("0x not followed by two hex digits"); | |
154 parser_read_number <<= 4; | |
155 parser_read_number += decode_hex_digit(c); | |
156 } | |
157 } | |
158 | |
159 static void | |
160 handle_word_token(first_char) | |
161 { | |
162 register int c; | |
163 register char *cp; | |
164 register int len; | |
165 | |
166 cp = parser_read_word; | |
167 *cp++ = first_char; | |
168 for (len = 1; ; ) { | |
169 c = my_getchar(); | |
170 if (!isalnum(c) && c != '_') | |
171 break; | |
172 if (len >= MAXWORD) | |
173 parse_error("text token is too long"); | |
174 *cp++ = c; | |
175 len++; | |
176 } | |
177 *cp = '\0'; | |
178 if (c < 0) | |
179 return; | |
180 ungetc(c, parser_readF); | |
181 } | |
182 | |
183 static int | |
184 get_token() | |
185 { | |
186 register int c; | |
187 | |
188 loop: c = my_getchar(); | |
189 switch (c) { | |
190 case EOF: | |
191 return(0); | |
192 case ' ': | |
193 case '\t': | |
194 goto loop; | |
195 case '\n': | |
196 parser_lineno++; | |
197 goto loop; | |
198 case '/': | |
199 handle_comment(); | |
200 goto loop; | |
201 case ',': | |
202 case ';': | |
203 case '=': | |
204 case '[': | |
205 case ']': | |
206 case '{': | |
207 case '}': | |
208 return(c); | |
209 case '0': | |
210 handle_hex_token(); | |
211 return(HEXBYTE); | |
212 } | |
213 if (isdigit(c)) { | |
214 handle_num_token(c); | |
215 return(NUMBER); | |
216 } | |
217 if (isalpha(c) || c == '_') { | |
218 handle_word_token(c); | |
219 return(WORD); | |
220 } | |
221 fprintf(stderr, "%s line %d: bad character \'%c\'\n", parser_filename, | |
222 parser_lineno, c); | |
223 exit(1); | |
224 } | |
225 | |
226 unsigned | |
227 read_char_file(filename, outbuf, buflimit) | |
228 char *filename; | |
229 u_char *outbuf; | |
230 unsigned buflimit; | |
231 { | |
232 register int t; | |
233 u_char *outptr; | |
234 unsigned bytecnt; | |
235 | |
236 parser_filename = filename; | |
237 parser_readF = fopen(parser_filename, "r"); | |
238 if (!parser_readF) { | |
239 perror(parser_filename); | |
240 exit(1); | |
241 } | |
242 parser_lineno = 1; | |
243 t = get_token(); | |
244 if (t != WORD || strcmp(parser_read_word, "const")) | |
245 parse_error("expected \"const\" keyword"); | |
246 t = get_token(); | |
247 if (t != WORD || strcmp(parser_read_word, "unsigned")) | |
248 parse_error("expected \"unsigned\" keyword"); | |
249 t = get_token(); | |
250 if (t != WORD || strcmp(parser_read_word, "char")) | |
251 parse_error("expected \"char\" keyword"); | |
252 t = get_token(); | |
253 if (t != WORD) | |
254 parse_error("expected char array name"); | |
255 t = get_token(); | |
256 if (t != '[') | |
257 parse_error("expected \'[\'"); | |
258 t = get_token(); | |
259 if (t == NUMBER) | |
260 t = get_token(); | |
261 if (t != ']') | |
262 parse_error("expected \']\'"); | |
263 t = get_token(); | |
264 if (t != '=') | |
265 parse_error("expected \'=\'"); | |
266 t = get_token(); | |
267 if (t != '{') | |
268 parse_error("expected \'{\'"); | |
269 /* get first hex byte */ | |
270 t = get_token(); | |
271 if (t != HEXBYTE) | |
272 parse_error("expected first hex byte"); | |
273 outptr = outbuf; | |
274 *outptr++ = parser_read_number; | |
275 bytecnt = 1; | |
276 for (;;) { | |
277 t = get_token(); | |
278 if (t == '}') | |
279 break; | |
280 if (t != ',') | |
281 parse_error("expected comma between bytes"); | |
282 t = get_token(); | |
283 if (t == '}') | |
284 break; | |
285 if (t != HEXBYTE) | |
286 parse_error("expected next hex byte"); | |
287 if (bytecnt >= buflimit) | |
288 parse_error("buffer limit exceeded"); | |
289 *outptr++ = parser_read_number; | |
290 bytecnt++; | |
291 } | |
292 t = get_token(); | |
293 if (t != ';') | |
294 parse_error("expected terminating \';\'"); | |
295 fclose(parser_readF); | |
296 return bytecnt; | |
297 } |