xref: /onnv-gate/usr/src/cmd/abi/spectrans/spec2trace/parseproto.y (revision 2775:892d346f56a9)
1*2775Sraf %{
2*2775Sraf /*
3*2775Sraf  * CDDL HEADER START
4*2775Sraf  *
5*2775Sraf  * The contents of this file are subject to the terms of the
6*2775Sraf  * Common Development and Distribution License, Version 1.0 only
7*2775Sraf  * (the "License").  You may not use this file except in compliance
8*2775Sraf  * with the License.
9*2775Sraf  *
10*2775Sraf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11*2775Sraf  * or http://www.opensolaris.org/os/licensing.
12*2775Sraf  * See the License for the specific language governing permissions
13*2775Sraf  * and limitations under the License.
14*2775Sraf  *
15*2775Sraf  * When distributing Covered Code, include this CDDL HEADER in each
16*2775Sraf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17*2775Sraf  * If applicable, add the following below this CDDL HEADER, with the
18*2775Sraf  * fields enclosed by brackets "[]" replaced with your own identifying
19*2775Sraf  * information: Portions Copyright [yyyy] [name of copyright owner]
20*2775Sraf  *
21*2775Sraf  * CDDL HEADER END
22*2775Sraf  */
23*2775Sraf 
24*2775Sraf /*
25*2775Sraf  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
26*2775Sraf  * Use is subject to license terms.
27*2775Sraf  */
28*2775Sraf 
29*2775Sraf #pragma ident	"%Z%%M%	%I%	%E% SMI"
30*2775Sraf 
31*2775Sraf #include "parseproto.h"
32*2775Sraf #include <assert.h>
33*2775Sraf 
34*2775Sraf static decl_spec_t	*declspec_Construct(void);
35*2775Sraf static void		 declspec_Destroy(decl_spec_t *);
36*2775Sraf static decl_spec_t	*declspec_Init(stt_t, char *);
37*2775Sraf static char		*declspec_VerifySTT(stt_t, stt_t);
38*2775Sraf static decl_spec_t	*declspec_AddSTT(decl_spec_t *, stt_t, const char **);
39*2775Sraf static decl_spec_t	*declspec_AddDS(decl_spec_t *,
40*2775Sraf 			    decl_spec_t *, const char **);
41*2775Sraf static stt_t		 declspec_GetSTT(decl_spec_t *);
42*2775Sraf static char		*declspec_GetTag(decl_spec_t *);
43*2775Sraf static type_t		*type_Construct(void);
44*2775Sraf static void		 type_Destroy(type_t *);
45*2775Sraf static type_t		*type_SetPtr(type_t *, stt_t);
46*2775Sraf static type_t		*type_SetFun(type_t *, decl_t *);
47*2775Sraf static type_t		*type_AddTail(type_t *, type_t *);
48*2775Sraf static	const char	*type_Verify(type_t *);
49*2775Sraf 
50*2775Sraf static	decl_t		*decl_Construct(void);
51*2775Sraf static	decl_t		*decl_AddArg(decl_t *, decl_t *);
52*2775Sraf static	int		 decl_IsVoid(decl_t *);
53*2775Sraf static	int		 decl_IsVoidArray(decl_t *);
54*2775Sraf static	const char	*decl_VerifyArgs(decl_t *);
55*2775Sraf static	decl_t		*decl_AddDS(decl_t *, decl_spec_t *, const char **);
56*2775Sraf static	decl_t		*decl_AddTypeTail(decl_t *, type_t *);
57*2775Sraf static	decl_t		*decl_addptr(decl_t *, type_t *);
58*2775Sraf static	decl_t		*decl_addary(decl_t *, char *);
59*2775Sraf static	decl_t		*decl_addfun(decl_t *, decl_t *);
60*2775Sraf static	decl_t		*decl_addellipsis(decl_t *);
61*2775Sraf 
62*2775Sraf #if defined(DEBUG)
63*2775Sraf static	void		type_PrintType(type_t *, int);
64*2775Sraf static	void		decl_PrintDecl(decl_t *, int);
65*2775Sraf static	void		decl_PrintTraceInfo(decl_t *);
66*2775Sraf static	char		*de_const(char *);
67*2775Sraf #endif
68*2775Sraf 
69*2775Sraf 
70*2775Sraf 
71*2775Sraf static	int	yylex(void);
72*2775Sraf static	void	yyerror(const char *);
73*2775Sraf static	int	yyparse(void);
74*2775Sraf 
75*2775Sraf #if defined(MEM_DEBUG)
76*2775Sraf static	int	declspec_Construct_calls;
77*2775Sraf static	int	type_Construct_calls;
78*2775Sraf static	int	decl_Construct_calls;
79*2775Sraf #endif
80*2775Sraf 
81*2775Sraf #if defined(DEBUG)
82*2775Sraf static	char	*de_const(char *);
83*2775Sraf #endif
84*2775Sraf %}
85*2775Sraf 
86*2775Sraf %union {
87*2775Sraf 	char		*s_val;
88*2775Sraf 	int		 i_val;
89*2775Sraf 	stt_t		 stt_val;
90*2775Sraf 	decl_spec_t	*ds_val;
91*2775Sraf 	type_t		*t_val;
92*2775Sraf 	decl_t		*d_val;
93*2775Sraf }
94*2775Sraf 
95*2775Sraf %token	<i_val>	ELLIPSIS
96*2775Sraf 
97*2775Sraf %token	<s_val>	INTEGER
98*2775Sraf %token	<s_val>	IDENTIFIER
99*2775Sraf %token	<s_val>	TYPEDEF_NAME
100*2775Sraf %type	<s_val>	constant_expression
101*2775Sraf 
102*2775Sraf %token	<stt_val>	REGISTER
103*2775Sraf %token	<stt_val>	TYPEDEF	EXTERN	AUTO	STATIC
104*2775Sraf %token	<stt_val>	VOID	CHAR	SHORT	INT	LONG
105*2775Sraf %token	<stt_val>	FLOAT	DOUBLE	SIGNED	UNSIGNED
106*2775Sraf %token	<stt_val>	CONST	VOLATILE	RESTRICT	RESTRICT_KYWD
107*2775Sraf %type	<stt_val>	struct_or_union
108*2775Sraf %type	<ds_val>	storage_class_specifier
109*2775Sraf %type	<ds_val>	type_qualifier
110*2775Sraf %type	<ds_val>	type_qualifier_list
111*2775Sraf 
112*2775Sraf %token	<ds_val>	STRUCT		UNION
113*2775Sraf %token	<ds_val>	ENUM
114*2775Sraf %type	<ds_val>	declaration_specifiers
115*2775Sraf %type	<ds_val>	type_specifier
116*2775Sraf %type	<ds_val>	struct_or_union_specifier enum_specifier
117*2775Sraf %type	<ds_val>	typedef_name
118*2775Sraf 
119*2775Sraf %type	<t_val>		pointer
120*2775Sraf 
121*2775Sraf %type	<d_val>		declaration
122*2775Sraf %type	<d_val>		init_declarator_list init_declarator
123*2775Sraf %type	<d_val>		declarator
124*2775Sraf %type	<d_val>		direct_declarator
125*2775Sraf %type	<d_val>		parameter_type_list parameter_list
126*2775Sraf %type	<d_val>		parameter_declaration
127*2775Sraf %type	<d_val>		abstract_declarator
128*2775Sraf %type	<d_val>		direct_abstract_declarator
129*2775Sraf 
130*2775Sraf %start	declaration
131*2775Sraf 
132*2775Sraf %%
133*2775Sraf 
134*2775Sraf /*
135*2775Sraf  * The grammar is derived from ANSI/ISO 9899-1990.
136*2775Sraf  */
137*2775Sraf 
138*2775Sraf declaration
139*2775Sraf 	: declaration_specifiers init_declarator_list ';'
140*2775Sraf 		{
141*2775Sraf 			decl_t	*dp;
142*2775Sraf 
143*2775Sraf 			protop = $$ = $2;
144*2775Sraf 
145*2775Sraf 			/* only one declaration allowed */
146*2775Sraf 			assert(protop->d_next == NULL);
147*2775Sraf 
148*2775Sraf 			for (dp = $2; dp && (errstr == NULL);
149*2775Sraf 			    dp = dp->d_next) {
150*2775Sraf 				const char	*sp;
151*2775Sraf 
152*2775Sraf 				decl_AddDS(dp, $1, &errstr);
153*2775Sraf 				if (sp = decl_Verify(dp))
154*2775Sraf 					errstr = sp;
155*2775Sraf 			}
156*2775Sraf 			declspec_Destroy($1);
157*2775Sraf 		}
158*2775Sraf 	| error ';'
159*2775Sraf 		{
160*2775Sraf 			protop = $$ = NULL;
161*2775Sraf 			errstr = "function prototype syntax error";
162*2775Sraf 		}
163*2775Sraf /*
164*2775Sraf  * XXX - Does not support a "stand-alone" declaration specifier. It is
165*2775Sraf  * essentially a type declaration, for example:
166*2775Sraf  *
167*2775Sraf  *	typedef enum { FALSE = 0, TRUE = 1 } boolean_t;
168*2775Sraf  * or
169*2775Sraf  *	struct _name { char *first; char *last };
170*2775Sraf  */
171*2775Sraf 
172*2775Sraf /* XXX	| declaration_specifiers */
173*2775Sraf 	;
174*2775Sraf 
175*2775Sraf declaration_specifiers
176*2775Sraf 	: storage_class_specifier declaration_specifiers
177*2775Sraf 		{
178*2775Sraf 			char const *ep;
179*2775Sraf 
180*2775Sraf 			$$ = declspec_AddDS($2, $1, &ep);
181*2775Sraf 			declspec_Destroy($1);
182*2775Sraf 
183*2775Sraf 			if (errstr == NULL)
184*2775Sraf 				errstr = ep;
185*2775Sraf 		}
186*2775Sraf 	| storage_class_specifier
187*2775Sraf 	| type_specifier declaration_specifiers
188*2775Sraf 		{
189*2775Sraf 			const char	*ep;
190*2775Sraf 
191*2775Sraf 			$$ = declspec_AddDS($2, $1, &ep);
192*2775Sraf 			declspec_Destroy($1);
193*2775Sraf 
194*2775Sraf 			if (errstr == NULL)
195*2775Sraf 				errstr = ep;
196*2775Sraf 		}
197*2775Sraf 	| type_specifier
198*2775Sraf 	| type_qualifier declaration_specifiers
199*2775Sraf 		{
200*2775Sraf 			const char	*ep;
201*2775Sraf 
202*2775Sraf 			$$ = declspec_AddDS($2, $1, &ep);
203*2775Sraf 			declspec_Destroy($1);
204*2775Sraf 
205*2775Sraf 			if (errstr == NULL)
206*2775Sraf 				errstr = ep;
207*2775Sraf 		}
208*2775Sraf 	| type_qualifier
209*2775Sraf 	;
210*2775Sraf 
211*2775Sraf storage_class_specifier
212*2775Sraf 	: REGISTER
213*2775Sraf 		{
214*2775Sraf 			$$ = declspec_Init(SCS_REGISTER, NULL);
215*2775Sraf 		}
216*2775Sraf /*
217*2775Sraf  * XXX - Does not support any storage class specifier other than
218*2775Sraf  * register, and then only for function arguments.
219*2775Sraf  *
220*2775Sraf 	| TYPEDEF
221*2775Sraf 		{
222*2775Sraf 			$$ = declspec_Init(SCS_TYPEDEF, NULL);
223*2775Sraf 		}
224*2775Sraf 	| EXTERN
225*2775Sraf 		{
226*2775Sraf 			$$ = declspec_Init(SCS_EXTERN, NULL);
227*2775Sraf 		}
228*2775Sraf 	| STATIC
229*2775Sraf 		{
230*2775Sraf 			$$ = declspec_Init(SCS_STATIC, NULL);
231*2775Sraf 		}
232*2775Sraf 	| AUTO
233*2775Sraf 		{
234*2775Sraf 			$$ = declspec_Init(SCS_AUTO, NULL);
235*2775Sraf 		}
236*2775Sraf  */
237*2775Sraf 	;
238*2775Sraf 
239*2775Sraf type_specifier
240*2775Sraf 	: VOID
241*2775Sraf 		{
242*2775Sraf 			$$ = declspec_Init(TS_VOID, NULL);
243*2775Sraf 			atIDENT = 1;
244*2775Sraf 		}
245*2775Sraf 	| CHAR
246*2775Sraf 		{
247*2775Sraf 			$$ = declspec_Init(TS_CHAR, NULL);
248*2775Sraf 			atIDENT = 1;
249*2775Sraf 		}
250*2775Sraf 	| SHORT
251*2775Sraf 		{
252*2775Sraf 			$$ = declspec_Init(TS_SHORT, NULL);
253*2775Sraf 			atIDENT = 1;
254*2775Sraf 		}
255*2775Sraf 	| INT
256*2775Sraf 		{
257*2775Sraf 			$$ = declspec_Init(TS_INT, NULL);
258*2775Sraf 			atIDENT = 1;
259*2775Sraf 		}
260*2775Sraf 	| LONG
261*2775Sraf 		{
262*2775Sraf 			$$ = declspec_Init(TS_LONG, NULL);
263*2775Sraf 			atIDENT = 1;
264*2775Sraf 		}
265*2775Sraf 	| FLOAT
266*2775Sraf 		{
267*2775Sraf 			$$ = declspec_Init(TS_FLOAT, NULL);
268*2775Sraf 			atIDENT = 1;
269*2775Sraf 		}
270*2775Sraf 	| DOUBLE
271*2775Sraf 		{
272*2775Sraf 			$$ = declspec_Init(TS_DOUBLE, NULL);
273*2775Sraf 			atIDENT = 1;
274*2775Sraf 		}
275*2775Sraf 	| SIGNED
276*2775Sraf 		{
277*2775Sraf 			$$ = declspec_Init(TS_SIGNED, NULL);
278*2775Sraf 			atIDENT = 1;
279*2775Sraf 		}
280*2775Sraf 	| UNSIGNED
281*2775Sraf 		{
282*2775Sraf 			$$ = declspec_Init(TS_UNSIGNED, NULL);
283*2775Sraf 			atIDENT = 1;
284*2775Sraf 		}
285*2775Sraf 	| struct_or_union_specifier
286*2775Sraf 	| enum_specifier
287*2775Sraf 	| typedef_name
288*2775Sraf 	;
289*2775Sraf 
290*2775Sraf typedef_name
291*2775Sraf 	: TYPEDEF_NAME
292*2775Sraf 		{
293*2775Sraf 			$$ = declspec_Init(TS_TYPEDEF, $1);
294*2775Sraf 			atIDENT = 1;
295*2775Sraf 			free($1);
296*2775Sraf 		}
297*2775Sraf 	;
298*2775Sraf 
299*2775Sraf /*
300*2775Sraf  * The "restrict" keyword is new in the C99 standard.
301*2775Sraf  * It is type qualifier like const and volatile.
302*2775Sraf  * We are using "_RESTRICT_KYWD" in headers and source code so
303*2775Sraf  * it is easily turned on and off by various macros at compile time.
304*2775Sraf  * In order for the "restrict" keyword to be recognized you must
305*2775Sraf  * be using a C99 compliant compiler in its native mode.
306*2775Sraf  */
307*2775Sraf type_qualifier
308*2775Sraf 	: CONST
309*2775Sraf 		{
310*2775Sraf 			$$ = declspec_Init(TQ_CONST, NULL);
311*2775Sraf 		}
312*2775Sraf 	| VOLATILE
313*2775Sraf 		{
314*2775Sraf 			$$ = declspec_Init(TQ_VOLATILE, NULL);
315*2775Sraf 		}
316*2775Sraf 	| RESTRICT
317*2775Sraf 		{
318*2775Sraf 			$$ = declspec_Init(TQ_RESTRICT, NULL);
319*2775Sraf 		}
320*2775Sraf 	| RESTRICT_KYWD
321*2775Sraf 		{
322*2775Sraf 			$$ = declspec_Init(TQ_RESTRICT_KYWD, NULL);
323*2775Sraf 		}
324*2775Sraf 	;
325*2775Sraf 
326*2775Sraf struct_or_union_specifier
327*2775Sraf 	: struct_or_union { atIDENT = 1; } IDENTIFIER
328*2775Sraf 		{
329*2775Sraf 			$$ = declspec_Init($1, $3);
330*2775Sraf 			free($3);
331*2775Sraf 		}
332*2775Sraf /*
333*2775Sraf  * XXX - struct or union definitions are not supported. It is generally
334*2775Sraf  * not done within the context of a function declaration (prototype) or
335*2775Sraf  * variable definition.
336*2775Sraf 
337*2775Sraf 	| struct_or_union IDENTIFIER '{' struct_declaration_list '}'
338*2775Sraf 	| struct_or_union '{' struct_declaration_list '}'
339*2775Sraf  */
340*2775Sraf 	;
341*2775Sraf 
342*2775Sraf struct_or_union
343*2775Sraf 	: STRUCT
344*2775Sraf 		{
345*2775Sraf 			$$ = TS_STRUCT;
346*2775Sraf 		}
347*2775Sraf 	| UNION
348*2775Sraf 		{
349*2775Sraf 			$$ = TS_UNION;
350*2775Sraf 		}
351*2775Sraf 	;
352*2775Sraf 
353*2775Sraf init_declarator_list
354*2775Sraf 	: init_declarator
355*2775Sraf 		{
356*2775Sraf 			$$ = $1;
357*2775Sraf 			atIDENT = 1;
358*2775Sraf 		}
359*2775Sraf /*
360*2775Sraf  * XXX - Does not support a comma separated list of declarations or
361*2775Sraf  * definitions. Function prototypes or variable definitions must be
362*2775Sraf  * given as one per C statement.
363*2775Sraf 
364*2775Sraf 	| init_declarator_list ',' init_declarator
365*2775Sraf 		{
366*2775Sraf 			$$ = decl_AddArg($1, $3);
367*2775Sraf 			atIDENT = 1;
368*2775Sraf 		}
369*2775Sraf */
370*2775Sraf 	;
371*2775Sraf 
372*2775Sraf init_declarator
373*2775Sraf 	: declarator
374*2775Sraf /*
375*2775Sraf  * XXX - Initialization is not supported.
376*2775Sraf 
377*2775Sraf 	| declarator '=' initializer
378*2775Sraf */
379*2775Sraf 	;
380*2775Sraf 
381*2775Sraf 
382*2775Sraf enum_specifier
383*2775Sraf 	: ENUM { atIDENT = 1; } IDENTIFIER
384*2775Sraf 		{
385*2775Sraf 			$$ = declspec_Init(TS_ENUM, $3);
386*2775Sraf 			free($3);
387*2775Sraf 		}
388*2775Sraf /*
389*2775Sraf  * XXX - enumerator definition is not supported for the same reasons
390*2775Sraf  * struct|union definition is not supported.
391*2775Sraf 
392*2775Sraf 	| ENUM IDENTIFIER '{' enumerator_list '}'
393*2775Sraf 	| ENUM '{' enumerator_list '}'
394*2775Sraf */
395*2775Sraf 	;
396*2775Sraf 
397*2775Sraf 
398*2775Sraf declarator
399*2775Sraf 	: pointer direct_declarator
400*2775Sraf 		{
401*2775Sraf 			$$ = decl_addptr($2, $1);
402*2775Sraf 		}
403*2775Sraf 	| direct_declarator
404*2775Sraf 	;
405*2775Sraf 
406*2775Sraf direct_declarator
407*2775Sraf 	: IDENTIFIER
408*2775Sraf 		{
409*2775Sraf 			$$ = decl_SetName(decl_Construct(), $1);
410*2775Sraf 			atIDENT = 0;
411*2775Sraf 			free($1);
412*2775Sraf 		}
413*2775Sraf 	| '(' declarator ')'
414*2775Sraf 		{
415*2775Sraf 			$$ = $2;
416*2775Sraf 		}
417*2775Sraf 	| direct_declarator '[' constant_expression ']'
418*2775Sraf 		{
419*2775Sraf 			$$ = decl_addary($1, $3);
420*2775Sraf 			free($3);
421*2775Sraf 		}
422*2775Sraf 	| direct_declarator '[' ']'
423*2775Sraf 		{
424*2775Sraf 			$$ = decl_addary($1, NULL);
425*2775Sraf 		}
426*2775Sraf 	| direct_declarator '(' parameter_type_list ')'
427*2775Sraf 		{
428*2775Sraf 			$$ = decl_addfun($1, $3);
429*2775Sraf 		}
430*2775Sraf 	| direct_declarator '(' ')'
431*2775Sraf 		{
432*2775Sraf 			$$ = decl_addfun($1, NULL);
433*2775Sraf 		}
434*2775Sraf 	;
435*2775Sraf 
436*2775Sraf pointer
437*2775Sraf 	: '*' type_qualifier_list
438*2775Sraf 		{
439*2775Sraf 			$$ = type_SetPtr(type_Construct(), ($2)->ds_stt);
440*2775Sraf 			declspec_Destroy($2);
441*2775Sraf 		}
442*2775Sraf 	| '*'
443*2775Sraf 		{
444*2775Sraf 			$$ = type_SetPtr(type_Construct(), TQ_NONE);
445*2775Sraf 		}
446*2775Sraf 	| '*' type_qualifier_list pointer
447*2775Sraf 		{
448*2775Sraf 			type_t	*tp = type_Construct();
449*2775Sraf 
450*2775Sraf 			type_SetPtr(tp, ($2)->ds_stt);
451*2775Sraf 			declspec_Destroy($2);
452*2775Sraf 			$$ = type_AddTail($3, tp);
453*2775Sraf 		}
454*2775Sraf 	| '*' pointer
455*2775Sraf 		{
456*2775Sraf 			type_t	*tp = type_Construct();
457*2775Sraf 
458*2775Sraf 			type_SetPtr(tp, TQ_NONE);
459*2775Sraf 			$$ = type_AddTail($2, tp);
460*2775Sraf 		}
461*2775Sraf 	;
462*2775Sraf 
463*2775Sraf type_qualifier_list
464*2775Sraf 	: type_qualifier
465*2775Sraf 	| type_qualifier_list type_qualifier
466*2775Sraf 		{
467*2775Sraf 			const char	*ep;
468*2775Sraf 
469*2775Sraf 			/* XXX - ignore any error */
470*2775Sraf 			$$ = declspec_AddDS($1, $2, &ep);
471*2775Sraf 			declspec_Destroy($2);
472*2775Sraf 		}
473*2775Sraf 	;
474*2775Sraf 
475*2775Sraf parameter_type_list
476*2775Sraf 	: parameter_list
477*2775Sraf 	| parameter_list ',' ELLIPSIS
478*2775Sraf 		{
479*2775Sraf 			$$ = decl_addellipsis($1);
480*2775Sraf 		}
481*2775Sraf 	;
482*2775Sraf 
483*2775Sraf parameter_list
484*2775Sraf 	: parameter_declaration
485*2775Sraf 		{
486*2775Sraf 			const char *sp = type_Verify($1->d_type);
487*2775Sraf 
488*2775Sraf 			if (sp)
489*2775Sraf 				errstr = sp;
490*2775Sraf 
491*2775Sraf 			$$ = $1;
492*2775Sraf 			atIDENT = 0;
493*2775Sraf 		}
494*2775Sraf 	| parameter_list ',' parameter_declaration
495*2775Sraf 		{
496*2775Sraf 			const char *sp = type_Verify($3->d_type);
497*2775Sraf 
498*2775Sraf 			if (sp)
499*2775Sraf 				errstr = sp;
500*2775Sraf 
501*2775Sraf 			$$ = decl_AddArg($1, $3);
502*2775Sraf 			atIDENT = 0;
503*2775Sraf 		}
504*2775Sraf 	;
505*2775Sraf 
506*2775Sraf parameter_declaration
507*2775Sraf 	: declaration_specifiers declarator
508*2775Sraf 		{
509*2775Sraf 			const char *ep;
510*2775Sraf 
511*2775Sraf 			$$ = decl_AddDS($2, $1, &ep);
512*2775Sraf 			declspec_Destroy($1);
513*2775Sraf 
514*2775Sraf 			if (errstr == NULL)
515*2775Sraf 				errstr = ep;
516*2775Sraf 		}
517*2775Sraf 	| declaration_specifiers abstract_declarator
518*2775Sraf 		{
519*2775Sraf 			const char *ep;
520*2775Sraf 
521*2775Sraf 			$$ = decl_AddDS($2, $1, &ep);
522*2775Sraf 			declspec_Destroy($1);
523*2775Sraf 
524*2775Sraf 			if (errstr == NULL)
525*2775Sraf 				errstr = ep;
526*2775Sraf 		}
527*2775Sraf 	| declaration_specifiers
528*2775Sraf 		{
529*2775Sraf 			const char *ep;
530*2775Sraf 
531*2775Sraf 			$$ = decl_AddDS(decl_Construct(), $1, &ep);
532*2775Sraf 			declspec_Destroy($1);
533*2775Sraf 
534*2775Sraf 			if (errstr == NULL)
535*2775Sraf 				errstr = ep;
536*2775Sraf 		}
537*2775Sraf 	;
538*2775Sraf 
539*2775Sraf abstract_declarator
540*2775Sraf 	: pointer
541*2775Sraf 		{
542*2775Sraf 			$$ = decl_addptr(decl_Construct(), $1);
543*2775Sraf 		}
544*2775Sraf 	| pointer direct_abstract_declarator
545*2775Sraf 		{
546*2775Sraf 			$$ = decl_addptr($2, $1);
547*2775Sraf 		}
548*2775Sraf 	| direct_abstract_declarator
549*2775Sraf 	;
550*2775Sraf 
551*2775Sraf direct_abstract_declarator
552*2775Sraf 	: '(' abstract_declarator ')'
553*2775Sraf 		{
554*2775Sraf 			$$ = $2;
555*2775Sraf 		}
556*2775Sraf 	| direct_abstract_declarator '[' constant_expression ']'
557*2775Sraf 		{
558*2775Sraf 			$$ = decl_addary($1, $3);
559*2775Sraf 			free($3);
560*2775Sraf 		}
561*2775Sraf 	| '[' constant_expression ']'
562*2775Sraf 		{
563*2775Sraf 			$$ = decl_addary(decl_Construct(), $2);
564*2775Sraf 			free($2);
565*2775Sraf 		}
566*2775Sraf 	| direct_abstract_declarator '[' ']'
567*2775Sraf 		{
568*2775Sraf 			$$ = decl_addary($1, NULL);
569*2775Sraf 		}
570*2775Sraf 	| '[' ']'
571*2775Sraf 		{
572*2775Sraf 			$$ = decl_addary(decl_Construct(), NULL);
573*2775Sraf 		}
574*2775Sraf 	| direct_abstract_declarator '(' parameter_type_list ')'
575*2775Sraf 		{
576*2775Sraf 			$$ = decl_addfun($1, $3);
577*2775Sraf 		}
578*2775Sraf 	| '(' parameter_type_list ')'
579*2775Sraf 		{
580*2775Sraf 			$$ = decl_addfun(decl_Construct(), $2);
581*2775Sraf 		}
582*2775Sraf 	| direct_abstract_declarator '(' ')'
583*2775Sraf 		{
584*2775Sraf 			$$ = decl_addfun($1, NULL);
585*2775Sraf 		}
586*2775Sraf 	| '(' ')'
587*2775Sraf 		{
588*2775Sraf 			$$ = decl_addfun(decl_Construct(), NULL);
589*2775Sraf 		}
590*2775Sraf 	;
591*2775Sraf 
592*2775Sraf /*
593*2775Sraf  * XXX - General case constant expressions are not supported. It would
594*2775Sraf  * be easy to implement (for the most part), but there are no cases to
595*2775Sraf  * date that require such a facility. The grammar does allow an
596*2775Sraf  * identifier (or typedef name) to be used since the prototype is not
597*2775Sraf  * processed by CPP. The only integer constant that is supported is
598*2775Sraf  * decimal.
599*2775Sraf  */
600*2775Sraf 
601*2775Sraf constant_expression
602*2775Sraf 	: INTEGER
603*2775Sraf 	| IDENTIFIER
604*2775Sraf 	| TYPEDEF_NAME
605*2775Sraf 	;
606*2775Sraf 
607*2775Sraf %%
608*2775Sraf 
609*2775Sraf /* Data Declarations */
610*2775Sraf 
611*2775Sraf typedef struct {
612*2775Sraf 	char	*name;
613*2775Sraf 	int	 token;
614*2775Sraf 	stt_t	 stt;
615*2775Sraf } keyword_t;
616*2775Sraf 
617*2775Sraf typedef struct {
618*2775Sraf 	stt_t	 s_stt;
619*2775Sraf 	char	*s_str;
620*2775Sraf } sttpair_t;
621*2775Sraf 
622*2775Sraf /* External Declarations */
623*2775Sraf 
624*2775Sraf static	const keyword_t	*lookup_keyword(const char *);
625*2775Sraf static	const char	*lookup_sttpair(stt_t);
626*2775Sraf static	int		 getch(void);
627*2775Sraf static	void		 ungetch(int);
628*2775Sraf static	void		 skipwhitespace(void);
629*2775Sraf static	int		 lookahead(int);
630*2775Sraf static	void		 skipcomment(void);
631*2775Sraf 
632*2775Sraf /* External Definitions */
633*2775Sraf 
634*2775Sraf static char		*input = NULL;	/* current place in the input stream */
635*2775Sraf /* at point in stream were identifier is expected */
636*2775Sraf static int		 atIDENT = 0;
637*2775Sraf static decl_t		*protop = NULL;	/* pointer to prototype */
638*2775Sraf static const char	*errstr = NULL;	/* error message */
639*2775Sraf 
640*2775Sraf /*
641*2775Sraf  * lookup_keyword - Given a string, return the keyword_t or NULL.
642*2775Sraf  */
643*2775Sraf 
644*2775Sraf static const keyword_t *
lookup_keyword(const char * name)645*2775Sraf lookup_keyword(const char *name) {
646*2775Sraf 	static	const keyword_t	keytbl[] = {
647*2775Sraf 		{	"register",	REGISTER,	SCS_REGISTER	},
648*2775Sraf #if UNSUPPORTED
649*2775Sraf 		{	"typedef",	TYPEDEF,	SCS_TYPEDEF	},
650*2775Sraf 		{	"auto",		AUTO,		SCS_AUTO	},
651*2775Sraf 		{	"static",	STATIC,		SCS_STATIC	},
652*2775Sraf 		{	"extern",	EXTERN,		SCS_EXTERN	},
653*2775Sraf #endif /* UNSUPPORTED */
654*2775Sraf 		{	"void",		VOID,		TS_VOID		},
655*2775Sraf 		{	"char",		CHAR,		TS_CHAR		},
656*2775Sraf 		{	"short",	SHORT,		TS_SHORT	},
657*2775Sraf 		{	"int",		INT,		TS_INT		},
658*2775Sraf 		{	"long",		LONG,		TS_LONG		},
659*2775Sraf 		{	"float",	FLOAT,		TS_FLOAT	},
660*2775Sraf 		{	"double",	DOUBLE,		TS_DOUBLE	},
661*2775Sraf 		{	"signed",	SIGNED,		TS_SIGNED	},
662*2775Sraf 		{	"unsigned",	UNSIGNED,	TS_UNSIGNED	},
663*2775Sraf 		{	"struct",	STRUCT,		TS_STRUCT	},
664*2775Sraf 		{	"union",	UNION,		TS_UNION	},
665*2775Sraf 		{	"enum",		ENUM,		TS_ENUM		},
666*2775Sraf 
667*2775Sraf 		{	"const",	CONST,		TQ_CONST	},
668*2775Sraf 		{	"volatile",	VOLATILE,	TQ_VOLATILE	},
669*2775Sraf 		{	"restrict",	RESTRICT,	TQ_RESTRICT	},
670*2775Sraf 		{	"_RESTRICT_KYWD",RESTRICT_KYWD,	TQ_RESTRICT_KYWD},
671*2775Sraf 	};
672*2775Sraf #define	NKEYWORD	(sizeof (keytbl)/sizeof (keyword_t))
673*2775Sraf 
674*2775Sraf 	int	i;
675*2775Sraf 
676*2775Sraf 	for (i = 0; i < NKEYWORD; ++i) {
677*2775Sraf 		char	*s = keytbl[i].name;
678*2775Sraf 
679*2775Sraf 		if ((*s == *name) && (strcmp(s, name) == 0))
680*2775Sraf 			return (&keytbl[i]);
681*2775Sraf 	}
682*2775Sraf 
683*2775Sraf 	return (NULL);
684*2775Sraf }
685*2775Sraf 
686*2775Sraf /*
687*2775Sraf  * lookup_sttpair - Given an stt_t return a string or NULL.
688*2775Sraf  *
689*2775Sraf  */
690*2775Sraf 
691*2775Sraf static const char *
lookup_sttpair(stt_t s)692*2775Sraf lookup_sttpair(stt_t s) {
693*2775Sraf 	/* valid type specifier combinations */
694*2775Sraf 	static const sttpair_t	stttbl[] = {
695*2775Sraf 		{ TS_VOID,				"void"		},
696*2775Sraf 		{ TS_CHAR,				"char"		},
697*2775Sraf 		{ TS_SIGNED | TS_CHAR,			"signed char"	},
698*2775Sraf 		{ TS_UNSIGNED | TS_CHAR,		"unsigned char"	},
699*2775Sraf 		{ TS_SHORT,				"short"		},
700*2775Sraf 		{ TS_SIGNED | TS_SHORT,			"signed short"	},
701*2775Sraf 		{ TS_SHORT | TS_INT,			"short int"	},
702*2775Sraf 		{ TS_SIGNED | TS_SHORT | TS_INT,
703*2775Sraf 		    "signed short int"				},
704*2775Sraf 		{ TS_UNSIGNED | TS_SHORT,
705*2775Sraf 		    "unsigned short"					},
706*2775Sraf 		{ TS_UNSIGNED | TS_SHORT | TS_INT,
707*2775Sraf 		    "unsigned short int"				},
708*2775Sraf 		{ TS_INT,				"int"		},
709*2775Sraf 		{ TS_SIGNED,				"signed"	},
710*2775Sraf 		{ TS_SIGNED | TS_INT,			"signed int"	},
711*2775Sraf 		{ TS_NO_TS,				""		},
712*2775Sraf 		{ TS_UNSIGNED,				"unsigned"	},
713*2775Sraf 		{ TS_UNSIGNED | TS_INT,			"unsigned int"	},
714*2775Sraf 		{ TS_LONG,				"long"		},
715*2775Sraf 		{ TS_SIGNED | TS_LONG,			"signed long"	},
716*2775Sraf 		{ TS_LONG | TS_INT,			"long int"	},
717*2775Sraf 		{ TS_SIGNED | TS_LONG | TS_INT,
718*2775Sraf 		    "signed long int"					},
719*2775Sraf 		{ TS_UNSIGNED | TS_LONG,		"unsigned long"	},
720*2775Sraf 		{ TS_UNSIGNED | TS_LONG | TS_INT,
721*2775Sraf 		    "unsigned long int"				},
722*2775Sraf 		{ TS_FLOAT,				"float"		},
723*2775Sraf 		{ TS_DOUBLE,				"double"	},
724*2775Sraf 		{ TS_LONG | TS_DOUBLE,			"long double"	},
725*2775Sraf 		{ TS_STRUCT,				"struct"	},
726*2775Sraf 		{ TS_UNION,				"union"		},
727*2775Sraf 		{ TS_ENUM,				"enum"		},
728*2775Sraf 		{ TS_TYPEDEF,				""		},
729*2775Sraf 		/* non-ANSI type: long long */
730*2775Sraf 		{ TS_LONGLONG,				"long long"	},
731*2775Sraf 		{ TS_LONGLONG | TS_INT,			"long long int"	},
732*2775Sraf 		{ TS_SIGNED | TS_LONGLONG,
733*2775Sraf 		    "signed long long"				},
734*2775Sraf 		{ TS_UNSIGNED | TS_LONGLONG,
735*2775Sraf 		    "unsigned long long"				},
736*2775Sraf 		{ TS_SIGNED | TS_LONGLONG | TS_INT,
737*2775Sraf 		    "signed long long int"				},
738*2775Sraf 		{ TS_UNSIGNED | TS_LONGLONG | TS_INT,
739*2775Sraf 		    "unsigned long long int"				},
740*2775Sraf 	};
741*2775Sraf 
742*2775Sraf #define	NDECLSPEC	(sizeof (stttbl)/sizeof (sttpair_t))
743*2775Sraf 
744*2775Sraf 	int	i;
745*2775Sraf 
746*2775Sraf 	for (i = 0; i < NDECLSPEC; ++i)
747*2775Sraf 		if (s == stttbl[i].s_stt)
748*2775Sraf 			return (stttbl[i].s_str);
749*2775Sraf 
750*2775Sraf 	return (NULL);
751*2775Sraf }
752*2775Sraf 
753*2775Sraf /*
754*2775Sraf  * yylex - return next token from the the input stream.
755*2775Sraf  *
756*2775Sraf  * The lexical analyzer does not recognize all possible C lexical
757*2775Sraf  * elements. It only recognizes those associated with function
758*2775Sraf  * declarations (read: prototypes) and data definitions.
759*2775Sraf  */
760*2775Sraf 
761*2775Sraf static int
yylex(void)762*2775Sraf yylex(void) {
763*2775Sraf 	char	buf[BUFSIZ];		/* string version of token */
764*2775Sraf 	int	c;
765*2775Sraf 	int	i = 0;
766*2775Sraf 
767*2775Sraf restart:
768*2775Sraf 	skipwhitespace();
769*2775Sraf 
770*2775Sraf 	switch (c = getch()) {
771*2775Sraf 	case '/':
772*2775Sraf 		if (lookahead('*')) {
773*2775Sraf 			skipcomment();
774*2775Sraf 			goto restart;
775*2775Sraf 		}
776*2775Sraf 
777*2775Sraf 	case '.':
778*2775Sraf 		if (lookahead('.')) {
779*2775Sraf 			if (lookahead('.'))
780*2775Sraf 				return (ELLIPSIS);
781*2775Sraf 		}
782*2775Sraf 
783*2775Sraf 	case EOF:
784*2775Sraf 	case '(':
785*2775Sraf 	case ')':
786*2775Sraf 	case ',':
787*2775Sraf 	case '[':
788*2775Sraf 	case ']':
789*2775Sraf 	case ';':
790*2775Sraf 	case '*':
791*2775Sraf 		return (c);
792*2775Sraf 
793*2775Sraf 	default:
794*2775Sraf 		if ((c == '_') || isalpha(c)) {
795*2775Sraf 			const keyword_t	*kp;
796*2775Sraf 
797*2775Sraf 			do {
798*2775Sraf 				buf[i++] = c;
799*2775Sraf 				c	 = getch();
800*2775Sraf 			} while ((c == '_') || isalnum(c));
801*2775Sraf 
802*2775Sraf 			ungetch(c);
803*2775Sraf 
804*2775Sraf 			buf[i] = '\0';
805*2775Sraf 
806*2775Sraf 			if ((kp = lookup_keyword(buf)) != NULL) {
807*2775Sraf 				yylval.stt_val = kp->stt;
808*2775Sraf 				return (kp->token);
809*2775Sraf 			} else {
810*2775Sraf 				yylval.s_val = strdup(buf);
811*2775Sraf 
812*2775Sraf 				return ((atIDENT) ? IDENTIFIER : TYPEDEF_NAME);
813*2775Sraf 			}
814*2775Sraf 		} else if (isdigit(c)) {
815*2775Sraf 			do {
816*2775Sraf 				buf[i++] = c;
817*2775Sraf 			} while (isdigit(c = getch()));
818*2775Sraf 
819*2775Sraf 			ungetch(c);
820*2775Sraf 
821*2775Sraf 			buf[i]	 = '\0';
822*2775Sraf 			yylval.s_val = strdup(buf);
823*2775Sraf 
824*2775Sraf 			return (INTEGER);
825*2775Sraf 		} else
826*2775Sraf 			return (c);
827*2775Sraf 	}
828*2775Sraf /* NOTREACHED */
829*2775Sraf }
830*2775Sraf 
831*2775Sraf /* getch - return the next character from the input stream. */
832*2775Sraf 
833*2775Sraf static int
getch(void)834*2775Sraf getch(void) {
835*2775Sraf 	int	c;
836*2775Sraf 
837*2775Sraf 	if ((c = *input) == '\0')
838*2775Sraf 		c = EOF;
839*2775Sraf 	else				/* only advance on non-NULL */
840*2775Sraf 		input++;
841*2775Sraf 
842*2775Sraf 	return (c);
843*2775Sraf }
844*2775Sraf 
845*2775Sraf /* ungetch - return a character to the input stream. */
846*2775Sraf 
847*2775Sraf static void
ungetch(int c)848*2775Sraf ungetch(int c) {
849*2775Sraf 	*(--input) = c;
850*2775Sraf }
851*2775Sraf 
852*2775Sraf /* skipwhitespace - skip over whitespace in the input stream. */
853*2775Sraf 
854*2775Sraf static void
skipwhitespace(void)855*2775Sraf skipwhitespace(void) {
856*2775Sraf 	int	c;
857*2775Sraf 
858*2775Sraf 	while (isspace(c = getch()))
859*2775Sraf 		;
860*2775Sraf 
861*2775Sraf 	ungetch(c);
862*2775Sraf }
863*2775Sraf 
864*2775Sraf /* skipcomment - scan ahead to the next end of comment. */
865*2775Sraf 
866*2775Sraf static void
skipcomment(void)867*2775Sraf skipcomment(void) {
868*2775Sraf 	loop {
869*2775Sraf 		int	c;
870*2775Sraf 
871*2775Sraf 		switch (c = getch()) {
872*2775Sraf 		case EOF:
873*2775Sraf 			return;
874*2775Sraf 
875*2775Sraf 		case '*':
876*2775Sraf 			if (lookahead('/'))
877*2775Sraf 				return;
878*2775Sraf 		}
879*2775Sraf 	}
880*2775Sraf /* NOTREACHED */
881*2775Sraf }
882*2775Sraf 
883*2775Sraf /* lookahead - does next character match 'c'? */
884*2775Sraf 
885*2775Sraf static int
lookahead(int c)886*2775Sraf lookahead(int c) {
887*2775Sraf 	int	ch = getch();
888*2775Sraf 	int	match;
889*2775Sraf 
890*2775Sraf 	if (!(match = (ch == c)))
891*2775Sraf 		ungetch(ch);
892*2775Sraf 
893*2775Sraf 	return (match);
894*2775Sraf }
895*2775Sraf 
896*2775Sraf /* putNtabs - write N '\t' to standard output. */
897*2775Sraf 
898*2775Sraf #if defined(DEBUG)
899*2775Sraf 
900*2775Sraf static void
putNTabs(int n)901*2775Sraf putNTabs(int n) {
902*2775Sraf 	int	 i;
903*2775Sraf 
904*2775Sraf 	for (i = 0; i < n; ++i)
905*2775Sraf 		putchar('\t');
906*2775Sraf }
907*2775Sraf #endif	/* DEBUG */
908*2775Sraf 
909*2775Sraf /* D E C L A R A T I O N   S P E C I F I E R S */
910*2775Sraf 
911*2775Sraf /*
912*2775Sraf  * Declaration specifiers encode storage class, type specifier and type
913*2775Sraf  * qualifier information. This includes any identifiers associated with
914*2775Sraf  * struct, union or enum declarations. Typedef names are also encoded
915*2775Sraf  * in declaration specifiers.
916*2775Sraf  */
917*2775Sraf 
918*2775Sraf /* declspec_Construct - allocate and initialize a declspec_t. */
919*2775Sraf 
920*2775Sraf static decl_spec_t *
declspec_Construct(void)921*2775Sraf declspec_Construct(void) {
922*2775Sraf 	decl_spec_t	*dsp = malloc(sizeof (decl_spec_t));
923*2775Sraf 
924*2775Sraf 	assert(dsp != NULL);
925*2775Sraf 	dsp->ds_stt = SCS_NONE | TS_NO_TS | TQ_NONE;
926*2775Sraf 	dsp->ds_id = NULL;
927*2775Sraf #if defined(MEM_DEBUG)
928*2775Sraf 	++declspec_Construct_calls;
929*2775Sraf #endif
930*2775Sraf 	return (dsp);
931*2775Sraf }
932*2775Sraf 
933*2775Sraf /* declspec_Destroy - free a declspec_t. */
934*2775Sraf 
935*2775Sraf static void
declspec_Destroy(decl_spec_t * dsp)936*2775Sraf declspec_Destroy(decl_spec_t *dsp) {
937*2775Sraf 	free(dsp->ds_id);
938*2775Sraf 	free(dsp);
939*2775Sraf #if defined(MEM_DEBUG)
940*2775Sraf 	--declspec_Construct_calls;
941*2775Sraf #endif
942*2775Sraf }
943*2775Sraf 
944*2775Sraf /*
945*2775Sraf  * declspec_Init - allocate and initialize a declspec_t given an
946*2775Sraf  *	stt_t and identifier.
947*2775Sraf  *
948*2775Sraf  * Note:
949*2775Sraf  *	1) identifier can be NULL.
950*2775Sraf  *	2) errors resulting in the stt_t and identifier are ignored.
951*2775Sraf  */
952*2775Sraf 
953*2775Sraf static decl_spec_t *
declspec_Init(stt_t s,char * tagp)954*2775Sraf declspec_Init(stt_t s, char *tagp) {
955*2775Sraf 	const char	*p;
956*2775Sraf 	decl_spec_t	*dsp = declspec_Construct();
957*2775Sraf 	decl_spec_t	 tmp;
958*2775Sraf 
959*2775Sraf 	tmp.ds_stt = s;
960*2775Sraf 	tmp.ds_id = tagp;
961*2775Sraf 
962*2775Sraf 	declspec_AddDS(dsp, &tmp, &p);		/* XXX ignore any error */
963*2775Sraf 
964*2775Sraf 	return (dsp);
965*2775Sraf }
966*2775Sraf 
967*2775Sraf /*
968*2775Sraf  * declspec_VerifySTT - verify that the two given stt_t can be combined.
969*2775Sraf  *
970*2775Sraf  * Note:
971*2775Sraf  *	1) The return value is a const char *, non-NULL to indicate an error.
972*2775Sraf  */
973*2775Sraf 
974*2775Sraf static char *
declspec_VerifySTT(stt_t s1,stt_t s2)975*2775Sraf declspec_VerifySTT(stt_t s1, stt_t s2) {
976*2775Sraf 	stt_t	result;
977*2775Sraf 
978*2775Sraf 	if ((s1 | s2) != (s1 ^ s2))
979*2775Sraf 		return ("attempt to add declaration specifier "
980*2775Sraf 		    "that is already present");
981*2775Sraf 
982*2775Sraf 	result = (s1 | s2) & TS_MASK;
983*2775Sraf 
984*2775Sraf 	if (lookup_sttpair(result) == NULL) {
985*2775Sraf 		if (STT_isbasic(result) && STT_isderived(result))
986*2775Sraf 			return ("attempt to combine basic and "
987*2775Sraf 			    "derived types");
988*2775Sraf 
989*2775Sraf 		if (STT_isvoid(result) &&
990*2775Sraf 		    (STT_isbasic(result) || STT_isderived(result)))
991*2775Sraf 			return ("attempt to combine void with "
992*2775Sraf 			    "other type specifiers");
993*2775Sraf 
994*2775Sraf 		if (STT_isfloat(result) && STT_isint(result))
995*2775Sraf 			return ("attempt to combine floating and "
996*2775Sraf 			    "integer type specifiers");
997*2775Sraf 
998*2775Sraf 		if (STT_ischar(result) && STT_isint(result))
999*2775Sraf 			return ("attempt to combine character and "
1000*2775Sraf 			    "integer type specifiers");
1001*2775Sraf 
1002*2775Sraf 		if (STT_has_explicit_sign(result) &&
1003*2775Sraf 		    (STT_isfloat(result) || STT_isderived(result)))
1004*2775Sraf 			return ("attempt to combine signed or "
1005*2775Sraf 			    "unsigned with float or derived type");
1006*2775Sraf 
1007*2775Sraf 		return ("invalid declaration specifier");
1008*2775Sraf 	}
1009*2775Sraf 
1010*2775Sraf 	return (NULL);
1011*2775Sraf }
1012*2775Sraf 
1013*2775Sraf /*
1014*2775Sraf  * declspec_AddSTT - add an stt_t to a decl_spec_t.
1015*2775Sraf  *
1016*2775Sraf  * Note:
1017*2775Sraf  *	1) The "long long" type is handled here.
1018*2775Sraf  *	   If both stt_t include TS_LONG then this is an attempt to use
1019*2775Sraf  *	   "long long". The TS_LONG is cleared from the s1 and s2 and
1020*2775Sraf  *	   then TS_LONGLONG is added to s2. The resulting s1 and s2 are
1021*2775Sraf  *	   passed to declspec_VerifySTT to determine if the result is valid.
1022*2775Sraf  *
1023*2775Sraf  *	2) This method of handling "long long" does detect the case of
1024*2775Sraf  *	   "long double long" and all it's variant forms.
1025*2775Sraf  */
1026*2775Sraf 
1027*2775Sraf static decl_spec_t *
declspec_AddSTT(decl_spec_t * dsp,stt_t s2,const char ** err)1028*2775Sraf declspec_AddSTT(decl_spec_t *dsp, stt_t s2, const char **err) {
1029*2775Sraf 	stt_t	s1 = dsp->ds_stt;
1030*2775Sraf 
1031*2775Sraf 	/* non-ANSI type: long long */
1032*2775Sraf 	if ((s1 & TS_LONG) && (s2 & TS_LONG)) {
1033*2775Sraf 		s1		&= ~(TS_LONG);
1034*2775Sraf 		dsp->ds_stt = s1;
1035*2775Sraf 		s2		&= ~(TS_LONG);
1036*2775Sraf 		s2		|= TS_LONGLONG;
1037*2775Sraf 	}
1038*2775Sraf 
1039*2775Sraf 	if ((*err = declspec_VerifySTT(s1, s2)) == NULL)
1040*2775Sraf 		dsp->ds_stt	|= s2;
1041*2775Sraf 
1042*2775Sraf 	return (dsp);
1043*2775Sraf }
1044*2775Sraf 
1045*2775Sraf /*
1046*2775Sraf  * declpec_AddDS - add a decl_spec_t to an existing decl_spec_t.
1047*2775Sraf  */
1048*2775Sraf 
1049*2775Sraf static decl_spec_t *
declspec_AddDS(decl_spec_t * dsp,decl_spec_t * tsp,const char ** err)1050*2775Sraf declspec_AddDS(decl_spec_t *dsp, decl_spec_t *tsp, const char **err) {
1051*2775Sraf 	declspec_AddSTT(dsp, tsp->ds_stt, err);
1052*2775Sraf 
1053*2775Sraf 	if ((*err == NULL) && tsp->ds_id) {
1054*2775Sraf 		free(dsp->ds_id);
1055*2775Sraf 		dsp->ds_id	 = strdup(tsp->ds_id);
1056*2775Sraf 
1057*2775Sraf 		assert(dsp->ds_id != NULL);
1058*2775Sraf 	}
1059*2775Sraf 
1060*2775Sraf 	return (dsp);
1061*2775Sraf }
1062*2775Sraf 
1063*2775Sraf /*
1064*2775Sraf  * declspec_GetSTT - return the stt_t within a decl_spec_t.
1065*2775Sraf  */
1066*2775Sraf 
1067*2775Sraf static stt_t
declspec_GetSTT(decl_spec_t * dsp)1068*2775Sraf declspec_GetSTT(decl_spec_t *dsp) {
1069*2775Sraf 	return (dsp->ds_stt);
1070*2775Sraf }
1071*2775Sraf 
1072*2775Sraf /*
1073*2775Sraf  * declspec_GetTag - return the identifier within a decl_spec_t.
1074*2775Sraf  */
1075*2775Sraf 
1076*2775Sraf static char *
declspec_GetTag(decl_spec_t * dsp)1077*2775Sraf declspec_GetTag(decl_spec_t *dsp) {
1078*2775Sraf 	return (dsp->ds_id);
1079*2775Sraf }
1080*2775Sraf 
1081*2775Sraf /*
1082*2775Sraf  * declspec_ToString - convert a decl_spec_t into a string.
1083*2775Sraf  *
1084*2775Sraf  * Note:
1085*2775Sraf  *	1) The form of the resulting string is always the same, i.e.
1086*2775Sraf  *
1087*2775Sraf  *		[register] [type_specifier] [const] [volatile]
1088*2775Sraf  *
1089*2775Sraf  * dsp must be correct
1090*2775Sraf  *
1091*2775Sraf  */
1092*2775Sraf 
1093*2775Sraf char *
declspec_ToString(char * bufp,decl_spec_t * dsp)1094*2775Sraf declspec_ToString(char *bufp, decl_spec_t *dsp) {
1095*2775Sraf 	const char	*s;
1096*2775Sraf 	int		 something = 0;
1097*2775Sraf 
1098*2775Sraf 	*bufp = '\0';
1099*2775Sraf 
1100*2775Sraf 	/* storage class specifier */
1101*2775Sraf 	switch (dsp->ds_stt & SCS_MASK) {
1102*2775Sraf 	case SCS_REGISTER:
1103*2775Sraf 		strcat(bufp, "register");
1104*2775Sraf 		something = 1;
1105*2775Sraf 		break;
1106*2775Sraf 	}
1107*2775Sraf 
1108*2775Sraf 	s = lookup_sttpair(dsp->ds_stt & TS_MASK);
1109*2775Sraf 
1110*2775Sraf 	/* type specifier */
1111*2775Sraf 	switch (dsp->ds_stt & TS_MASK) {
1112*2775Sraf 	case TS_STRUCT:
1113*2775Sraf 	case TS_UNION:
1114*2775Sraf 	case TS_ENUM:
1115*2775Sraf 		if (something)
1116*2775Sraf 			strcat(bufp, " ");
1117*2775Sraf 
1118*2775Sraf 		strcat(bufp, s);
1119*2775Sraf 		strcat(bufp, " ");
1120*2775Sraf 		strcat(bufp, dsp->ds_id);
1121*2775Sraf 		break;
1122*2775Sraf 
1123*2775Sraf 	case TS_TYPEDEF:
1124*2775Sraf 		if (something)
1125*2775Sraf 			strcat(bufp, " ");
1126*2775Sraf 
1127*2775Sraf 		strcat(bufp, dsp->ds_id);
1128*2775Sraf 		break;
1129*2775Sraf 
1130*2775Sraf 	default:
1131*2775Sraf 		if (something)
1132*2775Sraf 			strcat(bufp, " ");
1133*2775Sraf 
1134*2775Sraf 		strcat(bufp, s);
1135*2775Sraf 		break;
1136*2775Sraf 	}
1137*2775Sraf 
1138*2775Sraf 	if (s)
1139*2775Sraf 		something = 1;
1140*2775Sraf 
1141*2775Sraf 	if (something && (dsp->ds_stt & TQ_MASK))
1142*2775Sraf 		strcat(bufp, " ");
1143*2775Sraf 
1144*2775Sraf 	if (dsp->ds_stt & TQ_CONST)	/* type qualifier */
1145*2775Sraf 		strcat(bufp, "const");
1146*2775Sraf 
1147*2775Sraf 	if (dsp->ds_stt & TQ_VOLATILE) {
1148*2775Sraf 		if (dsp->ds_stt & TQ_CONST)
1149*2775Sraf 			strcat(bufp, " ");
1150*2775Sraf 
1151*2775Sraf 		strcat(bufp, "volatile");
1152*2775Sraf 	}
1153*2775Sraf 
1154*2775Sraf 	/*
1155*2775Sraf 	 * It currently acknowledges and ignores restrict or _RESTRICT_KYWD
1156*2775Sraf 	 * in code generation because of the uncertain behavior of "restrict".
1157*2775Sraf 	 */
1158*2775Sraf 	if (dsp->ds_stt & TQ_RESTRICT)
1159*2775Sraf 		strcat(bufp, "");
1160*2775Sraf 
1161*2775Sraf 	if (dsp->ds_stt & TQ_RESTRICT_KYWD)
1162*2775Sraf 		strcat(bufp, "");
1163*2775Sraf 
1164*2775Sraf 	return (bufp);
1165*2775Sraf }
1166*2775Sraf 
1167*2775Sraf /* T Y P E   M O D I F I E R S */
1168*2775Sraf 
1169*2775Sraf /*
1170*2775Sraf  * Type modifiers encode the "array of...", "pointer to ..." and
1171*2775Sraf  * "function returning ..." aspects of C types. The modifiers are kept
1172*2775Sraf  * as a linked list in precedence order. The grammar encodes the
1173*2775Sraf  * precedence order described by the standard.
1174*2775Sraf  *
1175*2775Sraf  * Type modifiers are always added at the end of list and the list is
1176*2775Sraf  * always traversed from head to tail.
1177*2775Sraf  */
1178*2775Sraf 
1179*2775Sraf /* type_Construct - allocate and initialize a type_t. */
1180*2775Sraf 
1181*2775Sraf static type_t *
type_Construct(void)1182*2775Sraf type_Construct(void) {
1183*2775Sraf 	type_t	*tp = malloc(sizeof (type_t));
1184*2775Sraf 
1185*2775Sraf 	assert(tp != NULL);
1186*2775Sraf 
1187*2775Sraf 	tp->t_next = NULL;			/* generic */
1188*2775Sraf 	tp->t_dt = DD_NONE;
1189*2775Sraf 
1190*2775Sraf 	tp->t_nargs = 0;			/* DD_FUN */
1191*2775Sraf 	tp->t_ellipsis = 0;
1192*2775Sraf 	tp->t_args = NULL;
1193*2775Sraf 						/* DD_PTR */
1194*2775Sraf 	tp->t_stt	 = (SCS_NONE | TS_NO_TS | TQ_NONE);
1195*2775Sraf 
1196*2775Sraf 	tp->t_sizestr = NULL;			/* DD_ARY */
1197*2775Sraf #if defined(MEM_DEBUG)
1198*2775Sraf 	++type_Construct_calls;
1199*2775Sraf #endif
1200*2775Sraf 	return (tp);
1201*2775Sraf }
1202*2775Sraf 
1203*2775Sraf /* type_Destroy - free a type_t list. */
1204*2775Sraf 
1205*2775Sraf static void
type_Destroy(type_t * tp)1206*2775Sraf type_Destroy(type_t *tp) {
1207*2775Sraf 	while (tp) {
1208*2775Sraf 		type_t	*nextp = tp->t_next;
1209*2775Sraf 
1210*2775Sraf 		switch (tp->t_dt) {
1211*2775Sraf 		case DD_FUN:
1212*2775Sraf 			decl_Destroy(tp->t_args);
1213*2775Sraf 			break;
1214*2775Sraf 
1215*2775Sraf 		case DD_PTR:
1216*2775Sraf 			break;
1217*2775Sraf 
1218*2775Sraf 		case DD_ARY:
1219*2775Sraf 			free(tp->t_sizestr);
1220*2775Sraf 			break;
1221*2775Sraf 		}
1222*2775Sraf 
1223*2775Sraf 		free(tp);
1224*2775Sraf 
1225*2775Sraf 		tp = nextp;
1226*2775Sraf #if defined(MEM_DEBUG)
1227*2775Sraf 		--type_Construct_calls;
1228*2775Sraf #endif
1229*2775Sraf 	}
1230*2775Sraf }
1231*2775Sraf 
1232*2775Sraf /*
1233*2775Sraf  * type_SetPtr - make a type_t into a "pointer to ..." variant.
1234*2775Sraf  *
1235*2775Sraf  * Note:
1236*2775Sraf  *	1) The stt_t will encode any type qualifiers (const, volatile).
1237*2775Sraf  */
1238*2775Sraf 
1239*2775Sraf static type_t *
type_SetPtr(type_t * tp,stt_t s)1240*2775Sraf type_SetPtr(type_t *tp, stt_t s) {
1241*2775Sraf 	assert(tp->t_dt == DD_NONE);
1242*2775Sraf 
1243*2775Sraf 	tp->t_dt = DD_PTR;
1244*2775Sraf 	tp->t_stt = s & TQ_MASK;
1245*2775Sraf 
1246*2775Sraf 	return (tp);
1247*2775Sraf }
1248*2775Sraf 
1249*2775Sraf /*
1250*2775Sraf  * type_SetAry - make a type_t into an "array of ...", variant.
1251*2775Sraf  *
1252*2775Sraf  * Note:
1253*2775Sraf  *	1) The array dimension can be NULL to indicate undefined, i.e. [].
1254*2775Sraf  */
1255*2775Sraf 
1256*2775Sraf static type_t *
type_SetAry(type_t * tp,char * dim)1257*2775Sraf type_SetAry(type_t *tp, char *dim) {
1258*2775Sraf 	assert(tp->t_dt == DD_NONE);
1259*2775Sraf 	assert(tp->t_sizestr == NULL);
1260*2775Sraf 
1261*2775Sraf 	tp->t_dt = DD_ARY;
1262*2775Sraf 
1263*2775Sraf 	if (dim) {
1264*2775Sraf 		tp->t_sizestr = strdup(dim);
1265*2775Sraf 		assert(tp->t_sizestr != NULL);
1266*2775Sraf 	} else
1267*2775Sraf 		tp->t_sizestr = NULL;
1268*2775Sraf 
1269*2775Sraf 	return (tp);
1270*2775Sraf }
1271*2775Sraf 
1272*2775Sraf /*
1273*2775Sraf  * type_SetFun - make a type_t into a "function returning ..." variant.
1274*2775Sraf  *
1275*2775Sraf  * Note:
1276*2775Sraf  *	1) The argument list can be NULL to indicate undefined, i.e. ().
1277*2775Sraf  */
1278*2775Sraf 
1279*2775Sraf static type_t *
type_SetFun(type_t * tp,decl_t * arglist)1280*2775Sraf type_SetFun(type_t *tp, decl_t *arglist) {
1281*2775Sraf 	assert(tp->t_dt == DD_NONE);
1282*2775Sraf 
1283*2775Sraf 	tp->t_dt = DD_FUN;
1284*2775Sraf 
1285*2775Sraf 	if (arglist) {
1286*2775Sraf 		tp->t_nargs = decl_GetArgLength(arglist);
1287*2775Sraf 		tp->t_args = arglist;
1288*2775Sraf 		tp->t_ellipsis = arglist->d_ellipsis;
1289*2775Sraf 	}
1290*2775Sraf 
1291*2775Sraf 	return (tp);
1292*2775Sraf }
1293*2775Sraf 
1294*2775Sraf /*
1295*2775Sraf  * type_AddTail - add a type_t to the end of an existing type_t list.
1296*2775Sraf  *
1297*2775Sraf  * Note:
1298*2775Sraf  *	1) The type_t *tp is added to the end of the type_t *dp list.
1299*2775Sraf  */
1300*2775Sraf 
1301*2775Sraf static type_t *
type_AddTail(type_t * dp,type_t * tp)1302*2775Sraf type_AddTail(type_t *dp, type_t *tp) {
1303*2775Sraf 	type_t	*lastp = dp;
1304*2775Sraf 	type_t	*p;
1305*2775Sraf 
1306*2775Sraf 	while (p = lastp->t_next)
1307*2775Sraf 		lastp = p;
1308*2775Sraf 
1309*2775Sraf 	lastp->t_next = tp;
1310*2775Sraf 
1311*2775Sraf 	return (dp);
1312*2775Sraf }
1313*2775Sraf 
1314*2775Sraf #if defined(DEBUG)
1315*2775Sraf 
1316*2775Sraf /* type_PrintType - print a type_t list onto standard output. */
1317*2775Sraf 
1318*2775Sraf static void
type_PrintType(type_t * tp,int lvl)1319*2775Sraf type_PrintType(type_t *tp, int lvl) {
1320*2775Sraf 	decl_spec_t	tmp;
1321*2775Sraf 	char		buf[BUFSIZ];
1322*2775Sraf 
1323*2775Sraf 	while (tp) {
1324*2775Sraf 		putNTabs(lvl);
1325*2775Sraf 
1326*2775Sraf 		switch (tp->t_dt) {
1327*2775Sraf 		case DD_PTR:
1328*2775Sraf 			tmp.ds_stt = tp->t_stt;
1329*2775Sraf 			tmp.ds_id = NULL;
1330*2775Sraf 
1331*2775Sraf 			printf("[%s] ptr to\n", declspec_ToString(buf, &tmp));
1332*2775Sraf 			break;
1333*2775Sraf 
1334*2775Sraf 		case DD_FUN:
1335*2775Sraf 			printf("fun [%d%c] %s\n",
1336*2775Sraf 			    tp->t_nargs,
1337*2775Sraf 			    (tp->t_ellipsis)? '+' : '=',
1338*2775Sraf 			    (tp->t_args)? "with arguments" :
1339*2775Sraf 			    "undefined arguments");
1340*2775Sraf 
1341*2775Sraf 			if (tp->t_args) {
1342*2775Sraf 				decl_PrintDecl(tp->t_args, lvl + 1);
1343*2775Sraf 
1344*2775Sraf 				if (tp->t_ellipsis) {
1345*2775Sraf 					putNTabs(lvl + 1);
1346*2775Sraf 					printf("...\n");
1347*2775Sraf 				}
1348*2775Sraf 			}
1349*2775Sraf 			break;
1350*2775Sraf 
1351*2775Sraf 		case DD_ARY:
1352*2775Sraf 			printf("ary [%s] of\n",
1353*2775Sraf 			    (tp->t_sizestr)? tp->t_sizestr : "");
1354*2775Sraf 			break;
1355*2775Sraf 		}
1356*2775Sraf 
1357*2775Sraf 		tp = tp->t_next;
1358*2775Sraf 	}
1359*2775Sraf }
1360*2775Sraf #endif	/* DEBUG */
1361*2775Sraf 
1362*2775Sraf /*
1363*2775Sraf  * type_Verify - verify a type_t list for semantic correctness.
1364*2775Sraf  *
1365*2775Sraf  * Note:
1366*2775Sraf  *	1) C supports most combinations of type modifiers.
1367*2775Sraf  *	   It does not support three combinations, they are:
1368*2775Sraf  *
1369*2775Sraf  *		function returning array
1370*2775Sraf  *		array of functions
1371*2775Sraf  *		function returning function
1372*2775Sraf  *
1373*2775Sraf  *	2) The enum values associated with type modifiers (i.e. DD_*)
1374*2775Sraf  *	   cannot be modified without changing the table included within the
1375*2775Sraf  *	   function.
1376*2775Sraf  *
1377*2775Sraf  * 	3) The function returns NULL to indicate that the type modifier
1378*2775Sraf  *	   list is valid and non-NULL to indicate an error.
1379*2775Sraf  *
1380*2775Sraf  *	4) A type_t of NULL is permitted to indicate an empty type_t list.
1381*2775Sraf  */
1382*2775Sraf 
1383*2775Sraf static const char *
type_Verify(type_t * tp)1384*2775Sraf type_Verify(type_t *tp) {
1385*2775Sraf 	static const char *dttbl[4][4] = {
1386*2775Sraf 		/* NONE	ARY	FUN	PTR */
1387*2775Sraf /* NONE */	{NULL,	NULL,	NULL,	NULL},
1388*2775Sraf /* ARY */	{NULL,	NULL,	"array of functions", NULL},
1389*2775Sraf /* FUN */	{NULL,	"function returning array",
1390*2775Sraf 		    "function returning function", NULL},
1391*2775Sraf /* PTR */	{NULL,	NULL,	NULL,	NULL},
1392*2775Sraf 	};
1393*2775Sraf 
1394*2775Sraf 	if (tp) {
1395*2775Sraf 		type_t	*nextp;
1396*2775Sraf 
1397*2775Sraf 		do {
1398*2775Sraf 			const char	*p;
1399*2775Sraf 			decl_type_t	 nt;
1400*2775Sraf 
1401*2775Sraf 			nt = (nextp = tp->t_next)? nextp->t_dt : DD_NONE;
1402*2775Sraf 
1403*2775Sraf 			if ((p = dttbl[tp->t_dt][nt]) != NULL)
1404*2775Sraf 				return (p);
1405*2775Sraf 
1406*2775Sraf 		} while (tp = nextp);
1407*2775Sraf 	}
1408*2775Sraf 
1409*2775Sraf 	return (NULL);
1410*2775Sraf }
1411*2775Sraf 
1412*2775Sraf /* type_GetNext - return the next type_t in the list. */
1413*2775Sraf 
1414*2775Sraf type_t *
type_GetNext(type_t * tp)1415*2775Sraf type_GetNext(type_t *tp) {
1416*2775Sraf 	return (tp->t_next);
1417*2775Sraf }
1418*2775Sraf 
1419*2775Sraf /*
1420*2775Sraf  * The following group of functions return and or
1421*2775Sraf  * test various aspects of type modifiers.
1422*2775Sraf  *
1423*2775Sraf  * 1) The three functions: type_IsPtrTo, type_IsFunction and
1424*2775Sraf  *    type_IsArray will accept an argument of NULL.
1425*2775Sraf  *
1426*2775Sraf  * 2) All other functions require one of the above three to be true.
1427*2775Sraf  *    Various asserts are in place to verify correct usage.
1428*2775Sraf  */
1429*2775Sraf 
1430*2775Sraf int
type_IsArray(type_t * tp)1431*2775Sraf type_IsArray(type_t *tp) {
1432*2775Sraf 	return (tp && (tp->t_dt == DD_ARY));
1433*2775Sraf }
1434*2775Sraf 
1435*2775Sraf char *
type_GetArraySize(type_t * tp)1436*2775Sraf type_GetArraySize(type_t *tp) {
1437*2775Sraf 	assert(tp->t_dt == DD_ARY);
1438*2775Sraf 
1439*2775Sraf 	return (tp->t_sizestr);
1440*2775Sraf }
1441*2775Sraf 
1442*2775Sraf int
type_IsPtrTo(type_t * tp)1443*2775Sraf type_IsPtrTo(type_t *tp) {
1444*2775Sraf 	return (tp && (tp->t_dt == DD_PTR));
1445*2775Sraf }
1446*2775Sraf 
1447*2775Sraf stt_t
type_GetPtrToTypeQual(type_t * tp)1448*2775Sraf type_GetPtrToTypeQual(type_t *tp) {
1449*2775Sraf 	assert(tp->t_dt == DD_PTR);
1450*2775Sraf 
1451*2775Sraf 	return (tp->t_stt);
1452*2775Sraf }
1453*2775Sraf 
1454*2775Sraf int
type_IsFunction(type_t * tp)1455*2775Sraf type_IsFunction(type_t *tp) {
1456*2775Sraf 	return (tp && (tp->t_dt == DD_FUN));
1457*2775Sraf }
1458*2775Sraf 
1459*2775Sraf int
type_GetArgLength(type_t * tp)1460*2775Sraf type_GetArgLength(type_t *tp) {
1461*2775Sraf 	assert(tp->t_dt == DD_FUN);
1462*2775Sraf 
1463*2775Sraf 	return (tp->t_nargs);
1464*2775Sraf }
1465*2775Sraf 
1466*2775Sraf int
type_IsVarargs(type_t * tp)1467*2775Sraf type_IsVarargs(type_t *tp) {
1468*2775Sraf 	while (tp && tp->t_dt == DD_PTR)
1469*2775Sraf 		tp = tp->t_next;
1470*2775Sraf 
1471*2775Sraf 	assert(tp->t_dt == DD_FUN);
1472*2775Sraf 
1473*2775Sraf 	return (tp->t_ellipsis);
1474*2775Sraf }
1475*2775Sraf 
1476*2775Sraf decl_t *
type_GetArg(type_t * tp)1477*2775Sraf type_GetArg(type_t *tp) {
1478*2775Sraf 	assert(tp->t_dt == DD_FUN);
1479*2775Sraf 
1480*2775Sraf 	return (tp->t_args);
1481*2775Sraf }
1482*2775Sraf 
1483*2775Sraf /*
1484*2775Sraf  * type_IsPtrFun - determine if the type_t results in a call-able function.
1485*2775Sraf  *
1486*2775Sraf  * Note:
1487*2775Sraf  *	1) The argument can be NULL.
1488*2775Sraf  *
1489*2775Sraf  *	2) The test is true if the type_t list is number of DD_PTR followed
1490*2775Sraf  *	by a DD_FUN.
1491*2775Sraf  */
1492*2775Sraf 
1493*2775Sraf int
type_IsPtrFun(type_t * tp)1494*2775Sraf type_IsPtrFun(type_t *tp) {
1495*2775Sraf 
1496*2775Sraf 	if (! (tp && (tp->t_dt == DD_PTR)))
1497*2775Sraf 		return (0);
1498*2775Sraf 
1499*2775Sraf 	tp = tp->t_next;
1500*2775Sraf 
1501*2775Sraf 	while (tp && (tp->t_dt == DD_PTR))
1502*2775Sraf 		tp = tp->t_next;
1503*2775Sraf 
1504*2775Sraf 	return (tp && (tp->t_dt == DD_FUN));
1505*2775Sraf }
1506*2775Sraf 
1507*2775Sraf /* D E C L A R A T O R */
1508*2775Sraf 
1509*2775Sraf /*
1510*2775Sraf  * A decl_t encodes the name,
1511*2775Sraf  * declaration specifiers and type modifiers of an object.
1512*2775Sraf  */
1513*2775Sraf 
1514*2775Sraf /* decl_Construct - allocate a decl_t. */
1515*2775Sraf 
1516*2775Sraf static decl_t *
decl_Construct(void)1517*2775Sraf decl_Construct(void) {
1518*2775Sraf 	decl_t	*dp = malloc(sizeof (decl_t));
1519*2775Sraf 
1520*2775Sraf 	assert(dp != NULL);
1521*2775Sraf 
1522*2775Sraf 	dp->d_name = NULL;
1523*2775Sraf 	dp->d_type = NULL;
1524*2775Sraf 	dp->d_next = NULL;
1525*2775Sraf 	dp->d_ds = declspec_Construct();
1526*2775Sraf 	dp->d_ellipsis = 0;
1527*2775Sraf #if defined(MEM_DEBUG)
1528*2775Sraf 	++decl_Construct_calls;
1529*2775Sraf #endif
1530*2775Sraf 	return (dp);
1531*2775Sraf }
1532*2775Sraf 
1533*2775Sraf /* decl_Destroy - free a decl_t list. */
1534*2775Sraf 
1535*2775Sraf void
decl_Destroy(decl_t * dp)1536*2775Sraf decl_Destroy(decl_t *dp) {
1537*2775Sraf 	while (dp) {
1538*2775Sraf 		decl_t	*nextp = dp->d_next;
1539*2775Sraf 
1540*2775Sraf 		type_Destroy(dp->d_type);
1541*2775Sraf 		declspec_Destroy(dp->d_ds);
1542*2775Sraf 		free(dp->d_name);
1543*2775Sraf 		free(dp);
1544*2775Sraf 
1545*2775Sraf 		dp = nextp;
1546*2775Sraf #if defined(MEM_DEBUG)
1547*2775Sraf 		--decl_Construct_calls;
1548*2775Sraf #endif
1549*2775Sraf 	}
1550*2775Sraf }
1551*2775Sraf 
1552*2775Sraf /*
1553*2775Sraf  * decl_GetArgLength - return the length of a decl_t list.
1554*2775Sraf  *
1555*2775Sraf  * Note:
1556*2775Sraf  *	1) The argument may be NULL to indicate an empty list, len == 0.
1557*2775Sraf  */
1558*2775Sraf 
1559*2775Sraf int
decl_GetArgLength(decl_t * dp)1560*2775Sraf decl_GetArgLength(decl_t *dp) {
1561*2775Sraf 	int	len;
1562*2775Sraf 
1563*2775Sraf 	for (len = 0; dp; dp = dp->d_next)
1564*2775Sraf 		++len;
1565*2775Sraf 
1566*2775Sraf 	return (len);
1567*2775Sraf }
1568*2775Sraf 
1569*2775Sraf /*
1570*2775Sraf  * The following group of functions get or test various aspects of a decl_t.
1571*2775Sraf  */
1572*2775Sraf 
1573*2775Sraf decl_t *
decl_GetNext(decl_t * dp)1574*2775Sraf decl_GetNext(decl_t *dp) {
1575*2775Sraf 	return (dp->d_next);
1576*2775Sraf }
1577*2775Sraf 
1578*2775Sraf stt_t
decl_GetDeclSpec(decl_t * dp)1579*2775Sraf decl_GetDeclSpec(decl_t *dp) {
1580*2775Sraf 	return (declspec_GetSTT(dp->d_ds));
1581*2775Sraf }
1582*2775Sraf 
1583*2775Sraf char *
decl_GetDSName(decl_t * dp)1584*2775Sraf decl_GetDSName(decl_t *dp) {
1585*2775Sraf 	return (declspec_GetTag(dp->d_ds));
1586*2775Sraf }
1587*2775Sraf 
1588*2775Sraf type_t *
decl_GetType(decl_t * dp)1589*2775Sraf decl_GetType(decl_t *dp) {
1590*2775Sraf 	return (dp->d_type);
1591*2775Sraf }
1592*2775Sraf 
1593*2775Sraf int
decl_IsVarargs(decl_t * dp)1594*2775Sraf decl_IsVarargs(decl_t *dp) {
1595*2775Sraf 	return (dp->d_ellipsis);
1596*2775Sraf }
1597*2775Sraf 
1598*2775Sraf int
decl_IsFunction(decl_t * dp)1599*2775Sraf decl_IsFunction(decl_t *dp) {
1600*2775Sraf 	return (type_IsFunction(dp->d_type));
1601*2775Sraf }
1602*2775Sraf 
1603*2775Sraf char *
decl_GetName(decl_t * dp)1604*2775Sraf decl_GetName(decl_t *dp) {
1605*2775Sraf 	return (dp->d_name);
1606*2775Sraf }
1607*2775Sraf 
1608*2775Sraf /*
1609*2775Sraf  * decl_AddArg - add a decl_t to the end of an decl_t list.
1610*2775Sraf  */
1611*2775Sraf 
1612*2775Sraf static decl_t *
decl_AddArg(decl_t * dp,decl_t * tp)1613*2775Sraf decl_AddArg(decl_t *dp, decl_t *tp) {
1614*2775Sraf 	decl_t	*lastp = dp;
1615*2775Sraf 	decl_t	*p;
1616*2775Sraf 
1617*2775Sraf 	while (p = lastp->d_next)
1618*2775Sraf 		lastp = p;
1619*2775Sraf 
1620*2775Sraf 	lastp->d_next = tp;
1621*2775Sraf 
1622*2775Sraf 	return (dp);
1623*2775Sraf }
1624*2775Sraf 
1625*2775Sraf /*
1626*2775Sraf  * decl_IsVoid - return true if the decl_t is a "pure" void declaration.
1627*2775Sraf  */
1628*2775Sraf 
1629*2775Sraf static int
decl_IsVoid(decl_t * dp)1630*2775Sraf decl_IsVoid(decl_t *dp) {
1631*2775Sraf 	return ((declspec_GetSTT(dp->d_ds) & TS_VOID) && (dp->d_type == NULL));
1632*2775Sraf }
1633*2775Sraf 
1634*2775Sraf /*
1635*2775Sraf  * decl_IsVoidArray - return true if the decl_t includes "void []".
1636*2775Sraf  */
1637*2775Sraf 
1638*2775Sraf static int
decl_IsVoidArray(decl_t * dp)1639*2775Sraf decl_IsVoidArray(decl_t *dp) {
1640*2775Sraf 	int	 retval = 0;
1641*2775Sraf 	type_t	*tp = dp->d_type;
1642*2775Sraf 
1643*2775Sraf 	if (tp) {
1644*2775Sraf 		type_t	*np;
1645*2775Sraf 
1646*2775Sraf 		while (np = type_GetNext(tp))
1647*2775Sraf 			tp = np;
1648*2775Sraf 
1649*2775Sraf 		retval = type_IsArray(tp) &&
1650*2775Sraf 		    (declspec_GetSTT(dp->d_ds) & TS_VOID);
1651*2775Sraf 	}
1652*2775Sraf 
1653*2775Sraf 	return (retval);
1654*2775Sraf }
1655*2775Sraf 
1656*2775Sraf /*
1657*2775Sraf  * decl_Verify - verify a decl_t.
1658*2775Sraf  */
1659*2775Sraf 
1660*2775Sraf static const char *
decl_Verify(decl_t * dp)1661*2775Sraf decl_Verify(decl_t *dp) {
1662*2775Sraf 	const char	*ep = NULL;
1663*2775Sraf 
1664*2775Sraf 	if (decl_IsVoid(dp))
1665*2775Sraf 		ep = "type is void";
1666*2775Sraf 	else if (decl_IsVoidArray(dp))
1667*2775Sraf 		ep = "type is void []";
1668*2775Sraf 	else
1669*2775Sraf 		ep = type_Verify(dp->d_type);
1670*2775Sraf 
1671*2775Sraf 	return (ep);
1672*2775Sraf }
1673*2775Sraf 
1674*2775Sraf /*
1675*2775Sraf  * decl_VerifyArgs - verify a decl_t list.
1676*2775Sraf  */
1677*2775Sraf 
1678*2775Sraf static const char *
decl_VerifyArgs(decl_t * dp)1679*2775Sraf decl_VerifyArgs(decl_t *dp) {
1680*2775Sraf 	decl_t		*tp = dp;
1681*2775Sraf 	const char	*ep = NULL;
1682*2775Sraf 
1683*2775Sraf 	if (dp) {
1684*2775Sraf 		int	 nv = 0;
1685*2775Sraf 		int	 nargs = decl_GetArgLength(dp);
1686*2775Sraf 
1687*2775Sraf 		for (; dp; dp = dp->d_next)
1688*2775Sraf 			if (decl_IsVoid(dp)) {
1689*2775Sraf 				++nv;
1690*2775Sraf 
1691*2775Sraf 				if (decl_GetName(dp))
1692*2775Sraf 					ep = "argument list includes "
1693*2775Sraf 					    "void with identifier";
1694*2775Sraf 			} else if (decl_IsVoidArray(dp))
1695*2775Sraf 				ep = "argument list includes void []";
1696*2775Sraf 
1697*2775Sraf 		if (nv) {		/* there was some void */
1698*2775Sraf 			if (nargs > 1)
1699*2775Sraf 				ep = "argument list includes void";
1700*2775Sraf 
1701*2775Sraf 			if (tp->d_ellipsis)
1702*2775Sraf 				ep = "argument list includes void and \"...\"";
1703*2775Sraf 		}
1704*2775Sraf 	}
1705*2775Sraf 
1706*2775Sraf 	return (ep);
1707*2775Sraf }
1708*2775Sraf 
1709*2775Sraf /* decl_AddDS - add a decl_spec_t to a decl_t. */
1710*2775Sraf 
1711*2775Sraf static decl_t *
decl_AddDS(decl_t * dp,decl_spec_t * dsp,const char ** err)1712*2775Sraf decl_AddDS(decl_t *dp, decl_spec_t *dsp, const char **err) {
1713*2775Sraf 	declspec_AddDS(dp->d_ds, dsp, err);
1714*2775Sraf 
1715*2775Sraf 	return (dp);
1716*2775Sraf }
1717*2775Sraf 
1718*2775Sraf /*
1719*2775Sraf  * decl_SetName - set the name associated with a decl_t.
1720*2775Sraf  *
1721*2775Sraf  * Note:
1722*2775Sraf  *	1) Any previously known name is free'd.
1723*2775Sraf  */
1724*2775Sraf 
1725*2775Sraf decl_t *
decl_SetName(decl_t * dp,char * s)1726*2775Sraf decl_SetName(decl_t *dp, char *s) {
1727*2775Sraf 	free(dp->d_name);
1728*2775Sraf 	dp->d_name = strdup(s);
1729*2775Sraf 	assert(dp->d_name != NULL);
1730*2775Sraf 
1731*2775Sraf 	return (dp);
1732*2775Sraf }
1733*2775Sraf 
1734*2775Sraf /*
1735*2775Sraf  * decl_AddTypeTail - add a type_t to the end of a decl_t type_t list.
1736*2775Sraf  */
1737*2775Sraf 
1738*2775Sraf static decl_t *
decl_AddTypeTail(decl_t * dp,type_t * tp)1739*2775Sraf decl_AddTypeTail(decl_t *dp, type_t *tp) {
1740*2775Sraf 	if (dp->d_type)
1741*2775Sraf 		type_AddTail(dp->d_type, tp);
1742*2775Sraf 	else
1743*2775Sraf 		dp->d_type = tp;
1744*2775Sraf 
1745*2775Sraf 	return (dp);
1746*2775Sraf }
1747*2775Sraf 
1748*2775Sraf /*
1749*2775Sraf  * decl_addptr - add a DD_PTR type_t to the end of a decl_t type_t list.
1750*2775Sraf  */
1751*2775Sraf 
1752*2775Sraf static decl_t *
decl_addptr(decl_t * dp,type_t * tp)1753*2775Sraf decl_addptr(decl_t *dp, type_t *tp) {
1754*2775Sraf 	decl_AddTypeTail(dp, tp);
1755*2775Sraf 
1756*2775Sraf 	return (dp);
1757*2775Sraf }
1758*2775Sraf 
1759*2775Sraf /*
1760*2775Sraf  * decl_addary - allocate and add a DD_ARY type_t to the end of
1761*2775Sraf  *	a decl_t type_t list.
1762*2775Sraf  */
1763*2775Sraf 
1764*2775Sraf static decl_t *
decl_addary(decl_t * dp,char * sizep)1765*2775Sraf decl_addary(decl_t *dp, char *sizep) {
1766*2775Sraf 	type_t	*tp = type_Construct();
1767*2775Sraf 
1768*2775Sraf 	type_SetAry(tp, sizep);
1769*2775Sraf 	decl_AddTypeTail(dp, tp);
1770*2775Sraf 
1771*2775Sraf 	return (dp);
1772*2775Sraf }
1773*2775Sraf 
1774*2775Sraf /*
1775*2775Sraf  * decl_addfun - allocate and add a DD_FUN type_t to the end of a
1776*2775Sraf  *	 decl_t type_t list.
1777*2775Sraf  */
1778*2775Sraf 
1779*2775Sraf static decl_t *
decl_addfun(decl_t * dp,decl_t * arglist)1780*2775Sraf decl_addfun(decl_t *dp, decl_t *arglist) {
1781*2775Sraf 	const char	*sp;
1782*2775Sraf 	type_t	*tp = type_Construct();
1783*2775Sraf 
1784*2775Sraf 	if (sp = decl_VerifyArgs(arglist))
1785*2775Sraf 		yyerror(sp);
1786*2775Sraf 
1787*2775Sraf 	type_SetFun(tp, arglist);
1788*2775Sraf 	decl_AddTypeTail(dp, tp);
1789*2775Sraf 
1790*2775Sraf 	return (dp);
1791*2775Sraf }
1792*2775Sraf 
1793*2775Sraf /*
1794*2775Sraf  * decl_addellipsis - set the ellipsis state in a decl_t.
1795*2775Sraf  *
1796*2775Sraf  * Note:
1797*2775Sraf  *	1) This function is only used in the grammar in the
1798*2775Sraf  *	   parameter list parsing.
1799*2775Sraf  */
1800*2775Sraf 
1801*2775Sraf static decl_t *
decl_addellipsis(decl_t * dp)1802*2775Sraf decl_addellipsis(decl_t *dp) {
1803*2775Sraf 	dp->d_ellipsis = 1;
1804*2775Sraf 
1805*2775Sraf 	return (dp);
1806*2775Sraf }
1807*2775Sraf 
1808*2775Sraf #if defined(DEBUG)
1809*2775Sraf 
1810*2775Sraf static void
decl_PrintDecl(decl_t * dp,int lvl)1811*2775Sraf decl_PrintDecl(decl_t *dp, int lvl) {
1812*2775Sraf 	char	buf[BUFSIZ];
1813*2775Sraf 
1814*2775Sraf 	while (dp) {
1815*2775Sraf 		putNTabs(lvl);
1816*2775Sraf 
1817*2775Sraf 		printf("name = %s, ds = %s\n",
1818*2775Sraf 				(dp->d_name)? dp->d_name : "<null>",
1819*2775Sraf 				declspec_ToString(buf, dp->d_ds));
1820*2775Sraf 
1821*2775Sraf 		if (dp->d_type)
1822*2775Sraf 			type_PrintType(dp->d_type, lvl + 1);
1823*2775Sraf 
1824*2775Sraf 		dp = dp->d_next;
1825*2775Sraf 	}
1826*2775Sraf }
1827*2775Sraf #endif	/* DEBUG */
1828*2775Sraf 
1829*2775Sraf static char *
char_getend(char * s)1830*2775Sraf char_getend(char *s) {
1831*2775Sraf 	while (*s != '\0')
1832*2775Sraf 		++s;
1833*2775Sraf 
1834*2775Sraf 	return (s);
1835*2775Sraf }
1836*2775Sraf 
1837*2775Sraf char *
decl_ToString(char * bufp,decl_dts_t out,decl_t * dp,const char * altname)1838*2775Sraf decl_ToString(char *bufp, decl_dts_t out, decl_t *dp,
1839*2775Sraf     const char *altname) {
1840*2775Sraf 	char	 tmp[BUFSIZ];
1841*2775Sraf 	char	 tmp2[BUFSIZ];
1842*2775Sraf 	const char *namep;
1843*2775Sraf 	char	*bend = bufp;
1844*2775Sraf 	type_t	*tp = dp->d_type;
1845*2775Sraf 	int ffun = 1;
1846*2775Sraf 
1847*2775Sraf 	switch (out) {
1848*2775Sraf 	default:
1849*2775Sraf 		out = DTS_DECL;
1850*2775Sraf 		/* FALLTHRU */
1851*2775Sraf 	case DTS_DECL:
1852*2775Sraf 		if (altname == NULL) {
1853*2775Sraf 			namep = dp->d_name;
1854*2775Sraf 		} else {
1855*2775Sraf 			namep = altname;
1856*2775Sraf 		}
1857*2775Sraf 		break;
1858*2775Sraf 	case DTS_CAST:
1859*2775Sraf 		namep = "(*)";
1860*2775Sraf 		break;
1861*2775Sraf 	case DTS_RET:
1862*2775Sraf 		if (altname == NULL) {
1863*2775Sraf 			namep = "_return";
1864*2775Sraf 		} else {
1865*2775Sraf 			namep = altname;
1866*2775Sraf 		}
1867*2775Sraf 		break;
1868*2775Sraf 	}
1869*2775Sraf 
1870*2775Sraf 	*bufp = '\0';
1871*2775Sraf 
1872*2775Sraf 	strcpy(tmp, (namep) ? namep : "");
1873*2775Sraf 
1874*2775Sraf 	while (tp) {
1875*2775Sraf 		switch (tp->t_dt) {
1876*2775Sraf 		case DD_PTR:
1877*2775Sraf 			if (tp->t_next &&
1878*2775Sraf 			    ((tp->t_next->t_dt == DD_ARY) ||
1879*2775Sraf 			    (tp->t_next->t_dt == DD_FUN))) {
1880*2775Sraf 				if (out == DTS_RET) {
1881*2775Sraf 					sprintf(bufp, "(*%s)", namep);
1882*2775Sraf 				} else {
1883*2775Sraf 					sprintf(bufp, "(*%s)", tmp);
1884*2775Sraf 				}
1885*2775Sraf 			} else if (tp->t_stt == TQ_CONST) {
1886*2775Sraf 				sprintf(bufp, "*const %s", tmp);
1887*2775Sraf 			} else if (tp->t_stt == TQ_VOLATILE) {
1888*2775Sraf 				sprintf(bufp, "*volatile %s", tmp);
1889*2775Sraf 			/*
1890*2775Sraf 			 * It currently acknowledges and ignores restrict
1891*2775Sraf 			 * or _RESTRICT_KYWD in code generation because
1892*2775Sraf 			 * of the uncertain behavior of "restrict".
1893*2775Sraf 			 */
1894*2775Sraf 			} else if (tp->t_stt == TQ_RESTRICT) {
1895*2775Sraf 				sprintf(bufp, "*%s", tmp);
1896*2775Sraf 			} else if (tp->t_stt == TQ_RESTRICT_KYWD) {
1897*2775Sraf 				sprintf(bufp, "*%s", tmp);
1898*2775Sraf 			} else {
1899*2775Sraf 				sprintf(bufp, "*%s", tmp);
1900*2775Sraf 			}
1901*2775Sraf 
1902*2775Sraf 			break;
1903*2775Sraf 
1904*2775Sraf 		case DD_ARY:
1905*2775Sraf 			sprintf(bufp, "%s[%s]",
1906*2775Sraf 			    tmp, (tp->t_sizestr)? tp->t_sizestr : "");
1907*2775Sraf 			break;
1908*2775Sraf 
1909*2775Sraf 		case DD_FUN:
1910*2775Sraf 			if (out == DTS_RET && ffun == 1) {
1911*2775Sraf 				strcpy(bufp, namep);
1912*2775Sraf 				ffun = 0;
1913*2775Sraf 			} else if (tp->t_args == NULL) {
1914*2775Sraf 				sprintf(bufp, "%s()", tmp);
1915*2775Sraf 			} else {
1916*2775Sraf 				char	 buf2[BUFSIZ];
1917*2775Sraf 				decl_t	*argp = tp->t_args;
1918*2775Sraf 
1919*2775Sraf 				sprintf(bufp, "%s(", tmp);
1920*2775Sraf 				bend = char_getend(bufp);
1921*2775Sraf 
1922*2775Sraf 				for (argp = tp->t_args; argp; /* noinc */) {
1923*2775Sraf 					decl_ToString(buf2, DTS_DECL, argp,
1924*2775Sraf 					    NULL);
1925*2775Sraf 					sprintf(bend, " %s", buf2);
1926*2775Sraf 
1927*2775Sraf 					bend = char_getend(bend);
1928*2775Sraf 
1929*2775Sraf 					if (argp = argp->d_next) {
1930*2775Sraf 						sprintf(bend, ",");
1931*2775Sraf 						bend = char_getend(bend);
1932*2775Sraf 					}
1933*2775Sraf 				}
1934*2775Sraf 
1935*2775Sraf 				if (tp->t_ellipsis) {
1936*2775Sraf 					sprintf(bend, ", ...");
1937*2775Sraf 					bend = char_getend(bend);
1938*2775Sraf 				}
1939*2775Sraf 
1940*2775Sraf 				sprintf(bend, ")");
1941*2775Sraf 			}
1942*2775Sraf 			break;
1943*2775Sraf 		}
1944*2775Sraf 
1945*2775Sraf 		tp = tp->t_next;
1946*2775Sraf 
1947*2775Sraf 		strcpy(tmp, bufp);
1948*2775Sraf 	}
1949*2775Sraf 
1950*2775Sraf 	if (out == DTS_CAST) {
1951*2775Sraf 		sprintf(bufp, "(%s %s)",
1952*2775Sraf 		    declspec_ToString(tmp2, dp->d_ds), tmp);
1953*2775Sraf 	} else {
1954*2775Sraf 		sprintf(bufp, "%s %s",
1955*2775Sraf 		    declspec_ToString(tmp2, dp->d_ds), tmp);
1956*2775Sraf 	}
1957*2775Sraf 
1958*2775Sraf 	return (bufp);
1959*2775Sraf }
1960*2775Sraf 
1961*2775Sraf decl_t *
decl_AddArgNames(decl_t * dp)1962*2775Sraf decl_AddArgNames(decl_t *dp) {
1963*2775Sraf 	int	 argno = 0;
1964*2775Sraf 	decl_t	*p = dp;
1965*2775Sraf 
1966*2775Sraf 	if (decl_IsFunction(dp)) {
1967*2775Sraf 		int	 argno = 0;
1968*2775Sraf 		decl_t	*p = dp->d_type->t_args;
1969*2775Sraf 
1970*2775Sraf 		while (p) {
1971*2775Sraf 			char	*s = decl_GetName(p);
1972*2775Sraf 
1973*2775Sraf 			if ((s == NULL) && !decl_IsVoid(p)) {
1974*2775Sraf 				char	buf[BUFSIZ];
1975*2775Sraf 
1976*2775Sraf 				sprintf(buf, "arg%d", argno);
1977*2775Sraf 				s = strdup(buf);
1978*2775Sraf 				decl_SetName(p, s);
1979*2775Sraf 			}
1980*2775Sraf 
1981*2775Sraf 			p = p->d_next;
1982*2775Sraf 			++argno;
1983*2775Sraf 		}
1984*2775Sraf 	}
1985*2775Sraf 	return (dp);
1986*2775Sraf }
1987*2775Sraf 
1988*2775Sraf const char *
decl_Parse(char * str,decl_t ** dpp)1989*2775Sraf decl_Parse(char *str, decl_t **dpp) {
1990*2775Sraf 	errstr = NULL;	/* setup the (static) globals */
1991*2775Sraf 	input = str;
1992*2775Sraf 	atIDENT = 0;
1993*2775Sraf 	protop = NULL;
1994*2775Sraf 
1995*2775Sraf 	yyparse();	/* parse the prototype */
1996*2775Sraf 
1997*2775Sraf 	if (errstr == NULL) {		/* success */
1998*2775Sraf 		*dpp = protop;
1999*2775Sraf 		decl_AddArgNames(protop);
2000*2775Sraf 	} else {	/* failure */
2001*2775Sraf 		*dpp = NULL;
2002*2775Sraf 		decl_Destroy(protop);
2003*2775Sraf 	}
2004*2775Sraf 
2005*2775Sraf 	return (errstr);
2006*2775Sraf }
2007*2775Sraf 
2008*2775Sraf static void
yyerror(const char * err)2009*2775Sraf yyerror(const char *err) {
2010*2775Sraf 	errstr = err;
2011*2775Sraf }
2012*2775Sraf 
2013*2775Sraf #if defined(DEBUG)
2014*2775Sraf 
2015*2775Sraf /* main */
2016*2775Sraf 
2017*2775Sraf static int yydebug = 1;
2018*2775Sraf 
2019*2775Sraf int
main(int argc,char * argv[])2020*2775Sraf main(int argc, char *argv[]) {
2021*2775Sraf 	int	i;
2022*2775Sraf 
2023*2775Sraf 	yydebug = 1;
2024*2775Sraf 
2025*2775Sraf 	for (i = 1; i < argc; ++i) {
2026*2775Sraf 		const char	*es;
2027*2775Sraf 		char		 buf[BUFSIZ];
2028*2775Sraf 		decl_t		*pp;
2029*2775Sraf 
2030*2775Sraf 		if (es = decl_Parse(argv[i], &pp))
2031*2775Sraf 			printf("parse failure: %s\n", es);
2032*2775Sraf 		else {
2033*2775Sraf #if GR_DEBUG
2034*2775Sraf 			decl_PrintDecl(pp, 0);
2035*2775Sraf 			decl_AddArgNames(pp);
2036*2775Sraf #endif
2037*2775Sraf 			printf("---\n%s;\n",
2038*2775Sraf 			    decl_ToString(buf, DTS_DECL, pp, NULL));
2039*2775Sraf 			printf("%s\n",
2040*2775Sraf 			    decl_ToString(buf, DTS_CAST, pp, NULL));
2041*2775Sraf 			printf("%s;\n",
2042*2775Sraf 			    decl_ToString(buf, DTS_RET, pp, "%s"));
2043*2775Sraf 
2044*2775Sraf #ifdef TRACE
2045*2775Sraf 			printf("\n\nTrace Info\n");
2046*2775Sraf 			decl_PrintTraceInfo(pp);
2047*2775Sraf #endif
2048*2775Sraf 		}
2049*2775Sraf 
2050*2775Sraf 		decl_Destroy(pp);
2051*2775Sraf 
2052*2775Sraf #if defined(MEM_DEBUG)
2053*2775Sraf 		printf("declspec : %d\n", declspec_Construct_calls);
2054*2775Sraf 		printf("type     : %d\n", type_Construct_calls);
2055*2775Sraf 		printf("decl     : %d\n", decl_Construct_calls);
2056*2775Sraf #endif
2057*2775Sraf 	}
2058*2775Sraf 
2059*2775Sraf 	return (0);
2060*2775Sraf }
2061*2775Sraf 
2062*2775Sraf #ifdef TRACE
2063*2775Sraf void
decl_PrintTraceInfo(decl_t * dp)2064*2775Sraf decl_PrintTraceInfo(decl_t *dp) {
2065*2775Sraf 	char	buf[BUFSIZ];
2066*2775Sraf 	char	f_type[BUFSIZ];
2067*2775Sraf 	char	f_print[BUFSIZ];
2068*2775Sraf 	char	a_name[BUFSIZ];
2069*2775Sraf 	char	a_type[BUFSIZ];
2070*2775Sraf 	char	a_print[BUFSIZ];
2071*2775Sraf 	decl_t	*funargs;
2072*2775Sraf 	type_t	*tp;
2073*2775Sraf 	int	isptrfun;
2074*2775Sraf 
2075*2775Sraf 	if (dp == NULL)
2076*2775Sraf 		return;
2077*2775Sraf 
2078*2775Sraf 	fprintf(stderr, "interface = %s\n",
2079*2775Sraf 	    (dp->d_name) ? dp->d_name : "<null>");
2080*2775Sraf 
2081*2775Sraf 	isptrfun = type_IsPtrFun(dp->d_type);
2082*2775Sraf 	if (type_IsFunction(dp->d_type) || isptrfun)
2083*2775Sraf 		decl_GetTraceInfo(dp, f_type, f_print, &funargs);
2084*2775Sraf 	else
2085*2775Sraf 		return;
2086*2775Sraf 
2087*2775Sraf 	fprintf(stderr, "return type = %s\n", f_type);
2088*2775Sraf 	fprintf(stderr, "print function = %s\n", f_print);
2089*2775Sraf 
2090*2775Sraf 	if (isptrfun)
2091*2775Sraf 		fprintf(stderr, "function is function pointer\n");
2092*2775Sraf 
2093*2775Sraf 	if (type_IsVarargs(dp->d_type))
2094*2775Sraf 		fprintf(stderr, "function is varargs\n");
2095*2775Sraf 
2096*2775Sraf 	while (funargs) {
2097*2775Sraf 		snprintf(a_type, BUFSIZ, "%s ",
2098*2775Sraf 		    declspec_ToString(buf, funargs->d_ds));
2099*2775Sraf 		snprintf(a_print, BUFSIZ, "%s",
2100*2775Sraf 		    de_const(declspec_ToString(buf, funargs->d_ds)));
2101*2775Sraf 
2102*2775Sraf 		tp = funargs->d_type;
2103*2775Sraf 
2104*2775Sraf 		while (tp) {
2105*2775Sraf 			if (tp->t_dt == DD_PTR || tp->t_dt == DD_ARY) {
2106*2775Sraf 				strcat(a_type, "*");
2107*2775Sraf 				strcat(a_print, "_P");
2108*2775Sraf 			}
2109*2775Sraf 			tp = tp->t_next;
2110*2775Sraf 		}
2111*2775Sraf 
2112*2775Sraf 		if (funargs->d_name) {
2113*2775Sraf 			snprintf(a_name, BUFSIZ, "%s",
2114*2775Sraf 			    funargs->d_name ? funargs->d_name : "<nil>");
2115*2775Sraf 			fprintf(stderr, "arg name = %s\n", a_name);
2116*2775Sraf 			fprintf(stderr, "arg type = %s\n", a_type);
2117*2775Sraf 			fprintf(stderr, "print function = %s\n", a_print);
2118*2775Sraf 		} else {
2119*2775Sraf 			strcpy(a_name, "");
2120*2775Sraf 			strcpy(a_print, "");
2121*2775Sraf 			fprintf(stderr, "arg type = %s\n", a_type);
2122*2775Sraf 		}
2123*2775Sraf 
2124*2775Sraf 		funargs = funargs->d_next;
2125*2775Sraf 	}
2126*2775Sraf }
2127*2775Sraf #endif	/* TRACE */
2128*2775Sraf #endif	/* DEBUG */
2129*2775Sraf 
2130*2775Sraf static char *
de_const(char * str)2131*2775Sraf de_const(char *str)
2132*2775Sraf {
2133*2775Sraf 	return (str);
2134*2775Sraf }
2135*2775Sraf 
2136*2775Sraf 
2137*2775Sraf void
decl_GetTraceInfo(decl_t * dp,char * f_type,char * f_print,decl_t ** funargs)2138*2775Sraf decl_GetTraceInfo(decl_t *dp, char *f_type, char *f_print, decl_t **funargs)
2139*2775Sraf {
2140*2775Sraf 	char	buf[BUFSIZ];
2141*2775Sraf 	type_t	*tp;
2142*2775Sraf 
2143*2775Sraf 	if (dp == NULL)
2144*2775Sraf 		return;
2145*2775Sraf 
2146*2775Sraf 	snprintf(f_type, BUFSIZ, "%s ",
2147*2775Sraf 	    declspec_ToString(buf, dp->d_ds));
2148*2775Sraf 	snprintf(f_print, BUFSIZ, "%s",
2149*2775Sraf 	    de_const(declspec_ToString(buf, dp->d_ds)));
2150*2775Sraf 	tp = dp->d_type;
2151*2775Sraf 	while (tp) {
2152*2775Sraf 		if (tp->t_dt == DD_PTR) {
2153*2775Sraf 			strcat(f_type, "*");
2154*2775Sraf 			strcat(f_print, "*");
2155*2775Sraf 		}
2156*2775Sraf 		tp = tp->t_next;
2157*2775Sraf 	}
2158*2775Sraf 
2159*2775Sraf 	strcat(f_type, "%s");
2160*2775Sraf 
2161*2775Sraf 	tp = decl_GetType(dp);
2162*2775Sraf 	if (type_IsPtrFun(tp)) {
2163*2775Sraf 		while (tp->t_dt != DD_FUN)
2164*2775Sraf 			tp = tp->t_next;
2165*2775Sraf 		*funargs = tp->t_args;
2166*2775Sraf 	} else {
2167*2775Sraf 		*funargs = dp->d_type->t_args;
2168*2775Sraf 	}
2169*2775Sraf }
2170*2775Sraf 
2171*2775Sraf char *
decl_ToFormal(decl_t * dp)2172*2775Sraf decl_ToFormal(decl_t *dp)
2173*2775Sraf {
2174*2775Sraf 	char tmp[BUFSIZ];
2175*2775Sraf 	static char bufp[BUFSIZ];
2176*2775Sraf 	char *bend;
2177*2775Sraf 	type_t	*tp = dp->d_type;
2178*2775Sraf 
2179*2775Sraf 	tmp[0] = 0;
2180*2775Sraf 	bufp[0] = 0;
2181*2775Sraf 	bend = bufp;
2182*2775Sraf 
2183*2775Sraf 	while (tp) {
2184*2775Sraf 		switch (tp->t_dt) {
2185*2775Sraf 		case DD_ARY:
2186*2775Sraf 			sprintf(bufp, "%s[%s]", tmp,
2187*2775Sraf 			    (tp->t_sizestr)? tp->t_sizestr : "");
2188*2775Sraf 			break;
2189*2775Sraf 
2190*2775Sraf 		case DD_FUN:
2191*2775Sraf 			if (tp->t_args != NULL) {
2192*2775Sraf 				char buf2[BUFSIZ];
2193*2775Sraf 				decl_t  *argp = tp->t_args;
2194*2775Sraf 
2195*2775Sraf 				bend = char_getend(bufp);
2196*2775Sraf 
2197*2775Sraf 				for (argp = tp->t_args; argp; /* noinc */) {
2198*2775Sraf 					decl_ToString(buf2, DTS_DECL, argp,
2199*2775Sraf 					    NULL);
2200*2775Sraf 					sprintf(bend, " %s", buf2);
2201*2775Sraf 
2202*2775Sraf 					bend    = char_getend(bend);
2203*2775Sraf 
2204*2775Sraf 					if (argp = argp->d_next) {
2205*2775Sraf 						sprintf(bend, ",");
2206*2775Sraf 						bend    = char_getend(bend);
2207*2775Sraf 					}
2208*2775Sraf 				}
2209*2775Sraf 				if (tp->t_ellipsis) {
2210*2775Sraf 					sprintf(bend, ", ...");
2211*2775Sraf 					bend    = char_getend(bend);
2212*2775Sraf 				}
2213*2775Sraf 
2214*2775Sraf 				sprintf(bend, "");
2215*2775Sraf 			}
2216*2775Sraf 			break;
2217*2775Sraf 		}
2218*2775Sraf 
2219*2775Sraf 		tp  = tp->t_next;
2220*2775Sraf 
2221*2775Sraf 		strcpy(tmp, bufp);
2222*2775Sraf 	}
2223*2775Sraf 
2224*2775Sraf 	sprintf(bufp, "%s", tmp);
2225*2775Sraf 
2226*2775Sraf 	return (bufp);
2227*2775Sraf }
2228