1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-18 20:10:29 +01:00

wmaker-check: rewrote parsing of structure fields for callback checker

Doug Torrance reported a problem with some versions of AWK which caused the
signed/unsigned attribute to not be properly ignored, because the regular
expression was using a GNU extension to keep it simple.

While trying to reproduce it, I discovered that mawk was chocking on one
regexp used in parsing the type+names parsing of structure members.

This patch is rewriting the parsing, because hacking regexp to make them
fall working is still not the best solution for maintainability. There is
now a clearer code which is also safer because it will handle more
gracefully corner cases.

Reported-by: Doug Torrance <dtorrance@monmouthcollege.edu>
Signed-off-by: Christophe CURIS <christophe.curis@free.fr>
This commit is contained in:
Christophe CURIS
2015-05-14 15:07:04 +02:00
committed by Carlos R. Mafra
parent ea42641033
commit fa5f8d9937

View File

@@ -163,8 +163,8 @@ function parse_structure(prefix) {
}
# skip line that define nothing interresting
if (/^[ \t]*$/) { continue; }
gsub(/^[ \t]+/, "");
if (/^$/) { continue; }
if (/^#/) { continue; }
gsub(/[ \t]+$/, "");
@@ -198,42 +198,82 @@ function parse_structure(prefix) {
print "Warning: line " FILENAME ":" NR " not understood inside struct" > "/dev/stderr";
continue;
}
gsub(/;$/, "");
# Skip the lines that define a bit-field because they cannot be safely
# pointed to anyway
if (/:/) { continue; }
# It looks like a valid line, separate the name from the type
gsub(/;$/, "");
name = $0;
gsub(/([A-Z_a-z][A-Z_a-z0-9]*([ \t]*,[ \t]*)*)*$/, "");
name = substr(name, length($0) + 1);
separate_type_and_names();
# In some rare case we cannot extract the name, that is likely a function pointer type
if (name == "") { continue; }
# Remove the sign specification because it is not a real problem
gsub(/\<(un)?signed\>/, " ");
if (/^[^A-Za-z]*$/) {
# If there is no more character, that means that the sign declaration was the only type specified, so
# we use the "int" type which is what C will use
$0 = "int " $0;
}
# Pack the type to have something consistent
gsub(/^[ \t]+/, "");
gsub(/[ \t]+$/, "");
gsub(/[ \t]*\*[ \t]*/, "*");
gsub(/[ \t]+/, " ");
if (type == "") { continue; }
# Save this information in an array
nb_vars = split(name, var_list, /[ \t]*,[ \t]*/);
for (i = 1; i <= nb_vars; i++) {
member[prefix ":" var_list[i] ] = $0;
for (i = 1; i <= nb_names; i++) {
# If it is an array, push that information into the type
idx = index(name_list[i], "[");
if (idx > 0) {
member[prefix ":" substr(name_list[i], 1, idx-1) ] = type substr(name_list[i], idx);
} else {
member[prefix ":" name_list[i] ] = type;
}
}
}
}
# Separate the declaration of an member of the struct: its type and the list of names
# The result is returned through variables "name_list + nb_names" and "type"
function separate_type_and_names() {
# Separate by names first
nb_names = split($0, name_list, /[ \t]*,[ \t]*/);
# Separate the type from the 1st name
if (name_list[1] ~ /\]$/) {
idx = index(name_list[1], "[") - 1;
} else {
idx = length(name_list[1]);
}
while (substr(name_list[1], idx, 1) ~ /[A-Za-z_0-9]/) { idx--; }
type = substr(name_list[1], 1, idx);
name_list[1] = substr(name_list[1], idx + 1);
if (type ~ /\(/) {
# If therese is a parenthesis in the type, that means we are parsing a function pointer
# declaration. This is not supported at current time (not needed), so we silently ignore
type = "";
return;
}
# Remove size information from array declarations
for (i in name_list) {
gsub(/\[[^\]]+\]/, "[]", name_list[i]);
}
# Parse the type to make it into a "standard" format
gsub(/[ \t]+$/, "", type);
nb_elem = split(type, type_list, /[ \t]+/);
type = "";
for (i = 1; i <= nb_elem; i++) {
if (type_list[i] == "signed" || type_list[i] == "unsigned") {
# The sign information is not a problem for pointer compatibility, so we do not keep it
continue;
}
if (type_list[i] ~ /^\*+$/) {
# If we have a pointer mark by itself, we glue it to the previous keyword
type = type type_list[i];
} else {
type = type " " type_list[i];
}
}
gsub(/^ /, "", type);
if (type ~ /^\*/ || type == "") {
# We have a signed/unsigned without explicit "int" specification, add it now
type = "int" type;
}
}
# The name of the variable is at the end, so find all structure definition
/^([a-z]*[ \t][ \t]*)*struct[ \t]/ {
@@ -364,7 +404,7 @@ function extract_string_to_element() {
return content "\"";
}
# Wherever a long C comment (/* comment */) is encounter, it is discarded
# Wherever a long C comment (/* comment */) is encountered, it is discarded
function skip_long_comment() {
while (1) {
idx = index($0, "*/");