#!/bin/bash ## (c) Denis Kaganovich ## v5.9 : ${TMPDIR:=/tmp} # grep 2.15 utf8 export LANG=C #BUS="PCI" BUS="\w+" STR="(?:^(?:static\s+)?(?:const\s+)?struct\s+${BUS,,}_device_id(?:\s+\w+)+|^(?:static\s+)?DEFINE_${BUS}_DEVICE_TABLE\(.*?\))" hdr(){ local h="$2" i x h="${h#$1}" h="${h#/}" for i in $(grep -sPrhl "^\s*#include\s+[\"<](?:.*/)?${h##*/}[\">]" $1 --include "*.[ch]"); do #" x="${i#$1}" x="${x#/}" x="${x%/*}" ( [[ -z ${h##$x/*} ]] && grep -qP "^\s*#include\s+\"${h#$x/}\"" "$i" ) || ( [[ -z "${h##include/*}" ]] && grep -qP "^\s*#include\s+<${h#include/}>" "$i" ) || continue case "$i" in *.h)hdr $1 "$i";; *)echo "$i";; esac done } str(){ local bus b i=$1 h=$2 m= grep -q "MODULE_DEVICE_TABLE" $i $h && return b=`grep -Prho "$STR" $i` && h=$i || bus=`grep -Prho "$STR" $h` # ??? while [ -n "$b" ]; do bus="${b%% *}" [ "$bus" = "$b" ] && b='' || m='+' b="${b#* }" case "$bus" in *DEFINE_*_DEVICE_TABLE*) bus="${bus#*DEFINE_}" n="${bus%%)*}" n="${n##*(}" bus="${bus%%_*}" [[ "$bus" != PCI ]] && echo "Debug: DEFINE_$bus_*DEVICE_TABLE in $i" >&2 bus="${bus,,}" ;; *) bus="${bus#*struct }" n="${bus%%[\[=]*}" n="${n##*device_id }" bus="${bus%%_device_id*}" ;; esac while [ -z "${n%%* }" -a -n "$n" ]; do n="${n%% }" done n="${n##* }" echo "$i $h $bus $n $m" done } fnd(){ local i h bus n m grep -sPrhl "$STR" $1 --include "*.[hc]"|while read h; do case "$h" in *.h)for i in $(hdr $1 "$h"); do str $i $h done;; *)str $h $h;; esac done|while read i h bus n m; do #grep -Prhl "$STR" $1 --include="*.c" | while read i ; do h:="$i" grep -q "^module_init[ ]*(\|^MODULE_DESCRIPTION(" $i || continue grep -q "MODULE_DEVICE_TABLE.*$n" $i $h && continue # [ -z "${bus_##* #*}" ] && echo "TODO: multi-bus device: $i - ${bus_}" && continue local ii="${i#$1}" ii="${ii#/}" # really it can be in .h, but too sometimes grep -sqP "^\s*\#include\s+" "$i" && mh=true || mh=false if [[ "$2" != "f" ]] ; then local b="$bus" case $b in of) b="of_platform";; esac grep -Pq "${STR}${b}_driver\s+" $i || { echo "UNSURE: $bus: $ii" continue } $mh || { echo "UNSURE: $bus: $ii - no linux/module.h" continue } fi bus="${bus%%_*}" case "$bus:$ii" in #*/neo1973_wm8753.c) #*/pci/endpoint/functions/*) # ?? */pci-epf-ntb.c|*-test.c|*/functions/*) echo "SKIPPED: $bus: $ii" continue ;; esac local BU case "$bus" in sdio)BU=MMC;; rio)BU=RAPIDIO;; *)BU="${bus^^}";; esac if [[ "$2" != "f" ]] && ! grep -Pqr "MODULE_DEVICE_TABLE\($bus," $1 --include="*.c" ; then echo "UNKNOWN BUS: $bus ($ii)" continue fi add='' [[ "$i" == "$h" ]] && add=' /* _module_id_ */ ' export add n if perl -e 'sub fix{ my ($s0,$s)=(@_); my $s1=$s; my $s2; ($s=~s/.*\{//gs)||return(($s0=~/[\]\)]/)?$s0.$s1:"[]$s0\{$s1\}, \{\}"); $s0.=$s1; $s1=$s0; $s=~s/\/\*.*\*\///gs; $s=~s/,\s*$//s || ($s1=~s/\}/\},/s) || exit 1; $s=~s/\"\"//gs; $s=~s/\s//gs; $s=~s/\}$//s || exit 1; $s=~s/[0,]//gs; $s=~s/\.\w+=//gs; # print STDERR "FIX0:"; $s || return $s0; $s1.="\n \{\}\n"; $s1 } while(){$s.=$_} exit !($s=~s/('"${STR//^/\\n}"'[^=;\{\}\]\)]*)([\]\)]?\s*=\s*\{)([^;]*)(\s*?\};)/index($1,$ENV{n})>=0?$1.fix("$2","$3").$4.$ENV{add}:$1.$2.$3.$4/ges && print $s)' <$h >"$TMPDIR/modulesfix.tmp" ; then cmp -s "$TMPDIR/modulesfix.tmp" $h && rm "$TMPDIR/modulesfix.tmp" || { [[ "$i" != "$h" ]] && echo "Fixing: ($n) ${h#$1/}" mv "$TMPDIR/modulesfix.tmp" $h } elif [[ "$2" != "f" ]]; then echo "BROKEN/UNSURE: $bus: $ii" continue fi xx='\nMODULE_DEVICE_TABLE('"$bus, $n"');' $mh || xx='\n#include '"$xx" if grep -Prq "^\s*(?:menu)?config\s+$BU(?:\s.*)?$" $1 --include="Kconfig*"; then echo "Fixing$m: $BU: ($n) $ii" xx='\n#ifdef CONFIG_'"$BU$xx"'\n#endif' else echo "Fixing$m: $bus: ($n) $ii" fi sed -i -e 's%^/\* _module_id_ \*/$%'"$xx"'\n%' $i grep -q "^MODULE_DEVICE_TABLE" $i || echo -e "$xx" >>$i done } [[ -z "$1" ]] && echo "$0 [f]" && exit 1 fnd $*