]> git.draconx.ca Git - cdecl99.git/blob - src/parse-decl.c
Rename libcdecl.c to parse-decl.c
[cdecl99.git] / src / parse-decl.c
1 #include <stdio.h>
2 #include <assert.h>
3
4 #include "cdecl.h"
5 #include "parse.h"
6 #include "scan.h"
7
8 #define PASTE(a, b) a ## b
9 #define PASTE2(a, b) PASTE(a, b)
10
11 #define BIT1(a)          ((1ul<<(CDECL_TYPE_ ## a)))
12 #define BIT2(a, b)       ((1ul<<(CDECL_TYPE_ ## a))|(1ul<<(CDECL_TYPE_ ## b)))
13 #define BIT3(a, b, c)    ((1ul<<(CDECL_TYPE_ ## a))|(1ul<<(CDECL_TYPE_ ## b))|(1ul<<(CDECL_TYPE_ ## c)))
14 #define BIT4(a, b, c, d) ((1ul<<(CDECL_TYPE_ ## a))|(1ul<<(CDECL_TYPE_ ## b))|(1ul<<(CDECL_TYPE_ ## c))|(1ul<<(CDECL_TYPE_ ## d)))
15
16 #define NARG_(_4, _3, _2, _1, n, ...) n
17 #define NARG(...) NARG_(__VA_ARGS__, 4, 3, 2, 1)
18
19 #define BITS(...) PASTE2(BIT, NARG(__VA_ARGS__))(__VA_ARGS__)
20
21 /*
22  * We can represent type specifiers as a bitmap, which gives us a finite
23  * list of acceptable bitmap values according to the C standard.  However,
24  * the "long" specifier is allowed to occur more than once, but only at most
25  * 2 times.  Treat it as a special case, assigning an unused bit to represent
26  * the second long.
27  */
28 #define CDECL_TYPE_LLONG       32
29
30 static int typemap_verify(unsigned long map)
31 {
32         /*
33          * This is the complete list of valid type specifiers from C99ยง6.7.2#2
34          */
35
36         switch (map) {
37         case BITS(VOID):
38         case BITS(CHAR):
39         case BITS(SIGNED, CHAR):
40         case BITS(UNSIGNED, CHAR):
41         case BITS(SHORT):
42         case BITS(SIGNED, SHORT):
43         case BITS(SHORT, INT):
44         case BITS(SIGNED, SHORT, INT):
45         case BITS(UNSIGNED, SHORT):
46         case BITS(UNSIGNED, SHORT, INT):
47         case BITS(INT):
48         case BITS(SIGNED):
49         case BITS(SIGNED, INT):
50         case BITS(UNSIGNED):
51         case BITS(UNSIGNED, INT):
52         case BITS(LONG):
53         case BITS(SIGNED, LONG):
54         case BITS(SIGNED, LONG, INT):
55         case BITS(UNSIGNED, LONG):
56         case BITS(UNSIGNED, LONG, INT):
57         case BITS(LLONG, LONG):
58         case BITS(SIGNED, LLONG, LONG):
59         case BITS(SIGNED, LLONG, LONG, INT):
60         case BITS(UNSIGNED, LLONG, LONG):
61         case BITS(UNSIGNED, LLONG, LONG, INT):
62         case BITS(BOOL):
63         case BITS(FLOAT):
64         case BITS(DOUBLE):
65         case BITS(LONG, DOUBLE):
66         case BITS(FLOAT, COMPLEX):
67         case BITS(DOUBLE, COMPLEX):
68         case BITS(LONG, DOUBLE, COMPLEX):
69         case BITS(STRUCT):
70         case BITS(UNION):
71         case BITS(ENUM):
72         case BITS(IDENT):
73                 return 0;
74         }
75
76         return -1;
77 }
78
79 static unsigned long
80 typemap_add_typespec(unsigned long map, struct cdecl_declspec *s)
81 {
82         assert(s->type < CDECL_TYPE_LLONG);
83
84         if (s->type == CDECL_TYPE_LONG) {
85                 if (map & BITS(LLONG)) {
86                         fprintf(stderr, "too many long specifiers\n");
87                         return -1;
88                 } else if (map & BITS(LONG)) {
89                         return map | BITS(LLONG);
90                 }
91         }
92
93         if (map & (1ul<<s->type)) {
94                 fprintf(stderr, "duplicate type specifier\n");
95                 return -1;
96         }
97
98         return map | (1<<s->type);
99 }
100
101 static int verify_specs(struct cdecl_declspec *s)
102 {
103         unsigned long typemap = 0;
104         unsigned num_storage = 0;
105
106         for (struct cdecl_declspec *c = s; c; c = c->next) {
107                 switch (cdecl_spec_kind(c)) {
108                 case CDECL_SPEC_TYPE:
109                         typemap = typemap_add_typespec(typemap, c);
110                         if (typemap == -1) {
111                                 return -1;
112                         }
113                         break;
114                 case CDECL_SPEC_STOR:
115                         if (++num_storage > 1) {
116                                 fprintf(stderr, "too many storage-class specifiers\n");
117                                 return -1;
118                         }
119                         break;
120                 case CDECL_SPEC_QUAL:
121                         /*
122                          * Since we don't support pointer types yet, all
123                          * restrict qualifiers are invalid.  Other qualifiers
124                          * are always valid.
125                          */
126                         if (c->type == CDECL_QUAL_RESTRICT) {
127                                 fprintf(stderr, "only pointer types can be restrict-qualified.\n");
128                                 return -1;
129                         }
130                         break;
131                 case CDECL_SPEC_FUNC:
132                         /*
133                          * Likewise for function specifiers.
134                          */
135                         fprintf(stderr, "only function declarations may have function specifiers.\n");
136                         return -1;
137                 default:
138                         abort();
139                 }
140         }
141
142         if (typemap_verify(typemap) == -1) {
143                 fprintf(stderr, "conflicting type specifiers\n");
144                 return -1;
145         }
146
147         return 0;
148 }
149
150 static int verify_decl(struct cdecl *decl)
151 {
152         return verify_specs(decl->specifiers);
153 }
154
155 struct cdecl *cdecl_parse_decl(const char *declstr)
156 {
157         YY_BUFFER_STATE state;
158         struct cdecl *decl;
159         int rc;
160
161         state = yy_scan_string(declstr);
162         rc = yyparse(&decl);
163         yy_delete_buffer(state);
164
165         if (rc != 0)
166                 return NULL;
167
168         rc = verify_decl(decl);
169         if (rc != 0) {
170                 cdecl_free(decl);
171                 return NULL;
172         }
173
174         return decl;
175 }