]>
Commit | Line | Data |
---|---|---|
28f540f4 RM |
1 | /* @(#)rpc_scan.c 2.1 88/08/01 4.0 RPCSRC */ |
2 | /* | |
3 | * Sun RPC is a product of Sun Microsystems, Inc. and is provided for | |
4 | * unrestricted use provided that this legend is included on all tape | |
5 | * media and as a part of the software program in whole or part. Users | |
6 | * may copy or modify Sun RPC without charge, but are not authorized | |
7 | * to license or distribute it to anyone else except as part of a product or | |
8 | * program developed by the user. | |
9 | * | |
10 | * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE | |
11 | * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR | |
12 | * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. | |
13 | * | |
14 | * Sun RPC is provided with no support and without any obligation on the | |
15 | * part of Sun Microsystems, Inc. to assist in its use, correction, | |
16 | * modification or enhancement. | |
17 | * | |
18 | * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE | |
19 | * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC | |
20 | * OR ANY PART THEREOF. | |
21 | * | |
22 | * In no event will Sun Microsystems, Inc. be liable for any lost revenue | |
23 | * or profits or other special, indirect and consequential damages, even if | |
24 | * Sun has been advised of the possibility of such damages. | |
25 | * | |
26 | * Sun Microsystems, Inc. | |
27 | * 2550 Garcia Avenue | |
28 | * Mountain View, California 94043 | |
29 | */ | |
30 | #ifndef lint | |
31 | static char sccsid[] = "@(#)rpc_scan.c 1.6 87/06/24 (C) 1987 SMI"; | |
32 | #endif | |
33 | ||
34 | /* | |
35 | * rpc_scan.c, Scanner for the RPC protocol compiler | |
36 | * Copyright (C) 1987, Sun Microsystems, Inc. | |
37 | */ | |
38 | #include <stdio.h> | |
39 | #include <ctype.h> | |
40 | #include <strings.h> | |
41 | #include "rpc_scan.h" | |
42 | #include "rpc_util.h" | |
43 | ||
44 | #define startcomment(where) (where[0] == '/' && where[1] == '*') | |
45 | #define endcomment(where) (where[-1] == '*' && where[0] == '/') | |
46 | ||
47 | static int pushed = 0; /* is a token pushed */ | |
48 | static token lasttok; /* last token, if pushed */ | |
49 | ||
50 | /* | |
51 | * scan expecting 1 given token | |
52 | */ | |
53 | void | |
54 | scan(expect, tokp) | |
55 | tok_kind expect; | |
56 | token *tokp; | |
57 | { | |
58 | get_token(tokp); | |
59 | if (tokp->kind != expect) { | |
60 | expected1(expect); | |
61 | } | |
62 | } | |
63 | ||
64 | /* | |
65 | * scan expecting 2 given tokens | |
66 | */ | |
67 | void | |
68 | scan2(expect1, expect2, tokp) | |
69 | tok_kind expect1; | |
70 | tok_kind expect2; | |
71 | token *tokp; | |
72 | { | |
73 | get_token(tokp); | |
74 | if (tokp->kind != expect1 && tokp->kind != expect2) { | |
75 | expected2(expect1, expect2); | |
76 | } | |
77 | } | |
78 | ||
79 | /* | |
80 | * scan expecting 3 given token | |
81 | */ | |
82 | void | |
83 | scan3(expect1, expect2, expect3, tokp) | |
84 | tok_kind expect1; | |
85 | tok_kind expect2; | |
86 | tok_kind expect3; | |
87 | token *tokp; | |
88 | { | |
89 | get_token(tokp); | |
90 | if (tokp->kind != expect1 && tokp->kind != expect2 | |
91 | && tokp->kind != expect3) { | |
92 | expected3(expect1, expect2, expect3); | |
93 | } | |
94 | } | |
95 | ||
96 | ||
97 | /* | |
98 | * scan expecting a constant, possibly symbolic | |
99 | */ | |
100 | void | |
101 | scan_num(tokp) | |
102 | token *tokp; | |
103 | { | |
104 | get_token(tokp); | |
105 | switch (tokp->kind) { | |
106 | case TOK_IDENT: | |
107 | break; | |
108 | default: | |
109 | error("constant or identifier expected"); | |
110 | } | |
111 | } | |
112 | ||
113 | ||
114 | /* | |
115 | * Peek at the next token | |
116 | */ | |
117 | void | |
118 | peek(tokp) | |
119 | token *tokp; | |
120 | { | |
121 | get_token(tokp); | |
122 | unget_token(tokp); | |
123 | } | |
124 | ||
125 | ||
126 | /* | |
127 | * Peek at the next token and scan it if it matches what you expect | |
128 | */ | |
129 | int | |
130 | peekscan(expect, tokp) | |
131 | tok_kind expect; | |
132 | token *tokp; | |
133 | { | |
134 | peek(tokp); | |
135 | if (tokp->kind == expect) { | |
136 | get_token(tokp); | |
137 | return (1); | |
138 | } | |
139 | return (0); | |
140 | } | |
141 | ||
142 | ||
143 | ||
144 | /* | |
145 | * Get the next token, printing out any directive that are encountered. | |
146 | */ | |
147 | void | |
148 | get_token(tokp) | |
149 | token *tokp; | |
150 | { | |
151 | int commenting; | |
152 | ||
153 | if (pushed) { | |
154 | pushed = 0; | |
155 | *tokp = lasttok; | |
156 | return; | |
157 | } | |
158 | commenting = 0; | |
159 | for (;;) { | |
160 | if (*where == 0) { | |
161 | for (;;) { | |
162 | if (!fgets(curline, MAXLINESIZE, fin)) { | |
163 | tokp->kind = TOK_EOF; | |
164 | *where = 0; | |
165 | return; | |
166 | } | |
167 | linenum++; | |
168 | if (commenting) { | |
169 | break; | |
170 | } else if (cppline(curline)) { | |
171 | docppline(curline, &linenum, | |
172 | &infilename); | |
173 | } else if (directive(curline)) { | |
174 | printdirective(curline); | |
175 | } else { | |
176 | break; | |
177 | } | |
178 | } | |
179 | where = curline; | |
180 | } else if (isspace(*where)) { | |
181 | while (isspace(*where)) { | |
182 | where++; /* eat */ | |
183 | } | |
184 | } else if (commenting) { | |
185 | where++; | |
186 | if (endcomment(where)) { | |
187 | where++; | |
188 | commenting--; | |
189 | } | |
190 | } else if (startcomment(where)) { | |
191 | where += 2; | |
192 | commenting++; | |
193 | } else { | |
194 | break; | |
195 | } | |
196 | } | |
197 | ||
198 | /* | |
199 | * 'where' is not whitespace, comment or directive Must be a token! | |
200 | */ | |
201 | switch (*where) { | |
202 | case ':': | |
203 | tokp->kind = TOK_COLON; | |
204 | where++; | |
205 | break; | |
206 | case ';': | |
207 | tokp->kind = TOK_SEMICOLON; | |
208 | where++; | |
209 | break; | |
210 | case ',': | |
211 | tokp->kind = TOK_COMMA; | |
212 | where++; | |
213 | break; | |
214 | case '=': | |
215 | tokp->kind = TOK_EQUAL; | |
216 | where++; | |
217 | break; | |
218 | case '*': | |
219 | tokp->kind = TOK_STAR; | |
220 | where++; | |
221 | break; | |
222 | case '[': | |
223 | tokp->kind = TOK_LBRACKET; | |
224 | where++; | |
225 | break; | |
226 | case ']': | |
227 | tokp->kind = TOK_RBRACKET; | |
228 | where++; | |
229 | break; | |
230 | case '{': | |
231 | tokp->kind = TOK_LBRACE; | |
232 | where++; | |
233 | break; | |
234 | case '}': | |
235 | tokp->kind = TOK_RBRACE; | |
236 | where++; | |
237 | break; | |
238 | case '(': | |
239 | tokp->kind = TOK_LPAREN; | |
240 | where++; | |
241 | break; | |
242 | case ')': | |
243 | tokp->kind = TOK_RPAREN; | |
244 | where++; | |
245 | break; | |
246 | case '<': | |
247 | tokp->kind = TOK_LANGLE; | |
248 | where++; | |
249 | break; | |
250 | case '>': | |
251 | tokp->kind = TOK_RANGLE; | |
252 | where++; | |
253 | break; | |
254 | ||
255 | case '"': | |
256 | tokp->kind = TOK_STRCONST; | |
257 | findstrconst(&where, &tokp->str); | |
258 | break; | |
259 | ||
260 | case '-': | |
261 | case '0': | |
262 | case '1': | |
263 | case '2': | |
264 | case '3': | |
265 | case '4': | |
266 | case '5': | |
267 | case '6': | |
268 | case '7': | |
269 | case '8': | |
270 | case '9': | |
271 | tokp->kind = TOK_IDENT; | |
272 | findconst(&where, &tokp->str); | |
273 | break; | |
274 | ||
275 | ||
276 | default: | |
277 | if (!(isalpha(*where) || *where == '_')) { | |
278 | char buf[100]; | |
279 | char *p; | |
280 | ||
281 | s_print(buf, "illegal character in file: "); | |
282 | p = buf + strlen(buf); | |
283 | if (isprint(*where)) { | |
284 | s_print(p, "%c", *where); | |
285 | } else { | |
286 | s_print(p, "%d", *where); | |
287 | } | |
288 | error(buf); | |
289 | } | |
290 | findkind(&where, tokp); | |
291 | break; | |
292 | } | |
293 | } | |
294 | ||
295 | ||
296 | ||
297 | static | |
298 | unget_token(tokp) | |
299 | token *tokp; | |
300 | { | |
301 | lasttok = *tokp; | |
302 | pushed = 1; | |
303 | } | |
304 | ||
305 | ||
306 | static | |
307 | findstrconst(str, val) | |
308 | char **str; | |
309 | char **val; | |
310 | { | |
311 | char *p; | |
312 | int size; | |
313 | ||
314 | p = *str; | |
315 | do { | |
316 | *p++; | |
317 | } while (*p && *p != '"'); | |
318 | if (*p == 0) { | |
319 | error("unterminated string constant"); | |
320 | } | |
321 | p++; | |
322 | size = p - *str; | |
323 | *val = alloc(size + 1); | |
324 | (void) strncpy(*val, *str, size); | |
325 | (*val)[size] = 0; | |
326 | *str = p; | |
327 | } | |
328 | ||
329 | static | |
330 | findconst(str, val) | |
331 | char **str; | |
332 | char **val; | |
333 | { | |
334 | char *p; | |
335 | int size; | |
336 | ||
337 | p = *str; | |
338 | if (*p == '0' && *(p + 1) == 'x') { | |
339 | p++; | |
340 | do { | |
341 | p++; | |
342 | } while (isxdigit(*p)); | |
343 | } else { | |
344 | do { | |
345 | p++; | |
346 | } while (isdigit(*p)); | |
347 | } | |
348 | size = p - *str; | |
349 | *val = alloc(size + 1); | |
350 | (void) strncpy(*val, *str, size); | |
351 | (*val)[size] = 0; | |
352 | *str = p; | |
353 | } | |
354 | ||
355 | ||
356 | ||
357 | static token symbols[] = { | |
358 | {TOK_CONST, "const"}, | |
359 | {TOK_UNION, "union"}, | |
360 | {TOK_SWITCH, "switch"}, | |
361 | {TOK_CASE, "case"}, | |
362 | {TOK_DEFAULT, "default"}, | |
363 | {TOK_STRUCT, "struct"}, | |
364 | {TOK_TYPEDEF, "typedef"}, | |
365 | {TOK_ENUM, "enum"}, | |
366 | {TOK_OPAQUE, "opaque"}, | |
367 | {TOK_BOOL, "bool"}, | |
368 | {TOK_VOID, "void"}, | |
369 | {TOK_CHAR, "char"}, | |
370 | {TOK_INT, "int"}, | |
371 | {TOK_UNSIGNED, "unsigned"}, | |
372 | {TOK_SHORT, "short"}, | |
373 | {TOK_LONG, "long"}, | |
374 | {TOK_FLOAT, "float"}, | |
375 | {TOK_DOUBLE, "double"}, | |
376 | {TOK_STRING, "string"}, | |
377 | {TOK_PROGRAM, "program"}, | |
378 | {TOK_VERSION, "version"}, | |
379 | {TOK_EOF, "??????"}, | |
380 | }; | |
381 | ||
382 | ||
383 | static | |
384 | findkind(mark, tokp) | |
385 | char **mark; | |
386 | token *tokp; | |
387 | { | |
388 | ||
389 | int len; | |
390 | token *s; | |
391 | char *str; | |
392 | ||
393 | str = *mark; | |
394 | for (s = symbols; s->kind != TOK_EOF; s++) { | |
395 | len = strlen(s->str); | |
396 | if (strncmp(str, s->str, len) == 0) { | |
397 | if (!isalnum(str[len]) && str[len] != '_') { | |
398 | tokp->kind = s->kind; | |
399 | tokp->str = s->str; | |
400 | *mark = str + len; | |
401 | return; | |
402 | } | |
403 | } | |
404 | } | |
405 | tokp->kind = TOK_IDENT; | |
406 | for (len = 0; isalnum(str[len]) || str[len] == '_'; len++); | |
407 | tokp->str = alloc(len + 1); | |
408 | (void) strncpy(tokp->str, str, len); | |
409 | tokp->str[len] = 0; | |
410 | *mark = str + len; | |
411 | } | |
412 | ||
413 | static | |
414 | cppline(line) | |
415 | char *line; | |
416 | { | |
417 | return (line == curline && *line == '#'); | |
418 | } | |
419 | ||
420 | static | |
421 | directive(line) | |
422 | char *line; | |
423 | { | |
424 | return (line == curline && *line == '%'); | |
425 | } | |
426 | ||
427 | static | |
428 | printdirective(line) | |
429 | char *line; | |
430 | { | |
431 | f_print(fout, "%s", line + 1); | |
432 | } | |
433 | ||
434 | static | |
435 | docppline(line, lineno, fname) | |
436 | char *line; | |
437 | int *lineno; | |
438 | char **fname; | |
439 | { | |
440 | char *file; | |
441 | int num; | |
442 | char *p; | |
443 | ||
444 | line++; | |
445 | while (isspace(*line)) { | |
446 | line++; | |
447 | } | |
448 | num = atoi(line); | |
449 | while (isdigit(*line)) { | |
450 | line++; | |
451 | } | |
452 | while (isspace(*line)) { | |
453 | line++; | |
454 | } | |
455 | if (*line != '"') { | |
456 | error("preprocessor error"); | |
457 | } | |
458 | line++; | |
459 | p = file = alloc(strlen(line) + 1); | |
460 | while (*line && *line != '"') { | |
461 | *p++ = *line++; | |
462 | } | |
463 | if (*line == 0) { | |
464 | error("preprocessor error"); | |
465 | } | |
466 | *p = 0; | |
467 | if (*file == 0) { | |
468 | *fname = NULL; | |
469 | } else { | |
470 | *fname = file; | |
471 | } | |
472 | *lineno = num - 1; | |
473 | } |