Pages

Friday, April 11, 2014

A HTML Analyzer for Peoplesoft Embeded Cobol

This is an attempt to create a more readable version with in-doc links for analyzing a Peoplesoft embedded Cobol.


#!/bin/ksh
#set -xv
# -----------------------------------------------------
# PCO Analyzer
# -----------------------------------------------------
# good context menu samples: http://s-yadav.github.io/contextMenu.html
# -----------------------------------------------------


function ltrim {
   str=`echo $1 | sed 's/^ *//g'`
}

function rtrim {
   str=`echo $1 | sed 's/ *$//g'`
}

function  trim {
   str=`echo $1 | sed -e 's/^ *//g' -e 's/ *$//g'`
}

tmp=$0.$$

trap "rm $tmp 2>/dev/null" 0 1 2 3 15


# -----------------------------------------------------
# MAIN
# -----------------------------------------------------
if [ $# -eq 0 ]
then
  echo Error: pco file name needed.
  exit 1
fi

pco="$PS_HOME/src/cbl/batch/"$1".pco"

if [ ! -f $pco ]
then
  echo Error: $pco does not exist.
  exit 1
fi

# extract statements; exclude comments
#grep -e '^[ \t]*.* DIVISION.' -e '^.......[AS].*\.' -e '^.*PERFORM ' -ie '^[ \t]*.*IF ' -ie '^[ \t]*.* ELSE[ \t]*$' -ie '^[ \t]*.*END-PERFORM' -ie 'UNTIL' -ie '^[ \t]*.*END-IF'  -ie '^[ \t]*.*EXEC SQL INCLUDE' -ie '^[ \t]* INCLUDE .*.sql' $pco | grep -v '^[ \t]*.* [AS].*-EXIT.' | grep -v '^......\*'  > $tmp

tmp=$pco

cat  << HERE
<!DOCTYPE html>
<html>

<head>
<style>
h3 {text-align:center}
   .srcecode  { white-space: pre;font-family:Courier,Times,serif; }
   .pretxt    { white-space: pre;font-family:Courier,Times,serif; }
   .data a, .data span, .data tr, .data td { white-space: pre;font-family:Courier,Times,serif; }
   .dvsn      { white-space: pre;font-family:Courier,Times,serif; }
   .filler    { white-space: pre;font-family:Courier,Times,serif; }
   .para      { white-space: pre;font-family:Courier; font-weight:bold; }
   .prfm      { white-space: pre;font-family:Courier; }
   .ifs       { white-space: pre;font-family:Courier; }
   .exec      { white-space: pre;font-family:Courier; }
   .cr_lf     { white-space: pre;font-family:Courier; display: none}
   .sql       { background-color:yellow;}
   .obso      { background-color:yellow;}
   .cmnt      { white-space: pre;font-family:Courier; color:green; font-weight:bold;}

#btnGroup {
   position: fixed;
   top: 10px; /* space between top of browser and annoying box */
   left: 10px; /* space between top of browser and annoying box */
   width: 100px;
   height: 100px;
}

#procPad {
   //border:2px solid;
   position: fixed;
   top: 50px; /* space between top of browser and box */
   left: 10px; /* space between top of browser and box */
   width: 50px;
   height: 50px;
}

#PadBox { width: 400px; margin: 0 auto; overflow: auto; border: 1px solid #0f0; padding: 2px; text-align: justify; background: transparent; }

#bookMark {
   position: fixed;
   top: 380px; /* space between top of browser and annoying box */
   left: 10px; /* space between top of browser and annoying box */
   width: 100px;
   height: 10px;
}

#bmBox {   
   position: fixed;
   top: 400px; /* space between top of browser and box */
   left: 10px; /* space between top of browser and box */
   height:320px;
   width:250px;
   border:1px solid #ccc;
   font:12px/16px Georgia, Garamond, Serif;
   overflow:auto;"}                                                        

</style>

