17c478bd9Sstevel@tonic-gate %{
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate  * CDDL HEADER START
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
67c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
77c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
87c478bd9Sstevel@tonic-gate  * with the License.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
117c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
127c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
137c478bd9Sstevel@tonic-gate  * and limitations under the License.
147c478bd9Sstevel@tonic-gate  *
157c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
167c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
177c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
187c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
197c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
207c478bd9Sstevel@tonic-gate  *
217c478bd9Sstevel@tonic-gate  * CDDL HEADER END
22f07a2a2eScraigm  */
23f07a2a2eScraigm 
24f07a2a2eScraigm /*
257c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
267c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
277c478bd9Sstevel@tonic-gate  */
28f07a2a2eScraigm 
297c478bd9Sstevel@tonic-gate #include "parseproto.h"
307c478bd9Sstevel@tonic-gate #include <assert.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate static decl_spec_t	*declspec_Construct(void);
337c478bd9Sstevel@tonic-gate static void		 declspec_Destroy(decl_spec_t *);
347c478bd9Sstevel@tonic-gate static decl_spec_t	*declspec_Init(stt_t, char *);
357c478bd9Sstevel@tonic-gate static char		*declspec_VerifySTT(stt_t, stt_t);
367c478bd9Sstevel@tonic-gate static decl_spec_t	*declspec_AddSTT(decl_spec_t *, stt_t, const char **);
377c478bd9Sstevel@tonic-gate static decl_spec_t	*declspec_AddDS(decl_spec_t *,
387c478bd9Sstevel@tonic-gate 			    decl_spec_t *, const char **);
397c478bd9Sstevel@tonic-gate static stt_t		 declspec_GetSTT(decl_spec_t *);
407c478bd9Sstevel@tonic-gate static char		*declspec_GetTag(decl_spec_t *);
417c478bd9Sstevel@tonic-gate static type_t		*type_Construct(void);
427c478bd9Sstevel@tonic-gate static void		 type_Destroy(type_t *);
437c478bd9Sstevel@tonic-gate static type_t		*type_SetPtr(type_t *, stt_t);
447c478bd9Sstevel@tonic-gate static type_t		*type_SetFun(type_t *, decl_t *);
457c478bd9Sstevel@tonic-gate static type_t		*type_AddTail(type_t *, type_t *);
467c478bd9Sstevel@tonic-gate static	const char	*type_Verify(type_t *);
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate static	decl_t		*decl_Construct(void);
497c478bd9Sstevel@tonic-gate static	decl_t		*decl_AddArg(decl_t *, decl_t *);
507c478bd9Sstevel@tonic-gate static	int		 decl_IsVoid(decl_t *);
517c478bd9Sstevel@tonic-gate static	int		 decl_IsVoidArray(decl_t *);
527c478bd9Sstevel@tonic-gate static	const char	*decl_VerifyArgs(decl_t *);
537c478bd9Sstevel@tonic-gate static	decl_t		*decl_AddDS(decl_t *, decl_spec_t *, const char **);
547c478bd9Sstevel@tonic-gate static	decl_t		*decl_AddTypeTail(decl_t *, type_t *);
557c478bd9Sstevel@tonic-gate static	decl_t		*decl_addptr(decl_t *, type_t *);
567c478bd9Sstevel@tonic-gate static	decl_t		*decl_addary(decl_t *, char *);
577c478bd9Sstevel@tonic-gate static	decl_t		*decl_addfun(decl_t *, decl_t *);
587c478bd9Sstevel@tonic-gate static	decl_t		*decl_addellipsis(decl_t *);
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #if defined(DEBUG)
617c478bd9Sstevel@tonic-gate static	void		type_PrintType(type_t *, int);
627c478bd9Sstevel@tonic-gate static	void		decl_PrintDecl(decl_t *, int);
637c478bd9Sstevel@tonic-gate static	void		decl_PrintTraceInfo(decl_t *);
647c478bd9Sstevel@tonic-gate static	char		*de_const(char *);
657c478bd9Sstevel@tonic-gate #endif
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate static	int	yylex(void);
707c478bd9Sstevel@tonic-gate static	void	yyerror(const char *);
717c478bd9Sstevel@tonic-gate static	int	yyparse(void);
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #if defined(MEM_DEBUG)
747c478bd9Sstevel@tonic-gate static	int	declspec_Construct_calls;
757c478bd9Sstevel@tonic-gate static	int	type_Construct_calls;
767c478bd9Sstevel@tonic-gate static	int	decl_Construct_calls;
777c478bd9Sstevel@tonic-gate #endif
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #if defined(DEBUG)
807c478bd9Sstevel@tonic-gate static	char	*de_const(char *);
817c478bd9Sstevel@tonic-gate #endif
827c478bd9Sstevel@tonic-gate %}
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate %union {
857c478bd9Sstevel@tonic-gate 	char		*s_val;
867c478bd9Sstevel@tonic-gate 	int		 i_val;
877c478bd9Sstevel@tonic-gate 	stt_t		 stt_val;
887c478bd9Sstevel@tonic-gate 	decl_spec_t	*ds_val;
897c478bd9Sstevel@tonic-gate 	type_t		*t_val;
907c478bd9Sstevel@tonic-gate 	decl_t		*d_val;
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate %token	<i_val>	ELLIPSIS
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate %token	<s_val>	INTEGER
967c478bd9Sstevel@tonic-gate %token	<s_val>	IDENTIFIER
977c478bd9Sstevel@tonic-gate %token	<s_val>	TYPEDEF_NAME
987c478bd9Sstevel@tonic-gate %type	<s_val>	constant_expression
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate %token	<stt_val>	REGISTER
1017c478bd9Sstevel@tonic-gate %token	<stt_val>	TYPEDEF	EXTERN	AUTO	STATIC
1027c478bd9Sstevel@tonic-gate %token	<stt_val>	VOID	CHAR	SHORT	INT	LONG
1037c478bd9Sstevel@tonic-gate %token	<stt_val>	FLOAT	DOUBLE	SIGNED	UNSIGNED
1047c478bd9Sstevel@tonic-gate %token	<stt_val>	CONST	VOLATILE	RESTRICT	RESTRICT_KYWD
1057c478bd9Sstevel@tonic-gate %type	<stt_val>	struct_or_union
1067c478bd9Sstevel@tonic-gate %type	<ds_val>	storage_class_specifier
1077c478bd9Sstevel@tonic-gate %type	<ds_val>	type_qualifier
1087c478bd9Sstevel@tonic-gate %type	<ds_val>	type_qualifier_list
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate %token	<ds_val>	STRUCT		UNION
1117c478bd9Sstevel@tonic-gate %token	<ds_val>	ENUM
1127c478bd9Sstevel@tonic-gate %type	<ds_val>	declaration_specifiers
1137c478bd9Sstevel@tonic-gate %type	<ds_val>	type_specifier
1147c478bd9Sstevel@tonic-gate %type	<ds_val>	struct_or_union_specifier enum_specifier
1157c478bd9Sstevel@tonic-gate %type	<ds_val>	typedef_name
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate %type	<t_val>		pointer
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate %type	<d_val>		declaration
1207c478bd9Sstevel@tonic-gate %type	<d_val>		init_declarator_list init_declarator
1217c478bd9Sstevel@tonic-gate %type	<d_val>		declarator
1227c478bd9Sstevel@tonic-gate %type	<d_val>		direct_declarator
1237c478bd9Sstevel@tonic-gate %type	<d_val>		parameter_type_list parameter_list
1247c478bd9Sstevel@tonic-gate %type	<d_val>		parameter_declaration
1257c478bd9Sstevel@tonic-gate %type	<d_val>		abstract_declarator
1267c478bd9Sstevel@tonic-gate %type	<d_val>		direct_abstract_declarator
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate %start	declaration
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate %%
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate /*
1337c478bd9Sstevel@tonic-gate  * The grammar is derived from ANSI/ISO 9899-1990.
1347c478bd9Sstevel@tonic-gate  */
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate declaration
1377c478bd9Sstevel@tonic-gate 	: declaration_specifiers init_declarator_list ';'
1387c478bd9Sstevel@tonic-gate 		{
1397c478bd9Sstevel@tonic-gate 			decl_t	*dp;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 			protop = $$ = $2;
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 			/* only one declaration allowed */
1447c478bd9Sstevel@tonic-gate 			assert(protop->d_next == NULL);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 			for (dp = $2; dp && (errstr == NULL);
1477c478bd9Sstevel@tonic-gate 			    dp = dp->d_next) {
1487c478bd9Sstevel@tonic-gate 				const char	*sp;
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 				decl_AddDS(dp, $1, &errstr);
1517c478bd9Sstevel@tonic-gate 				if (sp = decl_Verify(dp))
1527c478bd9Sstevel@tonic-gate 					errstr = sp;
1537c478bd9Sstevel@tonic-gate 			}
1547c478bd9Sstevel@tonic-gate 			declspec_Destroy($1);
1557c478bd9Sstevel@tonic-gate 		}
1567c478bd9Sstevel@tonic-gate 	| error ';'
1577c478bd9Sstevel@tonic-gate 		{
1587c478bd9Sstevel@tonic-gate 			protop = $$ = NULL;
1597c478bd9Sstevel@tonic-gate 			errstr = "function prototype syntax error";
1607c478bd9Sstevel@tonic-gate 		}
1617c478bd9Sstevel@tonic-gate /*
1627c478bd9Sstevel@tonic-gate  * XXX - Does not support a "stand-alone" declaration specifier. It is
1637c478bd9Sstevel@tonic-gate  * essentially a type declaration, for example:
1647c478bd9Sstevel@tonic-gate  *
1657c478bd9Sstevel@tonic-gate  *	typedef enum { FALSE = 0, TRUE = 1 } boolean_t;
1667c478bd9Sstevel@tonic-gate  * or
1677c478bd9Sstevel@tonic-gate  *	struct _name { char *first; char *last };
1687c478bd9Sstevel@tonic-gate  */
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate /* XXX	| declaration_specifiers */
1717c478bd9Sstevel@tonic-gate 	;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate declaration_specifiers
1747c478bd9Sstevel@tonic-gate 	: storage_class_specifier declaration_specifiers
1757c478bd9Sstevel@tonic-gate 		{
1767c478bd9Sstevel@tonic-gate 			char const *ep;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 			$$ = declspec_AddDS($2, $1, &ep);
1797c478bd9Sstevel@tonic-gate 			declspec_Destroy($1);
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 			if (errstr == NULL)
1827c478bd9Sstevel@tonic-gate 				errstr = ep;
1837c478bd9Sstevel@tonic-gate 		}
1847c478bd9Sstevel@tonic-gate 	| storage_class_specifier
1857c478bd9Sstevel@tonic-gate 	| type_specifier declaration_specifiers
1867c478bd9Sstevel@tonic-gate 		{
1877c478bd9Sstevel@tonic-gate 			const char	*ep;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 			$$ = declspec_AddDS($2, $1, &ep);
1907c478bd9Sstevel@tonic-gate 			declspec_Destroy($1);
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 			if (errstr == NULL)
1937c478bd9Sstevel@tonic-gate 				errstr = ep;
1947c478bd9Sstevel@tonic-gate 		}
1957c478bd9Sstevel@tonic-gate 	| type_specifier
1967c478bd9Sstevel@tonic-gate 	| type_qualifier declaration_specifiers
1977c478bd9Sstevel@tonic-gate 		{
1987c478bd9Sstevel@tonic-gate 			const char	*ep;
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 			$$ = declspec_AddDS($2, $1, &ep);
2017c478bd9Sstevel@tonic-gate 			declspec_Destroy($1);
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 			if (errstr == NULL)
2047c478bd9Sstevel@tonic-gate 				errstr = ep;
2057c478bd9Sstevel@tonic-gate 		}
2067c478bd9Sstevel@tonic-gate 	| type_qualifier
2077c478bd9Sstevel@tonic-gate 	;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate storage_class_specifier
2107c478bd9Sstevel@tonic-gate 	: REGISTER
2117c478bd9Sstevel@tonic-gate 		{
2127c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(SCS_REGISTER, NULL);
2137c478bd9Sstevel@tonic-gate 		}
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate  * XXX - Does not support any storage class specifier other than
2167c478bd9Sstevel@tonic-gate  * register, and then only for function arguments.
2177c478bd9Sstevel@tonic-gate  *
2187c478bd9Sstevel@tonic-gate 	| TYPEDEF
2197c478bd9Sstevel@tonic-gate 		{
2207c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(SCS_TYPEDEF, NULL);
2217c478bd9Sstevel@tonic-gate 		}
2227c478bd9Sstevel@tonic-gate 	| EXTERN
2237c478bd9Sstevel@tonic-gate 		{
2247c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(SCS_EXTERN, NULL);
2257c478bd9Sstevel@tonic-gate 		}
2267c478bd9Sstevel@tonic-gate 	| STATIC
2277c478bd9Sstevel@tonic-gate 		{
2287c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(SCS_STATIC, NULL);
2297c478bd9Sstevel@tonic-gate 		}
2307c478bd9Sstevel@tonic-gate 	| AUTO
2317c478bd9Sstevel@tonic-gate 		{
2327c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(SCS_AUTO, NULL);
2337c478bd9Sstevel@tonic-gate 		}
2347c478bd9Sstevel@tonic-gate  */
2357c478bd9Sstevel@tonic-gate 	;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate type_specifier
2387c478bd9Sstevel@tonic-gate 	: VOID
2397c478bd9Sstevel@tonic-gate 		{
2407c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_VOID, NULL);
2417c478bd9Sstevel@tonic-gate 			atIDENT = 1;
2427c478bd9Sstevel@tonic-gate 		}
2437c478bd9Sstevel@tonic-gate 	| CHAR
2447c478bd9Sstevel@tonic-gate 		{
2457c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_CHAR, NULL);
2467c478bd9Sstevel@tonic-gate 			atIDENT = 1;
2477c478bd9Sstevel@tonic-gate 		}
2487c478bd9Sstevel@tonic-gate 	| SHORT
2497c478bd9Sstevel@tonic-gate 		{
2507c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_SHORT, NULL);
2517c478bd9Sstevel@tonic-gate 			atIDENT = 1;
2527c478bd9Sstevel@tonic-gate 		}
2537c478bd9Sstevel@tonic-gate 	| INT
2547c478bd9Sstevel@tonic-gate 		{
2557c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_INT, NULL);
2567c478bd9Sstevel@tonic-gate 			atIDENT = 1;
2577c478bd9Sstevel@tonic-gate 		}
2587c478bd9Sstevel@tonic-gate 	| LONG
2597c478bd9Sstevel@tonic-gate 		{
2607c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_LONG, NULL);
2617c478bd9Sstevel@tonic-gate 			atIDENT = 1;
2627c478bd9Sstevel@tonic-gate 		}
2637c478bd9Sstevel@tonic-gate 	| FLOAT
2647c478bd9Sstevel@tonic-gate 		{
2657c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_FLOAT, NULL);
2667c478bd9Sstevel@tonic-gate 			atIDENT = 1;
2677c478bd9Sstevel@tonic-gate 		}
2687c478bd9Sstevel@tonic-gate 	| DOUBLE
2697c478bd9Sstevel@tonic-gate 		{
2707c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_DOUBLE, NULL);
2717c478bd9Sstevel@tonic-gate 			atIDENT = 1;
2727c478bd9Sstevel@tonic-gate 		}
2737c478bd9Sstevel@tonic-gate 	| SIGNED
2747c478bd9Sstevel@tonic-gate 		{
2757c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_SIGNED, NULL);
2767c478bd9Sstevel@tonic-gate 			atIDENT = 1;
2777c478bd9Sstevel@tonic-gate 		}
2787c478bd9Sstevel@tonic-gate 	| UNSIGNED
2797c478bd9Sstevel@tonic-gate 		{
2807c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_UNSIGNED, NULL);
2817c478bd9Sstevel@tonic-gate 			atIDENT = 1;
2827c478bd9Sstevel@tonic-gate 		}
2837c478bd9Sstevel@tonic-gate 	| struct_or_union_specifier
2847c478bd9Sstevel@tonic-gate 	| enum_specifier
2857c478bd9Sstevel@tonic-gate 	| typedef_name
2867c478bd9Sstevel@tonic-gate 	;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate typedef_name
2897c478bd9Sstevel@tonic-gate 	: TYPEDEF_NAME
2907c478bd9Sstevel@tonic-gate 		{
2917c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_TYPEDEF, $1);
2927c478bd9Sstevel@tonic-gate 			atIDENT = 1;
2937c478bd9Sstevel@tonic-gate 			free($1);
2947c478bd9Sstevel@tonic-gate 		}
2957c478bd9Sstevel@tonic-gate 	;
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate /*
2987c478bd9Sstevel@tonic-gate  * The "restrict" keyword is new in the C99 standard.
2997c478bd9Sstevel@tonic-gate  * It is type qualifier like const and volatile.
3007c478bd9Sstevel@tonic-gate  * We are using "_RESTRICT_KYWD" in headers and source code so
3017c478bd9Sstevel@tonic-gate  * it is easily turned on and off by various macros at compile time.
3027c478bd9Sstevel@tonic-gate  * In order for the "restrict" keyword to be recognized you must
3037c478bd9Sstevel@tonic-gate  * be using a C99 compliant compiler in its native mode.
3047c478bd9Sstevel@tonic-gate  */
3057c478bd9Sstevel@tonic-gate type_qualifier
3067c478bd9Sstevel@tonic-gate 	: CONST
3077c478bd9Sstevel@tonic-gate 		{
3087c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TQ_CONST, NULL);
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 	| VOLATILE
3117c478bd9Sstevel@tonic-gate 		{
3127c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TQ_VOLATILE, NULL);
3137c478bd9Sstevel@tonic-gate 		}
3147c478bd9Sstevel@tonic-gate 	| RESTRICT
3157c478bd9Sstevel@tonic-gate 		{
3167c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TQ_RESTRICT, NULL);
3177c478bd9Sstevel@tonic-gate 		}
3187c478bd9Sstevel@tonic-gate 	| RESTRICT_KYWD
3197c478bd9Sstevel@tonic-gate 		{
3207c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TQ_RESTRICT_KYWD, NULL);
3217c478bd9Sstevel@tonic-gate 		}
3227c478bd9Sstevel@tonic-gate 	;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate struct_or_union_specifier
3257c478bd9Sstevel@tonic-gate 	: struct_or_union { atIDENT = 1; } IDENTIFIER
3267c478bd9Sstevel@tonic-gate 		{
3277c478bd9Sstevel@tonic-gate 			$$ = declspec_Init($1, $3);
3287c478bd9Sstevel@tonic-gate 			free($3);
3297c478bd9Sstevel@tonic-gate 		}
3307c478bd9Sstevel@tonic-gate /*
3317c478bd9Sstevel@tonic-gate  * XXX - struct or union definitions are not supported. It is generally
3327c478bd9Sstevel@tonic-gate  * not done within the context of a function declaration (prototype) or
3337c478bd9Sstevel@tonic-gate  * variable definition.
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	| struct_or_union IDENTIFIER '{' struct_declaration_list '}'
3367c478bd9Sstevel@tonic-gate 	| struct_or_union '{' struct_declaration_list '}'
3377c478bd9Sstevel@tonic-gate  */
3387c478bd9Sstevel@tonic-gate 	;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate struct_or_union
3417c478bd9Sstevel@tonic-gate 	: STRUCT
3427c478bd9Sstevel@tonic-gate 		{
3437c478bd9Sstevel@tonic-gate 			$$ = TS_STRUCT;
3447c478bd9Sstevel@tonic-gate 		}
3457c478bd9Sstevel@tonic-gate 	| UNION
3467c478bd9Sstevel@tonic-gate 		{
3477c478bd9Sstevel@tonic-gate 			$$ = TS_UNION;
3487c478bd9Sstevel@tonic-gate 		}
3497c478bd9Sstevel@tonic-gate 	;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate init_declarator_list
3527c478bd9Sstevel@tonic-gate 	: init_declarator
3537c478bd9Sstevel@tonic-gate 		{
3547c478bd9Sstevel@tonic-gate 			$$ = $1;
3557c478bd9Sstevel@tonic-gate 			atIDENT = 1;
3567c478bd9Sstevel@tonic-gate 		}
3577c478bd9Sstevel@tonic-gate /*
3587c478bd9Sstevel@tonic-gate  * XXX - Does not support a comma separated list of declarations or
3597c478bd9Sstevel@tonic-gate  * definitions. Function prototypes or variable definitions must be
3607c478bd9Sstevel@tonic-gate  * given as one per C statement.
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	| init_declarator_list ',' init_declarator
3637c478bd9Sstevel@tonic-gate 		{
3647c478bd9Sstevel@tonic-gate 			$$ = decl_AddArg($1, $3);
3657c478bd9Sstevel@tonic-gate 			atIDENT = 1;
3667c478bd9Sstevel@tonic-gate 		}
3677c478bd9Sstevel@tonic-gate */
3687c478bd9Sstevel@tonic-gate 	;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate init_declarator
3717c478bd9Sstevel@tonic-gate 	: declarator
3727c478bd9Sstevel@tonic-gate /*
3737c478bd9Sstevel@tonic-gate  * XXX - Initialization is not supported.
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	| declarator '=' initializer
3767c478bd9Sstevel@tonic-gate */
3777c478bd9Sstevel@tonic-gate 	;
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate enum_specifier
3817c478bd9Sstevel@tonic-gate 	: ENUM { atIDENT = 1; } IDENTIFIER
3827c478bd9Sstevel@tonic-gate 		{
3837c478bd9Sstevel@tonic-gate 			$$ = declspec_Init(TS_ENUM, $3);
3847c478bd9Sstevel@tonic-gate 			free($3);
3857c478bd9Sstevel@tonic-gate 		}
3867c478bd9Sstevel@tonic-gate /*
3877c478bd9Sstevel@tonic-gate  * XXX - enumerator definition is not supported for the same reasons
3887c478bd9Sstevel@tonic-gate  * struct|union definition is not supported.
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	| ENUM IDENTIFIER '{' enumerator_list '}'
3917c478bd9Sstevel@tonic-gate 	| ENUM '{' enumerator_list '}'
3927c478bd9Sstevel@tonic-gate */
3937c478bd9Sstevel@tonic-gate 	;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate declarator
3977c478bd9Sstevel@tonic-gate 	: pointer direct_declarator
3987c478bd9Sstevel@tonic-gate 		{
3997c478bd9Sstevel@tonic-gate 			$$ = decl_addptr($2, $1);
4007c478bd9Sstevel@tonic-gate 		}
4017c478bd9Sstevel@tonic-gate 	| direct_declarator
4027c478bd9Sstevel@tonic-gate 	;
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate direct_declarator
4057c478bd9Sstevel@tonic-gate 	: IDENTIFIER
4067c478bd9Sstevel@tonic-gate 		{
4077c478bd9Sstevel@tonic-gate 			$$ = decl_SetName(decl_Construct(), $1);
4087c478bd9Sstevel@tonic-gate 			atIDENT = 0;
4097c478bd9Sstevel@tonic-gate 			free($1);
4107c478bd9Sstevel@tonic-gate 		}
4117c478bd9Sstevel@tonic-gate 	| '(' declarator ')'
4127c478bd9Sstevel@tonic-gate 		{
4137c478bd9Sstevel@tonic-gate 			$$ = $2;
4147c478bd9Sstevel@tonic-gate 		}
4157c478bd9Sstevel@tonic-gate 	| direct_declarator '[' constant_expression ']'
4167c478bd9Sstevel@tonic-gate 		{
4177c478bd9Sstevel@tonic-gate 			$$ = decl_addary($1, $3);
4187c478bd9Sstevel@tonic-gate 			free($3);
4197c478bd9Sstevel@tonic-gate 		}
4207c478bd9Sstevel@tonic-gate 	| direct_declarator '[' ']'
4217c478bd9Sstevel@tonic-gate 		{
4227c478bd9Sstevel@tonic-gate 			$$ = decl_addary($1, NULL);
4237c478bd9Sstevel@tonic-gate 		}
4247c478bd9Sstevel@tonic-gate 	| direct_declarator '(' parameter_type_list ')'
4257c478bd9Sstevel@tonic-gate 		{
4267c478bd9Sstevel@tonic-gate 			$$ = decl_addfun($1, $3);
4277c478bd9Sstevel@tonic-gate 		}
4287c478bd9Sstevel@tonic-gate 	| direct_declarator '(' ')'
4297c478bd9Sstevel@tonic-gate 		{
4307c478bd9Sstevel@tonic-gate 			$$ = decl_addfun($1, NULL);
4317c478bd9Sstevel@tonic-gate 		}
4327c478bd9Sstevel@tonic-gate 	;
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate pointer
4357c478bd9Sstevel@tonic-gate 	: '*' type_qualifier_list
4367c478bd9Sstevel@tonic-gate 		{
4377c478bd9Sstevel@tonic-gate 			$$ = type_SetPtr(type_Construct(), ($2)->ds_stt);
4387c478bd9Sstevel@tonic-gate 			declspec_Destroy($2);
4397c478bd9Sstevel@tonic-gate 		}
4407c478bd9Sstevel@tonic-gate 	| '*'
4417c478bd9Sstevel@tonic-gate 		{
4427c478bd9Sstevel@tonic-gate 			$$ = type_SetPtr(type_Construct(), TQ_NONE);
4437c478bd9Sstevel@tonic-gate 		}
4447c478bd9Sstevel@tonic-gate 	| '*' type_qualifier_list pointer
4457c478bd9Sstevel@tonic-gate 		{
4467c478bd9Sstevel@tonic-gate 			type_t	*tp = type_Construct();
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 			type_SetPtr(tp, ($2)->ds_stt);
4497c478bd9Sstevel@tonic-gate 			declspec_Destroy($2);
4507c478bd9Sstevel@tonic-gate 			$$ = type_AddTail($3, tp);
4517c478bd9Sstevel@tonic-gate 		}
4527c478bd9Sstevel@tonic-gate 	| '*' pointer
4537c478bd9Sstevel@tonic-gate 		{
4547c478bd9Sstevel@tonic-gate 			type_t	*tp = type_Construct();
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 			type_SetPtr(tp, TQ_NONE);
4577c478bd9Sstevel@tonic-gate 			$$ = type_AddTail($2, tp);
4587c478bd9Sstevel@tonic-gate 		}
4597c478bd9Sstevel@tonic-gate 	;
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate type_qualifier_list
4627c478bd9Sstevel@tonic-gate 	: type_qualifier
4637c478bd9Sstevel@tonic-gate 	| type_qualifier_list type_qualifier
4647c478bd9Sstevel@tonic-gate 		{
4657c478bd9Sstevel@tonic-gate 			const char	*ep;
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 			/* XXX - ignore any error */
4687c478bd9Sstevel@tonic-gate 			$$ = declspec_AddDS($1, $2, &ep);
4697c478bd9Sstevel@tonic-gate 			declspec_Destroy($2);
4707c478bd9Sstevel@tonic-gate 		}
4717c478bd9Sstevel@tonic-gate 	;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate parameter_type_list
4747c478bd9Sstevel@tonic-gate 	: parameter_list
4757c478bd9Sstevel@tonic-gate 	| parameter_list ',' ELLIPSIS
4767c478bd9Sstevel@tonic-gate 		{
4777c478bd9Sstevel@tonic-gate 			$$ = decl_addellipsis($1);
4787c478bd9Sstevel@tonic-gate 		}
4797c478bd9Sstevel@tonic-gate 	;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate parameter_list
4827c478bd9Sstevel@tonic-gate 	: parameter_declaration
4837c478bd9Sstevel@tonic-gate 		{
4847c478bd9Sstevel@tonic-gate 			const char *sp = type_Verify($1->d_type);
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 			if (sp)
4877c478bd9Sstevel@tonic-gate 				errstr = sp;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 			$$ = $1;
4907c478bd9Sstevel@tonic-gate 			atIDENT = 0;
4917c478bd9Sstevel@tonic-gate 		}
4927c478bd9Sstevel@tonic-gate 	| parameter_list ',' parameter_declaration
4937c478bd9Sstevel@tonic-gate 		{
4947c478bd9Sstevel@tonic-gate 			const char *sp = type_Verify($3->d_type);
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 			if (sp)
4977c478bd9Sstevel@tonic-gate 				errstr = sp;
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 			$$ = decl_AddArg($1, $3);
5007c478bd9Sstevel@tonic-gate 			atIDENT = 0;
5017c478bd9Sstevel@tonic-gate 		}
5027c478bd9Sstevel@tonic-gate 	;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate parameter_declaration
5057c478bd9Sstevel@tonic-gate 	: declaration_specifiers declarator
5067c478bd9Sstevel@tonic-gate 		{
5077c478bd9Sstevel@tonic-gate 			const char *ep;
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 			$$ = decl_AddDS($2, $1, &ep);
5107c478bd9Sstevel@tonic-gate 			declspec_Destroy($1);
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 			if (errstr == NULL)
5137c478bd9Sstevel@tonic-gate 				errstr = ep;
5147c478bd9Sstevel@tonic-gate 		}
5157c478bd9Sstevel@tonic-gate 	| declaration_specifiers abstract_declarator
5167c478bd9Sstevel@tonic-gate 		{
5177c478bd9Sstevel@tonic-gate 			const char *ep;
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 			$$ = decl_AddDS($2, $1, &ep);
5207c478bd9Sstevel@tonic-gate 			declspec_Destroy($1);
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 			if (errstr == NULL)
5237c478bd9Sstevel@tonic-gate 				errstr = ep;
5247c478bd9Sstevel@tonic-gate 		}
5257c478bd9Sstevel@tonic-gate 	| declaration_specifiers
5267c478bd9Sstevel@tonic-gate 		{
5277c478bd9Sstevel@tonic-gate 			const char *ep;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 			$$ = decl_AddDS(decl_Construct(), $1, &ep);
5307c478bd9Sstevel@tonic-gate 			declspec_Destroy($1);
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 			if (errstr == NULL)
5337c478bd9Sstevel@tonic-gate 				errstr = ep;
5347c478bd9Sstevel@tonic-gate 		}
5357c478bd9Sstevel@tonic-gate 	;
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate abstract_declarator
5387c478bd9Sstevel@tonic-gate 	: pointer
5397c478bd9Sstevel@tonic-gate 		{
5407c478bd9Sstevel@tonic-gate 			$$ = decl_addptr(decl_Construct(), $1);
5417c478bd9Sstevel@tonic-gate 		}
5427c478bd9Sstevel@tonic-gate 	| pointer direct_abstract_declarator
5437c478bd9Sstevel@tonic-gate 		{
5447c478bd9Sstevel@tonic-gate 			$$ = decl_addptr($2, $1);
5457c478bd9Sstevel@tonic-gate 		}
5467c478bd9Sstevel@tonic-gate 	| direct_abstract_declarator
5477c478bd9Sstevel@tonic-gate 	;
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate direct_abstract_declarator
5507c478bd9Sstevel@tonic-gate 	: '(' abstract_declarator ')'
5517c478bd9Sstevel@tonic-gate 		{
5527c478bd9Sstevel@tonic-gate 			$$ = $2;
5537c478bd9Sstevel@tonic-gate 		}
5547c478bd9Sstevel@tonic-gate 	| direct_abstract_declarator '[' constant_expression ']'
5557c478bd9Sstevel@tonic-gate 		{
5567c478bd9Sstevel@tonic-gate 			$$ = decl_addary($1, $3);
5577c478bd9Sstevel@tonic-gate 			free($3);
5587c478bd9Sstevel@tonic-gate 		}
5597c478bd9Sstevel@tonic-gate 	| '[' constant_expression ']'
5607c478bd9Sstevel@tonic-gate 		{
5617c478bd9Sstevel@tonic-gate 			$$ = decl_addary(decl_Construct(), $2);
5627c478bd9Sstevel@tonic-gate 			free($2);
5637c478bd9Sstevel@tonic-gate 		}
5647c478bd9Sstevel@tonic-gate 	| direct_abstract_declarator '[' ']'
5657c478bd9Sstevel@tonic-gate 		{
5667c478bd9Sstevel@tonic-gate 			$$ = decl_addary($1, NULL);
5677c478bd9Sstevel@tonic-gate 		}
5687c478bd9Sstevel@tonic-gate 	| '[' ']'
5697c478bd9Sstevel@tonic-gate 		{
5707c478bd9Sstevel@tonic-gate 			$$ = decl_addary(decl_Construct(), NULL);
5717c478bd9Sstevel@tonic-gate 		}
5727c478bd9Sstevel@tonic-gate 	| direct_abstract_declarator '(' parameter_type_list ')'
5737c478bd9Sstevel@tonic-gate 		{
5747c478bd9Sstevel@tonic-gate 			$$ = decl_addfun($1, $3);
5757c478bd9Sstevel@tonic-gate 		}
5767c478bd9Sstevel@tonic-gate 	| '(' parameter_type_list ')'
5777c478bd9Sstevel@tonic-gate 		{
5787c478bd9Sstevel@tonic-gate 			$$ = decl_addfun(decl_Construct(), $2);
5797c478bd9Sstevel@tonic-gate 		}
5807c478bd9Sstevel@tonic-gate 	| direct_abstract_declarator '(' ')'
5817c478bd9Sstevel@tonic-gate 		{
5827c478bd9Sstevel@tonic-gate 			$$ = decl_addfun($1, NULL);
5837c478bd9Sstevel@tonic-gate 		}
5847c478bd9Sstevel@tonic-gate 	| '(' ')'
5857c478bd9Sstevel@tonic-gate 		{
5867c478bd9Sstevel@tonic-gate 			$$ = decl_addfun(decl_Construct(), NULL);
5877c478bd9Sstevel@tonic-gate 		}
5887c478bd9Sstevel@tonic-gate 	;
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate /*
5917c478bd9Sstevel@tonic-gate  * XXX - General case constant expressions are not supported. It would
5927c478bd9Sstevel@tonic-gate  * be easy to implement (for the most part), but there are no cases to
5937c478bd9Sstevel@tonic-gate  * date that require such a facility. The grammar does allow an
5947c478bd9Sstevel@tonic-gate  * identifier (or typedef name) to be used since the prototype is not
5957c478bd9Sstevel@tonic-gate  * processed by CPP. The only integer constant that is supported is
5967c478bd9Sstevel@tonic-gate  * decimal.
5977c478bd9Sstevel@tonic-gate  */
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate constant_expression
6007c478bd9Sstevel@tonic-gate 	: INTEGER
6017c478bd9Sstevel@tonic-gate 	| IDENTIFIER
6027c478bd9Sstevel@tonic-gate 	| TYPEDEF_NAME
6037c478bd9Sstevel@tonic-gate 	;
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate %%
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate /* Data Declarations */
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate typedef struct {
6107c478bd9Sstevel@tonic-gate 	char	*name;
6117c478bd9Sstevel@tonic-gate 	int	 token;
6127c478bd9Sstevel@tonic-gate 	stt_t	 stt;
6137c478bd9Sstevel@tonic-gate } keyword_t;
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate typedef struct {
6167c478bd9Sstevel@tonic-gate 	stt_t	 s_stt;
6177c478bd9Sstevel@tonic-gate 	char	*s_str;
6187c478bd9Sstevel@tonic-gate } sttpair_t;
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate /* External Declarations */
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate static	const keyword_t	*lookup_keyword(const char *);
6237c478bd9Sstevel@tonic-gate static	const char	*lookup_sttpair(stt_t);
6247c478bd9Sstevel@tonic-gate static	int		 getch(void);
6257c478bd9Sstevel@tonic-gate static	void		 ungetch(int);
6267c478bd9Sstevel@tonic-gate static	void		 skipwhitespace(void);
6277c478bd9Sstevel@tonic-gate static	int		 lookahead(int);
6287c478bd9Sstevel@tonic-gate static	void		 skipcomment(void);
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate /* External Definitions */
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate static char		*input = NULL;	/* current place in the input stream */
6337c478bd9Sstevel@tonic-gate /* at point in stream were identifier is expected */
6347c478bd9Sstevel@tonic-gate static int		 atIDENT = 0;
6357c478bd9Sstevel@tonic-gate static decl_t		*protop = NULL;	/* pointer to prototype */
6367c478bd9Sstevel@tonic-gate static const char	*errstr = NULL;	/* error message */
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate /*
6397c478bd9Sstevel@tonic-gate  * lookup_keyword - Given a string, return the keyword_t or NULL.
6407c478bd9Sstevel@tonic-gate  */
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate static const keyword_t *
lookup_keyword(const char * name)6437c478bd9Sstevel@tonic-gate lookup_keyword(const char *name) {
6447c478bd9Sstevel@tonic-gate 	static	const keyword_t	keytbl[] = {
6457c478bd9Sstevel@tonic-gate 		{	"register",	REGISTER,	SCS_REGISTER	},
6467c478bd9Sstevel@tonic-gate #if UNSUPPORTED
6477c478bd9Sstevel@tonic-gate 		{	"typedef",	TYPEDEF,	SCS_TYPEDEF	},
6487c478bd9Sstevel@tonic-gate 		{	"auto",		AUTO,		SCS_AUTO	},
6497c478bd9Sstevel@tonic-gate 		{	"static",	STATIC,		SCS_STATIC	},
6507c478bd9Sstevel@tonic-gate 		{	"extern",	EXTERN,		SCS_EXTERN	},
6517c478bd9Sstevel@tonic-gate #endif /* UNSUPPORTED */
6527c478bd9Sstevel@tonic-gate 		{	"void",		VOID,		TS_VOID		},
6537c478bd9Sstevel@tonic-gate 		{	"char",		CHAR,		TS_CHAR		},
6547c478bd9Sstevel@tonic-gate 		{	"short",	SHORT,		TS_SHORT	},
6557c478bd9Sstevel@tonic-gate 		{	"int",		INT,		TS_INT		},
6567c478bd9Sstevel@tonic-gate 		{	"long",		LONG,		TS_LONG		},
6577c478bd9Sstevel@tonic-gate 		{	"float",	FLOAT,		TS_FLOAT	},
6587c478bd9Sstevel@tonic-gate 		{	"double",	DOUBLE,		TS_DOUBLE	},
6597c478bd9Sstevel@tonic-gate 		{	"signed",	SIGNED,		TS_SIGNED	},
6607c478bd9Sstevel@tonic-gate 		{	"unsigned",	UNSIGNED,	TS_UNSIGNED	},
6617c478bd9Sstevel@tonic-gate 		{	"struct",	STRUCT,		TS_STRUCT	},
6627c478bd9Sstevel@tonic-gate 		{	"union",	UNION,		TS_UNION	},
6637c478bd9Sstevel@tonic-gate 		{	"enum",		ENUM,		TS_ENUM		},
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 		{	"const",	CONST,		TQ_CONST	},
6667c478bd9Sstevel@tonic-gate 		{	"volatile",	VOLATILE,	TQ_VOLATILE	},
6677c478bd9Sstevel@tonic-gate 		{	"restrict",	RESTRICT,	TQ_RESTRICT	},
6687c478bd9Sstevel@tonic-gate 		{	"_RESTRICT_KYWD",RESTRICT_KYWD,	TQ_RESTRICT_KYWD},
6697c478bd9Sstevel@tonic-gate 	};
6707c478bd9Sstevel@tonic-gate #define	NKEYWORD	(sizeof (keytbl)/sizeof (keyword_t))
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	int	i;
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 	for (i = 0; i < NKEYWORD; ++i) {
6757c478bd9Sstevel@tonic-gate 		char	*s = keytbl[i].name;
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 		if ((*s == *name) && (strcmp(s, name) == 0))
6787c478bd9Sstevel@tonic-gate 			return (&keytbl[i]);
6797c478bd9Sstevel@tonic-gate 	}
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	return (NULL);
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate /*
6857c478bd9Sstevel@tonic-gate  * lookup_sttpair - Given an stt_t return a string or NULL.
6867c478bd9Sstevel@tonic-gate  *
6877c478bd9Sstevel@tonic-gate  */
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate static const char *
lookup_sttpair(stt_t s)6907c478bd9Sstevel@tonic-gate lookup_sttpair(stt_t s) {
6917c478bd9Sstevel@tonic-gate 	/* valid type specifier combinations */
6927c478bd9Sstevel@tonic-gate 	static const sttpair_t	stttbl[] = {
6937c478bd9Sstevel@tonic-gate 		{ TS_VOID,				"void"		},
6947c478bd9Sstevel@tonic-gate 		{ TS_CHAR,				"char"		},
6957c478bd9Sstevel@tonic-gate 		{ TS_SIGNED | TS_CHAR,			"signed char"	},
6967c478bd9Sstevel@tonic-gate 		{ TS_UNSIGNED | TS_CHAR,		"unsigned char"	},
6977c478bd9Sstevel@tonic-gate 		{ TS_SHORT,				"short"		},
6987c478bd9Sstevel@tonic-gate 		{ TS_SIGNED | TS_SHORT,			"signed short"	},
6997c478bd9Sstevel@tonic-gate 		{ TS_SHORT | TS_INT,			"short int"	},
7007c478bd9Sstevel@tonic-gate 		{ TS_SIGNED | TS_SHORT | TS_INT,
7017c478bd9Sstevel@tonic-gate 		    "signed short int"				},
7027c478bd9Sstevel@tonic-gate 		{ TS_UNSIGNED | TS_SHORT,
7037c478bd9Sstevel@tonic-gate 		    "unsigned short"					},
7047c478bd9Sstevel@tonic-gate 		{ TS_UNSIGNED | TS_SHORT | TS_INT,
7057c478bd9Sstevel@tonic-gate 		    "unsigned short int"				},
7067c478bd9Sstevel@tonic-gate 		{ TS_INT,				"int"		},
7077c478bd9Sstevel@tonic-gate 		{ TS_SIGNED,				"signed"	},
7087c478bd9Sstevel@tonic-gate 		{ TS_SIGNED | TS_INT,			"signed int"	},
7097c478bd9Sstevel@tonic-gate 		{ TS_NO_TS,				""		},
7107c478bd9Sstevel@tonic-gate 		{ TS_UNSIGNED,				"unsigned"	},
7117c478bd9Sstevel@tonic-gate 		{ TS_UNSIGNED | TS_INT,			"unsigned int"	},
7127c478bd9Sstevel@tonic-gate 		{ TS_LONG,				"long"		},
7137c478bd9Sstevel@tonic-gate 		{ TS_SIGNED | TS_LONG,			"signed long"	},
7147c478bd9Sstevel@tonic-gate 		{ TS_LONG | TS_INT,			"long int"	},
7157c478bd9Sstevel@tonic-gate 		{ TS_SIGNED | TS_LONG | TS_INT,
7167c478bd9Sstevel@tonic-gate 		    "signed long int"					},
7177c478bd9Sstevel@tonic-gate 		{ TS_UNSIGNED | TS_LONG,		"unsigned long"	},
7187c478bd9Sstevel@tonic-gate 		{ TS_UNSIGNED | TS_LONG | TS_INT,
7197c478bd9Sstevel@tonic-gate 		    "unsigned long int"				},
7207c478bd9Sstevel@tonic-gate 		{ TS_FLOAT,				"float"		},
7217c478bd9Sstevel@tonic-gate 		{ TS_DOUBLE,				"double"	},
7227c478bd9Sstevel@tonic-gate 		{ TS_LONG | TS_DOUBLE,			"long double"	},
7237c478bd9Sstevel@tonic-gate 		{ TS_STRUCT,				"struct"	},
7247c478bd9Sstevel@tonic-gate 		{ TS_UNION,				"union"		},
7257c478bd9Sstevel@tonic-gate 		{ TS_ENUM,				"enum"		},
7267c478bd9Sstevel@tonic-gate 		{ TS_TYPEDEF,				""		},
7277c478bd9Sstevel@tonic-gate 		/* non-ANSI type: long long */
7287c478bd9Sstevel@tonic-gate 		{ TS_LONGLONG,				"long long"	},
7297c478bd9Sstevel@tonic-gate 		{ TS_LONGLONG | TS_INT,			"long long int"	},
7307c478bd9Sstevel@tonic-gate 		{ TS_SIGNED | TS_LONGLONG,
7317c478bd9Sstevel@tonic-gate 		    "signed long long"				},
7327c478bd9Sstevel@tonic-gate 		{ TS_UNSIGNED | TS_LONGLONG,
7337c478bd9Sstevel@tonic-gate 		    "unsigned long long"				},
7347c478bd9Sstevel@tonic-gate 		{ TS_SIGNED | TS_LONGLONG | TS_INT,
7357c478bd9Sstevel@tonic-gate 		    "signed long long int"				},
7367c478bd9Sstevel@tonic-gate 		{ TS_UNSIGNED | TS_LONGLONG | TS_INT,
7377c478bd9Sstevel@tonic-gate 		    "unsigned long long int"				},
7387c478bd9Sstevel@tonic-gate 	};
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate #define	NDECLSPEC	(sizeof (stttbl)/sizeof (sttpair_t))
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	int	i;
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDECLSPEC; ++i)
7457c478bd9Sstevel@tonic-gate 		if (s == stttbl[i].s_stt)
7467c478bd9Sstevel@tonic-gate 			return (stttbl[i].s_str);
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 	return (NULL);
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate /*
7527c478bd9Sstevel@tonic-gate  * yylex - return next token from the the input stream.
7537c478bd9Sstevel@tonic-gate  *
7547c478bd9Sstevel@tonic-gate  * The lexical analyzer does not recognize all possible C lexical
7557c478bd9Sstevel@tonic-gate  * elements. It only recognizes those associated with function
7567c478bd9Sstevel@tonic-gate  * declarations (read: prototypes) and data definitions.
7577c478bd9Sstevel@tonic-gate  */
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate static int
yylex(void)7607c478bd9Sstevel@tonic-gate yylex(void) {
7617c478bd9Sstevel@tonic-gate 	char	buf[BUFSIZ];		/* string version of token */
7627c478bd9Sstevel@tonic-gate 	int	c;
7637c478bd9Sstevel@tonic-gate 	int	i = 0;
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate restart:
7667c478bd9Sstevel@tonic-gate 	skipwhitespace();
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	switch (c = getch()) {
7697c478bd9Sstevel@tonic-gate 	case '/':
7707c478bd9Sstevel@tonic-gate 		if (lookahead('*')) {
7717c478bd9Sstevel@tonic-gate 			skipcomment();
7727c478bd9Sstevel@tonic-gate 			goto restart;
7737c478bd9Sstevel@tonic-gate 		}
774*6ec25805SToomas Soome 		return (c);
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 	case '.':
7777c478bd9Sstevel@tonic-gate 		if (lookahead('.')) {
7787c478bd9Sstevel@tonic-gate 			if (lookahead('.'))
7797c478bd9Sstevel@tonic-gate 				return (ELLIPSIS);
7807c478bd9Sstevel@tonic-gate 		}
781*6ec25805SToomas Soome 		return (c);
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 	case EOF:
7847c478bd9Sstevel@tonic-gate 	case '(':
7857c478bd9Sstevel@tonic-gate 	case ')':
7867c478bd9Sstevel@tonic-gate 	case ',':
7877c478bd9Sstevel@tonic-gate 	case '[':
7887c478bd9Sstevel@tonic-gate 	case ']':
7897c478bd9Sstevel@tonic-gate 	case ';':
7907c478bd9Sstevel@tonic-gate 	case '*':
7917c478bd9Sstevel@tonic-gate 		return (c);
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	default:
7947c478bd9Sstevel@tonic-gate 		if ((c == '_') || isalpha(c)) {
7957c478bd9Sstevel@tonic-gate 			const keyword_t	*kp;
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 			do {
7987c478bd9Sstevel@tonic-gate 				buf[i++] = c;
7997c478bd9Sstevel@tonic-gate 				c	 = getch();
8007c478bd9Sstevel@tonic-gate 			} while ((c == '_') || isalnum(c));
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 			ungetch(c);
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 			buf[i] = '\0';
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 			if ((kp = lookup_keyword(buf)) != NULL) {
8077c478bd9Sstevel@tonic-gate 				yylval.stt_val = kp->stt;
8087c478bd9Sstevel@tonic-gate 				return (kp->token);
8097c478bd9Sstevel@tonic-gate 			} else {
8107c478bd9Sstevel@tonic-gate 				yylval.s_val = strdup(buf);
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 				return ((atIDENT) ? IDENTIFIER : TYPEDEF_NAME);
8137c478bd9Sstevel@tonic-gate 			}
8147c478bd9Sstevel@tonic-gate 		} else if (isdigit(c)) {
8157c478bd9Sstevel@tonic-gate 			do {
8167c478bd9Sstevel@tonic-gate 				buf[i++] = c;
8177c478bd9Sstevel@tonic-gate 			} while (isdigit(c = getch()));
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 			ungetch(c);
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 			buf[i]	 = '\0';
8227c478bd9Sstevel@tonic-gate 			yylval.s_val = strdup(buf);
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 			return (INTEGER);
8257c478bd9Sstevel@tonic-gate 		} else
8267c478bd9Sstevel@tonic-gate 			return (c);
8277c478bd9Sstevel@tonic-gate 	}
8287c478bd9Sstevel@tonic-gate /* NOTREACHED */
8297c478bd9Sstevel@tonic-gate }
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate /* getch - return the next character from the input stream. */
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate static int
getch(void)8347c478bd9Sstevel@tonic-gate getch(void) {
8357c478bd9Sstevel@tonic-gate 	int	c;
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate 	if ((c = *input) == '\0')
8387c478bd9Sstevel@tonic-gate 		c = EOF;
8397c478bd9Sstevel@tonic-gate 	else				/* only advance on non-NULL */
8407c478bd9Sstevel@tonic-gate 		input++;
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	return (c);
8437c478bd9Sstevel@tonic-gate }
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate /* ungetch - return a character to the input stream. */
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate static void
ungetch(int c)8487c478bd9Sstevel@tonic-gate ungetch(int c) {
8497c478bd9Sstevel@tonic-gate 	*(--input) = c;
8507c478bd9Sstevel@tonic-gate }
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate /* skipwhitespace - skip over whitespace in the input stream. */
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate static void
skipwhitespace(void)8557c478bd9Sstevel@tonic-gate skipwhitespace(void) {
8567c478bd9Sstevel@tonic-gate 	int	c;
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	while (isspace(c = getch()))
8597c478bd9Sstevel@tonic-gate 		;
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 	ungetch(c);
8627c478bd9Sstevel@tonic-gate }
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate /* skipcomment - scan ahead to the next end of comment. */
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate static void
skipcomment(void)8677c478bd9Sstevel@tonic-gate skipcomment(void) {
8687c478bd9Sstevel@tonic-gate 	loop {
8697c478bd9Sstevel@tonic-gate 		int	c;
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 		switch (c = getch()) {
8727c478bd9Sstevel@tonic-gate 		case EOF:
8737c478bd9Sstevel@tonic-gate 			return;
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 		case '*':
8767c478bd9Sstevel@tonic-gate 			if (lookahead('/'))
8777c478bd9Sstevel@tonic-gate 				return;
8787c478bd9Sstevel@tonic-gate 		}
8797c478bd9Sstevel@tonic-gate 	}
8807c478bd9Sstevel@tonic-gate /* NOTREACHED */
8817c478bd9Sstevel@tonic-gate }
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate /* lookahead - does next character match 'c'? */
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate static int
lookahead(int c)8867c478bd9Sstevel@tonic-gate lookahead(int c) {
8877c478bd9Sstevel@tonic-gate 	int	ch = getch();
8887c478bd9Sstevel@tonic-gate 	int	match;
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 	if (!(match = (ch == c)))
8917c478bd9Sstevel@tonic-gate 		ungetch(ch);
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 	return (match);
8947c478bd9Sstevel@tonic-gate }
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate /* putNtabs - write N '\t' to standard output. */
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate #if defined(DEBUG)
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate static void
putNTabs(int n)9017c478bd9Sstevel@tonic-gate putNTabs(int n) {
9027c478bd9Sstevel@tonic-gate 	int	 i;
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; ++i)
9057c478bd9Sstevel@tonic-gate 		putchar('\t');
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate /* D E C L A R A T I O N   S P E C I F I E R S */
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate /*
9127c478bd9Sstevel@tonic-gate  * Declaration specifiers encode storage class, type specifier and type
9137c478bd9Sstevel@tonic-gate  * qualifier information. This includes any identifiers associated with
9147c478bd9Sstevel@tonic-gate  * struct, union or enum declarations. Typedef names are also encoded
9157c478bd9Sstevel@tonic-gate  * in declaration specifiers.
9167c478bd9Sstevel@tonic-gate  */
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate /* declspec_Construct - allocate and initialize a declspec_t. */
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate static decl_spec_t *
declspec_Construct(void)9217c478bd9Sstevel@tonic-gate declspec_Construct(void) {
9227c478bd9Sstevel@tonic-gate 	decl_spec_t	*dsp = malloc(sizeof (decl_spec_t));
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 	assert(dsp != NULL);
9257c478bd9Sstevel@tonic-gate 	dsp->ds_stt = SCS_NONE | TS_NO_TS | TQ_NONE;
9267c478bd9Sstevel@tonic-gate 	dsp->ds_id = NULL;
9277c478bd9Sstevel@tonic-gate #if defined(MEM_DEBUG)
9287c478bd9Sstevel@tonic-gate 	++declspec_Construct_calls;
9297c478bd9Sstevel@tonic-gate #endif
9307c478bd9Sstevel@tonic-gate 	return (dsp);
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate /* declspec_Destroy - free a declspec_t. */
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate static void
declspec_Destroy(decl_spec_t * dsp)9367c478bd9Sstevel@tonic-gate declspec_Destroy(decl_spec_t *dsp) {
9377c478bd9Sstevel@tonic-gate 	free(dsp->ds_id);
9387c478bd9Sstevel@tonic-gate 	free(dsp);
9397c478bd9Sstevel@tonic-gate #if defined(MEM_DEBUG)
9407c478bd9Sstevel@tonic-gate 	--declspec_Construct_calls;
9417c478bd9Sstevel@tonic-gate #endif
9427c478bd9Sstevel@tonic-gate }
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate /*
9457c478bd9Sstevel@tonic-gate  * declspec_Init - allocate and initialize a declspec_t given an
9467c478bd9Sstevel@tonic-gate  *	stt_t and identifier.
9477c478bd9Sstevel@tonic-gate  *
9487c478bd9Sstevel@tonic-gate  * Note:
9497c478bd9Sstevel@tonic-gate  *	1) identifier can be NULL.
9507c478bd9Sstevel@tonic-gate  *	2) errors resulting in the stt_t and identifier are ignored.
9517c478bd9Sstevel@tonic-gate  */
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate static decl_spec_t *
declspec_Init(stt_t s,char * tagp)9547c478bd9Sstevel@tonic-gate declspec_Init(stt_t s, char *tagp) {
9557c478bd9Sstevel@tonic-gate 	const char	*p;
9567c478bd9Sstevel@tonic-gate 	decl_spec_t	*dsp = declspec_Construct();
9577c478bd9Sstevel@tonic-gate 	decl_spec_t	 tmp;
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 	tmp.ds_stt = s;
9607c478bd9Sstevel@tonic-gate 	tmp.ds_id = tagp;
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 	declspec_AddDS(dsp, &tmp, &p);		/* XXX ignore any error */
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	return (dsp);
9657c478bd9Sstevel@tonic-gate }
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate /*
9687c478bd9Sstevel@tonic-gate  * declspec_VerifySTT - verify that the two given stt_t can be combined.
9697c478bd9Sstevel@tonic-gate  *
9707c478bd9Sstevel@tonic-gate  * Note:
9717c478bd9Sstevel@tonic-gate  *	1) The return value is a const char *, non-NULL to indicate an error.
9727c478bd9Sstevel@tonic-gate  */
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate static char *
declspec_VerifySTT(stt_t s1,stt_t s2)9757c478bd9Sstevel@tonic-gate declspec_VerifySTT(stt_t s1, stt_t s2) {
9767c478bd9Sstevel@tonic-gate 	stt_t	result;
9777c478bd9Sstevel@tonic-gate 
9787c478bd9Sstevel@tonic-gate 	if ((s1 | s2) != (s1 ^ s2))
9797c478bd9Sstevel@tonic-gate 		return ("attempt to add declaration specifier "
9807c478bd9Sstevel@tonic-gate 		    "that is already present");
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 	result = (s1 | s2) & TS_MASK;
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	if (lookup_sttpair(result) == NULL) {
9857c478bd9Sstevel@tonic-gate 		if (STT_isbasic(result) && STT_isderived(result))
9867c478bd9Sstevel@tonic-gate 			return ("attempt to combine basic and "
9877c478bd9Sstevel@tonic-gate 			    "derived types");
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 		if (STT_isvoid(result) &&
9907c478bd9Sstevel@tonic-gate 		    (STT_isbasic(result) || STT_isderived(result)))
9917c478bd9Sstevel@tonic-gate 			return ("attempt to combine void with "
9927c478bd9Sstevel@tonic-gate 			    "other type specifiers");
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 		if (STT_isfloat(result) && STT_isint(result))
9957c478bd9Sstevel@tonic-gate 			return ("attempt to combine floating and "
9967c478bd9Sstevel@tonic-gate 			    "integer type specifiers");
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 		if (STT_ischar(result) && STT_isint(result))
9997c478bd9Sstevel@tonic-gate 			return ("attempt to combine character and "
10007c478bd9Sstevel@tonic-gate 			    "integer type specifiers");
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 		if (STT_has_explicit_sign(result) &&
10037c478bd9Sstevel@tonic-gate 		    (STT_isfloat(result) || STT_isderived(result)))
10047c478bd9Sstevel@tonic-gate 			return ("attempt to combine signed or "
10057c478bd9Sstevel@tonic-gate 			    "unsigned with float or derived type");
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 		return ("invalid declaration specifier");
10087c478bd9Sstevel@tonic-gate 	}
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 	return (NULL);
10117c478bd9Sstevel@tonic-gate }
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate /*
10147c478bd9Sstevel@tonic-gate  * declspec_AddSTT - add an stt_t to a decl_spec_t.
10157c478bd9Sstevel@tonic-gate  *
10167c478bd9Sstevel@tonic-gate  * Note:
10177c478bd9Sstevel@tonic-gate  *	1) The "long long" type is handled here.
10187c478bd9Sstevel@tonic-gate  *	   If both stt_t include TS_LONG then this is an attempt to use
10197c478bd9Sstevel@tonic-gate  *	   "long long". The TS_LONG is cleared from the s1 and s2 and
10207c478bd9Sstevel@tonic-gate  *	   then TS_LONGLONG is added to s2. The resulting s1 and s2 are
10217c478bd9Sstevel@tonic-gate  *	   passed to declspec_VerifySTT to determine if the result is valid.
10227c478bd9Sstevel@tonic-gate  *
10237c478bd9Sstevel@tonic-gate  *	2) This method of handling "long long" does detect the case of
10247c478bd9Sstevel@tonic-gate  *	   "long double long" and all it's variant forms.
10257c478bd9Sstevel@tonic-gate  */
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate static decl_spec_t *
declspec_AddSTT(decl_spec_t * dsp,stt_t s2,const char ** err)10287c478bd9Sstevel@tonic-gate declspec_AddSTT(decl_spec_t *dsp, stt_t s2, const char **err) {
10297c478bd9Sstevel@tonic-gate 	stt_t	s1 = dsp->ds_stt;
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 	/* non-ANSI type: long long */
10327c478bd9Sstevel@tonic-gate 	if ((s1 & TS_LONG) && (s2 & TS_LONG)) {
10337c478bd9Sstevel@tonic-gate 		s1		&= ~(TS_LONG);
10347c478bd9Sstevel@tonic-gate 		dsp->ds_stt = s1;
10357c478bd9Sstevel@tonic-gate 		s2		&= ~(TS_LONG);
10367c478bd9Sstevel@tonic-gate 		s2		|= TS_LONGLONG;
10377c478bd9Sstevel@tonic-gate 	}
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate 	if ((*err = declspec_VerifySTT(s1, s2)) == NULL)
10407c478bd9Sstevel@tonic-gate 		dsp->ds_stt	|= s2;
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	return (dsp);
10437c478bd9Sstevel@tonic-gate }
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate /*
10467c478bd9Sstevel@tonic-gate  * declpec_AddDS - add a decl_spec_t to an existing decl_spec_t.
10477c478bd9Sstevel@tonic-gate  */
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate static decl_spec_t *
declspec_AddDS(decl_spec_t * dsp,decl_spec_t * tsp,const char ** err)10507c478bd9Sstevel@tonic-gate declspec_AddDS(decl_spec_t *dsp, decl_spec_t *tsp, const char **err) {
10517c478bd9Sstevel@tonic-gate 	declspec_AddSTT(dsp, tsp->ds_stt, err);
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate 	if ((*err == NULL) && tsp->ds_id) {
10547c478bd9Sstevel@tonic-gate 		free(dsp->ds_id);
10557c478bd9Sstevel@tonic-gate 		dsp->ds_id	 = strdup(tsp->ds_id);
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 		assert(dsp->ds_id != NULL);
10587c478bd9Sstevel@tonic-gate 	}
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 	return (dsp);
10617c478bd9Sstevel@tonic-gate }
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate /*
10647c478bd9Sstevel@tonic-gate  * declspec_GetSTT - return the stt_t within a decl_spec_t.
10657c478bd9Sstevel@tonic-gate  */
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate static stt_t
declspec_GetSTT(decl_spec_t * dsp)10687c478bd9Sstevel@tonic-gate declspec_GetSTT(decl_spec_t *dsp) {
10697c478bd9Sstevel@tonic-gate 	return (dsp->ds_stt);
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate /*
10737c478bd9Sstevel@tonic-gate  * declspec_GetTag - return the identifier within a decl_spec_t.
10747c478bd9Sstevel@tonic-gate  */
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate static char *
declspec_GetTag(decl_spec_t * dsp)10777c478bd9Sstevel@tonic-gate declspec_GetTag(decl_spec_t *dsp) {
10787c478bd9Sstevel@tonic-gate 	return (dsp->ds_id);
10797c478bd9Sstevel@tonic-gate }
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate /*
10827c478bd9Sstevel@tonic-gate  * declspec_ToString - convert a decl_spec_t into a string.
10837c478bd9Sstevel@tonic-gate  *
10847c478bd9Sstevel@tonic-gate  * Note:
10857c478bd9Sstevel@tonic-gate  *	1) The form of the resulting string is always the same, i.e.
10867c478bd9Sstevel@tonic-gate  *
10877c478bd9Sstevel@tonic-gate  *		[register] [type_specifier] [const] [volatile]
10887c478bd9Sstevel@tonic-gate  *
10897c478bd9Sstevel@tonic-gate  * dsp must be correct
10907c478bd9Sstevel@tonic-gate  *
10917c478bd9Sstevel@tonic-gate  */
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate char *
declspec_ToString(char * bufp,decl_spec_t * dsp)10947c478bd9Sstevel@tonic-gate declspec_ToString(char *bufp, decl_spec_t *dsp) {
10957c478bd9Sstevel@tonic-gate 	const char	*s;
10967c478bd9Sstevel@tonic-gate 	int		 something = 0;
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 	*bufp = '\0';
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 	/* storage class specifier */
11017c478bd9Sstevel@tonic-gate 	switch (dsp->ds_stt & SCS_MASK) {
11027c478bd9Sstevel@tonic-gate 	case SCS_REGISTER:
11037c478bd9Sstevel@tonic-gate 		strcat(bufp, "register");
11047c478bd9Sstevel@tonic-gate 		something = 1;
11057c478bd9Sstevel@tonic-gate 		break;
11067c478bd9Sstevel@tonic-gate 	}
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 	s = lookup_sttpair(dsp->ds_stt & TS_MASK);
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 	/* type specifier */
11117c478bd9Sstevel@tonic-gate 	switch (dsp->ds_stt & TS_MASK) {
11127c478bd9Sstevel@tonic-gate 	case TS_STRUCT:
11137c478bd9Sstevel@tonic-gate 	case TS_UNION:
11147c478bd9Sstevel@tonic-gate 	case TS_ENUM:
11157c478bd9Sstevel@tonic-gate 		if (something)
11167c478bd9Sstevel@tonic-gate 			strcat(bufp, " ");
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate 		strcat(bufp, s);
11197c478bd9Sstevel@tonic-gate 		strcat(bufp, " ");
11207c478bd9Sstevel@tonic-gate 		strcat(bufp, dsp->ds_id);
11217c478bd9Sstevel@tonic-gate 		break;
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	case TS_TYPEDEF:
11247c478bd9Sstevel@tonic-gate 		if (something)
11257c478bd9Sstevel@tonic-gate 			strcat(bufp, " ");
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 		strcat(bufp, dsp->ds_id);
11287c478bd9Sstevel@tonic-gate 		break;
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 	default:
11317c478bd9Sstevel@tonic-gate 		if (something)
11327c478bd9Sstevel@tonic-gate 			strcat(bufp, " ");
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 		strcat(bufp, s);
11357c478bd9Sstevel@tonic-gate 		break;
11367c478bd9Sstevel@tonic-gate 	}
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate 	if (s)
11397c478bd9Sstevel@tonic-gate 		something = 1;
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 	if (something && (dsp->ds_stt & TQ_MASK))
11427c478bd9Sstevel@tonic-gate 		strcat(bufp, " ");
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate 	if (dsp->ds_stt & TQ_CONST)	/* type qualifier */
11457c478bd9Sstevel@tonic-gate 		strcat(bufp, "const");
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate 	if (dsp->ds_stt & TQ_VOLATILE) {
11487c478bd9Sstevel@tonic-gate 		if (dsp->ds_stt & TQ_CONST)
11497c478bd9Sstevel@tonic-gate 			strcat(bufp, " ");
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 		strcat(bufp, "volatile");
11527c478bd9Sstevel@tonic-gate 	}
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 	/*
11557c478bd9Sstevel@tonic-gate 	 * It currently acknowledges and ignores restrict or _RESTRICT_KYWD
11567c478bd9Sstevel@tonic-gate 	 * in code generation because of the uncertain behavior of "restrict".
11577c478bd9Sstevel@tonic-gate 	 */
11587c478bd9Sstevel@tonic-gate 	if (dsp->ds_stt & TQ_RESTRICT)
11597c478bd9Sstevel@tonic-gate 		strcat(bufp, "");
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 	if (dsp->ds_stt & TQ_RESTRICT_KYWD)
11627c478bd9Sstevel@tonic-gate 		strcat(bufp, "");
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 	return (bufp);
11657c478bd9Sstevel@tonic-gate }
11667c478bd9Sstevel@tonic-gate 
11677c478bd9Sstevel@tonic-gate /* T Y P E   M O D I F I E R S */
11687c478bd9Sstevel@tonic-gate 
11697c478bd9Sstevel@tonic-gate /*
11707c478bd9Sstevel@tonic-gate  * Type modifiers encode the "array of...", "pointer to ..." and
11717c478bd9Sstevel@tonic-gate  * "function returning ..." aspects of C types. The modifiers are kept
11727c478bd9Sstevel@tonic-gate  * as a linked list in precedence order. The grammar encodes the
11737c478bd9Sstevel@tonic-gate  * precedence order described by the standard.
11747c478bd9Sstevel@tonic-gate  *
11757c478bd9Sstevel@tonic-gate  * Type modifiers are always added at the end of list and the list is
11767c478bd9Sstevel@tonic-gate  * always traversed from head to tail.
11777c478bd9Sstevel@tonic-gate  */
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate /* type_Construct - allocate and initialize a type_t. */
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate static type_t *
type_Construct(void)11827c478bd9Sstevel@tonic-gate type_Construct(void) {
11837c478bd9Sstevel@tonic-gate 	type_t	*tp = malloc(sizeof (type_t));
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	assert(tp != NULL);
11867c478bd9Sstevel@tonic-gate 
11877c478bd9Sstevel@tonic-gate 	tp->t_next = NULL;			/* generic */
11887c478bd9Sstevel@tonic-gate 	tp->t_dt = DD_NONE;
11897c478bd9Sstevel@tonic-gate 
11907c478bd9Sstevel@tonic-gate 	tp->t_nargs = 0;			/* DD_FUN */
11917c478bd9Sstevel@tonic-gate 	tp->t_ellipsis = 0;
11927c478bd9Sstevel@tonic-gate 	tp->t_args = NULL;
11937c478bd9Sstevel@tonic-gate 						/* DD_PTR */
11947c478bd9Sstevel@tonic-gate 	tp->t_stt	 = (SCS_NONE | TS_NO_TS | TQ_NONE);
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate 	tp->t_sizestr = NULL;			/* DD_ARY */
11977c478bd9Sstevel@tonic-gate #if defined(MEM_DEBUG)
11987c478bd9Sstevel@tonic-gate 	++type_Construct_calls;
11997c478bd9Sstevel@tonic-gate #endif
12007c478bd9Sstevel@tonic-gate 	return (tp);
12017c478bd9Sstevel@tonic-gate }
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate /* type_Destroy - free a type_t list. */
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate static void
type_Destroy(type_t * tp)12067c478bd9Sstevel@tonic-gate type_Destroy(type_t *tp) {
12077c478bd9Sstevel@tonic-gate 	while (tp) {
12087c478bd9Sstevel@tonic-gate 		type_t	*nextp = tp->t_next;
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 		switch (tp->t_dt) {
12117c478bd9Sstevel@tonic-gate 		case DD_FUN:
12127c478bd9Sstevel@tonic-gate 			decl_Destroy(tp->t_args);
12137c478bd9Sstevel@tonic-gate 			break;
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 		case DD_PTR:
12167c478bd9Sstevel@tonic-gate 			break;
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 		case DD_ARY:
12197c478bd9Sstevel@tonic-gate 			free(tp->t_sizestr);
12207c478bd9Sstevel@tonic-gate 			break;
12217c478bd9Sstevel@tonic-gate 		}
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate 		free(tp);
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate 		tp = nextp;
12267c478bd9Sstevel@tonic-gate #if defined(MEM_DEBUG)
12277c478bd9Sstevel@tonic-gate 		--type_Construct_calls;
12287c478bd9Sstevel@tonic-gate #endif
12297c478bd9Sstevel@tonic-gate 	}
12307c478bd9Sstevel@tonic-gate }
12317c478bd9Sstevel@tonic-gate 
12327c478bd9Sstevel@tonic-gate /*
12337c478bd9Sstevel@tonic-gate  * type_SetPtr - make a type_t into a "pointer to ..." variant.
12347c478bd9Sstevel@tonic-gate  *
12357c478bd9Sstevel@tonic-gate  * Note:
12367c478bd9Sstevel@tonic-gate  *	1) The stt_t will encode any type qualifiers (const, volatile).
12377c478bd9Sstevel@tonic-gate  */
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate static type_t *
type_SetPtr(type_t * tp,stt_t s)12407c478bd9Sstevel@tonic-gate type_SetPtr(type_t *tp, stt_t s) {
12417c478bd9Sstevel@tonic-gate 	assert(tp->t_dt == DD_NONE);
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 	tp->t_dt = DD_PTR;
12447c478bd9Sstevel@tonic-gate 	tp->t_stt = s & TQ_MASK;
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 	return (tp);
12477c478bd9Sstevel@tonic-gate }
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate /*
12507c478bd9Sstevel@tonic-gate  * type_SetAry - make a type_t into an "array of ...", variant.
12517c478bd9Sstevel@tonic-gate  *
12527c478bd9Sstevel@tonic-gate  * Note:
12537c478bd9Sstevel@tonic-gate  *	1) The array dimension can be NULL to indicate undefined, i.e. [].
12547c478bd9Sstevel@tonic-gate  */
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate static type_t *
type_SetAry(type_t * tp,char * dim)12577c478bd9Sstevel@tonic-gate type_SetAry(type_t *tp, char *dim) {
12587c478bd9Sstevel@tonic-gate 	assert(tp->t_dt == DD_NONE);
12597c478bd9Sstevel@tonic-gate 	assert(tp->t_sizestr == NULL);
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 	tp->t_dt = DD_ARY;
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 	if (dim) {
12647c478bd9Sstevel@tonic-gate 		tp->t_sizestr = strdup(dim);
12657c478bd9Sstevel@tonic-gate 		assert(tp->t_sizestr != NULL);
12667c478bd9Sstevel@tonic-gate 	} else
12677c478bd9Sstevel@tonic-gate 		tp->t_sizestr = NULL;
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate 	return (tp);
12707c478bd9Sstevel@tonic-gate }
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate /*
12737c478bd9Sstevel@tonic-gate  * type_SetFun - make a type_t into a "function returning ..." variant.
12747c478bd9Sstevel@tonic-gate  *
12757c478bd9Sstevel@tonic-gate  * Note:
12767c478bd9Sstevel@tonic-gate  *	1) The argument list can be NULL to indicate undefined, i.e. ().
12777c478bd9Sstevel@tonic-gate  */
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate static type_t *
type_SetFun(type_t * tp,decl_t * arglist)12807c478bd9Sstevel@tonic-gate type_SetFun(type_t *tp, decl_t *arglist) {
12817c478bd9Sstevel@tonic-gate 	assert(tp->t_dt == DD_NONE);
12827c478bd9Sstevel@tonic-gate 
12837c478bd9Sstevel@tonic-gate 	tp->t_dt = DD_FUN;
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 	if (arglist) {
12867c478bd9Sstevel@tonic-gate 		tp->t_nargs = decl_GetArgLength(arglist);
12877c478bd9Sstevel@tonic-gate 		tp->t_args = arglist;
12887c478bd9Sstevel@tonic-gate 		tp->t_ellipsis = arglist->d_ellipsis;
12897c478bd9Sstevel@tonic-gate 	}
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 	return (tp);
12927c478bd9Sstevel@tonic-gate }
12937c478bd9Sstevel@tonic-gate 
12947c478bd9Sstevel@tonic-gate /*
12957c478bd9Sstevel@tonic-gate  * type_AddTail - add a type_t to the end of an existing type_t list.
12967c478bd9Sstevel@tonic-gate  *
12977c478bd9Sstevel@tonic-gate  * Note:
12987c478bd9Sstevel@tonic-gate  *	1) The type_t *tp is added to the end of the type_t *dp list.
12997c478bd9Sstevel@tonic-gate  */
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate static type_t *
type_AddTail(type_t * dp,type_t * tp)13027c478bd9Sstevel@tonic-gate type_AddTail(type_t *dp, type_t *tp) {
13037c478bd9Sstevel@tonic-gate 	type_t	*lastp = dp;
13047c478bd9Sstevel@tonic-gate 	type_t	*p;
13057c478bd9Sstevel@tonic-gate 
13067c478bd9Sstevel@tonic-gate 	while (p = lastp->t_next)
13077c478bd9Sstevel@tonic-gate 		lastp = p;
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 	lastp->t_next = tp;
13107c478bd9Sstevel@tonic-gate 
13117c478bd9Sstevel@tonic-gate 	return (dp);
13127c478bd9Sstevel@tonic-gate }
13137c478bd9Sstevel@tonic-gate 
13147c478bd9Sstevel@tonic-gate #if defined(DEBUG)
13157c478bd9Sstevel@tonic-gate 
13167c478bd9Sstevel@tonic-gate /* type_PrintType - print a type_t list onto standard output. */
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate static void
type_PrintType(type_t * tp,int lvl)13197c478bd9Sstevel@tonic-gate type_PrintType(type_t *tp, int lvl) {
13207c478bd9Sstevel@tonic-gate 	decl_spec_t	tmp;
13217c478bd9Sstevel@tonic-gate 	char		buf[BUFSIZ];
13227c478bd9Sstevel@tonic-gate 
13237c478bd9Sstevel@tonic-gate 	while (tp) {
13247c478bd9Sstevel@tonic-gate 		putNTabs(lvl);
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate 		switch (tp->t_dt) {
13277c478bd9Sstevel@tonic-gate 		case DD_PTR:
13287c478bd9Sstevel@tonic-gate 			tmp.ds_stt = tp->t_stt;
13297c478bd9Sstevel@tonic-gate 			tmp.ds_id = NULL;
13307c478bd9Sstevel@tonic-gate 
13317c478bd9Sstevel@tonic-gate 			printf("[%s] ptr to\n", declspec_ToString(buf, &tmp));
13327c478bd9Sstevel@tonic-gate 			break;
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate 		case DD_FUN:
13357c478bd9Sstevel@tonic-gate 			printf("fun [%d%c] %s\n",
13367c478bd9Sstevel@tonic-gate 			    tp->t_nargs,
13377c478bd9Sstevel@tonic-gate 			    (tp->t_ellipsis)? '+' : '=',
13387c478bd9Sstevel@tonic-gate 			    (tp->t_args)? "with arguments" :
13397c478bd9Sstevel@tonic-gate 			    "undefined arguments");
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 			if (tp->t_args) {
13427c478bd9Sstevel@tonic-gate 				decl_PrintDecl(tp->t_args, lvl + 1);
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 				if (tp->t_ellipsis) {
13457c478bd9Sstevel@tonic-gate 					putNTabs(lvl + 1);
13467c478bd9Sstevel@tonic-gate 					printf("...\n");
13477c478bd9Sstevel@tonic-gate 				}
13487c478bd9Sstevel@tonic-gate 			}
13497c478bd9Sstevel@tonic-gate 			break;
13507c478bd9Sstevel@tonic-gate 
13517c478bd9Sstevel@tonic-gate 		case DD_ARY:
13527c478bd9Sstevel@tonic-gate 			printf("ary [%s] of\n",
13537c478bd9Sstevel@tonic-gate 			    (tp->t_sizestr)? tp->t_sizestr : "");
13547c478bd9Sstevel@tonic-gate 			break;
13557c478bd9Sstevel@tonic-gate 		}
13567c478bd9Sstevel@tonic-gate 
13577c478bd9Sstevel@tonic-gate 		tp = tp->t_next;
13587c478bd9Sstevel@tonic-gate 	}
13597c478bd9Sstevel@tonic-gate }
13607c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate /*
13637c478bd9Sstevel@tonic-gate  * type_Verify - verify a type_t list for semantic correctness.
13647c478bd9Sstevel@tonic-gate  *
13657c478bd9Sstevel@tonic-gate  * Note:
13667c478bd9Sstevel@tonic-gate  *	1) C supports most combinations of type modifiers.
13677c478bd9Sstevel@tonic-gate  *	   It does not support three combinations, they are:
13687c478bd9Sstevel@tonic-gate  *
13697c478bd9Sstevel@tonic-gate  *		function returning array
13707c478bd9Sstevel@tonic-gate  *		array of functions
13717c478bd9Sstevel@tonic-gate  *		function returning function
13727c478bd9Sstevel@tonic-gate  *
13737c478bd9Sstevel@tonic-gate  *	2) The enum values associated with type modifiers (i.e. DD_*)
13747c478bd9Sstevel@tonic-gate  *	   cannot be modified without changing the table included within the
13757c478bd9Sstevel@tonic-gate  *	   function.
13767c478bd9Sstevel@tonic-gate  *
13777c478bd9Sstevel@tonic-gate  * 	3) The function returns NULL to indicate that the type modifier
13787c478bd9Sstevel@tonic-gate  *	   list is valid and non-NULL to indicate an error.
13797c478bd9Sstevel@tonic-gate  *
13807c478bd9Sstevel@tonic-gate  *	4) A type_t of NULL is permitted to indicate an empty type_t list.
13817c478bd9Sstevel@tonic-gate  */
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate static const char *
type_Verify(type_t * tp)13847c478bd9Sstevel@tonic-gate type_Verify(type_t *tp) {
13857c478bd9Sstevel@tonic-gate 	static const char *dttbl[4][4] = {
13867c478bd9Sstevel@tonic-gate 		/* NONE	ARY	FUN	PTR */
13877c478bd9Sstevel@tonic-gate /* NONE */	{NULL,	NULL,	NULL,	NULL},
13887c478bd9Sstevel@tonic-gate /* ARY */	{NULL,	NULL,	"array of functions", NULL},
13897c478bd9Sstevel@tonic-gate /* FUN */	{NULL,	"function returning array",
13907c478bd9Sstevel@tonic-gate 		    "function returning function", NULL},
13917c478bd9Sstevel@tonic-gate /* PTR */	{NULL,	NULL,	NULL,	NULL},
13927c478bd9Sstevel@tonic-gate 	};
13937c478bd9Sstevel@tonic-gate 
13947c478bd9Sstevel@tonic-gate 	if (tp) {
13957c478bd9Sstevel@tonic-gate 		type_t	*nextp;
13967c478bd9Sstevel@tonic-gate 
13977c478bd9Sstevel@tonic-gate 		do {
13987c478bd9Sstevel@tonic-gate 			const char	*p;
13997c478bd9Sstevel@tonic-gate 			decl_type_t	 nt;
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate 			nt = (nextp = tp->t_next)? nextp->t_dt : DD_NONE;
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 			if ((p = dttbl[tp->t_dt][nt]) != NULL)
14047c478bd9Sstevel@tonic-gate 				return (p);
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 		} while (tp = nextp);
14077c478bd9Sstevel@tonic-gate 	}
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 	return (NULL);
14107c478bd9Sstevel@tonic-gate }
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate /* type_GetNext - return the next type_t in the list. */
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate type_t *
type_GetNext(type_t * tp)14157c478bd9Sstevel@tonic-gate type_GetNext(type_t *tp) {
14167c478bd9Sstevel@tonic-gate 	return (tp->t_next);
14177c478bd9Sstevel@tonic-gate }
14187c478bd9Sstevel@tonic-gate 
14197c478bd9Sstevel@tonic-gate /*
14207c478bd9Sstevel@tonic-gate  * The following group of functions return and or
14217c478bd9Sstevel@tonic-gate  * test various aspects of type modifiers.
14227c478bd9Sstevel@tonic-gate  *
14237c478bd9Sstevel@tonic-gate  * 1) The three functions: type_IsPtrTo, type_IsFunction and
14247c478bd9Sstevel@tonic-gate  *    type_IsArray will accept an argument of NULL.
14257c478bd9Sstevel@tonic-gate  *
14267c478bd9Sstevel@tonic-gate  * 2) All other functions require one of the above three to be true.
14277c478bd9Sstevel@tonic-gate  *    Various asserts are in place to verify correct usage.
14287c478bd9Sstevel@tonic-gate  */
14297c478bd9Sstevel@tonic-gate 
14307c478bd9Sstevel@tonic-gate int
type_IsArray(type_t * tp)14317c478bd9Sstevel@tonic-gate type_IsArray(type_t *tp) {
14327c478bd9Sstevel@tonic-gate 	return (tp && (tp->t_dt == DD_ARY));
14337c478bd9Sstevel@tonic-gate }
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate char *
type_GetArraySize(type_t * tp)14367c478bd9Sstevel@tonic-gate type_GetArraySize(type_t *tp) {
14377c478bd9Sstevel@tonic-gate 	assert(tp->t_dt == DD_ARY);
14387c478bd9Sstevel@tonic-gate 
14397c478bd9Sstevel@tonic-gate 	return (tp->t_sizestr);
14407c478bd9Sstevel@tonic-gate }
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate int
type_IsPtrTo(type_t * tp)14437c478bd9Sstevel@tonic-gate type_IsPtrTo(type_t *tp) {
14447c478bd9Sstevel@tonic-gate 	return (tp && (tp->t_dt == DD_PTR));
14457c478bd9Sstevel@tonic-gate }
14467c478bd9Sstevel@tonic-gate 
14477c478bd9Sstevel@tonic-gate stt_t
type_GetPtrToTypeQual(type_t * tp)14487c478bd9Sstevel@tonic-gate type_GetPtrToTypeQual(type_t *tp) {
14497c478bd9Sstevel@tonic-gate 	assert(tp->t_dt == DD_PTR);
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	return (tp->t_stt);
14527c478bd9Sstevel@tonic-gate }
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate int
type_IsFunction(type_t * tp)14557c478bd9Sstevel@tonic-gate type_IsFunction(type_t *tp) {
14567c478bd9Sstevel@tonic-gate 	return (tp && (tp->t_dt == DD_FUN));
14577c478bd9Sstevel@tonic-gate }
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate int
type_GetArgLength(type_t * tp)14607c478bd9Sstevel@tonic-gate type_GetArgLength(type_t *tp) {
14617c478bd9Sstevel@tonic-gate 	assert(tp->t_dt == DD_FUN);
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate 	return (tp->t_nargs);
14647c478bd9Sstevel@tonic-gate }
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate int
type_IsVarargs(type_t * tp)14677c478bd9Sstevel@tonic-gate type_IsVarargs(type_t *tp) {
14687c478bd9Sstevel@tonic-gate 	while (tp && tp->t_dt == DD_PTR)
14697c478bd9Sstevel@tonic-gate 		tp = tp->t_next;
14707c478bd9Sstevel@tonic-gate 
14717c478bd9Sstevel@tonic-gate 	assert(tp->t_dt == DD_FUN);
14727c478bd9Sstevel@tonic-gate 
14737c478bd9Sstevel@tonic-gate 	return (tp->t_ellipsis);
14747c478bd9Sstevel@tonic-gate }
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate decl_t *
type_GetArg(type_t * tp)14777c478bd9Sstevel@tonic-gate type_GetArg(type_t *tp) {
14787c478bd9Sstevel@tonic-gate 	assert(tp->t_dt == DD_FUN);
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	return (tp->t_args);
14817c478bd9Sstevel@tonic-gate }
14827c478bd9Sstevel@tonic-gate 
14837c478bd9Sstevel@tonic-gate /*
14847c478bd9Sstevel@tonic-gate  * type_IsPtrFun - determine if the type_t results in a call-able function.
14857c478bd9Sstevel@tonic-gate  *
14867c478bd9Sstevel@tonic-gate  * Note:
14877c478bd9Sstevel@tonic-gate  *	1) The argument can be NULL.
14887c478bd9Sstevel@tonic-gate  *
14897c478bd9Sstevel@tonic-gate  *	2) The test is true if the type_t list is number of DD_PTR followed
14907c478bd9Sstevel@tonic-gate  *	by a DD_FUN.
14917c478bd9Sstevel@tonic-gate  */
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate int
type_IsPtrFun(type_t * tp)14947c478bd9Sstevel@tonic-gate type_IsPtrFun(type_t *tp) {
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate 	if (! (tp && (tp->t_dt == DD_PTR)))
14977c478bd9Sstevel@tonic-gate 		return (0);
14987c478bd9Sstevel@tonic-gate 
14997c478bd9Sstevel@tonic-gate 	tp = tp->t_next;
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 	while (tp && (tp->t_dt == DD_PTR))
15027c478bd9Sstevel@tonic-gate 		tp = tp->t_next;
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 	return (tp && (tp->t_dt == DD_FUN));
15057c478bd9Sstevel@tonic-gate }
15067c478bd9Sstevel@tonic-gate 
15077c478bd9Sstevel@tonic-gate /* D E C L A R A T O R */
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate /*
15107c478bd9Sstevel@tonic-gate  * A decl_t encodes the name,
15117c478bd9Sstevel@tonic-gate  * declaration specifiers and type modifiers of an object.
15127c478bd9Sstevel@tonic-gate  */
15137c478bd9Sstevel@tonic-gate 
15147c478bd9Sstevel@tonic-gate /* decl_Construct - allocate a decl_t. */
15157c478bd9Sstevel@tonic-gate 
15167c478bd9Sstevel@tonic-gate static decl_t *
decl_Construct(void)15177c478bd9Sstevel@tonic-gate decl_Construct(void) {
15187c478bd9Sstevel@tonic-gate 	decl_t	*dp = malloc(sizeof (decl_t));
15197c478bd9Sstevel@tonic-gate 
15207c478bd9Sstevel@tonic-gate 	assert(dp != NULL);
15217c478bd9Sstevel@tonic-gate 
15227c478bd9Sstevel@tonic-gate 	dp->d_name = NULL;
15237c478bd9Sstevel@tonic-gate 	dp->d_type = NULL;
15247c478bd9Sstevel@tonic-gate 	dp->d_next = NULL;
15257c478bd9Sstevel@tonic-gate 	dp->d_ds = declspec_Construct();
15267c478bd9Sstevel@tonic-gate 	dp->d_ellipsis = 0;
15277c478bd9Sstevel@tonic-gate #if defined(MEM_DEBUG)
15287c478bd9Sstevel@tonic-gate 	++decl_Construct_calls;
15297c478bd9Sstevel@tonic-gate #endif
15307c478bd9Sstevel@tonic-gate 	return (dp);
15317c478bd9Sstevel@tonic-gate }
15327c478bd9Sstevel@tonic-gate 
15337c478bd9Sstevel@tonic-gate /* decl_Destroy - free a decl_t list. */
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate void
decl_Destroy(decl_t * dp)15367c478bd9Sstevel@tonic-gate decl_Destroy(decl_t *dp) {
15377c478bd9Sstevel@tonic-gate 	while (dp) {
15387c478bd9Sstevel@tonic-gate 		decl_t	*nextp = dp->d_next;
15397c478bd9Sstevel@tonic-gate 
15407c478bd9Sstevel@tonic-gate 		type_Destroy(dp->d_type);
15417c478bd9Sstevel@tonic-gate 		declspec_Destroy(dp->d_ds);
15427c478bd9Sstevel@tonic-gate 		free(dp->d_name);
15437c478bd9Sstevel@tonic-gate 		free(dp);
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate 		dp = nextp;
15467c478bd9Sstevel@tonic-gate #if defined(MEM_DEBUG)
15477c478bd9Sstevel@tonic-gate 		--decl_Construct_calls;
15487c478bd9Sstevel@tonic-gate #endif
15497c478bd9Sstevel@tonic-gate 	}
15507c478bd9Sstevel@tonic-gate }
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate /*
15537c478bd9Sstevel@tonic-gate  * decl_GetArgLength - return the length of a decl_t list.
15547c478bd9Sstevel@tonic-gate  *
15557c478bd9Sstevel@tonic-gate  * Note:
15567c478bd9Sstevel@tonic-gate  *	1) The argument may be NULL to indicate an empty list, len == 0.
15577c478bd9Sstevel@tonic-gate  */
15587c478bd9Sstevel@tonic-gate 
15597c478bd9Sstevel@tonic-gate int
decl_GetArgLength(decl_t * dp)15607c478bd9Sstevel@tonic-gate decl_GetArgLength(decl_t *dp) {
15617c478bd9Sstevel@tonic-gate 	int	len;
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 	for (len = 0; dp; dp = dp->d_next)
15647c478bd9Sstevel@tonic-gate 		++len;
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate 	return (len);
15677c478bd9Sstevel@tonic-gate }
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate /*
15707c478bd9Sstevel@tonic-gate  * The following group of functions get or test various aspects of a decl_t.
15717c478bd9Sstevel@tonic-gate  */
15727c478bd9Sstevel@tonic-gate 
15737c478bd9Sstevel@tonic-gate decl_t *
decl_GetNext(decl_t * dp)15747c478bd9Sstevel@tonic-gate decl_GetNext(decl_t *dp) {
15757c478bd9Sstevel@tonic-gate 	return (dp->d_next);
15767c478bd9Sstevel@tonic-gate }
15777c478bd9Sstevel@tonic-gate 
15787c478bd9Sstevel@tonic-gate stt_t
decl_GetDeclSpec(decl_t * dp)15797c478bd9Sstevel@tonic-gate decl_GetDeclSpec(decl_t *dp) {
15807c478bd9Sstevel@tonic-gate 	return (declspec_GetSTT(dp->d_ds));
15817c478bd9Sstevel@tonic-gate }
15827c478bd9Sstevel@tonic-gate 
15837c478bd9Sstevel@tonic-gate char *
decl_GetDSName(decl_t * dp)15847c478bd9Sstevel@tonic-gate decl_GetDSName(decl_t *dp) {
15857c478bd9Sstevel@tonic-gate 	return (declspec_GetTag(dp->d_ds));
15867c478bd9Sstevel@tonic-gate }
15877c478bd9Sstevel@tonic-gate 
15887c478bd9Sstevel@tonic-gate type_t *
decl_GetType(decl_t * dp)15897c478bd9Sstevel@tonic-gate decl_GetType(decl_t *dp) {
15907c478bd9Sstevel@tonic-gate 	return (dp->d_type);
15917c478bd9Sstevel@tonic-gate }
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate int
decl_IsVarargs(decl_t * dp)15947c478bd9Sstevel@tonic-gate decl_IsVarargs(decl_t *dp) {
15957c478bd9Sstevel@tonic-gate 	return (dp->d_ellipsis);
15967c478bd9Sstevel@tonic-gate }
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate int
decl_IsFunction(decl_t * dp)15997c478bd9Sstevel@tonic-gate decl_IsFunction(decl_t *dp) {
16007c478bd9Sstevel@tonic-gate 	return (type_IsFunction(dp->d_type));
16017c478bd9Sstevel@tonic-gate }
16027c478bd9Sstevel@tonic-gate 
16037c478bd9Sstevel@tonic-gate char *
decl_GetName(decl_t * dp)16047c478bd9Sstevel@tonic-gate decl_GetName(decl_t *dp) {
16057c478bd9Sstevel@tonic-gate 	return (dp->d_name);
16067c478bd9Sstevel@tonic-gate }
16077c478bd9Sstevel@tonic-gate 
16087c478bd9Sstevel@tonic-gate /*
16097c478bd9Sstevel@tonic-gate  * decl_AddArg - add a decl_t to the end of an decl_t list.
16107c478bd9Sstevel@tonic-gate  */
16117c478bd9Sstevel@tonic-gate 
16127c478bd9Sstevel@tonic-gate static decl_t *
decl_AddArg(decl_t * dp,decl_t * tp)16137c478bd9Sstevel@tonic-gate decl_AddArg(decl_t *dp, decl_t *tp) {
16147c478bd9Sstevel@tonic-gate 	decl_t	*lastp = dp;
16157c478bd9Sstevel@tonic-gate 	decl_t	*p;
16167c478bd9Sstevel@tonic-gate 
16177c478bd9Sstevel@tonic-gate 	while (p = lastp->d_next)
16187c478bd9Sstevel@tonic-gate 		lastp = p;
16197c478bd9Sstevel@tonic-gate 
16207c478bd9Sstevel@tonic-gate 	lastp->d_next = tp;
16217c478bd9Sstevel@tonic-gate 
16227c478bd9Sstevel@tonic-gate 	return (dp);
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate 
16257c478bd9Sstevel@tonic-gate /*
16267c478bd9Sstevel@tonic-gate  * decl_IsVoid - return true if the decl_t is a "pure" void declaration.
16277c478bd9Sstevel@tonic-gate  */
16287c478bd9Sstevel@tonic-gate 
16297c478bd9Sstevel@tonic-gate static int
decl_IsVoid(decl_t * dp)16307c478bd9Sstevel@tonic-gate decl_IsVoid(decl_t *dp) {
16317c478bd9Sstevel@tonic-gate 	return ((declspec_GetSTT(dp->d_ds) & TS_VOID) && (dp->d_type == NULL));
16327c478bd9Sstevel@tonic-gate }
16337c478bd9Sstevel@tonic-gate 
16347c478bd9Sstevel@tonic-gate /*
16357c478bd9Sstevel@tonic-gate  * decl_IsVoidArray - return true if the decl_t includes "void []".
16367c478bd9Sstevel@tonic-gate  */
16377c478bd9Sstevel@tonic-gate 
16387c478bd9Sstevel@tonic-gate static int
decl_IsVoidArray(decl_t * dp)16397c478bd9Sstevel@tonic-gate decl_IsVoidArray(decl_t *dp) {
16407c478bd9Sstevel@tonic-gate 	int	 retval = 0;
16417c478bd9Sstevel@tonic-gate 	type_t	*tp = dp->d_type;
16427c478bd9Sstevel@tonic-gate 
16437c478bd9Sstevel@tonic-gate 	if (tp) {
16447c478bd9Sstevel@tonic-gate 		type_t	*np;
16457c478bd9Sstevel@tonic-gate 
16467c478bd9Sstevel@tonic-gate 		while (np = type_GetNext(tp))
16477c478bd9Sstevel@tonic-gate 			tp = np;
16487c478bd9Sstevel@tonic-gate 
16497c478bd9Sstevel@tonic-gate 		retval = type_IsArray(tp) &&
16507c478bd9Sstevel@tonic-gate 		    (declspec_GetSTT(dp->d_ds) & TS_VOID);
16517c478bd9Sstevel@tonic-gate 	}
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate 	return (retval);
16547c478bd9Sstevel@tonic-gate }
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate /*
16577c478bd9Sstevel@tonic-gate  * decl_Verify - verify a decl_t.
16587c478bd9Sstevel@tonic-gate  */
16597c478bd9Sstevel@tonic-gate 
16607c478bd9Sstevel@tonic-gate static const char *
decl_Verify(decl_t * dp)16617c478bd9Sstevel@tonic-gate decl_Verify(decl_t *dp) {
16627c478bd9Sstevel@tonic-gate 	const char	*ep = NULL;
16637c478bd9Sstevel@tonic-gate 
16647c478bd9Sstevel@tonic-gate 	if (decl_IsVoid(dp))
16657c478bd9Sstevel@tonic-gate 		ep = "type is void";
16667c478bd9Sstevel@tonic-gate 	else if (decl_IsVoidArray(dp))
16677c478bd9Sstevel@tonic-gate 		ep = "type is void []";
16687c478bd9Sstevel@tonic-gate 	else
16697c478bd9Sstevel@tonic-gate 		ep = type_Verify(dp->d_type);
16707c478bd9Sstevel@tonic-gate 
16717c478bd9Sstevel@tonic-gate 	return (ep);
16727c478bd9Sstevel@tonic-gate }
16737c478bd9Sstevel@tonic-gate 
16747c478bd9Sstevel@tonic-gate /*
16757c478bd9Sstevel@tonic-gate  * decl_VerifyArgs - verify a decl_t list.
16767c478bd9Sstevel@tonic-gate  */
16777c478bd9Sstevel@tonic-gate 
16787c478bd9Sstevel@tonic-gate static const char *
decl_VerifyArgs(decl_t * dp)16797c478bd9Sstevel@tonic-gate decl_VerifyArgs(decl_t *dp) {
16807c478bd9Sstevel@tonic-gate 	decl_t		*tp = dp;
16817c478bd9Sstevel@tonic-gate 	const char	*ep = NULL;
16827c478bd9Sstevel@tonic-gate 
16837c478bd9Sstevel@tonic-gate 	if (dp) {
16847c478bd9Sstevel@tonic-gate 		int	 nv = 0;
16857c478bd9Sstevel@tonic-gate 		int	 nargs = decl_GetArgLength(dp);
16867c478bd9Sstevel@tonic-gate 
16877c478bd9Sstevel@tonic-gate 		for (; dp; dp = dp->d_next)
16887c478bd9Sstevel@tonic-gate 			if (decl_IsVoid(dp)) {
16897c478bd9Sstevel@tonic-gate 				++nv;
16907c478bd9Sstevel@tonic-gate 
16917c478bd9Sstevel@tonic-gate 				if (decl_GetName(dp))
16927c478bd9Sstevel@tonic-gate 					ep = "argument list includes "
16937c478bd9Sstevel@tonic-gate 					    "void with identifier";
16947c478bd9Sstevel@tonic-gate 			} else if (decl_IsVoidArray(dp))
16957c478bd9Sstevel@tonic-gate 				ep = "argument list includes void []";
16967c478bd9Sstevel@tonic-gate 
16977c478bd9Sstevel@tonic-gate 		if (nv) {		/* there was some void */
16987c478bd9Sstevel@tonic-gate 			if (nargs > 1)
16997c478bd9Sstevel@tonic-gate 				ep = "argument list includes void";
17007c478bd9Sstevel@tonic-gate 
17017c478bd9Sstevel@tonic-gate 			if (tp->d_ellipsis)
17027c478bd9Sstevel@tonic-gate 				ep = "argument list includes void and \"...\"";
17037c478bd9Sstevel@tonic-gate 		}
17047c478bd9Sstevel@tonic-gate 	}
17057c478bd9Sstevel@tonic-gate 
17067c478bd9Sstevel@tonic-gate 	return (ep);
17077c478bd9Sstevel@tonic-gate }
17087c478bd9Sstevel@tonic-gate 
17097c478bd9Sstevel@tonic-gate /* decl_AddDS - add a decl_spec_t to a decl_t. */
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate static decl_t *
decl_AddDS(decl_t * dp,decl_spec_t * dsp,const char ** err)17127c478bd9Sstevel@tonic-gate decl_AddDS(decl_t *dp, decl_spec_t *dsp, const char **err) {
17137c478bd9Sstevel@tonic-gate 	declspec_AddDS(dp->d_ds, dsp, err);
17147c478bd9Sstevel@tonic-gate 
17157c478bd9Sstevel@tonic-gate 	return (dp);
17167c478bd9Sstevel@tonic-gate }
17177c478bd9Sstevel@tonic-gate 
17187c478bd9Sstevel@tonic-gate /*
17197c478bd9Sstevel@tonic-gate  * decl_SetName - set the name associated with a decl_t.
17207c478bd9Sstevel@tonic-gate  *
17217c478bd9Sstevel@tonic-gate  * Note:
17227c478bd9Sstevel@tonic-gate  *	1) Any previously known name is free'd.
17237c478bd9Sstevel@tonic-gate  */
17247c478bd9Sstevel@tonic-gate 
17257c478bd9Sstevel@tonic-gate decl_t *
decl_SetName(decl_t * dp,char * s)17267c478bd9Sstevel@tonic-gate decl_SetName(decl_t *dp, char *s) {
17277c478bd9Sstevel@tonic-gate 	free(dp->d_name);
17287c478bd9Sstevel@tonic-gate 	dp->d_name = strdup(s);
17297c478bd9Sstevel@tonic-gate 	assert(dp->d_name != NULL);
17307c478bd9Sstevel@tonic-gate 
17317c478bd9Sstevel@tonic-gate 	return (dp);
17327c478bd9Sstevel@tonic-gate }
17337c478bd9Sstevel@tonic-gate 
17347c478bd9Sstevel@tonic-gate /*
17357c478bd9Sstevel@tonic-gate  * decl_AddTypeTail - add a type_t to the end of a decl_t type_t list.
17367c478bd9Sstevel@tonic-gate  */
17377c478bd9Sstevel@tonic-gate 
17387c478bd9Sstevel@tonic-gate static decl_t *
decl_AddTypeTail(decl_t * dp,type_t * tp)17397c478bd9Sstevel@tonic-gate decl_AddTypeTail(decl_t *dp, type_t *tp) {
17407c478bd9Sstevel@tonic-gate 	if (dp->d_type)
17417c478bd9Sstevel@tonic-gate 		type_AddTail(dp->d_type, tp);
17427c478bd9Sstevel@tonic-gate 	else
17437c478bd9Sstevel@tonic-gate 		dp->d_type = tp;
17447c478bd9Sstevel@tonic-gate 
17457c478bd9Sstevel@tonic-gate 	return (dp);
17467c478bd9Sstevel@tonic-gate }
17477c478bd9Sstevel@tonic-gate 
17487c478bd9Sstevel@tonic-gate /*
17497c478bd9Sstevel@tonic-gate  * decl_addptr - add a DD_PTR type_t to the end of a decl_t type_t list.
17507c478bd9Sstevel@tonic-gate  */
17517c478bd9Sstevel@tonic-gate 
17527c478bd9Sstevel@tonic-gate static decl_t *
decl_addptr(decl_t * dp,type_t * tp)17537c478bd9Sstevel@tonic-gate decl_addptr(decl_t *dp, type_t *tp) {
17547c478bd9Sstevel@tonic-gate 	decl_AddTypeTail(dp, tp);
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 	return (dp);
17577c478bd9Sstevel@tonic-gate }
17587c478bd9Sstevel@tonic-gate 
17597c478bd9Sstevel@tonic-gate /*
17607c478bd9Sstevel@tonic-gate  * decl_addary - allocate and add a DD_ARY type_t to the end of
17617c478bd9Sstevel@tonic-gate  *	a decl_t type_t list.
17627c478bd9Sstevel@tonic-gate  */
17637c478bd9Sstevel@tonic-gate 
17647c478bd9Sstevel@tonic-gate static decl_t *
decl_addary(decl_t * dp,char * sizep)17657c478bd9Sstevel@tonic-gate decl_addary(decl_t *dp, char *sizep) {
17667c478bd9Sstevel@tonic-gate 	type_t	*tp = type_Construct();
17677c478bd9Sstevel@tonic-gate 
17687c478bd9Sstevel@tonic-gate 	type_SetAry(tp, sizep);
17697c478bd9Sstevel@tonic-gate 	decl_AddTypeTail(dp, tp);
17707c478bd9Sstevel@tonic-gate 
17717c478bd9Sstevel@tonic-gate 	return (dp);
17727c478bd9Sstevel@tonic-gate }
17737c478bd9Sstevel@tonic-gate 
17747c478bd9Sstevel@tonic-gate /*
17757c478bd9Sstevel@tonic-gate  * decl_addfun - allocate and add a DD_FUN type_t to the end of a
17767c478bd9Sstevel@tonic-gate  *	 decl_t type_t list.
17777c478bd9Sstevel@tonic-gate  */
17787c478bd9Sstevel@tonic-gate 
17797c478bd9Sstevel@tonic-gate static decl_t *
decl_addfun(decl_t * dp,decl_t * arglist)17807c478bd9Sstevel@tonic-gate decl_addfun(decl_t *dp, decl_t *arglist) {
17817c478bd9Sstevel@tonic-gate 	const char	*sp;
17827c478bd9Sstevel@tonic-gate 	type_t	*tp = type_Construct();
17837c478bd9Sstevel@tonic-gate 
17847c478bd9Sstevel@tonic-gate 	if (sp = decl_VerifyArgs(arglist))
17857c478bd9Sstevel@tonic-gate 		yyerror(sp);
17867c478bd9Sstevel@tonic-gate 
17877c478bd9Sstevel@tonic-gate 	type_SetFun(tp, arglist);
17887c478bd9Sstevel@tonic-gate 	decl_AddTypeTail(dp, tp);
17897c478bd9Sstevel@tonic-gate 
17907c478bd9Sstevel@tonic-gate 	return (dp);
17917c478bd9Sstevel@tonic-gate }
17927c478bd9Sstevel@tonic-gate 
17937c478bd9Sstevel@tonic-gate /*
17947c478bd9Sstevel@tonic-gate  * decl_addellipsis - set the ellipsis state in a decl_t.
17957c478bd9Sstevel@tonic-gate  *
17967c478bd9Sstevel@tonic-gate  * Note:
17977c478bd9Sstevel@tonic-gate  *	1) This function is only used in the grammar in the
17987c478bd9Sstevel@tonic-gate  *	   parameter list parsing.
17997c478bd9Sstevel@tonic-gate  */
18007c478bd9Sstevel@tonic-gate 
18017c478bd9Sstevel@tonic-gate static decl_t *
decl_addellipsis(decl_t * dp)18027c478bd9Sstevel@tonic-gate decl_addellipsis(decl_t *dp) {
18037c478bd9Sstevel@tonic-gate 	dp->d_ellipsis = 1;
18047c478bd9Sstevel@tonic-gate 
18057c478bd9Sstevel@tonic-gate 	return (dp);
18067c478bd9Sstevel@tonic-gate }
18077c478bd9Sstevel@tonic-gate 
18087c478bd9Sstevel@tonic-gate #if defined(DEBUG)
18097c478bd9Sstevel@tonic-gate 
18107c478bd9Sstevel@tonic-gate static void
decl_PrintDecl(decl_t * dp,int lvl)18117c478bd9Sstevel@tonic-gate decl_PrintDecl(decl_t *dp, int lvl) {
18127c478bd9Sstevel@tonic-gate 	char	buf[BUFSIZ];
18137c478bd9Sstevel@tonic-gate 
18147c478bd9Sstevel@tonic-gate 	while (dp) {
18157c478bd9Sstevel@tonic-gate 		putNTabs(lvl);
18167c478bd9Sstevel@tonic-gate 
18177c478bd9Sstevel@tonic-gate 		printf("name = %s, ds = %s\n",
18187c478bd9Sstevel@tonic-gate 				(dp->d_name)? dp->d_name : "<null>",
18197c478bd9Sstevel@tonic-gate 				declspec_ToString(buf, dp->d_ds));
18207c478bd9Sstevel@tonic-gate 
18217c478bd9Sstevel@tonic-gate 		if (dp->d_type)
18227c478bd9Sstevel@tonic-gate 			type_PrintType(dp->d_type, lvl + 1);
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate 		dp = dp->d_next;
18257c478bd9Sstevel@tonic-gate 	}
18267c478bd9Sstevel@tonic-gate }
18277c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
18287c478bd9Sstevel@tonic-gate 
18297c478bd9Sstevel@tonic-gate static char *
char_getend(char * s)18307c478bd9Sstevel@tonic-gate char_getend(char *s) {
18317c478bd9Sstevel@tonic-gate 	while (*s != '\0')
18327c478bd9Sstevel@tonic-gate 		++s;
18337c478bd9Sstevel@tonic-gate 
18347c478bd9Sstevel@tonic-gate 	return (s);
18357c478bd9Sstevel@tonic-gate }
18367c478bd9Sstevel@tonic-gate 
18377c478bd9Sstevel@tonic-gate char *
decl_ToString(char * bufp,decl_dts_t out,decl_t * dp,const char * altname)18387c478bd9Sstevel@tonic-gate decl_ToString(char *bufp, decl_dts_t out, decl_t *dp,
18397c478bd9Sstevel@tonic-gate     const char *altname) {
18407c478bd9Sstevel@tonic-gate 	char	 tmp[BUFSIZ];
18417c478bd9Sstevel@tonic-gate 	char	 tmp2[BUFSIZ];
18427c478bd9Sstevel@tonic-gate 	const char *namep;
18437c478bd9Sstevel@tonic-gate 	char	*bend = bufp;
18447c478bd9Sstevel@tonic-gate 	type_t	*tp = dp->d_type;
18457c478bd9Sstevel@tonic-gate 	int ffun = 1;
18467c478bd9Sstevel@tonic-gate 
18477c478bd9Sstevel@tonic-gate 	switch (out) {
18487c478bd9Sstevel@tonic-gate 	default:
18497c478bd9Sstevel@tonic-gate 		out = DTS_DECL;
18507c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
18517c478bd9Sstevel@tonic-gate 	case DTS_DECL:
18527c478bd9Sstevel@tonic-gate 		if (altname == NULL) {
18537c478bd9Sstevel@tonic-gate 			namep = dp->d_name;
18547c478bd9Sstevel@tonic-gate 		} else {
18557c478bd9Sstevel@tonic-gate 			namep = altname;
18567c478bd9Sstevel@tonic-gate 		}
18577c478bd9Sstevel@tonic-gate 		break;
18587c478bd9Sstevel@tonic-gate 	case DTS_CAST:
18597c478bd9Sstevel@tonic-gate 		namep = "(*)";
18607c478bd9Sstevel@tonic-gate 		break;
18617c478bd9Sstevel@tonic-gate 	case DTS_RET:
18627c478bd9Sstevel@tonic-gate 		if (altname == NULL) {
18637c478bd9Sstevel@tonic-gate 			namep = "_return";
18647c478bd9Sstevel@tonic-gate 		} else {
18657c478bd9Sstevel@tonic-gate 			namep = altname;
18667c478bd9Sstevel@tonic-gate 		}
18677c478bd9Sstevel@tonic-gate 		break;
18687c478bd9Sstevel@tonic-gate 	}
18697c478bd9Sstevel@tonic-gate 
18707c478bd9Sstevel@tonic-gate 	*bufp = '\0';
18717c478bd9Sstevel@tonic-gate 
18727c478bd9Sstevel@tonic-gate 	strcpy(tmp, (namep) ? namep : "");
18737c478bd9Sstevel@tonic-gate 
18747c478bd9Sstevel@tonic-gate 	while (tp) {
18757c478bd9Sstevel@tonic-gate 		switch (tp->t_dt) {
18767c478bd9Sstevel@tonic-gate 		case DD_PTR:
18777c478bd9Sstevel@tonic-gate 			if (tp->t_next &&
18787c478bd9Sstevel@tonic-gate 			    ((tp->t_next->t_dt == DD_ARY) ||
18797c478bd9Sstevel@tonic-gate 			    (tp->t_next->t_dt == DD_FUN))) {
18807c478bd9Sstevel@tonic-gate 				if (out == DTS_RET) {
18817c478bd9Sstevel@tonic-gate 					sprintf(bufp, "(*%s)", namep);
18827c478bd9Sstevel@tonic-gate 				} else {
18837c478bd9Sstevel@tonic-gate 					sprintf(bufp, "(*%s)", tmp);
18847c478bd9Sstevel@tonic-gate 				}
18857c478bd9Sstevel@tonic-gate 			} else if (tp->t_stt == TQ_CONST) {
18867c478bd9Sstevel@tonic-gate 				sprintf(bufp, "*const %s", tmp);
18877c478bd9Sstevel@tonic-gate 			} else if (tp->t_stt == TQ_VOLATILE) {
18887c478bd9Sstevel@tonic-gate 				sprintf(bufp, "*volatile %s", tmp);
18897c478bd9Sstevel@tonic-gate 			/*
18907c478bd9Sstevel@tonic-gate 			 * It currently acknowledges and ignores restrict
18917c478bd9Sstevel@tonic-gate 			 * or _RESTRICT_KYWD in code generation because
18927c478bd9Sstevel@tonic-gate 			 * of the uncertain behavior of "restrict".
18937c478bd9Sstevel@tonic-gate 			 */
18947c478bd9Sstevel@tonic-gate 			} else if (tp->t_stt == TQ_RESTRICT) {
18957c478bd9Sstevel@tonic-gate 				sprintf(bufp, "*%s", tmp);
18967c478bd9Sstevel@tonic-gate 			} else if (tp->t_stt == TQ_RESTRICT_KYWD) {
18977c478bd9Sstevel@tonic-gate 				sprintf(bufp, "*%s", tmp);
18987c478bd9Sstevel@tonic-gate 			} else {
18997c478bd9Sstevel@tonic-gate 				sprintf(bufp, "*%s", tmp);
19007c478bd9Sstevel@tonic-gate 			}
19017c478bd9Sstevel@tonic-gate 
19027c478bd9Sstevel@tonic-gate 			break;
19037c478bd9Sstevel@tonic-gate 
19047c478bd9Sstevel@tonic-gate 		case DD_ARY:
19057c478bd9Sstevel@tonic-gate 			sprintf(bufp, "%s[%s]",
19067c478bd9Sstevel@tonic-gate 			    tmp, (tp->t_sizestr)? tp->t_sizestr : "");
19077c478bd9Sstevel@tonic-gate 			break;
19087c478bd9Sstevel@tonic-gate 
19097c478bd9Sstevel@tonic-gate 		case DD_FUN:
19107c478bd9Sstevel@tonic-gate 			if (out == DTS_RET && ffun == 1) {
19117c478bd9Sstevel@tonic-gate 				strcpy(bufp, namep);
19127c478bd9Sstevel@tonic-gate 				ffun = 0;
19137c478bd9Sstevel@tonic-gate 			} else if (tp->t_args == NULL) {
19147c478bd9Sstevel@tonic-gate 				sprintf(bufp, "%s()", tmp);
19157c478bd9Sstevel@tonic-gate 			} else {
19167c478bd9Sstevel@tonic-gate 				char	 buf2[BUFSIZ];
19177c478bd9Sstevel@tonic-gate 				decl_t	*argp = tp->t_args;
19187c478bd9Sstevel@tonic-gate 
19197c478bd9Sstevel@tonic-gate 				sprintf(bufp, "%s(", tmp);
19207c478bd9Sstevel@tonic-gate 				bend = char_getend(bufp);
19217c478bd9Sstevel@tonic-gate 
19227c478bd9Sstevel@tonic-gate 				for (argp = tp->t_args; argp; /* noinc */) {
19237c478bd9Sstevel@tonic-gate 					decl_ToString(buf2, DTS_DECL, argp,
19247c478bd9Sstevel@tonic-gate 					    NULL);
19257c478bd9Sstevel@tonic-gate 					sprintf(bend, " %s", buf2);
19267c478bd9Sstevel@tonic-gate 
19277c478bd9Sstevel@tonic-gate 					bend = char_getend(bend);
19287c478bd9Sstevel@tonic-gate 
19297c478bd9Sstevel@tonic-gate 					if (argp = argp->d_next) {
19307c478bd9Sstevel@tonic-gate 						sprintf(bend, ",");
19317c478bd9Sstevel@tonic-gate 						bend = char_getend(bend);
19327c478bd9Sstevel@tonic-gate 					}
19337c478bd9Sstevel@tonic-gate 				}
19347c478bd9Sstevel@tonic-gate 
19357c478bd9Sstevel@tonic-gate 				if (tp->t_ellipsis) {
19367c478bd9Sstevel@tonic-gate 					sprintf(bend, ", ...");
19377c478bd9Sstevel@tonic-gate 					bend = char_getend(bend);
19387c478bd9Sstevel@tonic-gate 				}
19397c478bd9Sstevel@tonic-gate 
19407c478bd9Sstevel@tonic-gate 				sprintf(bend, ")");
19417c478bd9Sstevel@tonic-gate 			}
19427c478bd9Sstevel@tonic-gate 			break;
19437c478bd9Sstevel@tonic-gate 		}
19447c478bd9Sstevel@tonic-gate 
19457c478bd9Sstevel@tonic-gate 		tp = tp->t_next;
19467c478bd9Sstevel@tonic-gate 
19477c478bd9Sstevel@tonic-gate 		strcpy(tmp, bufp);
19487c478bd9Sstevel@tonic-gate 	}
19497c478bd9Sstevel@tonic-gate 
19507c478bd9Sstevel@tonic-gate 	if (out == DTS_CAST) {
19517c478bd9Sstevel@tonic-gate 		sprintf(bufp, "(%s %s)",
19527c478bd9Sstevel@tonic-gate 		    declspec_ToString(tmp2, dp->d_ds), tmp);
19537c478bd9Sstevel@tonic-gate 	} else {
19547c478bd9Sstevel@tonic-gate 		sprintf(bufp, "%s %s",
19557c478bd9Sstevel@tonic-gate 		    declspec_ToString(tmp2, dp->d_ds), tmp);
19567c478bd9Sstevel@tonic-gate 	}
19577c478bd9Sstevel@tonic-gate 
19587c478bd9Sstevel@tonic-gate 	return (bufp);
19597c478bd9Sstevel@tonic-gate }
19607c478bd9Sstevel@tonic-gate 
19617c478bd9Sstevel@tonic-gate decl_t *
decl_AddArgNames(decl_t * dp)19627c478bd9Sstevel@tonic-gate decl_AddArgNames(decl_t *dp) {
19637c478bd9Sstevel@tonic-gate 	int	 argno = 0;
19647c478bd9Sstevel@tonic-gate 	decl_t	*p = dp;
19657c478bd9Sstevel@tonic-gate 
19667c478bd9Sstevel@tonic-gate 	if (decl_IsFunction(dp)) {
19677c478bd9Sstevel@tonic-gate 		int	 argno = 0;
19687c478bd9Sstevel@tonic-gate 		decl_t	*p = dp->d_type->t_args;
19697c478bd9Sstevel@tonic-gate 
19707c478bd9Sstevel@tonic-gate 		while (p) {
19717c478bd9Sstevel@tonic-gate 			char	*s = decl_GetName(p);
19727c478bd9Sstevel@tonic-gate 
19737c478bd9Sstevel@tonic-gate 			if ((s == NULL) && !decl_IsVoid(p)) {
19747c478bd9Sstevel@tonic-gate 				char	buf[BUFSIZ];
19757c478bd9Sstevel@tonic-gate 
19767c478bd9Sstevel@tonic-gate 				sprintf(buf, "arg%d", argno);
19777c478bd9Sstevel@tonic-gate 				s = strdup(buf);
19787c478bd9Sstevel@tonic-gate 				decl_SetName(p, s);
19797c478bd9Sstevel@tonic-gate 			}
19807c478bd9Sstevel@tonic-gate 
19817c478bd9Sstevel@tonic-gate 			p = p->d_next;
19827c478bd9Sstevel@tonic-gate 			++argno;
19837c478bd9Sstevel@tonic-gate 		}
19847c478bd9Sstevel@tonic-gate 	}
19857c478bd9Sstevel@tonic-gate 	return (dp);
19867c478bd9Sstevel@tonic-gate }
19877c478bd9Sstevel@tonic-gate 
19887c478bd9Sstevel@tonic-gate const char *
decl_Parse(char * str,decl_t ** dpp)19897c478bd9Sstevel@tonic-gate decl_Parse(char *str, decl_t **dpp) {
19907c478bd9Sstevel@tonic-gate 	errstr = NULL;	/* setup the (static) globals */
19917c478bd9Sstevel@tonic-gate 	input = str;
19927c478bd9Sstevel@tonic-gate 	atIDENT = 0;
19937c478bd9Sstevel@tonic-gate 	protop = NULL;
19947c478bd9Sstevel@tonic-gate 
19957c478bd9Sstevel@tonic-gate 	yyparse();	/* parse the prototype */
19967c478bd9Sstevel@tonic-gate 
19977c478bd9Sstevel@tonic-gate 	if (errstr == NULL) {		/* success */
19987c478bd9Sstevel@tonic-gate 		*dpp = protop;
19997c478bd9Sstevel@tonic-gate 		decl_AddArgNames(protop);
20007c478bd9Sstevel@tonic-gate 	} else {	/* failure */
20017c478bd9Sstevel@tonic-gate 		*dpp = NULL;
20027c478bd9Sstevel@tonic-gate 		decl_Destroy(protop);
20037c478bd9Sstevel@tonic-gate 	}
20047c478bd9Sstevel@tonic-gate 
20057c478bd9Sstevel@tonic-gate 	return (errstr);
20067c478bd9Sstevel@tonic-gate }
20077c478bd9Sstevel@tonic-gate 
20087c478bd9Sstevel@tonic-gate static void
yyerror(const char * err)20097c478bd9Sstevel@tonic-gate yyerror(const char *err) {
20107c478bd9Sstevel@tonic-gate 	errstr = err;
20117c478bd9Sstevel@tonic-gate }
20127c478bd9Sstevel@tonic-gate 
20137c478bd9Sstevel@tonic-gate #if defined(DEBUG)
20147c478bd9Sstevel@tonic-gate 
20157c478bd9Sstevel@tonic-gate /* main */
20167c478bd9Sstevel@tonic-gate 
20177c478bd9Sstevel@tonic-gate static int yydebug = 1;
20187c478bd9Sstevel@tonic-gate 
20197c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])20207c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) {
20217c478bd9Sstevel@tonic-gate 	int	i;
20227c478bd9Sstevel@tonic-gate 
20237c478bd9Sstevel@tonic-gate 	yydebug = 1;
20247c478bd9Sstevel@tonic-gate 
20257c478bd9Sstevel@tonic-gate 	for (i = 1; i < argc; ++i) {
20267c478bd9Sstevel@tonic-gate 		const char	*es;
20277c478bd9Sstevel@tonic-gate 		char		 buf[BUFSIZ];
20287c478bd9Sstevel@tonic-gate 		decl_t		*pp;
20297c478bd9Sstevel@tonic-gate 
20307c478bd9Sstevel@tonic-gate 		if (es = decl_Parse(argv[i], &pp))
20317c478bd9Sstevel@tonic-gate 			printf("parse failure: %s\n", es);
20327c478bd9Sstevel@tonic-gate 		else {
20337c478bd9Sstevel@tonic-gate #if GR_DEBUG
20347c478bd9Sstevel@tonic-gate 			decl_PrintDecl(pp, 0);
20357c478bd9Sstevel@tonic-gate 			decl_AddArgNames(pp);
20367c478bd9Sstevel@tonic-gate #endif
20377c478bd9Sstevel@tonic-gate 			printf("---\n%s;\n",
20387c478bd9Sstevel@tonic-gate 			    decl_ToString(buf, DTS_DECL, pp, NULL));
20397c478bd9Sstevel@tonic-gate 			printf("%s\n",
20407c478bd9Sstevel@tonic-gate 			    decl_ToString(buf, DTS_CAST, pp, NULL));
20417c478bd9Sstevel@tonic-gate 			printf("%s;\n",
20427c478bd9Sstevel@tonic-gate 			    decl_ToString(buf, DTS_RET, pp, "%s"));
20437c478bd9Sstevel@tonic-gate 
20447c478bd9Sstevel@tonic-gate #ifdef TRACE
20457c478bd9Sstevel@tonic-gate 			printf("\n\nTrace Info\n");
20467c478bd9Sstevel@tonic-gate 			decl_PrintTraceInfo(pp);
20477c478bd9Sstevel@tonic-gate #endif
20487c478bd9Sstevel@tonic-gate 		}
20497c478bd9Sstevel@tonic-gate 
20507c478bd9Sstevel@tonic-gate 		decl_Destroy(pp);
20517c478bd9Sstevel@tonic-gate 
20527c478bd9Sstevel@tonic-gate #if defined(MEM_DEBUG)
20537c478bd9Sstevel@tonic-gate 		printf("declspec : %d\n", declspec_Construct_calls);
20547c478bd9Sstevel@tonic-gate 		printf("type     : %d\n", type_Construct_calls);
20557c478bd9Sstevel@tonic-gate 		printf("decl     : %d\n", decl_Construct_calls);
20567c478bd9Sstevel@tonic-gate #endif
20577c478bd9Sstevel@tonic-gate 	}
20587c478bd9Sstevel@tonic-gate 
20597c478bd9Sstevel@tonic-gate 	return (0);
20607c478bd9Sstevel@tonic-gate }
20617c478bd9Sstevel@tonic-gate 
20627c478bd9Sstevel@tonic-gate #ifdef TRACE
20637c478bd9Sstevel@tonic-gate void
decl_PrintTraceInfo(decl_t * dp)20647c478bd9Sstevel@tonic-gate decl_PrintTraceInfo(decl_t *dp) {
20657c478bd9Sstevel@tonic-gate 	char	buf[BUFSIZ];
20667c478bd9Sstevel@tonic-gate 	char	f_type[BUFSIZ];
20677c478bd9Sstevel@tonic-gate 	char	f_print[BUFSIZ];
20687c478bd9Sstevel@tonic-gate 	char	a_name[BUFSIZ];
20697c478bd9Sstevel@tonic-gate 	char	a_type[BUFSIZ];
20707c478bd9Sstevel@tonic-gate 	char	a_print[BUFSIZ];
20717c478bd9Sstevel@tonic-gate 	decl_t	*funargs;
20727c478bd9Sstevel@tonic-gate 	type_t	*tp;
20737c478bd9Sstevel@tonic-gate 	int	isptrfun;
20747c478bd9Sstevel@tonic-gate 
20757c478bd9Sstevel@tonic-gate 	if (dp == NULL)
20767c478bd9Sstevel@tonic-gate 		return;
20777c478bd9Sstevel@tonic-gate 
20787c478bd9Sstevel@tonic-gate 	fprintf(stderr, "interface = %s\n",
20797c478bd9Sstevel@tonic-gate 	    (dp->d_name) ? dp->d_name : "<null>");
20807c478bd9Sstevel@tonic-gate 
20817c478bd9Sstevel@tonic-gate 	isptrfun = type_IsPtrFun(dp->d_type);
20827c478bd9Sstevel@tonic-gate 	if (type_IsFunction(dp->d_type) || isptrfun)
20837c478bd9Sstevel@tonic-gate 		decl_GetTraceInfo(dp, f_type, f_print, &funargs);
20847c478bd9Sstevel@tonic-gate 	else
20857c478bd9Sstevel@tonic-gate 		return;
20867c478bd9Sstevel@tonic-gate 
20877c478bd9Sstevel@tonic-gate 	fprintf(stderr, "return type = %s\n", f_type);
20887c478bd9Sstevel@tonic-gate 	fprintf(stderr, "print function = %s\n", f_print);
20897c478bd9Sstevel@tonic-gate 
20907c478bd9Sstevel@tonic-gate 	if (isptrfun)
20917c478bd9Sstevel@tonic-gate 		fprintf(stderr, "function is function pointer\n");
20927c478bd9Sstevel@tonic-gate 
20937c478bd9Sstevel@tonic-gate 	if (type_IsVarargs(dp->d_type))
20947c478bd9Sstevel@tonic-gate 		fprintf(stderr, "function is varargs\n");
20957c478bd9Sstevel@tonic-gate 
20967c478bd9Sstevel@tonic-gate 	while (funargs) {
20977c478bd9Sstevel@tonic-gate 		snprintf(a_type, BUFSIZ, "%s ",
20987c478bd9Sstevel@tonic-gate 		    declspec_ToString(buf, funargs->d_ds));
20997c478bd9Sstevel@tonic-gate 		snprintf(a_print, BUFSIZ, "%s",
21007c478bd9Sstevel@tonic-gate 		    de_const(declspec_ToString(buf, funargs->d_ds)));
21017c478bd9Sstevel@tonic-gate 
21027c478bd9Sstevel@tonic-gate 		tp = funargs->d_type;
21037c478bd9Sstevel@tonic-gate 
21047c478bd9Sstevel@tonic-gate 		while (tp) {
21057c478bd9Sstevel@tonic-gate 			if (tp->t_dt == DD_PTR || tp->t_dt == DD_ARY) {
21067c478bd9Sstevel@tonic-gate 				strcat(a_type, "*");
21077c478bd9Sstevel@tonic-gate 				strcat(a_print, "_P");
21087c478bd9Sstevel@tonic-gate 			}
21097c478bd9Sstevel@tonic-gate 			tp = tp->t_next;
21107c478bd9Sstevel@tonic-gate 		}
21117c478bd9Sstevel@tonic-gate 
21127c478bd9Sstevel@tonic-gate 		if (funargs->d_name) {
21137c478bd9Sstevel@tonic-gate 			snprintf(a_name, BUFSIZ, "%s",
21147c478bd9Sstevel@tonic-gate 			    funargs->d_name ? funargs->d_name : "<nil>");
21157c478bd9Sstevel@tonic-gate 			fprintf(stderr, "arg name = %s\n", a_name);
21167c478bd9Sstevel@tonic-gate 			fprintf(stderr, "arg type = %s\n", a_type);
21177c478bd9Sstevel@tonic-gate 			fprintf(stderr, "print function = %s\n", a_print);
21187c478bd9Sstevel@tonic-gate 		} else {
21197c478bd9Sstevel@tonic-gate 			strcpy(a_name, "");
21207c478bd9Sstevel@tonic-gate 			strcpy(a_print, "");
21217c478bd9Sstevel@tonic-gate 			fprintf(stderr, "arg type = %s\n", a_type);
21227c478bd9Sstevel@tonic-gate 		}
21237c478bd9Sstevel@tonic-gate 
21247c478bd9Sstevel@tonic-gate 		funargs = funargs->d_next;
21257c478bd9Sstevel@tonic-gate 	}
21267c478bd9Sstevel@tonic-gate }
21277c478bd9Sstevel@tonic-gate #endif	/* TRACE */
21287c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
21297c478bd9Sstevel@tonic-gate 
21307c478bd9Sstevel@tonic-gate static char *
de_const(char * str)21317c478bd9Sstevel@tonic-gate de_const(char *str)
21327c478bd9Sstevel@tonic-gate {
21337c478bd9Sstevel@tonic-gate 	return (str);
21347c478bd9Sstevel@tonic-gate }
21357c478bd9Sstevel@tonic-gate 
21367c478bd9Sstevel@tonic-gate 
21377c478bd9Sstevel@tonic-gate void
decl_GetTraceInfo(decl_t * dp,char * f_type,char * f_print,decl_t ** funargs)21387c478bd9Sstevel@tonic-gate decl_GetTraceInfo(decl_t *dp, char *f_type, char *f_print, decl_t **funargs)
21397c478bd9Sstevel@tonic-gate {
21407c478bd9Sstevel@tonic-gate 	char	buf[BUFSIZ];
21417c478bd9Sstevel@tonic-gate 	type_t	*tp;
21427c478bd9Sstevel@tonic-gate 
21437c478bd9Sstevel@tonic-gate 	if (dp == NULL)
21447c478bd9Sstevel@tonic-gate 		return;
21457c478bd9Sstevel@tonic-gate 
21467c478bd9Sstevel@tonic-gate 	snprintf(f_type, BUFSIZ, "%s ",
21477c478bd9Sstevel@tonic-gate 	    declspec_ToString(buf, dp->d_ds));
21487c478bd9Sstevel@tonic-gate 	snprintf(f_print, BUFSIZ, "%s",
21497c478bd9Sstevel@tonic-gate 	    de_const(declspec_ToString(buf, dp->d_ds)));
21507c478bd9Sstevel@tonic-gate 	tp = dp->d_type;
21517c478bd9Sstevel@tonic-gate 	while (tp) {
21527c478bd9Sstevel@tonic-gate 		if (tp->t_dt == DD_PTR) {
21537c478bd9Sstevel@tonic-gate 			strcat(f_type, "*");
21547c478bd9Sstevel@tonic-gate 			strcat(f_print, "*");
21557c478bd9Sstevel@tonic-gate 		}
21567c478bd9Sstevel@tonic-gate 		tp = tp->t_next;
21577c478bd9Sstevel@tonic-gate 	}
21587c478bd9Sstevel@tonic-gate 
21597c478bd9Sstevel@tonic-gate 	strcat(f_type, "%s");
21607c478bd9Sstevel@tonic-gate 
21617c478bd9Sstevel@tonic-gate 	tp = decl_GetType(dp);
21627c478bd9Sstevel@tonic-gate 	if (type_IsPtrFun(tp)) {
21637c478bd9Sstevel@tonic-gate 		while (tp->t_dt != DD_FUN)
21647c478bd9Sstevel@tonic-gate 			tp = tp->t_next;
21657c478bd9Sstevel@tonic-gate 		*funargs = tp->t_args;
21667c478bd9Sstevel@tonic-gate 	} else {
21677c478bd9Sstevel@tonic-gate 		*funargs = dp->d_type->t_args;
21687c478bd9Sstevel@tonic-gate 	}
21697c478bd9Sstevel@tonic-gate }
21707c478bd9Sstevel@tonic-gate 
21717c478bd9Sstevel@tonic-gate char *
decl_ToFormal(decl_t * dp)21727c478bd9Sstevel@tonic-gate decl_ToFormal(decl_t *dp)
21737c478bd9Sstevel@tonic-gate {
21747c478bd9Sstevel@tonic-gate 	char tmp[BUFSIZ];
2175f07a2a2eScraigm 	static char bufp[BUFSIZ];
21767c478bd9Sstevel@tonic-gate 	char *bend;
21777c478bd9Sstevel@tonic-gate 	type_t	*tp = dp->d_type;
21787c478bd9Sstevel@tonic-gate 
21797c478bd9Sstevel@tonic-gate 	tmp[0] = 0;
21807c478bd9Sstevel@tonic-gate 	bufp[0] = 0;
21817c478bd9Sstevel@tonic-gate 	bend = bufp;
21827c478bd9Sstevel@tonic-gate 
21837c478bd9Sstevel@tonic-gate 	while (tp) {
21847c478bd9Sstevel@tonic-gate 		switch (tp->t_dt) {
21857c478bd9Sstevel@tonic-gate 		case DD_ARY:
21867c478bd9Sstevel@tonic-gate 			sprintf(bufp, "%s[%s]", tmp,
21877c478bd9Sstevel@tonic-gate 			    (tp->t_sizestr)? tp->t_sizestr : "");
21887c478bd9Sstevel@tonic-gate 			break;
21897c478bd9Sstevel@tonic-gate 
21907c478bd9Sstevel@tonic-gate 		case DD_FUN:
21917c478bd9Sstevel@tonic-gate 			if (tp->t_args != NULL) {
21927c478bd9Sstevel@tonic-gate 				char buf2[BUFSIZ];
21937c478bd9Sstevel@tonic-gate 				decl_t  *argp = tp->t_args;
21947c478bd9Sstevel@tonic-gate 
21957c478bd9Sstevel@tonic-gate 				bend = char_getend(bufp);
21967c478bd9Sstevel@tonic-gate 
21977c478bd9Sstevel@tonic-gate 				for (argp = tp->t_args; argp; /* noinc */) {
21987c478bd9Sstevel@tonic-gate 					decl_ToString(buf2, DTS_DECL, argp,
21997c478bd9Sstevel@tonic-gate 					    NULL);
22007c478bd9Sstevel@tonic-gate 					sprintf(bend, " %s", buf2);
22017c478bd9Sstevel@tonic-gate 
22027c478bd9Sstevel@tonic-gate 					bend    = char_getend(bend);
22037c478bd9Sstevel@tonic-gate 
22047c478bd9Sstevel@tonic-gate 					if (argp = argp->d_next) {
22057c478bd9Sstevel@tonic-gate 						sprintf(bend, ",");
22067c478bd9Sstevel@tonic-gate 						bend    = char_getend(bend);
22077c478bd9Sstevel@tonic-gate 					}
22087c478bd9Sstevel@tonic-gate 				}
22097c478bd9Sstevel@tonic-gate 				if (tp->t_ellipsis) {
22107c478bd9Sstevel@tonic-gate 					sprintf(bend, ", ...");
22117c478bd9Sstevel@tonic-gate 					bend    = char_getend(bend);
22127c478bd9Sstevel@tonic-gate 				}
22137c478bd9Sstevel@tonic-gate 
22147c478bd9Sstevel@tonic-gate 				sprintf(bend, "");
22157c478bd9Sstevel@tonic-gate 			}
22167c478bd9Sstevel@tonic-gate 			break;
22177c478bd9Sstevel@tonic-gate 		}
22187c478bd9Sstevel@tonic-gate 
22197c478bd9Sstevel@tonic-gate 		tp  = tp->t_next;
22207c478bd9Sstevel@tonic-gate 
22217c478bd9Sstevel@tonic-gate 		strcpy(tmp, bufp);
22227c478bd9Sstevel@tonic-gate 	}
22237c478bd9Sstevel@tonic-gate 
22247c478bd9Sstevel@tonic-gate 	sprintf(bufp, "%s", tmp);
22257c478bd9Sstevel@tonic-gate 
22267c478bd9Sstevel@tonic-gate 	return (bufp);
22277c478bd9Sstevel@tonic-gate }
2228