
#  SCCS_ID: @(#)awk_percent	29.1 86/05/15 Unsupported Contributed Utility
#  Script name is awk_percent.  It is called by the script /usr/contrib/bin/gp_list.
#
#  This awk script takes the output from the profiler which has been
#  through the formatting script '/usr/contrib/bin/gp_list' and re-formats it
#  so that it prints the name of the routine, % of the total hits of
#  COUNT1, the total numbers for COUNT1 through COUNT4, and the total
#  hits for the routine.
#
#  The general format for the profiler data coming into the script is:
#
#   COUNT1   COUNT2   COUNT3   COUNT4   SEG   STT  NAME   TOTAL
#
#  where "SEG"  is the segment number the routine was found in, and 
#  "STT" is the offset into that segment.  The format script 'gp_list'
#  uses these numbers plus the link map for the system and user program
#  to figure out what the name of the routine is.
#
#  Set up variables at beginning of awk script; start will indicate whether
#  or not the actual profile data has been found (i.e. the lines for
#  total hits and idle have been scanned), and total is the total hits for
#  the profile.  Total is used to calculate the percentage of the COUNT1's.
#  Error is used as a flag to indicate if the formatter was unable to find
#  user routines in the link map.  If so, this script prints one error 
#  message.  In general, if one routine isn't found you have the wrong
#  link map and you will have LOTS of unknown routines.  Rather than printing
#  the error message every time, we only print it once.
#
BEGIN { 
  start = 0;
  total = 0;
  error = 0;
}
#  Now begin scanning the profile data.  Start has been initialized to
#  0, and as long as this is true and the first piece of data in the line
#  is not "COUNT1" then you have the header for the profile.  In this
#  case, all you want to do is print the lines and then go to the next
#  line (record).
{
#
  while ( ($1 != "COUNT1") && (start != 1) )
     {
       print $0;
       next;
     };

#  This next part occurs when the current record has "COUNT1" as the
#  first thing in the line.  This will become the header line.  Print
#  it out in a formatted statement, print a blank line, and then set
#  start to 1.  This indicates that real profile data follows.
#
  if ( start != 1)
    {
       printf ( "%-29s %5s %10s %7s %7s %7s %8s\n", "NAME", " % ",\
		"COUNT1", "COUNT2", "COUNT3", "COUNT4", "TOTAL" );
       print "";
       start = 1;
    }

#  Now the start variable is 1, and if the 5th thing on the line is the
#  word "total" then this is the "total hits" line.  It gets printed
#  out like all the rest of the data, only there are fewer things on the
#  line so it needs a special format.  From the "TOTAL" column of this
#  line you get the total hits which will be used to calculate the 
#  percentages of the COUNT1's for the rest of the data so the variable
#  total gets set here.
#
    else if ( (start == 1) && ($5 == "total") )
      {
	total = $1/100;
	name = $5 "_" $6;
        printf ( "%-29s %5.1f %10d %7d %7d %7d %8d\n", name, $1/total,\
		  $1, $2, $3, $4, $7 );
        next;
      }

#  A line which has the 5th thing as the word "idle" is also a special
#  format.  It is treated like the "total hits" line as far as the 
#  format for printing the data goes.
#
      else if ( (start == 1) && ($5 == "idle") )
	{
          printf ( "%-29s %5.1f %10d %7d %7d %7d %8d\n", $5, $1/total,\
		    $1, $2, $3, $4, $6 );
          next;
        }

#  A line which has the 5th thing as the word "user" and the 6th the
#  word "code" also has a special format.  The data format is like
#  the above two cases.  The name written out is "user_code".  This
#  is other user code which was encountered during the profile 
#  and for which the profiler wasn't initialized.  This number can be
#  large if you profile on a system where lots of things are going on.
#
       else if ( (start == 1) && ($5 == "user") && ($6 == "code") )
	 {
	   name = $5 "_" $6;
	   printf ( "%-29s %5.1f %10d %7d %7d %7d %8d\n", name, $1/total,\
		     $1, $2, $3, $4, $7 );
           next;
         }

#  If the 7th thing on the line is the word "UNKNOWN" there are 2
#  possibilities.  The first is that the routine is a system routine
#  which hasn't been included in the link map.  The other is that
#  it is a user routine which hasn't been included in the link map.
#  You can tell the difference by whether the segment number in the
#  profile data is low (system routine) or high (user routine).  We
#  are using 3000 as the magic cut off number.  If the segment number
#  (which is the 5th thing on the normal profile data line) is above
#  3000 then we're assuming that the routine is a user routine.
#  If a user routine is not included in the link map then there's 
#  a strong possiblility that the link map is incorrect.  So we print
#  an error message along with the normal format data.
#
        else if ( (start == 1) && ($7 == "UNKNOWN") && ($5 > 3000) )
	  {
	    if ( error == 0 )
	      {
	         print ("*** ERROR:  User code is unknown; wrong link map?" );
		 error = 1;
              };

            printf ( "%-29s %5.1f %10d %7d %7d %7d %8d\n", $7, $1/total,\
		      $1, $2, $3, $4, $8 );
	    next;
          }

#  This is the other case mentioned above, where the routine hasn't been
#  included in the link map but the 5th thing (segment number) is below
#  3000, indicating a system routine.  Here you may or may not have the
#  correct system link map included.  So we just print the normal format
#  data with the name as "UNKNOWNSYS".
#
	  else if ( (start == 1) && ($7 == "UNKNOWN") && ($5 < 2048) )
	    {
              printf ( "%-29s %5.1f %10d %7d %7d %7d %8d\n",\
		       "UNKNOWNSYS", $1/total, $1, $2, $3, $4, $8 );
	      next;
            }

#  This loop prints blank lines.  If the line length is 0 and it's included
#  in the regular profile data we just print it out without trying to
#  interpret it.  Then we go to the next line.
#
            else if ( (start == 1) && (length ($0) == 0) )
	      {
		print $0;
		next;
              }

#  Finally, this is the general case.  That is, there is a name for the
#  routine which was found in the link map, and so we print the name,
#  percentage of the total hits of COUNT1, and then the numbers for COUNT1
#  through COUNT4 and the TOTAL number of hits for the routine.
#
	      else
	        {
                   printf ( "%-29s %5.1f %10d %7d %7d %7d %8d\n", $7, \
			     $1/total, $1, $2, $3, $4, $8 );
		  next;
                };
}
