coverity modeling build automation tool – cmbat (one way to write multiple-choice menu via shell)

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

About daveti

Interested in kernel hacking, compilers, machine learning and guitars.
This entry was posted in Dave's Tools and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s