]> git.draconx.ca Git - cdecl99.git/blob - src/gen-specstr.awk
libcdecl: Re-use strings from parser in spec_string.
[cdecl99.git] / src / gen-specstr.awk
1 #!/bin/awk -f
2 #
3 # Copyright © 2021, 2023 Nick Bowler
4 #
5 # Generate a function to return the C keyword corresponding to a specifier
6 # type as a string, for internal use by the output routines.
7 #
8 # License WTFPL2: Do What The Fuck You Want To Public License, version 2.
9 # This is free software: you are free to do what the fuck you want to.
10 # There is NO WARRANTY, to the extent permitted by law.
11
12 END {
13   print "/*";
14   if (FILENAME) {
15     print " * Automatically generated by gen-specstr.awk from " FILENAME;
16   } else {
17     print " * Automatically generated by gen-specstr.awk";
18   }
19   print " * Do not edit.";
20   print " */";
21 }
22
23 BEGIN {
24   kinds["TYPE"] = kinds["STOR"] = kinds["QUAL"] = kinds["FUNC"] = 1;
25   count = maxwidth = 0;
26 }
27
28 # Locate all the relevant identifiers in cdecl.h.  We assume everything
29 # is in numerically increasing order within the various enums.
30 $1 ~ /^CDECL_/ {
31   sub(/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ_].*/, "", $1);
32
33   split($1, parts, "_");
34   if (parts[2] == "SPEC") {
35     x = $0;
36     sub(/^.*= */, "", x);
37     sub(/,? *$/, "", x);
38
39     x = int(x / 512) % 8;
40     if (skiptab[x]) {
41       print "cannot create skip table";
42       exit 1;
43     }
44
45     skiptab[x] = parts[3];
46   }
47
48   if (parts[2] in kinds) {
49     kind_counts[parts[2]]++;
50     specs[count++] = parts[3];
51
52     if (length(parts[3]) > maxwidth)
53       maxwidth = length(parts[3]);
54   }
55 }
56
57 END {
58   # Create the token table.  The first 5 entries key off of bits 9 through 11,
59   # which is sufficient to distinguish the different specifier kinds and is
60   # used to partition the rest of the token table.
61   skip_count = 0;
62   for (i in skiptab) {
63     if (skip_count < i)
64       skip_count = i;
65   }
66
67   skip_pos = ++skip_count;
68   for (i = 0; i < skip_count; i++) {
69     offset_table = offset_table skip_pos ", ";
70     skip_pos += kind_counts[skiptab[i]];
71   }
72   sub(/ $/, "\n\t\t", offset_table);
73
74   for (i = 0; i < count; i++) {
75     suffix = "";
76     if (i+1 < count)
77       suffix = ",\n\t\t";
78
79     if (specs[i] == "IDENT")
80       s = "0";
81     else
82       s = "T_" substr(specs[i] "                ", 1, maxwidth) " - 256";
83     offset_table = offset_table s suffix;
84   }
85
86   print "static const char *spec_string(unsigned type)"
87   print "{"
88   print "\tstatic const uint_least8_t idx[] = {";
89   print "\t\t" offset_table;
90   print "\t};\n";
91
92   print "\tunsigned x = (type & 0xff) + idx[type >> 9];";
93   print "\tassert(x < sizeof idx);";
94   print "\tif (!(x = idx[x]))";
95   print "\t\treturn \"\";";
96   print "\treturn cdecl__token_name(x + 256);";
97   print "}";
98 }