Some old systems that still make some sense to be supported have only gawk 3, so let's support them for now. In order to achieve that, multiple changes have been implemented: - Multidimensional arrays are replaced with single-dimensional ones. In most places it's a "][" -> ", " replacement, as awk allows some kind of emulation of multidimensional arrays that way, but in several occasions (specifically for storing name and special fields) we have to iterate over them later, so we store that information in additional arrays in order to get the keys. - "switch" statements are replaced with sets of "if ... else if ... else" statements. This change is trivial, except we've added a temporary variable in what_is order to store expression value, for readability purposes. - No support for array iteration ordering. This one is most ugly of them all. Luckily, not that ugly, we've just had to process index a bit in order to make it lexicographically sortable and add two temporary arrays containing sorted indices in order to sort over them instead of those two arrays that we've added in order to work around lack of multidimensional array support. * mpers.awk (compare_indices): Remove unused function. (array_get, update_upper_bound, /^DW_AT_data_member_location/, /^DW_AT_byte_size/, /^DW_AT_encoding/): Replace multidimensional array access with comma-concatenated index. (norm_idx): New function. (array_seq): Replace multidimensional array access with comma-concatenated index. Use comma-concatenated pair of (array_idx, "seq") in order to check presence of the item in an array. (what_is): Add enc and i local variables. Store the value of array[what_idx, "encoding"] in it. Replace "switch" statements with sets of "if ... else if ... else" statements. Replace multidimensional array access with comma-concatenated index. Use for (... ; ...; ...) iteration over aparents_keys instead of iteration over array. (/^<[[:xdigit:]]+>/): Store idx as norm_idx(matches[2]). Replace multidimensional array access with comma-concatenated index. Store an additional flag in array_names array. (/^DW_AT_name/): Replace multidimensional array access with comma-concatenated index. Add a flag to array_names for that idx. (/^DW_AT_type/): Do not capture "0x" as a part of a group, normalise the captured group. Replace multidimensional array access with comma-concatenated index. (/^Abbrev Number:[^(]+\(DW_TAG_/): Replace multidimensional array access with comma-concatenated index. Store additional flags in array_special and array_parents arrays. (END): Remove PROCINFO["sorted_in"] setup. Sort array_parents. Replace multidimensional array access with comma-concatenated index. Iterate over array_special to go over all the items that have "special" field. Iterate over array_names to go over all items that have "name" field. * NEWS: Mention it.
243 lines
7.6 KiB
Awk
243 lines
7.6 KiB
Awk
#!/bin/gawk
|
|
#
|
|
# Copyright (c) 2015 Elvira Khabirova <lineprinter0@gmail.com>
|
|
# Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
|
|
# Copyright (c) 2015-2017 The strace developers.
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions
|
|
# are met:
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
# 3. The name of the author may not be used to endorse or promote products
|
|
# derived from this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
function array_get(array_idx, array_member, \
|
|
array_return)
|
|
{
|
|
array_return = array[array_idx, array_member]
|
|
if ("" == array_return) {
|
|
printf("%s: index [%s] without %s\n",
|
|
FILENAME, array_idx, array_member) > "/dev/stderr"
|
|
exit 1
|
|
}
|
|
return array_return
|
|
}
|
|
function norm_idx(idx)
|
|
{
|
|
return sprintf("%016s", idx)
|
|
}
|
|
function array_seq(array_idx)
|
|
{
|
|
if ((array_idx, "seq") in array)
|
|
return array[array_idx, "seq"]
|
|
index_seq++
|
|
array[array_idx, "seq"] = index_seq
|
|
return index_seq
|
|
}
|
|
function enter(array_idx,
|
|
item)
|
|
{
|
|
if (array_idx in called) {
|
|
printf("%s: index loop detected:", FILENAME) > "/dev/stderr"
|
|
for (item in called)
|
|
printf(" %s", item) > "/dev/stderr"
|
|
print "" > "/dev/stderr"
|
|
exit 1
|
|
}
|
|
called[array_idx] = 1
|
|
}
|
|
function leave(array_idx, to_return)
|
|
{
|
|
delete called[array_idx]
|
|
return to_return
|
|
}
|
|
function update_upper_bound(idx, val, \
|
|
count)
|
|
{
|
|
count = array[idx, "count"]
|
|
if (count == "")
|
|
count = 1
|
|
array[idx, "count"] = count * val
|
|
array[idx, "upper_bound"] = array[idx, "upper_bound"] "[" val "]"
|
|
}
|
|
function what_is(what_idx, \
|
|
item, loc_diff, location, prev_location, prev_returned_size, \
|
|
special, to_return, type_idx, enc, i)
|
|
{
|
|
enter(what_idx)
|
|
special = array_get(what_idx, "special")
|
|
if (special == "base_type") {
|
|
enc = array_get(what_idx, "encoding")
|
|
if (enc == 5) { # signed
|
|
printf("int%s_t ",
|
|
8 * array_get(what_idx, "byte_size"))
|
|
} else if (enc == 7) { # unsigned
|
|
printf("uint%s_t ",
|
|
8 * array_get(what_idx, "byte_size"))
|
|
} else { # float, signed/unsigned char
|
|
printf("%s ", array_get(what_idx, "name"))
|
|
}
|
|
returned_size = array_get(what_idx, "byte_size")
|
|
} else if (special == "enumeration_type") {
|
|
returned_size = array_get(what_idx, "byte_size")
|
|
printf("uint%s_t ", 8 * returned_size)
|
|
} else if (special == "pointer_type") {
|
|
printf("mpers_ptr_t ")
|
|
returned_size = array_get(what_idx, "byte_size")
|
|
} else if (special == "array_type") {
|
|
type_idx = array_get(what_idx, "type")
|
|
what_is(type_idx)
|
|
to_return = array[what_idx, "upper_bound"]
|
|
if ("" == to_return)
|
|
to_return = "[0]"
|
|
returned_size = array[what_idx, "count"] * returned_size
|
|
return leave(what_idx, to_return)
|
|
} else if (special == "structure_type") {
|
|
print "struct {"
|
|
prev_location = 0
|
|
location = 0
|
|
returned_size = 0
|
|
prev_returned_size = 0
|
|
for (i = 1; i <= parents_cnt; i += 1) {
|
|
if (array_parents[aparents_keys[i]] == what_idx) {
|
|
location = array_get(aparents_keys[i], "location")
|
|
loc_diff = location - prev_location - \
|
|
prev_returned_size
|
|
if (loc_diff != 0) {
|
|
printf("unsigned char mpers_%s_%s[%s];\n",
|
|
"filler", array_seq(aparents_keys[i]), loc_diff)
|
|
}
|
|
prev_location = location
|
|
returned = what_is(aparents_keys[i])
|
|
prev_returned_size = returned_size
|
|
printf("%s%s;\n", array[aparents_keys[i], "name"], returned)
|
|
}
|
|
}
|
|
returned_size = array_get(what_idx, "byte_size")
|
|
loc_diff = returned_size - prev_location - prev_returned_size
|
|
if (loc_diff != 0) {
|
|
printf("unsigned char mpers_%s_%s[%s];\n",
|
|
"end_filler", array_seq(item), loc_diff)
|
|
}
|
|
printf("} ATTRIBUTE_PACKED ")
|
|
} else if (special == "union_type") {
|
|
print "union {"
|
|
for (i = 1; i <= parents_cnt; i += 1) {
|
|
if (array_parents[aparents_keys[i]] == what_idx) {
|
|
returned = what_is(aparents_keys[i])
|
|
printf("%s%s;\n", array[aparents_keys[i], "name"], returned)
|
|
}
|
|
}
|
|
printf("} ")
|
|
returned_size = array_get(what_idx, "byte_size")
|
|
} else if (special == "typedef") {
|
|
type_idx = array_get(what_idx, "type")
|
|
return leave(what_idx, what_is(type_idx))
|
|
} else if (special == "member") {
|
|
type_idx = array_get(what_idx, "type")
|
|
return leave(what_idx, what_is(type_idx))
|
|
} else {
|
|
type_idx = array_get(what_idx, "type")
|
|
what_is(type_idx)
|
|
}
|
|
return leave(what_idx, "")
|
|
}
|
|
BEGIN {
|
|
match(ARCH_FLAG, /[[:digit:]]+/, temparray)
|
|
default_pointer_size = temparray[0] / 8
|
|
print "#include <inttypes.h>"
|
|
}
|
|
/^<[[:xdigit:]]+>/ {
|
|
match($0, /([[:alnum:]]+)><([[:alnum:]]+)/, matches)
|
|
level = matches[1]
|
|
idx = norm_idx(matches[2])
|
|
array[idx, "idx"] = idx
|
|
parent[level] = idx
|
|
}
|
|
/^DW_AT_data_member_location/ {
|
|
if (!match($0, /\(DW_OP_plus_uconst:[[:space:]]+([[:digit:]]+)\)/, temparray))
|
|
match($0, /([[:digit:]]+)/, temparray)
|
|
array[idx, "location"] = temparray[1]
|
|
}
|
|
/^DW_AT_name/ {
|
|
match($0, /:[[:space:]]+([[:alpha:]_][[:alnum:]_[:space:]]*)/, \
|
|
temparray)
|
|
array_names[idx] = 1
|
|
array[idx, "name"] = temparray[1]
|
|
}
|
|
/^DW_AT_byte_size/ {
|
|
match($0, /[[:digit:]]+/, temparray)
|
|
array[idx, "byte_size"] = temparray[0]
|
|
}
|
|
/^DW_AT_encoding/ {
|
|
match($0, /[[:digit:]]+/, temparray)
|
|
array[idx, "encoding"] = temparray[0]
|
|
}
|
|
/^DW_AT_type/ {
|
|
match($0, /:[[:space:]]+<0x([[:xdigit:]]*)>$/, temparray)
|
|
array[idx, "type"] = norm_idx(temparray[1])
|
|
}
|
|
/^DW_AT_upper_bound/ {
|
|
match($0, /[[:digit:]]+/, temparray)
|
|
update_upper_bound(parent[level - 1], temparray[0] + 1)
|
|
}
|
|
/^DW_AT_count/ {
|
|
match($0, /[[:digit:]]+/, temparray)
|
|
update_upper_bound(parent[level - 1], temparray[0])
|
|
}
|
|
/^Abbrev Number:[^(]+\(DW_TAG_/ {
|
|
if (match($0, /typedef|union_type|structure_type|pointer_type\
|
|
|enumeration_type|array_type|base_type|member/, temparray)) {
|
|
array_special[idx] = temparray[0]
|
|
array[idx, "special"] = temparray[0]
|
|
if ("pointer_type" == temparray[0])
|
|
array[idx, "byte_size"] = default_pointer_size
|
|
if (level > 1 && "member" == temparray[0])
|
|
array_parents[idx] = parent[level-1]
|
|
}
|
|
}
|
|
END {
|
|
parents_cnt = asorti(array_parents, aparents_keys)
|
|
|
|
for (item in array_special) {
|
|
if (array[item, "special"] == "pointer_type") {
|
|
mpers_ptr_t = \
|
|
"uint" 8 * array_get(item, "byte_size") "_t"
|
|
print "#ifndef mpers_ptr_t_is_" mpers_ptr_t
|
|
print "typedef " mpers_ptr_t " mpers_ptr_t;"
|
|
print "#define mpers_ptr_t_is_" mpers_ptr_t
|
|
print "#endif"
|
|
break
|
|
}
|
|
}
|
|
for (item in array_names) {
|
|
if (array[item, "name"] == VAR_NAME) {
|
|
type = array_get(item, "type")
|
|
print "typedef"
|
|
what_is(type)
|
|
name = array_get(type, "name")
|
|
print ARCH_FLAG "_" name ";"
|
|
print "#define MPERS_" \
|
|
ARCH_FLAG "_" name " " \
|
|
ARCH_FLAG "_" name
|
|
break
|
|
}
|
|
}
|
|
}
|