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