#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 -r 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 -r n; do
sed -n "/struct${s}sk_buff${s}\*${s}${n}/,/^[{}].*$/{ /kfree(${s}${n}${s})/= }" $f | while read -r 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 -r n; do
echo "$n"; 
done | 
sort | uniq -c | sort -rn | while read -r 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
}}}

catch tests below 0 on unsigned
{{{
# define what to search for
left_operator="\([;,|^?:(]\|[\!+*/%&|~^-]=\|>>=\|<<=\|\[\|&&\|$an_$s&\)"
right_operator="\([;,&|^?:)]\|[\!+*/%&|~^<>-]=\|>>=\|<<=\|>[^>]\|<[^<]\|\]\)"
variable="$s\(\(++\|--\)$w\|$w\(++\|--\)\|$w\)$s"
comparison="\(\(>=\|<\)${s}0\|\([><\!=]=\|[<>]\)$s-$s$D\)$s"
query="$left_operator$variable$comparison$right_operator"

arr="\(\[[^\]]*\]$s\)*"
attr="__attribute__$s(([^;]*))"
# for each unsigned typedefs
for ut in "unsigned" "unsigned long" $(
git-grep "^${s}typedef${S}unsigned$S\($V$S\)*\($V$s$arr\|$attr$S$V$s$arr\|$V$s$arr$S$attr\)$s;$cendl" | 
sed -n "s/^[^.]*\.[hc]:${s}typedef${S}unsigned$S\($V$S\)*\(\($V\)$s$arr\|$attr$S\($V\)$s$arr\|\($V\)$s$arr$S$attr\)$s;$cendl/\3\5\7/p" |
sort | uniq); do

# create the spatch
  cat > ../spatches/negative_unsigned.cocci << EOF
@@
constant C;
$ut i;
@@
(
* i < 0
|
* i < -C
|
* i > -C
|
* i <= -C
|
* i >= -C
)
EOF

  # find
  for f in $(git-grep -l "\(^\|$Q\)$ut\($Q\|$\)" | grep "[^.]*\.[ch]" | xargs grep -l "$query"); do
    spatch -quiet -all_includes -I ./include -sp_file ../spatches/negative_unsigned $f;
  done
done > ../spatch.log
}}}

to display the results of the previous patch as 'vi file +line' commands:
{{{
sed -n "s/^\(.\)\(-- \([^[:space:]]*\)[[:space:]]\|@ -\([0-9]*\),\|\).*$/\1 \3\4/p" ../spatch.log|
while read a b; do
  if [ "$a" = "-" ]; then
    if [ -f "$b" ]; then
      f="$b"
    elif [ -z "$b" ]; then
      echo "vi $f +$i";
      i=$(($i+1));
    fi
  elif [ "$a" = "@" ]; then
    i=$b;
  else
    i=$(($i+1));
  fi
done
}}}

