]> git.draconx.ca Git - cdecl99.git/blob - src/typemap.c
Move typemap stuff into a separate file.
[cdecl99.git] / src / typemap.c
1 #include <stdio.h>
2 #include <stdbool.h>
3 #include "cdecl.h"
4 #include "typemap.h"
5
6 /*
7  * We can represent type specifiers as a bitmap, which gives us a finite
8  * list of acceptable bitmap values according to the C standard.  However,
9  * the "long" specifier is allowed to occur more than once, but only at most
10  * 2 times.  Treat it as a special case, assigning an unused bit to represent
11  * the second long.
12  */
13 #define CDECL_TYPE_LLONG 31
14
15 static unsigned long add_typespec(unsigned long map, struct cdecl_declspec *s)
16 {
17         if (s->type >= CDECL_TYPE_LLONG) {
18                 fprintf(stderr, "invalid type specifier\n");
19                 return -1;
20         }
21
22         if (s->type == CDECL_TYPE_LONG) {
23                 if (map & (1ul<<CDECL_TYPE_LLONG)) {
24                         fprintf(stderr, "too many long specifiers\n");
25                         return -1;
26                 } else if (map & (1ul<<CDECL_TYPE_LONG)) {
27                         return map | (1ul<<CDECL_TYPE_LLONG);
28                 }
29         }
30
31         if (map & (1ul<<s->type)) {
32                 fprintf(stderr, "duplicate type specifier\n");
33                 return -1;
34         }
35
36         return map | (1ul<<s->type);
37 }
38
39 bool cdecl__typemap_is_valid(unsigned long map)
40 {
41         switch (map) {
42 #       include "validtypes.h"
43                 return true;
44         }
45
46         return false;
47 }
48
49 unsigned long cdecl__build_typemap(struct cdecl_declspec *s)
50 {
51         unsigned long map = 0;
52
53         for (struct cdecl_declspec *c = s; c; c = c->next) {
54                 if (cdecl_spec_kind(c) != CDECL_SPEC_TYPE)
55                         continue;
56
57                 map = add_typespec(map, c);
58                 if (map == -1)
59                         break;
60         }
61
62         return map;
63 }