# SPDX-License-Identifier: Public Domain # Replace open-coded bodies of macros with their macro name. # Confidence: Low # Bugs: I'd better have written this generator in python when it grew # over 5 lines.. Tested with busybox awk and GNU awk. # # Usage: # awk -f ~/coccinelle/use-defines.1.awk < gcc/tree.h > ~/coccinelle/gcc-tree_p.1.cocci # find ./ \( -name "testsuite" -o -name "contrib" -o -name "examples" -o -name ".git" \) -prune -o \( -name "*.[chpx]*" -a -type f -a ! -name "tree.h" \) -exec spatch --c++=11 --smpl-spacing --in-place --sp-file ~/coccinelle/gcc-tree_p.1.cocci {} \; # git diff | sed \ # -e '/^\+/s/\([^[:space:]]\)(/\1 (/g' \ # -e '/^\+s*.*( (/s/( (/((/g' \ # -e /^\+/s/ / /g' \ # -e '/^\+/s/[[:space:]]*$//' # > /tmp/non.patch BEGIN{ i=1 # Skip redefinitions and a handful of unwanted tokens like NULL_TREE seen["NULL_TREE"] = 1; # we want to retain "NULL" seen["TREE_REALPART"] = 1; # seems to confuse cocci seen["TREE_IMAGPART"] = 1; # seems to confuse cocci seen["DECL_BUILT_IN_CLASS"] = 1; # seems to confuse cocci seen["CAN_HAVE_RANGE_P"] = 1; # keep CAN_HAVE_LOCATION_P print("// Use *_P() from tree.h") print("//") print("// find ./ \( -name ""testsuite"" -o -name ""contrib"" -o -name ""examples"" -o -name "".git"" \) -prune -o \( -name ""*.[chpx]*"" -a -type f -a ! -name ""tree.h"" \) -exec spatch --c++=11 --smpl-spacing --in-place --sp-file ~/coccinelle/gcc-tree_p.1.cocci {} \;") print("// sed -e '/^\+/s/\([^[:space:]]\)(/\\1 (/g' -e ...") } # *_P () /^[[:space:]]*#[[:space:]]*define[[:space:]]*[A-Z_]+_P[[:space:]]*\([A-Za-z_, \t]*\)/{ # all macros with argument(s) #/^[[:space:]]*#[[:space:]]*define[[:space:]]*[A-Z_]+[[:space:]]*\([A-Za-z0-9_, \t]*\)/{ gsub(/^[[:space:]]*#[[:space:]]*define[[:space:]]*/, "") sub("\(", " ") def = $1 sub("^[^[:space:]]*[[:space:]]*", "") sub("\)", ") ") arg = "" do { arg = arg $1 sub("^[^)[:space:]]*[[:space:]]*", "") if (arg ~ /\)$/) { arg = substr(arg, 1, length(arg) - 1) break } } while (1) gsub(",", ", ", arg) sub("^[^)]*)[[:space:]]*", "") #printf("// def='%s' arg='%s'\n", def, arg) body = "" do { gsub(/(^[[:space:]]*|[[:space:]]*$)/, "") gsub(/[[:space:]][[:space:]]*/, " ") body = body $0 if (body ~ /\\$/) { gsub(/\\$/, "", body) getline } else { break } } while (1) # Ignore some corner cases or unuseful stuff like _CHECK() # NULL_TREE(tree) # CASE_FLT_FN CASE_FLT_FN_FLOATN_NX CASE_BUILT_IN_TM_STORE ... if (!length(body) || body ~ /##/ || body == "NULL" || def ~ /_CHECK$/) { next } if (body ~ /^__extension__/) { next; # NIH } for_loop = body ~ /^for[^[:alnum:]]/ do_loop = body ~ /^(do|while)[^[:alnum:]]/ if (for_loop || do_loop) { next; } if (! seen[def]) { seen[def] = 1 #printf("// body='%s'\n", body) print("@ rule" i++ " @") print("expression " arg ";") if (0 && for_loop) { print("statement FOR_LOOP_BODY;") } split("HOST_WIDE_INT signop", types) for (t in types) { if (body ~ types[t]) { printf("type %s;\n", types[t]) } } split("tree built_in_class", types) for (t in types) { if (body ~ types[t]) { printf("typedef %s;\n", types[t]) } } split("error_mark_node", types) for (t in types) { if (body ~ types[t]) { printf("identifier %s;\n", types[t]) } } print("@@"); print("- " body) print("+ " def " (" arg ")") print("") } }