| #!/usr/bin/perl -w |
| |
| #AUTHORS: Vijay Ganesh, David L. Dill BEGIN DATE: November, 2005 |
| # |
| #Permission is hereby granted, free of charge, to any person obtaining |
| #a copy of this software and associated documentation files (the |
| #"Software"), to deal in the Software without restriction, including |
| #without limitation the rights to use, copy, modify, merge, publish, |
| #distribute, sublicense, and/or sell copies of the Software, and to |
| #permit persons to whom the Software is furnished to do so, subject to |
| #the following conditions: |
| # |
| #The above copyright notice and this permission notice shall be |
| #included in all copies or substantial portions of the Software. |
| # |
| #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| #EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| #MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| #NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| #LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| #OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| #WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| # |
| #given a file containing kind names, one per line produces .h and .cpp |
| #files for the kinds. |
| |
| use Getopt::Long; |
| my $fname = "ASTKind.kinds"; |
| my $timestamp = 1; |
| GetOptions ("file=s" => \$fname, "timestamp!" => \$timestamp); |
| |
| #globals |
| @kindnames = (); |
| $minkids = 0; |
| $maxkids = 0; |
| @cat_bits = (); |
| @category_names = (); |
| %cat_index = (); |
| |
| if ($timestamp) { |
| $now = " " . localtime time; |
| } else { |
| $now = ""; |
| } |
| |
| sub read_kind_defs { |
| open(KFILE, "< $fname") || die "Cannot open .kinds file $fname: $!\n"; |
| @kindlines = <KFILE>; |
| close(KFILE) |
| } |
| |
| # create lists of things indexed by kinds. |
| sub split_fields { |
| my $kind_cat_bits; |
| # matches anything with three whitespace-delimited alphanumeric fields, |
| # followed by rest of line. Automatically ignores lines beginning with '#' and blank lines. |
| for (@kindlines) { |
| if (/Categories:\s+(.*)/) { |
| @category_names = split(/\s+/, $1); |
| $i = 0; |
| for (@category_names) { |
| $cat_index{$_} = $i++; |
| # print "cat_index{$_} = $i\n"; |
| } |
| } |
| elsif (/^(\w+)\s+(\w+)\s+(\w+|-)\s+(.*)/) { |
| push(@kindnames, $1); |
| push(@minkids, $2); |
| push(@maxkids, $3); |
| @kind_cats = split(/\s+/, $4); |
| # build a bit vector of categories. |
| $kind_cat_bits = 0; |
| for (@kind_cats) { |
| $kind_cat_bits |= (1 << int($cat_index{$_})); |
| } |
| push(@cat_bits, $kind_cat_bits); |
| } |
| } |
| } |
| |
| sub gen_h_file { |
| open(HFILE, "> ASTKind.h") || die "Cannot open .h file: $!\n"; |
| |
| print HFILE |
| "#ifndef TESTKINDS_H\n", |
| "#define TESTKINDS_H\n", |
| "// Generated automatically by genkinds.pl from ASTKind.kinds$now.\n", |
| "// Do not edit\n", |
| "#include <iostream>\n", |
| "namespace stp {\n typedef enum {\n"; |
| |
| for my $i (0 .. $#kindnames) { |
| print HFILE " ", $kindnames[$i]; |
| print HFILE "," unless $i == $#kindnames; |
| print HFILE "\n"; |
| } |
| |
| print HFILE |
| "} Kind;\n\n", |
| "extern unsigned char _kind_categories[];\n\n"; |
| |
| # For category named "cat", generate functions "bool is_cat_kind(k);" |
| |
| |
| for (@category_names) { |
| my $catname = $_; |
| my $kind_cat_bit = (1 << int($cat_index{$catname})); |
| print HFILE "inline bool is_", $catname, "_kind(Kind k) { return (_kind_categories[k] & $kind_cat_bit); }\n\n" |
| } |
| |
| print HFILE |
| "extern const char *_kind_names[];\n\n", |
| "/** Prints symbolic name of kind */\n", |
| "inline std::ostream& operator<<(std::ostream &os, const Kind &kind) { os << _kind_names[kind]; return os; }\n", |
| "\n\n", |
| "} // end namespace\n", |
| "\n\n#endif\n"; |
| |
| close(HFILE); |
| } |
| |
| # generate the .cpp file |
| |
| sub gen_cpp_file { |
| open(CPPFILE, "> ASTKind.cpp") || die "Cannot open .h file: $!\n"; |
| |
| print CPPFILE |
| "// Generated automatically by genkinds.h from ASTKind.kinds$now.\n", |
| "// Do not edit\n", |
| "namespace stp {\n", |
| "#if defined(__GNUC__) || defined(__clang__)\n\n", |
| "__attribute__((visibility(\"default\")))\n\n", |
| "#endif\n\n", |
| "const char * _kind_names[] = {\n"; |
| |
| for my $i (0 .. $#kindnames) { |
| print CPPFILE " \"", $kindnames[$i], "\",\n"; |
| } |
| print CPPFILE "};\n\n"; |
| |
| # category bits |
| print CPPFILE |
| "#if defined(__GNUC__) || defined(__clang__)\n\n", |
| "__attribute__((visibility(\"default\")))\n\n", |
| "#endif\n\n", |
| "unsigned char _kind_categories[] = {\n"; |
| |
| #for (@cat_bits) { |
| for my $i (0 .. $#kindnames) { |
| print CPPFILE " ", $cat_bits[$i], ", //", $kindnames[$i], "\n"; |
| } |
| print CPPFILE |
| "};\n", |
| "\n} // end namespace\n"; |
| |
| close(CPPFILE); |
| } |
| |
| &read_kind_defs; |
| &split_fields; |
| &gen_h_file; |
| &gen_cpp_file; |