• Immutable Page
  • Info
  • Attachments

roelkluin/cvars

The script below can be used for static code analysis. It requires git, sed and grep

# (c) Roel Kluin, 2009, GPL v2.
#!/bin/bash

# does git grep -n -E [options] "$(bli2 "[query]")".
gg()
{
 local opts; local q; local opts
 while [ $# -ne 0 ]; do
  [ "${1:0:2}" = "--" ] && break;
  if [ "${1:0:1}" = "-" ]; then
   opts="${opts:+$opts }${q:+$q }$1";
   q=""
  else
   q="$1"
  fi
  shift;
 done
 git grep -n -E $opts "$(bli2 "$q")" $@
}

# blank_it: creates extended regular expressions
bli2()
{
local int="[[:digit:]]"
local hex="[[:xdigit:]]"
local up_="[[:upper:]_]"
local al_="[[:alpha:]_]"
local AN_="[[:upper:][:digit:]_]"
local an_="[[:alnum:]_]"
local sp="[[:space:]]"
local ns="[^[:space:]]"
local V="$al_+$an_*"
local em='!'

local l="$1"
l="${l//@&...@/(&+\(-..\))*}"                                                   # 4 backrefs
l="${l//@|...@/(\|+\(-..\))*}"                                                  # 4 backrefs
l="${l//@&...&@/&+@...&@}"                                                      # 4 backrefs
l="${l//@|...|@/\|+@...|@}"                                                     # 4 backrefs
l="${l//@...&@/(\(-..\)&+)*}"                                                   # 4 backrefs
l="${l//@...|@/(\(-..\)\|+)*}"                                                  # 4 backrefs
l="${l//@&|...@/([&|]+\(-..\))*}"                                               # 4 backrefs
l="${l//@&|...&|@/[&|]+@...&|@}"                                                # 4 backrefs
l="${l//@...&|@/(\(-..\)[&|]+)*}"                                               # 4 backrefs
l="${l//\\\(-8.\\\)/[^()|&;]*(\(.8.\)[^()|&;]*)*}"                              # 9 backrefs
l="${l//\\\(-..\\\)/[^()|&;]*(\(...\)[^()|&;]*)*}"                              # 3 backrefs
l="${l//\\\(...\\\)/\([^();]*(\([^();]*(\([^();]*\)[^();]*)*\)[^();]*)*\)}"     # 2 backrefs
l="${l//\\\(.8.\\\)/\([^();]*(\([^();]*(\([^();]*(\([^();]*(\([^();]*(\([^();]*(\([^();]*(\([^();]*(\([^();]*\)[^();]*)*\)[^();]*)*\)[^();]*)*\)[^();]*)\)[^();]*)*\)[^();]*)*\)[^();]*)*\)[^();]*)*\)}"                # 8 backrefs
l="${l//\\\[...\\\]/\[[^][]*(\[[^][]*(\[[^][]*\][^][]*)*\][^][]*)*\]}"          # 2 backrefs
l="${l//@V/$V}"
l="${l//@Q2/[^[:alnum:]_>.]}"
l="${l//@Q1/[^[:alnum:]_.-]}"
l="${l//@Q/[^[:alnum:]_]}"
l="${l//@d/($int+[uUlLfF]?|$int+[uU]?[lL][lL]?|0x$hex+|$int+[lL][lL][uU]|$int*\.$int+[fF]?)}"
l="${l//@K/$up_+$AN_*}"
l="${l//@s/ }"
l="${l//@n/([^\n]*\n)*}"
l="${l//@S/$sp+}"
l="${l//\\$em/$em}"
l="${l//\\t/$(echo -e "\t")}"
l="${l//@w/($V| \. | -> |\[ [^][]* \]|\( [^)(]* \))+}"
# warning: @dstring is impossible because of previous parsing of @d
 echo "$l" | sed -r "
:a
s/@branch/\(\\\\\{\.\.\.\\\\\}\|\[\^\{\};\]\*;\)/g              # 2 backrefs
s/@in_branches/\(\\\\\{\\\\\{-\.\.\\\\\}\)+/g                   # 4 backrefs
s/@in_branch/\(\\\\\{\\\\\{-\.\.\\\\\}\)\?/g                    # 4 backrefs
s/@branch8/\(\\\\\{\.8\.\\\\\}\|\[\^\{\};\]\*;\)/g              # 9 backrefs
s/\\\\\{-\.\.\\\\\}/\[^\}\{\]*\(\\\\\{...\\\\\}\[^\}\{\]*\)*/g  # 3 backrefs
s/\\\\\{-8\.\\\\\}/\[^\}\{\]*\(\\\\\{.8.\\\\\}\[^\}\{\]*\)*/g   # 9 backrefs
s/\\\\\{\.\.\.\\\\\}/\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}/g     # 2 backrefs
s/\\\\\{\.8\.\\\\\}/\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*(\\\\\{\[^\}\{\]*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}\[^\}\{\]*)*\\\\\}/g            # 8 backrefs

s/($an_)$sp+($an_)/\1$sp+\2/g
s/((^|[^\\\\])\[\^?([^][[:space:]]*|\[:[^][]+:\])*)($sp+)/\1@\4@/g
s/([^@[:space:]]|^)$sp+/\1$sp*/g
s/@($sp+)@/\1/g
$!{
 N
 ba
}
"
}

# echoes a sed script to filter multiline grep -n -H to display only
# the ones with particular patterns. The last eregex determines what
# is displayed, unless one of the eregexes before the last - if any -
# match.
#
# e.g. grep -E -n -H -B1 -A10 "foo" ~/file | sed -n -r "$(ecsed2 "foo.*bar" "foo")"
# searches for lines with `foo', not followed by `bar'
ecsed2()
{
local match= exclude print catchrefs l;
local op_sp="[ $(echo -e "\t")]*"
while [ $# -ne 1 ]; do
 if [ -n "$1" ]; then
  if [ "${1:0:6}" = "--sed=" ]; then
   exclude="${1:6}";
  elif [ "${1:0:11}" = "--backrefs=" ]; then
   catchrefs="${1:11}";
  elif [ "${1:0:10}" = "--prepend=" ]; then
   match="${1:10}";
  else
   #echo "excluded:^[^\n]*\n.*$match$1" 1>&2
   exclude="$exclude
/$(bli2 "^[^\n]*\n.*$match$1")/b" # the first line is the vi file +line printing
  fi
 fi
 shift
done
match="$match$1"
[ -z "$catchrefs" ] && catchrefs="$(echo "$match" | grep -o -E "\\\\[1-9]" | sort | uniq)"
for l in $catchrefs; do
 print="${print:+$print, }${l:1:1}: $l"
done
match="$(bli2 "^[^\n]*\n.*$match")"
print="${print:+h;s/$match.*$/----[ backrefs: $print ]----/p;x;}
s/^([^[:space:]]+)[:-]([1-9][0-9]*).(.*)$/---[ vi \1 +\2 ]---\3/p"
echo "
/^--$/b
s/^([^[:space:]]+[:-][1-9][0-9]*.)/\1\n/
:loop
H
\$!{
 n
 /^--$/!{
  s/^[^[:space:]]+[:-][1-9][0-9]*.//
  /^\}/!b loop
  /^\{/{
   x
   s/$(bli2 "^([^\n]*\n)(.*@Q2)?(@V\(.8.\) \n\{[^\n]*)")$/\1\3/
   x
  }
 }
}
x
s/^[^\n]*\n//
/$match/!b
/(\*\/|\/[\/*])/{
 s/($op_sp\/\*+|^([^\n]*\n))([^\/]*|\/*[^*\/])*\*+\//\2/g
 /\/[\/*]/ s/$op_sp\/(\/[^\n]*((\n|$))|\*+([^*]*|\**[^*\/])*$)/\3/g
}
/$match/!b
$exclude
$print
"
}


# gres does something like
# git grep -E -n [-opts] "$(bli2 "$1")" -- '*.c' '*.h' | sed -n -r "$(ecsed2 "${@:2})"
gres()
{
 local opts gq sq eopts fil tim;
 while [ $# -ne 0 ]; do
  if [ "${1:0:1}" != "-" ]; then
   break;
  fi
  if [ "${1:0:6}" = "--time" ]; then
   tim="time";
  elif [ "${1:0:10}" = "--prepend=" ]; then
   gq="${1:10}";
  elif [ "${1:0:6}" = "--FiL=" ]; then
   fil="${1:6}";
  elif [ "${1:0:11}" = "--backrefs=" ]; then
   eopts="${eopts:+$eopts }$1";
  elif [ "${1:0:6}" = "--sed=" ]; then
   eopts="${eopts:+$eopts }$1";
  else
   opts="${opts:+$opts }$1";
  fi
  shift;
 done
 if [ -n "$fil" ]; then
  sq="$(ecsed2 "$prt" $eopts "$@")"
  $tim sed -n -r "$sq" "$fil"
 elif [ -z "$(echo "$opts" | grep -o "[-][ACB][1-9]")" ]; then
  echo "gres without --FiL=... requires an -[ABC]n Context argument, otherwise use grep"
  return;
 fi
 if [ -z "$gq" ]; then
  gq="$(bli2 "$1")";
  sq="$(ecsed2 "$prt" $eopts "${@:2}")"
 else
  gq="$(bli2 "$gq")"
  sq="$(ecsed2 "$prt" $eopts "--PrE=$gq" "$@")";
 fi
 $tim git grep -E -n $opts "$gq" -- '*.c' '*.h' 2>&1 | sed -n -r "$sq"
}

To use, save, e.g. as ~/bin/cvars.sh, and source it.

For examples see examples on my page

Tell others about this page:

last edited 2010-02-13 21:31:12 by roelkluin