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