<script>
function btnInit()
{
   document.getElementById("btnGroup").style.left=(screen.width-330)+"px";

   document.getElementById("procPad").style.left=(screen.width-100-document.getElementById("pad").offsetWidth+35)+"px";

   document.getElementById("bmBox").style.left=(screen.width-100-document.getElementById("bmBox").offsetWidth+35)+"px";

   document.getElementById("bookMark").style.left=(screen.width-330)+"px";

   if (typeof window.clipboardData == "undefined")
      document.getElementById("btnCopy").value = "Select";

   document.getElementById("btnCopy").disabled = false;
 
   document.getElementById("pad").style.visibility = "hidden";

   document.getElementById("btnHide").value="Pad";

   //document.getElementById("box").contentEditable='true';
}

function procPin(proc)
{
   var txt=document.getElementById("pad").value;

   if (txt.length > 0)       txt=txt+"\n";

   txt=txt+proc;      

   document.getElementById("pad").value=txt;

   document.getElementById("pad").style.visibility = "visible";

   document.getElementById("btnCopy").disabled = false;

   document.getElementById("btnHide").value="Hide";

}

function clearPad()
{
   document.getElementById("pad").value="";
   document.getElementById("btnCopy").disabled = true;
}

function hidePad()
{
   x=document.getElementById("pad");

   x.style.visibility = (x.style.visibility == "visible"?"hidden":"visible");

   document.getElementById("btnHide").value = (x.style.visibility == "visible"?"Hide":"Pad");
}

function copyPad(text) {

 var controlValue = document.getElementById("pad").value;

 if (window.clipboardData)
    window.clipboardData.setData("Text", controlValue);
 else
    document.getElementById("pad").select();

}

function foldCode(text) {

  // show or hide code
  if ( document.getElementsByClassName)
     var elemArray = document.getElementsByClassName('filler');
  else
     var elemArray = document.querySelectorAll("." + 'filler');
 
  for(var i = 0; i < elemArray.length; i++)
      elemArray[i].style.display= (document.getElementById("btnFold").value == "Fold"?"none":"block");

  document.getElementById("btnFold").value = (document.getElementById("btnFold").value == "Fold"?"Unfold":"Fold");

  // show or hide comments
  if ( document.getElementsByClassName)
     var elemArray = document.getElementsByClassName('cmnt');
  else
     var elemArray = document.querySelectorAll("." + 'cmnt');
 
  for(var i = 0; i < elemArray.length; i++)
      elemArray[i].style.display= (document.getElementById("btnFold").value == "Fold"?"block":"none");

  // show or hide cr_lf
  if ( document.getElementsByClassName)
     var elemArray = document.getElementsByClassName('cr_lf');
  else
     var elemArray = document.querySelectorAll("." + 'cr_lf');
 
  for(var i = 0; i < elemArray.length; i++)
      elemArray[i].style.display= (document.getElementById("btnFold").value == "Fold"?"none":"block");

}

function bmPara(proc){
   document.getElementById("bmBox").innerHTML=
      document.getElementById("bmBox").innerHTML+"<a href=\\"#"+proc+"\\" title=\\"Jump to "+proc+"\\">"+proc+"</a><br>";
}


</script>
</head>

<body onload="btnInit();clearPad();">

<h3> <a id="top">PCO Analyzer</a></h3>
<h4> PCO=$pco</h4>
<h4> 1. <a href="#flow">Code Flow</a></h4>
<h4> 2. <a href="#count">Paragraph Count</a></h4>
<h4> 3. <a href="#sql">SQL Copy Books</a></h4>
<hr>

<div id="btnGroup">
   <table>
   <tr>
   <td><input id="btnBack"  action="action" type="button" value="Back"  onclick="history.go(-1);" /></td>
   <td><input id="btnHide"  action="action" type="button" value="Hide"  onclick="hidePad();" /></td>
   <td><input id="btnClear" action="action" type="button" value="Clear" onclick="clearPad();" /></td>
   <td><input id="btnCopy"  action="action" type="button" value="Copy"  onclick="copyPad();" /></td>
   <td><input id="btnFold"  action="action" type="button" value="Fold"  onclick="foldCode();" /></td>
   </tr>
   </table>
