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