xref: /titanic_53/usr/src/cmd/rpcgen/rpc_parse.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */
28*7c478bd9Sstevel@tonic-gate /*
29*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
30*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
31*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
32*7c478bd9Sstevel@tonic-gate  *
33*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
34*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
35*7c478bd9Sstevel@tonic-gate  * contributors.
36*7c478bd9Sstevel@tonic-gate  */
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate /*
41*7c478bd9Sstevel@tonic-gate  * rpc_parse.c, Parser for the RPC protocol compiler
42*7c478bd9Sstevel@tonic-gate  */
43*7c478bd9Sstevel@tonic-gate #include <stdio.h>
44*7c478bd9Sstevel@tonic-gate #include <string.h>
45*7c478bd9Sstevel@tonic-gate #include "rpc/types.h"
46*7c478bd9Sstevel@tonic-gate #include "rpc_scan.h"
47*7c478bd9Sstevel@tonic-gate #include "rpc_parse.h"
48*7c478bd9Sstevel@tonic-gate #include "rpc_util.h"
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #define	ARGNAME "arg"
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate extern char *make_argname();
53*7c478bd9Sstevel@tonic-gate extern char *strdup();
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate /*
56*7c478bd9Sstevel@tonic-gate  * return the next definition you see
57*7c478bd9Sstevel@tonic-gate  */
58*7c478bd9Sstevel@tonic-gate definition *
59*7c478bd9Sstevel@tonic-gate get_definition()
60*7c478bd9Sstevel@tonic-gate {
61*7c478bd9Sstevel@tonic-gate 	definition *defp;
62*7c478bd9Sstevel@tonic-gate 	token tok;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate 	defp = ALLOC(definition);
65*7c478bd9Sstevel@tonic-gate 	get_token(&tok);
66*7c478bd9Sstevel@tonic-gate 	switch (tok.kind) {
67*7c478bd9Sstevel@tonic-gate 	case TOK_STRUCT:
68*7c478bd9Sstevel@tonic-gate 		def_struct(defp);
69*7c478bd9Sstevel@tonic-gate 		break;
70*7c478bd9Sstevel@tonic-gate 	case TOK_UNION:
71*7c478bd9Sstevel@tonic-gate 		def_union(defp);
72*7c478bd9Sstevel@tonic-gate 		break;
73*7c478bd9Sstevel@tonic-gate 	case TOK_TYPEDEF:
74*7c478bd9Sstevel@tonic-gate 		def_typedef(defp);
75*7c478bd9Sstevel@tonic-gate 		break;
76*7c478bd9Sstevel@tonic-gate 	case TOK_ENUM:
77*7c478bd9Sstevel@tonic-gate 		def_enum(defp);
78*7c478bd9Sstevel@tonic-gate 		break;
79*7c478bd9Sstevel@tonic-gate 	case TOK_PROGRAM:
80*7c478bd9Sstevel@tonic-gate 		def_program(defp);
81*7c478bd9Sstevel@tonic-gate 		break;
82*7c478bd9Sstevel@tonic-gate 	case TOK_CONST:
83*7c478bd9Sstevel@tonic-gate 		def_const(defp);
84*7c478bd9Sstevel@tonic-gate 		break;
85*7c478bd9Sstevel@tonic-gate 	case TOK_EOF:
86*7c478bd9Sstevel@tonic-gate 		return (NULL);
87*7c478bd9Sstevel@tonic-gate 	default:
88*7c478bd9Sstevel@tonic-gate 		error("definition keyword expected");
89*7c478bd9Sstevel@tonic-gate 	}
90*7c478bd9Sstevel@tonic-gate 	scan(TOK_SEMICOLON, &tok);
91*7c478bd9Sstevel@tonic-gate 	isdefined(defp);
92*7c478bd9Sstevel@tonic-gate 	return (defp);
93*7c478bd9Sstevel@tonic-gate }
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate static
96*7c478bd9Sstevel@tonic-gate isdefined(defp)
97*7c478bd9Sstevel@tonic-gate 	definition *defp;
98*7c478bd9Sstevel@tonic-gate {
99*7c478bd9Sstevel@tonic-gate 	STOREVAL(&defined, defp);
100*7c478bd9Sstevel@tonic-gate }
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate /*
103*7c478bd9Sstevel@tonic-gate  * We treat s == NULL the same as *s == '\0'
104*7c478bd9Sstevel@tonic-gate  */
105*7c478bd9Sstevel@tonic-gate streqn(const char *s1, const char *s2)
106*7c478bd9Sstevel@tonic-gate {
107*7c478bd9Sstevel@tonic-gate 	if (s1 == NULL)
108*7c478bd9Sstevel@tonic-gate 		s1 = "";
109*7c478bd9Sstevel@tonic-gate 	if (s2 == NULL)
110*7c478bd9Sstevel@tonic-gate 		s2 = "";
111*7c478bd9Sstevel@tonic-gate 	if (s1 == s2)
112*7c478bd9Sstevel@tonic-gate 		return (1);
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 	return (strcmp(s1, s2) == 0);
115*7c478bd9Sstevel@tonic-gate }
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate static int
118*7c478bd9Sstevel@tonic-gate cmptype(definition *defp, char *type)
119*7c478bd9Sstevel@tonic-gate {
120*7c478bd9Sstevel@tonic-gate 	/* We only want typedef definitions */
121*7c478bd9Sstevel@tonic-gate 	if (streq(defp->def_name, type) && defp->def_kind == DEF_TYPEDEF)
122*7c478bd9Sstevel@tonic-gate 		return (1);
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	return (0);
125*7c478bd9Sstevel@tonic-gate }
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate static int
128*7c478bd9Sstevel@tonic-gate check_self_reference(const char *name, const declaration *decp, int first)
129*7c478bd9Sstevel@tonic-gate {
130*7c478bd9Sstevel@tonic-gate 	/*
131*7c478bd9Sstevel@tonic-gate 	 * Now check for the following special case if first is true:
132*7c478bd9Sstevel@tonic-gate 	 *
133*7c478bd9Sstevel@tonic-gate 	 * struct foo {
134*7c478bd9Sstevel@tonic-gate 	 *	...
135*7c478bd9Sstevel@tonic-gate 	 *	foo *next;
136*7c478bd9Sstevel@tonic-gate 	 * };
137*7c478bd9Sstevel@tonic-gate 	 *
138*7c478bd9Sstevel@tonic-gate 	 *
139*7c478bd9Sstevel@tonic-gate 	 * In the above cases foo has not yet been entered in the type list,
140*7c478bd9Sstevel@tonic-gate 	 * defined. So there is no typedef entry. The prefix in that case
141*7c478bd9Sstevel@tonic-gate 	 * could be empty.
142*7c478bd9Sstevel@tonic-gate 	 */
143*7c478bd9Sstevel@tonic-gate 	if (decp->rel == REL_POINTER &&
144*7c478bd9Sstevel@tonic-gate 	    (streqn(decp->prefix, "struct") ||
145*7c478bd9Sstevel@tonic-gate 	    (first && streqn(decp->prefix, ""))) &&
146*7c478bd9Sstevel@tonic-gate 	    streqn(name, decp->type))
147*7c478bd9Sstevel@tonic-gate 		return (1);
148*7c478bd9Sstevel@tonic-gate 	return (0);
149*7c478bd9Sstevel@tonic-gate }
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate static int
152*7c478bd9Sstevel@tonic-gate is_self_reference(definition *defp, declaration *decp)
153*7c478bd9Sstevel@tonic-gate {
154*7c478bd9Sstevel@tonic-gate 	declaration current;
155*7c478bd9Sstevel@tonic-gate 	definition *dp;
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	if (check_self_reference(defp->def_name, decp, 1))
158*7c478bd9Sstevel@tonic-gate 		return (1);
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	/*
161*7c478bd9Sstevel@tonic-gate 	 * Check for valid declaration:
162*7c478bd9Sstevel@tonic-gate 	 * Only prefixes allowed are none and struct.
163*7c478bd9Sstevel@tonic-gate 	 * Only relations allowed are pointer or alias.
164*7c478bd9Sstevel@tonic-gate 	 */
165*7c478bd9Sstevel@tonic-gate 	if (!streqn(decp->prefix, "struct") && !streqn(decp->prefix, ""))
166*7c478bd9Sstevel@tonic-gate 		return (0);
167*7c478bd9Sstevel@tonic-gate 	if (decp->rel != REL_POINTER && decp->rel != REL_ALIAS)
168*7c478bd9Sstevel@tonic-gate 		return (0);
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate 	current.rel = decp->rel;
171*7c478bd9Sstevel@tonic-gate 	current.prefix = decp->prefix;
172*7c478bd9Sstevel@tonic-gate 	current.type = decp->type;
173*7c478bd9Sstevel@tonic-gate 	current.name = decp->name;
174*7c478bd9Sstevel@tonic-gate 	decp = &current;
175*7c478bd9Sstevel@tonic-gate 	while (!check_self_reference(defp->def_name, decp, 0)) {
176*7c478bd9Sstevel@tonic-gate 		dp = FINDVAL(defined, decp->type, cmptype);
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 		/*
179*7c478bd9Sstevel@tonic-gate 		 * Check if we found a definition.
180*7c478bd9Sstevel@tonic-gate 		 */
181*7c478bd9Sstevel@tonic-gate 		if (dp == NULL)
182*7c478bd9Sstevel@tonic-gate 			return (0);
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 		/*
185*7c478bd9Sstevel@tonic-gate 		 * Check for valid prefix. We eventually need to see one
186*7c478bd9Sstevel@tonic-gate 		 * and only one struct.
187*7c478bd9Sstevel@tonic-gate 		 */
188*7c478bd9Sstevel@tonic-gate 		if (streqn(decp->prefix, "")) {
189*7c478bd9Sstevel@tonic-gate 			/*
190*7c478bd9Sstevel@tonic-gate 			 * If the current declaration prefix in empty
191*7c478bd9Sstevel@tonic-gate 			 * then the definition found must have an empty
192*7c478bd9Sstevel@tonic-gate 			 * prefix or a struct prefix
193*7c478bd9Sstevel@tonic-gate 			 */
194*7c478bd9Sstevel@tonic-gate 			if (!streqn(dp->def.ty.old_prefix, "") &&
195*7c478bd9Sstevel@tonic-gate 			    !streqn(dp->def.ty.old_prefix, "struct"))
196*7c478bd9Sstevel@tonic-gate 				return (0);
197*7c478bd9Sstevel@tonic-gate 		} else if (streqn(decp->prefix, "struct") &&
198*7c478bd9Sstevel@tonic-gate 			!streqn(dp->def.ty.old_prefix, ""))
199*7c478bd9Sstevel@tonic-gate 			/*
200*7c478bd9Sstevel@tonic-gate 			 * if the current prefix is struct tne new prefix
201*7c478bd9Sstevel@tonic-gate 			 * must be empty
202*7c478bd9Sstevel@tonic-gate 			 */
203*7c478bd9Sstevel@tonic-gate 			return (0);
204*7c478bd9Sstevel@tonic-gate 		else if (!streqn(decp->prefix, "struct"))
205*7c478bd9Sstevel@tonic-gate 			/* Should never get here */
206*7c478bd9Sstevel@tonic-gate 			return (0);
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 		/*
209*7c478bd9Sstevel@tonic-gate 		 * Check for valid relation. We need to see one and
210*7c478bd9Sstevel@tonic-gate 		 * only one REL_POINTER. The only valid relation types
211*7c478bd9Sstevel@tonic-gate 		 * are REL_POINTER and REL_ALIAS.
212*7c478bd9Sstevel@tonic-gate 		 */
213*7c478bd9Sstevel@tonic-gate 		if (decp->rel == REL_POINTER && dp->def.ty.rel != REL_ALIAS)
214*7c478bd9Sstevel@tonic-gate 			return (0);
215*7c478bd9Sstevel@tonic-gate 		else if (decp->rel == REL_ALIAS &&
216*7c478bd9Sstevel@tonic-gate 			(dp->def.ty.rel != REL_ALIAS &&
217*7c478bd9Sstevel@tonic-gate 			dp->def.ty.rel != REL_POINTER))
218*7c478bd9Sstevel@tonic-gate 			return (0);
219*7c478bd9Sstevel@tonic-gate 		else if (decp->rel != REL_ALIAS && decp->rel != REL_POINTER)
220*7c478bd9Sstevel@tonic-gate 			/* Should never get here */
221*7c478bd9Sstevel@tonic-gate 			return (0);
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 		/* Set up the current declaration */
224*7c478bd9Sstevel@tonic-gate 		if (streqn(decp->prefix, ""))
225*7c478bd9Sstevel@tonic-gate 			decp->prefix = dp->def.ty.old_prefix;
226*7c478bd9Sstevel@tonic-gate 		decp->type = dp->def.ty.old_type;
227*7c478bd9Sstevel@tonic-gate 		if (decp->rel == REL_ALIAS)
228*7c478bd9Sstevel@tonic-gate 			decp->rel = dp->def.ty.rel;
229*7c478bd9Sstevel@tonic-gate 	}
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	/* We have a self reference type */
232*7c478bd9Sstevel@tonic-gate 	return (1);
233*7c478bd9Sstevel@tonic-gate }
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate static
236*7c478bd9Sstevel@tonic-gate def_struct(defp)
237*7c478bd9Sstevel@tonic-gate 	definition *defp;
238*7c478bd9Sstevel@tonic-gate {
239*7c478bd9Sstevel@tonic-gate 	token tok;
240*7c478bd9Sstevel@tonic-gate 	declaration dec;
241*7c478bd9Sstevel@tonic-gate 	decl_list *decls;
242*7c478bd9Sstevel@tonic-gate 	decl_list **tailp, *endp;
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 	defp->def_kind = DEF_STRUCT;
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	scan(TOK_IDENT, &tok);
247*7c478bd9Sstevel@tonic-gate 	defp->def_name = tok.str;
248*7c478bd9Sstevel@tonic-gate 	scan(TOK_LBRACE, &tok);
249*7c478bd9Sstevel@tonic-gate 	tailp = &defp->def.st.decls;
250*7c478bd9Sstevel@tonic-gate 	defp->def.st.tail = NULL;
251*7c478bd9Sstevel@tonic-gate 	do {
252*7c478bd9Sstevel@tonic-gate 		get_declaration(&dec, DEF_STRUCT);
253*7c478bd9Sstevel@tonic-gate 		decls = ALLOC(decl_list);
254*7c478bd9Sstevel@tonic-gate 		decls->decl = dec;
255*7c478bd9Sstevel@tonic-gate 		/*
256*7c478bd9Sstevel@tonic-gate 		 * Keep a referenct to the last declaration to check for
257*7c478bd9Sstevel@tonic-gate 		 * tail recurrsion.
258*7c478bd9Sstevel@tonic-gate 		 */
259*7c478bd9Sstevel@tonic-gate 		endp = *tailp = decls;
260*7c478bd9Sstevel@tonic-gate 		tailp = &decls->next;
261*7c478bd9Sstevel@tonic-gate 		scan(TOK_SEMICOLON, &tok);
262*7c478bd9Sstevel@tonic-gate 		peek(&tok);
263*7c478bd9Sstevel@tonic-gate 	} while (tok.kind != TOK_RBRACE);
264*7c478bd9Sstevel@tonic-gate 	*tailp = NULL;
265*7c478bd9Sstevel@tonic-gate 	/*
266*7c478bd9Sstevel@tonic-gate 	 * Check for tail recurse. If the last declaration refers to this
267*7c478bd9Sstevel@tonic-gate 	 * structure then mark this stucture to convert the tail recursion
268*7c478bd9Sstevel@tonic-gate 	 * to itteration.
269*7c478bd9Sstevel@tonic-gate 	 */
270*7c478bd9Sstevel@tonic-gate 	defp->def.st.self_pointer = is_self_reference(defp, &endp->decl);
271*7c478bd9Sstevel@tonic-gate 	get_token(&tok);
272*7c478bd9Sstevel@tonic-gate 	defp->def.st.tail = endp;
273*7c478bd9Sstevel@tonic-gate }
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate static
276*7c478bd9Sstevel@tonic-gate def_program(defp)
277*7c478bd9Sstevel@tonic-gate 	definition *defp;
278*7c478bd9Sstevel@tonic-gate {
279*7c478bd9Sstevel@tonic-gate 	token tok;
280*7c478bd9Sstevel@tonic-gate 	declaration dec;
281*7c478bd9Sstevel@tonic-gate 	decl_list *decls;
282*7c478bd9Sstevel@tonic-gate 	decl_list **tailp;
283*7c478bd9Sstevel@tonic-gate 	version_list *vlist;
284*7c478bd9Sstevel@tonic-gate 	version_list **vtailp;
285*7c478bd9Sstevel@tonic-gate 	proc_list *plist;
286*7c478bd9Sstevel@tonic-gate 	proc_list **ptailp;
287*7c478bd9Sstevel@tonic-gate 	int num_args;
288*7c478bd9Sstevel@tonic-gate 	bool_t isvoid = FALSE;	/* whether first argument is void */
289*7c478bd9Sstevel@tonic-gate 	defp->def_kind = DEF_PROGRAM;
290*7c478bd9Sstevel@tonic-gate 	scan(TOK_IDENT, &tok);
291*7c478bd9Sstevel@tonic-gate 	defp->def_name = tok.str;
292*7c478bd9Sstevel@tonic-gate 	scan(TOK_LBRACE, &tok);
293*7c478bd9Sstevel@tonic-gate 	vtailp = &defp->def.pr.versions;
294*7c478bd9Sstevel@tonic-gate 	tailp = &defp->def.st.decls;
295*7c478bd9Sstevel@tonic-gate 	scan(TOK_VERSION, &tok);
296*7c478bd9Sstevel@tonic-gate 	do {
297*7c478bd9Sstevel@tonic-gate 		scan(TOK_IDENT, &tok);
298*7c478bd9Sstevel@tonic-gate 		vlist = ALLOC(version_list);
299*7c478bd9Sstevel@tonic-gate 		vlist->vers_name = tok.str;
300*7c478bd9Sstevel@tonic-gate 		scan(TOK_LBRACE, &tok);
301*7c478bd9Sstevel@tonic-gate 		ptailp = &vlist->procs;
302*7c478bd9Sstevel@tonic-gate 		do {
303*7c478bd9Sstevel@tonic-gate 			/* get result type */
304*7c478bd9Sstevel@tonic-gate 			plist = ALLOC(proc_list);
305*7c478bd9Sstevel@tonic-gate 			get_type(&plist->res_prefix, &plist->res_type,
306*7c478bd9Sstevel@tonic-gate 			    DEF_RESULT);
307*7c478bd9Sstevel@tonic-gate 			if (streq(plist->res_type, "opaque")) {
308*7c478bd9Sstevel@tonic-gate 				error("illegal result type");
309*7c478bd9Sstevel@tonic-gate 			}
310*7c478bd9Sstevel@tonic-gate 			scan(TOK_IDENT, &tok);
311*7c478bd9Sstevel@tonic-gate 			plist->proc_name = tok.str;
312*7c478bd9Sstevel@tonic-gate 			scan(TOK_LPAREN, &tok);
313*7c478bd9Sstevel@tonic-gate 			/* get args - first one */
314*7c478bd9Sstevel@tonic-gate 			num_args = 1;
315*7c478bd9Sstevel@tonic-gate 			isvoid = FALSE;
316*7c478bd9Sstevel@tonic-gate 			/*
317*7c478bd9Sstevel@tonic-gate 			 * type of DEF_PROGRAM in the first
318*7c478bd9Sstevel@tonic-gate 			 * get_prog_declaration and DEF_STURCT in the next
319*7c478bd9Sstevel@tonic-gate 			 * allows void as argument if it is the only argument
320*7c478bd9Sstevel@tonic-gate 			 */
321*7c478bd9Sstevel@tonic-gate 			get_prog_declaration(&dec, DEF_PROGRAM, num_args);
322*7c478bd9Sstevel@tonic-gate 			if (streq(dec.type, "void"))
323*7c478bd9Sstevel@tonic-gate 				isvoid = TRUE;
324*7c478bd9Sstevel@tonic-gate 			decls = ALLOC(decl_list);
325*7c478bd9Sstevel@tonic-gate 			plist->args.decls = decls;
326*7c478bd9Sstevel@tonic-gate 			decls->decl = dec;
327*7c478bd9Sstevel@tonic-gate 			tailp = &decls->next;
328*7c478bd9Sstevel@tonic-gate 			/* get args */
329*7c478bd9Sstevel@tonic-gate 			while (peekscan(TOK_COMMA, &tok)) {
330*7c478bd9Sstevel@tonic-gate 				num_args++;
331*7c478bd9Sstevel@tonic-gate 				get_prog_declaration(&dec, DEF_STRUCT,
332*7c478bd9Sstevel@tonic-gate 						    num_args);
333*7c478bd9Sstevel@tonic-gate 				decls = ALLOC(decl_list);
334*7c478bd9Sstevel@tonic-gate 				decls->decl = dec;
335*7c478bd9Sstevel@tonic-gate 				*tailp = decls;
336*7c478bd9Sstevel@tonic-gate 				if (streq(dec.type, "void"))
337*7c478bd9Sstevel@tonic-gate 					isvoid = TRUE;
338*7c478bd9Sstevel@tonic-gate 				tailp = &decls->next;
339*7c478bd9Sstevel@tonic-gate 			}
340*7c478bd9Sstevel@tonic-gate 			/* multiple arguments are only allowed in newstyle */
341*7c478bd9Sstevel@tonic-gate 			if (!newstyle && num_args > 1) {
342*7c478bd9Sstevel@tonic-gate 				error("only one argument is allowed");
343*7c478bd9Sstevel@tonic-gate 			}
344*7c478bd9Sstevel@tonic-gate 			if (isvoid && num_args > 1) {
345*7c478bd9Sstevel@tonic-gate 				error("illegal use of void "
346*7c478bd9Sstevel@tonic-gate 				    "in program definition");
347*7c478bd9Sstevel@tonic-gate 			}
348*7c478bd9Sstevel@tonic-gate 			*tailp = NULL;
349*7c478bd9Sstevel@tonic-gate 			scan(TOK_RPAREN, &tok);
350*7c478bd9Sstevel@tonic-gate 			scan(TOK_EQUAL, &tok);
351*7c478bd9Sstevel@tonic-gate 			scan_num(&tok);
352*7c478bd9Sstevel@tonic-gate 			scan(TOK_SEMICOLON, &tok);
353*7c478bd9Sstevel@tonic-gate 			plist->proc_num = tok.str;
354*7c478bd9Sstevel@tonic-gate 			plist->arg_num = num_args;
355*7c478bd9Sstevel@tonic-gate 			*ptailp = plist;
356*7c478bd9Sstevel@tonic-gate 			ptailp = &plist->next;
357*7c478bd9Sstevel@tonic-gate 			peek(&tok);
358*7c478bd9Sstevel@tonic-gate 		} while (tok.kind != TOK_RBRACE);
359*7c478bd9Sstevel@tonic-gate 		*ptailp = NULL;
360*7c478bd9Sstevel@tonic-gate 		*vtailp = vlist;
361*7c478bd9Sstevel@tonic-gate 		vtailp = &vlist->next;
362*7c478bd9Sstevel@tonic-gate 		scan(TOK_RBRACE, &tok);
363*7c478bd9Sstevel@tonic-gate 		scan(TOK_EQUAL, &tok);
364*7c478bd9Sstevel@tonic-gate 		scan_num(&tok);
365*7c478bd9Sstevel@tonic-gate 		vlist->vers_num = tok.str;
366*7c478bd9Sstevel@tonic-gate 		/* make the argument structure name for each arg */
367*7c478bd9Sstevel@tonic-gate 		for (plist = vlist->procs; plist != NULL;
368*7c478bd9Sstevel@tonic-gate 		    plist = plist->next) {
369*7c478bd9Sstevel@tonic-gate 			plist->args.argname = make_argname(plist->proc_name,
370*7c478bd9Sstevel@tonic-gate 							vlist->vers_num);
371*7c478bd9Sstevel@tonic-gate 			/* free the memory ?? */
372*7c478bd9Sstevel@tonic-gate 		}
373*7c478bd9Sstevel@tonic-gate 		scan(TOK_SEMICOLON, &tok);
374*7c478bd9Sstevel@tonic-gate 		scan2(TOK_VERSION, TOK_RBRACE, &tok);
375*7c478bd9Sstevel@tonic-gate 	} while (tok.kind == TOK_VERSION);
376*7c478bd9Sstevel@tonic-gate 	scan(TOK_EQUAL, &tok);
377*7c478bd9Sstevel@tonic-gate 	scan_num(&tok);
378*7c478bd9Sstevel@tonic-gate 	defp->def.pr.prog_num = tok.str;
379*7c478bd9Sstevel@tonic-gate 	*vtailp = NULL;
380*7c478bd9Sstevel@tonic-gate }
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate static
384*7c478bd9Sstevel@tonic-gate def_enum(defp)
385*7c478bd9Sstevel@tonic-gate 	definition *defp;
386*7c478bd9Sstevel@tonic-gate {
387*7c478bd9Sstevel@tonic-gate 	token tok;
388*7c478bd9Sstevel@tonic-gate 	enumval_list *elist;
389*7c478bd9Sstevel@tonic-gate 	enumval_list **tailp;
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	defp->def_kind = DEF_ENUM;
392*7c478bd9Sstevel@tonic-gate 	scan(TOK_IDENT, &tok);
393*7c478bd9Sstevel@tonic-gate 	defp->def_name = tok.str;
394*7c478bd9Sstevel@tonic-gate 	scan(TOK_LBRACE, &tok);
395*7c478bd9Sstevel@tonic-gate 	tailp = &defp->def.en.vals;
396*7c478bd9Sstevel@tonic-gate 	do {
397*7c478bd9Sstevel@tonic-gate 		scan(TOK_IDENT, &tok);
398*7c478bd9Sstevel@tonic-gate 		elist = ALLOC(enumval_list);
399*7c478bd9Sstevel@tonic-gate 		elist->name = tok.str;
400*7c478bd9Sstevel@tonic-gate 		elist->assignment = NULL;
401*7c478bd9Sstevel@tonic-gate 		scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
402*7c478bd9Sstevel@tonic-gate 		if (tok.kind == TOK_EQUAL) {
403*7c478bd9Sstevel@tonic-gate 			scan_num(&tok);
404*7c478bd9Sstevel@tonic-gate 			elist->assignment = tok.str;
405*7c478bd9Sstevel@tonic-gate 			scan2(TOK_COMMA, TOK_RBRACE, &tok);
406*7c478bd9Sstevel@tonic-gate 		}
407*7c478bd9Sstevel@tonic-gate 		*tailp = elist;
408*7c478bd9Sstevel@tonic-gate 		tailp = &elist->next;
409*7c478bd9Sstevel@tonic-gate 	} while (tok.kind != TOK_RBRACE);
410*7c478bd9Sstevel@tonic-gate 	*tailp = NULL;
411*7c478bd9Sstevel@tonic-gate }
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate static
414*7c478bd9Sstevel@tonic-gate def_const(defp)
415*7c478bd9Sstevel@tonic-gate 	definition *defp;
416*7c478bd9Sstevel@tonic-gate {
417*7c478bd9Sstevel@tonic-gate 	token tok;
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 	defp->def_kind = DEF_CONST;
420*7c478bd9Sstevel@tonic-gate 	scan(TOK_IDENT, &tok);
421*7c478bd9Sstevel@tonic-gate 	defp->def_name = tok.str;
422*7c478bd9Sstevel@tonic-gate 	scan(TOK_EQUAL, &tok);
423*7c478bd9Sstevel@tonic-gate 	scan2(TOK_IDENT, TOK_STRCONST, &tok);
424*7c478bd9Sstevel@tonic-gate 	defp->def.co = tok.str;
425*7c478bd9Sstevel@tonic-gate }
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate static
428*7c478bd9Sstevel@tonic-gate def_union(defp)
429*7c478bd9Sstevel@tonic-gate 	definition *defp;
430*7c478bd9Sstevel@tonic-gate {
431*7c478bd9Sstevel@tonic-gate 	token tok;
432*7c478bd9Sstevel@tonic-gate 	declaration dec;
433*7c478bd9Sstevel@tonic-gate 	case_list *cases, *tcase;
434*7c478bd9Sstevel@tonic-gate 	case_list **tailp;
435*7c478bd9Sstevel@tonic-gate 	int flag;
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 	defp->def_kind = DEF_UNION;
438*7c478bd9Sstevel@tonic-gate 	scan(TOK_IDENT, &tok);
439*7c478bd9Sstevel@tonic-gate 	defp->def_name = tok.str;
440*7c478bd9Sstevel@tonic-gate 	scan(TOK_SWITCH, &tok);
441*7c478bd9Sstevel@tonic-gate 	scan(TOK_LPAREN, &tok);
442*7c478bd9Sstevel@tonic-gate 	get_declaration(&dec, DEF_UNION);
443*7c478bd9Sstevel@tonic-gate 	defp->def.un.enum_decl = dec;
444*7c478bd9Sstevel@tonic-gate 	tailp = &defp->def.un.cases;
445*7c478bd9Sstevel@tonic-gate 	scan(TOK_RPAREN, &tok);
446*7c478bd9Sstevel@tonic-gate 	scan(TOK_LBRACE, &tok);
447*7c478bd9Sstevel@tonic-gate 	scan(TOK_CASE, &tok);
448*7c478bd9Sstevel@tonic-gate 	while (tok.kind == TOK_CASE) {
449*7c478bd9Sstevel@tonic-gate 		scan2(TOK_IDENT, TOK_CHARCONST, &tok);
450*7c478bd9Sstevel@tonic-gate 		cases = ALLOC(case_list);
451*7c478bd9Sstevel@tonic-gate 		cases->case_name = tok.str;
452*7c478bd9Sstevel@tonic-gate 		scan(TOK_COLON, &tok);
453*7c478bd9Sstevel@tonic-gate 		/* now peek at next token */
454*7c478bd9Sstevel@tonic-gate 		flag = 0;
455*7c478bd9Sstevel@tonic-gate 		if (peekscan(TOK_CASE, &tok)) {
456*7c478bd9Sstevel@tonic-gate 			do {
457*7c478bd9Sstevel@tonic-gate 				scan2(TOK_IDENT, TOK_CHARCONST, &tok);
458*7c478bd9Sstevel@tonic-gate 				cases->contflag = 1;
459*7c478bd9Sstevel@tonic-gate 				/* continued case statement */
460*7c478bd9Sstevel@tonic-gate 				*tailp = cases;
461*7c478bd9Sstevel@tonic-gate 				tailp = &cases->next;
462*7c478bd9Sstevel@tonic-gate 				cases = ALLOC(case_list);
463*7c478bd9Sstevel@tonic-gate 				cases->case_name = tok.str;
464*7c478bd9Sstevel@tonic-gate 				scan(TOK_COLON, &tok);
465*7c478bd9Sstevel@tonic-gate 			} while (peekscan(TOK_CASE, &tok));
466*7c478bd9Sstevel@tonic-gate 		}
467*7c478bd9Sstevel@tonic-gate 		else
468*7c478bd9Sstevel@tonic-gate 			if (flag)
469*7c478bd9Sstevel@tonic-gate 			{
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 				*tailp = cases;
472*7c478bd9Sstevel@tonic-gate 				tailp = &cases->next;
473*7c478bd9Sstevel@tonic-gate 				cases = ALLOC(case_list);
474*7c478bd9Sstevel@tonic-gate 			};
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 		get_declaration(&dec, DEF_UNION);
477*7c478bd9Sstevel@tonic-gate 		cases->case_decl = dec;
478*7c478bd9Sstevel@tonic-gate 		cases->contflag = 0; /* no continued case statement */
479*7c478bd9Sstevel@tonic-gate 		*tailp = cases;
480*7c478bd9Sstevel@tonic-gate 		tailp = &cases->next;
481*7c478bd9Sstevel@tonic-gate 		scan(TOK_SEMICOLON, &tok);
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 		scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
484*7c478bd9Sstevel@tonic-gate 	}
485*7c478bd9Sstevel@tonic-gate 	*tailp = NULL;
486*7c478bd9Sstevel@tonic-gate 	if (tok.kind == TOK_DEFAULT) {
487*7c478bd9Sstevel@tonic-gate 		scan(TOK_COLON, &tok);
488*7c478bd9Sstevel@tonic-gate 		get_declaration(&dec, DEF_UNION);
489*7c478bd9Sstevel@tonic-gate 		defp->def.un.default_decl = ALLOC(declaration);
490*7c478bd9Sstevel@tonic-gate 		*defp->def.un.default_decl = dec;
491*7c478bd9Sstevel@tonic-gate 		scan(TOK_SEMICOLON, &tok);
492*7c478bd9Sstevel@tonic-gate 		scan(TOK_RBRACE, &tok);
493*7c478bd9Sstevel@tonic-gate 	} else {
494*7c478bd9Sstevel@tonic-gate 		defp->def.un.default_decl = NULL;
495*7c478bd9Sstevel@tonic-gate 	}
496*7c478bd9Sstevel@tonic-gate }
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate static char *reserved_words[] =
499*7c478bd9Sstevel@tonic-gate {
500*7c478bd9Sstevel@tonic-gate 	"array",
501*7c478bd9Sstevel@tonic-gate 	"bytes",
502*7c478bd9Sstevel@tonic-gate 	"destroy",
503*7c478bd9Sstevel@tonic-gate 	"free",
504*7c478bd9Sstevel@tonic-gate 	"getpos",
505*7c478bd9Sstevel@tonic-gate 	"inline",
506*7c478bd9Sstevel@tonic-gate 	"pointer",
507*7c478bd9Sstevel@tonic-gate 	"reference",
508*7c478bd9Sstevel@tonic-gate 	"setpos",
509*7c478bd9Sstevel@tonic-gate 	"sizeof",
510*7c478bd9Sstevel@tonic-gate 	"union",
511*7c478bd9Sstevel@tonic-gate 	"vector",
512*7c478bd9Sstevel@tonic-gate 	NULL
513*7c478bd9Sstevel@tonic-gate 	};
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate static char *reserved_types[] =
516*7c478bd9Sstevel@tonic-gate {
517*7c478bd9Sstevel@tonic-gate 	"opaque",
518*7c478bd9Sstevel@tonic-gate 	"string",
519*7c478bd9Sstevel@tonic-gate 	NULL
520*7c478bd9Sstevel@tonic-gate 	};
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate /*
523*7c478bd9Sstevel@tonic-gate  * check that the given name is not one that would eventually result in
524*7c478bd9Sstevel@tonic-gate  * xdr routines that would conflict with internal XDR routines.
525*7c478bd9Sstevel@tonic-gate  */
526*7c478bd9Sstevel@tonic-gate static check_type_name(name, new_type)
527*7c478bd9Sstevel@tonic-gate int new_type;
528*7c478bd9Sstevel@tonic-gate char *name;
529*7c478bd9Sstevel@tonic-gate {
530*7c478bd9Sstevel@tonic-gate 	int i;
531*7c478bd9Sstevel@tonic-gate 	char tmp[100];
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 	for (i = 0; reserved_words[i] != NULL; i++) {
534*7c478bd9Sstevel@tonic-gate 		if (strcmp(name, reserved_words[i]) == 0) {
535*7c478bd9Sstevel@tonic-gate 			snprintf(tmp, sizeof (tmp),
536*7c478bd9Sstevel@tonic-gate 				"illegal (reserved) name :\'%s\' "
537*7c478bd9Sstevel@tonic-gate 				"in type definition",
538*7c478bd9Sstevel@tonic-gate 				name);
539*7c478bd9Sstevel@tonic-gate 			error(tmp);
540*7c478bd9Sstevel@tonic-gate 		}
541*7c478bd9Sstevel@tonic-gate 	}
542*7c478bd9Sstevel@tonic-gate 	if (new_type) {
543*7c478bd9Sstevel@tonic-gate 		for (i = 0; reserved_types[i] != NULL; i++) {
544*7c478bd9Sstevel@tonic-gate 			if (strcmp(name, reserved_types[i]) == 0) {
545*7c478bd9Sstevel@tonic-gate 				snprintf(tmp, sizeof (tmp),
546*7c478bd9Sstevel@tonic-gate 					"illegal (reserved) name :\'%s\' "
547*7c478bd9Sstevel@tonic-gate 					"in type definition",
548*7c478bd9Sstevel@tonic-gate 					name);
549*7c478bd9Sstevel@tonic-gate 				error(tmp);
550*7c478bd9Sstevel@tonic-gate 			}
551*7c478bd9Sstevel@tonic-gate 		}
552*7c478bd9Sstevel@tonic-gate 	}
553*7c478bd9Sstevel@tonic-gate }
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate static
558*7c478bd9Sstevel@tonic-gate def_typedef(defp)
559*7c478bd9Sstevel@tonic-gate 	definition *defp;
560*7c478bd9Sstevel@tonic-gate {
561*7c478bd9Sstevel@tonic-gate 	declaration dec;
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 	defp->def_kind = DEF_TYPEDEF;
564*7c478bd9Sstevel@tonic-gate 	get_declaration(&dec, DEF_TYPEDEF);
565*7c478bd9Sstevel@tonic-gate 	defp->def_name = dec.name;
566*7c478bd9Sstevel@tonic-gate 	check_type_name(dec.name, 1);
567*7c478bd9Sstevel@tonic-gate 	defp->def.ty.old_prefix = dec.prefix;
568*7c478bd9Sstevel@tonic-gate 	defp->def.ty.old_type = dec.type;
569*7c478bd9Sstevel@tonic-gate 	defp->def.ty.rel = dec.rel;
570*7c478bd9Sstevel@tonic-gate 	defp->def.ty.array_max = dec.array_max;
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate static
574*7c478bd9Sstevel@tonic-gate get_declaration(dec, dkind)
575*7c478bd9Sstevel@tonic-gate 	declaration *dec;
576*7c478bd9Sstevel@tonic-gate 	defkind dkind;
577*7c478bd9Sstevel@tonic-gate {
578*7c478bd9Sstevel@tonic-gate 	token tok;
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 	get_type(&dec->prefix, &dec->type, dkind);
581*7c478bd9Sstevel@tonic-gate 	dec->rel = REL_ALIAS;
582*7c478bd9Sstevel@tonic-gate 	if (streq(dec->type, "void")) {
583*7c478bd9Sstevel@tonic-gate 		return;
584*7c478bd9Sstevel@tonic-gate 	}
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate 	check_type_name(dec->type, 0);
587*7c478bd9Sstevel@tonic-gate 	scan2(TOK_STAR, TOK_IDENT, &tok);
588*7c478bd9Sstevel@tonic-gate 	if (tok.kind == TOK_STAR) {
589*7c478bd9Sstevel@tonic-gate 		dec->rel = REL_POINTER;
590*7c478bd9Sstevel@tonic-gate 		scan(TOK_IDENT, &tok);
591*7c478bd9Sstevel@tonic-gate 	}
592*7c478bd9Sstevel@tonic-gate 	dec->name = tok.str;
593*7c478bd9Sstevel@tonic-gate 	if (peekscan(TOK_LBRACKET, &tok)) {
594*7c478bd9Sstevel@tonic-gate 		if (dec->rel == REL_POINTER) {
595*7c478bd9Sstevel@tonic-gate 			error("no array-of-pointer declarations "
596*7c478bd9Sstevel@tonic-gate 			    "-- use typedef");
597*7c478bd9Sstevel@tonic-gate 		}
598*7c478bd9Sstevel@tonic-gate 		dec->rel = REL_VECTOR;
599*7c478bd9Sstevel@tonic-gate 		scan_num(&tok);
600*7c478bd9Sstevel@tonic-gate 		dec->array_max = tok.str;
601*7c478bd9Sstevel@tonic-gate 		scan(TOK_RBRACKET, &tok);
602*7c478bd9Sstevel@tonic-gate 	} else if (peekscan(TOK_LANGLE, &tok)) {
603*7c478bd9Sstevel@tonic-gate 		if (dec->rel == REL_POINTER) {
604*7c478bd9Sstevel@tonic-gate 			error("no array-of-pointer declarations "
605*7c478bd9Sstevel@tonic-gate 			    "-- use typedef");
606*7c478bd9Sstevel@tonic-gate 		}
607*7c478bd9Sstevel@tonic-gate 		dec->rel = REL_ARRAY;
608*7c478bd9Sstevel@tonic-gate 		if (peekscan(TOK_RANGLE, &tok)) {
609*7c478bd9Sstevel@tonic-gate 			dec->array_max = "~0";	/* unspecified size, use max */
610*7c478bd9Sstevel@tonic-gate 		} else {
611*7c478bd9Sstevel@tonic-gate 			scan_num(&tok);
612*7c478bd9Sstevel@tonic-gate 			dec->array_max = tok.str;
613*7c478bd9Sstevel@tonic-gate 			scan(TOK_RANGLE, &tok);
614*7c478bd9Sstevel@tonic-gate 		}
615*7c478bd9Sstevel@tonic-gate 	}
616*7c478bd9Sstevel@tonic-gate 	if (streq(dec->type, "opaque")) {
617*7c478bd9Sstevel@tonic-gate 		if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
618*7c478bd9Sstevel@tonic-gate 			error("array declaration expected");
619*7c478bd9Sstevel@tonic-gate 		}
620*7c478bd9Sstevel@tonic-gate 	} else if (streq(dec->type, "string")) {
621*7c478bd9Sstevel@tonic-gate 		if (dec->rel != REL_ARRAY) {
622*7c478bd9Sstevel@tonic-gate 			error("variable-length array declaration expected");
623*7c478bd9Sstevel@tonic-gate 		}
624*7c478bd9Sstevel@tonic-gate 	}
625*7c478bd9Sstevel@tonic-gate }
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate static
629*7c478bd9Sstevel@tonic-gate get_prog_declaration(dec, dkind, num)
630*7c478bd9Sstevel@tonic-gate 	declaration *dec;
631*7c478bd9Sstevel@tonic-gate 	defkind dkind;
632*7c478bd9Sstevel@tonic-gate 	int num;  /* arg number */
633*7c478bd9Sstevel@tonic-gate {
634*7c478bd9Sstevel@tonic-gate 	token tok;
635*7c478bd9Sstevel@tonic-gate 	char name[sizeof (ARGNAME) + 10];
636*7c478bd9Sstevel@tonic-gate 
637*7c478bd9Sstevel@tonic-gate 	if (dkind == DEF_PROGRAM) {
638*7c478bd9Sstevel@tonic-gate 		peek(&tok);
639*7c478bd9Sstevel@tonic-gate 		if (tok.kind == TOK_RPAREN) { /* no arguments */
640*7c478bd9Sstevel@tonic-gate 			dec->rel = REL_ALIAS;
641*7c478bd9Sstevel@tonic-gate 			dec->type = "void";
642*7c478bd9Sstevel@tonic-gate 			dec->prefix = NULL;
643*7c478bd9Sstevel@tonic-gate 			dec->name = NULL;
644*7c478bd9Sstevel@tonic-gate 			return;
645*7c478bd9Sstevel@tonic-gate 		}
646*7c478bd9Sstevel@tonic-gate 	}
647*7c478bd9Sstevel@tonic-gate 	get_type(&dec->prefix, &dec->type, dkind);
648*7c478bd9Sstevel@tonic-gate 	dec->rel = REL_ALIAS;
649*7c478bd9Sstevel@tonic-gate 	if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
650*7c478bd9Sstevel@tonic-gate 		dec->name = strdup(tok.str);
651*7c478bd9Sstevel@tonic-gate 	else {
652*7c478bd9Sstevel@tonic-gate 		/* default name of argument */
653*7c478bd9Sstevel@tonic-gate 		snprintf(name, sizeof (name), "%s%d", ARGNAME, num);
654*7c478bd9Sstevel@tonic-gate 		dec->name = strdup(name);
655*7c478bd9Sstevel@tonic-gate 	}
656*7c478bd9Sstevel@tonic-gate 	if (dec->name == NULL)
657*7c478bd9Sstevel@tonic-gate 		error("internal error -- out of memory");
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	if (streq(dec->type, "void")) {
660*7c478bd9Sstevel@tonic-gate 		return;
661*7c478bd9Sstevel@tonic-gate 	}
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 	if (streq(dec->type, "opaque")) {
664*7c478bd9Sstevel@tonic-gate 		error("opaque -- illegal argument type");
665*7c478bd9Sstevel@tonic-gate 	}
666*7c478bd9Sstevel@tonic-gate 	if (peekscan(TOK_STAR, &tok)) {
667*7c478bd9Sstevel@tonic-gate 		if (streq(dec->type, "string")) {
668*7c478bd9Sstevel@tonic-gate 			error("pointer to string not allowed "
669*7c478bd9Sstevel@tonic-gate 			    "in program arguments\n");
670*7c478bd9Sstevel@tonic-gate 		}
671*7c478bd9Sstevel@tonic-gate 		dec->rel = REL_POINTER;
672*7c478bd9Sstevel@tonic-gate 		if (peekscan(TOK_IDENT, &tok))
673*7c478bd9Sstevel@tonic-gate 			/* optional name of argument */
674*7c478bd9Sstevel@tonic-gate 			dec->name = strdup(tok.str);
675*7c478bd9Sstevel@tonic-gate 	}
676*7c478bd9Sstevel@tonic-gate 	if (peekscan(TOK_LANGLE, &tok)) {
677*7c478bd9Sstevel@tonic-gate 		if (!streq(dec->type, "string")) {
678*7c478bd9Sstevel@tonic-gate 			error("arrays cannot be declared as arguments "
679*7c478bd9Sstevel@tonic-gate 			    "to procedures -- use typedef");
680*7c478bd9Sstevel@tonic-gate 		}
681*7c478bd9Sstevel@tonic-gate 		dec->rel = REL_ARRAY;
682*7c478bd9Sstevel@tonic-gate 		if (peekscan(TOK_RANGLE, &tok)) {
683*7c478bd9Sstevel@tonic-gate 			dec->array_max = "~0";
684*7c478bd9Sstevel@tonic-gate 			/* unspecified size, use max */
685*7c478bd9Sstevel@tonic-gate 		} else {
686*7c478bd9Sstevel@tonic-gate 			scan_num(&tok);
687*7c478bd9Sstevel@tonic-gate 			dec->array_max = tok.str;
688*7c478bd9Sstevel@tonic-gate 			scan(TOK_RANGLE, &tok);
689*7c478bd9Sstevel@tonic-gate 		}
690*7c478bd9Sstevel@tonic-gate 	}
691*7c478bd9Sstevel@tonic-gate 	if (streq(dec->type, "string")) {
692*7c478bd9Sstevel@tonic-gate 		if (dec->rel != REL_ARRAY) {
693*7c478bd9Sstevel@tonic-gate 			/*
694*7c478bd9Sstevel@tonic-gate 			 * .x specifies just string as
695*7c478bd9Sstevel@tonic-gate 			 * type of argument
696*7c478bd9Sstevel@tonic-gate 			 * - make it string<>
697*7c478bd9Sstevel@tonic-gate 			 */
698*7c478bd9Sstevel@tonic-gate 			dec->rel = REL_ARRAY;
699*7c478bd9Sstevel@tonic-gate 			dec->array_max = "~0"; /* unspecified size, use max */
700*7c478bd9Sstevel@tonic-gate 		}
701*7c478bd9Sstevel@tonic-gate 	}
702*7c478bd9Sstevel@tonic-gate }
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate static
707*7c478bd9Sstevel@tonic-gate get_type(prefixp, typep, dkind)
708*7c478bd9Sstevel@tonic-gate 	char **prefixp;
709*7c478bd9Sstevel@tonic-gate 	char **typep;
710*7c478bd9Sstevel@tonic-gate 	defkind dkind;
711*7c478bd9Sstevel@tonic-gate {
712*7c478bd9Sstevel@tonic-gate 	token tok;
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate 	*prefixp = NULL;
715*7c478bd9Sstevel@tonic-gate 	get_token(&tok);
716*7c478bd9Sstevel@tonic-gate 	switch (tok.kind) {
717*7c478bd9Sstevel@tonic-gate 	case TOK_IDENT:
718*7c478bd9Sstevel@tonic-gate 		*typep = tok.str;
719*7c478bd9Sstevel@tonic-gate 		break;
720*7c478bd9Sstevel@tonic-gate 	case TOK_STRUCT:
721*7c478bd9Sstevel@tonic-gate 	case TOK_ENUM:
722*7c478bd9Sstevel@tonic-gate 	case TOK_UNION:
723*7c478bd9Sstevel@tonic-gate 		*prefixp = tok.str;
724*7c478bd9Sstevel@tonic-gate 		scan(TOK_IDENT, &tok);
725*7c478bd9Sstevel@tonic-gate 		*typep = tok.str;
726*7c478bd9Sstevel@tonic-gate 		break;
727*7c478bd9Sstevel@tonic-gate 	case TOK_UNSIGNED:
728*7c478bd9Sstevel@tonic-gate 		unsigned_dec(typep);
729*7c478bd9Sstevel@tonic-gate 		break;
730*7c478bd9Sstevel@tonic-gate 	case TOK_SHORT:
731*7c478bd9Sstevel@tonic-gate 		*typep = "short";
732*7c478bd9Sstevel@tonic-gate 		(void) peekscan(TOK_INT, &tok);
733*7c478bd9Sstevel@tonic-gate 		break;
734*7c478bd9Sstevel@tonic-gate 	case TOK_LONG:
735*7c478bd9Sstevel@tonic-gate 		*typep = "long";
736*7c478bd9Sstevel@tonic-gate 		(void) peekscan(TOK_INT, &tok);
737*7c478bd9Sstevel@tonic-gate 		break;
738*7c478bd9Sstevel@tonic-gate 	case TOK_HYPER:
739*7c478bd9Sstevel@tonic-gate 		*typep = "longlong_t";
740*7c478bd9Sstevel@tonic-gate 		(void) peekscan(TOK_INT, &tok);
741*7c478bd9Sstevel@tonic-gate 		break;
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 	case TOK_VOID:
744*7c478bd9Sstevel@tonic-gate 		if (dkind != DEF_UNION && dkind != DEF_PROGRAM &&
745*7c478bd9Sstevel@tonic-gate 		    dkind != DEF_RESULT) {
746*7c478bd9Sstevel@tonic-gate 			error("voids allowed only inside union and "
747*7c478bd9Sstevel@tonic-gate 			    "program definitions with one argument");
748*7c478bd9Sstevel@tonic-gate 		}
749*7c478bd9Sstevel@tonic-gate 		*typep = tok.str;
750*7c478bd9Sstevel@tonic-gate 		break;
751*7c478bd9Sstevel@tonic-gate 	case TOK_ONEWAY:
752*7c478bd9Sstevel@tonic-gate 		if (dkind != DEF_RESULT) {
753*7c478bd9Sstevel@tonic-gate 			error("oneways allowed only inside result definitions");
754*7c478bd9Sstevel@tonic-gate 		}
755*7c478bd9Sstevel@tonic-gate 		*typep = tok.str;
756*7c478bd9Sstevel@tonic-gate 		break;
757*7c478bd9Sstevel@tonic-gate 	case TOK_STRING:
758*7c478bd9Sstevel@tonic-gate 	case TOK_OPAQUE:
759*7c478bd9Sstevel@tonic-gate 	case TOK_CHAR:
760*7c478bd9Sstevel@tonic-gate 	case TOK_INT:
761*7c478bd9Sstevel@tonic-gate 	case TOK_FLOAT:
762*7c478bd9Sstevel@tonic-gate 	case TOK_DOUBLE:
763*7c478bd9Sstevel@tonic-gate 	case TOK_BOOL:
764*7c478bd9Sstevel@tonic-gate 	case TOK_QUAD:
765*7c478bd9Sstevel@tonic-gate 		*typep = tok.str;
766*7c478bd9Sstevel@tonic-gate 		break;
767*7c478bd9Sstevel@tonic-gate 	default:
768*7c478bd9Sstevel@tonic-gate 		error("expected type specifier");
769*7c478bd9Sstevel@tonic-gate 	}
770*7c478bd9Sstevel@tonic-gate }
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate static
773*7c478bd9Sstevel@tonic-gate unsigned_dec(typep)
774*7c478bd9Sstevel@tonic-gate 	char **typep;
775*7c478bd9Sstevel@tonic-gate {
776*7c478bd9Sstevel@tonic-gate 	token tok;
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 	peek(&tok);
779*7c478bd9Sstevel@tonic-gate 	switch (tok.kind) {
780*7c478bd9Sstevel@tonic-gate 	case TOK_CHAR:
781*7c478bd9Sstevel@tonic-gate 		get_token(&tok);
782*7c478bd9Sstevel@tonic-gate 		*typep = "u_char";
783*7c478bd9Sstevel@tonic-gate 		break;
784*7c478bd9Sstevel@tonic-gate 	case TOK_SHORT:
785*7c478bd9Sstevel@tonic-gate 		get_token(&tok);
786*7c478bd9Sstevel@tonic-gate 		*typep = "u_short";
787*7c478bd9Sstevel@tonic-gate 		(void) peekscan(TOK_INT, &tok);
788*7c478bd9Sstevel@tonic-gate 		break;
789*7c478bd9Sstevel@tonic-gate 	case TOK_LONG:
790*7c478bd9Sstevel@tonic-gate 		get_token(&tok);
791*7c478bd9Sstevel@tonic-gate 		*typep = "u_long";
792*7c478bd9Sstevel@tonic-gate 		(void) peekscan(TOK_INT, &tok);
793*7c478bd9Sstevel@tonic-gate 		break;
794*7c478bd9Sstevel@tonic-gate 	case TOK_HYPER:
795*7c478bd9Sstevel@tonic-gate 		get_token(&tok);
796*7c478bd9Sstevel@tonic-gate 		*typep = "u_longlong_t";
797*7c478bd9Sstevel@tonic-gate 		(void) peekscan(TOK_INT, &tok);
798*7c478bd9Sstevel@tonic-gate 		break;
799*7c478bd9Sstevel@tonic-gate 	case TOK_INT:
800*7c478bd9Sstevel@tonic-gate 		get_token(&tok);
801*7c478bd9Sstevel@tonic-gate 		*typep = "u_int";
802*7c478bd9Sstevel@tonic-gate 		break;
803*7c478bd9Sstevel@tonic-gate 	default:
804*7c478bd9Sstevel@tonic-gate 		*typep = "u_int";
805*7c478bd9Sstevel@tonic-gate 		break;
806*7c478bd9Sstevel@tonic-gate 	}
807*7c478bd9Sstevel@tonic-gate }
808