rpc_parse.c revision 1.5 1 /* $NetBSD: rpc_parse.c,v 1.5 1995/08/29 23:05:55 cgd 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 #ifndef lint
33 static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI";
34 #endif
35
36 /*
37 * rpc_parse.c, Parser for the RPC protocol compiler
38 * Copyright (C) 1987 Sun Microsystems, Inc.
39 */
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include "rpc/types.h"
44 #include "rpc_scan.h"
45 #include "rpc_parse.h"
46 #include "rpc_util.h"
47
48 #define ARGNAME "arg"
49
50 static isdefined __P((definition *));
51 static def_struct __P((definition *));
52 static def_program __P((definition *));
53 static def_enum __P((definition *));
54 static def_const __P((definition *));
55 static def_union __P((definition *));
56 static def_typedef __P((definition *));
57 static get_declaration __P((declaration *, defkind));
58 static get_prog_declaration __P((declaration *, defkind, int));
59 static get_type __P((char **, char **, defkind));
60 static unsigned_dec __P((char **));
61
62 /*
63 * return the next definition you see
64 */
65 definition *
66 get_definition()
67 {
68 definition *defp;
69 token tok;
70
71 defp = ALLOC(definition);
72 get_token(&tok);
73 switch (tok.kind) {
74 case TOK_STRUCT:
75 def_struct(defp);
76 break;
77 case TOK_UNION:
78 def_union(defp);
79 break;
80 case TOK_TYPEDEF:
81 def_typedef(defp);
82 break;
83 case TOK_ENUM:
84 def_enum(defp);
85 break;
86 case TOK_PROGRAM:
87 def_program(defp);
88 break;
89 case TOK_CONST:
90 def_const(defp);
91 break;
92 case TOK_EOF:
93 return (NULL);
94 default:
95 error("definition keyword expected");
96 }
97 scan(TOK_SEMICOLON, &tok);
98 isdefined(defp);
99 return (defp);
100 }
101
102 static
103 isdefined(defp)
104 definition *defp;
105 {
106 STOREVAL(&defined, defp);
107 }
108
109 static
110 def_struct(defp)
111 definition *defp;
112 {
113 token tok;
114 declaration dec;
115 decl_list *decls;
116 decl_list **tailp;
117
118 defp->def_kind = DEF_STRUCT;
119
120 scan(TOK_IDENT, &tok);
121 defp->def_name = tok.str;
122 scan(TOK_LBRACE, &tok);
123 tailp = &defp->def.st.decls;
124 do {
125 get_declaration(&dec, DEF_STRUCT);
126 decls = ALLOC(decl_list);
127 decls->decl = dec;
128 *tailp = decls;
129 tailp = &decls->next;
130 scan(TOK_SEMICOLON, &tok);
131 peek(&tok);
132 } while (tok.kind != TOK_RBRACE);
133 get_token(&tok);
134 *tailp = NULL;
135 }
136
137 static
138 def_program(defp)
139 definition *defp;
140 {
141 token tok;
142 declaration dec;
143 decl_list *decls;
144 decl_list **tailp;
145 version_list *vlist;
146 version_list **vtailp;
147 proc_list *plist;
148 proc_list **ptailp;
149 int num_args;
150 bool_t isvoid = FALSE; /* whether first argument is void */
151 defp->def_kind = DEF_PROGRAM;
152 scan(TOK_IDENT, &tok);
153 defp->def_name = tok.str;
154 scan(TOK_LBRACE, &tok);
155 vtailp = &defp->def.pr.versions;
156 tailp = &defp->def.st.decls;
157 scan(TOK_VERSION, &tok);
158 do {
159 scan(TOK_IDENT, &tok);
160 vlist = ALLOC(version_list);
161 vlist->vers_name = tok.str;
162 scan(TOK_LBRACE, &tok);
163 ptailp = &vlist->procs;
164 do {
165 /* get result type */
166 plist = ALLOC(proc_list);
167 get_type(&plist->res_prefix, &plist->res_type,
168 DEF_PROGRAM);
169 if (streq(plist->res_type, "opaque")) {
170 error("illegal result type");
171 }
172 scan(TOK_IDENT, &tok);
173 plist->proc_name = tok.str;
174 scan(TOK_LPAREN, &tok);
175 /* get args - first one*/
176 num_args = 1;
177 isvoid = FALSE;
178 /* type of DEF_PROGRAM in the first
179 * get_prog_declaration and DEF_STURCT in the next
180 * allows void as argument if it is the only argument
181 */
182 get_prog_declaration(&dec, DEF_PROGRAM, num_args);
183 if (streq(dec.type, "void"))
184 isvoid = TRUE;
185 decls = ALLOC(decl_list);
186 plist->args.decls = decls;
187 decls->decl = dec;
188 tailp = &decls->next;
189 /* get args */
190 while(peekscan(TOK_COMMA, &tok)) {
191 num_args++;
192 get_prog_declaration(&dec, DEF_STRUCT,
193 num_args);
194 decls = ALLOC(decl_list);
195 decls->decl = dec;
196 *tailp = decls;
197 if (streq(dec.type, "void"))
198 isvoid = TRUE;
199 tailp = &decls->next;
200 }
201 /* multiple arguments are only allowed in newstyle */
202 if( !newstyle && num_args > 1 ) {
203 error("only one argument is allowed" );
204 }
205 if (isvoid && num_args > 1) {
206 error("illegal use of void in program definition");
207 }
208 *tailp = NULL;
209 scan(TOK_RPAREN, &tok);
210 scan(TOK_EQUAL, &tok);
211 scan_num(&tok);
212 scan(TOK_SEMICOLON, &tok);
213 plist->proc_num = tok.str;
214 plist->arg_num = num_args;
215 *ptailp = plist;
216 ptailp = &plist->next;
217 peek(&tok);
218 } while (tok.kind != TOK_RBRACE);
219 *ptailp = NULL;
220 *vtailp = vlist;
221 vtailp = &vlist->next;
222 scan(TOK_RBRACE, &tok);
223 scan(TOK_EQUAL, &tok);
224 scan_num(&tok);
225 vlist->vers_num = tok.str;
226 /* make the argument structure name for each arg*/
227 for(plist = vlist->procs; plist != NULL;
228 plist = plist->next) {
229 plist->args.argname = make_argname(plist->proc_name,
230 vlist->vers_num);
231 /* free the memory ??*/
232 }
233 scan(TOK_SEMICOLON, &tok);
234 scan2(TOK_VERSION, TOK_RBRACE, &tok);
235 } while (tok.kind == TOK_VERSION);
236 scan(TOK_EQUAL, &tok);
237 scan_num(&tok);
238 defp->def.pr.prog_num = tok.str;
239 *vtailp = NULL;
240 }
241
242
243 static
244 def_enum(defp)
245 definition *defp;
246 {
247 token tok;
248 enumval_list *elist;
249 enumval_list **tailp;
250
251 defp->def_kind = DEF_ENUM;
252 scan(TOK_IDENT, &tok);
253 defp->def_name = tok.str;
254 scan(TOK_LBRACE, &tok);
255 tailp = &defp->def.en.vals;
256 do {
257 scan(TOK_IDENT, &tok);
258 elist = ALLOC(enumval_list);
259 elist->name = tok.str;
260 elist->assignment = NULL;
261 scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
262 if (tok.kind == TOK_EQUAL) {
263 scan_num(&tok);
264 elist->assignment = tok.str;
265 scan2(TOK_COMMA, TOK_RBRACE, &tok);
266 }
267 *tailp = elist;
268 tailp = &elist->next;
269 } while (tok.kind != TOK_RBRACE);
270 *tailp = NULL;
271 }
272
273 static
274 def_const(defp)
275 definition *defp;
276 {
277 token tok;
278
279 defp->def_kind = DEF_CONST;
280 scan(TOK_IDENT, &tok);
281 defp->def_name = tok.str;
282 scan(TOK_EQUAL, &tok);
283 scan2(TOK_IDENT, TOK_STRCONST, &tok);
284 defp->def.co = tok.str;
285 }
286
287 static
288 def_union(defp)
289 definition *defp;
290 {
291 token tok;
292 declaration dec;
293 case_list *cases,*tcase;
294 case_list **tailp;
295 int flag;
296
297 defp->def_kind = DEF_UNION;
298 scan(TOK_IDENT, &tok);
299 defp->def_name = tok.str;
300 scan(TOK_SWITCH, &tok);
301 scan(TOK_LPAREN, &tok);
302 get_declaration(&dec, DEF_UNION);
303 defp->def.un.enum_decl = dec;
304 tailp = &defp->def.un.cases;
305 scan(TOK_RPAREN, &tok);
306 scan(TOK_LBRACE, &tok);
307 scan(TOK_CASE, &tok);
308 while (tok.kind == TOK_CASE) {
309 scan2(TOK_IDENT, TOK_CHARCONST, &tok);
310 cases = ALLOC(case_list);
311 cases->case_name = tok.str;
312 scan(TOK_COLON, &tok);
313 /* now peek at next token */
314 flag=0;
315 if(peekscan(TOK_CASE,&tok))
316 {
317
318 do
319 {
320 scan2(TOK_IDENT, TOK_CHARCONST, &tok);
321 cases->contflag=1; /* continued case statement */
322 *tailp = cases;
323 tailp = &cases->next;
324 cases = ALLOC(case_list);
325 cases->case_name = tok.str;
326 scan(TOK_COLON, &tok);
327
328 }while(peekscan(TOK_CASE,&tok));
329 }
330 else
331 if(flag)
332 {
333
334 *tailp = cases;
335 tailp = &cases->next;
336 cases = ALLOC(case_list);
337 };
338
339 get_declaration(&dec, DEF_UNION);
340 cases->case_decl = dec;
341 cases->contflag=0; /* no continued case statement */
342 *tailp = cases;
343 tailp = &cases->next;
344 scan(TOK_SEMICOLON, &tok);
345
346 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
347 }
348 *tailp = NULL;
349 if (tok.kind == TOK_DEFAULT) {
350 scan(TOK_COLON, &tok);
351 get_declaration(&dec, DEF_UNION);
352 defp->def.un.default_decl = ALLOC(declaration);
353 *defp->def.un.default_decl = dec;
354 scan(TOK_SEMICOLON, &tok);
355 scan(TOK_RBRACE, &tok);
356 } else {
357 defp->def.un.default_decl = NULL;
358 }
359 }
360
361 static char* reserved_words[] = {
362 "array",
363 "bytes",
364 "destroy",
365 "free",
366 "getpos",
367 "inline",
368 "pointer",
369 "reference",
370 "setpos",
371 "sizeof",
372 "union",
373 "vector",
374 NULL
375 };
376
377 static char* reserved_types[] = {
378 "opaque",
379 "string",
380 NULL
381 };
382
383 /* check that the given name is not one that would eventually result in
384 xdr routines that would conflict with internal XDR routines. */
385 static check_type_name( name, new_type )
386 int new_type;
387 char* name;
388 {
389 int i;
390 char tmp[100];
391
392 for( i = 0; reserved_words[i] != NULL; i++ ) {
393 if( strcmp( name, reserved_words[i] ) == 0 ) {
394 sprintf(tmp,
395 "illegal (reserved) name :\'%s\' in type definition", name );
396 error(tmp);
397 }
398 }
399 if( new_type ) {
400 for( i = 0; reserved_types[i] != NULL; i++ ) {
401 if( strcmp( name, reserved_types[i] ) == 0 ) {
402 sprintf(tmp,
403 "illegal (reserved) name :\'%s\' in type definition", name );
404 error(tmp);
405 }
406 }
407 }
408 }
409
410 static
411 def_typedef(defp)
412 definition *defp;
413 {
414 declaration dec;
415
416 defp->def_kind = DEF_TYPEDEF;
417 get_declaration(&dec, DEF_TYPEDEF);
418 defp->def_name = dec.name;
419 check_type_name( dec.name, 1 );
420 defp->def.ty.old_prefix = dec.prefix;
421 defp->def.ty.old_type = dec.type;
422 defp->def.ty.rel = dec.rel;
423 defp->def.ty.array_max = dec.array_max;
424 }
425
426 static
427 get_declaration(dec, dkind)
428 declaration *dec;
429 defkind dkind;
430 {
431 token tok;
432
433 get_type(&dec->prefix, &dec->type, dkind);
434 dec->rel = REL_ALIAS;
435 if (streq(dec->type, "void")) {
436 return;
437 }
438
439 check_type_name( dec->type, 0 );
440
441 scan2(TOK_STAR, TOK_IDENT, &tok);
442 if (tok.kind == TOK_STAR) {
443 dec->rel = REL_POINTER;
444 scan(TOK_IDENT, &tok);
445 }
446 dec->name = tok.str;
447 if (peekscan(TOK_LBRACKET, &tok)) {
448 if (dec->rel == REL_POINTER) {
449 error("no array-of-pointer declarations -- use typedef");
450 }
451 dec->rel = REL_VECTOR;
452 scan_num(&tok);
453 dec->array_max = tok.str;
454 scan(TOK_RBRACKET, &tok);
455 } else if (peekscan(TOK_LANGLE, &tok)) {
456 if (dec->rel == REL_POINTER) {
457 error("no array-of-pointer declarations -- use typedef");
458 }
459 dec->rel = REL_ARRAY;
460 if (peekscan(TOK_RANGLE, &tok)) {
461 dec->array_max = "~0"; /* unspecified size, use max */
462 } else {
463 scan_num(&tok);
464 dec->array_max = tok.str;
465 scan(TOK_RANGLE, &tok);
466 }
467 }
468 if (streq(dec->type, "opaque")) {
469 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
470 error("array declaration expected");
471 }
472 } else if (streq(dec->type, "string")) {
473 if (dec->rel != REL_ARRAY) {
474 error("variable-length array declaration expected");
475 }
476 }
477 }
478
479 static
480 get_prog_declaration(dec, dkind, num)
481 declaration *dec;
482 defkind dkind;
483 int num; /* arg number */
484 {
485 token tok;
486 char name[10]; /* argument name */
487
488 if (dkind == DEF_PROGRAM) {
489 peek(&tok);
490 if (tok.kind == TOK_RPAREN) { /* no arguments */
491 dec->rel = REL_ALIAS;
492 dec->type = "void";
493 dec->prefix = NULL;
494 dec->name = NULL;
495 return;
496 }
497 }
498 get_type(&dec->prefix, &dec->type, dkind);
499 dec->rel = REL_ALIAS;
500 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
501 strcpy(name, tok.str);
502 else
503 sprintf(name, "%s%d", ARGNAME, num); /* default name of argument */
504
505 dec->name = (char *)strdup(name);
506
507 if (streq(dec->type, "void")) {
508 return;
509 }
510
511 if (streq(dec->type, "opaque")) {
512 error("opaque -- illegal argument type");
513 }
514 if (peekscan(TOK_STAR, &tok)) {
515 if (streq(dec->type, "string")) {
516 error("pointer to string not allowed in program arguments\n");
517 }
518 dec->rel = REL_POINTER;
519 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
520 dec->name = (char *)strdup(tok.str);
521 }
522 if (peekscan(TOK_LANGLE, &tok)) {
523 if (!streq(dec->type, "string")) {
524 error("arrays cannot be declared as arguments to procedures -- use typedef");
525 }
526 dec->rel = REL_ARRAY;
527 if (peekscan(TOK_RANGLE, &tok)) {
528 dec->array_max = "~0";/* unspecified size, use max */
529 } else {
530 scan_num(&tok);
531 dec->array_max = tok.str;
532 scan(TOK_RANGLE, &tok);
533 }
534 }
535 if (streq(dec->type, "string")) {
536 if (dec->rel != REL_ARRAY) { /* .x specifies just string as
537 * type of argument
538 * - make it string<>
539 */
540 dec->rel = REL_ARRAY;
541 dec->array_max = "~0";/* unspecified size, use max */
542 }
543 }
544 }
545
546
547
548 static
549 get_type(prefixp, typep, dkind)
550 char **prefixp;
551 char **typep;
552 defkind dkind;
553 {
554 token tok;
555
556 *prefixp = NULL;
557 get_token(&tok);
558 switch (tok.kind) {
559 case TOK_IDENT:
560 *typep = tok.str;
561 break;
562 case TOK_STRUCT:
563 case TOK_ENUM:
564 case TOK_UNION:
565 *prefixp = tok.str;
566 scan(TOK_IDENT, &tok);
567 *typep = tok.str;
568 break;
569 case TOK_UNSIGNED:
570 unsigned_dec(typep);
571 break;
572 case TOK_SHORT:
573 *typep = "short";
574 (void) peekscan(TOK_INT, &tok);
575 break;
576 case TOK_LONG:
577 *typep = "long";
578 (void) peekscan(TOK_INT, &tok);
579 break;
580 case TOK_VOID:
581 if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
582 error("voids allowed only inside union and program definitions with one argument");
583 }
584 *typep = tok.str;
585 break;
586 case TOK_STRING:
587 case TOK_OPAQUE:
588 case TOK_CHAR:
589 case TOK_INT:
590 case TOK_FLOAT:
591 case TOK_DOUBLE:
592 case TOK_BOOL:
593 *typep = tok.str;
594 break;
595 default:
596 error("expected type specifier");
597 }
598 }
599
600 static
601 unsigned_dec(typep)
602 char **typep;
603 {
604 token tok;
605
606 peek(&tok);
607 switch (tok.kind) {
608 case TOK_CHAR:
609 get_token(&tok);
610 *typep = "u_char";
611 break;
612 case TOK_SHORT:
613 get_token(&tok);
614 *typep = "u_short";
615 (void) peekscan(TOK_INT, &tok);
616 break;
617 case TOK_LONG:
618 get_token(&tok);
619 *typep = "u_long";
620 (void) peekscan(TOK_INT, &tok);
621 break;
622 case TOK_INT:
623 get_token(&tok);
624 *typep = "u_int";
625 break;
626 default:
627 *typep = "u_int";
628 break;
629 }
630 }
631