|
| 1 | +# Copyright 2019 - Omar Sandoval |
| 2 | +# SPDX-License-Identifier: GPL-3.0+ |
| 3 | + |
| 4 | +# This script generates "arch_foo.c" from "arch_foo.c.in". It uses |
| 5 | +# "parse_arch.awk" to parse the input file and generates three definitions: |
| 6 | +# |
| 7 | +# 1. An array of register definitions: |
| 8 | +# static const struct drgn_register registers[]; |
| 9 | +# |
| 10 | +# 2. A lookup function (implemented as a trie using nested switch statements): |
| 11 | +# static const struct drgn_register *register_by_name(const char *name); |
| 12 | +# |
| 13 | +# 3. A macro containing initializers for the "name", "arch", "registers", |
| 14 | +# "num_registers", and "register_by_name" members of "struct |
| 15 | +# drgn_architecture_info": |
| 16 | +# #define ARCHITECTURE_INFO |
| 17 | +# |
| 18 | +# The prologue and epilogue are copied before and after these definitions, |
| 19 | +# respectively. |
| 20 | + |
| 21 | +function add_to_trie(node, s, value, char) { |
| 22 | + if (length(s) == 0) { |
| 23 | + node[""] = value |
| 24 | + } else { |
| 25 | + char = substr(s, 1, 1) |
| 26 | + if (!(char in node)) { |
| 27 | + # Force node[char] to be an array. |
| 28 | + node[char][""] = "" |
| 29 | + delete node[char][""] |
| 30 | + } |
| 31 | + add_to_trie(node[char], substr(s, 2), value) |
| 32 | + } |
| 33 | +} |
| 34 | + |
| 35 | +function trie_to_switch(node, indent, char) { |
| 36 | + print indent "switch (*(p++)) {" |
| 37 | + PROCINFO["sorted_in"] = "@ind_str_asc" |
| 38 | + for (char in node) { |
| 39 | + if (length(char) == 0) { |
| 40 | + print indent "case '\\0':" |
| 41 | + print indent "\treturn ®isters[" node[""] "];" |
| 42 | + } else { |
| 43 | + print indent "case '" char "':" |
| 44 | + trie_to_switch(node[char], "\t" indent) |
| 45 | + } |
| 46 | + } |
| 47 | + print indent "default:" |
| 48 | + print indent "\treturn NULL;" |
| 49 | + print indent "}" |
| 50 | +} |
| 51 | + |
| 52 | +ENDFILE { |
| 53 | + print "/* Generated by libdrgn/build-aux/gen_arch.awk. */" |
| 54 | + |
| 55 | + if (length(prologue) != 0) |
| 56 | + print prologue |
| 57 | + |
| 58 | + print "static const struct drgn_register registers[] = {" |
| 59 | + i = 0 |
| 60 | + split("", trie) |
| 61 | + PROCINFO["sorted_in"] = "@val_num_asc" |
| 62 | + for (reg in registers) { |
| 63 | + print "\t{ \"" reg "\", " registers[reg] ", }," |
| 64 | + add_to_trie(trie, reg, i++) |
| 65 | + } |
| 66 | + print "};" |
| 67 | + print "" |
| 68 | + |
| 69 | + print "static const struct drgn_register *register_by_name(const char *p)" |
| 70 | + print "{" |
| 71 | + trie_to_switch(trie, "\t") |
| 72 | + print "}" |
| 73 | + print "" |
| 74 | + |
| 75 | + print "#define ARCHITECTURE_INFO \\" |
| 76 | + print "\t.name = \"" arch_name "\", \\" |
| 77 | + print "\t.arch = DRGN_ARCH_" toupper(sanitize(arch_name)) ", \\" |
| 78 | + print "\t.registers = registers, \\" |
| 79 | + print "\t.num_registers = " i ", \\" |
| 80 | + print "\t.register_by_name = register_by_name" |
| 81 | + |
| 82 | + printf "%s", epilogue |
| 83 | +} |
0 commit comments