xref: /netbsd-src/usr.bin/rpcgen/rpc_parse.c (revision 76dfffe33547c37f8bdd446e3e4ab0f3c16cea4b)
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