/* REXX exec/edit macro to convert SuperC output to 'HILITE'd HTML    */
/*** trace ?r ***************************************************** \| *
*               (C) Copyright Robert AH Prins, 2007-2016               *
************************************************************************
*  ------------------------------------------------------------------  *
* | Date       | By   | Remarks                                      | *
* |------------+------+----------------------------------------------| *
* |            |      |                                              | *
* |------------+------+----------------------------------------------| *
* | 2016-11-24 | RAHP | SuperC column format changed                 | *
* |------------+------+----------------------------------------------| *
* | 2016-11-18 | RAHP | Multiple updates/simplifications             | *
* |------------+------+----------------------------------------------| *
* | 2012-11-26 | RAHP | Remove '$', '#' & '@' in names (ooREXX)      | *
* |------------+------+----------------------------------------------| *
* | 2012-06-25 | RAHP | Add IP address                               | *
* |------------+------+----------------------------------------------| *
* | 2012-06-04 | RAHP | Cater for non-PDS line compares              | *
* |------------+------+----------------------------------------------| *
* | 2009-07-30 | RAHP | Add HTML comment for the 'otherwise' lines   | *
* |------------+------+----------------------------------------------| *
* | 2009-07-27 | RAHP | Use pop-up on ISPF to display progress       | *
* |------------+------+----------------------------------------------| *
* | 2009-07-08 | RAHP | - correct addition of extraneous blank line  | *
* |            |      |   to processed Search-For output             | *
* |            |      | - add note about broken highlighting for     | *
* |            |      |   Search-For output                          | *
* |            |      | - add note about improved highlighting for   | *
* |            |      |   SuperC summary output                      | *
* |------------+------+----------------------------------------------| *
* | 2009-07-02 | RAHP | Add selection for short CSS 'em' colors      | *
* |------------+------+----------------------------------------------| *
* | 2009-07-01 | RAHP | - process FILE compare output                | *
* |            |      | - process BYTE compare output                | *
* |            |      | - further tweaks to LINE compare processing  | *
* |------------+------+----------------------------------------------| *
* | 2009-06-22 | RAHP | Suppress tags around blanks                  | *
* |------------+------+----------------------------------------------| *
* | 2009-06-04 | RAHP | Split positional search strings              | *
* |------------+------+----------------------------------------------| *
* | 2009-05-20 | RAHP | Clean up HTML entities processing            | *
* |------------+------+----------------------------------------------| *
* | 2009-05-18 | RAHP | Add code to process 'WIDE' line compares     | *
* |------------+------+----------------------------------------------| *
* | 2009-05-13 | RAHP | Add code to process 'NARROW' line compares   | *
* |------------+------+----------------------------------------------| *
* | 2009-05-06 | RAHP | LONG can reuse code of 'Standard'            | *
* |------------+------+----------------------------------------------| *
* | 2009-04-22 | RAHP | Update comment                               | *
* |------------+------+----------------------------------------------| *
* | 2009-04-09 | RAHP | Restructure code for SuperC std line compare | *
* |------------+------+----------------------------------------------| *
* | 2009-04-01 | RAHP | Add font selection for generated HTML        | *
* |------------+------+----------------------------------------------| *
* | 2009-03-31 | RAHP | Handle additional SuperC (Line) output       | *
* |------------+------+----------------------------------------------| *
* | 2009-02-09 | RAHP | RACF problem with 'html' extension @ NVSM    | *
* |------------+------+----------------------------------------------| *
* | 2007-09-24 | RAHP | Further tweaks                               | *
* |------------+------+----------------------------------------------| *
* | 2007-09-18 | RAHP | - add GPL V3 License                         | *
* |            |      | - use EHISUPP 'get_options' to retrieve some | *
* |            |      |   processing options                         | *
* |------------+------+----------------------------------------------| *
* | 2007-09-06 | RAHP | Cater for PC environment                     | *
* |------------+------+----------------------------------------------| *
* | 2007-08-30 | RAHP | Initial version - as yet only what I needed| | *
* |------------+------+----------------------------------------------| *
************************************************************************
* EHISUPC is a REXX exec/edit macro that analyses SuperC output and    *
* builds a HTML file with the color attributes as used by ISPF Edit.   *
*                                                                      *
* Notes:                                                               *
*                                                                      *
* - the output of Search-For using the XREF option, either alone or    *
*   combined with the IDPFX option, will not produce any sensible ISPF *
*   highlighting. This macro does not try to do better|                *
* - the highlighting of some SuperC summary output is broken in ISPF,  *
*   this macro tries to correct this.                                  *
*                                                                      *
* This file can be transferred to the PC by using ISPF Workstation     *
* Agent. In addition the exec might invoke the Windows application     *
* associated with file extension ".html"                               *
*                                                                      *
* The exec runs as ISPF edit macro or might be used as line command    *
* on the extended member list of ISPF List Utility (usually menu       *
* option 3.4).                                                         *
*                                                                      *
* In addition the exec can be invoked on the command line. In this     *
* case the dataset name has to be supplied as invocation parameter.    *
*                                                                      *
* t_rex will contain the environment. It can be:                       *
*                                                                      *
* - TSO     - TSO/ISPF                                                 *
* - MVS     - z/OS (PGM=IRXJCL)                                        *
* - SYSTEM  - Regina                                                   *
* - COMMAND - PC DOS 7/2000                                            *
* - CMD     - Object REXX (OS/2, Windoze)                              *
************************************************************************
* Send questions, suggestions and/or bug reports to:                   *
*                                                                      *
* robert@prino.org / robert.ah.prins@gmail.com                         *
*                                                                      *
* Robert AH Prins                                                      *
* Taboralaan 46                                                        *
* 8400 Oostende                                                        *
* Belgium                                                              *
************************************************************************
* This program is free software: you can redistribute it and/or        *
* modify it under the terms of the GNU General Public License as       *
* published by the Free Software Foundation, either version 3 of       *
* the License, or (at your option) any later version.                  *
*                                                                      *
* This program is distributed in the hope that it will be useful,      *
* but WITHOUT ANY WARRANTY; without even the implied warranty of       *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the         *
* GNU General Public License for more details.                         *
*                                                                      *
* You should have received a copy of the GNU General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>  *
***********************************************************************/
parse source source
parse value source with . . moi . . . cmdenv aspace .

signal on syntax

t_rex = address()

if t_rex  = 'TSO' &,
   aspace = 'ISPF' then
  do
    "ispexec vget (zenvir)"
    envir = strip(substr(zenvir, 17, 8))
  end
else
  envir = 'OTHER'

parse arg idsn

call get_source                /* Read the SuperC/Search-For output   */
call init_vars                 /* Initialize the global variables     */
call build_html                /* Now go on and build the HTML output */

call ehisupp 'generate_output,'sep','htmlout  || sep ||,
                                     odsn     || sep ||,
                                     title    || sep ||,
                                     header   || sep ||,
                                     footer   || sep ||,
                                     htmlfont

if t_rex  = 'TSO' &,
   aspace = 'ISPF' then
  if envir \= 'BATCH' then
    do
      /*****************************************************************
      * Show the resulting dataset, if desired                         *
      *****************************************************************/
      if view_html = 'YES' then
        "ispexec view dataset("odsn")"

      /*****************************************************************
      * Transfer the html file to the PC                               *
      *****************************************************************/
      if xfer_wsa = 'YES' then
        call ehisupp 'xfer_and_show_html,'sep','dir_pc   || sep ||,
                                                htmlfile || sep ||,
                                                odsn     || sep ||,
                                                ipaddr   || sep ||,
                                                start_browser
    end
  else
    do
      if macmode then
        "isredit end"
    end
exit

/***********************************************************************
* TRANSLATE_ENTITIES                                                   *
*                                                                      *
* This procedure translates special characters to HTML entities        *
***********************************************************************/
translate_entities: procedure expose special_chars special_html
  parse arg in

  out = ''

  if translate(in, ' ', special_chars) = in then
    out = in
  else
    do while in \== ''
      c = left(in, 1)
      k = wordpos(c, special_chars)

      if k \= 0 then
        out = out || word(special_html, k)
      else
        out = out || c

      in = substr(in, 2)
    end
return out

/***********************************************************************
* GET_SOURCE:                                                          *
*                                                                      *
* Read the SuperC/Search-For output                                    *
***********************************************************************/
get_source:
  macmode = 0
  rxdata. = ''
  pgm     = ''

  select
    when t_rex = 'TSO' then call get_source_tso
    when t_rex = 'MVS' then call get_source_mvs
    otherwise               call get_source_pc
  end

  rx = 1
return

