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 #include "parseproto.h"
30 #include <assert.h>
31
32 static decl_spec_t *declspec_Construct(void);
33 static void declspec_Destroy(decl_spec_t *);
34 static decl_spec_t *declspec_Init(stt_t, char *);
35 static char *declspec_VerifySTT(stt_t, stt_t);
36 static decl_spec_t *declspec_AddSTT(decl_spec_t *, stt_t, const char **);
37 static decl_spec_t *declspec_AddDS(decl_spec_t *,
38 decl_spec_t *, const char **);
39 static stt_t declspec_GetSTT(decl_spec_t *);
40 static char *declspec_GetTag(decl_spec_t *);
41 static type_t *type_Construct(void);
42 static void type_Destroy(type_t *);
43 static type_t *type_SetPtr(type_t *, stt_t);
44 static type_t *type_SetFun(type_t *, decl_t *);
45 static type_t *type_AddTail(type_t *, type_t *);
46 static const char *type_Verify(type_t *);
47
48 static decl_t *decl_Construct(void);
49 static decl_t *decl_AddArg(decl_t *, decl_t *);
50 static int decl_IsVoid(decl_t *);
51 static int decl_IsVoidArray(decl_t *);
52 static const char *decl_VerifyArgs(decl_t *);
53 static decl_t *decl_AddDS(decl_t *, decl_spec_t *, const char **);
54 static decl_t *decl_AddTypeTail(decl_t *, type_t *);
55 static decl_t *decl_addptr(decl_t *, type_t *);
56 static decl_t *decl_addary(decl_t *, char *);
57 static decl_t *decl_addfun(decl_t *, decl_t *);
58 static decl_t *decl_addellipsis(decl_t *);
59
60 #if defined(DEBUG)
61 static void type_PrintType(type_t *, int);
62 static void decl_PrintDecl(decl_t *, int);
63 static void decl_PrintTraceInfo(decl_t *);
64 static char *de_const(char *);
65 #endif
66
67
68
69 static int yylex(void);
70 static int yyerror(const char *);
71 static int yyparse(void);
72
73 #if defined(MEM_DEBUG)
74 static int declspec_Construct_calls;
75 static int type_Construct_calls;
76 static int decl_Construct_calls;
77 #endif
78
79 #if defined(DEBUG)
80 static char *de_const(char *);
81 #endif
82 %}
83
84 %union {
85 char *s_val;
86 int i_val;
87 stt_t stt_val;
88 decl_spec_t *ds_val;
89 type_t *t_val;
90 decl_t *d_val;
91 }
92
93 %token <i_val> ELLIPSIS
94
95 %token <s_val> INTEGER
96 %token <s_val> IDENTIFIER
97 %token <s_val> TYPEDEF_NAME
98 %type <s_val> constant_expression
99
100 %token <stt_val> REGISTER
101 %token <stt_val> TYPEDEF EXTERN AUTO STATIC
102 %token <stt_val> VOID CHAR SHORT INT LONG
103 %token <stt_val> FLOAT DOUBLE SIGNED UNSIGNED
104 %token <stt_val> CONST VOLATILE RESTRICT RESTRICT_KYWD
105 %type <stt_val> struct_or_union
106 %type <ds_val> storage_class_specifier
107 %type <ds_val> type_qualifier
108 %type <ds_val> type_qualifier_list
109
110 %token <ds_val> STRUCT UNION
111 %token <ds_val> ENUM
112 %type <ds_val> declaration_specifiers
113 %type <ds_val> type_specifier
114 %type <ds_val> struct_or_union_specifier enum_specifier
115 %type <ds_val> typedef_name
116
117 %type <t_val> pointer
118
119 %type <d_val> declaration
120 %type <d_val> init_declarator_list init_declarator
121 %type <d_val> declarator
122 %type <d_val> direct_declarator
123 %type <d_val> parameter_type_list parameter_list
124 %type <d_val> parameter_declaration
125 %type <d_val> abstract_declarator
126 %type <d_val> direct_abstract_declarator
127
128 %start declaration
129
130 %%
131
132 /*
133 * The grammar is derived from ANSI/ISO 9899-1990.
134 */
135
136 declaration
137 : declaration_specifiers init_declarator_list ';'
138 {
139 decl_t *dp;
140
141 protop = $$ = $2;
142
143 /* only one declaration allowed */
144 assert(protop->d_next == NULL);
145
146 for (dp = $2; dp && (errstr == NULL);
147 dp = dp->d_next) {
148 const char *sp;
149
150 decl_AddDS(dp, $1, &errstr);
151 if (sp = decl_Verify(dp))
152 errstr = sp;
153 }
154 declspec_Destroy($1);
155 }
156 | error ';'
157 {
158 protop = $$ = NULL;
159 errstr = "function prototype syntax error";
160 }
161 /*
162 * XXX - Does not support a "stand-alone" declaration specifier. It is
163 * essentially a type declaration, for example:
164 *
165 * typedef enum { FALSE = 0, TRUE = 1 } boolean_t;
166 * or
167 * struct _name { char *first; char *last };
168 */
169
170 /* XXX | declaration_specifiers */
171 ;
172
173 declaration_specifiers
174 : storage_class_specifier declaration_specifiers
175 {
176 char const *ep;
177
178 $$ = declspec_AddDS($2, $1, &ep);
179 declspec_Destroy($1);
180
181 if (errstr == NULL)
182 errstr = ep;
183 }
184 | storage_class_specifier
185 | type_specifier declaration_specifiers
186 {
187 const char *ep;
188
189 $$ = declspec_AddDS($2, $1, &ep);
190 declspec_Destroy($1);
191
192 if (errstr == NULL)
193 errstr = ep;
194 }
195 | type_specifier
196 | type_qualifier declaration_specifiers
197 {
198 const char *ep;
199
200 $$ = declspec_AddDS($2, $1, &ep);
201 declspec_Destroy($1);
202
203 if (errstr == NULL)
204 errstr = ep;
205 }
206 | type_qualifier
207 ;
208
209 storage_class_specifier
210 : REGISTER
211 {
212 $$ = declspec_Init(SCS_REGISTER, NULL);
213 }
214 /*
215 * XXX - Does not support any storage class specifier other than
216 * register, and then only for function arguments.
217 *
218 | TYPEDEF
219 {
220 $$ = declspec_Init(SCS_TYPEDEF, NULL);
221 }
222 | EXTERN
223 {
224 $$ = declspec_Init(SCS_EXTERN, NULL);
225 }
226 | STATIC
227 {
228 $$ = declspec_Init(SCS_STATIC, NULL);
229 }
230 | AUTO
231 {
232 $$ = declspec_Init(SCS_AUTO, NULL);
233 }
234 */
235 ;
236
237 type_specifier
238 : VOID
239 {
240 $$ = declspec_Init(TS_VOID, NULL);
241 atIDENT = 1;
242 }
243 | CHAR
244 {
245 $$ = declspec_Init(TS_CHAR, NULL);
246 atIDENT = 1;
247 }
248 | SHORT
249 {
250 $$ = declspec_Init(TS_SHORT, NULL);
251 atIDENT = 1;
252 }
253 | INT
254 {
255 $$ = declspec_Init(TS_INT, NULL);
256 atIDENT = 1;
257 }
258 | LONG
259 {
260 $$ = declspec_Init(TS_LONG, NULL);
261 atIDENT = 1;
262 }
263 | FLOAT
264 {
265 $$ = declspec_Init(TS_FLOAT, NULL);
266 atIDENT = 1;
267 }
268 | DOUBLE
269 {
270 $$ = declspec_Init(TS_DOUBLE, NULL);
271 atIDENT = 1;
272 }
273 | SIGNED
274 {
275 $$ = declspec_Init(TS_SIGNED, NULL);
276 atIDENT = 1;
277 }
278 | UNSIGNED
279 {
280 $$ = declspec_Init(TS_UNSIGNED, NULL);
281 atIDENT = 1;
282 }
283 | struct_or_union_specifier
284 | enum_specifier
285 | typedef_name
286 ;
287
288 typedef_name
289 : TYPEDEF_NAME
290 {
291 $$ = declspec_Init(TS_TYPEDEF, $1);
292 atIDENT = 1;
293 free($1);
294 }
295 ;
296
297 /*
298 * The "restrict" keyword is new in the C99 standard.
299 * It is type qualifier like const and volatile.
300 * We are using "_RESTRICT_KYWD" in headers and source code so
301 * it is easily turned on and off by various macros at compile time.
302 * In order for the "restrict" keyword to be recognized you must
303 * be using a C99 compliant compiler in its native mode.
304 */
305 type_qualifier
306 : CONST
307 {
308 $$ = declspec_Init(TQ_CONST, NULL);
309 }
310 | VOLATILE
311 {
312 $$ = declspec_Init(TQ_VOLATILE, NULL);
313 }
314 | RESTRICT
315 {
316 $$ = declspec_Init(TQ_RESTRICT, NULL);
317 }
318 | RESTRICT_KYWD
319 {
320 $$ = declspec_Init(TQ_RESTRICT_KYWD, NULL);
321 }
322 ;
323
324 struct_or_union_specifier
325 : struct_or_union { atIDENT = 1; } IDENTIFIER
326 {
327 $$ = declspec_Init($1, $3);
328 free($3);
329 }
330 /*
331 * XXX - struct or union definitions are not supported. It is generally
332 * not done within the context of a function declaration (prototype) or
333 * variable definition.
334
335 | struct_or_union IDENTIFIER '{' struct_declaration_list '}'
336 | struct_or_union '{' struct_declaration_list '}'
337 */
338 ;
339
340 struct_or_union
341 : STRUCT
342 {
343 $$ = TS_STRUCT;
344 }
345 | UNION
346 {
347 $$ = TS_UNION;
348 }
349 ;
350
351 init_declarator_list
352 : init_declarator
353 {
354 $$ = $1;
355 atIDENT = 1;
356 }
357 /*
358 * XXX - Does not support a comma separated list of declarations or
359 * definitions. Function prototypes or variable definitions must be
360 * given as one per C statement.
361
362 | init_declarator_list ',' init_declarator
363 {
364 $$ = decl_AddArg($1, $3);
365 atIDENT = 1;
366 }
367 */
368 ;
369
370 init_declarator
371 : declarator
372 /*
373 * XXX - Initialization is not supported.
374
375 | declarator '=' initializer
376 */
377 ;
378
379
380 enum_specifier
381 : ENUM { atIDENT = 1; } IDENTIFIER
382 {
383 $$ = declspec_Init(TS_ENUM, $3);
384 free($3);
385 }
386 /*
387 * XXX - enumerator definition is not supported for the same reasons
388 * struct|union definition is not supported.
389
390 | ENUM IDENTIFIER '{' enumerator_list '}'
391 | ENUM '{' enumerator_list '}'
392 */
393 ;
394
395
396 declarator
397 : pointer direct_declarator
398 {
399 $$ = decl_addptr($2, $1);
400 }
401 | direct_declarator
402 ;
403
404 direct_declarator
405 : IDENTIFIER
406 {
407 $$ = decl_SetName(decl_Construct(), $1);
408 atIDENT = 0;
409 free($1);
410 }
411 | '(' declarator ')'
412 {
413 $$ = $2;
414 }
415 | direct_declarator '[' constant_expression ']'
416 {
417 $$ = decl_addary($1, $3);
418 free($3);
419 }
420 | direct_declarator '[' ']'
421 {
422 $$ = decl_addary($1, NULL);
423 }
424 | direct_declarator '(' parameter_type_list ')'
425 {
426 $$ = decl_addfun($1, $3);
427 }
428 | direct_declarator '(' ')'
429 {
430 $$ = decl_addfun($1, NULL);
431 }
432 ;
433
434 pointer
435 : '*' type_qualifier_list
436 {
437 $$ = type_SetPtr(type_Construct(), ($2)->ds_stt);
438 declspec_Destroy($2);
439 }
440 | '*'
441 {
442 $$ = type_SetPtr(type_Construct(), TQ_NONE);
443 }
444 | '*' type_qualifier_list pointer
445 {
446 type_t *tp = type_Construct();
447
448 type_SetPtr(tp, ($2)->ds_stt);
449 declspec_Destroy($2);
450 $$ = type_AddTail($3, tp);
451 }
452 | '*' pointer
453 {
454 type_t *tp = type_Construct();
455
456 type_SetPtr(tp, TQ_NONE);
457 $$ = type_AddTail($2, tp);
458 }
459 ;
460
461 type_qualifier_list
462 : type_qualifier
463 | type_qualifier_list type_qualifier
464 {
465 const char *ep;
466
467 /* XXX - ignore any error */
468 $$ = declspec_AddDS($1, $2, &ep);
469 declspec_Destroy($2);
470 }
471 ;
472
473 parameter_type_list
474 : parameter_list
475 | parameter_list ',' ELLIPSIS
476 {
477 $$ = decl_addellipsis($1);
478 }
479 ;
480
481 parameter_list
482 : parameter_declaration
483 {
484 const char *sp = type_Verify($1->d_type);
485
486 if (sp)
487 errstr = sp;
488
489 $$ = $1;
490 atIDENT = 0;
491 }
492 | parameter_list ',' parameter_declaration
493 {
494 const char *sp = type_Verify($3->d_type);
495
496 if (sp)
497 errstr = sp;
498
499 $$ = decl_AddArg($1, $3);
500 atIDENT = 0;
501 }
502 ;
503
504 parameter_declaration
505 : declaration_specifiers declarator
506 {
507 const char *ep;
508
509 $$ = decl_AddDS($2, $1, &ep);
510 declspec_Destroy($1);
511
512 if (errstr == NULL)
513 errstr = ep;
514 }
515 | declaration_specifiers abstract_declarator
516 {
517 const char *ep;
518
519 $$ = decl_AddDS($2, $1, &ep);
520 declspec_Destroy($1);
521
522 if (errstr == NULL)
523 errstr = ep;
524 }
525 | declaration_specifiers
526 {
527 const char *ep;
528
529 $$ = decl_AddDS(decl_Construct(), $1, &ep);
530 declspec_Destroy($1);
531
532 if (errstr == NULL)
533 errstr = ep;
534 }
535 ;
536
537 abstract_declarator
538 : pointer
539 {
540 $$ = decl_addptr(decl_Construct(), $1);
541 }
542 | pointer direct_abstract_declarator
543 {
544 $$ = decl_addptr($2, $1);
545 }
546 | direct_abstract_declarator
547 ;
548
549 direct_abstract_declarator
550 : '(' abstract_declarator ')'
551 {
552 $$ = $2;
553 }
554 | direct_abstract_declarator '[' constant_expression ']'
555 {
556 $$ = decl_addary($1, $3);
557 free($3);
558 }
559 | '[' constant_expression ']'
560 {
561 $$ = decl_addary(decl_Construct(), $2);
562 free($2);
563 }
564 | direct_abstract_declarator '[' ']'
565 {
566 $$ = decl_addary($1, NULL);
567 }
568 | '[' ']'
569 {
570 $$ = decl_addary(decl_Construct(), NULL);
571 }
572 | direct_abstract_declarator '(' parameter_type_list ')'
573 {
574 $$ = decl_addfun($1, $3);
575 }
576 | '(' parameter_type_list ')'
577 {
578 $$ = decl_addfun(decl_Construct(), $2);
579 }
580 | direct_abstract_declarator '(' ')'
581 {
582 $$ = decl_addfun($1, NULL);
583 }
584 | '(' ')'
585 {
586 $$ = decl_addfun(decl_Construct(), NULL);
587 }
588 ;
589
590 /*
591 * XXX - General case constant expressions are not supported. It would
592 * be easy to implement (for the most part), but there are no cases to
593 * date that require such a facility. The grammar does allow an
594 * identifier (or typedef name) to be used since the prototype is not
595 * processed by CPP. The only integer constant that is supported is
596 * decimal.
597 */
598
599 constant_expression
600 : INTEGER
601 | IDENTIFIER
602 | TYPEDEF_NAME
603 ;
604
605 %%
606
607 /* Data Declarations */
608
609 typedef struct {
610 char *name;
611 int token;
612 stt_t stt;
613 } keyword_t;
614
615 typedef struct {
616 stt_t s_stt;
617 char *s_str;
618 } sttpair_t;
619
620 /* External Declarations */
621
622 static const keyword_t *lookup_keyword(const char *);
623 static const char *lookup_sttpair(stt_t);
624 static int getch(void);
625 static void ungetch(int);
626 static void skipwhitespace(void);
627 static int lookahead(int);
628 static void skipcomment(void);
629
630 /* External Definitions */
631
632 static char *input = NULL; /* current place in the input stream */
633 /* at point in stream were identifier is expected */
634 static int atIDENT = 0;
635 static decl_t *protop = NULL; /* pointer to prototype */
636 static const char *errstr = NULL; /* error message */
637
638 /*
639 * lookup_keyword - Given a string, return the keyword_t or NULL.
640 */
641
642 static const keyword_t *
lookup_keyword(const char * name)643 lookup_keyword(const char *name) {
644 static const keyword_t keytbl[] = {
645 { "register", REGISTER, SCS_REGISTER },
646 #if UNSUPPORTED
647 { "typedef", TYPEDEF, SCS_TYPEDEF },
648 { "auto", AUTO, SCS_AUTO },
649 { "static", STATIC, SCS_STATIC },
650 { "extern", EXTERN, SCS_EXTERN },
651 #endif /* UNSUPPORTED */
652 { "void", VOID, TS_VOID },
653 { "char", CHAR, TS_CHAR },
654 { "short", SHORT, TS_SHORT },
655 { "int", INT, TS_INT },
656 { "long", LONG, TS_LONG },
657 { "float", FLOAT, TS_FLOAT },
658 { "double", DOUBLE, TS_DOUBLE },
659 { "signed", SIGNED, TS_SIGNED },
660 { "unsigned", UNSIGNED, TS_UNSIGNED },
661 { "struct", STRUCT, TS_STRUCT },
662 { "union", UNION, TS_UNION },
663 { "enum", ENUM, TS_ENUM },
664
665 { "const", CONST, TQ_CONST },
666 { "volatile", VOLATILE, TQ_VOLATILE },
667 { "restrict", RESTRICT, TQ_RESTRICT },
668 { "_RESTRICT_KYWD",RESTRICT_KYWD, TQ_RESTRICT_KYWD},
669 };
670 #define NKEYWORD (sizeof (keytbl)/sizeof (keyword_t))
671
672 int i;
673
674 for (i = 0; i < NKEYWORD; ++i) {
675 char *s = keytbl[i].name;
676
677 if ((*s == *name) && (strcmp(s, name) == 0))
678 return (&keytbl[i]);
679 }
680
681 return (NULL);
682 }
683
684 /*
685 * lookup_sttpair - Given an stt_t return a string or NULL.
686 *
687 */
688
689 static const char *
lookup_sttpair(stt_t s)690 lookup_sttpair(stt_t s) {
691 /* valid type specifier combinations */
692 static const sttpair_t stttbl[] = {
693 { TS_VOID, "void" },
694 { TS_CHAR, "char" },
695 { TS_SIGNED | TS_CHAR, "signed char" },
696 { TS_UNSIGNED | TS_CHAR, "unsigned char" },
697 { TS_SHORT, "short" },
698 { TS_SIGNED | TS_SHORT, "signed short" },
699 { TS_SHORT | TS_INT, "short int" },
700 { TS_SIGNED | TS_SHORT | TS_INT,
701 "signed short int" },
702 { TS_UNSIGNED | TS_SHORT,
703 "unsigned short" },
704 { TS_UNSIGNED | TS_SHORT | TS_INT,
705 "unsigned short int" },
706 { TS_INT, "int" },
707 { TS_SIGNED, "signed" },
708 { TS_SIGNED | TS_INT, "signed int" },
709 { TS_NO_TS, "" },
710 { TS_UNSIGNED, "unsigned" },
711 { TS_UNSIGNED | TS_INT, "unsigned int" },
712 { TS_LONG, "long" },
713 { TS_SIGNED | TS_LONG, "signed long" },
714 { TS_LONG | TS_INT, "long int" },
715 { TS_SIGNED | TS_LONG | TS_INT,
716 "signed long int" },
717 { TS_UNSIGNED | TS_LONG, "unsigned long" },
718 { TS_UNSIGNED | TS_LONG | TS_INT,
719 "unsigned long int" },
720 { TS_FLOAT, "float" },
721 { TS_DOUBLE, "double" },
722 { TS_LONG | TS_DOUBLE, "long double" },
723 { TS_STRUCT, "struct" },
724 { TS_UNION, "union" },
725 { TS_ENUM, "enum" },
726 { TS_TYPEDEF, "" },
727 /* non-ANSI type: long long */
728 { TS_LONGLONG, "long long" },
729 { TS_LONGLONG | TS_INT, "long long int" },
730 { TS_SIGNED | TS_LONGLONG,
731 "signed long long" },
732 { TS_UNSIGNED | TS_LONGLONG,
733 "unsigned long long" },
734 { TS_SIGNED | TS_LONGLONG | TS_INT,
735 "signed long long int" },
736 { TS_UNSIGNED | TS_LONGLONG | TS_INT,
737 "unsigned long long int" },
738 };
739
740 #define NDECLSPEC (sizeof (stttbl)/sizeof (sttpair_t))
741
742 int i;
743
744 for (i = 0; i < NDECLSPEC; ++i)
745 if (s == stttbl[i].s_stt)
746 return (stttbl[i].s_str);
747
748 return (NULL);
749 }
750
751 /*
752 * yylex - return next token from the the input stream.
753 *
754 * The lexical analyzer does not recognize all possible C lexical
755 * elements. It only recognizes those associated with function
756 * declarations (read: prototypes) and data definitions.
757 */
758
759 static int
yylex(void)760 yylex(void) {
761 char buf[BUFSIZ]; /* string version of token */
762 int c;
763 int i = 0;
764
765 restart:
766 skipwhitespace();
767
768 switch (c = getch()) {
769 case '/':
770 if (lookahead('*')) {
771 skipcomment();
772 goto restart;
773 }
774 return (c);
775
776 case '.':
777 if (lookahead('.')) {
778 if (lookahead('.'))
779 return (ELLIPSIS);
780 }
781 return (c);
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 (void) 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 int
yyerror(const char * err)2009 yyerror(const char *err)
2010 {
2011 errstr = err;
2012 return (0);
2013 }
2014
2015 #if defined(DEBUG)
2016
2017 /* main */
2018
2019 static int yydebug = 1;
2020
2021 int
main(int argc,char * argv[])2022 main(int argc, char *argv[]) {
2023 int i;
2024
2025 yydebug = 1;
2026
2027 for (i = 1; i < argc; ++i) {
2028 const char *es;
2029 char buf[BUFSIZ];
2030 decl_t *pp;
2031
2032 if (es = decl_Parse(argv[i], &pp))
2033 printf("parse failure: %s\n", es);
2034 else {
2035 #if GR_DEBUG
2036 decl_PrintDecl(pp, 0);
2037 decl_AddArgNames(pp);
2038 #endif
2039 printf("---\n%s;\n",
2040 decl_ToString(buf, DTS_DECL, pp, NULL));
2041 printf("%s\n",
2042 decl_ToString(buf, DTS_CAST, pp, NULL));
2043 printf("%s;\n",
2044 decl_ToString(buf, DTS_RET, pp, "%s"));
2045
2046 #ifdef TRACE
2047 printf("\n\nTrace Info\n");
2048 decl_PrintTraceInfo(pp);
2049 #endif
2050 }
2051
2052 decl_Destroy(pp);
2053
2054 #if defined(MEM_DEBUG)
2055 printf("declspec : %d\n", declspec_Construct_calls);
2056 printf("type : %d\n", type_Construct_calls);
2057 printf("decl : %d\n", decl_Construct_calls);
2058 #endif
2059 }
2060
2061 return (0);
2062 }
2063
2064 #ifdef TRACE
2065 void
decl_PrintTraceInfo(decl_t * dp)2066 decl_PrintTraceInfo(decl_t *dp) {
2067 char buf[BUFSIZ];
2068 char f_type[BUFSIZ];
2069 char f_print[BUFSIZ];
2070 char a_name[BUFSIZ];
2071 char a_type[BUFSIZ];
2072 char a_print[BUFSIZ];
2073 decl_t *funargs;
2074 type_t *tp;
2075 int isptrfun;
2076
2077 if (dp == NULL)
2078 return;
2079
2080 fprintf(stderr, "interface = %s\n",
2081 (dp->d_name) ? dp->d_name : "<null>");
2082
2083 isptrfun = type_IsPtrFun(dp->d_type);
2084 if (type_IsFunction(dp->d_type) || isptrfun)
2085 decl_GetTraceInfo(dp, f_type, f_print, &funargs);
2086 else
2087 return;
2088
2089 fprintf(stderr, "return type = %s\n", f_type);
2090 fprintf(stderr, "print function = %s\n", f_print);
2091
2092 if (isptrfun)
2093 fprintf(stderr, "function is function pointer\n");
2094
2095 if (type_IsVarargs(dp->d_type))
2096 fprintf(stderr, "function is varargs\n");
2097
2098 while (funargs) {
2099 snprintf(a_type, BUFSIZ, "%s ",
2100 declspec_ToString(buf, funargs->d_ds));
2101 snprintf(a_print, BUFSIZ, "%s",
2102 de_const(declspec_ToString(buf, funargs->d_ds)));
2103
2104 tp = funargs->d_type;
2105
2106 while (tp) {
2107 if (tp->t_dt == DD_PTR || tp->t_dt == DD_ARY) {
2108 strcat(a_type, "*");
2109 strcat(a_print, "_P");
2110 }
2111 tp = tp->t_next;
2112 }
2113
2114 if (funargs->d_name) {
2115 snprintf(a_name, BUFSIZ, "%s",
2116 funargs->d_name ? funargs->d_name : "<nil>");
2117 fprintf(stderr, "arg name = %s\n", a_name);
2118 fprintf(stderr, "arg type = %s\n", a_type);
2119 fprintf(stderr, "print function = %s\n", a_print);
2120 } else {
2121 strcpy(a_name, "");
2122 strcpy(a_print, "");
2123 fprintf(stderr, "arg type = %s\n", a_type);
2124 }
2125
2126 funargs = funargs->d_next;
2127 }
2128 }
2129 #endif /* TRACE */
2130 #endif /* DEBUG */
2131
2132 static char *
de_const(char * str)2133 de_const(char *str)
2134 {
2135 return (str);
2136 }
2137
2138
2139 void
decl_GetTraceInfo(decl_t * dp,char * f_type,char * f_print,decl_t ** funargs)2140 decl_GetTraceInfo(decl_t *dp, char *f_type, char *f_print, decl_t **funargs)
2141 {
2142 char buf[BUFSIZ];
2143 type_t *tp;
2144
2145 if (dp == NULL)
2146 return;
2147
2148 snprintf(f_type, BUFSIZ, "%s ",
2149 declspec_ToString(buf, dp->d_ds));
2150 snprintf(f_print, BUFSIZ, "%s",
2151 de_const(declspec_ToString(buf, dp->d_ds)));
2152 tp = dp->d_type;
2153 while (tp) {
2154 if (tp->t_dt == DD_PTR) {
2155 strcat(f_type, "*");
2156 strcat(f_print, "*");
2157 }
2158 tp = tp->t_next;
2159 }
2160
2161 strcat(f_type, "%s");
2162
2163 tp = decl_GetType(dp);
2164 if (type_IsPtrFun(tp)) {
2165 while (tp->t_dt != DD_FUN)
2166 tp = tp->t_next;
2167 *funargs = tp->t_args;
2168 } else {
2169 *funargs = dp->d_type->t_args;
2170 }
2171 }
2172
2173 char *
decl_ToFormal(decl_t * dp)2174 decl_ToFormal(decl_t *dp)
2175 {
2176 char tmp[BUFSIZ];
2177 static char bufp[BUFSIZ];
2178 char *bend;
2179 type_t *tp = dp->d_type;
2180
2181 tmp[0] = 0;
2182 bufp[0] = 0;
2183 bend = bufp;
2184
2185 while (tp) {
2186 switch (tp->t_dt) {
2187 case DD_ARY:
2188 sprintf(bufp, "%s[%s]", tmp,
2189 (tp->t_sizestr)? tp->t_sizestr : "");
2190 break;
2191
2192 case DD_FUN:
2193 if (tp->t_args != NULL) {
2194 char buf2[BUFSIZ];
2195 decl_t *argp = tp->t_args;
2196
2197 bend = char_getend(bufp);
2198
2199 for (argp = tp->t_args; argp; /* noinc */) {
2200 decl_ToString(buf2, DTS_DECL, argp,
2201 NULL);
2202 sprintf(bend, " %s", buf2);
2203
2204 bend = char_getend(bend);
2205
2206 if (argp = argp->d_next) {
2207 sprintf(bend, ",");
2208 bend = char_getend(bend);
2209 }
2210 }
2211 if (tp->t_ellipsis) {
2212 sprintf(bend, ", ...");
2213 bend = char_getend(bend);
2214 }
2215
2216 sprintf(bend, "");
2217 }
2218 break;
2219 }
2220
2221 tp = tp->t_next;
2222
2223 strcpy(tmp, bufp);
2224 }
2225
2226 sprintf(bufp, "%s", tmp);
2227
2228 return (bufp);
2229 }
2230