== 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[:- ]linenr or 
# (as pasted from git-grep -n)
v()
{
  f="$1"
  [ $# -eq 2 ] && l=$2
  if [ ! -f "$f" ]; then
    l=${f##*[:-]};
    f="${f%[:-]*}";
  fi
  [ -f "$f" -a $l -gt 0 ] && vi "$f" +"$l";
}

export int="[0-9]"
export hex="[a-f0-9]"
export hEx="[A-Fa-f0-9]"
export HEX="[A-F0-9]"
export upp="[A-Z]"
export up_="[A-Z_]"
export low="[a-z0-9]"
export lo_="[a-z0-9_]"
export alp="[A-Za-z]"
export al_="[A-Za-z_]"
export ALN="[A-Z0-9]"
export AN_="[A-Z0-9_]"
export aln="[A-Za-z0-9]"
export an_="[A-Za-z0-9_]"
# to match something like 1ul, floats or hexes as well:
export D="$int*\.\?$int\+x\?$hex*[uUlL]\{0,3\}[fF]\?"

# more strict and catches it (costs one backreference for (git-)grep)
export d="\($int\+[uUlLfF]\?\|$int\+[uU]\?[lL][lL]\?\|0x$hex\+\|0x$HEX\+\|$i\+[lL][lL][uU]\|$i*\.$i\+[fF]\?\)"

# capital: can be used to catch a definition or config option
export K="$UP_\+$AN_*";

# can be used for a variable/function name:
export V="$an_\+$an_*"

# works the same as above, but also for members and arrays: one backreference
# is more strict
export W="$V\(\[$s$V$s\]\|\[$s$D$s\]\|\.$V\|->$V\)*"
# catches it at once (less strict)
export w="\($V\|${V}\[$s$an_*${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"

# to match nested parentheses
export nps="[^()]*"
export nstdps="\(($nps\(($nps\(($nps\(($nps\(($nps)$nps\)*)$nps\)*)$nps\)*)$nps\)*)$nps\)*"

# works similar to git-grep -n "$query" | tr ":" " "
# except that :'s in the line are preserved
ggrep2fnl()
{
  git-grep -n "$1" | while read -r 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()
{
  [ $# -ne 1 ] && return 1;
  f="${1%[:-]*}"
  [ ! -f "$f" ] && return 2;
  l="${1##*[:-]}"

  Z="[@[:space:]]"
  func="\($V$Z\+\)*${V}[*@[:space:]]\+$V$s($nps$nstdps)"
  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 -r 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
}

getstruct()
{
  q="^$s\($V$S\)*struct\(${S}__$V\($s($nps$nstdps)\)\?\)*$S$1\(${S}__$V\($s($nps$nstdps)\)\?\)*${s}[{]\?$cendl";
  ggrep2fnl "$q" | while read -r 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,/$se/p" "$f"
  done
}

getdef()
{
  del="[[:space:](]"
  sed_print=":a; /\\\\\\\\$/{N;ba}; p}"

  while getopts dmho Options; do
    case $Options in
      h) echo "getdef [options] DEFINITION_NAME(s)

print definition(s) / macro(s)

options
-d              print only definitions
-m              print only macros
-o              print as a single line (squeezes spaces)"
        return ;;
      d)
        del="[[:space:]]" ;;
      m)
        del="(" ;;
      o)
        sed_print=":a; /\\\\\\\\$/{N;ba}; s/\(\/\(\/.*\|\*\([^*]*\|\**[^\/]\)*\*\/$s\)\?\(\\\\\\\\\n\|$\)\|$S\)\+/ /g; s/^$S//g; p}" ;;
    esac
  done
while [ $OPTIND -gt 1 ]; do
  shift;
  OPTIND=$(($OPTIND-1));
done
  def="^$s#${s}define$S$1$del"
  for f in $(git-grep -l -I "$def"); do
    sed -n "/$def/,/[^\\\\]$/{/$def/=; $sed_print" "$f" |
    sed "/^[0-9]*$/s/^\([0-9]*\)$/\/\/---[ vi ${f//\//\\/} +\1 ]---/"
  done
}

# 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"
}

# get filename in git-diff with match $1 (matches from start of line)
# in after (default, $2 == "+") or before ($2 == "-") changes were made
gdfwm()
{
dil="+";
[ $# -eq 2 ] && dil="$2";
echo "$dil"
git-diff | grep "^\($dil\{3\}\|$dil$1$\)" | grep -B1 "^${dil}[^$dil]" | 
sed -n "s/^$dil\{3\} [^\/]*\/\([^\n]*\)$/\1/p"; 
}

# get filename and line in git-diff with match $1 (matches from start to end of line)
gdflwm()
{
git-diff |
sed -n "s/^\(.\)\(++ [^\/]*\/\(.*\)\|@ -[0-9]*,[0-9]* +\([0-9]*\),.*\|\($1\)\|.*\)$/\1 \3\4\5/p" |
while read a b; do
  if [ "$a" = "+" ]; then
    if [ -f "$b" ]; then
      f="$b"
    elif [ -n "$b" ]; then
      echo "$f $i";
      i=$(($i+1));
    fi
  elif [ "$a" = "@" ]; then
    i=$b;
  elif [ "$a" != "-" ]; then
    i=$(($i+1))
  fi
done
}
}}}

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 -r name; do
        sed -n "/^P:[ \t]*.*$name/,/^$/{
                s/^L:[ \t]*\(.*\)$/\1/p
        }" ./MAINTAINERS
done | sort | uniq -c | sort -n -r | while read -r 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 -r nr tot list; do
        echo -e "$nr/$tot Acks were commited by maintainers of list $list"
done
}}}