]> git.draconx.ca Git - cdecl99.git/commitdiff
Move typemap stuff into a separate file.
authorNick Bowler <nbowler@draconx.ca>
Tue, 21 Jun 2011 22:29:30 +0000 (18:29 -0400)
committerNick Bowler <nbowler@draconx.ca>
Tue, 21 Jun 2011 22:29:30 +0000 (18:29 -0400)
These functions will be generally useful.  They are not part of the
public API, so we use the cdecl__ prefix for internal functions.

While we're at it, make the code easier to understand by automatically
generating the huge switch statement and eliminating the silly macros.

Makefile.am
src/.gitignore
src/parse-decl.c
src/typemap.c [new file with mode: 0644]
src/typemap.h [new file with mode: 0644]
src/validtypes.in [new file with mode: 0644]
src/validtypes.sed [new file with mode: 0644]

index 0caecb251b47390f03bb90eba2196136547b6aa7..8f82af4fabe34a0ec1a77838c00b461c9b4651a3 100644 (file)
@@ -9,8 +9,8 @@ include_HEADERS = src/cdecl.h
 noinst_HEADERS = src/scan.h src/parse.h
 
 lib_LTLIBRARIES = libcdecl.la
-libcdecl_la_LDFLAGS = -export-symbols-regex '^cdecl_'
-libcdecl_la_SOURCES = src/scan.c src/parse.c src/parse-decl.c
+libcdecl_la_LDFLAGS = -export-symbols-regex '^cdecl_[[:lower:]]'
+libcdecl_la_SOURCES = src/scan.c src/parse.c src/parse-decl.c src/typemap.c
 
 bin_PROGRAMS = cdecl99
 cdecl99_SOURCES = src/cdecl99.c
@@ -19,6 +19,12 @@ cdecl99_LDADD = libcdecl.la
 src/parse.lo: src/scan.h
 src/scan.lo: src/parse.h
 src/parse-decl.lo: src/scan.h src/parse.h
+src/typemap.lo: src/validtypes.h
+
+src/validtypes.h: src/validtypes.in $(srcdir)/src/validtypes.sed
+       $(AM_V_GEN)sed -f $(srcdir)/src/validtypes.sed \
+               < src/validtypes.in > $@.tmp
+       $(AM_V_at)mv -f $@.tmp $@
 
 # These are required to prevent the builtin lex/yacc rules from
 # superseding ours...
index 47a2c45b5c91c6b580cea2c30f56ffa326c07cf5..6cb92c656d9a810bf739d2f6cf32377963fafe41 100644 (file)
@@ -2,3 +2,4 @@ parse.stamp
 parse.[ch]
 scan.stamp
 scan.[ch]
+validtypes.h
index c06080b40328f16db118337ddd17b55303ca8982..e9756e390e4df54e485ff7a81a5aeea0fc8968f5 100644 (file)
 #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");
@@ -139,11 +52,6 @@ static int verify_specs(struct cdecl_declspec *s)
                }
        }
 
-       if (typemap_verify(typemap) == -1) {
-               fprintf(stderr, "conflicting type specifiers\n");
-               return -1;
-       }
-
        return 0;
 }
 
diff --git a/src/typemap.c b/src/typemap.c
new file mode 100644 (file)
index 0000000..0e5b41c
--- /dev/null
@@ -0,0 +1,63 @@
+#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;
+}
diff --git a/src/typemap.h b/src/typemap.h
new file mode 100644 (file)
index 0000000..285ff29
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef CDECL_TYPEMAP_H_
+#define CDECL_TYPEMAP_H_
+
+_Bool cdecl__typemap_is_valid(unsigned long map);
+unsigned long cdecl__build_typemap(struct cdecl_declspec *s);
+
+#endif
diff --git a/src/validtypes.in b/src/validtypes.in
new file mode 100644 (file)
index 0000000..f81b424
--- /dev/null
@@ -0,0 +1,39 @@
+/* The complete list of valid type specifiers according to C99§6.7.2#2 */
+void
+char
+signed char
+unsigned char
+short
+signed short
+short int
+signed short int
+unsigned short
+unsigned short int
+int
+signed
+signed int
+unsigned
+unsigned int
+long
+long int
+signed long
+signed long int
+unsigned long
+unsigned long int
+long long
+long long int
+signed long long
+signed long long int
+unsigned long long
+unsigned long long int
+bool
+float
+double
+long double
+float complex
+double complex
+long double complex
+struct
+union
+enum
+ident
diff --git a/src/validtypes.sed b/src/validtypes.sed
new file mode 100644 (file)
index 0000000..fd45fde
--- /dev/null
@@ -0,0 +1,8 @@
+1i\
+/* This file is automatically generated by validtypes.sed */
+/[^[:alpha:][:space:]]/b
+y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
+s/LONG[[:space:]][[:space:]]*LONG/LLONG LONG/
+s/[[:upper:]][[:upper:]]*/(1ul<<CDECL_TYPE_&)/g
+s/[[:space:]][[:space:]]*/|/g
+s/.*/case &:/