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