/***********************************************************************
* GET_SOURCE_TSO:                                                      *
*                                                                      *
* Read the text when running under TSO                                 *
***********************************************************************/
get_source_tso:
  if aspace = 'ISPF' then
    "isredit macro (parm) NOPROCESS"
  else
    rc = 4

  /*********************************************************************
  * Running as edit macro                                              *
  *********************************************************************/
  if rc = 0 then
    do
      macmode = 1

      if parm = '?' then
        do
          "isredit ehihelp" moi
          exit
        end

      "isredit (ZF)  = linenum .zf"
      "isredit (ZL)  = linenum .zl"

      "isredit (DSN) = dataset"
      "isredit (MEM) = member"

      if mem = '' then
        idsn = "'" || dsn || "'"
      else
        do
          pgm  = mem
          idsn = "'" || dsn || '(' || mem || ")'"
        end

      /*****************************************************************
      * Read the (selected) source into a stem                         *
      *****************************************************************/
      i = 0
      do j = +zf to +zl
        "isredit (DATALINE) = line" j

        i        = i + 1
        rxdata.i = strip(dataline, 'T')
      end

      rxdata.0 = i
    end
  /*********************************************************************
  * Running as TSO command                                             *
  *********************************************************************/
  else
    do
      if idsn = '' then
        do
          msg =     left('Error - No dataset name passed', 75)
          msg = msg left(moi 'can be used as an edit macro or',
                         'as a line command on the ISPF', 75)
          msg = msg left('dataset list utility. In both cases the',
                         'dataset name will be automatically', 75)
          msg = msg left('determined.', 75)
          msg = msg left('If you call' moi 'on the command line you',
                         'have to pass the name of the', 75)
          msg = msg left('dataset to be processed, e.g.', 75)
          msg = msg left('Command ===>' moi '''my.superc.list''', 75)

          zedsmsg = ''
          zedlmsg = msg

          if t_rex  = 'TSO'  &,
             aspace = 'ISPF' &,
             envir \= 'BATCH' then
            "ispexec setmsg msg(ISRZ001)"
          else
            do while msg \= ''
              say left(msg, 75)
              msg = substr(msg, 76)
            end

          exit 8
        end

      /*****************************************************************
      * Force single quotes around dataset name and check if it's OK   *
      *****************************************************************/
      idsn = "'" || strip(idsn,, '''') || "'"

      if sysdsn(idsn) \= 'OK' then
        do
          say 'Error - Dataset' idsn 'could not be found'
          exit 8
        end

      /*****************************************************************
      * Extract member name, if present                                *
      *****************************************************************/
      parse var idsn . '(' mem ')'

      if mem \= '' then
        pgm = mem

      /*****************************************************************
      * Read the SuperC/Search-For output                              *
      *****************************************************************/
      dynlib = 'dyn'random(99999)

      "alloc f("dynlib") da("idsn") shr reu"
      if rc > 0 then
        do
          say 'Error - Dataset' idsn 'could not be allocated - rc' rc
          exit 8
        end

      "execio * diskr" dynlib "( stem rxdata. finis"
      if rc > 0 then
        do
          say 'Error - Dataset' idsn 'could not be read - rc' rc
          exit 8
        end

      "free f("dynlib")"
    end

  olines = rxdata.0
return

/***********************************************************************
* GET_SOURCE_PC:                                                       *
*                                                                      *
* Read the text when running on the PC                                 *
***********************************************************************/
get_source_pc:
  if idsn = '' then
    do
      say 'Syntax:' moi 'superc.file'
      exit 8
    end

  do i = 1 by 1 while lines(idsn)
    rxdata.i = linein(idsn)
  end

  rxdata.0 = i - 1
  olines   = rxdata.0
return

/***********************************************************************
* INIT_VARS:                                                           *
*                                                                      *
* This procedure initialises the global variables                      *
***********************************************************************/
init_vars:
  /*********************************************************************
  * Parameter separator for EHISUPP exec                               *
  *********************************************************************/
  sep = x2c(00)d2c(random(2**16))x2c(ff)d2c(random(2**16))x2c(00)
  sep = translate(sep, x2c(bababababa), ' <>&"')

  /*********************************************************************
  * Get processing options                                             *
  *********************************************************************/
  opt = ehisupp('get_options,'sep','moi)
  parse value opt with view_html     (sep),
                       xfer_wsa      (sep),
                       start_browser (sep),
                       ispf_edit     (sep),
                       show_progress (sep),
                       dir_pc        (sep),
                       htmlfont      (sep),
                       ipaddr        (sep) .

  /*********************************************************************
  * Temporary output dataset                                           *
  *********************************************************************/
  if mem \= '' then
    odsn = "'" || userid() || '.' || mem || ".superc.html'"
  else
    odsn = "'" || userid() || '.' || moi || ".superc.html'"

  /*********************************************************************
  * Text strings for title, header and footer                          *
  *********************************************************************/
  title  = 'SuperC output:' strip(idsn,, '''')
  header = 'SuperC output:' strip(idsn,, '''')
  now    = date('S')
  now    = left(now, 4)'-'substr(now, 5, 2)'-'right(now, 2)'T'time()
  footer = 'Generated on' now 'by' userid() 'with' moi

  /*********************************************************************
  * Name of generated html file on PC                                  *
  *********************************************************************/
  if pgm \= '' then
    htmlfile = pgm || '.html'
  else
    htmlfile = 'superc.html'

  /*********************************************************************
  * HTML colors                                                        *
  *                                                                    *
  * - lime(green) - usually unchanged data                             *
  * - red         - change types                                       *
  * - white       - headings                                           *
  * - aqua(turq)  - output                                             *
  * - yellow      - new data                                           *
  * - blue        - old data                                           *
  *********************************************************************/
  col_lim  = '<em class="l">'                              /* lime    */
  col_red  = '<em class="r">'                              /* red     */
  col_whi  = '<em class="w">'                              /* white   */
  col_tur  = '<em class="t">'                              /* turq    */
  col_yel  = '<em class="y">'                              /* yellow  */
  col_blu  = '<em class="b">'                              /* blue    */

  col.0    = col_lim                 /* Unchanged line                */
  col.0i   = col_yel                 /* Inserted line                 */
  col.0d   = col_blu                 /* Deleted line                  */
  col.0im  = col_yel                 /* Inserted line                 */
  col.0dm  = col_blu                 /* Deleted line                  */
  col.0dr  = col_blu                 /* Deleted bytes                 */
  col.0rn  = col_yel                 /* Reformat new                  */
  col.0ro  = col_blu                 /* Reformat old                  */
  col.0ei  = col_tur                 /* Informational message         */
  col.0ew  = col_yel                 /* Warning message               */
  col.0ee  = col_red                 /* Error message                 */

  /*********************************************************************
  * HTML special characters and their defined entities                 *
  *********************************************************************/
  special_chars  = '& < > "'
  special_html   = '&amp; &lt; &gt; &quot;'
return

/***********************************************************************
* BUILD_HTML:                                                          *
*                                                                      *
* This procedure builds the HTML output                                *
***********************************************************************/
build_html:
  /*********************************************************************
  * Initialize the html output string                                  *
  *********************************************************************/
  if ispf_edit = 'ISPF' then
    htmlout = x2c(ff)ispf_edit || x2c(ff)right(olines, 6, '0')x2c(ff)
  else
    htmlout = ''

  /*********************************************************************
  * Determine if there are print-control characters                    *
  *********************************************************************/
  if left(rxdata.1, 1) = '1' then
    asa = 1
  else
    asa = 0

  call time 'E'

  /*********************************************************************
  * Determine if this is a Search-For or SuperC listing                *
  *********************************************************************/
  if substr(rxdata.2, 44 + asa, 10) = 'SRCH DSN: ' then
    call srchfor
  else
    select
      when pos('(' || 'LINE COMPARE)',,
               rxdata.4) \= 0 then call superc_line

      when pos('(' || 'FILE COMPARE)',,
               rxdata.4) \= 0 then call superc_file

      when pos('(' || 'BYTE COMPARE)',,
               rxdata.4) \= 0 then call superc_byte

      /*****************************************************************
      * To be implemented at some stage, maybe...                      *
      ******************************************************************
      when pos('(' || 'WORD COMPARE)',,
               rxdata.4) \= 0 then call superc_word
      *****************************************************************/
      otherwise nop
    end
return

/***********************************************************************
* SRCHFOR:                                                             *
*                                                                      *
* This procedure processes the output of Seach-For                     *
***********************************************************************/
srchfor:
  sect. = 0

  /*********************************************************************
  * Loop over the source                                               *
  *********************************************************************/
  do rx = 1 to rxdata.0
    /*******************************************************************
    * Display (optional) progress messages                             *
    *******************************************************************/
    if show_progress > 0 then
      if rx // show_progress = 0 then
        do
          progress = 'Elapsed time' right(time('E'), 12),
                     '- lines processed' right(rx, 6)

          if t_rex  = 'TSO'  &,
             aspace = 'ISPF' then
            rc = ehisupp('monitor,'moi 'Progress,'progress)
          else
            say progress
        end

    /*******************************************************************
    * Fetch line                                                       *
    *******************************************************************/
    line = strip(rxdata.rx, 'T')

    if asa then
      if left(line, 1) = '1' then
        cc = col_lim'1</em>'
      else
        cc = ' '
    else
      cc = ''

    line = substr(line, asa + 1)
    copy = 0

    select
      when line = '' then
        this = ''

      when left(line, 10) = '  ISRSUPC ' then
        this = col_whi || line'</em>'

      when pos(' ' || '--------- STRING(S) FOUND ---', line) = 29 then
        do
          mem       = left(line, 9)
          rem       = substr(line, 10)
          this      = col_red || mem'</em>' ||,
                      col_tur || rem'</em>'
          sect.0fnd = 1
        end

      when pos(' ' || 'LINE-#  SOURCE SECTION       ', line) \= 0 then
        do
          parse value line with pre 'DSN: ' dsn
          this      = col_whi || pre || 'DSN: </em>' ||,
                      col_yel || dsn'</em>'
        end

      when pos(' M' || 'EMBER   LINE-#  SOURCE LINE ', line) \= 0 then
        do
          this = col_lim || ' MEMBER   </em>'           ||,
                 col_whi || 'LINE-#  </em>'             ||,
                 col_lim || 'SOURCE LINE              ' ||,
                 col_whi || 'SRCH DSN: </em>'           ||,
                 col_yel || substr(line, 54)'</em>'
          copy = 1
        end

      when pos(' M' || 'EMBER  CONC#  LINE-#  SOURCE LINE ',,
               line) \= 0 then
        do
          this = col_lim || ' MEMBER  CONC#  </em>' ||,
                 col_whi || 'LINE-#  </em>'         ||,
                 col_lim || 'SOURCE LINE        '   ||,
                 col_whi || 'SRCH DSN: </em>'       ||,
                 col_yel || substr(line, 54)'</em>'
          copy = 1
        end

      when pos('L' || 'INES-FOUND  LINES-PROC  MEMBERS-W/LN',,
               line) \= 0 then
        this = col_whi || line'</em>'

      when pos('P' || 'ROCESS OPTIONS USED: ', line) \= 0 then
        this = col_whi || 'P' || 'ROCESS OPTIONS USED: </em>' ||,
               col_tur || substr(line, 23)'</em>'

      when pos('     S' || 'EARCH-FOR SUMMARY SECTION ', line) \= 0 then
        do
          sect.0fnd = 0
          this      = col_whi'     S' || 'EARCH-FOR SUMMARY SECTION' ||,
                             '            SRCH DSN: </em>'     ||,
                      col_yel || substr(line, 54)'</em>'
        end

      when pos('X' || 'REF STRING-FOUND ', line) \= 0 then
        this = substr(line, 1, 29) ||,
               col_whi || translate_entities(substr(line, 30))'</em>'

      when pos('T' || 'HE FOLLOWING PROCESS STATEMENTS ',,
               line) \= 0 then
        do
          this = col_whi || line'</em>'

          do rx = rx + 1 to rxdata.0
            if left(rxdata.rx, 1) \= ' ' then
              do
                rx = rx - 1
                leave
              end

            if strip(rxdata.rx) \= '' then
              this = this'<br>'col_tur ||,
                               translate_entities(rxdata.rx)'</em>'
            else
              this = this'<br> '
          end
        end

      /*****************************************************************
      * Extraneous options                                             *
      *****************************************************************/
      when pos('E' || 'XTRANEOUS OR CONFLICTING PROCESS ',,
               line) \= 0 then
        do
          this = col_whi || line'</em><br>'
          rx   = rx + 1
          this = this || col_red || rxdata.rx'</em>'
        end

      when pos('T' || 'HE FOLLOWING "SRH" FILE CONCATENATED',,
               line) \= 0 then
        do
          this = col_whi || translate_entities(line)'</em>'

          do rx = rx + 1 to rxdata.0
            if left(rxdata.rx, 3) = '   ' then
              do
                rx = rx - 1
                leave
              end

            this = this'<br>'col_yel || rxdata.rx'</em>'
          end
        end

      when pos('I' || 'SRS0', line) = 1 then
        do
          col  = value('col.0e'substr(line, 8, 1))

          this = col_whi || substr(line,  1, 9)'</em>' ||,
                 col     || substr(line, 10)'</em>'
        end

      when sect.0fnd then
        do
          this = col_blu || substr(line,  1, 7)'</em>' ||,
                 col_lim || translate_entities(substr(line, 8))'</em>'
        end

      otherwise
        do
          say 'SuperC_SFOR: Otherwise entered @ line' right(rx, 5)
          say 'Line' strip(line, 'T')
          this = '<!-- Oops -->'line
        end
    end

    htmlout = htmlout || cc || this'<br>'

    /*******************************************************************
    * Process data following the '  MEMBER ... LINE-#' lines           *
    *******************************************************************/
    if copy then
      do rx = rx + 1 to rxdata.0
        if substr(rxdata.rx, 1 + asa, 10) = '  ISRSUPC ' then
          do
            rx = rx - 1
            leave
          end

        htmlout = htmlout || translate_entities(rxdata.rx)'<br>'
      end
  end
return

/***********************************************************************
* SUPERC_LINE:                                                         *
*                                                                      *
* This procedure processes the output of SuperC (Line Compare)         *
***********************************************************************/
superc_line:
  null = x2c(00)
  line = strip(rxdata.7, 'T') || null

  slc.0t = ''

  /*********************************************************************
  * Following code does not work with cmpcolm/lstcolm processing!      *
  *********************************************************************/
  select
    when pos('-' || '-7----+-' || null, line) \= 0 then slc.0t = 'L'
    when pos('5' || '----+      ----+', line) \= 0 then slc.0t = 'N'
    when pos('+' || '----8      ----+', line) \= 0 then slc.0t = 'W'
    when pos('-' || '---+----1----+--', line) \= 0 then slc.0t = 'S'
    otherwise
      do
        zedsmsg = ''
        zedlmsg = moi 'does not recognize this type of SuperC Line',
                  'Compare output, processing terminated|'
        "ispexec setmsg msg(ISRZ001)"
        exit
      end
  end

  /*********************************************************************
  * Process the file                                                   *
  *********************************************************************/
  sect. = 0

  /*********************************************************************
  * Loop over the source                                               *
  *********************************************************************/
  rx = 1

  do while rx <= rxdata.0
    /*******************************************************************
    * Display (optional) progress messages                             *
    *******************************************************************/
    if show_progress > 0 then
      if rx // show_progress = 0 then
        do
          progress = 'Elapsed time' right(time('E'), 12),
                     '- lines processed' right(rx, 6)

          if t_rex  = 'TSO'  &,
             aspace = 'ISPF' then
            rc = ehisupp('monitor,'moi 'Progress,'progress)
          else
            say progress
        end

    /*******************************************************************
    * Fetch line                                                       *
    *******************************************************************/
    line = strip(strip(rxdata.rx, 'T'), 'T', x2c(00))

    if asa then
      if left(line, 1) = '1' then
        cc = col_lim'1</em>'
      else
        cc = ' '
    else
      cc = ''

    line = substr(line, asa + 1)

    select
      /*****************************************************************
      * Blank line                                                     *
      *****************************************************************/
      when line = '' then
        this = ''

      /*****************************************************************
      * Main headings                                                  *
      *****************************************************************/
      when left(line, 10) = '  ISRSUPC ' then
        do
          this = col_whi || line'</em>'

          /*************************************************************
          * Reset type and section for a new (concatenated) listing    *
          *************************************************************/
          if right(line, 10) = 'PAGE     1' then
            sect. = 0
        end

      /*****************************************************************
      * Messages                                                       *
      *****************************************************************/
      when left(line, 5) = 'ISRS0' then
        do
          col  = value('col.0e'substr(line, 8, 1))

          this = col_whi || substr(line,  1, 9)'</em>' ||,
                 col     || substr(line, 10)'</em>'
        end

      /*****************************************************************
      * Subheading with filenames                                      *
      *****************************************************************/
      when left(line, 4) = 'NEW:' then
        do
          parse value line with 'NEW: ' newdsn 'OLD: ' olddsn
          this = col_whi || 'NEW: </em>' ||,
                 col_yel || newdsn       || '</em>' ||,
                 col_whi || 'OLD: </em>' ||,
                 col_blu || olddsn       || '</em>'
        end

      /*****************************************************************
      * Section heading                                                *
      *****************************************************************/
      when pos('L' || 'ISTING OUTPUT SECTION (LINE COMPARE)',,
               line) = 22 then
        do
          this        = col_whi || line'</em>'
          sect.0diffs = 1
        end

      /*****************************************************************
      * Find positions to color ("standard" and LONGLN)                *
      *****************************************************************/
      when (slc.0t = 'S' |,
            slc.0t = 'L') &,
           pos('I' || 'D       SOURCE LINES', line) = 1 then
        do
          this = col_whi || line'</em>'
          !typ = pos('TYPE ',  line)
          !len = pos('  LEN ', line)
          !new = pos('N-LN# ', line)
          !old = pos('O-LN#',  line)
        end

      /*****************************************************************
      * Find positions to color ("NARROW")                             *
      *****************************************************************/
      when slc.0t = 'N' &,
           pos('I' || 'D          NEW FILE LINES', line) = 1 then
        do
          this = col_whi || line'</em>'

          !nid = pos('ID   ', line)
          !nd  = !nid + 3
          !oid = pos('ID   ', line, !nid + 1)
          !od  = !oid + 3
          !sep = !oid - 2

          !new = pos('N-LN#', line)
          !old = pos('O-LN#', line)
        end

      /*****************************************************************
      * Find positions to color ("WIDE")                               *
      *****************************************************************/
      when slc.0t = 'W' &,
           pos('I' || 'D          NEW FILE LINES', line) = 1 then
        do
          this = col_whi || line'</em>'

          !nid = pos('ID   ', line)
          !nd  = !nid + 3
          !oid = pos('ID   ', line, !nid + 1)
          !od  = !oid + 3
          !sep = !oid - 2

          !ntyp = pos('TYPE ',  line)
          !nlen = pos('  LEN ', line)
          !otyp = pos('TYPE ',  line, !ntyp + 1)
          !olen = pos('  LEN ', line, !nlen + 1)
          !new  = pos('N-LN# ', line)
          !old  = pos('O-LN#',  line)
        end

      /*****************************************************************
      * Ruler                                                          *
      *****************************************************************/
      when (slc.0t = 'S' | slc.0t = 'L') &,
            pos(' ' || '   ----+----1----+----2', line) = 1 |,
           (slc.0t = 'N' | slc.0t = 'W') &,
            pos(' ' || '  ----+----1----+----2', line) = 1 then
        this = col_tur || line'</em>'

      /*****************************************************************
      * Change section cutoff                                          *
      *****************************************************************/
      when pos('*** C' || 'HANGE SECTION CUTOFF *', line) = 1 then
        this = col_tur || line'</em>'

      /*****************************************************************
      * Summaries                                                      *
      *****************************************************************/
      when pos('M' || 'EMBER SUMMARY LISTING (LINE COMPARE)',,
               line) = 23 then
        do
          this        = col_whi || line'</em>'
          sect.0diffs = 0
        end

      when pos('C' || 'HNG MEMBERS-COMPARED ', line)  = 1 &,
           pos('N' || 'EW-PROC OLD-PROC',      line) \= 0 then
        do
          this  = col_whi || line'</em>'
          line  = line' '

          /*************************************************************
          * Get positions of columns to be HTML'ised                   *
          *************************************************************/
          kw.1  = 'CHNG'
          kw.2  = 'MEMBERS-COMPARED'
          kw.3  = ' NEW-PROC'
          kw.4  = ' OLD-PROC'
          kw.5  = ' MATCHED'
          kw.6  = ' NEW-INS'
          kw.7  = ' OLD-DEL'
          kw.8  = ' REFM-LN'
          kw.9  = ' N-DP-LN'
          kw.10 = ' O-DP-LN'
          kw.11 = '  CONC#'
          kw.0  = 11

          do ? = 1 to kw.0
            c.?.0p = pos(kw.?' ', line)
            c.?.0l = length(kw.?)
          end

          sect.0diffs = 0
          sect.0mem   = 1
        end

      /*****************************************************************
      * Overall totals                                                 *
      *****************************************************************/
      when pos('N' || 'ON-PAIRED NEW FILE MEMBERS', line) \= 0 &,
           pos('N' || 'ON-PAIRED OLD FILE MEMBERS', line) \= 0 then
        do
          parse value line with p1 '|' p2
          this  = col_whi || p1  || '</em>' ||,
                  col_tur || '|' || '</em>' ||,
                  col_whi || p2  || '</em>'

          sect.0pair = 1

          in_cat     = (pos(' CONC# ', line) \= 0)
        end

      /*****************************************************************
      * Overall totals                                                 *
      *****************************************************************/
      when pos('P' || 'DS LINE OVERALL TOTALS', line)  = 24 |,
           pos('L' || 'INE COMPARE SUMMARY AND', line) = 24 then
        do
          this        = col_whi || line'</em>'
          sect.0pair  = 0
          sect.0diffs = 0
          sect.0total = sect.0total + 1
        end

      /*****************************************************************
      * Listing type line                                              *
      *****************************************************************/
      when pos('L' || 'ISTING-TYPE = ', line) \= 0 then
        do
          sect.0total = sect.0total + 1

          li_ty = 'L' || 'ISTING-TYPE = '
          co_co = 'C' || 'OMPARE-COLUMNS = '
          lo_li = 'L' || 'ONGEST-LINE = '

          parse value line with (li_ty) t,
                                (co_co) c,
                                (lo_li) l

          this = col_whi || li_ty || '</em>' ||,
                 col_tur || t                 || '</em>'

          if c \= '' then
            this = this ||,
                   col_whi || co_co || '</em>' ||,
                   col_tur || c     || '</em>' ||,
                   col_whi || lo_li || '</em>' ||,
                   col_tur || l     || '</em>'
        end

      /*****************************************************************
      * Process options line                                           *
      *****************************************************************/
      when pos('P' || 'ROCESS OPTIONS USED:', line) \= 0 then
        do
          p_opt = 'P' || 'ROCESS OPTIONS USED: '
          parse value line with (p_opt) t

          this = col_whi || p_opt || '</em>' ||,
                 col_tur || t     || '</em>'
        end

      /*****************************************************************
      * Process statements lines                                       *
      *****************************************************************/
      when pos('T' || 'HE FOLLOWING PROCESS STATEMENTS', line) \= 0 then
        do
          sect.0process = 1
          this          = col_whi || line || '</em>'
        end

      /*****************************************************************
      * Concatenated file listing                                      *
      *****************************************************************/
      when pos('T' || 'HE FOLLOWING "OLD" FILE CONCATENATED',,
               line) \= 0 |,
           pos('T' || 'HE FOLLOWING "NEW" FILE CONCATENATED',,
               line) \= 0 then
        do
          sect.0process = 0
          sect.0concat  = 1

          if pos('"OLD"', line) \= 0 then
            col_cat = col_blu
          else
            col_cat = col_yel

          this = col_whi || translate_entities(line) || '</em>'
        end

      /*****************************************************************
      * Extraneous options                                             *
      *****************************************************************/
      when pos('E' || 'XTRANEOUS OR CONFLICTING', line) \= 0 then
        do
          sect.         = 0
          sect.0extconf = 1
          this          = col_whi || line || '</em>'
        end

      /*****************************************************************
      * The annotated differences ("standard" and LONGLN)              *
      *****************************************************************/
      when (slc.0t = 'S' |,
            slc.0t = 'L') &,
           sect.0diffs = 1 then
        do
          if left(line, 1) = 'I'  |,
             left(line, 1) = 'D'  |,
             left(line, 2) = 'RN' |,
             left(line, 2) = 'RO' |,
             pos('MAT=', line) = !typ then
            do
              if !old - !new > 6 then
                do
                  !!new = !new - 2
                  !!old = !old - 2
                end
              else
                do
                  !!new = !new
                  !!old = !old
                end

              parse var line p0,
                             =4 p1,
                             =(!typ) p2,
                             =(!len) p3,
                             =(!!new) p4,
                             =(!!old) p5

              c = '0'strip(left(p0, 2))

              if strip(p0) \= '' then
                p0 = col_red || p0'</em>'

              if strip(p1) \= '' then
                p1 = col.c   || translate_entities(p1)'</em>'

              if strip(p2) \= '' then
                p2 = col_red || p2'</em>'

              if strip(p3) \= '' then
                p3 = col_lim || p3'</em>'

              if strip(p4) \= '' then
                p4 = col_yel || p4'</em>'

              if strip(p5) \= '' then
                p5 = col_blu || p5'</em>'

              this = p0 || p1 || p2 || p3 || p4 || p5
            end
          else
            do
              this = col_lim || line || '</em>'
            end
        end

      /*****************************************************************
      * The annotated differences ("NARROW")                           *
      *****************************************************************/
      when slc.0t = 'N' &,
           sect.0diffs = 1 then
        do
          parse var line =(!nid) p0,
                         =(!nd)  p1,
                         =(!sep) p2,
                         =(!oid) p3,
                         =(!od)  p4,
                         =(!new) p5,
                         =(!old) p6

          if strip(p0) \= ' ' then
            if left(p0, 3) = 'IMR' then
              p0 = col_lim || p0'</em>'
            else
              p0 = col_red || p0'</em>'

          if strip(p1) \= ' ' then
            p1 = col_yel || translate_entities(p1)'</em>'

          if strip(p2) \= ' ' then
            p2 = col_tur || p2'</em>'

          if strip(p3) \= ' ' then
            if left(p3, 3) = 'DMR' then
              p3 = col_lim || p3'</em>'
            else
              p3 = col_red || p3'</em>'

          if strip(p4) \= ' ' then
            p4 = col_blu || translate_entities(p4)'</em>'

          mat = 0

          if strip(p5) \= ' ' then
            do
              if \datatype(left(p5, 1), 'N') then
                do
                  mat = 1
                  p5  = col_red || p5'</em>'
                end
              else
                p5 = col_yel || p5'</em>'
            end

          if strip(p6) \= ' ' then
            if mat then
              p6 = col_lim || p6'</em>'
            else
              p6 = col_blu || p6'</em>'

          this = p0 || p1 || p2 || p3 || p4 || p5 || p6
        end

      /*****************************************************************
      * The annotated differences ("WIDE")                             *
      *****************************************************************/
      when slc.0t = 'W' &,
           sect.0diffs = 1 then
        do
          parse var line =(!nid)  p0,
                         =(!nd)   p1,
                         =(!sep)  p2,
                         =(!oid)  p3,
                         =(!od)   p4,
                         =(!ntyp) p5,
                         =(!nlen) p6,
                         =(!otyp) p7,
                         =(!olen) p8,
                         =(!new)  p9,
                         =(!old)  p10

          if strip(p0) = '' then
            do
              if strip(p1) \= ' ' then
                p1 = col_lim || translate_entities(p1)'</em>'

              if strip(p4) \= ' ' then
                p4 = col_lim || translate_entities(p4)'</em>'
            end
          else
            do
              if strip(p0) \= ' ' then
                p0 = col_red || p0'</em>'

              if strip(p1) \= ' ' then
                p1 = col_yel || translate_entities(p1)'</em>'

              if strip(p3) \= ' ' then
                p3 = col_red || p3'</em>'

              if strip(p4) \= ' ' then
                p4 = col_blu || translate_entities(p4)'</em>'

              if strip(p7) \= ' ' then
                p7 = col_red || p7'</em>'

              if strip(p8) \= ' ' then
                p8 = col_lim || p8'</em>'
            end

          if strip(p2) \= ' ' then
            p2 = col_tur || p2'</em>'

          if strip(p5) \= ' ' then
            p5 = col_red || p5'</em>'

          if strip(p6) \= ' ' then
            p6 = col_lim || p6'</em>'

          if strip(p9) \= ' ' then
            p9 = col_yel || p9'</em>'

          if strip(p10) \= ' ' then
            p10 = col_blu || p10'</em>'

          this = p0 || p1 || p2 || p3 || p4 ||,
                 p5 || p6 || p7 || p8 || p9 || p10
        end

      /*****************************************************************
      * The new:old changes per member summary                         *
      *****************************************************************/
      when sect.0mem      = 1 &,
           left(line, 5) == '     ' then
        this = col_lim || line || '</em>'

      when sect.0mem           = 1 &,
           substr(line, 7, 8) == '  TOTAL ' then
        do
          p    = pos(' TOTAL ', line)
          parse var line p1 =(p) p2
          this = col_lim || p1 || '</em>' ||,
                 col_whi || p2 || '</em>'

          if pos('TOTAL OLD FILE MEMBER(S) NOT PAIRED', line) \= 0 then
            sect.0mem = 0
        end

      when sect.0mem = 1 then
        do
          if value('c.'kw.0'.0p') \= 0 then
            do
              parse var line            ast,
                             =(c.2.0p)  mems,
                             =(c.11.0p) conc,
                             =(c.3.0p)  new_proc,
                             =(c.4.0p)  old_proc,
                             =(c.5.0p)  matched,
                             =(c.6.0p)  new_ins,
                             =(c.7.0p)  old_del,
                             =(c.8.0p)  refm_ln,
                             =(c.9.0p)  n_dp_ln,
                             =(c.10.0p) o_dp_ln

              conc = col_lim || conc || '</em>'
            end
          else
            do
              parse var line            ast,
                             =(c.2.0p)  mems,
                             =(c.3.0p)  new_proc,
                             =(c.4.0p)  old_proc,
                             =(c.5.0p)  matched,
                             =(c.6.0p)  new_ins,
                             =(c.7.0p)  old_del,
                             =(c.8.0p)  refm_ln,
                             =(c.9.0p)  n_dp_ln,
                             =(c.10.0p) o_dp_ln

              conc = ''
            end

          if strip(ast) \= '' then
            ast = col_red || ast || '</em>'

          if strip(mems) \= '' then
            mems = col_red || mems || '</em>'

          if strip(new_proc) \= '' then
            new_proc = col_yel || new_proc || '</em>'

          if strip(old_proc) \= '' then
            old_proc = col_blu || old_proc || '</em>'

          if strip(matched) \= '' then
            matched = col_lim || matched || '</em>'

          if strip(new_ins) \= '' then
            new_ins = col_yel || new_ins || '</em>'

          if strip(old_del) \= '' then
            old_del = col_blu || old_del || '</em>'

          if strip(refm_ln) \= '' then
            refm_ln = col_lim || refm_ln || '</em>'

          if strip(n_dp_ln) \= '' then
            n_dp_ln = col_yel || n_dp_ln || '</em>'

          if strip(o_dp_ln) \= '' then
            o_dp_ln = col_blu || o_dp_ln || '</em>'

          this = ast      ||,
                 mems     ||,
                 conc     ||,
                 new_proc ||,
                 old_proc ||,
                 matched  ||,
                 new_ins  ||,
                 old_del  ||,
                 refm_ln  ||,
                 n_dp_ln  ||,
                 o_dp_ln
        end

      /*****************************************************************
      * No-paired members section                                      *
      *****************************************************************/
      when sect.0pair = 1 then
        do
          parse value line with p1 '|' p2

          if in_cat then
            do
              if pos('(', p1) \= 0 then
                do
                  parse value p1 with p11 '(' p12 ')' p13
                  p1 = col_yel || p11          || '</em>' ||,
                       col_lim || '('p12')'p13 || '</em>'
                end

              if pos('(', p2) \= 0 then
                do
                  parse value p2 with p21 '(' p22 ')' p23
                  p2 = col_blu || p21          || '</em>' ||,
                       col_lim || '('p22')'p23 || '</em>'
                end
            end
          else
            do
              if strip(p1) \= '' then
                p1 = col_yel || p1  || '</em>'

              if strip(p2) \= '' then
                p2 = col_blu || p2  || '</em>'
            end

          this = p1 || col_tur || '|' || '</em>' || p2
        end

      /*****************************************************************
      * Overall totals                                                 *
      *****************************************************************/
      when sect.0total = 1 then
        do
          stot.    = x2c(00ff)
          stot.1.1 = 'N' || 'UMBER OF LINE MATCHES'
          stot.1.2 = 'T' || 'OTAL CHANGES (PAIRED+NONPAIRED CHNG)'

          stot.2.1 = 'R' || 'EFORMATTED LINES'
          stot.2.2 = 'P' || 'AIRED CHANGES (REFM+PAIRED INS/DEL)'

          stot.3.1 = 'N' || 'EW FILE LINE INSERTIONS'
          stot.3.2 = 'N' || 'ON-PAIRED INSERTS'
          stot.3.3 = 'N' || 'EW FILE TEXT STRING CHANGED'

          stot.4.1 = 'O' || 'LD FILE LINE DELETIONS'
          stot.4.2 = 'N' || 'ON-PAIRED DELETES'
          stot.4.3 = 'O' || 'LD FILE TEXT STRING CHANGED'

          stot.5.2 = 'L' || 'INES DETECTED AS MOVED'

          stot.6.1 = 'N' || 'EW FILE LINES PROCESSED'
          stot.6.2 = 'N' || 'EW FILE LINES DP OPTION'
          stot.6.3 = 'N' || 'EW FILE PART COMMENT LINES'

          stot.7.1 = 'O' || 'LD FILE LINES PROCESSED'
          stot.7.2 = 'O' || 'LD FILE LINES DP OPTION'
          stot.7.3 = 'O' || 'LD FILE PART COMMENT LINES'

          this = ''
          n.   = ''
          s.   = ''

          do j = 1 to 7 while this = ''
            lin = line

            p1 = pos(stot.j.1, lin)
            if p1 \= 0 then
              do
                n.1 = left(lin, p1 - 1)
                s.1 = stot.j.1
                lin = substr(lin, p1 + length(stot.j.1))
              end

            p2 = pos(stot.j.2, lin)
            if p2 \= 0 then
              do
                n.2 = left(lin, p2 - 1)
                s.2 = stot.j.2
                lin = substr(lin, p2 + length(stot.j.2))
              end

            p3 = pos(stot.j.3, lin)
            if p3 \= 0 then
              do
                n.3 = left(lin, p3 - 1)
                s.3 = stot.j.3
                lin = substr(lin, p3 + length(stot.j.3))
              end

            if n.1 \= '' |,
               n.2 \= '' |,
               n.3 \= '' then
              do
                if strip(n.1) \= '' then
                  n.1 = col_lim || n.1 || '</em>'

                if strip(s.1) \= '' then
                  s.1 = col_whi || s.1 || '</em>'

                if strip(n.2) \= '' then
                  n.2 = col_lim || n.2 || '</em>'

                if strip(s.2) \= '' then
                  s.2 = col_whi || s.2 || '</em>'

                if strip(n.3) \= '' then
                  n.3 = col_lim || n.3 || '</em>'

                if strip(s.3) \= '' then
                  s.3 = col_whi || s.3 || '</em>'

                this =  n.1 || s.1 || n.2 || s.2 || n.3 || s.3
              end
          end
        end

      /*****************************************************************
      * Process statements                                             *
      *****************************************************************/
      when sect.0process = 1 then
        do
          this = col_tur || translate_entities(line) || '</em>'
        end

      /*****************************************************************
      * Concatenated dataset listing(s)                                *
      *****************************************************************/
      when sect.0concat = 1 then
        do
          this = col_cat || line || '</em>'
        end

      /*****************************************************************
      * Extraneous options                                             *
      *****************************************************************/
      when sect.0extconf = 1 then
        do
          this = col_red || line || '</em>'
        end

      otherwise
        do
          say 'SuperC_Line: Otherwise entered @ line' right(rx, 5)
          say 'Line' strip(line, 'T')
          say 'Type' slc.0t
          this = '<!-- Oops (Type' slc.0t') -->'line
        end
    end

    htmlout = htmlout || cc || strip(this, 'T')'<br>'
    rx      = rx + 1
  end
return

/***********************************************************************
* SUPERC_FILE:                                                         *
*                                                                      *
* This procedure processes the output of SuperC (File Compare)         *
***********************************************************************/
superc_file:
  /*********************************************************************
  * Process the file                                                   *
  *********************************************************************/
  sect.  = 0
  slc.0t = ''

  /*********************************************************************
  * Loop over the source                                               *
  *********************************************************************/
  rx = 1

  do while rx <= rxdata.0
    /*******************************************************************
    * Display (optional) progress messages                             *
    *******************************************************************/
    if show_progress > 0 then
      if rx // show_progress = 0 then
        do
          progress = 'Elapsed time' right(time('E'), 12),
                     '- lines processed' right(rx, 6)

          if t_rex  = 'TSO'  &,
             aspace = 'ISPF' then
            rc = ehisupp('monitor,'moi 'Progress,'progress)
          else
            say progress
        end

    /*******************************************************************
    * Fetch line                                                       *
    *******************************************************************/
    line = strip(rxdata.rx, 'T')

    if asa then
      if left(line, 1) = '1' then
        cc = col_lim'1</em>'
      else
        cc = ' '
    else
      cc = ''

    line = substr(line, asa + 1)

    select
      /*****************************************************************
      * Blank line                                                     *
      *****************************************************************/
      when line = '' then
        this = ''

      /*****************************************************************
      * Main headings                                                  *
      *****************************************************************/
      when left(line, 10) = '  ISRSUPC ' then
        do
          this = col_whi || line'</em>'

          /*************************************************************
          * Reset type and section for a new (concatenated) listing    *
          *************************************************************/
          if right(line, 10) = 'PAGE     1' then
            do
              sect.  = 0
              slc.0t = ''
            end
        end

      /*****************************************************************
      * Messages                                                       *
      *****************************************************************/
      when left(line, 5) = 'ISRS0' then
        do
          col  = value('col.0e'substr(line, 8, 1))

          this = col_whi || substr(line,  1, 9)'</em>' ||,
                 col     || substr(line, 10)'</em>'
        end

      /*****************************************************************
      * Subheading with filenames                                      *
      *****************************************************************/
      when left(line, 4) = 'NEW:' then
        do
          parse value line with 'NEW: ' newdsn 'OLD: ' olddsn
          this = col_whi || 'NEW: </em>' ||,
                 col_yel || newdsn       || '</em>' ||,
                 col_whi || 'OLD: </em>' ||,
                 col_blu || olddsn       || '</em>'
        end

      /*****************************************************************
      * Section heading - PS                                           *
      *****************************************************************/
      when pos('C' || 'OMPARE SUMMARY LISTING (FILE COMPARE)',,
               line) = 20 then
        do
          this   = col_whi || line'</em>'
          slc.0t = 'PS'
        end

      /*****************************************************************
      * Section heading - PO                                           *
      *****************************************************************/
      when pos('M' || 'EMBER SUMMARY LISTING (FILE COMPARE)',,
               line) = 23 then
        do
          this   = col_whi || line'</em>'
          slc.0t = 'PO'
        end

      /*****************************************************************
      * Totals                                                         *
      *****************************************************************/
      when pos(' T' || 'OTAL ', line) = 8 then
        do
          parse var line pre +8 post

          this = col_lim || pre  || '</em>' ||,
                 col_whi || post || '</em>'
        end

      /*****************************************************************
      * Summaries                                                      *
      *****************************************************************/
      when pos('D' || 'IFF SAME', line) = 1 then
        do
          sect.       = 0
          sect.0diffs = 1

          this        = col_whi || line'</em>'
          line        = line' '

          /*************************************************************
          * Get positions of columns to be HTML'ised                   *
          *************************************************************/
          kw.1  = 'DIFF'
          kw.2  = 'SAME'
          kw.3  = 'N-BYTES'
          kw.4  = 'O-BYTES'
          kw.5  = 'N-LINES'
          kw.6  = 'O-LINES'
          kw.7  = 'N-HASH-SUM'
          kw.8  = 'O-HASH-SUM'
          kw.9  = 'MEMBERS-COMPARED'
          kw.10 = 'CONC#'
          kw.0  = 10

          do ? = 1 to kw.0
            c.?.0p = pos(kw.?' ', line)
            c.?.0l = length(kw.?)
          end

          in_cat = (pos(' CONC# ', line) \= 0)
        end

      /*****************************************************************
      * Overall totals                                                 *
      *****************************************************************/
      when pos('N' || 'ON-PAIRED NEW FILE MEMBERS', line) \= 0 &,
           pos('N' || 'ON-PAIRED OLD FILE MEMBERS', line) \= 0 then
        do
          sect.      = 0
          sect.0pair = 1

          parse value line with p1 '|' p2
          this  = col_whi || p1  || '</em>' ||,
                  col_tur || '|' || '</em>' ||,
                  col_whi || p2  || '</em>'

          in_cat     = (pos(' CONC# ', line) \= 0)
        end

      /*****************************************************************
      * Process options line                                           *
      *****************************************************************/
      when pos('P' || 'ROCESS OPTIONS USED:', line) \= 0 then
        do
          sect. = 0

          p_opt = 'P' || 'ROCESS OPTIONS USED: '
          parse value line with (p_opt) t

          this = col_whi || p_opt || '</em>' ||,
                 col_tur || t     || '</em>'
        end

      /*****************************************************************
      * Process statements lines                                       *
      *****************************************************************/
      when pos('T' || 'HE FOLLOWING PROCESS STATEMENTS', line) \= 0 then
        do
          sect.         = 0
          sect.0process = 1

          this          = col_whi || line || '</em>'
        end

      /*****************************************************************
      * Concatenated file listing                                      *
      *****************************************************************/
      when pos('T' || 'HE FOLLOWING "OLD" FILE CONCATENATED',,
               line) \= 0 |,
           pos('T' || 'HE FOLLOWING "NEW" FILE CONCATENATED',,
               line) \= 0 then
        do
          sect.         = 0
          sect.0concat  = 1

          if pos('"OLD"', line) \= 0 then
            col_cat = col_blu
          else
            col_cat = col_yel

          this = col_whi || translate_entities(line) || '</em>'
        end

      /*****************************************************************
      * Extraneous options                                             *
      *****************************************************************/
      when pos('E' || 'XTRANEOUS OR CONFLICTING', line) \= 0 then
        do
          sect.         = 0
          sect.0extconf = 1

          this          = col_whi || line || '</em>'
        end

      /*****************************************************************
      * Differences (PS)                                               *
      *****************************************************************/
      when sect.0diffs & slc.0t = 'PS' then
        do
          parse var line            diff,
                         =(c.2.0p)  same,
                         =(c.3.0p)  n_bytes,
                         =(c.4.0p)  o_bytes,
                         =(c.5.0p)  n_lines,
                         =(c.6.0p)  o_lines,
                         =(c.7.0p)  n_hash,
                         =(c.8.0p)  o_hash

          mems = ''
          conc = ''

          if diff \= '' then
            do
              diff = col_red || diff || '</em>'

              if same \= '' then
                same = col_lim || same || '</em>'

              if n_bytes \= '' then
                n_bytes = col_yel || n_bytes || '</em>'

              if o_bytes \= '' then
                o_bytes = col_blu || o_bytes || '</em>'

              if n_lines \= '' then
                n_lines = col_yel || n_lines || '</em>'

              if o_lines \= '' then
                o_lines = col_blu || o_lines || '</em>'

              if n_hash \= '' then
                n_hash  = col_yel || n_hash || '</em>'

              if o_hash \= '' then
                o_hash  = col_blu || o_hash || '</em>'

              this = diff    || same    ||,
                     mems    || conc    ||,
                     n_bytes || o_bytes ||,
                     n_lines || o_lines ||,
                     n_hash  || o_hash
            end
          else
            this = col_lim || line || '</em>'
        end

      /*****************************************************************
      * Differences (PO)                                               *
      *****************************************************************/
      when sect.0diffs & slc.0t = 'PO' then
        do
          conc = ''

          if in_cat then
            parse var line            diff,
                           =(c.2.0p)  same,
                           =(c.9.0p)  mems,
                           =(c.10.0p) conc,
                           =(c.3.0p)  n_bytes,
                           =(c.4.0p)  o_bytes,
                           =(c.5.0p)  n_lines,
                           =(c.6.0p)  o_lines,
                           =(c.7.0p)  n_hash,
                           =(c.8.0p)  o_hash
          else
            parse var line            diff,
                           =(c.2.0p)  same,
                           =(c.9.0p)  mems,
                           =(c.3.0p)  n_bytes,
                           =(c.4.0p)  o_bytes,
                           =(c.5.0p)  n_lines,
                           =(c.6.0p)  o_lines,
                           =(c.7.0p)  n_hash,
                           =(c.8.0p)  o_hash

          select
            when strip(mems) = '-------------' then
              this = col_whi || strip(line,, 'T') || '</em>'

            when strip(mems) = 'MEMBER TOTALS' then
              do
                this = col_whi || diff || same || mems || '</em>'

                if \in_cat then
                  do
                    tmp = left(line, 31) || substr(line, 40)
                    parse var tmp =(c.3.0p)  n_bytes,
                                  =(c.4.0p)  o_bytes,
                                  =(c.5.0p)  n_lines,
                                  =(c.6.0p)  o_lines,
                                  =(c.7.0p)  .

                  end

                this = this    ||,
                       col_lim || conc    ||,
                                  n_bytes ||,
                                  o_bytes ||,
                                  n_lines ||,
                                  o_lines || '</em>'

                sect.0diffs = 0
              end

            otherwise
              do
                if diff = '' then
                  this = col_lim || line || '</em>'
                else
                  do
                    this = col_red || diff || same || mems || '</em>'

                    if conc \= '' then
                      this = this || col_lim || conc || '</em>'

                    this = this ||,
                           col_yel || n_bytes || '</em>' ||,
                           col_blu || o_bytes || '</em>' ||,
                           col_yel || n_lines || '</em>' ||,
                           col_blu || o_lines || '</em>' ||,
                           col_yel || n_hash  || '</em>' ||,
                           col_blu || o_hash  || '</em>'
                  end
              end
          end
        end

      /*****************************************************************
      * No-paired members section                                      *
      *****************************************************************/
      when sect.0pair = 1 then
        do
          parse value line with p1 '|' p2

          if in_cat then
            do
              if pos('(', p1) \= 0 then
                do
                  parse value p1 with p11 '(' p12 ')' p13
                  p1 = col_yel || p11          || '</em>' ||,
                       col_lim || '('p12')'p13 || '</em>'
                end

              if pos('(', p2) \= 0 then
                do
                  parse value p2 with p21 '(' p22 ')' p23
                  p2 = col_blu || p21          || '</em>' ||,
                       col_lim || '('p22')'p23 || '</em>'
                end
            end
          else
            do
              if strip(p1) \= '' then
                p1 = col_yel || p1  || '</em>'

              if strip(p2) \= '' then
                p2 = col_blu || p2  || '</em>'
            end

          this = p1 || col_tur || '|' || '</em>' || p2
        end

      /*****************************************************************
      * Process statements                                             *
      *****************************************************************/
      when sect.0process = 1 then
        do
          this = col_tur || translate_entities(line) || '</em>'
        end

      /*****************************************************************
      * Concatenated dataset listing(s)                                *
      *****************************************************************/
      when sect.0concat = 1 then
        do
          this = col_cat || line || '</em>'
        end

      /*****************************************************************
      * Extraneous options                                             *
      *****************************************************************/
      when sect.0extconf = 1 then
        do
          this = col_red || line || '</em>'
        end

      otherwise
        do
          say 'SuperC_File: Otherwise entered @ line' right(rx, 5)
          say 'Line' strip(line, 'T')
          say 'Type' slc.0t
          this = '<!-- Oops (Type' slc.0t') -->'line
        end
    end

    htmlout = htmlout || cc || strip(this, 'T')'<br>'
    rx      = rx + 1
  end
return

/***********************************************************************
* SUPERC_BYTE:                                                         *
*                                                                      *
* This procedure processes the output of SuperC (Byte Compare)         *
***********************************************************************/
superc_byte:
  null = x2c(00)
  line = strip(rxdata.7, 'T') || null

  /*********************************************************************
  * Process the file                                                   *
  *********************************************************************/
  sect. = 0

  /*********************************************************************
  * Loop over the source                                               *
  *********************************************************************/
  rx = 1

  do while rx <= rxdata.0
    /*******************************************************************
    * Display (optional) progress messages                             *
    *******************************************************************/
    if show_progress > 0 then
      if rx // show_progress = 0 then
        do
          progress = 'Elapsed time' right(time('E'), 12),
                     '- lines processed' right(rx, 6)

          if t_rex  = 'TSO'  &,
             aspace = 'ISPF' then
            rc = ehisupp('monitor,'moi 'Progress,'progress)
          else
            say progress
        end

    /*******************************************************************
    * Fetch line                                                       *
    *******************************************************************/
    line = strip(rxdata.rx, 'T')

    if asa then
      if left(line, 1) = '1' then
        cc = col_lim'1</em>'
      else
        cc = ' '
    else
      cc = ''

    line = substr(line, asa + 1)

    select
      /*****************************************************************
      * Blank line                                                     *
      *****************************************************************/
      when line = '' then
        this = ''

      /*****************************************************************
      * Main headings                                                  *
      *****************************************************************/
      when left(line, 10) = '  ISRSUPC ' then
        do
          this  = col_whi || line'</em>'
          sect. = 0
        end

      /*****************************************************************
      * Messages                                                       *
      *****************************************************************/
      when left(line, 5) = 'ISRS0' then
        do
          col  = value('col.0e'substr(line, 8, 1))

          this = col_whi || substr(line,  1, 9)'</em>' ||,
                 col     || substr(line, 10)'</em>'
        end

      /*****************************************************************
      * Subheading with filenames                                      *
      *****************************************************************/
      when left(line, 4) = 'NEW:' then
        do
          parse value line with 'NEW: ' newdsn 'OLD: ' olddsn
          this = col_whi || 'NEW: </em>' ||,
                 col_yel || newdsn       || '</em>' ||,
                 col_whi || 'OLD: </em>' ||,
                 col_blu || olddsn       || '</em>'
        end

      /*****************************************************************
      * Section heading                                                *
      *****************************************************************/
      when pos('L' || 'ISTING OUTPUT SECTION (BYTE COMPARE)',,
               line) = 22 then
        do
          this = col_whi || line'</em>'
        end

      /*****************************************************************
      * Find positions to color                                        *
      *****************************************************************/
      when pos('I' || 'D  NEW-OFFSET / HEX-DATA', line) = 1 then
        do
          this = col_whi || line'</em>'

          !nid = pos('ID  ', line)
          !nof = !nid + 4
          !sep = !nid + 10
          !dif = !nid + 11
          !feb = pos('*         EBCDIC' || ' TEXT            *', line)
          !fet = !feb + 1
          !leb = !feb + 33
          !oid = pos('ID ', line, !nid + 1)
          !oof = !oid + 3

          sect.0diffs = 1
        end

      /*****************************************************************
      * Ruler                                                          *
      *****************************************************************/
      when pos('0' || '------- 4------- 8-------', line) = 12 then
        this = col_tur || line'</em>'

      /*****************************************************************
      * Summary listings                                               *
      *****************************************************************/
      when pos('M' || 'EMBER SUMMARY LISTING (BYTE COMPARE)',,
               line) = 23 then
        this = col_whi || line'</em>'

      when pos('B' || 'YTE COMPARE SUMMARY AND STATISTICS',,
               line) = 24 then
        do
          this        = col_whi || line'</em>'
          sect.0total = sect.0total + 1
        end

      /*****************************************************************
      * Summaries                                                      *
      *****************************************************************/
      when pos('C' || 'HNG MEMBERS-COMPARED ', line)  = 1 &,
           pos('N' || 'EW-PROC OLD-PROC',      line) \= 0 then
        do
          this  = col_whi || line'</em>'
          line  = line' '

          /*************************************************************
          * Get positions of columns to be HTML'ised                   *
          *************************************************************/
          kw.1  = 'CHNG'
          kw.2  = 'MEMBERS-COMPARED'
          kw.3  = ' NEW-PROC'
          kw.4  = ' OLD-PROC'
          kw.5  = ' MATCHED'
          kw.6  = ' NEW-INS'
          kw.7  = ' OLD-DEL'
          kw.8  = '  CONC#'
          kw.0  = 8

          do ? = 1 to kw.0
            c.?.0p = pos(kw.?' ', line)
            c.?.0l = length(kw.?)
          end

          sect.0diffs = 0
          sect.0mem   = 1
        end

      /*****************************************************************
      * Non-paired member listing                                      *
      *****************************************************************/
      when pos('N' || 'ON-PAIRED NEW FILE MEMBERS', line) \= 0 &,
           pos('N' || 'ON-PAIRED OLD FILE MEMBERS', line) \= 0 then
        do
          parse value line with p1 '|' p2
          this  = col_whi || p1  || '</em>' ||,
                  col_tur || '|' || '</em>' ||,
                  col_whi || p2  || '</em>'

          sect.0pair = 1

          in_cat     = (pos(' CONC# ', line) \= 0)
        end

      /*****************************************************************
      * Overall totals                                                 *
      *****************************************************************/
      when pos('P' || 'DS BYTE OVERALL TOTALS', line) = 24 then
        do
          this        = col_whi || line'</em>'
          sect.0pair  = 0
          sect.0total = sect.0total + 1
        end

      /*****************************************************************
      * Listing type line                                              *
      *****************************************************************/
      when pos('L' || 'ISTING-TYPE = ', line) \= 0 then
        do
          sect.0total = sect.0total + 1

          li_ty = 'L' || 'ISTING-TYPE = '
          co_co = 'C' || 'OMPARE-COLUMNS = '
          lo_li = 'L' || 'ONGEST-LINE = '

          parse value line with (li_ty) t,
                                (co_co) c,
                                (lo_li) l

          this = col_whi || li_ty || '</em>' ||,
                 col_tur || t                 || '</em>'

          if c \= '' then
            this = this ||,
                   col_whi || co_co || '</em>' ||,
                   col_tur || c     || '</em>' ||,
                   col_whi || lo_li || '</em>' ||,
                   col_tur || l     || '</em>'
        end

      /*****************************************************************
      * Process options line                                           *
      *****************************************************************/
      when pos('P' || 'ROCESS OPTIONS USED:', line) \= 0 then
        do
          p_opt = 'P' || 'ROCESS OPTIONS USED: '
          parse value line with (p_opt) t

          this = col_whi || p_opt || '</em>' ||,
                 col_tur || t     || '</em>'
        end

      /*****************************************************************
      * Process statements lines                                       *
      *****************************************************************/
      when pos('T' || 'HE FOLLOWING PROCESS STATEMENTS', line) \= 0 then
        do
          sect.0process = 1
          this          = col_whi || line || '</em>'
        end

      /*****************************************************************
      * Concatenated file listing                                      *
      *****************************************************************/
      when pos('T' || 'HE FOLLOWING "OLD" FILE CONCATENATED',,
               line) \= 0 |,
           pos('T' || 'HE FOLLOWING "NEW" FILE CONCATENATED',,
               line) \= 0 then
        do
          sect.0process = 0
          sect.0concat  = 1

          if pos('"OLD"', line) \= 0 then
            col_cat = col_blu
          else
            col_cat = col_yel

          this = col_whi || translate_entities(line) || '</em>'
        end

      /*****************************************************************
      * Extraneous options                                             *
      *****************************************************************/
      when pos('E' || 'XTRANEOUS OR CONFLICTING', line) \= 0 then
        do
          sect.         = 0
          sect.0extconf = 1
          this          = col_whi || line || '</em>'
        end

      /*****************************************************************
      * The annotated differences                                      *
      *****************************************************************/
      when sect.0diffs = 1 then
        do
          parse var line =(!nid) p0,
                         =(!nof) p1,
                         =(!sep) p2,
                         =(!dif) p3,
                         =(!feb) p4,
                         =(!fet) p5,
                         =(!leb) p6,
                         =(!oid) p7,
                         =(!oof) p8
          c = '0'strip(left(p0, 2))

          if strip(p0) \= '' then
            p0 = col_red || p0'</em>'

          if strip(p1) \= '' then
            p1 = col_yel || p1'</em>'

          if strip(p2) \= '' then
            p2 = col_tur || p2'</em>'

          if strip(p3) \= '' then
            p3 = col.c || p3'</em>'

          if strip(p4) \= '' then
            p4 = col_tur || p4'</em>'

          if strip(p5) \= '' then
            p5 = col.c || translate_entities(p5)'</em>'

          if strip(p6) \= '' then
            p6 = col_tur || p6'</em>'

          if strip(p7) \= '' then
            p7 = col_red || p7'</em>'

          if strip(p8) \= '' then
            p8 = col_blu || p8'</em>'

          this = p0 || p1 || p2 || p3 || p4 ||,
                 p5 || p6 || p7 || p8
        end

      /*****************************************************************
      * The new:old changes per member summary                         *
      *****************************************************************/
      when sect.0mem      = 1 &,
           left(line, 5) == '     ' then
        this = col_lim || line || '</em>'

      when sect.0mem           = 1 &,
           substr(line, 7, 8) == '  TOTAL ' then
        do
          p    = pos(' TOTAL ', line)
          parse var line p1 =(p) p2
          this = col_lim || p1 || '</em>' ||,
                 col_whi || p2 || '</em>'

          if pos('TOTAL OLD FILE MEMBER(S) NOT PAIRED', line) \= 0 then
            sect.0mem = 0
        end

      when sect.0mem = 1 then
        do
          if value('c.'kw.0'.0p') \= 0 then
            do
              parse var line           ast,
                             =(c.2.0p) mems,
                             =(c.8.0p) conc,
                             =(c.3.0p) new_proc,
                             =(c.4.0p) old_proc,
                             =(c.5.0p) matched,
                             =(c.6.0p) new_ins,
                             =(c.7.0p) old_del

              conc = col_lim || conc || '</em>'
            end
          else
            do
              parse var line           ast,
                             =(c.2.0p) mems,
                             =(c.3.0p) new_proc,
                             =(c.4.0p) old_proc,
                             =(c.5.0p) matched,
                             =(c.6.0p) new_ins,
                             =(c.7.0p) old_del

              conc = ''
            end

          if strip(ast) \= '' then
            ast = col_red || ast || '</em>'

          if strip(mems) \= '' then
            mems = col_red || mems || '</em>'

          if strip(new_proc) \= '' then
            new_proc = col_yel || new_proc || '</em>'

          if strip(old_proc) \= '' then
            old_proc = col_blu || old_proc || '</em>'

          if strip(matched) \= '' then
            matched = col_lim || matched || '</em>'

          if strip(new_ins) \= '' then
            new_ins = col_yel || new_ins || '</em>'

          if strip(old_del) \= '' then
            old_del = col_blu || old_del || '</em>'

          this = ast      ||,
                 mems     ||,
                 conc     ||,
                 new_proc ||,
                 old_proc ||,
                 matched  ||,
                 new_ins  ||,
                 old_del
        end

      /*****************************************************************
      * No-paired members section                                      *
      *****************************************************************/
      when sect.0pair = 1 then
        do
          parse value line with p1 '|' p2

          if in_cat then
            do
              if pos('(', p1) \= 0 then
                do
                  parse value p1 with p11 '(' p12 ')' p13
                  p1 = col_yel || p11          || '</em>' ||,
                       col_lim || '('p12')'p13 || '</em>'
                end

              if pos('(', p2) \= 0 then
                do
                  parse value p2 with p21 '(' p22 ')' p23
                  p2 = col_blu || p21          || '</em>' ||,
                       col_lim || '('p22')'p23 || '</em>'
                end
            end
          else
            do
              if strip(p1) \= '' then
                p1 = col_yel || p1  || '</em>'

              if strip(p2) \= '' then
                p2 = col_blu || p2  || '</em>'
            end

          this = p1 || col_tur || '|' || '</em>' || p2
        end

      /*****************************************************************
      * Overall totals                                                 *
      *****************************************************************/
      when sect.0total = 1 then
        do
          stot.    = x2c(00ff)
          stot.1.1 = 'N' || 'UMBER OF BYTE MATCHES'
          stot.1.2 = 'T' || 'OTAL CHANGES (PAIRED+NONPAIRED CHNG)'

          stot.2.1 = 'N' || 'EW FILE BYTE INSERTIONS'
          stot.2.2 = 'N' || 'ON-PAIRED INSERTS'

          stot.3.1 = 'O' || 'LD FILE BYTE DELETIONS'
          stot.3.2 = 'N' || 'ON-PAIRED DELETES'

          stot.4.1 = 'N' || 'EW FILE BYTES PROCESSED'

          stot.5.1 = 'O' || 'LD FILE BYTES PROCESSED'

          this = ''
          n.   = ''
          s.   = ''

          do j = 1 to 5 while this = ''
            lin = line

            p1 = pos(stot.j.1, lin)
            if p1 \= 0 then
              do
                n.1 = left(lin, p1 - 1)
                s.1 = stot.j.1
                lin = substr(lin, p1 + length(stot.j.1))
              end

            p2 = pos(stot.j.2, lin)
            if p2 \= 0 then
              do
                n.2 = left(lin, p2 - 1)
                s.2 = stot.j.2
                lin = substr(lin, p2 + length(stot.j.2))
              end

            p3 = pos(stot.j.3, lin)
            if p3 \= 0 then
              do
                n.3 = left(lin, p3 - 1)
                s.3 = stot.j.3
                lin = substr(lin, p3 + length(stot.j.3))
              end

            if n.1 \= '' |,
               n.2 \= '' |,
               n.3 \= '' then
              do
                if strip(n.1) \= '' then
                  n.1 = col_lim || n.1 || '</em>'

                if strip(s.1) \= '' then
                  s.1 = col_whi || s.1 || '</em>'

                if strip(n.2) \= '' then
                  n.2 = col_lim || n.2 || '</em>'

                if strip(s.2) \= '' then
                  s.2 = col_whi || s.2 || '</em>'

                if strip(n.3) \= '' then
                  n.3 = col_lim || n.3 || '</em>'

                if strip(s.3) \= '' then
                  s.3 = col_whi || s.3 || '</em>'

                this =  n.1 || s.1 || n.2 || s.2 || n.3 || s.3
              end
          end
        end

      /*****************************************************************
      * Process statements                                             *
      *****************************************************************/
      when sect.0process = 1 then
        do
          this = col_tur || translate_entities(line) || '</em>'
        end

      /*****************************************************************
      * Concatenated dataset listing(s)                                *
      *****************************************************************/
      when sect.0concat = 1 then
        do
          this = col_cat || line || '</em>'
        end

      /*****************************************************************
      * Extraneous options                                             *
      *****************************************************************/
      when sect.0extconf = 1 then
        do
          this = col_red || line || '</em>'
        end

      otherwise
        do
          say 'SuperC_Line: Otherwise entered @ line' right(rx, 5)
          say 'Line' strip(line, 'T')
          say 'Type' slc.0t
          this = '<!-- Oops (Type' slc.0t') -->'line
        end
    end

    htmlout = htmlout || cc || strip(this, 'T')'<br>'
    rx      = rx + 1
  end
return

/***********************************************************************
* SYNTAX:                                                              *
*                                                                      *
* This procedure gives a 'clean' exit for errors                       *
***********************************************************************/
syntax:
  say errortext(rc)
  say sigl':' sourceline(sigl)
  say rx':' rxdata.rx
exit