]> git.draconx.ca Git - cdecl99.git/blob - src/gen-specstr.awk
Release 1.3.
[cdecl99.git] / src / gen-specstr.awk
1 #!/bin/awk -f
2 #
3 # Copyright © 2021, 2023-2024 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 = 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 }
53
54 END {
55   # Create the token table.  The first 5 entries key off of bits 9 through 11,
56   # which is sufficient to distinguish the different specifier kinds and is
57   # used to partition the rest of the token table.
58   skip_count = 0;
59   for (i in skiptab) {
60     if (skip_count < i)
61       skip_count = i;
62   }
63
64   skip_pos = ++skip_count;
65   for (i = 0; i < skip_count; i++) {
66     offset_table = offset_table skip_pos ", ";
67     skip_pos += kind_counts[skiptab[i]];
68   }
69   sub(/ $/, "\n\t\t", offset_table);
70
71   for (i = 0; i < count; i++) {
72     suffix = "";
73     if (i+1 < count)
74       suffix = ",\n\t\t";
75
76     if (specs[i] == "IDENT")
77       s = "0";
78     else
79       s = "PACK_TOKEN(T_" specs[i] ")";
80     offset_table = offset_table s suffix;
81   }
82
83   print "static const char *spec_string(unsigned type)"
84   print "{"
85   print "\tstatic const unsigned char _Alignas(1) idx[] = {";
86   print "\t\t" offset_table;
87   print "\t};\n";
88
89   print "\tunsigned x = (type & 0xff) + idx[type >> 9];";
90   print "\tassert(x < sizeof idx);";
91   print "\tif (!(x = idx[x]))";
92   print "\t\treturn \"\";";
93   print "\treturn cdecl__token_name(UNPACK_TOKEN(x));";
94   print "}";
95 }