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:
committed by
Carlos R. Mafra
parent
ea42641033
commit
fa5f8d9937
@@ -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, "*/");
|
||||
|
||||
Reference in New Issue
Block a user