1cabdff1aSopenharmony_ci#!/bin/sh
2cabdff1aSopenharmony_ci
3cabdff1aSopenharmony_ci# if no argument provided, write stdin to a file and re-run the script
4cabdff1aSopenharmony_ciif [ $# = 0 ]; then
5cabdff1aSopenharmony_ci    cat > patcheck.stdout
6cabdff1aSopenharmony_ci    $0 patcheck.stdout
7cabdff1aSopenharmony_ci    rm -f patcheck.stdout
8cabdff1aSopenharmony_ci    exit
9cabdff1aSopenharmony_cifi
10cabdff1aSopenharmony_ci
11cabdff1aSopenharmony_ciGREP=grep
12cabdff1aSopenharmony_ciEGREP=egrep
13cabdff1aSopenharmony_ciTMP=patcheck.tmp
14cabdff1aSopenharmony_ciOPT="-nH"
15cabdff1aSopenharmony_ci#FILES=$($GREP '^+++' $* | sed 's/+++ //g')
16cabdff1aSopenharmony_ci
17cabdff1aSopenharmony_ciecho patCHeck 1e10.0
18cabdff1aSopenharmony_ciecho This tool is intended to help a human check/review patches. It is very far from
19cabdff1aSopenharmony_ciecho being free of false positives and negatives, and its output are just hints of what
20cabdff1aSopenharmony_ciecho may or may not be bad. When you use it and it misses something or detects
21cabdff1aSopenharmony_ciecho something wrong, fix it and send a patch to the ffmpeg-devel mailing list.
22cabdff1aSopenharmony_ciecho License: GPL, Author: Michael Niedermayer
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ciERE_PRITYP='(unsigned *|)(char|short|long|int|long *int|short *int|void|float|double|(u|)int(8|16|32|64)_t)'
25cabdff1aSopenharmony_ciERE_TYPES='(const|static|av_cold|inline| *)*('$ERE_PRITYP'|[a-zA-Z][a-zA-Z0-9_]*)[* ]{1,}[a-zA-Z][a-zA-Z0-9_]*'
26cabdff1aSopenharmony_ciERE_FUNCS="$ERE_TYPES"' *\('
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_cihiegrep(){
29cabdff1aSopenharmony_ci    arg="$1"
30cabdff1aSopenharmony_ci    msg="$2"
31cabdff1aSopenharmony_ci    shift 2
32cabdff1aSopenharmony_ci    $GREP $OPT '^+' $* | $GREP -v ':+++'| $EGREP --color=always -- "$arg"> $TMP && printf "\n$msg\n"
33cabdff1aSopenharmony_ci    cat $TMP
34cabdff1aSopenharmony_ci}
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_cihiegrep2(){
37cabdff1aSopenharmony_ci    arg="$1"
38cabdff1aSopenharmony_ci    varg="$2"
39cabdff1aSopenharmony_ci    msg="$3"
40cabdff1aSopenharmony_ci    shift 3
41cabdff1aSopenharmony_ci    $GREP $OPT '^+' $* | $GREP -v ':+++' | $EGREP -v -- "$varg" | $EGREP --color=always -- "$arg" > $TMP && printf "\n$msg\n"
42cabdff1aSopenharmony_ci    cat $TMP
43cabdff1aSopenharmony_ci}
44cabdff1aSopenharmony_ci
45cabdff1aSopenharmony_cihiegrep 'static[^(]*\*[a-zA-Z_]*\[' 'pointer array is not const' $*
46cabdff1aSopenharmony_cihiegrep '[[:space:]]$'    'trailing whitespace' $*
47cabdff1aSopenharmony_cihiegrep "$(echo x | tr 'x' '\t')"         'tabs' $*
48cabdff1aSopenharmony_ci#hiegrep ':\+$'          'Empty lines' $*
49cabdff1aSopenharmony_cihiegrep ';;'              'double ;' $*
50cabdff1aSopenharmony_cihiegrep2 '\b_[a-zA-Z0-9_]{1,}' '__(asm|attribute)([^a-zA-Z0-9]|$)' 'reserved identifer' $*
51cabdff1aSopenharmony_cihiegrep '//[-/<\* ]*$'    'empty comment' $*
52cabdff1aSopenharmony_cihiegrep '/\*[-<\* ]*\*/'  'empty comment' $*
53cabdff1aSopenharmony_cihiegrep '(static|inline|const) *\1[^_a-zA-Z]'  'duplicate word' $*
54cabdff1aSopenharmony_cihiegrep 'INIT_VLC_USE_STATIC' 'forbidden ancient vlc type' $*
55cabdff1aSopenharmony_cihiegrep '=[-+\*\&] ' 'looks like compound assignment' $*
56cabdff1aSopenharmony_cihiegrep2 '/\*\* *[a-zA-Z0-9].*' '\*/' 'Inconsistently formatted doxygen comment' $*
57cabdff1aSopenharmony_cihiegrep '; */\*\*[^<]' 'Misformatted doxygen comment' $*
58cabdff1aSopenharmony_cihiegrep '//!|/\*!' 'inconsistent doxygen syntax' $*
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_cihiegrep2 '(int|unsigned|static|void)[a-zA-Z0-9 _]*(init|end)[a-zA-Z0-9 _]*\(.*[^;]$' '(av_cold|:\+[^a-zA-Z_])' 'These functions may need av_cold, please review the whole patch for similar functions needing av_cold' $*
61cabdff1aSopenharmony_ci
62cabdff1aSopenharmony_cihiegrep '\+= *1 *;'     'can be simplified to ++' $*
63cabdff1aSopenharmony_cihiegrep '-= *1 *;'      'can be simplified to --' $*
64cabdff1aSopenharmony_cihiegrep '((!|=)= *(0|NULL)[^0-9a-z]|[^0-9a-z](0|NULL) *(!|=)=)' 'x==0 / x!=0 can be simplified to !x / x' $*
65cabdff1aSopenharmony_ci
66cabdff1aSopenharmony_ci$EGREP $OPT '^\+ *(const *|)static' $*| $EGREP --color=always '[^=]= *(0|NULL)[^0-9a-zA-Z]'> $TMP && printf '\nuseless 0 init\n'
67cabdff1aSopenharmony_cicat $TMP
68cabdff1aSopenharmony_cihiegrep '# *ifdef * (HAVE|CONFIG)_' 'ifdefs that should be #if' $*
69cabdff1aSopenharmony_ci
70cabdff1aSopenharmony_cihiegrep '\b(awnser|cant|dont|wont|doesnt|usefull|successfull|occured|teh|alot|wether|skiped|skiping|heigth|informations|colums|loosy|loosing|ouput|seperate|preceed|upto|paket|posible|unkown|inpossible|dimention|acheive|funtions|overriden|outputing|seperation|initalize|compatibilty|bistream|knwon|unknwon|choosen|additonal|gurantee|availble|wich|begining|milisecond|missmatch|threshhold)\b' 'common typos' $*
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_cihiegrep 'av_log\( *NULL' 'Missing context in av_log' $*
73cabdff1aSopenharmony_cihiegrep '[^sn]printf' 'Please use av_log' $*
74cabdff1aSopenharmony_cihiegrep '\bmalloc' 'Please use av_malloc' $*
75cabdff1aSopenharmony_cihiegrep '\) *av_malloc' 'useless casts' $*
76cabdff1aSopenharmony_cihiegrep ':\+ *'"$ERE_PRITYP"' *inline' 'non static inline or strangely ordered inline+static' $*
77cabdff1aSopenharmony_cihiegrep "$ERE_FUNCS"' *\)' 'missing void' $*
78cabdff1aSopenharmony_cihiegrep '(sprintf|strcat|strcpy)' 'Possible security issue, make sure this is safe or use snprintf/av_strl*' $*
79cabdff1aSopenharmony_cihiegrep '/ *(2|4|8|16|32|64|128|256|512|1024|2048|4096|8192|16384|32768|65536)[^0-9]' 'divide by 2^x could use >> maybe' $*
80cabdff1aSopenharmony_cihiegrep '#(el|)if *(0|1)' 'useless #if' $*
81cabdff1aSopenharmony_cihiegrep 'if *\( *(0|1) *\)' 'useless if()' $*
82cabdff1aSopenharmony_cihiegrep '& *[a-zA-Z0-9_]* *\[ *0 *\]' 'useless & [0]' $*
83cabdff1aSopenharmony_cihiegrep '(\( *[0-9] *(&&|\|\|)|(&&|\|\|) *[0-9] *\))' 'overriding condition' $*
84cabdff1aSopenharmony_cihiegrep '(:\+|,|;)( *|static|\*)*'"$ERE_PRITYP"' *\*( |\*)*(src|source|input|in[^a-z])' 'missing const?' $*
85cabdff1aSopenharmony_cihiegrep '(:\+|,|;)( *|static|\*)*'"$ERE_PRITYP"' *(src|source|input|in)([0-9A-Z_][0-9A-Za-z_]*){1,} *\[' 'missing const (test2)?' $*
86cabdff1aSopenharmony_cihiegrep ' *static *'"$ERE_FUNCS"'[^)]*\);' 'static prototype, maybe you should reorder your functions' $*
87cabdff1aSopenharmony_cihiegrep '@file: *[a-zA-Z0-9_]' 'doxy filetag with filename can in the future cause problems when forgotten during a rename' $*
88cabdff1aSopenharmony_cihiegrep '\bassert' 'Please use av_assert0, av_assert1 or av_assert2' $*
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_cihiegrep2 '\.long_name *=' 'NULL_IF_CONFIG_SMAL' 'missing NULL_IF_CONFIG_SMAL' $*
91cabdff1aSopenharmony_cihiegrep2 '\.pix_fmts *= *\(' 'const' 'missing const for pix_fmts array' $*
92cabdff1aSopenharmony_cihiegrep2 '\.sample_fmts *= *\(' 'const' 'missing const for sample_fmts array' $*
93cabdff1aSopenharmony_cihiegrep2 '\.supported_framerates *= *\(' 'const' 'missing const for supported_framerates array' $*
94cabdff1aSopenharmony_cihiegrep2 '\.channel_layouts *= *\(' 'const' 'missing const for channel_layouts array' $*
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_ci#$EGREP $OPT '^\+.*const ' $*| $GREP -v 'static'> $TMP && printf '\nnon static const\n'
97cabdff1aSopenharmony_ci#cat $TMP
98cabdff1aSopenharmony_ci
99cabdff1aSopenharmony_cihiegrep2 "$ERE_TYPES" '(static|av_|ff_|typedef|:\+[^a-zA-Z_])' 'Non static with no ff_/av_ prefix' $*
100cabdff1aSopenharmony_ci
101cabdff1aSopenharmony_cihiegrep ':\+[^}#]*else' 'missing } prior to else' $*
102cabdff1aSopenharmony_cihiegrep '(if|while|for)\(' 'missing whitespace between keyword and ( (feel free to ignore)' $*
103cabdff1aSopenharmony_cihiegrep '(else|do){'       'missing whitespace between keyword and { (feel free to ignore)' $*
104cabdff1aSopenharmony_cihiegrep '}(else|while)'    'missing whitespace between } and keyword (feel free to ignore)' $*
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ci#FIXME this should print the previous statement maybe
107cabdff1aSopenharmony_cihiegrep ':\+  *{ *$' '{ should be on the same line as the related previous statement' $*
108cabdff1aSopenharmony_ci
109cabdff1aSopenharmony_ci
110cabdff1aSopenharmony_cirm $TMP
111cabdff1aSopenharmony_cifor i in $($GREP -H '^+.*@param' $*| sed 's/^\([^:]*\):.*@param\(\[.*\]\|\) *\([a-zA-Z0-9_]*\) .*$/\1:\3/') ; do
112cabdff1aSopenharmony_ci    doxpar=$(echo $i | sed 's/^.*:\(.*\)$/\1/')
113cabdff1aSopenharmony_ci    file=$(echo $i | sed 's/^\([^:]*\):.*$/\1/')
114cabdff1aSopenharmony_ci    $GREP " *$doxpar *[),]" $file | $GREP -v '@param' >/dev/null || $GREP --color=always "@param *$doxpar" $file >>$TMP
115cabdff1aSopenharmony_cidone
116cabdff1aSopenharmony_ciif test -e $TMP ; then
117cabdff1aSopenharmony_ci    printf '\nmismatching doxy params\n'
118cabdff1aSopenharmony_ci    cat $TMP
119cabdff1aSopenharmony_cifi
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci$EGREP -B2 $OPT '^(\+|) *('"$ERE_TYPES"'|# *define)' $* | $EGREP -A2 --color=always '(:|-)\+[^/]*/(\*([^*]|$)|/([^/]|$))' > $TMP && printf "\n Non doxy comments\n"
122cabdff1aSopenharmony_cicat $TMP
123cabdff1aSopenharmony_ci
124cabdff1aSopenharmony_cirm $TMP
125cabdff1aSopenharmony_cifor i in \
126cabdff1aSopenharmony_ci    $($EGREP -H '^\+ *'"$ERE_TYPES" $*  |\
127cabdff1aSopenharmony_ci    $GREP -v '(' | $EGREP -v '\Wgoto\W' |\
128cabdff1aSopenharmony_ci    xargs -d '\n' -n 1 |\
129cabdff1aSopenharmony_ci    $GREP -o '[* ][* ]*[a-zA-Z][0-9a-zA-Z_]* *[,;=]' |\
130cabdff1aSopenharmony_ci    sed 's/.[* ]*\([a-zA-Z][0-9a-zA-Z_]*\) *[,;=]/\1/') \
131cabdff1aSopenharmony_ci    ; do
132cabdff1aSopenharmony_ci    echo $i | $GREP '^NULL$' && continue
133cabdff1aSopenharmony_ci    $EGREP $i' *(\+|-|\*|/|\||&|%|)=[^=]' $* >/dev/null || echo "possibly never written:"$i >> $TMP
134cabdff1aSopenharmony_ci    $EGREP '(=|\(|return).*'$i'(==|[^=])*$'    $* >/dev/null || echo "possibly never read   :"$i >> $TMP
135cabdff1aSopenharmony_ci    $EGREP -o $i' *((\+|-|\*|/|\||&|%|)=[^=]|\+\+|--) *(0x|)[0-9]*(;|)'   $* |\
136cabdff1aSopenharmony_ci           $EGREP -v $i' *= *(0x|)[0-9]{1,};'>/dev/null || echo "possibly constant     :"$i >> $TMP
137cabdff1aSopenharmony_cidone
138cabdff1aSopenharmony_ciif test -e $TMP ; then
139cabdff1aSopenharmony_ci    printf '\npossibly unused variables\n'
140cabdff1aSopenharmony_ci    cat $TMP
141cabdff1aSopenharmony_cifi
142cabdff1aSopenharmony_ci
143cabdff1aSopenharmony_ci$GREP '^+++ .*Changelog' $* >/dev/null || printf "\nMissing changelog entry (ignore if minor change)\n"
144cabdff1aSopenharmony_ci
145cabdff1aSopenharmony_cicat $* | $GREP -v '^-' | tr '\n' '@' | $EGREP --color=always -o '(fprintf|av_log|printf)\([^)]*\)[+ ;@]*\1'  >$TMP && printf "\nMergeable calls\n"
146cabdff1aSopenharmony_cicat $TMP | tr '@' '\n'
147cabdff1aSopenharmony_ci
148cabdff1aSopenharmony_cicat $* | tr '\n' '@' | $EGREP --color=always -o '\+ *if *\( *([A-Za-z0-9_]*) *[<>]=? *[0-9]* *\) * \1 *= *[0-9]* *;[ @\\+]*else *if *\( *\1 *[<>]=? *[0-9]* *\) *\1 *= *[0-9]* *;'  >$TMP && printf "\nav_clip / av_clip_uint8 / av_clip_int16 / ...\n"
149cabdff1aSopenharmony_cicat $TMP | tr '@' '\n'
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_cicat $* | tr '\n' '@' | $EGREP --color=always -o '\+ *if *\( *([A-Za-z0-9_]*) *[<>]=? *([A-Za-z0-9_]*) *\)[ @\\+]*(\1|\2) *= *(\1|\2) *;'  >$TMP && printf "\nFFMIN/FFMAX\n"
152cabdff1aSopenharmony_cicat $TMP | tr '@' '\n'
153cabdff1aSopenharmony_ci
154cabdff1aSopenharmony_cicat $* | tr '\n' '@' | $EGREP --color=always -o '\+ *if *\( *([A-Za-z0-9_]*) *\)[ @\\+]*av_free(p|) *\( *(&|) *\1[^-.]'  >$TMP && printf "\nav_free(NULL) is safe\n"
155cabdff1aSopenharmony_cicat $TMP | tr '@' '\n'
156cabdff1aSopenharmony_ci
157cabdff1aSopenharmony_cicat $* | tr '\n' '@' | $EGREP --color=always -o '[^a-zA-Z0-9_]([a-zA-Z0-9_]*) *= *av_malloc *\([^)]*\)[ @;\\+]*memset *\( *\1'  >$TMP && printf "\nav_mallocz()\n"
158cabdff1aSopenharmony_cicat $TMP | tr '@' '\n'
159cabdff1aSopenharmony_ci
160cabdff1aSopenharmony_ci
161cabdff1aSopenharmony_ci# does not work
162cabdff1aSopenharmony_ci#cat $* | tr '\n' '@' | $EGREP -o '[^a-zA-Z_0-9]([a-zA-Z][a-zA-Z_0-9]*) *=[^=].*\1' | $EGREP -o '[^a-zA-Z_0-9]([a-zA-Z][a-zA-Z_0-9]*) *=[^=].*\1 *=[^=]'  >$TMP && printf "\nPossibly written 2x before read\n"
163cabdff1aSopenharmony_ci#cat $TMP | tr '@' '\n'
164cabdff1aSopenharmony_ci
165cabdff1aSopenharmony_ciexit
166cabdff1aSopenharmony_ci
167cabdff1aSopenharmony_ciTODO/idea list:
168cabdff1aSopenharmony_ci
169cabdff1aSopenharmony_cifor all demuxers & muxers
170cabdff1aSopenharmony_ci    $EGREP for "avctx->priv_data"
171cabdff1aSopenharmony_ci
172cabdff1aSopenharmony_civertical align =
173cabdff1aSopenharmony_ci/* and * align
174cabdff1aSopenharmony_ciarrays fitting in smaller types
175cabdff1aSopenharmony_civariables written to twice with no interspaced read
176cabdff1aSopenharmony_cimemset(block, 0, 6*64*sizeof(int16_t)); -> clear_blocks
177cabdff1aSopenharmony_cicheck existence of long_name in AVCodec
178cabdff1aSopenharmony_cicheck that the patch does not touch codec & (de)muxer layer at the same time ->split
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ciwrite a regression test containing at least a line that triggers each warning once
181