I have been responsible for Coverity tool integration/test/support in ALU LCP (Linux Control Platform) dept for nearly 2 years. In this post, I would share a ksh tool/framework wrote on 2009 for Coverity modeling build automation. However, I would not involve too many things on Coverity itself (except the necessary background) but rather than some code examples to show one way to write multiple-choice menu via shell (如何用SHELL写多选菜单)- that’s is my point. Of course, if cmbat itself would give you a hint, thank God:)
Coverity: Coverity is a static code analysis tool developed by Coverity Inc. (It is said the biggest and strongest company on static code analysis. Another 2 famous ones you may heard of are Klocwork and Insure++)
Coverity modeling: Because of path limitation of analysis, some functions are unable to be analyzed. Coverity modeling is used to downsize these functions helping Coverity itself doing analysis on them. (There are also other usages on modeling, please refer to Coverity document. How to write Coverity modeling is not covered in this post the either way.)
cmbat: The basic idea is to construct modeling for some important functions (such as memory allocation/deallocation in our case). Then construct the corresponding modeling lib used by cmbat. The last thing is to write an automation tool (ksh in our case) according to your Coverity integration way. Again, please focus on the way to implement multiple-choice menu via shell.
/home/daveti/cmbat/libcov_mm: ll
total 10
drwxr-xr-x 4 daveti daveti 5 Jan 8 03:07 ims
-rw-r--r-- 1 daveti daveti 246 Jan 8 03:07 ims.map
-rw-r--r-- 1 daveti daveti 1094 Jan 8 03:07 ims_rmm.map
drwxr-xr-x 4 daveti daveti 5 Jan 8 03:07 msc
-rw-r--r-- 1 daveti daveti 335 Jan 8 03:07 msc.map
-rw-r--r-- 1 daveti daveti 1184 Jan 8 03:07 msc_rmm.map
drwxr-xr-x 4 daveti daveti 5 Jan 8 03:07 rmm
-rw-r--r-- 1 daveti daveti 851 Jan 8 03:07 rmm.map
/home/daveti/cmbat/libcov_mm: cat ims.map
1:$IMSLIB/alloc/SIPia_Create_1xx_Response.c
2:$IMSLIB/alloc/SIPia_Create_Final_Response.c
3:$IMSLIB/alloc/SIPia_Build_Request.c
4:$IMSLIB/alloc/SIPia_clone.c
5:$IMSLIB/alloc/SIPia_new.c
6:$IMSLIB/dealloc/SIPia_delete.c
7:$IMSLIB/ims_all.c
8:Quit
#!/opt/ksh93e/bin/ksh
##########################################################
# Coverity Modeling Build Automation Tool (cmbat)
# April 22 - 30, 2009
# Version 0.1
# Last Modified: Jan 8, 2011
# Dave.Tian@alcatel-lucent.com
# For Detailed information please refer to
# http://daveti.blog.com
##########################################################
# Set Environment
#################
export MODELLIB=/home/daveti/cmbat/libcov_mm
export IMSLIB=$MODELLIB/ims
MENU_CHOICE=""# record the input number string
MENU_MAP=""# find the corresponding map file
MAX_NUM="8"# max number of options among all the available submenus
# in this case, we've only got one IMS submenu with max 8 options
IMS_NUM="8"# max number of options per submenu
IMS_ALL="7"# option number for all the functoins listed in this submenu
IMS_QUIT="8"# option number for quit in this submenu
# U could imagine there should be many more stuffs like this
# if we need to implement more submenu/modeling lib
X_NUM=""# X_XXX is used to match each submenu
X_ALL=""
X_QUIT=""
X_LIB1=""
X_LIB2=""
ALL_FILE1=""
ALL_FILE2=""
BJOBSID=""
BJOBSLINE=""
BJOBSSTAT=""
# Init the menu count for Multiple choices
##########################################
typeset -i count
count=1
while [ "$count" -le "$MAX_NUM" ]
do
# Once such error happens below
# ./cmbat[45]: menu_1=0: not found
# Please make sure you are using ksh93 not ksh87
typeset -i menu_${count}
menu_${count}=0
count=$(($count+1))
done
# Define functions
##################
cleanup() {
[[ -f $ROOT/cov.M.out ]] && rm $ROOT/cov.M.out > /dev/null 2>&1
[[ -f $ROOT/cov.A.out ]] && rm $ROOT/cov.A.out > /dev/null 2>&1
[[ -f $ROOT/cov.B.out ]] && rm $ROOT/cov.B.out > /dev/null 2>&1
[[ -f $ROOT/cov.F.out ]] && rm $ROOT/cov.F.out > /dev/null 2>&1
[[ -f $ROOT/lib.xmldb ]] && rm $ROOT/lib.xmldb > /dev/null 2>&1
[[ -f $PWD/cov.M.out ]] && rm $PWD/cov.M.out > /dev/null 2>&1
[[ -f $PWD/cov.T.out ]] && rm $PWD/cov.T.out > /dev/null 2>&1
[[ -f $PWD/cov.J.out ]] && rm $PWD/cov.J.out > /dev/null 2>&1
[[ -f $PWD/cov.A.out ]] && rm $PWD/cov.A.out > /dev/null 2>&1
[[ -f $PWD/cov.B.out ]] && rm $PWD/cov.B.out > /dev/null 2>&1
[[ -f $PWD/cov.F.out ]] && rm $PWD/cov.F.out > /dev/null 2>&1
return
}
clean_tmp() {
[[ -f $PWD/cov.T.out ]] && rm $PWD/cov.T.out > /dev/null 2>&1
[[ -f $PWD/cov.J.out ]] && rm $PWD/cov.J.out > /dev/null 2>&1
return
}
show_mainmenu() {
echo "*************************************"
echo "* Main Menu *"
echo "*************************************"
echo " [1] MSC"
echo " [2] IMS"
echo " [3] RMM"
echo " [4] MSC+RMM"
echo " [5] IMS+RMM"
echo " [6] All"
echo " [7] Quit"
echo
show_input_s
return
}
show_submenu_ims() {
echo
echo "******************************************"
echo "* IMS Modeling *"
echo "******************************************"
echo "Allocation:"
echo "------------------------------------------"
echo " [1] SIPia_Create_1xx_Response"
echo " [2] SIPia_Create_Final_Response"
echo " [3] SIPia_Build_Request"
echo " [4] SIPia_clone"
echo " [5] SIPia_new"
echo
echo "De-allocation:"
echo "------------------------------------------"
echo " [6] SIPia_delete"
echo
echo "All/Quit:"
echo "------------------------------------------"
echo " [7] All"
echo " [8] Quit"
echo
show_input_m
MENU_MAP="ims.map"
ALL_FILE1="ims_all.c"
X_LIB1=$IMSLIB
X_NUM=$IMS_NUM
X_ALL=$IMS_ALL
X_QUIT=$IMS_QUIT
return
}
show_error() {
echo "Invalid input."
cleanup
return
}
show_input_s() {
print -n "Please enter your single choice: "
read MENU_CHOICE
return
}
show_input_m() {
echo "Please use COMMA to seperate the multiple choices!"
print -n "Please enter your multiple choices: "
read MENU_CHOICE
return
}
show_model() {
echo "Coverity Modeling ......"
return
}
show_build() {
echo "Coverity Building ......"
return
}
show_analysis() {
echo "Coverity Analyzing ......"
return
}
# This function is especially for ALU LCP Coverity Integration
check_jobs() {
# get the job id from BJOBSLINE
BJOBSID=$(echo $BJOBSLINE | cut -d" " -f2 | tr -d "<>")
bjobs $BJOBSID > cov.J.out
echo $BJOBSLINE
# get the job stat from BJOBSLINE
# Pay more attention about the multiple backspaces
BJOBSSTAT=$(grep $BJOBSID cov.J.out | sed 's/ */ /g' | cut -d" " -f3)
# handle the DONE stat and JOB-is-not-found
until [ "$BJOBSSTAT" = "DONE" ]
do
echo "####################################################"
sleep 10
bjobs $BJOBSID > cov.J.out
BJOBSSTAT=$(grep $BJOBSID cov.J.out | sed 's/ */ /g' | cut -d" " -f3)
if [ "$BJOBSSTAT" = "EXIT" ]
then
break
echo "Build job is terminated abnormally."
echo "Please check the build environment."
cleanup
exit 1
fi
done
return
}
proc_Multi_args() {
if [ -n "$MENU_CHOICE" ]
then
# check for valid input
for num in $(echo $MENU_CHOICE | tr "," "n")
do
if ([[ $num != [0-9] ]] && [[ $num != [1-9][0-9] ]]) || [ "$num" -gt "$X_NUM" ]
then
echo "Input should be a number and not greater than the QUIT item."
show_error
exit 1
fi
done
# Count the number of choices
for num in $(echo $MENU_CHOICE | tr "," "n")
do
((menu_${num}+=1))
done
# check for duplicate
typeset -i looper
looper=1
while [ "$looper" -le "$X_NUM" ]
do
if [ $((menu_${looper})) -gt 1 ]
then
echo "Input should not be duplicated."
show_error
exit 1
fi
((looper+=1))
done
# check the all choice
looper=1
if [ $((menu_${X_ALL})) -eq 1 ]
then
while [ "$looper" -le "$X_NUM" ]
do
if [ $((menu_${looper})) -eq 1 ] && [ "$looper" -ne "$X_ALL" ]
then
echo "Only choose ALL to model all the functions."
show_error
exit 1
fi
((looper+=1))
done
fi
# check the quit choice
looper=1
if [ $((menu_${X_QUIT})) -eq 1 ]
then
while [ "$looper" -le "$X_NUM" ]
do
if [ $((menu_${looper})) -eq 1 ] && [ "$looper" -ne "$X_QUIT" ]
then
echo "Only choose QUIT to quit the menu."
show_error
exit 1
fi
((looper+=1))
done
fi
# map the choices into real path
for num2 in $(echo $MENU_CHOICE | tr "," "n")
do
grep ^$num2: "$MODELLIB/$MENU_MAP" | tr -d "$num2:" | tr -s "n" " " >> cov.T.out
done
return
else
show_error
exit 1
fi
}
# This function is ALU LCP Coverity Integration specific.
# Try to write your own Coverity modeling, build and analysis code here.
make_model() {
if [ $((menu_${X_ALL})) -eq 1 ]
then
show_model
if [ -z "$ALL_FILE2" ] && [ -z "$X_LIB2" ]
then
BJOBSLINE=$(bsub -q $BLD_Q "$MAKEMODEL --config $CONFIGFILE -of $ROOT/lib.xmldb $X_LIB1/$ALL_FILE1 > cov.M.out 2>&1")
elif [ -n "$ALL_FILE2" ] && [ -n "$X_LIB2" ]
then
BJOBSLINE=$(bsub -q $BLD_Q "$MAKEMODEL --config $CONFIGFILE -of $ROOT/lib.xmldb $X_LIB1/$ALL_FILE1 $X_LIB2/$ALL_FILE2 > cov.M.out
2>&1")
else
show_error
exit 1
fi
elif [ $((menu_${X_QUIT})) -eq 1 ]
then
exit 0
else
show_model
BJOBSLINE=$(bsub -q $BLD_Q "$MAKEMODEL --config $CONFIGFILE -of $ROOT/lib.xmldb $(cat cov.T.out) > cov.M.out 2>&1")
fi
check_jobs
show_build
BJOBSLINE=$(/home/coverity/tools/bsubcov -b)
check_jobs
show_analysis
BJOBSLINE=$(bsub -q $BLD_Q "ksh /home/coverity/tools/subcmds/model.covscr.devA")
check_jobs
clean_tmp
return
}
# Interactive mode
##################
show_mainmenu
if [ "$MENU_CHOICE" = "1" ]
then
show_submenu_msc # N/A
proc_Multi_args
make_model
elif [ "$MENU_CHOICE" = "2" ]
then
show_submenu_ims
proc_Multi_args
make_model
elif [ "$MENU_CHOICE" = "3" ]
then
show_submenu_rmm # N/A
proc_Multi_args
make_model
elif [ "$MENU_CHOICE" = "4" ]
then
show_submenu_msc_rmm # N/A
proc_Multi_args
make_model
elif [ "$MENU_CHOICE" = "5" ]
then
show_submenu_ims_rmm # N/A
proc_Multi_args
make_model
elif [ "$MENU_CHOICE" = "6" ]
then
# Do modeling, build, anaylsis based on all available function modelings
# Again, this is ALU LCP Coverity Integration specific.
show_model
BJOBSLINE=$(bsub -q $BLD_Q "$MAKEMODEL --config $CONFIGFILE -of $ROOT/lib.xmldb $IMSLIB/ims_all.c $MSCLIB/msc_all.c $RMMLIB/rmm_all.c > cov.M.out
2>&1")
check_jobs
show_build
BJOBSLINE=$(/home/coverity/tools/bsubcov -b)
check_jobs
show_analysis
BJOBSLINE=$(bsub -q $BLD_Q "ksh /home/coverity/tools/subcmds/model.covscr.devA")
check_jobs
clean_tmp
elif [ "$MENU_CHOICE" = "7" ]
then
exit 0
else
show_error
exit 1
fi