</div>

<div id="procPad">
   <textarea id="pad" rows="19" cols="30" style="color: red; background-color: lightyellow; font-style:italic; font-weight:bold" onkeydown="document.getElementById('Copy').disabled = false;">
   </textarea>
</div>

<div id="bookMark">Bookmarks:</div>
<div id="bmBox"></div>

HERE

nawk -v sq="'" '

  # ---------------------------
  # function replacing bind variable with actual value
  # parameters: st=sql statement, bn=bind seq, bv=bind value
  # ---------------------------

  function ltrim(s) { sub(/^[ \t\r\n]+/, "", s); return s }
  function rtrim(s) { sub(/[ \t\r\n]+$/, "", s); return s }
  function trim(s)  { return rtrim(ltrim(s)); }

  # -----------------------------------------------------
  # begin section
  # -----------------------------------------------------
  BEGIN {

     #print "<div class=\"data\"><span>"
  }

  END {
     #print "</span>"
     #print "</div> "
     print "       "
     print "       "
     #print "</body>"
     #print "</html>"

  }

  # -----------------------------------------------------
  # main section
  # -----------------------------------------------------
  {
     # sanitize
     gsub(/</,"\&lt;",$0);
     gsub(/>/,"\&gt;",$0);

     if (substr($0,7,1) == "*")
        print "<span class=\"cmnt\"   style=\"display:block;\">"$0"</span>"
     else{
     # remove comments in col 1-7
     txt=substr($0,7);

     # DIVISION
     if ( $0 ~ / DIVISION./ ){
         if ($0 ~/PROCEDURE /)
            print "<b><a id=\"flow\">Flow</a> <a href=\"#top\">Top</a></b>";
         print "<span class=\"dvsn\"   style=\"display:block;\">"$0"</span>" ;
 
     }
     else if ( txt ~ /^[ \t]*[AS][0-9].*\./ && txt !~ /^[ \t]*[AS][0-9].*-EXIT[ \t]*\./)
     { 
         # PARAGRAPH heading - w/o ending "."
   
         sub(/\./," ",txt);
         str=trim(txt);
       
         #print " ";
         print "<span class=\"cr_lf\"> </span>"

         if (txt ~ /[ \t]*[AS][0-9].*-EXIT[ \t]*$/) {
            print "<span class=\"filler\"   style=\"display:block;\">"rtrim($0)"</span>"
         }
         else {
            print "<span class=\"para\"   style=\"display:block;\"><a id=\"" str "\">" rtrim($0) "</a> <a href=\"#P_" str "\">called by</a> <a href=\"#U_" str"\">Count</a> <a href=\"javascript:bmPara("sq str sq ");\">bookmark</a> <a href=\"javascript:procPin("sq str sq ");\">pin</a></span>"
         }
     }
     else if (ltrim($0) ~ /PERFORM [AS]/ )
     {
        # PERFORM paragraph
   
        str=rtrim($0);

        for(i=1; i<=NF; ++i)
        {
          if (index($i,"PERFORM") > 0)
             break;
        }
   
        i++;
        para=$i

        sub(/PERFORM /,"PERFORM <a id=\"P_"$i"\"><a href=\"#"$i"\">",str);
        print "<span class=\"prfm\"   style=\"display:block;\">"rtrim(str)"</a></a></span>";
     }
     else if (ltrim($0) ~ /EXEC SQL INCLUDE/ )
     {
        # sql copy books
   
        #str=$0;
        #
        #cpy=$4;
        #
        #gsub(/\"/,"",cpy);
        #
        ##sub(/INCLUDE/,"INCLUDE <span class=\"sql\">",str);
        # sub(/INCLUDE/,"INCLUDE <span class=\"sql\"><a id=\"I_"cpy"\"><a href=\"#"cpy"\">",str);
        #sub(/END-EXEC/,"</a></a></span>END-EXEC",str);
        #print rtrim(str);
   
        for(i=1; i<=NF; ++i)
        {
          if (index($i,"sql") > 0)
             break;
        }
   
        cpy=$i
   
        gsub(/\"/,"",cpy);
   
        gsub(/\".*.sql\"/,"<span class=\"sql\"><a id=\"I_"cpy"\"><a href=\"#"cpy"\">&<called by</a></a></span>",$0);
   
        print "<span class=\"exec\"   style=\"display:block;\">"$0"</span>";
     }
     else if (ltrim($0) ~ /^INCLUDE/ )
     {
        # sql copy books
   
        for(i=1; i<=NF; ++i)
        {
          if (index($i,"sql") > 0)
             break;
        }
   
        cpy=$i
   
        gsub(/\"/,"",cpy);
   
        gsub(/\".*.sql\"/,"<span class=\"sql\"><a id=\"I_"cpy"\"><a href=\"#"cpy"\">&<called by</a></a></span>",$0);
   
        print "<span class=\"exec\"   style=\"display:block;\">"$0"</span>";
   
   
     }
     else if ( toupper(txt) ~ /^[ \t]*IF / || toupper(txt) ~ /^[ \t]*ELSE[ \t]*$/ || toupper(txt) ~ /^[ \t]*END-IF[ \t]*/){
        # if-then-else
        print "<span class=\"ifs\"    style=\"display:block;\">"$0"</span>"
     }
     else if ( txt ~ /^[ \t]*EXIT[ \t]*\. /){
            # EXIT statement
            print "<span class=\"filler\" style=\"display:block;\">"$0"</span>"               
     }
     else
     {
        len=length($0);     

        if ( len == 0 )
           print "<span class=\"filler\" style=\"display:block;\"> </span>"
        else
           print "<span class=\"filler\" style=\"display:block;\">"$0"</span>"
     }}
   
}' $tmp


if [ $? -ne 0 ]; then
   exit 1
fi

# get paragraph count

print "<hr>"
print "<span class=\"pretxt\">"
print "<a id=\"count\"><b>Count</b></a> <a href=\"#top\">Top</a>"
print " "

grep -e '^[ \t]*[AS][0-9]' $tmp | grep -v '^[ \t]*[AS][0-9].*-EXIT' | sort > $0.$$

while read x
do

##
##for x in `grep '^[ \t]*[AS][0-9]' $tmp | tr '.' ' ' | sort`
##do

   col7=`echo $x | cut -c7-7`

   if [ '*' != $col7 ]; then

      para=`echo $x "\c" | sed -e 's/^ *//' -e 's/ *$//' -e 's/ *\.$//'`
      cnt=`grep "PERFORM $para" $tmp |  egrep -c '^.{6} '`
    
    
      href='<a href="#'$para'.">'
      cpy2=$para'</a></a>'
    
      printf "<a id=\"U_"$para"\"><a href=\"#%s\">%-40s:" $para $cpy2
    
      if [ $cnt -eq 0 ]; then
         printf "<span class=\"obso\">"
      fi
    
      printf "%d" $cnt
    
      if [ $cnt -eq 0 ]; then
         printf "</span>"
      fi
    
      printf "\n"
   fi
##
##done

done < $0.$$

print "</span>"

if [ $? -ne 0 ]; then
   exit 1
fi

### get sql copy books
echo "<hr>"
echo "<span class=\"pretxt\">"
print "<a id=\"sql\"><b>SQL Copy Books</b></a> <a href=\"#top\">Top</a>"

for x in `grep -e ' EXEC SQL INCLUDE ' -e '^[ \t]* INCLUDE ' $tmp |  egrep '^.{6} ' | awk -F \" '{print $2}' | sort`
do
   cpy=$x

   echo " "
   echo "<a id=\""$cpy"\">*********"$cpy"</a> <a href=\"#I_"$cpy"\">called by</a> <a href=""javascript:bmPara('"$cpy"');"">bookmark</a>"
 
   cat $PS_HOME/src/sql/$cpy

done

echo  "</span>" 
echo  "       "  
echo  "</body>" 
echo  "</html>" 

rm  $0.$$