#format wiki #language nl == Roel Kluin == Email: [[MailTo(12o3l AT SPAMFREE tiscali DOT nl)]] ... ---- CategoryHomepage all code is (c) Roel kluin, 2007 GNU GPL V.2. == Examples == These may require the script 'vars' below sourced, and should be called in a git tree. I simply paste them into my console (bash). Match Unlikely(x) ?= y {{{ git-grep -n "\(un\)\?likely$s([^()]*\(([^()]*)[^()]*\)*)$s.=" }}} These can be replaced with strchr: {{{ E="\([^\"\\]\|\\[\\tnr\?'\"0bafv]\|\\[0-7]\{1,3\}\|\\[a-f0-9]\{1,2\}\|\\[A-F0-9]\{1,2\}\)" git-grep -n "strstr$s($s$W$s,$s\"$E\"$s)" }}} Show module initializing functions, not using {{{__init}}} or similarly exit: {{{ git-grep -n "\(void\|int\)$s[[:alnum:]_]*module_[ei][xn]it(void)" | grep -v "__[ie][xn]it" }}} Matches if(function) BUG(): {{{ q="${s}if$s(\($ccode$Q\)\?$L$s($ccode)$s$ccode$s)" git-grep -n -B1 "^\($q\)\?${s}BUG($s)$s;$cendl" | grep "$q$cendl" | grep -v "\(sizeof\|unlikely\|likely\)($ccode)" | less }}} A sed script to audit ioremap/iounmap balancing (can be adapted for others): {{{ git-grep -l '[^[:alnum:]]ioremap' | while read g; do echo "--------------------------[ $g ]--------------------------" sed -n "/[^[:alnum:]]ioremap.*(\(.*\))/,/^[}{]$/{ s/\(.*return.*\)/\1\t\t-------return/ tp s/\(.*goto.*\)/\1\t\t------goto/ tp s/\(.*iounmap.*\)/\1\t\t<----/ tp s/\(.*ioremap.*\)/\1\t\t---->/ Tp = :p p }" $g done | less }}} Make sure no-one is freeing skbs with kfree instead of kfree_skb: {{{ for f in $(git-grep -l "struct${s}sk_buff"); do sed -n "s/^.*struct${S}sk_buff${s}\*${s}\(${V}\)$Q.*$/\1/p" $f | sort | uniq | while read n; do sed -n "/struct${s}sk_buff${s}\*${s}${n}/,/^[{}].*$/{ /kfree(${s}${n}${s})/= }" $f | while read q; do echo -e "kfreeing sk_buff $n at line $q in $f\n$q"; sed -n "/struct${s}sk_buff${s}\*${s}${n}/,/^[{}].*$/p" $f; done done done 2>&1 | less }}} matches a comparison as the last argument of a function. This may be correct but it is sometimes a misplaced check (and should be placed after the parenthesis instead). Use getcalls and/or getfunc to determine whether a boolean as the last argument is correct: {{{ h="\(([^()]*)\)\+"; git-grep -n -A9 ",[^);,]*=" | sed -n "s/^\([^\.]*\.[chsS]-[0-9]*-\|\([^\.]*\.[chsS]:[0-9]*:\)$s\)\(.*\)$/\2\3/p" | tr "\n" "@" | grep -o "@[^@]*$W$s(\(\([^,()]*\|$h\)*,\)\+\([^,()]*\|$h\)*[^\"]=${s}[^\",()]*)${s}[)&|]" | tr "@\t" " " | tr -s " " | less }}} Find values used as a boolean instead of the more common bitwise usage: {{{ f1="\($W${s}[&|]\|[0-9]\+${s}[&|]\|)${s}[&|]\)" # adds 2 h="\(([^()]*\(([^()]*\(([^()]*)[^()]*\)*[^()]*)[^()]*\)*)\)\?" git-grep "\($f1$s$V$s$h$s\(&&\|||\|)\|?\)\|\(&&\|||\|(\)$s$V$s$h${s}[&|]$s\([0-9]*\($W\|[^0]\)[0-9]*\)\)" | sed -n "s/^.*\($f1$s\($V\)$s\(([^()]*)\)\?$s\(&&\|||\|)\)\|\(&&\|||\|(\)$s\($V\)$s\(([^()]*)\)\?${s}[&|]$s\([0-9]*\($W\|[^0]\)[0-9]*\)\).*$/\4\8/p" | while read n; do echo "$n"; done | sort | uniq -c | sort -rn | while read n a; do b=$(git-grep -n "\(\(\(if\|while\)$s(\|&&\|||\|\!\)$s$a$s\(&&\|||\|\|)?\|(\)\|\(&&\|||\|(\)$s$a$s\(&&\|||\|(\|?\)\)" | grep -v "Kconfig") [ -z "$b" ] && continue; c=`echo "$b" | wc -l` let d=$(($n/$c)) echo "----[ a=\"$a\" # used $n times as bitwise, $c times as boolean, div $d ]----" [ $c -gt 20 ] && continue; [ $d -lt 5 ] && continue; echo "$b" done | less }}} == Scripts == I called it vars, it contains some functions for kernel hacking. usage: "source path/to/vars" N.B. do not source this in a shell that you plan to use to compile a kernel ($Q is used in Makefiles as well, which will give some problems) {{{ #!/bin/bash # (c) Roel kluin, 2008 GNU GPL V.2 alias gg="git-grep -n" # Usage: v /path/to/sourcefile.c:1 # (as pasted from git-grep -n) v() { [ -n "$1" ] && vi ${1%[:-]*} +${1##*[:-]} } # a number export D="[0-9]\+" # we could also use this, to match something like 1ul, floats or hexes as well: # but the parentheses will cost one backreference for (git-)grep export d="\([0-9]\+[uUlLfF]\?\|[0-9]\+[uU]\?[lL][lL]\?\|0x[a-f0-9]\+\|0x[A-F0-9]\+\|[0-9]\+[lL][lL][uU]\|[0-9]*\.[0-9]\+[fF]\?\)" # can be used for a variable/function name: export V="[A-Za-z_]\+[A-Za-z0-9_]*" # capital: a config option/definition export K="[A-Z]\+[A-Z0-9_]*"; # works the same as above, but also for members and arrays: one backreference export W="$V\(\[$s$V$s\]\|\[$s$D$s\]\|\.$V\|->$V\)*" # seperators: export s="[[:space:]]*"; export S="[[:space:]]\+" # useful to delimit a variable name: export Q="[^[:alnum:]_]" # match the end of the line, including comments: one backreference (but at eol) export cendl="$s\(\/[\*\/].*\)\?$" # match something that is not comment, string or character: 2 backreferences export ccode="\([^\/\"']*\|\/[^\*\/]\|\/\*\([^\*]*\|\**[^\/\*]\)*\*\+\/\|'[^']*'\|\"[^\"]*\"\)*" # resp function open and end (only works when indentation is correct. export fo="^[\{]$cendl" export fe="^[\}]$cendl" # works similar to git-grep -n "$query" | tr ":" " " # except that :'s in the line are preserved ggrep2fnl() { git-grep -n "$1" | while read fnl; do f="$(echo "$fnl"| cut -d":" -f1)"; e="$(echo "$f" | rev | cut --complement -c3- | rev)"; [ "$e" != ".h" -a "$e" != ".c" ] && continue; echo "$f $(echo "$fnl"| cut -d":" -f2) $(echo "$fnl"| cut -d":" -f3-)"; done } #print function declaration at file "$1", line "$2" # also works for /path/to/filename.c:nr getfuncat() { if [ "$#" -eq 1 ]; then f="${1%[:-]*}" l="${1##*[:-]}" else f="$1" l="$2" fi Z="@[:space:]" a="[^()]*" func="\(${V}[$Z]\+\)*${V}[*$Z]\+$V$s($a\(($a\(($a\(($a)$a\)*)$a\)*)$a\)*$a)" eol="[$Z]*\([$Z]\|\/\/[^@]*@\|\/\*\([^\*]*\|\**[^\/\*]\)*\*\+\/\)*@{" head -n$l "$f" | tr "\n" "@" | sed -n "s/.*@\($func\)$eol.*/\1@@/p" | tail -n1 | tr "@" "\n" } #print function declaration(s) getfunc() { q="^\(${V}[*&[:space:]]\+\)*$1$s(${ccode}[^;]$cendl"; ggrep2fnl "$q" | while read f n l; do [ -z "`echo $l | grep "{$cendl"`" -a \ -n "`sed -n "$n,/{$cendl/{/;/p}" "$f"`" ] && continue echo "//---[ vi $f +$n ]---" [ -n "`echo $l | grep "^$s$1"`" ] && let "n--" sed -n "$n,/$fe/p" "$f" done } # helper to print definition(s) / macro(s) _getdef() { ggrep2fnl "$2" | while read f n l; do echo "---[ vi $f +$n ]---" 1>&2 if [ -z `echo $l | grep "\\$cendl"` ]; then echo $l else sed -n "/$2/,/[^\\]$cendl/p" "$f" fi done } #print definition(s) / macro(s) getdef() { _getdef "$1" "^$s#${s}define$S$1\(([^()]*)\)\?$S" } #print only macro(s) getmac() { _getdef "$1" "^$s#${s}define$S$1([^()]*)$S" } #print function declaration(s) / definition(s) / macro(s) getfod() { getfunc $1; getdef $1; } #print macro(s) or function declaration(s) getfom() { getfunc $1; getmac $1; } # echoes "function name" at file "$1" line "$2" det_func() { q="^\(${V}[*&[:space:]]\+\)*\($V\)$s(${ccode}[^;]$cendl" head "$1" -n"$2" | tac | sed -n "/$q/{s/$q/\2/p;q}" } getcalls() { git-grep -n "\(^\|^$ccode$Q\)$1$s(\($ccode\()$s;\|[^)]\|)$ccode)$ccode\)\)\?$cendl" } }}} To translate a module name (as listed in modprobe -l or modinfo -n ''module'') into a kernel .config option: {{{ #!/bin/bash mod="${1%.ko}"; dir="${1%/*}"; sed -e :a -e '/\\$/N; s/\\\n//; ta' "${dir#*/kernel/}/Makefile" | \ sed -n "s/^obj-\$(CONFIG_\([A-Z0-9_]*\))\W*+=\W*"${mod##*/}"\.o$/\1/p"; }}} Based on Linus' script to get the email address of a maintainer, I wrote this script to get the address of a list rather than a maintainers address for mailing. {{{ git log --since="1 year ago" "$@" | sed -n "s/^ .[-a-z]*by: \(.*\) <.*$/\1/p" | sort | uniq | sort -n -r | while read name; do sed -n "/^P:[ \t]*.*$name/,/^$/{ s/^L:[ \t]*\(.*\)$/\1/p }" ./MAINTAINERS done | sort | uniq -c | sort -n -r | while read nr list; do tot=`grep -c "^L:\W*.*$list.*" ./MAINTAINERS` echo "`expr $nr / \( $tot + 1 \)` $nr $tot $list" done | sort -r | cut -d " " -f2- | while read nr tot list; do echo -e "$nr/$tot Acks were commited by maintainers of list $list" done }}}