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