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