# UNISRC_ID: @(#)profile.sh	27.7	85/05/07  
#  FILE NAME is 'profile'
#
#  This shell script will profile a program using the System Profiler.
#
#  The script does a 'chatr' of the program to the screen and asks the
#  user to make sure that the program is sharable and not demand loadable.
#  It also asks that the user make sure that the program has been exec'd
#  once.  This means that the program must be started up to the point where
#  it begins execution.  That ensures that all the code segments have been
#  faulted into the machine once.  The profiler can't find the program unless
#  this process has been done.
#
#  If the user responds that the above two requirements have been met, the
#  script next asks if the program has an input file which should be 
#  redirected as its input.  It then asks if the user wants existing link
#  maps removed.  Next, it asks if the default system link map
#  and program profile result files are acceptable.  If not, it prompts
#  for these two files.  In addition, it asks if further filtering of the
#  profiler data is desired.  If so, a script to generate percentages of 
#  the COUNT1's is used and another script can be used to remove all routines
#  whose percentage is 0 from the final output.
#
#  Next, the script initializes the profiler, starts the profiler, runs the
#  program using arguments/output file supplied in the run line and optional
#  input file name requested from the user.  (See the Syntax section below.)
#  It waits for the program to finish, then stops the profiler, closes it, 
#  and runs the resultant binary data through filters to make it readable. 
#  This data is then written to the program profile result file.
#
#  In its terse mode, when called with 'prof', the script leaves out most
#  of the beginning explanation and simply prompts for responses.
#
#  Syntax:
#
#  profile program  [> output.file] | [arguments]
#  or
#  prof program  [> output.file] | [arguments]
#
#  The script will pass the arguments and/or file output redirection information
#  to the program.   
#
#  NOTE:  The user will be prompted for the name of a file used for redirected
#         input to the program once the script has begun execution.  Any attempt
#         to redirect input on the execution line will cause both the script and
#         the program to look for input in this file.
#
if [ $# -lt 1 ]
  then
    echo "Usage:" >/dev/tty
    echo "profile program [\"[< input.file [> output.file]] | arguments\"]" \
	  >/dev/tty
    echo "OR" >/dev/tty
    echo "prof program [\"[< input.file [> output.file]] | arguments\"]" \
	  >/dev/tty
    exit 1

  elif [ ! -x $1 ]
    then
     echo "The program you want to profile is not executable or does not exist"\
           >/dev/tty
      exit 1
fi

program=$1
shift

#  Get a base name for the profiler files.
#  Only the first 8 characters of the original program name will be
#  used for this basename.

name=`basename $program`
name=`expr substr $name 1 8`

if [ $0 = "prof" ]
  then
    echo "Program sharable, not demand loadable, and exec'd? [yes]">/dev/tty
  else
    echo "Warning: The system should be quiescent when profiling." >/dev/tty
    echo "">/dev/tty

    echo "The program you want to profile:" $program >/dev/tty
    echo "must be sharable and NOT demand loadable.  Please verify this from the" >/dev/tty
    echo "'chatr' output now being written to the screen.">/dev/tty
    echo "">/dev/tty
    
    chatr $program>/dev/tty

    echo "">/dev/tty

    echo "The profiler must also find your program's exec map in memory to perform" >/dev/tty
    echo "initialization.   It is usually sufficient to run the program until it" >/dev/tty
    echo "begins execution and then stop it with a 'kill' command or the 'BREAK' key." >/dev/tty
    echo "If the program is large, it is possible for the memory manager to deallocate" >/dev/tty
    echo "it before initialization begins.  If this happens, the profiler will fail" >/dev/tty
    echo "with errinfo 5002.  The best solution for this problem is to set the sticky" >/dev/tty
    echo "bit on the program with chmod, run it, kill it, and start the script again." >/dev/tty
    echo "">/dev/tty
    echo "Have the above 2 requirements been met?">/dev/tty
    echo "Please respond 'y' or 'n' for 'yes ' or  'no '.">/dev/tty
    echo "The default is 'yes'.">/dev/tty
  fi
    
read ans1

if [ ${ans1:=y} = 'n' -o $ans1 = 'N' -o $ans1 = 'no' -o $ans1 = 'NO' ]
  then
     exit
  fi

if [ $0 = "prof" ]
  then 
     echo "input?" >/dev/tty
  else
     echo "If the program needs input which should be redirected from a file"\
		>/dev/tty
     echo "please enter the name of that file.">/dev/tty
     echo "">/dev/tty
 fi

read inputt
if [ inputt = "" ]
  then
      inputt=0
  fi

if [ $0 = "prof" ]
  then
    echo "remove any existing linkmap files? [n]" >/dev/tty
  else
    echo "">/dev/tty
    echo "If linkmaps don't already exist they will be created.  If they do exist, do" >/dev/tty
    echo "you want them removed and new ones created?  Please respond 'RETURN' to keep" >/dev/tty
    echo "any existing maps or enter 'y' to have them removed and new ones created." >/dev/tty
  fi

read rmmap

if [ ${rmmap:=n} = 'y' -o $rmmap = 'Y' -o $rmmap = 'yes' -o $rmmap = 'YES' ]
  then
    rm -f $name.pt1 $name.pt2
  fi

if [ $0 = "prof" ]
  then
     echo "linkmap? [/usr/contrib/lib/convtools/fmtlmap]" >/dev/tty
  else
     echo "">/dev/tty
     echo "The default file name for the system link map is">/dev/tty
     echo "/usr/contrib/lib/convtools/fmtlmap.  Is this acceptable?">/dev/tty
     echo "Please respond 'RETURN' to use this file name or enter the requested file">/dev/tty
     echo "name followed by 'RETURN'.">/dev/tty
  fi

read syslink 
echo ${syslink:=/usr/contrib/lib/convtools/fmtlmap} >/dev/null

if [ $0 = "prof" ]
  then
    echo "results? [$name.pro]" >/dev/tty
  else
    echo "">/dev/tty
    echo "The default file name for the profile results destination_file is"\
	   >/dev/tty
    echo $name.pro "in the current directory.  Is this acceptable?"\
	   >/dev/tty
    echo "Please respond 'RETURN' to use this file name or enter the requested file">/dev/tty
    echo "name followed by 'RETURN'.">/dev/tty
  fi

read resfile
echo ${resfile:=$name.pro} >/dev/null

if [ $0 = "prof" ]
  then
    echo "percent script? [y]" >/dev/tty
  else
    echo "">/dev/tty
    echo "An additional filter is available to calculate the percentage of the total">/dev/tty
    echo "for each routine.  Do you want to use this filter?  (The results of this">/dev/tty
    echo "filter will be in the file name generated from the program profile results">/dev/tty
    echo "name appended with a '.p')">/dev/tty
    echo "Please respond 'RETURN' to use this filter or enter 'n' to not use it,">/dev/tty
    echo "followed by 'RETURN'.">/dev/tty
  fi

read percent
echo ${percent:=y} >/dev/null

if [ $percent = 'y' ]
  then 
     percent=-p
  else
     percent=""
  fi

if [ $0 = "prof" ]
  then
    echo "shorten script? [y]" >/dev/tty
  else
    echo "">/dev/tty
    echo "An additional filter is available to shorten the percentage formatted profile">/dev/tty
    echo "data.  It removes all routine data whose percentage of the total is 0.  Do">/dev/tty
    echo "you want to use this filter?  (The results of this filter will be in the file">/dev/tty
    echo "name generated from the program profile results name appended with a '.s')">/dev/tty
    echo "Please respond 'RETURN' to use this filter or enter 'n' to not use it,">/dev/tty
    echo "followed by 'RETURN'.">/dev/tty
  fi

read shorten
echo ${shorten:=y} >/dev/null

if [ $shorten = 'y' ]
  then 
     shorten=-s
  else
     shorten=""
  fi

comment="profile_for_program_"$program
echo "">/dev/tty

echo "Initializing the profiler.">/dev/tty

/usr/contrib/bin/gpinit -p $program -d >/dev/tty

echo "">/dev/tty
echo "Starting the profiler and running the program.">/dev/tty

/usr/contrib/bin/gpstart >/dev/tty

$program $@ < $inputt

/usr/contrib/bin/gpstop >/dev/tty

echo "">/dev/tty
echo "Profiler stopped; closing profiler.">/dev/tty

/usr/contrib/bin/gpclose -f $name.raw -c$comment >/dev/tty

echo "Setting up program and system map data.">/dev/tty
if [ ! -s $name.pt1 ]
  then
     nm -p $program | nmfmt | sort +0n +1n > $name.pt1
fi

if [ ! -s $name.pt2 ]
  then
     cat $syslink $name.pt1 > $name.pt2
fi

echo "Executing filters to produce readable profile data.">/dev/tty
/usr/contrib/bin/gp_list $name.raw $name.pt2 $resfile $percent $shorten\
     >/dev/tty
    
if [ -s $resfile ]
  then
    echo "profiling finished - readable file $resfile created.">/dev/tty

    if [ -s $resfile.p ]
      then 
	echo "Data as a percentage of total counts in $resfile.p">/dev/tty
      fi

    if [ -s $resfile.s ]
      then 
	echo "Shortened percentage formatted output in $resfile.s">/dev/tty
      fi

  else
    echo "error:  profiling finished - readable file NOT created.">/dev/tty
fi
