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