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