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