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)1257