--- /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;
+}