strace/mpers.awk
Eugene Syromyatnikov 1b75ffef40 mpers: implement gawk 3 support
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.
2018-01-21 01:46:04 +00:00

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
}
}
}