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