]> git.draconx.ca Git - cdecl99.git/commitdiff
Replace typegen.sh with a new and improved script.
authorNick Bowler <nbowler@draconx.ca>
Wed, 10 Mar 2021 07:31:59 +0000 (02:31 -0500)
committerNick Bowler <nbowler@draconx.ca>
Wed, 10 Mar 2021 07:31:59 +0000 (02:31 -0500)
The old typegen.sh has a bunch of portability problems; let's write
a new script in awk which is a better tool for this sort of code
generation task anyway.

Makefile.am
test/declgen.c
test/gen-typegen.awk [new file with mode: 0755]
test/typegen.sh [deleted file]

index 44b4601c6c99e648eb46f708a29251495b17a1b3..82a6c0dfb3b6ff8400d29fd06efb58d36b608934 100644 (file)
@@ -24,12 +24,12 @@ MAINTAINERCLEANFILES = src/scan.c src/scan.h src/scan.stamp \
 DISTCLEANFILES =
 
 CLEANFILES = src/validtypes.h src/namespecs.h src/ordspecs.h \
-             test/typegen.h $(EXTRA_LTLIBRARIES)
+             $(EXTRA_LTLIBRARIES)
 
 EXTRA_DIST = bootstrap $(DX_BASEDIR)/scripts/fix-gnulib.pl m4/gnulib-cache.m4 \
              src/types.lst src/validtypes.sed src/specs.lst src/namespecs.sed \
-             src/ordspecs.sed test/typegen.sh src/parse.y src/parse.stamp \
-             src/scan.l src/scan.stamp COPYING.WTFPL2 README.md INSTALL
+             src/ordspecs.sed src/parse.y src/parse.stamp src/scan.l \
+             src/scan.stamp COPYING.WTFPL2 README.md INSTALL
 
 dist_man_MANS = doc/cdecl99.1 doc/libcdecl.3
 
@@ -106,11 +106,6 @@ src/ordspecs.h: $(srcdir)/src/specs.lst $(srcdir)/src/ordspecs.sed
                < $(srcdir)/src/specs.lst > $@.tmp
        $(AM_V_at) mv -f $@.tmp $@
 
-test/typegen.h: $(srcdir)/src/types.lst $(srcdir)/test/typegen.sh
-       $(AM_V_GEN) $(SHELL) $(srcdir)/test/typegen.sh \
-               < $(srcdir)/src/types.lst > $@.tmp
-       $(AM_V_at)mv -f $@.tmp $@
-
 # Supporting rules for gettext.
 include $(top_srcdir)/common/snippet/gettext.mk
 
@@ -219,6 +214,13 @@ src/cmdlist.h: src/gen-cmdlist.awk src/execute.c
 DISTCLEANFILES += src/cmdlist.h
 EXTRA_DIST += src/gen-cmdlist.awk
 
+test/typegen.h: test/gen-typegen.awk src/types.lst
+       $(AM_V_GEN) $(AWK) -f $(srcdir)/test/gen-typegen.awk \
+                             $(srcdir)/src/types.lst >$@.tmp
+       $(AM_V_at) mv -f $@.tmp $@
+DISTCLEANFILES += test/typegen.h
+EXTRA_DIST += test/gen-typegen.awk
+
 # Supporting rules for bison/flex.
 
 BISON_V   = $(BISON_V_@AM_V@)
index 4fb39cb52e26539d29df0749a1c8e24e508c07d0..c02613a23cd4cb632097c1176122838d521e876a 100644 (file)
@@ -150,21 +150,15 @@ struct cdecl_declspec *gen_storspecs(struct gen_rng *rng, bool registeronly)
  * Generate random type specifiers.  There is a short list of valid
  * combinations, from which we can select one uniformly at random.
  */
