#include <assert.h>
#include "cdecl.h"
+#include "typemap.h"
#include "parse.h"
#include "scan.h"
-#define PASTE(a, b) a ## b
-#define PASTE2(a, b) PASTE(a, b)
-
-#define BIT1(a) ((1ul<<(CDECL_TYPE_ ## a)))
-#define BIT2(a, b) ((1ul<<(CDECL_TYPE_ ## a))|(1ul<<(CDECL_TYPE_ ## b)))
-#define BIT3(a, b, c) ((1ul<<(CDECL_TYPE_ ## a))|(1ul<<(CDECL_TYPE_ ## b))|(1ul<<(CDECL_TYPE_ ## c)))
-#define BIT4(a, b, c, d) ((1ul<<(CDECL_TYPE_ ## a))|(1ul<<(CDECL_TYPE_ ## b))|(1ul<<(CDECL_TYPE_ ## c))|(1ul<<(CDECL_TYPE_ ## d)))
-
-#define NARG_(_4, _3, _2, _1, n, ...) n
-#define NARG(...) NARG_(__VA_ARGS__, 4, 3, 2, 1)
-
-#define BITS(...) PASTE2(BIT, NARG(__VA_ARGS__))(__VA_ARGS__)
-
-/*
- * We can represent type specifiers as a bitmap, which gives us a finite
- * list of acceptable bitmap values according to the C standard. However,
- * the "long" specifier is allowed to occur more than once, but only at most
- * 2 times. Treat it as a special case, assigning an unused bit to represent
- * the second long.
- */
-#define CDECL_TYPE_LLONG 32
-
-static int typemap_verify(unsigned long map)
-{
- /*
- * This is the complete list of valid type specifiers from C99§6.7.2#2
- */
-
- switch (map) {
- case BITS(VOID):
- case BITS(CHAR):
- case BITS(SIGNED, CHAR):
- case BITS(UNSIGNED, CHAR):
- case BITS(SHORT):
- case BITS(SIGNED, SHORT):
- case BITS(SHORT, INT):
- case BITS(SIGNED, SHORT, INT):
- case BITS(UNSIGNED, SHORT):
- case BITS(UNSIGNED, SHORT, INT):
- case BITS(INT):
- case BITS(SIGNED):
- case BITS(SIGNED, INT):
- case BITS(UNSIGNED):
- case BITS(UNSIGNED, INT):
- case BITS(LONG):
- case BITS(SIGNED, LONG):
- case BITS(SIGNED, LONG, INT):
- case BITS(UNSIGNED, LONG):
- case BITS(UNSIGNED, LONG, INT):
- case BITS(LLONG, LONG):
- case BITS(SIGNED, LLONG, LONG):
- case BITS(SIGNED, LLONG, LONG, INT):
- case BITS(UNSIGNED, LLONG, LONG):
- case BITS(UNSIGNED, LLONG, LONG, INT):
- case BITS(BOOL):
- case BITS(FLOAT):
- case BITS(DOUBLE):
- case BITS(LONG, DOUBLE):
- case BITS(FLOAT, COMPLEX):
- case BITS(DOUBLE, COMPLEX):
- case BITS(LONG, DOUBLE, COMPLEX):
- case BITS(STRUCT):
- case BITS(UNION):
- case BITS(ENUM):
- case BITS(IDENT):
- return 0;
- }
-
- return -1;
-}
-
-static unsigned long
-typemap_add_typespec(unsigned long map, struct cdecl_declspec *s)
+static int verify_specs(struct cdecl_declspec *s)
{
- assert(s->type < CDECL_TYPE_LLONG);
+ unsigned num_storage = 0;
+ unsigned long typemap;
- if (s->type == CDECL_TYPE_LONG) {
- if (map & BITS(LLONG)) {
- fprintf(stderr, "too many long specifiers\n");
- return -1;
- } else if (map & BITS(LONG)) {
- return map | BITS(LLONG);
- }
- }
+ typemap = cdecl__build_typemap(s);
+ if (typemap == -1)
+ return -1;
- if (map & (1ul<<s->type)) {
- fprintf(stderr, "duplicate type specifier\n");
+ if (!cdecl__typemap_is_valid(typemap)) {
+ fprintf(stderr, "conflicting type specifiers\n");
return -1;
}
- return map | (1<<s->type);
-}
-
-static int verify_specs(struct cdecl_declspec *s)
-{
- unsigned long typemap = 0;
- unsigned num_storage = 0;
-
for (struct cdecl_declspec *c = s; c; c = c->next) {
switch (cdecl_spec_kind(c)) {
case CDECL_SPEC_TYPE:
- typemap = typemap_add_typespec(typemap, c);
- if (typemap == -1) {
- return -1;
- }
- break;
+ continue;
case CDECL_SPEC_STOR:
if (++num_storage > 1) {
fprintf(stderr, "too many storage-class specifiers\n");
}
}
- if (typemap_verify(typemap) == -1) {
- fprintf(stderr, "conflicting type specifiers\n");
- return -1;
- }
-
return 0;
}
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+#include "cdecl.h"
+#include "typemap.h"
+
+/*
+ * We can represent type specifiers as a bitmap, which gives us a finite
+ * list of acceptable bitmap values according to the C standard. However,
+ * the "long" specifier is allowed to occur more than once, but only at most
+ * 2 times. Treat it as a special case, assigning an unused bit to represent
+ * the second long.
+ */
+#define CDECL_TYPE_LLONG 31
+
+static unsigned long add_typespec(unsigned long map, struct cdecl_declspec *s)
+{
+ if (s->type >= CDECL_TYPE_LLONG) {
+ fprintf(stderr, "invalid type specifier\n");
+ return -1;
+ }
+
+ if (s->type == CDECL_TYPE_LONG) {
+ if (map & (1ul<<CDECL_TYPE_LLONG)) {
+ fprintf(stderr, "too many long specifiers\n");
+ return -1;
+ } else if (map & (1ul<<CDECL_TYPE_LONG)) {
+ return map | (1ul<<CDECL_TYPE_LLONG);
+ }
+ }
+
+ if (map & (1ul<<s->type)) {
+ fprintf(stderr, "duplicate type specifier\n");
+ return -1;
+ }
+
+ return map | (1ul<<s->type);
+}
+
+bool cdecl__typemap_is_valid(unsigned long map)
+{
+ switch (map) {
+# include "validtypes.h"
+ return true;
+ }
+
+ return false;
+}
+
+unsigned long cdecl__build_typemap(struct cdecl_declspec *s)
+{
+ unsigned long map = 0;
+
+ for (struct cdecl_declspec *c = s; c; c = c->next) {
+ if (cdecl_spec_kind(c) != CDECL_SPEC_TYPE)
+ continue;
+
+ map = add_typespec(map, c);
+ if (map == -1)
+ break;
+ }
+
+ return map;
+}