1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4 5ZEPHYR_BASE=$( builtin cd "$( dirname "$DIR" )" && pwd ${PWD_OPT}) 6DIR="$(dirname $(readlink -f $0))/.." 7SPATCH="`which ${SPATCH:=spatch}`" 8 9if [ ! -x "$SPATCH" ]; then 10 echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/' 11 exit 1 12fi 13 14VERBOSE=0 15usage="Usage: ./scripts/coccicheck [OPTIONS]... [DIRECTORY|FILE]... 16 17OPTIONS: 18------- 19 20-m= , --mode= specify the mode use {report, patch, org, context, chain} 21-v= , --verbose= enable verbose output {1} 22-j= , --jobs= number of jobs to use {0 - `nproc`} 23-c= , --cocci= specify cocci script to use 24-d= , --debug= specify file to store debug log 25-f= , --sp-flag= pass additional flag to spatch 26-h , --help display help and exit 27 28Default values if any OPTION is not supplied: 29-------------------------------------------- 30 31mode = report 32verbose = 0 (disabled) 33jobs = maximum jobs available on the machine 34cocci = all cocci scripts available at scripts/coccinelle/* 35 36If no [DIRECTORY|FILE] is supplied, entire codebase is processed. 37 38For detailed documentation refer: doc/guides/coccinelle.rst" 39 40for i in "$@" 41do 42 case $i in 43 -m=*|--mode=*) 44 MODE="${i#*=}" 45 shift # past argument=value 46 ;; 47 -v=*|--verbose=*) 48 VERBOSE="${i#*=}" 49 shift # past argument=value 50 ;; 51 -j=*|--jobs=*) 52 J="${i#*=}" 53 shift 54 ;; 55 -c=*|--cocci=*) 56 COCCI="${i#*=}" 57 shift 58 ;; 59 -d=*|--debug=*) 60 DEBUG_FILE="${i#*=}" 61 shift 62 ;; 63 -f=*|--sp-flag=*) 64 SPFLAGS="${i#*=}" 65 shift 66 ;; 67 -h|--help) 68 echo "$usage" 69 exit 1 70 ;; 71 *) 72 FILE="${i#*=}" 73 if [ ! -e "$FILE" ]; then 74 echo "unknown option: '${i#*=}'" 75 echo "$usage" 76 exit 2 77 fi 78 ;; 79 esac 80done 81 82FLAGS="--very-quiet" 83 84if [ "$FILE" = "" ] ; then 85 OPTIONS="--dir $ZEPHYR_BASE" 86else 87 OPTIONS="--dir $FILE" 88fi 89 90if [ -z "$J" ]; then 91 NPROC=$(getconf _NPROCESSORS_ONLN) 92else 93 NPROC="$J" 94fi 95 96OPTIONS="--macro-file $ZEPHYR_BASE/scripts/coccinelle/macros.h $OPTIONS" 97 98if [ "$FILE" != "" ] ; then 99 OPTIONS="--patch $ZEPHYR_BASE $OPTIONS" 100fi 101 102if [ "$NPROC" != "1" ]; then 103 # Using 0 should work as well, refer to _SC_NPROCESSORS_ONLN use on 104 # https://github.com/rdicosmo/parmap/blob/master/setcore_stubs.c 105 OPTIONS="$OPTIONS --jobs $NPROC --chunksize 1" 106fi 107 108if [ "$MODE" = "" ] ; then 109 echo 'You have not explicitly specified the mode to use. Using default "report" mode.' 110 echo 'Available modes are the following: 'patch', 'report', 'context', 'org'' 111 echo 'You can specify the mode with "./scripts/coccicheck --mode=<mode>"' 112 echo 'Note however that some modes are not implemented by some semantic patches.' 113 MODE="report" 114fi 115 116if [ "$MODE" = "chain" ] ; then 117 echo 'You have selected the "chain" mode.' 118 echo 'All available modes will be tried (in that order): patch, report, context, org' 119elif [ "$MODE" = "report" -o "$MODE" = "org" ] ; then 120 FLAGS="--no-show-diff $FLAGS" 121fi 122 123 echo '' 124 echo 'Please check for false positives in the output before submitting a patch.' 125 echo 'When using "patch" mode, carefully review the patch before submitting it.' 126 echo '' 127 128run_cmd_parmap() { 129 if [ $VERBOSE -ne 0 ] ; then 130 echo "Running ($NPROC in parallel): $@" 131 fi 132 echo $@ >>$DEBUG_FILE 133 $@ 2>>$DEBUG_FILE 134 err=$? 135 if [[ $err -ne 0 ]]; then 136 echo "coccicheck failed" 137 exit $err 138 fi 139} 140 141# You can override heuristics with SPFLAGS, these must always go last 142OPTIONS="$OPTIONS $SPFLAGS" 143 144coccinelle () { 145 COCCI="$1" 146 OPT=`grep "Options:" $COCCI | cut -d':' -f2` 147 VIRTUAL=`grep "virtual" $COCCI | cut -d' ' -f2` 148 149 if [[ $VIRTUAL = "" ]]; then 150 echo "No available modes found in \"$COCCI\" script." 151 echo "Consider adding virtual rules to the script." 152 exit 1 153 elif [[ $VIRTUAL != *"$MODE"* ]]; then 154 echo "Invalid mode \"$MODE\" supplied!" 155 echo "Available modes for \"`basename $COCCI`\" are: "$VIRTUAL"" 156 157 if [[ $VIRTUAL == *report* ]]; then 158 MODE=report 159 elif [[ $VIRTUAL == *context* ]]; then 160 MODE=context 161 elif [[ $VIRTUAL == *patch* ]]; then 162 MODE=patch 163 else 164 MODE=org 165 fi 166 echo "Using random available mode: \"$MODE\"" 167 echo '' 168 fi 169 170 if [ $VERBOSE -ne 0 ] ; then 171 172 FILE=${COCCI#$ZEPHYR_BASE/} 173 174 echo "Processing `basename $COCCI`" 175 echo "with option(s) \"$OPT\"" 176 echo '' 177 echo 'Message example to submit a patch:' 178 179 sed -ne 's|^///||p' $COCCI 180 181 if [ "$MODE" = "patch" ] ; then 182 echo ' The semantic patch that makes this change is available' 183 elif [ "$MODE" = "report" ] ; then 184 echo ' The semantic patch that makes this report is available' 185 elif [ "$MODE" = "context" ] ; then 186 echo ' The semantic patch that spots this code is available' 187 elif [ "$MODE" = "org" ] ; then 188 echo ' The semantic patch that makes this Org report is available' 189 else 190 echo ' The semantic patch that makes this output is available' 191 fi 192 echo " in $FILE." 193 echo '' 194 echo ' More information about semantic patching is available at' 195 echo ' http://coccinelle.lip6.fr/' 196 echo '' 197 198 if [ "`sed -ne 's|^//#||p' $COCCI`" ] ; then 199 echo 'Semantic patch information:' 200 sed -ne 's|^//#||p' $COCCI 201 echo '' 202 fi 203 fi 204 205 if [ "$MODE" = "chain" ] ; then 206 run_cmd_parmap $SPATCH -D patch \ 207 $FLAGS --cocci-file $COCCI $OPT $OPTIONS || \ 208 run_cmd_parmap $SPATCH -D report \ 209 $FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff || \ 210 run_cmd_parmap $SPATCH -D context \ 211 $FLAGS --cocci-file $COCCI $OPT $OPTIONS || \ 212 run_cmd_parmap $SPATCH -D org \ 213 $FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff || exit 1 214 elif [ "$MODE" = "rep+ctxt" ] ; then 215 run_cmd_parmap $SPATCH -D report \ 216 $FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff && \ 217 run_cmd_parmap $SPATCH -D context \ 218 $FLAGS --cocci-file $COCCI $OPT $OPTIONS || exit 1 219 else 220 run_cmd_parmap $SPATCH -D $MODE $FLAGS --cocci-file $COCCI $OPT $OPTIONS || exit 1 221 fi 222 223 MODE=report 224} 225 226if [ "$DEBUG_FILE" != "/dev/null" -a "$DEBUG_FILE" != "" ]; then 227 if [ -f $DEBUG_FILE ]; then 228 echo "Debug file \"$DEBUG_FILE\" exists, bailing ..." 229 exit 230 fi 231else 232 DEBUG_FILE="/dev/null" 233fi 234 235if [ "$COCCI" = "" ] ; then 236 for f in `find $ZEPHYR_BASE/scripts/coccinelle/ -name '*.cocci' -type f | sort`; do 237 coccinelle $f 238 echo '-------------------------------------------------------------------------' 239 echo '' 240 done 241else 242 coccinelle $COCCI 243fi 244