#!/bin/awk -f # # Copyright © 2021, 2023-2024 Nick Bowler # # Generate a function to return the C keyword corresponding to a specifier # type as a string, for internal use by the output routines. # # 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-specstr.awk from " FILENAME; } else { print " * Automatically generated by gen-specstr.awk"; } print " * Do not edit."; print " */"; } BEGIN { kinds["TYPE"] = kinds["STOR"] = kinds["QUAL"] = kinds["FUNC"] = 1; count = 0; } # Locate all the relevant identifiers in cdecl.h. We assume everything # is in numerically increasing order within the various enums. $1 ~ /^CDECL_/ { sub(/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ_].*/, "", $1); split($1, parts, "_"); if (parts[2] == "SPEC") { x = $0; sub(/^.*= */, "", x); sub(/,? *$/, "", x); x = int(x / 512) % 8; if (skiptab[x]) { print "cannot create skip table"; exit 1; } skiptab[x] = parts[3]; } if (parts[2] in kinds) { kind_counts[parts[2]]++; specs[count++] = parts[3]; } } END { # Create the token table. The first 5 entries key off of bits 9 through 11, # which is sufficient to distinguish the different specifier kinds and is # used to partition the rest of the token table. skip_count = 0; for (i in skiptab) { if (skip_count < i) skip_count = i; } skip_pos = ++skip_count; for (i = 0; i < skip_count; i++) { offset_table = offset_table skip_pos ", "; skip_pos += kind_counts[skiptab[i]]; } sub(/ $/, "\n\t\t", offset_table); for (i = 0; i < count; i++) { suffix = ""; if (i+1 < count) suffix = ",\n\t\t"; if (specs[i] == "IDENT") s = "0"; else s = "PACK_TOKEN(T_" specs[i] ")"; offset_table = offset_table s suffix; } print "static const char *spec_string(unsigned type)" print "{" print "\tstatic const unsigned char _Alignas(1) idx[] = {"; print "\t\t" offset_table; print "\t};\n"; print "\tunsigned x = (type & 0xff) + idx[type >> 9];"; print "\tassert(x < sizeof idx);"; print "\tif (!(x = idx[x]))"; print "\t\treturn \"\";"; print "\treturn cdecl__token_name(UNPACK_TOKEN(x));"; print "}"; }