-static const unsigned long total_types;
-static struct cdecl_declspec *gen_raw_typespecs(struct gen_rng *rng)
-{
-       switch (gsl_rng_uniform_int(rng->rng, total_types)) {
-#      include "typegen.h"
-       }
-}
-static const unsigned long total_types = TOTAL_TYPES;
+#include "typegen.h"
 
 struct cdecl_declspec *gen_typespecs(struct gen_rng *rng, bool voidtype)
 {
        struct cdecl_declspec *specs;
 
 retry:
-       specs = gen_raw_typespecs(rng);
+       specs = gen_raw_typespecs(gsl_rng_uniform_int(rng->rng,
+                                                     GEN_TOTAL_TYPES));
 
        switch (specs->type) {
        /* void is not always valid, so we might need to pick again. */
diff --git a/test/gen-typegen.awk b/test/gen-typegen.awk
new file mode 100755 (executable)
index 0000000..0ae20f5
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/awk -f
+#
+# Copyright © 2021 Nick Bowler
+#
+# Generate a mapping from a (random) integer to a list of type specifiers
+# represented by struct cdecl_declspec.  Used internally by declgen to
+# produce random valid declarations.
+#
+# License WTFPL2: Do What The Fuck You Want To Public License, version 2.
+# This is free software: you are free to do what the fuck you want to.
+# There is NO WARRANTY, to the extent permitted by law.
+
+END {
+  print "/*"
+  if (FILENAME) {
+    print " * Automatically generated by gen-typegen.awk from " FILENAME
+  } else {
+    print " * Automatically generated by gen-typegen.awk"
+  }
+  print " * Do not edit."
+  print " */"
+}
+
+BEGIN {
+  count = 0
+}
+
+$0 ~ /^[abcdefghijklmnopqrstuvwxyz_]/ {
+  for (i = 1; i <= NF; i++) {
+    sub(/_/, "", $i)
+    $i = "CDECL_TYPE_" toupper($i)
+  }
+  specs[count++] = $0
+}
+
+END {
+  print "static inline struct cdecl_declspec *"
+  print "gen_raw_typespec_(unsigned type, struct cdecl_declspec *next)\n{"
+  print "\tstruct cdecl_declspec *s = malloc_nofail(sizeof *s);"
+  print "\t*s = (struct cdecl_declspec) { .next = next, .type = type };"
+  print "\treturn s;\n}\n"
+
+  print "static inline struct cdecl_declspec *"
+  print "gen_raw_typespecs(unsigned rngval)\n{"
+  print "\tswitch (rngval) {"
+
+  for (i = 0; i < count; i++) {
+    print "\tcase " i ":"
+    $0 = specs[i]
+
+    for (j = 1; j <= NF; j++) {
+      prefix = j == 1 ? "return" : "";
+
+      printf "\t\t%6s gen_raw_typespec_(%s,\n", prefix, $j
+    }
+    printf "\t\t%25sNULL%.*s;\n", "", NF, "))))))))"
+  }
+  print "\tdefault:\n\t\tassert(0);\n\t}"
+  print "}\n"
+  print "enum { GEN_TOTAL_TYPES = " count " };"
+}
diff --git a/test/typegen.sh b/test/typegen.sh
deleted file mode 100755 (executable)
index 1658d5d..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2011 Nick Bowler
-#
-# License WTFPL2: Do What The Fuck You Want To Public License, version 2.
-# This is free software: you are free to do what the fuck you want to.
-# There is NO WARRANTY, to the extent permitted by law.
-
-cat <<EOF
-/* This file was automatically generated by $0 $*. */
-struct cdecl_declspec *s, *p;
-EOF
-
-i=0
-while read line
-do
-       case "$line" in
-       [[:alpha:]_]*)
-               :
-               ;;
-       *)
-               printf '%s\n' "$line";
-               continue
-               ;;
-       esac
-
-       cat <<EOF
-case $i:
-       s = NULL;
-EOF
-
-       set $line
-       while test $# -gt 0
-       do
-               token=`printf '%s' "$1" | tr [:lower:] [:upper:] | tr -d _`
-               cat <<EOF
-       p = s;
-       s = malloc_nofail(sizeof *s);
-       *s = (struct cdecl_declspec) {
-               .type = CDECL_TYPE_$token,
-               .next = p,
-       };
-EOF
-               shift
-       done
-
-       i=`expr $i + 1`
-       cat <<EOF
-       return s;
-EOF
-done
-
-cat <<EOF
-default:
-       assert(0);
-#define TOTAL_TYPES $i
-EOF