1753d2d2eSraf %{
2753d2d2eSraf /*
3753d2d2eSraf  * CDDL HEADER START
4753d2d2eSraf  *
5753d2d2eSraf  * The contents of this file are subject to the terms of the
6753d2d2eSraf  * Common Development and Distribution License, Version 1.0 only
7753d2d2eSraf  * (the "License").  You may not use this file except in compliance
8753d2d2eSraf  * with the License.
9753d2d2eSraf  *
10753d2d2eSraf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11753d2d2eSraf  * or http://www.opensolaris.org/os/licensing.
12753d2d2eSraf  * See the License for the specific language governing permissions
13753d2d2eSraf  * and limitations under the License.
14753d2d2eSraf  *
15753d2d2eSraf  * When distributing Covered Code, include this CDDL HEADER in each
16753d2d2eSraf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17753d2d2eSraf  * If applicable, add the following below this CDDL HEADER, with the
18753d2d2eSraf  * fields enclosed by brackets "[]" replaced with your own identifying
19753d2d2eSraf  * information: Portions Copyright [yyyy] [name of copyright owner]
20753d2d2eSraf  *
21753d2d2eSraf  * CDDL HEADER END
22753d2d2eSraf  */
23753d2d2eSraf 
24753d2d2eSraf /*
25753d2d2eSraf  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
26753d2d2eSraf  * Use is subject to license terms.
27753d2d2eSraf  */
28753d2d2eSraf 
29753d2d2eSraf #include "parseproto.h"
30753d2d2eSraf #include <assert.h>
31753d2d2eSraf 
32753d2d2eSraf static decl_spec_t	*declspec_Construct(void);
33753d2d2eSraf static void		 declspec_Destroy(decl_spec_t *);
34753d2d2eSraf static decl_spec_t	*declspec_Init(stt_t, char *);
35753d2d2eSraf static char		*declspec_VerifySTT(stt_t, stt_t);
36753d2d2eSraf static decl_spec_t	*declspec_AddSTT(decl_spec_t *, stt_t, const char **);
37753d2d2eSraf static decl_spec_t	*declspec_AddDS(decl_spec_t *,
38753d2d2eSraf 			    decl_spec_t *, const char **);
39753d2d2eSraf static stt_t		 declspec_GetSTT(decl_spec_t *);
40753d2d2eSraf static char		*declspec_GetTag(decl_spec_t *);
41753d2d2eSraf static type_t		*type_Construct(void);
42753d2d2eSraf static void		 type_Destroy(type_t *);
43753d2d2eSraf static type_t		*type_SetPtr(type_t *, stt_t);
44753d2d2eSraf static type_t		*type_SetFun(type_t *, decl_t *);
45753d2d2eSraf static type_t		*type_AddTail(type_t *, type_t *);
46753d2d2eSraf static	const char	*type_Verify(type_t *);
47753d2d2eSraf 
48753d2d2eSraf static	decl_t		*decl_Construct(void);
49753d2d2eSraf static	decl_t		*decl_AddArg(decl_t *, decl_t *);
50753d2d2eSraf static	int		 decl_IsVoid(decl_t *);
51753d2d2eSraf static	int		 decl_IsVoidArray(decl_t *);
52753d2d2eSraf static	const char	*decl_VerifyArgs(decl_t *);
53753d2d2eSraf static	decl_t		*decl_AddDS(decl_t *, decl_spec_t *, const char **);
54753d2d2eSraf static	decl_t		*decl_AddTypeTail(decl_t *, type_t *);
55753d2d2eSraf static	decl_t		*decl_addptr(decl_t *, type_t *);
56753d2d2eSraf static	decl_t		*decl_addary(decl_t *, char *);
57753d2d2eSraf static	decl_t		*decl_addfun(decl_t *, decl_t *);
58753d2d2eSraf static	decl_t		*decl_addellipsis(decl_t *);
59753d2d2eSraf 
60753d2d2eSraf #if defined(DEBUG)
61753d2d2eSraf static	void		type_PrintType(type_t *, int);
62753d2d2eSraf static	void		decl_PrintDecl(decl_t *, int);
63753d2d2eSraf static	void		decl_PrintTraceInfo(decl_t *);
64753d2d2eSraf static	char		*de_const(char *);
65753d2d2eSraf #endif
66753d2d2eSraf 
67753d2d2eSraf 
68753d2d2eSraf 
69753d2d2eSraf static	int	yylex(void);
70753d2d2eSraf static	void	yyerror(const char *);
71753d2d2eSraf static	int	yyparse(void);
72753d2d2eSraf 
73753d2d2eSraf #if defined(MEM_DEBUG)
74753d2d2eSraf static	int	declspec_Construct_calls;
75753d2d2eSraf static	int	type_Construct_calls;
76753d2d2eSraf static	int	decl_Construct_calls;
77753d2d2eSraf #endif
78753d2d2eSraf 
79753d2d2eSraf #if defined(DEBUG)
80753d2d2eSraf static	char	*de_const(char *);
81753d2d2eSraf #endif
82753d2d2eSraf %}
83753d2d2eSraf 
84753d2d2eSraf %union {
85753d2d2eSraf 	char		*s_val;
86753d2d2eSraf 	int		 i_val;
87753d2d2eSraf 	stt_t		 stt_val;
88753d2d2eSraf 	decl_spec_t	*ds_val;
89753d2d2eSraf 	type_t		*t_val;
90753d2d2eSraf 	decl_t		*d_val;
91753d2d2eSraf }
92753d2d2eSraf 
93753d2d2eSraf %token	<i_val>	ELLIPSIS
94753d2d2eSraf 
95753d2d2eSraf %token	<s_val>	INTEGER
96753d2d2eSraf %token	<s_val>	IDENTIFIER
97753d2d2eSraf %token	<s_val>	TYPEDEF_NAME
98753d2d2eSraf %type	<s_val>	constant_expression
99753d2d2eSraf 
100753d2d2eSraf %token	<stt_val>	REGISTER
101753d2d2eSraf %token	<stt_val>	TYPEDEF	EXTERN	AUTO	STATIC
102753d2d2eSraf %token	<stt_val>	VOID	CHAR	SHORT	INT	LONG
103753d2d2eSraf %token	<stt_val>	FLOAT	DOUBLE	SIGNED	UNSIGNED
104753d2d2eSraf %token	<stt_val>	CONST	VOLATILE	RESTRICT	RESTRICT_KYWD
105753d2d2eSraf %type	<stt_val>	struct_or_union
106753d2d2eSraf %type	<ds_val>	storage_class_specifier
107753d2d2eSraf %type	<ds_val>	type_qualifier
108753d2d2eSraf %type	<ds_val>	type_qualifier_list
109753d2d2eSraf 
110753d2d2eSraf %token	<ds_val>	STRUCT		UNION
111753d2d2eSraf %token	<ds_val>	ENUM
112753d2d2eSraf %type	<ds_val>	declaration_specifiers
113753d2d2eSraf %type	<ds_val>	type_specifier
114753d2d2eSraf %type	<ds_val>	struct_or_union_specifier enum_specifier
115753d2d2eSraf %type	<ds_val>	typedef_name
116753d2d2eSraf 
117753d2d2eSraf %type	<t_val>		pointer
118753d2d2eSraf 
119753d2d2eSraf %type	<d_val>		declaration
120753d2d2eSraf %type	<d_val>		init_declarator_list init_declarator
121753d2d2eSraf %type	<d_val>		declarator
122753d2d2eSraf %type	<d_val>		direct_declarator
123753d2d2eSraf %type	<d_val>		parameter_type_list parameter_list
124753d2d2eSraf %type	<d_val>		parameter_declaration
125753d2d2eSraf %type	<d_val>		abstract_declarator
126753d2d2eSraf %type	<d_val>		direct_abstract_declarator
127753d2d2eSraf 
128753d2d2eSraf %start	declaration
129753d2d2eSraf 
130753d2d2eSraf %%
131753d2d2eSraf 
132753d2d2eSraf /*
133753d2d2eSraf  * The grammar is derived from ANSI/ISO 9899-1990.
134753d2d2eSraf  */
135753d2d2eSraf 
136753d2d2eSraf declaration
137753d2d2eSraf 	: declaration_specifiers init_declarator_list ';'
138753d2d2eSraf 		{
139753d2d2eSraf 			decl_t	*dp;
140753d2d2eSraf 
141753d2d2eSraf 			protop = $$ = $2;
142753d2d2eSraf 
143753d2d2eSraf 			/* only one declaration allowed */
144753d2d2eSraf 			assert(protop->d_next == NULL);
145753d2d2eSraf 
146753d2d2eSraf 			for (dp = $2; dp && (errstr == NULL);
147753d2d2eSraf 			    dp = dp->d_next) {
148753d2d2eSraf 				const char	*sp;
149753d2d2eSraf 
150753d2d2eSraf 				decl_AddDS(dp, $1, &errstr);
151753d2d2eSraf 				if (sp = decl_Verify(dp))
152753d2d2eSraf 					errstr = sp;
153753d2d2eSraf 			}
154753d2d2eSraf 			declspec_Destroy($1);
155753d2d2eSraf 		}
156753d2d2eSraf 	| error ';'
157753d2d2eSraf 		{
158753d2d2eSraf 			protop = $$ = NULL;
159753d2d2eSraf 			errstr = "function prototype syntax error";
160753d2d2eSraf 		}
161753d2d2eSraf /*
162753d2d2eSraf  * XXX - Does not support a "stand-alone" declaration specifier. It is
163753d2d2eSraf  * essentially a type declaration, for example:
164753d2d2eSraf  *
165753d2d2eSraf  *	typedef enum { FALSE = 0, TRUE = 1 } boolean_t;
166753d2d2eSraf  * or
167753d2d2eSraf  *	struct _name { char *first; char *last };
168753d2d2eSraf  */
169753d2d2eSraf 
170753d2d2eSraf /* XXX	| declaration_specifiers */
171753d2d2eSraf 	;
172753d2d2eSraf 
173753d2d2eSraf declaration_specifiers
174753d2d2eSraf 	: storage_class_specifier declaration_specifiers
175753d2d2eSraf 		{
176753d2d2eSraf 			char const *ep;
177753d2d2eSraf 
178753d2d2eSraf 			$$ = declspec_AddDS($2, $1, &ep);
179753d2d2eSraf 			declspec_Destroy($1);
180753d2d2eSraf 
181753d2d2eSraf 			if (errstr == NULL)
182753d2d2eSraf 				errstr = ep;
183753d2d2eSraf 		}
184753d2d2eSraf 	| storage_class_specifier
185753d2d2eSraf 	| type_specifier declaration_specifiers
186753d2d2eSraf 		{
187753d2d2eSraf 			const char	*ep;
188753d2d2eSraf 
189753d2d2eSraf 			$$ = declspec_AddDS($2, $1, &ep);
190753d2d2eSraf 			declspec_Destroy($1);
191753d2d2eSraf 
192753d2d2eSraf 			if (errstr == NULL)
193753d2d2eSraf 				errstr = ep;
194753d2d2eSraf 		}
195753d2d2eSraf 	| type_specifier
196753d2d2eSraf 	| type_qualifier declaration_specifiers
197753d2d2eSraf 		{
198753d2d2eSraf 			const char	*ep;
199753d2d2eSraf 
200753d2d2eSraf 			$$ = declspec_AddDS($2, $1, &ep);
201753d2d2eSraf 			declspec_Destroy($1);
202753d2d2eSraf 
203753d2d2eSraf 			if (errstr == NULL)
204753d2d2eSraf 				errstr = ep;
205753d2d2eSraf 		}
206753d2d2eSraf 	| type_qualifier
207753d2d2eSraf 	;
208753d2d2eSraf 
209753d2d2eSraf storage_class_specifier
210753d2d2eSraf 	: REGISTER
211753d2d2eSraf 		{
212753d2d2eSraf 			$$ = declspec_Init(SCS_REGISTER, NULL);
213753d2d2eSraf 		}
214753d2d2eSraf /*
215753d2d2eSraf  * XXX - Does not support any storage class specifier other than
216753d2d2eSraf  * register, and then only for function arguments.
217753d2d2eSraf  *
218753d2d2eSraf 	| TYPEDEF
219753d2d2eSraf 		{
220753d2d2eSraf 			$$ = declspec_Init(SCS_TYPEDEF, NULL);
221753d2d2eSraf 		}
222753d2d2eSraf 	| EXTERN
223753d2d2eSraf 		{
224753d2d2eSraf 			$$ = declspec_Init(SCS_EXTERN, NULL);
225753d2d2eSraf 		}
226753d2d2eSraf 	| STATIC
227753d2d2eSraf 		{
228753d2d2eSraf 			$$ = declspec_Init(SCS_STATIC, NULL);
229753d2d2eSraf 		}
230753d2d2eSraf 	| AUTO
231753d2d2eSraf 		{
232753d2d2eSraf 			$$ = declspec_Init(SCS_AUTO, NULL);
233753d2d2eSraf 		}
234753d2d2eSraf  */
235753d2d2eSraf 	;
236753d2d2eSraf 
237753d2d2eSraf type_specifier
238753d2d2eSraf 	: VOID
239753d2d2eSraf 		{
240753d2d2eSraf 			$$ = declspec_Init(TS_VOID, NULL);
241753d2d2eSraf 			atIDENT = 1;
242753d2d2eSraf 		}
243753d2d2eSraf 	| CHAR
244753d2d2eSraf 		{
245753d2d2eSraf 			$$ = declspec_Init(TS_CHAR, NULL);
246753d2d2eSraf 			atIDENT = 1;
247753d2d2eSraf 		}
248753d2d2eSraf 	| SHORT
249753d2d2eSraf 		{
250753d2d2eSraf 			$$ = declspec_Init(TS_SHORT, NULL);
251753d2d2eSraf 			atIDENT = 1;
252753d2d2eSraf 		}
253753d2d2eSraf 	| INT
254753d2d2eSraf 		{
255753d2d2eSraf 			$$ = declspec_Init(TS_INT, NULL);
256753d2d2eSraf 			atIDENT = 1;
257753d2d2eSraf 		}
258753d2d2eSraf 	| LONG
259753d2d2eSraf 		{
260753d2d2eSraf 			$$ = declspec_Init(TS_LONG, NULL);
261753d2d2eSraf 			atIDENT = 1;
262753d2d2eSraf 		}
263753d2d2eSraf 	| FLOAT
264753d2d2eSraf 		{
265753d2d2eSraf 			$$ = declspec_Init(TS_FLOAT, NULL);
266753d2d2eSraf 			atIDENT = 1;
267753d2d2eSraf 		}
268753d2d2eSraf 	| DOUBLE
269753d2d2eSraf 		{
270753d2d2eSraf 			$$ = declspec_Init(TS_DOUBLE, NULL);
271753d2d2eSraf 			atIDENT = 1;
272753d2d2eSraf 		}
273753d2d2eSraf 	| SIGNED
274753d2d2eSraf 		{
275753d2d2eSraf 			$$ = declspec_Init(TS_SIGNED, NULL);
276753d2d2eSraf 			atIDENT = 1;
277753d2d2eSraf 		}
278753d2d2eSraf 	| UNSIGNED
279753d2d2eSraf 		{
280753d2d2eSraf 			$$ = declspec_Init(TS_UNSIGNED, NULL);
281753d2d2eSraf 			atIDENT = 1;
282753d2d2eSraf 		}
283753d2d2eSraf 	| struct_or_union_specifier
284753d2d2eSraf 	| enum_specifier
285753d2d2eSraf 	| typedef_name
286753d2d2eSraf 	;
287753d2d2eSraf 
288753d2d2eSraf typedef_name
289753d2d2eSraf 	: TYPEDEF_NAME
290753d2d2eSraf 		{
291753d2d2eSraf 			$$ = declspec_Init(TS_TYPEDEF, $1);
292753d2d2eSraf 			atIDENT = 1;
293753d2d2eSraf 			free($1);
294753d2d2eSraf 		}
295753d2d2eSraf 	;
296753d2d2eSraf 
297753d2d2eSraf /*
298753d2d2eSraf  * The "restrict" keyword is new in the C99 standard.
299753d2d2eSraf  * It is type qualifier like const and volatile.
300753d2d2eSraf  * We are using "_RESTRICT_KYWD" in headers and source code so
301753d2d2eSraf  * it is easily turned on and off by various macros at compile time.
302753d2d2eSraf  * In order for the "restrict" keyword to be recognized you must
303753d2d2eSraf  * be using a C99 compliant compiler in its native mode.
304753d2d2eSraf  */
305753d2d2eSraf type_qualifier
306753d2d2eSraf 	: CONST
307753d2d2eSraf 		{
308753d2d2eSraf 			$$ = declspec_Init(TQ_CONST, NULL);
309753d2d2eSraf 		}
310753d2d2eSraf 	| VOLATILE
311753d2d2eSraf 		{
312753d2d2eSraf 			$$ = declspec_Init(TQ_VOLATILE, NULL);
313753d2d2eSraf 		}
314753d2d2eSraf 	| RESTRICT
315753d2d2eSraf 		{
316753d2d2eSraf 			$$ = declspec_Init(TQ_RESTRICT, NULL);
317753d2d2eSraf 		}
318753d2d2eSraf 	| RESTRICT_KYWD
319753d2d2eSraf 		{
320753d2d2eSraf 			$$ = declspec_Init(TQ_RESTRICT_KYWD, NULL);
321753d2d2eSraf 		}
322753d2d2eSraf 	;
323753d2d2eSraf 
324753d2d2eSraf struct_or_union_specifier
325753d2d2eSraf 	: struct_or_union { atIDENT = 1; } IDENTIFIER
326753d2d2eSraf 		{
327753d2d2eSraf 			$$ = declspec_Init($1, $3);
328753d2d2eSraf 			free($3);
329753d2d2eSraf 		}
330753d2d2eSraf /*
331753d2d2eSraf  * XXX - struct or union definitions are not supported. It is generally
332753d2d2eSraf  * not done within the context of a function declaration (prototype) or
333753d2d2eSraf  * variable definition.
334753d2d2eSraf 
335753d2d2eSraf 	| struct_or_union IDENTIFIER '{' struct_declaration_list '}'
336753d2d2eSraf 	| struct_or_union '{' struct_declaration_list '}'
337753d2d2eSraf  */
338753d2d2eSraf 	;
339753d2d2eSraf 
340753d2d2eSraf struct_or_union
341753d2d2eSraf 	: STRUCT
342753d2d2eSraf 		{
343753d2d2eSraf 			$$ = TS_STRUCT;
344753d2d2eSraf 		}
345753d2d2eSraf 	| UNION
346753d2d2eSraf 		{
347753d2d2eSraf 			$$ = TS_UNION;
348753d2d2eSraf 		}
349753d2d2eSraf 	;
350753d2d2eSraf 
351753d2d2eSraf init_declarator_list
352753d2d2eSraf 	: init_declarator
353753d2d2eSraf 		{
354753d2d2eSraf 			$$ = $1;
355753d2d2eSraf 			atIDENT = 1;
356753d2d2eSraf 		}
357753d2d2eSraf /*
358753d2d2eSraf  * XXX - Does not support a comma separated list of declarations or
359753d2d2eSraf  * definitions. Function prototypes or variable definitions must be
360753d2d2eSraf  * given as one per C statement.
361753d2d2eSraf 
362753d2d2eSraf 	| init_declarator_list ',' init_declarator
363753d2d2eSraf 		{
364753d2d2eSraf 			$$ = decl_AddArg($1, $3);
365753d2d2eSraf 			atIDENT = 1;
366753d2d2eSraf 		}
367753d2d2eSraf */
368753d2d2eSraf 	;
369753d2d2eSraf 
370753d2d2eSraf init_declarator
371753d2d2eSraf 	: declarator
372753d2d2eSraf /*
373753d2d2eSraf  * XXX - Initialization is not supported.
374753d2d2eSraf 
375753d2d2eSraf 	| declarator '=' initializer
376753d2d2eSraf */
377753d2d2eSraf 	;
378753d2d2eSraf 
379753d2d2eSraf 
380753d2d2eSraf enum_specifier
381753d2d2eSraf 	: ENUM { atIDENT = 1; } IDENTIFIER
382753d2d2eSraf 		{
383753d2d2eSraf 			$$ = declspec_Init(TS_ENUM, $3);
384753d2d2eSraf 			free($3);
385753d2d2eSraf 		}
386753d2d2eSraf /*
387753d2d2eSraf  * XXX - enumerator definition is not supported for the same reasons
388753d2d2eSraf  * struct|union definition is not supported.
389753d2d2eSraf 
390753d2d2eSraf 	| ENUM IDENTIFIER '{' enumerator_list '}'
391753d2d2eSraf 	| ENUM '{' enumerator_list '}'
392753d2d2eSraf */
393753d2d2eSraf 	;
394753d2d2eSraf 
395753d2d2eSraf 
396753d2d2eSraf declarator
397753d2d2eSraf 	: pointer direct_declarator
398753d2d2eSraf 		{
399753d2d2eSraf 			$$ = decl_addptr($2, $1);
400753d2d2eSraf 		}
401753d2d2eSraf 	| direct_declarator
402753d2d2eSraf 	;
403753d2d2eSraf 
404753d2d2eSraf direct_declarator
405753d2d2eSraf 	: IDENTIFIER
406753d2d2eSraf 		{
407753d2d2eSraf 			$$ = decl_SetName(decl_Construct(), $1);
408753d2d2eSraf 			atIDENT = 0;
409753d2d2eSraf 			free($1);
410753d2d2eSraf 		}
411753d2d2eSraf 	| '(' declarator ')'
412753d2d2eSraf 		{
413753d2d2eSraf 			$$ = $2;
414753d2d2eSraf 		}
415753d2d2eSraf 	| direct_declarator '[' constant_expression ']'
416753d2d2eSraf 		{
417753d2d2eSraf 			$$ = decl_addary($1, $3);
418753d2d2eSraf 			free($3);
419753d2d2eSraf 		}
420753d2d2eSraf 	| direct_declarator '[' ']'
421753d2d2eSraf 		{
422753d2d2eSraf 			$$ = decl_addary($1, NULL);
423753d2d2eSraf 		}
424753d2d2eSraf 	| direct_declarator '(' parameter_type_list ')'
425753d2d2eSraf 		{
426753d2d2eSraf 			$$ = decl_addfun($1, $3);
427753d2d2eSraf 		}
428753d2d2eSraf 	| direct_declarator '(' ')'
429753d2d2eSraf 		{
430753d2d2eSraf 			$$ = decl_addfun($1, NULL);
431753d2d2eSraf 		}
432753d2d2eSraf 	;
433753d2d2eSraf 
434753d2d2eSraf pointer
435753d2d2eSraf 	: '*' type_qualifier_list
436753d2d2eSraf 		{
437753d2d2eSraf 			$$ = type_SetPtr(type_Construct(), ($2)->ds_stt);
438753d2d2eSraf 			declspec_Destroy($2);
439753d2d2eSraf 		}
440753d2d2eSraf 	| '*'
441753d2d2eSraf 		{
442753d2d2eSraf 			$$ = type_SetPtr(type_Construct(), TQ_NONE);
443753d2d2eSraf 		}
444753d2d2eSraf 	| '*' type_qualifier_list pointer
445753d2d2eSraf 		{
446753d2d2eSraf 			type_t	*tp = type_Construct();
447753d2d2eSraf 
448753d2d2eSraf 			type_SetPtr(tp, ($2)->ds_stt);
449753d2d2eSraf 			declspec_Destroy($2);
450753d2d2eSraf 			$$ = type_AddTail($3, tp);
451753d2d2eSraf 		}
452753d2d2eSraf 	| '*' pointer
453753d2d2eSraf 		{
454753d2d2eSraf 			type_t	*tp = type_Construct();
455753d2d2eSraf 
456753d2d2eSraf 			type_SetPtr(tp, TQ_NONE);
457753d2d2eSraf 			$$ = type_AddTail($2, tp);
458753d2d2eSraf 		}
459753d2d2eSraf 	;
460753d2d2eSraf 
461753d2d2eSraf type_qualifier_list
462753d2d2eSraf 	: type_qualifier
463753d2d2eSraf 	| type_qualifier_list type_qualifier
464753d2d2eSraf 		{
465753d2d2eSraf 			const char	*ep;
466753d2d2eSraf 
467753d2d2eSraf 			/* XXX - ignore any error */
468753d2d2eSraf 			$$ = declspec_AddDS($1, $2, &ep);
469753d2d2eSraf 			declspec_Destroy($2);
470753d2d2eSraf 		}
471753d2d2eSraf 	;
472753d2d2eSraf 
473753d2d2eSraf parameter_type_list
474753d2d2eSraf 	: parameter_list
475753d2d2eSraf 	| parameter_list ',' ELLIPSIS
476753d2d2eSraf 		{
477753d2d2eSraf 			$$ = decl_addellipsis($1);
478753d2d2eSraf 		}
479753d2d2eSraf 	;
480753d2d2eSraf 
481753d2d2eSraf parameter_list
482753d2d2eSraf 	: parameter_declaration
483753d2d2eSraf 		{
484753d2d2eSraf 			const char *sp = type_Verify($1->d_type);
485753d2d2eSraf 
486753d2d2eSraf 			if (sp)
487753d2d2eSraf 				errstr = sp;
488753d2d2eSraf 
489753d2d2eSraf 			$$ = $1;
490753d2d2eSraf 			atIDENT = 0;
491753d2d2eSraf 		}
492753d2d2eSraf 	| parameter_list ',' parameter_declaration
493753d2d2eSraf 		{
494753d2d2eSraf 			const char *sp = type_Verify($3->d_type);
495753d2d2eSraf 
496753d2d2eSraf 			if (sp)
497753d2d2eSraf 				errstr = sp;
498753d2d2eSraf 
499753d2d2eSraf 			$$ = decl_AddArg($1, $3);
500753d2d2eSraf 			atIDENT = 0;
501753d2d2eSraf 		}
502753d2d2eSraf 	;
503753d2d2eSraf 
504753d2d2eSraf parameter_declaration
505753d2d2eSraf 	: declaration_specifiers declarator
506753d2d2eSraf 		{
507753d2d2eSraf 			const char *ep;
508753d2d2eSraf 
509753d2d2eSraf 			$$ = decl_AddDS($2, $1, &ep);
510753d2d2eSraf 			declspec_Destroy($1);
511753d2d2eSraf 
512753d2d2eSraf 			if (errstr == NULL)
513753d2d2eSraf 				errstr = ep;
514753d2d2eSraf 		}
515753d2d2eSraf 	| declaration_specifiers abstract_declarator
516753d2d2eSraf 		{
517753d2d2eSraf 			const char *ep;
518753d2d2eSraf 
519753d2d2eSraf 			$$ = decl_AddDS($2, $1, &ep);
520753d2d2eSraf 			declspec_Destroy($1);
521753d2d2eSraf 
522753d2d2eSraf 			if (errstr == NULL)
523753d2d2eSraf 				errstr = ep;
524753d2d2eSraf 		}
525753d2d2eSraf 	| declaration_specifiers
526753d2d2eSraf 		{
527753d2d2eSraf 			const char *ep;
528753d2d2eSraf 
529753d2d2eSraf 			$$ = decl_AddDS(decl_Construct(), $1, &ep);
530753d2d2eSraf 			declspec_Destroy($1);
531753d2d2eSraf 
532753d2d2eSraf 			if (errstr == NULL)
533753d2d2eSraf 				errstr = ep;
534753d2d2eSraf 		}
535753d2d2eSraf 	;
536753d2d2eSraf 
537753d2d2eSraf abstract_declarator
538753d2d2eSraf 	: pointer
539753d2d2eSraf 		{
540753d2d2eSraf 			$$ = decl_addptr(decl_Construct(), $1);
541753d2d2eSraf 		}
542753d2d2eSraf 	| pointer direct_abstract_declarator
543753d2d2eSraf 		{
544753d2d2eSraf 			$$ = decl_addptr($2, $1);
545753d2d2eSraf 		}
546753d2d2eSraf 	| direct_abstract_declarator
547753d2d2eSraf 	;
548753d2d2eSraf 
549753d2d2eSraf direct_abstract_declarator
550753d2d2eSraf 	: '(' abstract_declarator ')'
551753d2d2eSraf 		{
552753d2d2eSraf 			$$ = $2;
553753d2d2eSraf 		}
554753d2d2eSraf 	| direct_abstract_declarator '[' constant_expression ']'
555753d2d2eSraf 		{
556753d2d2eSraf 			$$ = decl_addary($1, $3);
557753d2d2eSraf 			free($3);
558753d2d2eSraf 		}
559753d2d2eSraf 	| '[' constant_expression ']'
560753d2d2eSraf 		{
561753d2d2eSraf 			$$ = decl_addary(decl_Construct(), $2);
562753d2d2eSraf 			free($2);
563753d2d2eSraf 		}
564753d2d2eSraf 	| direct_abstract_declarator '[' ']'
565753d2d2eSraf 		{
566753d2d2eSraf 			$$ = decl_addary($1, NULL);
567753d2d2eSraf 		}
568753d2d2eSraf 	| '[' ']'
569753d2d2eSraf 		{
570753d2d2eSraf 			$$ = decl_addary(decl_Construct(), NULL);
571753d2d2eSraf 		}
572753d2d2eSraf 	| direct_abstract_declarator '(' parameter_type_list ')'
573753d2d2eSraf 		{
574753d2d2eSraf 			$$ = decl_addfun($1, $3);
575753d2d2eSraf 		}
576753d2d2eSraf 	| '(' parameter_type_list ')'
577753d2d2eSraf 		{
578753d2d2eSraf 			$$ = decl_addfun(decl_Construct(), $2);
579753d2d2eSraf 		}
580753d2d2eSraf 	| direct_abstract_declarator '(' ')'
581753d2d2eSraf 		{
582753d2d2eSraf 			$$ = decl_addfun($1, NULL);
583753d2d2eSraf 		}
584753d2d2eSraf 	| '(' ')'
585753d2d2eSraf 		{
586753d2d2eSraf 			$$ = decl_addfun(decl_Construct(), NULL);
587753d2d2eSraf 		}
588753d2d2eSraf 	;
589753d2d2eSraf 
590753d2d2eSraf /*
591753d2d2eSraf  * XXX - General case constant expressions are not supported. It would
592753d2d2eSraf  * be easy to implement (for the most part), but there are no cases to
593753d2d2eSraf  * date that require such a facility. The grammar does allow an
594753d2d2eSraf  * identifier (or typedef name) to be used since the prototype is not
595753d2d2eSraf  * processed by CPP. The only integer constant that is supported is
596753d2d2eSraf  * decimal.
597753d2d2eSraf  */
598753d2d2eSraf 
599753d2d2eSraf constant_expression
600753d2d2eSraf 	: INTEGER
601753d2d2eSraf 	| IDENTIFIER
602753d2d2eSraf 	| TYPEDEF_NAME
603753d2d2eSraf 	;
604753d2d2eSraf 
605753d2d2eSraf %%
606753d2d2eSraf 
607753d2d2eSraf /* Data Declarations */
608753d2d2eSraf 
609753d2d2eSraf typedef struct {
610753d2d2eSraf 	char	*name;
611753d2d2eSraf 	int	 token;
612753d2d2eSraf 	stt_t	 stt;
613753d2d2eSraf } keyword_t;
614753d2d2eSraf 
615753d2d2eSraf typedef struct {
616753d2d2eSraf 	stt_t	 s_stt;
617753d2d2eSraf 	char	*s_str;
618753d2d2eSraf } sttpair_t;
619753d2d2eSraf 
620753d2d2eSraf /* External Declarations */
621753d2d2eSraf 
622753d2d2eSraf static	const keyword_t	*lookup_keyword(const char *);
623753d2d2eSraf static	const char	*lookup_sttpair(stt_t);
624753d2d2eSraf static	int		 getch(void);
625753d2d2eSraf static	void		 ungetch(int);
626753d2d2eSraf static	void		 skipwhitespace(void);
627753d2d2eSraf static	int		 lookahead(int);
628753d2d2eSraf static	void		 skipcomment(void);
629753d2d2eSraf 
630753d2d2eSraf /* External Definitions */
631753d2d2eSraf 
632753d2d2eSraf static char		*input = NULL;	/* current place in the input stream */
633753d2d2eSraf /* at point in stream were identifier is expected */
634753d2d2eSraf static int		 atIDENT = 0;
635753d2d2eSraf static decl_t		*protop = NULL;	/* pointer to prototype */
636753d2d2eSraf static const char	*errstr = NULL;	/* error message */
637753d2d2eSraf 
638753d2d2eSraf /*
639753d2d2eSraf  * lookup_keyword - Given a string, return the keyword_t or NULL.
640753d2d2eSraf  */
641753d2d2eSraf 
642753d2d2eSraf static const keyword_t *
lookup_keyword(const char * name)643753d2d2eSraf lookup_keyword(const char *name) {
644753d2d2eSraf 	static	const keyword_t	keytbl[] = {
645753d2d2eSraf 		{	"register",	REGISTER,	SCS_REGISTER	},
646753d2d2eSraf #if UNSUPPORTED
647753d2d2eSraf 		{	"typedef",	TYPEDEF,	SCS_TYPEDEF	},
648753d2d2eSraf 		{	"auto",		AUTO,		SCS_AUTO	},
649753d2d2eSraf 		{	"static",	STATIC,		SCS_STATIC	},
650753d2d2eSraf 		{	"extern",	EXTERN,		SCS_EXTERN	},
651753d2d2eSraf #endif /* UNSUPPORTED */
652753d2d2eSraf 		{	"void",		VOID,		TS_VOID		},
653753d2d2eSraf 		{	"char",		CHAR,		TS_CHAR		},
654753d2d2eSraf 		{	"short",	SHORT,		TS_SHORT	},
655753d2d2eSraf 		{	"int",		INT,		TS_INT		},
656753d2d2eSraf 		{	"long",		LONG,		TS_LONG		},
657753d2d2eSraf 		{	"float",	FLOAT,		TS_FLOAT	},
658753d2d2eSraf 		{	"double",	DOUBLE,		TS_DOUBLE	},
659753d2d2eSraf 		{	"signed",	SIGNED,		TS_SIGNED	},
660753d2d2eSraf 		{	"unsigned",	UNSIGNED,	TS_UNSIGNED	},
661753d2d2eSraf 		{	"struct",	STRUCT,		TS_STRUCT	},
662753d2d2eSraf 		{	"union",	UNION,		TS_UNION	},
663753d2d2eSraf 		{	"enum",		ENUM,		TS_ENUM		},
664753d2d2eSraf 
665753d2d2eSraf 		{	"const",	CONST,		TQ_CONST	},
666753d2d2eSraf 		{	"volatile",	VOLATILE,	TQ_VOLATILE	},
667753d2d2eSraf 		{	"restrict",	RESTRICT,	TQ_RESTRICT	},
668753d2d2eSraf 		{	"_RESTRICT_KYWD",RESTRICT_KYWD,	TQ_RESTRICT_KYWD},
669753d2d2eSraf 	};
670753d2d2eSraf #define	NKEYWORD	(sizeof (keytbl)/sizeof (keyword_t))
671753d2d2eSraf 
672753d2d2eSraf 	int	i;
673753d2d2eSraf 
674753d2d2eSraf 	for (i = 0; i < NKEYWORD; ++i) {
675753d2d2eSraf 		char	*s = keytbl[i].name;
676753d2d2eSraf 
677753d2d2eSraf 		if ((*s == *name) && (strcmp(s, name) == 0))
678753d2d2eSraf 			return (&keytbl[i]);
679753d2d2eSraf 	}
680753d2d2eSraf 
681753d2d2eSraf 	return (NULL);
682753d2d2eSraf }
683753d2d2eSraf 
684753d2d2eSraf /*
685753d2d2eSraf  * lookup_sttpair - Given an stt_t return a string or NULL.
686753d2d2eSraf  *
687753d2d2eSraf  */
688753d2d2eSraf 
689753d2d2eSraf static const char *
lookup_sttpair(stt_t s)690753d2d2eSraf lookup_sttpair(stt_t s) {
691753d2d2eSraf 	/* valid type specifier combinations */
692753d2d2eSraf 	static const sttpair_t	stttbl[] = {
693753d2d2eSraf 		{ TS_VOID,				"void"		},
694753d2d2eSraf 		{ TS_CHAR,				"char"		},
695753d2d2eSraf 		{ TS_SIGNED | TS_CHAR,			"signed char"	},
696753d2d2eSraf 		{ TS_UNSIGNED | TS_CHAR,		"unsigned char"	},
697753d2d2eSraf 		{ TS_SHORT,				"short"		},
698753d2d2eSraf 		{ TS_SIGNED | TS_SHORT,			"signed short"	},
699753d2d2eSraf 		{ TS_SHORT | TS_INT,			"short int"	},
700753d2d2eSraf 		{ TS_SIGNED | TS_SHORT | TS_INT,
701753d2d2eSraf 		    "signed short int"				},
702753d2d2eSraf 		{ TS_UNSIGNED | TS_SHORT,
703753d2d2eSraf 		    "unsigned short"					},
704753d2d2eSraf 		{ TS_UNSIGNED | TS_SHORT | TS_INT,
705753d2d2eSraf 		    "unsigned short int"				},
706753d2d2eSraf 		{ TS_INT,				"int"		},
707753d2d2eSraf 		{ TS_SIGNED,				"signed"	},
708753d2d2eSraf 		{ TS_SIGNED | TS_INT,			"signed int"	},
709753d2d2eSraf 		{ TS_NO_TS,				""		},
710753d2d2eSraf 		{ TS_UNSIGNED,				"unsigned"	},
711753d2d2eSraf 		{ TS_UNSIGNED | TS_INT,			"unsigned int"	},
712753d2d2eSraf 		{ TS_LONG,				"long"		},
713753d2d2eSraf 		{ TS_SIGNED | TS_LONG,			"signed long"	},
714753d2d2eSraf 		{ TS_LONG | TS_INT,			"long int"	},
715753d2d2eSraf 		{ TS_SIGNED | TS_LONG | TS_INT,
716753d2d2eSraf 		    "signed long int"					},
717753d2d2eSraf 		{ TS_UNSIGNED | TS_LONG,		"unsigned long"	},
718753d2d2eSraf 		{ TS_UNSIGNED | TS_LONG | TS_INT,
719753d2d2eSraf 		    "unsigned long int"				},
720753d2d2eSraf 		{ TS_FLOAT,				"float"		},
721753d2d2eSraf 		{ TS_DOUBLE,				"double"	},
722753d2d2eSraf 		{ TS_LONG | TS_DOUBLE,			"long double"	},
723753d2d2eSraf 		{ TS_STRUCT,				"struct"	},
724753d2d2eSraf 		{ TS_UNION,				"union"		},
725753d2d2eSraf 		{ TS_ENUM,				"enum"		},
726753d2d2eSraf 		{ TS_TYPEDEF,				""		},
727753d2d2eSraf 		/* non-ANSI type: long long */
728753d2d2eSraf 		{ TS_LONGLONG,				"long long"	},
729753d2d2eSraf 		{ TS_LONGLONG | TS_INT,			"long long int"	},
730753d2d2eSraf 		{ TS_SIGNED | TS_LONGLONG,
731753d2d2eSraf 		    "signed long long"				},
732753d2d2eSraf 		{ TS_UNSIGNED | TS_LONGLONG,
733753d2d2eSraf 		    "unsigned long long"				},
734753d2d2eSraf 		{ TS_SIGNED | TS_LONGLONG | TS_INT,
735753d2d2eSraf 		    "signed long long int"				},
736753d2d2eSraf 		{ TS_UNSIGNED | TS_LONGLONG | TS_INT,
737753d2d2eSraf 		    "unsigned long long int"				},
738753d2d2eSraf 	};
739753d2d2eSraf 
740753d2d2eSraf #define	NDECLSPEC	(sizeof (stttbl)/sizeof (sttpair_t))
741753d2d2eSraf 
742753d2d2eSraf 	int	i;
743753d2d2eSraf 
744753d2d2eSraf 	for (i = 0; i < NDECLSPEC; ++i)
745753d2d2eSraf 		if (s == stttbl[i].s_stt)
746753d2d2eSraf 			return (stttbl[i].s_str);
747753d2d2eSraf 
748753d2d2eSraf 	return (NULL);
749753d2d2eSraf }
750753d2d2eSraf 
751753d2d2eSraf /*
752753d2d2eSraf  * yylex - return next token from the the input stream.
753753d2d2eSraf  *
754753d2d2eSraf  * The lexical analyzer does not recognize all possible C lexical
755753d2d2eSraf  * elements. It only recognizes those associated with function
756753d2d2eSraf  * declarations (read: prototypes) and data definitions.
757753d2d2eSraf  */
758753d2d2eSraf 
759753d2d2eSraf static int
yylex(void)760753d2d2eSraf yylex(void) {
761753d2d2eSraf 	char	buf[BUFSIZ];		/* string version of token */
762753d2d2eSraf 	int	c;
763753d2d2eSraf 	int	i = 0;
764753d2d2eSraf 
765753d2d2eSraf restart:
766753d2d2eSraf 	skipwhitespace();
767753d2d2eSraf 
768753d2d2eSraf 	switch (c = getch()) {
769753d2d2eSraf 	case '/':
770753d2d2eSraf 		if (lookahead('*')) {
771753d2d2eSraf 			skipcomment();
772753d2d2eSraf 			goto restart;
773753d2d2eSraf 		}
774*6ec25805SToomas Soome 		return (c);
775753d2d2eSraf 
776753d2d2eSraf 	case '.':
777753d2d2eSraf 		if (lookahead('.')) {
778753d2d2eSraf 			if (lookahead('.'))
779753d2d2eSraf 				return (ELLIPSIS);
780753d2d2eSraf 		}
781*6ec25805SToomas Soome 		return (c);
782753d2d2eSraf 
783753d2d2eSraf 	case EOF:
784753d2d2eSraf 	case '(':
785753d2d2eSraf 	case ')':
786753d2d2eSraf 	case ',':
787753d2d2eSraf 	case '[':
788753d2d2eSraf 	case ']':
789753d2d2eSraf 	case ';':
790753d2d2eSraf 	case '*':
791753d2d2eSraf 		return (c);
792753d2d2eSraf 
793753d2d2eSraf 	default:
794753d2d2eSraf 		if ((c == '_') || isalpha(c)) {
795753d2d2eSraf 			const keyword_t	*kp;
796753d2d2eSraf 
797753d2d2eSraf 			do {
798753d2d2eSraf 				buf[i++] = c;
799753d2d2eSraf 				c	 = getch();
800753d2d2eSraf 			} while ((c == '_') || isalnum(c));
801753d2d2eSraf 
802753d2d2eSraf 			ungetch(c);
803753d2d2eSraf 
804753d2d2eSraf 			buf[i] = '\0';
805753d2d2eSraf 
806753d2d2eSraf 			if ((kp = lookup_keyword(buf)) != NULL) {
807753d2d2eSraf 				yylval.stt_val = kp->stt;
808753d2d2eSraf 				return (kp->token);
809753d2d2eSraf 			} else {
810753d2d2eSraf 				yylval.s_val = strdup(buf);
811753d2d2eSraf 
812753d2d2eSraf 				return ((atIDENT) ? IDENTIFIER : TYPEDEF_NAME);
813753d2d2eSraf 			}
814753d2d2eSraf 		} else if (isdigit(c)) {
815753d2d2eSraf 			do {
816753d2d2eSraf 				buf[i++] = c;
817753d2d2eSraf 			} while (isdigit(c = getch()));
818753d2d2eSraf 
819753d2d2eSraf 			ungetch(c);
820753d2d2eSraf 
821753d2d2eSraf 			buf[i]	 = '\0';
822753d2d2eSraf 			yylval.s_val = strdup(buf);
823753d2d2eSraf 
824753d2d2eSraf 			return (INTEGER);
825753d2d2eSraf 		} else
826753d2d2eSraf 			return (c);
827753d2d2eSraf 	}
828753d2d2eSraf /* NOTREACHED */
829753d2d2eSraf }
830753d2d2eSraf 
831753d2d2eSraf /* getch - return the next character from the input stream. */
832753d2d2eSraf 
833753d2d2eSraf static int
getch(void)834753d2d2eSraf getch(void) {
835753d2d2eSraf 	int	c;
836753d2d2eSraf 
837753d2d2eSraf 	if ((c = *input) == '\0')
838753d2d2eSraf 		c = EOF;
839753d2d2eSraf 	else				/* only advance on non-NULL */
840753d2d2eSraf 		input++;
841753d2d2eSraf 
842753d2d2eSraf 	return (c);
843753d2d2eSraf }
844753d2d2eSraf 
845753d2d2eSraf /* ungetch - return a character to the input stream. */
846753d2d2eSraf 
847753d2d2eSraf static void
ungetch(int c)848753d2d2eSraf ungetch(int c) {
849753d2d2eSraf 	*(--input) = c;
850753d2d2eSraf }
851753d2d2eSraf 
852753d2d2eSraf /* skipwhitespace - skip over whitespace in the input stream. */
853753d2d2eSraf 
854753d2d2eSraf static void
skipwhitespace(void)855753d2d2eSraf skipwhitespace(void) {
856753d2d2eSraf 	int	c;
857753d2d2eSraf 
858753d2d2eSraf 	while (isspace(c = getch()))
859753d2d2eSraf 		;
860753d2d2eSraf 
861753d2d2eSraf 	ungetch(c);
862753d2d2eSraf }
863753d2d2eSraf 
864753d2d2eSraf /* skipcomment - scan ahead to the next end of comment. */
865753d2d2eSraf 
866753d2d2eSraf static void
skipcomment(void)867753d2d2eSraf skipcomment(void) {
868753d2d2eSraf 	loop {
869753d2d2eSraf 		int	c;
870753d2d2eSraf 
871753d2d2eSraf 		switch (c = getch()) {
872753d2d2eSraf 		case EOF:
873753d2d2eSraf 			return;
874753d2d2eSraf 
875753d2d2eSraf 		case '*':
876753d2d2eSraf 			if (lookahead('/'))
877753d2d2eSraf 				return;
878753d2d2eSraf 		}
879753d2d2eSraf 	}
880753d2d2eSraf /* NOTREACHED */
881753d2d2eSraf }
882753d2d2eSraf 
883753d2d2eSraf /* lookahead - does next character match 'c'? */
884753d2d2eSraf 
885753d2d2eSraf static int
lookahead(int c)886753d2d2eSraf lookahead(int c) {
887753d2d2eSraf 	int	ch = getch();
888753d2d2eSraf 	int	match;
889753d2d2eSraf 
890753d2d2eSraf 	if (!(match = (ch == c)))
891753d2d2eSraf 		ungetch(ch);
892753d2d2eSraf 
893753d2d2eSraf 	return (match);
894753d2d2eSraf }
895753d2d2eSraf 
896753d2d2eSraf /* putNtabs - write N '\t' to standard output. */
897753d2d2eSraf 
898753d2d2eSraf #if defined(DEBUG)
899753d2d2eSraf 
900753d2d2eSraf static void
putNTabs(int n)901753d2d2eSraf putNTabs(int n) {
902753d2d2eSraf 	int	 i;
903753d2d2eSraf 
904753d2d2eSraf 	for (i = 0; i < n; ++i)
905753d2d2eSraf 		putchar('\t');
906753d2d2eSraf }
907753d2d2eSraf #endif	/* DEBUG */
908753d2d2eSraf 
909753d2d2eSraf /* D E C L A R A T I O N   S P E C I F I E R S */
910753d2d2eSraf 
911753d2d2eSraf /*
912753d2d2eSraf  * Declaration specifiers encode storage class, type specifier and type
913753d2d2eSraf  * qualifier information. This includes any identifiers associated with
914753d2d2eSraf  * struct, union or enum declarations. Typedef names are also encoded
915753d2d2eSraf  * in declaration specifiers.
916753d2d2eSraf  */
917753d2d2eSraf 
918753d2d2eSraf /* declspec_Construct - allocate and initialize a declspec_t. */
919753d2d2eSraf 
920753d2d2eSraf static decl_spec_t *
declspec_Construct(void)921753d2d2eSraf declspec_Construct(void) {
922753d2d2eSraf 	decl_spec_t	*dsp = malloc(sizeof (decl_spec_t));
923753d2d2eSraf 
924753d2d2eSraf 	assert(dsp != NULL);
925753d2d2eSraf 	dsp->ds_stt = SCS_NONE | TS_NO_TS | TQ_NONE;
926753d2d2eSraf 	dsp->ds_id = NULL;
927753d2d2eSraf #if defined(MEM_DEBUG)
928753d2d2eSraf 	++declspec_Construct_calls;
929753d2d2eSraf #endif
930753d2d2eSraf 	return (dsp);
931753d2d2eSraf }
932753d2d2eSraf 
933753d2d2eSraf /* declspec_Destroy - free a declspec_t. */
934753d2d2eSraf 
935753d2d2eSraf static void
declspec_Destroy(decl_spec_t * dsp)936753d2d2eSraf declspec_Destroy(decl_spec_t *dsp) {
937753d2d2eSraf 	free(dsp->ds_id);
938753d2d2eSraf 	free(dsp);
939753d2d2eSraf #if defined(MEM_DEBUG)
940753d2d2eSraf 	--declspec_Construct_calls;
941753d2d2eSraf #endif
942753d2d2eSraf }
943753d2d2eSraf 
944753d2d2eSraf /*
945753d2d2eSraf  * declspec_Init - allocate and initialize a declspec_t given an
946753d2d2eSraf  *	stt_t and identifier.
947753d2d2eSraf  *
948753d2d2eSraf  * Note:
949753d2d2eSraf  *	1) identifier can be NULL.
950753d2d2eSraf  *	2) errors resulting in the stt_t and identifier are ignored.
951753d2d2eSraf  */
952753d2d2eSraf 
953753d2d2eSraf static decl_spec_t *
declspec_Init(stt_t s,char * tagp)954753d2d2eSraf declspec_Init(stt_t s, char *tagp) {
955753d2d2eSraf 	const char	*p;
956753d2d2eSraf 	decl_spec_t	*dsp = declspec_Construct();
957753d2d2eSraf 	decl_spec_t	 tmp;
958753d2d2eSraf 
959753d2d2eSraf 	tmp.ds_stt = s;
960753d2d2eSraf 	tmp.ds_id = tagp;
961753d2d2eSraf 
962753d2d2eSraf 	declspec_AddDS(dsp, &tmp, &p);		/* XXX ignore any error */
963753d2d2eSraf 
964753d2d2eSraf 	return (dsp);
965753d2d2eSraf }
966753d2d2eSraf 
967753d2d2eSraf /*
968753d2d2eSraf  * declspec_VerifySTT - verify that the two given stt_t can be combined.
969753d2d2eSraf  *
970753d2d2eSraf  * Note:
971753d2d2eSraf  *	1) The return value is a const char *, non-NULL to indicate an error.
972753d2d2eSraf  */
973753d2d2eSraf 
974753d2d2eSraf static char *
declspec_VerifySTT(stt_t s1,stt_t s2)975753d2d2eSraf declspec_VerifySTT(stt_t s1, stt_t s2) {
976753d2d2eSraf 	stt_t	result;
977753d2d2eSraf 
978753d2d2eSraf 	if ((s1 | s2) != (s1 ^ s2))
979753d2d2eSraf 		return ("attempt to add declaration specifier "
980753d2d2eSraf 		    "that is already present");
981753d2d2eSraf 
982753d2d2eSraf 	result = (s1 | s2) & TS_MASK;
983753d2d2eSraf 
984753d2d2eSraf 	if (lookup_sttpair(result) == NULL) {
985753d2d2eSraf 		if (STT_isbasic(result) && STT_isderived(result))
986753d2d2eSraf 			return ("attempt to combine basic and "
987753d2d2eSraf 			    "derived types");
988753d2d2eSraf 
989753d2d2eSraf 		if (STT_isvoid(result) &&
990753d2d2eSraf 		    (STT_isbasic(result) || STT_isderived(result)))
991753d2d2eSraf 			return ("attempt to combine void with "
992753d2d2eSraf 			    "other type specifiers");
993753d2d2eSraf 
994753d2d2eSraf 		if (STT_isfloat(result) && STT_isint(result))
995753d2d2eSraf 			return ("attempt to combine floating and "
996753d2d2eSraf 			    "integer type specifiers");
997753d2d2eSraf 
998753d2d2eSraf 		if (STT_ischar(result) && STT_isint(result))
999753d2d2eSraf 			return ("attempt to combine character and "
1000753d2d2eSraf 			    "integer type specifiers");
1001753d2d2eSraf 
1002753d2d2eSraf 		if (STT_has_explicit_sign(result) &&
1003753d2d2eSraf 		    (STT_isfloat(result) || STT_isderived(result)))
1004753d2d2eSraf 			return ("attempt to combine signed or "
1005753d2d2eSraf 			    "unsigned with float or derived type");
1006753d2d2eSraf 
1007753d2d2eSraf 		return ("invalid declaration specifier");
1008753d2d2eSraf 	}
1009753d2d2eSraf 
1010753d2d2eSraf 	return (NULL);
1011753d2d2eSraf }
1012753d2d2eSraf 
1013753d2d2eSraf /*
1014753d2d2eSraf  * declspec_AddSTT - add an stt_t to a decl_spec_t.
1015753d2d2eSraf  *
1016753d2d2eSraf  * Note:
1017753d2d2eSraf  *	1) The "long long" type is handled here.
1018753d2d2eSraf  *	   If both stt_t include TS_LONG then this is an attempt to use
1019753d2d2eSraf  *	   "long long". The TS_LONG is cleared from the s1 and s2 and
1020753d2d2eSraf  *	   then TS_LONGLONG is added to s2. The resulting s1 and s2 are
1021753d2d2eSraf  *	   passed to declspec_VerifySTT to determine if the result is valid.
1022753d2d2eSraf  *
1023753d2d2eSraf  *	2) This method of handling "long long" does detect the case of
1024753d2d2eSraf  *	   "long double long" and all it's variant forms.
1025753d2d2eSraf  */
1026753d2d2eSraf 
1027753d2d2eSraf static decl_spec_t *
declspec_AddSTT(decl_spec_t * dsp,stt_t s2,const char ** err)1028753d2d2eSraf declspec_AddSTT(decl_spec_t *dsp, stt_t s2, const char **err) {
1029753d2d2eSraf 	stt_t	s1 = dsp->ds_stt;
1030753d2d2eSraf 
1031753d2d2eSraf 	/* non-ANSI type: long long */
1032753d2d2eSraf 	if ((s1 & TS_LONG) && (s2 & TS_LONG)) {
1033753d2d2eSraf 		s1		&= ~(TS_LONG);
1034753d2d2eSraf 		dsp->ds_stt = s1;
1035753d2d2eSraf 		s2		&= ~(TS_LONG);
1036753d2d2eSraf 		s2		|= TS_LONGLONG;
1037753d2d2eSraf 	}
1038753d2d2eSraf 
1039753d2d2eSraf 	if ((*err = declspec_VerifySTT(s1, s2)) == NULL)
1040753d2d2eSraf 		dsp->ds_stt	|= s2;
1041753d2d2eSraf 
1042753d2d2eSraf 	return (dsp);
1043753d2d2eSraf }
1044753d2d2eSraf 
1045753d2d2eSraf /*
1046753d2d2eSraf  * declpec_AddDS - add a decl_spec_t to an existing decl_spec_t.
1047753d2d2eSraf  */
1048753d2d2eSraf 
1049753d2d2eSraf static decl_spec_t *
declspec_AddDS(decl_spec_t * dsp,decl_spec_t * tsp,const char ** err)1050753d2d2eSraf declspec_AddDS(decl_spec_t *dsp, decl_spec_t *tsp, const char **err) {
1051753d2d2eSraf 	declspec_AddSTT(dsp, tsp->ds_stt, err);
1052753d2d2eSraf 
1053753d2d2eSraf 	if ((*err == NULL) && tsp->ds_id) {
1054753d2d2eSraf 		free(dsp->ds_id);
1055753d2d2eSraf 		dsp->ds_id	 = strdup(tsp->ds_id);
1056753d2d2eSraf 
1057753d2d2eSraf 		assert(dsp->ds_id != NULL);
1058753d2d2eSraf 	}
1059753d2d2eSraf 
1060753d2d2eSraf 	return (dsp);
1061753d2d2eSraf }
1062753d2d2eSraf 
1063753d2d2eSraf /*
1064753d2d2eSraf  * declspec_GetSTT - return the stt_t within a decl_spec_t.
1065753d2d2eSraf  */
1066753d2d2eSraf 
1067753d2d2eSraf static stt_t
declspec_GetSTT(decl_spec_t * dsp)1068753d2d2eSraf declspec_GetSTT(decl_spec_t *dsp) {
1069753d2d2eSraf 	return (dsp->ds_stt);
1070753d2d2eSraf }
1071753d2d2eSraf 
1072753d2d2eSraf /*
1073753d2d2eSraf  * declspec_GetTag - return the identifier within a decl_spec_t.
1074753d2d2eSraf  */
1075753d2d2eSraf 
1076753d2d2eSraf static char *
declspec_GetTag(decl_spec_t * dsp)1077753d2d2eSraf declspec_GetTag(decl_spec_t *dsp) {
1078753d2d2eSraf 	return (dsp->ds_id);
1079753d2d2eSraf }
1080753d2d2eSraf 
1081753d2d2eSraf /*
1082753d2d2eSraf  * declspec_ToString - convert a decl_spec_t into a string.
1083753d2d2eSraf  *
1084753d2d2eSraf  * Note:
1085753d2d2eSraf  *	1) The form of the resulting string is always the same, i.e.
1086753d2d2eSraf  *
1087753d2d2eSraf  *		[register] [type_specifier] [const] [volatile]
1088753d2d2eSraf  *
1089753d2d2eSraf  * dsp must be correct
1090753d2d2eSraf  *
1091753d2d2eSraf  */
1092753d2d2eSraf 
1093753d2d2eSraf char *
declspec_ToString(char * bufp,decl_spec_t * dsp)1094753d2d2eSraf declspec_ToString(char *bufp, decl_spec_t *dsp) {
1095753d2d2eSraf 	const char	*s;
1096753d2d2eSraf 	int		 something = 0;
1097753d2d2eSraf 
1098753d2d2eSraf 	*bufp = '\0';
1099753d2d2eSraf 
1100753d2d2eSraf 	/* storage class specifier */
1101753d2d2eSraf 	switch (dsp->ds_stt & SCS_MASK) {
1102753d2d2eSraf 	case SCS_REGISTER:
1103753d2d2eSraf 		strcat(bufp, "register");
1104753d2d2eSraf 		something = 1;
1105753d2d2eSraf 		break;
1106753d2d2eSraf 	}
1107753d2d2eSraf 
1108753d2d2eSraf 	s = lookup_sttpair(dsp->ds_stt & TS_MASK);
1109753d2d2eSraf 
1110753d2d2eSraf 	/* type specifier */
1111753d2d2eSraf 	switch (dsp->ds_stt & TS_MASK) {
1112753d2d2eSraf 	case TS_STRUCT:
1113753d2d2eSraf 	case TS_UNION:
1114753d2d2eSraf 	case TS_ENUM:
1115753d2d2eSraf 		if (something)
1116753d2d2eSraf 			strcat(bufp, " ");
1117753d2d2eSraf 
1118753d2d2eSraf 		strcat(bufp, s);
1119753d2d2eSraf 		strcat(bufp, " ");
1120753d2d2eSraf 		strcat(bufp, dsp->ds_id);
1121753d2d2eSraf 		break;
1122753d2d2eSraf 
1123753d2d2eSraf 	case TS_TYPEDEF:
1124753d2d2eSraf 		if (something)
1125753d2d2eSraf 			strcat(bufp, " ");
1126753d2d2eSraf 
1127753d2d2eSraf 		strcat(bufp, dsp->ds_id);
1128753d2d2eSraf 		break;
1129753d2d2eSraf 
1130753d2d2eSraf 	default:
1131753d2d2eSraf 		if (something)
1132753d2d2eSraf 			strcat(bufp, " ");
1133753d2d2eSraf 
1134753d2d2eSraf 		strcat(bufp, s);
1135753d2d2eSraf 		break;
1136753d2d2eSraf 	}
1137753d2d2eSraf 
1138753d2d2eSraf 	if (s)
1139753d2d2eSraf 		something = 1;
1140753d2d2eSraf 
1141753d2d2eSraf 	if (something && (dsp->ds_stt & TQ_MASK))
1142753d2d2eSraf 		strcat(bufp, " ");
1143753d2d2eSraf 
1144753d2d2eSraf 	if (dsp->ds_stt & TQ_CONST)	/* type qualifier */
1145753d2d2eSraf 		strcat(bufp, "const");
1146753d2d2eSraf 
1147753d2d2eSraf 	if (dsp->ds_stt & TQ_VOLATILE) {
1148753d2d2eSraf 		if (dsp->ds_stt & TQ_CONST)
1149753d2d2eSraf 			strcat(bufp, " ");
1150753d2d2eSraf 
1151753d2d2eSraf 		strcat(bufp, "volatile");
1152753d2d2eSraf 	}
1153753d2d2eSraf 
1154753d2d2eSraf 	/*
1155753d2d2eSraf 	 * It currently acknowledges and ignores restrict or _RESTRICT_KYWD
1156753d2d2eSraf 	 * in code generation because of the uncertain behavior of "restrict".
1157753d2d2eSraf 	 */
1158753d2d2eSraf 	if (dsp->ds_stt & TQ_RESTRICT)
1159753d2d2eSraf 		strcat(bufp, "");
1160753d2d2eSraf 
1161753d2d2eSraf 	if (dsp->ds_stt & TQ_RESTRICT_KYWD)
1162753d2d2eSraf 		strcat(bufp, "");
1163753d2d2eSraf 
1164753d2d2eSraf 	return (bufp);
1165753d2d2eSraf }
1166753d2d2eSraf 
1167753d2d2eSraf /* T Y P E   M O D I F I E R S */
1168753d2d2eSraf 
1169753d2d2eSraf /*
1170753d2d2eSraf  * Type modifiers encode the "array of...", "pointer to ..." and
1171753d2d2eSraf  * "function returning ..." aspects of C types. The modifiers are kept
1172753d2d2eSraf  * as a linked list in precedence order. The grammar encodes the
1173753d2d2eSraf  * precedence order described by the standard.
1174753d2d2eSraf  *
1175753d2d2eSraf  * Type modifiers are always added at the end of list and the list is
1176753d2d2eSraf  * always traversed from head to tail.
1177753d2d2eSraf  */
1178753d2d2eSraf 
1179753d2d2eSraf /* type_Construct - allocate and initialize a type_t. */
1180753d2d2eSraf 
1181753d2d2eSraf static type_t *
type_Construct(void)1182753d2d2eSraf type_Construct(void) {
1183753d2d2eSraf 	type_t	*tp = malloc(sizeof (type_t));
1184753d2d2eSraf 
1185753d2d2eSraf 	assert(tp != NULL);
1186753d2d2eSraf 
1187753d2d2eSraf 	tp->t_next = NULL;			/* generic */
1188753d2d2eSraf 	tp->t_dt = DD_NONE;
1189753d2d2eSraf 
1190753d2d2eSraf 	tp->t_nargs = 0;			/* DD_FUN */
1191753d2d2eSraf 	tp->t_ellipsis = 0;
1192753d2d2eSraf 	tp->t_args = NULL;
1193753d2d2eSraf 						/* DD_PTR */
1194753d2d2eSraf 	tp->t_stt	 = (SCS_NONE | TS_NO_TS | TQ_NONE);
1195753d2d2eSraf 
1196753d2d2eSraf 	tp->t_sizestr = NULL;			/* DD_ARY */
1197753d2d2eSraf #if defined(MEM_DEBUG)
1198753d2d2eSraf 	++type_Construct_calls;
1199753d2d2eSraf #endif
1200753d2d2eSraf 	return (tp);
1201753d2d2eSraf }
1202753d2d2eSraf 
1203753d2d2eSraf /* type_Destroy - free a type_t list. */
1204753d2d2eSraf 
1205753d2d2eSraf static void
type_Destroy(type_t * tp)1206753d2d2eSraf type_Destroy(type_t *tp) {
1207753d2d2eSraf 	while (tp) {
1208753d2d2eSraf 		type_t	*nextp = tp->t_next;
1209753d2d2eSraf 
1210753d2d2eSraf 		switch (tp->t_dt) {
1211753d2d2eSraf 		case DD_FUN:
1212753d2d2eSraf 			decl_Destroy(tp->t_args);
1213753d2d2eSraf 			break;
1214753d2d2eSraf 
1215753d2d2eSraf 		case DD_PTR:
1216753d2d2eSraf 			break;
1217753d2d2eSraf 
1218753d2d2eSraf 		case DD_ARY:
1219753d2d2eSraf 			free(tp->t_sizestr);
1220753d2d2eSraf 			break;
1221753d2d2eSraf 		}
1222753d2d2eSraf 
1223753d2d2eSraf 		free(tp);
1224753d2d2eSraf 
1225753d2d2eSraf 		tp = nextp;
1226753d2d2eSraf #if defined(MEM_DEBUG)
1227753d2d2eSraf 		--type_Construct_calls;
1228753d2d2eSraf #endif
1229753d2d2eSraf 	}
1230753d2d2eSraf }
1231753d2d2eSraf 
1232753d2d2eSraf /*
1233753d2d2eSraf  * type_SetPtr - make a type_t into a "pointer to ..." variant.
1234753d2d2eSraf  *
1235753d2d2eSraf  * Note:
1236753d2d2eSraf  *	1) The stt_t will encode any type qualifiers (const, volatile).
1237753d2d2eSraf  */
1238753d2d2eSraf 
1239753d2d2eSraf static type_t *
type_SetPtr(type_t * tp,stt_t s)1240753d2d2eSraf type_SetPtr(type_t *tp, stt_t s) {
1241753d2d2eSraf 	assert(tp->t_dt == DD_NONE);
1242753d2d2eSraf 
1243753d2d2eSraf 	tp->t_dt = DD_PTR;
1244753d2d2eSraf 	tp->t_stt = s & TQ_MASK;
1245753d2d2eSraf 
1246753d2d2eSraf 	return (tp);
1247753d2d2eSraf }
1248753d2d2eSraf 
1249753d2d2eSraf /*
1250753d2d2eSraf  * type_SetAry - make a type_t into an "array of ...", variant.
1251753d2d2eSraf  *
1252753d2d2eSraf  * Note:
1253753d2d2eSraf  *	1) The array dimension can be NULL to indicate undefined, i.e. [].
1254753d2d2eSraf  */
1255753d2d2eSraf 
1256753d2d2eSraf static type_t *
type_SetAry(type_t * tp,char * dim)1257753d2d2eSraf type_SetAry(type_t *tp, char *dim) {
1258753d2d2eSraf 	assert(tp->t_dt == DD_NONE);
1259753d2d2eSraf 	assert(tp->t_sizestr == NULL);
1260753d2d2eSraf 
1261753d2d2eSraf 	tp->t_dt = DD_ARY;
1262753d2d2eSraf 
1263753d2d2eSraf 	if (dim) {
1264753d2d2eSraf 		tp->t_sizestr = strdup(dim);
1265753d2d2eSraf 		assert(tp->t_sizestr != NULL);
1266753d2d2eSraf 	} else
1267753d2d2eSraf 		tp->t_sizestr = NULL;
1268753d2d2eSraf 
1269753d2d2eSraf 	return (tp);
1270753d2d2eSraf }
1271753d2d2eSraf 
1272753d2d2eSraf /*
1273753d2d2eSraf  * type_SetFun - make a type_t into a "function returning ..." variant.
1274753d2d2eSraf  *
1275753d2d2eSraf  * Note:
1276753d2d2eSraf  *	1) The argument list can be NULL to indicate undefined, i.e. ().
1277753d2d2eSraf  */
1278753d2d2eSraf 
1279753d2d2eSraf static type_t *
type_SetFun(type_t * tp,decl_t * arglist)1280753d2d2eSraf type_SetFun(type_t *tp, decl_t *arglist) {
1281753d2d2eSraf 	assert(tp->t_dt == DD_NONE);
1282753d2d2eSraf 
1283753d2d2eSraf 	tp->t_dt = DD_FUN;
1284753d2d2eSraf 
1285753d2d2eSraf 	if (arglist) {
1286753d2d2eSraf 		tp->t_nargs = decl_GetArgLength(arglist);
1287753d2d2eSraf 		tp->t_args = arglist;
1288753d2d2eSraf 		tp->t_ellipsis = arglist->d_ellipsis;
1289753d2d2eSraf 	}
1290753d2d2eSraf 
1291753d2d2eSraf 	return (tp);
1292753d2d2eSraf }
1293753d2d2eSraf 
1294753d2d2eSraf /*
1295753d2d2eSraf  * type_AddTail - add a type_t to the end of an existing type_t list.
1296753d2d2eSraf  *
1297753d2d2eSraf  * Note:
1298753d2d2eSraf  *	1) The type_t *tp is added to the end of the type_t *dp list.
1299753d2d2eSraf  */
1300753d2d2eSraf 
1301753d2d2eSraf static type_t *
type_AddTail(type_t * dp,type_t * tp)1302753d2d2eSraf type_AddTail(type_t *dp, type_t *tp) {
1303753d2d2eSraf 	type_t	*lastp = dp;
1304753d2d2eSraf 	type_t	*p;
1305753d2d2eSraf 
1306753d2d2eSraf 	while (p = lastp->t_next)
1307753d2d2eSraf 		lastp = p;
1308753d2d2eSraf 
1309753d2d2eSraf 	lastp->t_next = tp;
1310753d2d2eSraf 
1311753d2d2eSraf 	return (dp);
1312753d2d2eSraf }
1313753d2d2eSraf 
1314753d2d2eSraf #if defined(DEBUG)
1315753d2d2eSraf 
1316753d2d2eSraf /* type_PrintType - print a type_t list onto standard output. */
1317753d2d2eSraf 
1318753d2d2eSraf static void
type_PrintType(type_t * tp,int lvl)1319753d2d2eSraf type_PrintType(type_t *tp, int lvl) {
1320753d2d2eSraf 	decl_spec_t	tmp;
1321753d2d2eSraf 	char		buf[BUFSIZ];
1322753d2d2eSraf 
1323753d2d2eSraf 	while (tp) {
1324753d2d2eSraf 		putNTabs(lvl);
1325753d2d2eSraf 
1326753d2d2eSraf 		switch (tp->t_dt) {
1327753d2d2eSraf 		case DD_PTR:
1328753d2d2eSraf 			tmp.ds_stt = tp->t_stt;
1329753d2d2eSraf 			tmp.ds_id = NULL;
1330753d2d2eSraf 
1331753d2d2eSraf 			printf("[%s] ptr to\n", declspec_ToString(buf, &tmp));
1332753d2d2eSraf 			break;
1333753d2d2eSraf 
1334753d2d2eSraf 		case DD_FUN:
1335753d2d2eSraf 			printf("fun [%d%c] %s\n",
1336753d2d2eSraf 			    tp->t_nargs,
1337753d2d2eSraf 			    (tp->t_ellipsis)? '+' : '=',
1338753d2d2eSraf 			    (tp->t_args)? "with arguments" :
1339753d2d2eSraf 			    "undefined arguments");
1340753d2d2eSraf 
1341753d2d2eSraf 			if (tp->t_args) {
1342753d2d2eSraf 				decl_PrintDecl(tp->t_args, lvl + 1);
1343753d2d2eSraf 
1344753d2d2eSraf 				if (tp->t_ellipsis) {
1345753d2d2eSraf 					putNTabs(lvl + 1);
1346753d2d2eSraf 					printf("...\n");
1347753d2d2eSraf 				}
1348753d2d2eSraf 			}
1349753d2d2eSraf 			break;
1350753d2d2eSraf 
1351753d2d2eSraf 		case DD_ARY:
1352753d2d2eSraf 			printf("ary [%s] of\n",
1353753d2d2eSraf 			    (tp->t_sizestr)? tp->t_sizestr : "");
1354753d2d2eSraf 			break;
1355753d2d2eSraf 		}
1356753d2d2eSraf 
1357753d2d2eSraf 		tp = tp->t_next;
1358753d2d2eSraf 	}
1359753d2d2eSraf }
1360753d2d2eSraf #endif	/* DEBUG */
1361753d2d2eSraf 
1362753d2d2eSraf /*
1363753d2d2eSraf  * type_Verify - verify a type_t list for semantic correctness.
1364753d2d2eSraf  *
1365753d2d2eSraf  * Note:
1366753d2d2eSraf  *	1) C supports most combinations of type modifiers.
1367753d2d2eSraf  *	   It does not support three combinations, they are:
1368753d2d2eSraf  *
1369753d2d2eSraf  *		function returning array
1370753d2d2eSraf  *		array of functions
1371753d2d2eSraf  *		function returning function
1372753d2d2eSraf  *
1373753d2d2eSraf  *	2) The enum values associated with type modifiers (i.e. DD_*)
1374753d2d2eSraf  *	   cannot be modified without changing the table included within the
1375753d2d2eSraf  *	   function.
1376753d2d2eSraf  *
1377753d2d2eSraf  * 	3) The function returns NULL to indicate that the type modifier
1378753d2d2eSraf  *	   list is valid and non-NULL to indicate an error.
1379753d2d2eSraf  *
1380753d2d2eSraf  *	4) A type_t of NULL is permitted to indicate an empty type_t list.
1381753d2d2eSraf  */
1382753d2d2eSraf 
1383753d2d2eSraf static const char *
type_Verify(type_t * tp)1384753d2d2eSraf type_Verify(type_t *tp) {
1385753d2d2eSraf 	static const char *dttbl[4][4] = {
1386753d2d2eSraf 		/* NONE	ARY	FUN	PTR */
1387753d2d2eSraf /* NONE */	{NULL,	NULL,	NULL,	NULL},
1388753d2d2eSraf /* ARY */	{NULL,	NULL,	"array of functions", NULL},
1389753d2d2eSraf /* FUN */	{NULL,	"function returning array",
1390753d2d2eSraf 		    "function returning function", NULL},
1391753d2d2eSraf /* PTR */	{NULL,	NULL,	NULL,	NULL},
1392753d2d2eSraf 	};
1393753d2d2eSraf 
1394753d2d2eSraf 	if (tp) {
1395753d2d2eSraf 		type_t	*nextp;
1396753d2d2eSraf 
1397753d2d2eSraf 		do {
1398753d2d2eSraf 			const char	*p;
1399753d2d2eSraf 			decl_type_t	 nt;
1400753d2d2eSraf 
1401753d2d2eSraf 			nt = (nextp = tp->t_next)? nextp->t_dt : DD_NONE;
1402753d2d2eSraf 
1403753d2d2eSraf 			if ((p = dttbl[tp->t_dt][nt]) != NULL)
1404753d2d2eSraf 				return (p);
1405753d2d2eSraf 
1406753d2d2eSraf 		} while (tp = nextp);
1407753d2d2eSraf 	}
1408753d2d2eSraf 
1409753d2d2eSraf 	return (NULL);
1410753d2d2eSraf }
1411753d2d2eSraf 
1412753d2d2eSraf /* type_GetNext - return the next type_t in the list. */
1413753d2d2eSraf 
1414753d2d2eSraf type_t *
type_GetNext(type_t * tp)1415753d2d2eSraf type_GetNext(type_t *tp) {
1416753d2d2eSraf 	return (tp->t_next);
1417753d2d2eSraf }
1418753d2d2eSraf 
1419753d2d2eSraf /*
1420753d2d2eSraf  * The following group of functions return and or
1421753d2d2eSraf  * test various aspects of type modifiers.
1422753d2d2eSraf  *
1423753d2d2eSraf  * 1) The three functions: type_IsPtrTo, type_IsFunction and
1424753d2d2eSraf  *    type_IsArray will accept an argument of NULL.
1425753d2d2eSraf  *
1426753d2d2eSraf  * 2) All other functions require one of the above three to be true.
1427753d2d2eSraf  *    Various asserts are in place to verify correct usage.
1428753d2d2eSraf  */
1429753d2d2eSraf 
1430753d2d2eSraf int
type_IsArray(type_t * tp)1431753d2d2eSraf type_IsArray(type_t *tp) {
1432753d2d2eSraf 	return (tp && (tp->t_dt == DD_ARY));
1433753d2d2eSraf }
1434753d2d2eSraf 
1435753d2d2eSraf char *
type_GetArraySize(type_t * tp)1436753d2d2eSraf type_GetArraySize(type_t *tp) {
1437753d2d2eSraf 	assert(tp->t_dt == DD_ARY);
1438753d2d2eSraf 
1439753d2d2eSraf 	return (tp->t_sizestr);
1440753d2d2eSraf }
1441753d2d2eSraf 
1442753d2d2eSraf int
type_IsPtrTo(type_t * tp)1443753d2d2eSraf type_IsPtrTo(type_t *tp) {
1444753d2d2eSraf 	return (tp && (tp->t_dt == DD_PTR));
1445753d2d2eSraf }
1446753d2d2eSraf 
1447753d2d2eSraf stt_t
type_GetPtrToTypeQual(type_t * tp)1448753d2d2eSraf type_GetPtrToTypeQual(type_t *tp) {
1449753d2d2eSraf 	assert(tp->t_dt == DD_PTR);
1450753d2d2eSraf 
1451753d2d2eSraf 	return (tp->t_stt);
1452753d2d2eSraf }
1453753d2d2eSraf 
1454753d2d2eSraf int
type_IsFunction(type_t * tp)1455753d2d2eSraf type_IsFunction(type_t *tp) {
1456753d2d2eSraf 	return (tp && (tp->t_dt == DD_FUN));
1457753d2d2eSraf }
1458753d2d2eSraf 
1459753d2d2eSraf int
type_GetArgLength(type_t * tp)1460753d2d2eSraf type_GetArgLength(type_t *tp) {
1461753d2d2eSraf 	assert(tp->t_dt == DD_FUN);
1462753d2d2eSraf 
1463753d2d2eSraf 	return (tp->t_nargs);
1464753d2d2eSraf }
1465753d2d2eSraf 
1466753d2d2eSraf int
type_IsVarargs(type_t * tp)1467753d2d2eSraf type_IsVarargs(type_t *tp) {
1468753d2d2eSraf 	while (tp && tp->t_dt == DD_PTR)
1469753d2d2eSraf 		tp = tp->t_next;
1470753d2d2eSraf 
1471753d2d2eSraf 	assert(tp->t_dt == DD_FUN);
1472753d2d2eSraf 
1473753d2d2eSraf 	return (tp->t_ellipsis);
1474753d2d2eSraf }
1475753d2d2eSraf 
1476753d2d2eSraf decl_t *
type_GetArg(type_t * tp)1477753d2d2eSraf type_GetArg(type_t *tp) {
1478753d2d2eSraf 	assert(tp->t_dt == DD_FUN);
1479753d2d2eSraf 
1480753d2d2eSraf 	return (tp->t_args);
1481753d2d2eSraf }
1482753d2d2eSraf 
1483753d2d2eSraf /*
1484753d2d2eSraf  * type_IsPtrFun - determine if the type_t results in a call-able function.
1485753d2d2eSraf  *
1486753d2d2eSraf  * Note:
1487753d2d2eSraf  *	1) The argument can be NULL.
1488753d2d2eSraf  *
1489753d2d2eSraf  *	2) The test is true if the type_t list is number of DD_PTR followed
1490753d2d2eSraf  *	by a DD_FUN.
1491753d2d2eSraf  */
1492753d2d2eSraf 
1493753d2d2eSraf int
type_IsPtrFun(type_t * tp)1494753d2d2eSraf type_IsPtrFun(type_t *tp) {
1495753d2d2eSraf 
1496753d2d2eSraf 	if (! (tp && (tp->t_dt == DD_PTR)))
1497753d2d2eSraf 		return (0);
1498753d2d2eSraf 
1499753d2d2eSraf 	tp = tp->t_next;
1500753d2d2eSraf 
1501753d2d2eSraf 	while (tp && (tp->t_dt == DD_PTR))
1502753d2d2eSraf 		tp = tp->t_next;
1503753d2d2eSraf 
1504753d2d2eSraf 	return (tp && (tp->t_dt == DD_FUN));
1505753d2d2eSraf }
1506753d2d2eSraf 
1507753d2d2eSraf /* D E C L A R A T O R */
1508753d2d2eSraf 
1509753d2d2eSraf /*
1510753d2d2eSraf  * A decl_t encodes the name,
1511753d2d2eSraf  * declaration specifiers and type modifiers of an object.
1512753d2d2eSraf  */
1513753d2d2eSraf 
1514753d2d2eSraf /* decl_Construct - allocate a decl_t. */
1515753d2d2eSraf 
1516753d2d2eSraf static decl_t *
decl_Construct(void)1517753d2d2eSraf decl_Construct(void) {
1518753d2d2eSraf 	decl_t	*dp = malloc(sizeof (decl_t));
1519753d2d2eSraf 
1520753d2d2eSraf 	assert(dp != NULL);
1521753d2d2eSraf 
1522753d2d2eSraf 	dp->d_name = NULL;
1523753d2d2eSraf 	dp->d_type = NULL;
1524753d2d2eSraf 	dp->d_next = NULL;
1525753d2d2eSraf 	dp->d_ds = declspec_Construct();
1526753d2d2eSraf 	dp->d_ellipsis = 0;
1527753d2d2eSraf #if defined(MEM_DEBUG)
1528753d2d2eSraf 	++decl_Construct_calls;
1529753d2d2eSraf #endif
1530753d2d2eSraf 	return (dp);
1531753d2d2eSraf }
1532753d2d2eSraf 
1533753d2d2eSraf /* decl_Destroy - free a decl_t list. */
1534753d2d2eSraf 
1535753d2d2eSraf void
decl_Destroy(decl_t * dp)1536753d2d2eSraf decl_Destroy(decl_t *dp) {
1537753d2d2eSraf 	while (dp) {
1538753d2d2eSraf 		decl_t	*nextp = dp->d_next;
1539753d2d2eSraf 
1540753d2d2eSraf 		type_Destroy(dp->d_type);
1541753d2d2eSraf 		declspec_Destroy(dp->d_ds);
1542753d2d2eSraf 		free(dp->d_name);
1543753d2d2eSraf 		free(dp);
1544753d2d2eSraf 
1545753d2d2eSraf 		dp = nextp;
1546753d2d2eSraf #if defined(MEM_DEBUG)
1547753d2d2eSraf 		--decl_Construct_calls;
1548753d2d2eSraf #endif
1549753d2d2eSraf 	}
1550753d2d2eSraf }
1551753d2d2eSraf 
1552753d2d2eSraf /*
1553753d2d2eSraf  * decl_GetArgLength - return the length of a decl_t list.
1554753d2d2eSraf  *
1555753d2d2eSraf  * Note:
1556753d2d2eSraf  *	1) The argument may be NULL to indicate an empty list, len == 0.
1557753d2d2eSraf  */
1558753d2d2eSraf 
1559753d2d2eSraf int
decl_GetArgLength(decl_t * dp)1560753d2d2eSraf decl_GetArgLength(decl_t *dp) {
1561753d2d2eSraf 	int	len;
1562753d2d2eSraf 
1563753d2d2eSraf 	for (len = 0; dp; dp = dp->d_next)
1564753d2d2eSraf 		++len;
1565753d2d2eSraf 
1566753d2d2eSraf 	return (len);
1567753d2d2eSraf }
1568753d2d2eSraf 
1569753d2d2eSraf /*
1570753d2d2eSraf  * The following group of functions get or test various aspects of a decl_t.
1571753d2d2eSraf  */
1572753d2d2eSraf 
1573753d2d2eSraf decl_t *
decl_GetNext(decl_t * dp)1574753d2d2eSraf decl_GetNext(decl_t *dp) {
1575753d2d2eSraf 	return (dp->d_next);
1576753d2d2eSraf }
1577753d2d2eSraf 
1578753d2d2eSraf stt_t
decl_GetDeclSpec(decl_t * dp)1579753d2d2eSraf decl_GetDeclSpec(decl_t *dp) {
1580753d2d2eSraf 	return (declspec_GetSTT(dp->d_ds));
1581753d2d2eSraf }
1582753d2d2eSraf 
1583753d2d2eSraf char *
decl_GetDSName(decl_t * dp)1584753d2d2eSraf decl_GetDSName(decl_t *dp) {
1585753d2d2eSraf 	return (declspec_GetTag(dp->d_ds));
1586753d2d2eSraf }
1587753d2d2eSraf 
1588753d2d2eSraf type_t *
decl_GetType(decl_t * dp)1589753d2d2eSraf decl_GetType(decl_t *dp) {
1590753d2d2eSraf 	return (dp->d_type);
1591753d2d2eSraf }
1592753d2d2eSraf 
1593753d2d2eSraf int
decl_IsVarargs(decl_t * dp)1594753d2d2eSraf decl_IsVarargs(decl_t *dp) {
1595753d2d2eSraf 	return (dp->d_ellipsis);
1596753d2d2eSraf }
1597753d2d2eSraf 
1598753d2d2eSraf int
decl_IsFunction(decl_t * dp)1599753d2d2eSraf decl_IsFunction(decl_t *dp) {
1600753d2d2eSraf 	return (type_IsFunction(dp->d_type));
1601753d2d2eSraf }
1602753d2d2eSraf 
1603753d2d2eSraf char *
decl_GetName(decl_t * dp)1604753d2d2eSraf decl_GetName(decl_t *dp) {
1605753d2d2eSraf 	return (dp->d_name);
1606753d2d2eSraf }
1607753d2d2eSraf 
1608753d2d2eSraf /*
1609753d2d2eSraf  * decl_AddArg - add a decl_t to the end of an decl_t list.
1610753d2d2eSraf  */
1611753d2d2eSraf 
1612753d2d2eSraf static decl_t *
decl_AddArg(decl_t * dp,decl_t * tp)1613753d2d2eSraf decl_AddArg(decl_t *dp, decl_t *tp) {
1614753d2d2eSraf 	decl_t	*lastp = dp;
1615753d2d2eSraf 	decl_t	*p;
1616753d2d2eSraf 
1617753d2d2eSraf 	while (p = lastp->d_next)
1618753d2d2eSraf 		lastp = p;
1619753d2d2eSraf 
1620753d2d2eSraf 	lastp->d_next = tp;
1621753d2d2eSraf 
1622753d2d2eSraf 	return (dp);
1623753d2d2eSraf }
1624753d2d2eSraf 
1625753d2d2eSraf /*
1626753d2d2eSraf  * decl_IsVoid - return true if the decl_t is a "pure" void declaration.
1627753d2d2eSraf  */
1628753d2d2eSraf 
1629753d2d2eSraf static int
decl_IsVoid(decl_t * dp)1630753d2d2eSraf decl_IsVoid(decl_t *dp) {
1631753d2d2eSraf 	return ((declspec_GetSTT(dp->d_ds) & TS_VOID) && (dp->d_type == NULL));
1632753d2d2eSraf }
1633753d2d2eSraf 
1634753d2d2eSraf /*
1635753d2d2eSraf  * decl_IsVoidArray - return true if the decl_t includes "void []".
1636753d2d2eSraf  */
1637753d2d2eSraf 
1638753d2d2eSraf static int
decl_IsVoidArray(decl_t * dp)1639753d2d2eSraf decl_IsVoidArray(decl_t *dp) {
1640753d2d2eSraf 	int	 retval = 0;
1641753d2d2eSraf 	type_t	*tp = dp->d_type;
1642753d2d2eSraf 
1643753d2d2eSraf 	if (tp) {
1644753d2d2eSraf 		type_t	*np;
1645753d2d2eSraf 
1646753d2d2eSraf 		while (np = type_GetNext(tp))
1647753d2d2eSraf 			tp = np;
1648753d2d2eSraf 
1649753d2d2eSraf 		retval = type_IsArray(tp) &&
1650753d2d2eSraf 		    (declspec_GetSTT(dp->d_ds) & TS_VOID);
1651753d2d2eSraf 	}
1652753d2d2eSraf 
1653753d2d2eSraf 	return (retval);
1654753d2d2eSraf }
1655753d2d2eSraf 
1656753d2d2eSraf /*
1657753d2d2eSraf  * decl_Verify - verify a decl_t.
1658753d2d2eSraf  */
1659753d2d2eSraf 
1660753d2d2eSraf static const char *
decl_Verify(decl_t * dp)1661753d2d2eSraf decl_Verify(decl_t *dp) {
1662753d2d2eSraf 	const char	*ep = NULL;
1663753d2d2eSraf 
1664753d2d2eSraf 	if (decl_IsVoid(dp))
1665753d2d2eSraf 		ep = "type is void";
1666753d2d2eSraf 	else if (decl_IsVoidArray(dp))
1667753d2d2eSraf 		ep = "type is void []";
1668753d2d2eSraf 	else
1669753d2d2eSraf 		ep = type_Verify(dp->d_type);
1670753d2d2eSraf 
1671753d2d2eSraf 	return (ep);
1672753d2d2eSraf }
1673753d2d2eSraf 
1674753d2d2eSraf /*
1675753d2d2eSraf  * decl_VerifyArgs - verify a decl_t list.
1676753d2d2eSraf  */
1677753d2d2eSraf 
1678753d2d2eSraf static const char *
decl_VerifyArgs(decl_t * dp)1679753d2d2eSraf decl_VerifyArgs(decl_t *dp) {
1680753d2d2eSraf 	decl_t		*tp = dp;
1681753d2d2eSraf 	const char	*ep = NULL;
1682753d2d2eSraf 
1683753d2d2eSraf 	if (dp) {
1684753d2d2eSraf 		int	 nv = 0;
1685753d2d2eSraf 		int	 nargs = decl_GetArgLength(dp);
1686753d2d2eSraf 
1687753d2d2eSraf 		for (; dp; dp = dp->d_next)
1688753d2d2eSraf 			if (decl_IsVoid(dp)) {
1689753d2d2eSraf 				++nv;
1690753d2d2eSraf 
1691753d2d2eSraf 				if (decl_GetName(dp))
1692753d2d2eSraf 					ep = "argument list includes "
1693753d2d2eSraf 					    "void with identifier";
1694753d2d2eSraf 			} else if (decl_IsVoidArray(dp))
1695753d2d2eSraf 				ep = "argument list includes void []";
1696753d2d2eSraf 
1697753d2d2eSraf 		if (nv) {		/* there was some void */
1698753d2d2eSraf 			if (nargs > 1)
1699753d2d2eSraf 				ep = "argument list includes void";
1700753d2d2eSraf 
1701753d2d2eSraf 			if (tp->d_ellipsis)
1702753d2d2eSraf 				ep = "argument list includes void and \"...\"";
1703753d2d2eSraf 		}
1704753d2d2eSraf 	}
1705753d2d2eSraf 
1706753d2d2eSraf 	return (ep);
1707753d2d2eSraf }
1708753d2d2eSraf 
1709753d2d2eSraf /* decl_AddDS - add a decl_spec_t to a decl_t. */
1710753d2d2eSraf 
1711753d2d2eSraf static decl_t *
decl_AddDS(decl_t * dp,decl_spec_t * dsp,const char ** err)1712753d2d2eSraf decl_AddDS(decl_t *dp, decl_spec_t *dsp, const char **err) {
1713753d2d2eSraf 	declspec_AddDS(dp->d_ds, dsp, err);
1714753d2d2eSraf 
1715753d2d2eSraf 	return (dp);
1716753d2d2eSraf }
1717753d2d2eSraf 
1718753d2d2eSraf /*
1719753d2d2eSraf  * decl_SetName - set the name associated with a decl_t.
1720753d2d2eSraf  *
1721753d2d2eSraf  * Note:
1722753d2d2eSraf  *	1) Any previously known name is free'd.
1723753d2d2eSraf  */
1724753d2d2eSraf 
1725753d2d2eSraf decl_t *
decl_SetName(decl_t * dp,char * s)1726753d2d2eSraf decl_SetName(decl_t *dp, char *s) {
1727753d2d2eSraf 	free(dp->d_name);
1728753d2d2eSraf 	dp->d_name = strdup(s);
1729753d2d2eSraf 	assert(dp->d_name != NULL);
1730753d2d2eSraf 
1731753d2d2eSraf 	return (dp);
1732753d2d2eSraf }
1733753d2d2eSraf 
1734753d2d2eSraf /*
1735753d2d2eSraf  * decl_AddTypeTail - add a type_t to the end of a decl_t type_t list.
1736753d2d2eSraf  */
1737753d2d2eSraf 
1738753d2d2eSraf static decl_t *
decl_AddTypeTail(decl_t * dp,type_t * tp)1739753d2d2eSraf decl_AddTypeTail(decl_t *dp, type_t *tp) {
1740753d2d2eSraf 	if (dp->d_type)
1741753d2d2eSraf 		type_AddTail(dp->d_type, tp);
1742753d2d2eSraf 	else
1743753d2d2eSraf 		dp->d_type = tp;
1744753d2d2eSraf 
1745753d2d2eSraf 	return (dp);
1746753d2d2eSraf }
1747753d2d2eSraf 
1748753d2d2eSraf /*
1749753d2d2eSraf  * decl_addptr - add a DD_PTR type_t to the end of a decl_t type_t list.
1750753d2d2eSraf  */
1751753d2d2eSraf 
1752753d2d2eSraf static decl_t *
decl_addptr(decl_t * dp,type_t * tp)1753753d2d2eSraf decl_addptr(decl_t *dp, type_t *tp) {
1754753d2d2eSraf 	decl_AddTypeTail(dp, tp);
1755753d2d2eSraf 
1756753d2d2eSraf 	return (dp);
1757753d2d2eSraf }
1758753d2d2eSraf 
1759753d2d2eSraf /*
1760753d2d2eSraf  * decl_addary - allocate and add a DD_ARY type_t to the end of
1761753d2d2eSraf  *	a decl_t type_t list.
1762753d2d2eSraf  */
1763753d2d2eSraf 
1764753d2d2eSraf static decl_t *
decl_addary(decl_t * dp,char * sizep)1765753d2d2eSraf decl_addary(decl_t *dp, char *sizep) {
1766753d2d2eSraf 	type_t	*tp = type_Construct();
1767753d2d2eSraf 
1768753d2d2eSraf 	type_SetAry(tp, sizep);
1769753d2d2eSraf 	decl_AddTypeTail(dp, tp);
1770753d2d2eSraf 
1771753d2d2eSraf 	return (dp);
1772753d2d2eSraf }
1773753d2d2eSraf 
1774753d2d2eSraf /*
1775753d2d2eSraf  * decl_addfun - allocate and add a DD_FUN type_t to the end of a
1776753d2d2eSraf  *	 decl_t type_t list.
1777753d2d2eSraf  */
1778753d2d2eSraf 
1779753d2d2eSraf static decl_t *
decl_addfun(decl_t * dp,decl_t * arglist)1780753d2d2eSraf decl_addfun(decl_t *dp, decl_t *arglist) {
1781753d2d2eSraf 	const char	*sp;
1782753d2d2eSraf 	type_t	*tp = type_Construct();
1783753d2d2eSraf 
1784753d2d2eSraf 	if (sp = decl_VerifyArgs(arglist))
1785753d2d2eSraf 		yyerror(sp);
1786753d2d2eSraf 
1787753d2d2eSraf 	type_SetFun(tp, arglist);
1788753d2d2eSraf 	decl_AddTypeTail(dp, tp);
1789753d2d2eSraf 
1790753d2d2eSraf 	return (dp);
1791753d2d2eSraf }
1792753d2d2eSraf 
1793753d2d2eSraf /*
1794753d2d2eSraf  * decl_addellipsis - set the ellipsis state in a decl_t.
1795753d2d2eSraf  *
1796753d2d2eSraf  * Note:
1797753d2d2eSraf  *	1) This function is only used in the grammar in the
1798753d2d2eSraf  *	   parameter list parsing.
1799753d2d2eSraf  */
1800753d2d2eSraf 
1801753d2d2eSraf static decl_t *
decl_addellipsis(decl_t * dp)1802753d2d2eSraf decl_addellipsis(decl_t *dp) {
1803753d2d2eSraf 	dp->d_ellipsis = 1;
1804753d2d2eSraf 
1805753d2d2eSraf 	return (dp);
1806753d2d2eSraf }
1807753d2d2eSraf 
1808753d2d2eSraf #if defined(DEBUG)
1809753d2d2eSraf 
1810753d2d2eSraf static void
decl_PrintDecl(decl_t * dp,int lvl)1811753d2d2eSraf decl_PrintDecl(decl_t *dp, int lvl) {
1812753d2d2eSraf 	char	buf[BUFSIZ];
1813753d2d2eSraf 
1814753d2d2eSraf 	while (dp) {
1815753d2d2eSraf 		putNTabs(lvl);
1816753d2d2eSraf 
1817753d2d2eSraf 		printf("name = %s, ds = %s\n",
1818753d2d2eSraf 				(dp->d_name)? dp->d_name : "<null>",
1819753d2d2eSraf 				declspec_ToString(buf, dp->d_ds));
1820753d2d2eSraf 
1821753d2d2eSraf 		if (dp->d_type)
1822753d2d2eSraf 			type_PrintType(dp->d_type, lvl + 1);
1823753d2d2eSraf 
1824753d2d2eSraf 		dp = dp->d_next;
1825753d2d2eSraf 	}
1826753d2d2eSraf }
1827753d2d2eSraf #endif	/* DEBUG */
1828753d2d2eSraf 
1829753d2d2eSraf static char *
char_getend(char * s)1830753d2d2eSraf char_getend(char *s) {
1831753d2d2eSraf 	while (*s != '\0')
1832753d2d2eSraf 		++s;
1833753d2d2eSraf 
1834753d2d2eSraf 	return (s);
1835753d2d2eSraf }
1836753d2d2eSraf 
1837753d2d2eSraf char *
decl_ToString(char * bufp,decl_dts_t out,decl_t * dp,const char * altname)1838753d2d2eSraf decl_ToString(char *bufp, decl_dts_t out, decl_t *dp,
1839753d2d2eSraf     const char *altname) {
1840753d2d2eSraf 	char	 tmp[BUFSIZ];
1841753d2d2eSraf 	char	 tmp2[BUFSIZ];
1842753d2d2eSraf 	const char *namep;
1843753d2d2eSraf 	char	*bend = bufp;
1844753d2d2eSraf 	type_t	*tp = dp->d_type;
1845753d2d2eSraf 	int ffun = 1;
1846753d2d2eSraf 
1847753d2d2eSraf 	switch (out) {
1848753d2d2eSraf 	default:
1849753d2d2eSraf 		out = DTS_DECL;
1850753d2d2eSraf 		/* FALLTHRU */
1851753d2d2eSraf 	case DTS_DECL:
1852753d2d2eSraf 		if (altname == NULL) {
1853753d2d2eSraf 			namep = dp->d_name;
1854753d2d2eSraf 		} else {
1855753d2d2eSraf 			namep = altname;
1856753d2d2eSraf 		}
1857753d2d2eSraf 		break;
1858753d2d2eSraf 	case DTS_CAST:
1859753d2d2eSraf 		namep = "(*)";
1860753d2d2eSraf 		break;
1861753d2d2eSraf 	case DTS_RET:
1862753d2d2eSraf 		if (altname == NULL) {
1863753d2d2eSraf 			namep = "_return";
1864753d2d2eSraf 		} else {
1865753d2d2eSraf 			namep = altname;
1866753d2d2eSraf 		}
1867753d2d2eSraf 		break;
1868753d2d2eSraf 	}
1869753d2d2eSraf 
1870753d2d2eSraf 	*bufp = '\0';
1871753d2d2eSraf 
1872753d2d2eSraf 	strcpy(tmp, (namep) ? namep : "");
1873753d2d2eSraf 
1874753d2d2eSraf 	while (tp) {
1875753d2d2eSraf 		switch (tp->t_dt) {
1876753d2d2eSraf 		case DD_PTR:
1877753d2d2eSraf 			if (tp->t_next &&
1878753d2d2eSraf 			    ((tp->t_next->t_dt == DD_ARY) ||
1879753d2d2eSraf 			    (tp->t_next->t_dt == DD_FUN))) {
1880753d2d2eSraf 				if (out == DTS_RET) {
1881753d2d2eSraf 					sprintf(bufp, "(*%s)", namep);
1882753d2d2eSraf 				} else {
1883753d2d2eSraf 					sprintf(bufp, "(*%s)", tmp);
1884753d2d2eSraf 				}
1885753d2d2eSraf 			} else if (tp->t_stt == TQ_CONST) {
1886753d2d2eSraf 				sprintf(bufp, "*const %s", tmp);
1887753d2d2eSraf 			} else if (tp->t_stt == TQ_VOLATILE) {
1888753d2d2eSraf 				sprintf(bufp, "*volatile %s", tmp);
1889753d2d2eSraf 			/*
1890753d2d2eSraf 			 * It currently acknowledges and ignores restrict
1891753d2d2eSraf 			 * or _RESTRICT_KYWD in code generation because
1892753d2d2eSraf 			 * of the uncertain behavior of "restrict".
1893753d2d2eSraf 			 */
1894753d2d2eSraf 			} else if (tp->t_stt == TQ_RESTRICT) {
1895753d2d2eSraf 				sprintf(bufp, "*%s", tmp);
1896753d2d2eSraf 			} else if (tp->t_stt == TQ_RESTRICT_KYWD) {
1897753d2d2eSraf 				sprintf(bufp, "*%s", tmp);
1898753d2d2eSraf 			} else {
1899753d2d2eSraf 				sprintf(bufp, "*%s", tmp);
1900753d2d2eSraf 			}
1901753d2d2eSraf 
1902753d2d2eSraf 			break;
1903753d2d2eSraf 
1904753d2d2eSraf 		case DD_ARY:
1905753d2d2eSraf 			sprintf(bufp, "%s[%s]",
1906753d2d2eSraf 			    tmp, (tp->t_sizestr)? tp->t_sizestr : "");
1907753d2d2eSraf 			break;
1908753d2d2eSraf 
1909753d2d2eSraf 		case DD_FUN:
1910753d2d2eSraf 			if (out == DTS_RET && ffun == 1) {
1911753d2d2eSraf 				strcpy(bufp, namep);
1912753d2d2eSraf 				ffun = 0;
1913753d2d2eSraf 			} else if (tp->t_args == NULL) {
1914753d2d2eSraf 				sprintf(bufp, "%s()", tmp);
1915753d2d2eSraf 			} else {
1916753d2d2eSraf 				char	 buf2[BUFSIZ];
1917753d2d2eSraf 				decl_t	*argp = tp->t_args;
1918753d2d2eSraf 
1919753d2d2eSraf 				sprintf(bufp, "%s(", tmp);
1920753d2d2eSraf 				bend = char_getend(bufp);
1921753d2d2eSraf 
1922753d2d2eSraf 				for (argp = tp->t_args; argp; /* noinc */) {
1923753d2d2eSraf 					decl_ToString(buf2, DTS_DECL, argp,
1924753d2d2eSraf 					    NULL);
1925753d2d2eSraf 					sprintf(bend, " %s", buf2);
1926753d2d2eSraf 
1927753d2d2eSraf 					bend = char_getend(bend);
1928753d2d2eSraf 
1929753d2d2eSraf 					if (argp = argp->d_next) {
1930753d2d2eSraf 						sprintf(bend, ",");
1931753d2d2eSraf 						bend = char_getend(bend);
1932753d2d2eSraf 					}
1933753d2d2eSraf 				}
1934753d2d2eSraf 
1935753d2d2eSraf 				if (tp->t_ellipsis) {
1936753d2d2eSraf 					sprintf(bend, ", ...");
1937753d2d2eSraf 					bend = char_getend(bend);
1938753d2d2eSraf 				}
1939753d2d2eSraf 
1940753d2d2eSraf 				sprintf(bend, ")");
1941753d2d2eSraf 			}
1942753d2d2eSraf 			break;
1943753d2d2eSraf 		}
1944753d2d2eSraf 
1945753d2d2eSraf 		tp = tp->t_next;
1946753d2d2eSraf 
1947753d2d2eSraf 		strcpy(tmp, bufp);
1948753d2d2eSraf 	}
1949753d2d2eSraf 
1950753d2d2eSraf 	if (out == DTS_CAST) {
1951753d2d2eSraf 		sprintf(bufp, "(%s %s)",
1952753d2d2eSraf 		    declspec_ToString(tmp2, dp->d_ds), tmp);
1953753d2d2eSraf 	} else {
1954753d2d2eSraf 		sprintf(bufp, "%s %s",
1955753d2d2eSraf 		    declspec_ToString(tmp2, dp->d_ds), tmp);
1956753d2d2eSraf 	}
1957753d2d2eSraf 
1958753d2d2eSraf 	return (bufp);
1959753d2d2eSraf }
1960753d2d2eSraf 
1961753d2d2eSraf decl_t *
decl_AddArgNames(decl_t * dp)1962753d2d2eSraf decl_AddArgNames(decl_t *dp) {
1963753d2d2eSraf 	int	 argno = 0;
1964753d2d2eSraf 	decl_t	*p = dp;
1965753d2d2eSraf 
1966753d2d2eSraf 	if (decl_IsFunction(dp)) {
1967753d2d2eSraf 		int	 argno = 0;
1968753d2d2eSraf 		decl_t	*p = dp->d_type->t_args;
1969753d2d2eSraf 
1970753d2d2eSraf 		while (p) {
1971753d2d2eSraf 			char	*s = decl_GetName(p);
1972753d2d2eSraf 
1973753d2d2eSraf 			if ((s == NULL) && !decl_IsVoid(p)) {
1974753d2d2eSraf 				char	buf[BUFSIZ];
1975753d2d2eSraf 
1976753d2d2eSraf 				sprintf(buf, "arg%d", argno);
1977753d2d2eSraf 				s = strdup(buf);
1978753d2d2eSraf 				decl_SetName(p, s);
1979753d2d2eSraf 			}
1980753d2d2eSraf 
1981753d2d2eSraf 			p = p->d_next;
1982753d2d2eSraf 			++argno;
1983753d2d2eSraf 		}
1984753d2d2eSraf 	}
1985753d2d2eSraf 	return (dp);
1986753d2d2eSraf }
1987753d2d2eSraf 
1988753d2d2eSraf const char *
decl_Parse(char * str,decl_t ** dpp)1989753d2d2eSraf decl_Parse(char *str, decl_t **dpp) {
1990753d2d2eSraf 	errstr = NULL;	/* setup the (static) globals */
1991753d2d2eSraf 	input = str;
1992753d2d2eSraf 	atIDENT = 0;
1993753d2d2eSraf 	protop = NULL;
1994753d2d2eSraf 
1995753d2d2eSraf 	yyparse();	/* parse the prototype */
1996753d2d2eSraf 
1997753d2d2eSraf 	if (errstr == NULL) {		/* success */
1998753d2d2eSraf 		*dpp = protop;
1999753d2d2eSraf 		decl_AddArgNames(protop);
2000753d2d2eSraf 	} else {	/* failure */
2001753d2d2eSraf 		*dpp = NULL;
2002753d2d2eSraf 		decl_Destroy(protop);
2003753d2d2eSraf 	}
2004753d2d2eSraf 
2005753d2d2eSraf 	return (errstr);
2006753d2d2eSraf }
2007753d2d2eSraf 
2008753d2d2eSraf static void
yyerror(const char * err)2009753d2d2eSraf yyerror(const char *err) {
2010753d2d2eSraf 	errstr = err;
2011753d2d2eSraf }
2012753d2d2eSraf 
2013753d2d2eSraf #if defined(DEBUG)
2014753d2d2eSraf 
2015753d2d2eSraf /* main */
2016753d2d2eSraf 
2017753d2d2eSraf static int yydebug = 1;
2018753d2d2eSraf 
2019753d2d2eSraf int
main(int argc,char * argv[])2020753d2d2eSraf main(int argc, char *argv[]) {
2021753d2d2eSraf 	int	i;
2022753d2d2eSraf 
2023753d2d2eSraf 	yydebug = 1;
2024753d2d2eSraf 
2025753d2d2eSraf 	for (i = 1; i < argc; ++i) {
2026753d2d2eSraf 		const char	*es;
2027753d2d2eSraf 		char		 buf[BUFSIZ];
2028753d2d2eSraf 		decl_t		*pp;
2029753d2d2eSraf 
2030753d2d2eSraf 		if (es = decl_Parse(argv[i], &pp))
2031753d2d2eSraf 			printf("parse failure: %s\n", es);
2032753d2d2eSraf 		else {
2033753d2d2eSraf #if GR_DEBUG
2034753d2d2eSraf 			decl_PrintDecl(pp, 0);
2035753d2d2eSraf 			decl_AddArgNames(pp);
2036753d2d2eSraf #endif
2037753d2d2eSraf 			printf("---\n%s;\n",
2038753d2d2eSraf 			    decl_ToString(buf, DTS_DECL, pp, NULL));
2039753d2d2eSraf 			printf("%s\n",
2040753d2d2eSraf 			    decl_ToString(buf, DTS_CAST, pp, NULL));
2041753d2d2eSraf 			printf("%s;\n",
2042753d2d2eSraf 			    decl_ToString(buf, DTS_RET, pp, "%s"));
2043753d2d2eSraf 
2044753d2d2eSraf #ifdef TRACE
2045753d2d2eSraf 			printf("\n\nTrace Info\n");
2046753d2d2eSraf 			decl_PrintTraceInfo(pp);
2047753d2d2eSraf #endif
2048753d2d2eSraf 		}
2049753d2d2eSraf 
2050753d2d2eSraf 		decl_Destroy(pp);
2051753d2d2eSraf 
2052753d2d2eSraf #if defined(MEM_DEBUG)
2053753d2d2eSraf 		printf("declspec : %d\n", declspec_Construct_calls);
2054753d2d2eSraf 		printf("type     : %d\n", type_Construct_calls);
2055753d2d2eSraf 		printf("decl     : %d\n", decl_Construct_calls);
2056753d2d2eSraf #endif
2057753d2d2eSraf 	}
2058753d2d2eSraf 
2059753d2d2eSraf 	return (0);
2060753d2d2eSraf }
2061753d2d2eSraf 
2062753d2d2eSraf #ifdef TRACE
2063753d2d2eSraf void
decl_PrintTraceInfo(decl_t * dp)2064753d2d2eSraf decl_PrintTraceInfo(decl_t *dp) {
2065753d2d2eSraf 	char	buf[BUFSIZ];
2066753d2d2eSraf 	char	f_type[BUFSIZ];
2067753d2d2eSraf 	char	f_print[BUFSIZ];
2068753d2d2eSraf 	char	a_name[BUFSIZ];
2069753d2d2eSraf 	char	a_type[BUFSIZ];
2070753d2d2eSraf 	char	a_print[BUFSIZ];
2071753d2d2eSraf 	decl_t	*funargs;
2072753d2d2eSraf 	type_t	*tp;
2073753d2d2eSraf 	int	isptrfun;
2074753d2d2eSraf 
2075753d2d2eSraf 	if (dp == NULL)
2076753d2d2eSraf 		return;
2077753d2d2eSraf 
2078753d2d2eSraf 	fprintf(stderr, "interface = %s\n",
2079753d2d2eSraf 	    (dp->d_name) ? dp->d_name : "<null>");
2080753d2d2eSraf 
2081753d2d2eSraf 	isptrfun = type_IsPtrFun(dp->d_type);
2082753d2d2eSraf 	if (type_IsFunction(dp->d_type) || isptrfun)
2083753d2d2eSraf 		decl_GetTraceInfo(dp, f_type, f_print, &funargs);
2084753d2d2eSraf 	else
2085753d2d2eSraf 		return;
2086753d2d2eSraf 
2087753d2d2eSraf 	fprintf(stderr, "return type = %s\n", f_type);
2088753d2d2eSraf 	fprintf(stderr, "print function = %s\n", f_print);
2089753d2d2eSraf 
2090753d2d2eSraf 	if (isptrfun)
2091753d2d2eSraf 		fprintf(stderr, "function is function pointer\n");
2092753d2d2eSraf 
2093753d2d2eSraf 	if (type_IsVarargs(dp->d_type))
2094753d2d2eSraf 		fprintf(stderr, "function is varargs\n");
2095753d2d2eSraf 
2096753d2d2eSraf 	while (funargs) {
2097753d2d2eSraf 		snprintf(a_type, BUFSIZ, "%s ",
2098753d2d2eSraf 		    declspec_ToString(buf, funargs->d_ds));
2099753d2d2eSraf 		snprintf(a_print, BUFSIZ, "%s",
2100753d2d2eSraf 		    de_const(declspec_ToString(buf, funargs->d_ds)));
2101753d2d2eSraf 
2102753d2d2eSraf 		tp = funargs->d_type;
2103753d2d2eSraf 
2104753d2d2eSraf 		while (tp) {
2105753d2d2eSraf 			if (tp->t_dt == DD_PTR || tp->t_dt == DD_ARY) {
2106753d2d2eSraf 				strcat(a_type, "*");
2107753d2d2eSraf 				strcat(a_print, "_P");
2108753d2d2eSraf 			}
2109753d2d2eSraf 			tp = tp->t_next;
2110753d2d2eSraf 		}
2111753d2d2eSraf 
2112753d2d2eSraf 		if (funargs->d_name) {
2113753d2d2eSraf 			snprintf(a_name, BUFSIZ, "%s",
2114753d2d2eSraf 			    funargs->d_name ? funargs->d_name : "<nil>");
2115753d2d2eSraf 			fprintf(stderr, "arg name = %s\n", a_name);
2116753d2d2eSraf 			fprintf(stderr, "arg type = %s\n", a_type);
2117753d2d2eSraf 			fprintf(stderr, "print function = %s\n", a_print);
2118753d2d2eSraf 		} else {
2119753d2d2eSraf 			strcpy(a_name, "");
2120753d2d2eSraf 			strcpy(a_print, "");
2121753d2d2eSraf 			fprintf(stderr, "arg type = %s\n", a_type);
2122753d2d2eSraf 		}
2123753d2d2eSraf 
2124753d2d2eSraf 		funargs = funargs->d_next;
2125753d2d2eSraf 	}
2126753d2d2eSraf }
2127753d2d2eSraf #endif	/* TRACE */
2128753d2d2eSraf #endif	/* DEBUG */
2129753d2d2eSraf 
2130753d2d2eSraf static char *
de_const(char * str)2131753d2d2eSraf de_const(char *str)
2132753d2d2eSraf {
2133753d2d2eSraf 	return (str);
2134753d2d2eSraf }
2135753d2d2eSraf 
2136753d2d2eSraf 
2137753d2d2eSraf void
decl_GetTraceInfo(decl_t * dp,char * f_type,char * f_print,decl_t ** funargs)2138753d2d2eSraf decl_GetTraceInfo(decl_t *dp, char *f_type, char *f_print, decl_t **funargs)
2139753d2d2eSraf {
2140753d2d2eSraf 	char	buf[BUFSIZ];
2141753d2d2eSraf 	type_t	*tp;
2142753d2d2eSraf 
2143753d2d2eSraf 	if (dp == NULL)
2144753d2d2eSraf 		return;
2145753d2d2eSraf 
2146753d2d2eSraf 	snprintf(f_type, BUFSIZ, "%s ",
2147753d2d2eSraf 	    declspec_ToString(buf, dp->d_ds));
2148753d2d2eSraf 	snprintf(f_print, BUFSIZ, "%s",
2149753d2d2eSraf 	    de_const(declspec_ToString(buf, dp->d_ds)));
2150753d2d2eSraf 	tp = dp->d_type;
2151753d2d2eSraf 	while (tp) {
2152753d2d2eSraf 		if (tp->t_dt == DD_PTR) {
2153753d2d2eSraf 			strcat(f_type, "*");
2154753d2d2eSraf 			strcat(f_print, "*");
2155753d2d2eSraf 		}
2156753d2d2eSraf 		tp = tp->t_next;
2157753d2d2eSraf 	}
2158753d2d2eSraf 
2159753d2d2eSraf 	strcat(f_type, "%s");
2160753d2d2eSraf 
2161753d2d2eSraf 	tp = decl_GetType(dp);
2162753d2d2eSraf 	if (type_IsPtrFun(tp)) {
2163753d2d2eSraf 		while (tp->t_dt != DD_FUN)
2164753d2d2eSraf 			tp = tp->t_next;
2165753d2d2eSraf 		*funargs = tp->t_args;
2166753d2d2eSraf 	} else {
2167753d2d2eSraf 		*funargs = dp->d_type->t_args;
2168753d2d2eSraf 	}
2169753d2d2eSraf }
2170753d2d2eSraf 
2171753d2d2eSraf char *
decl_ToFormal(decl_t * dp)2172753d2d2eSraf decl_ToFormal(decl_t *dp)
2173753d2d2eSraf {
2174753d2d2eSraf 	char tmp[BUFSIZ];
2175753d2d2eSraf 	static char bufp[BUFSIZ];
2176753d2d2eSraf 	char *bend;
2177753d2d2eSraf 	type_t	*tp = dp->d_type;
2178753d2d2eSraf 
2179753d2d2eSraf 	tmp[0] = 0;
2180753d2d2eSraf 	bufp[0] = 0;
2181753d2d2eSraf 	bend = bufp;
2182753d2d2eSraf 
2183753d2d2eSraf 	while (tp) {
2184753d2d2eSraf 		switch (tp->t_dt) {
2185753d2d2eSraf 		case DD_ARY:
2186753d2d2eSraf 			sprintf(bufp, "%s[%s]", tmp,
2187753d2d2eSraf 			    (tp->t_sizestr)? tp->t_sizestr : "");
2188753d2d2eSraf 			break;
2189753d2d2eSraf 
2190753d2d2eSraf 		case DD_FUN:
2191753d2d2eSraf 			if (tp->t_args != NULL) {
2192753d2d2eSraf 				char buf2[BUFSIZ];
2193753d2d2eSraf 				decl_t  *argp = tp->t_args;
2194753d2d2eSraf 
2195753d2d2eSraf 				bend = char_getend(bufp);
2196753d2d2eSraf 
2197753d2d2eSraf 				for (argp = tp->t_args; argp; /* noinc */) {
2198753d2d2eSraf 					decl_ToString(buf2, DTS_DECL, argp,
2199753d2d2eSraf 					    NULL);
2200753d2d2eSraf 					sprintf(bend, " %s", buf2);
2201753d2d2eSraf 
2202753d2d2eSraf 					bend    = char_getend(bend);
2203753d2d2eSraf 
2204753d2d2eSraf 					if (argp = argp->d_next) {
2205753d2d2eSraf 						sprintf(bend, ",");
2206753d2d2eSraf 						bend    = char_getend(bend);
2207753d2d2eSraf 					}
2208753d2d2eSraf 				}
2209753d2d2eSraf 				if (tp->t_ellipsis) {
2210753d2d2eSraf 					sprintf(bend, ", ...");
2211753d2d2eSraf 					bend    = char_getend(bend);
2212753d2d2eSraf 				}
2213753d2d2eSraf 
2214753d2d2eSraf 				sprintf(bend, "");
2215753d2d2eSraf 			}
2216753d2d2eSraf 			break;
2217753d2d2eSraf 		}
2218753d2d2eSraf 
2219753d2d2eSraf 		tp  = tp->t_next;
2220753d2d2eSraf 
2221753d2d2eSraf 		strcpy(tmp, bufp);
2222753d2d2eSraf 	}
2223753d2d2eSraf 
2224753d2d2eSraf 	sprintf(bufp, "%s", tmp);
2225753d2d2eSraf 
2226753d2d2eSraf 	return (bufp);
2227753d2d2eSraf }
2228