/******************************************************************************/
/*                                                                            */
/* rxcomp.rex - Compare two rexx files element-wise                           */
/* ================================================                           */
/*                                                                            */
/* This program is part of the Rexx Parser package                            */
/* [See https://rexx.epbcn.com/rexx-parser/]                                  */
/*                                                                            */
/* Copyright (c) 2026-2026 Josep Maria Blasco <josep.maria.blasco@epbcn.com>  */
/*                                                                            */
/* License: Apache License 2.0 (https://www.apache.org/licenses/LICENSE-2.0)  */
/*                                                                            */
/* Version history:                                                           */
/*                                                                            */
/* Date     Version Details                                                   */
/* -------- ------- --------------------------------------------------------- */
/* 20260117    0.4a First release                                             */
/* 20260313    0.5  Move error handling to ErrorHandler.cls                   */
/* 20260314         Use InitCLI() from CLISupport.cls                         */
/*                                                                            */
/******************************************************************************/

  Signal On Syntax

  CLIhelper    = InitCLI()
  myName       = CLIhelper~name
  myHelp       = CLIhelper~help
  args         = CLIhelper~args

  If args~items == 0 Then Signal Help

  unicode      = 0
  experimental = 0
  executor     = 0
  itrace       = 0

ProcessOptions:
  If args~items == 0 Then Signal Help

  option = args[1]
  args~delete(1)

  If option[1] == "-" Then Do
    Select Case Lower(option)
      When "-h", "--help"       Then Signal Help
      When "-u", "--tutor", -
        "--unicode"             Then unicode = 1
      When "-e", "-exp",  -
        "--experimental"        Then experimental = 1
      When "-xtr", "--executor" Then executor = 1
      When "-it", "--itrace"    Then itrace = 1
      Otherwise Call Error "Invalid option '"option"'."
    End
    Signal ProcessOptions
  End

  sfile1 = option -- Remember file1 as written

  file1 = .context~package~findProgram(option)

  If file1 == .Nil Then Call Error "File '"option"' does not exist."

  If args~items == 0 Then Call Error "Missing filename after '"option"'."

  option = args[1]
  args~delete(1)

  sfile2 = option -- Remember file2 as written

  file2 = .context~package~findProgram(option)

  If file2 == .Nil Then Call Error "File '"option"' does not exist."

  If args~items > 0 Then Call Error "Invalid parameter '"args[1]"'."

  Options = .Array~new
  If Unicode      Then Options~append(("UNICODE", 1))
  If experimental Then Options~append(("EXPERIMENTAL", 1))
  If executor     Then Options~append(("EXECUTOR", 1))

  source   = LoadProgramSource(file1)
  fullpath = file1
  parser1  = .Rexx.Parser~new(file1, source, Options)
  element1 = parser1~firstElement

  source   = LoadProgramSource(file2)
  fullpath = file2
  parser2  = .Rexx.Parser~new(file2, source, Options)
  element2 = parser2~firstElement

  Loop While element1 \< .EL.END_OF_SOURCE, element2 \< .EL.END_OF_SOURCE
    Call Next
    from1 = element1~from
    from2 = element2~from
    to1   = element1~to
    to2   = element2~to
    cat1  = element1~category
    cat2  = element2~category
    src1  = element1~source
    src2  = element2~source
    If cat1 \== cat2 Then Call CategoriesDiffer
    If element1 < .ALL.SYMBOLS_AND_KEYWORDS Then Call CaselessCompare
    Else If element1 < .EL.TAKEN_CONSTANT, Pos(src1[1], "'""") == 0 Then Call CaselessCompare
    Else Call Compare
  End

  If element1 \< .EL.END_OF_SOURCE Then Do
    Say file2 "exhausted but" file1 "continues at ["from1"-"to1"]: '"src1"'."
    Exit 1
  End

  If element2 \< .EL.END_OF_SOURCE Then Do
    Say file1 "exhausted but" file2 "continues at ["from2"-"to2"]: '"src2"'."
    Exit 1
  End

  Exit

CategoriesDiffer:
  Say sfile1 "@" from1"-"to1 "is '"src1"' (a" .Parser.CategoryName[cat1]"), but" .EndOfLine || -
    sfile2 "@" from2"-"to2 "is '"src2"' (a" .Parser.CategoryName[cat2]")."
  Exit 1

CaselessCompare:
  val1  = element1~value
  val2  = element2~value
  If val1 == val2 Then Return
  Say "Elements '"val1"' ["from1"-"to1"] and '"val2"' ["from2"-"to2"] differ."
  Exit 1

Compare:
  If src1 == src2 Then Return
  Say "Elements '"src1"' ["from1"-"to1"] (a" .Parser.CategoryName[cat1]") and '"src2"' ["from2"-"to2"] (a" .Parser.CategoryName[cat2]") differ."
  Exit 1

Next:
  Call Next1
  Call Next2
  Return

Next1:
  element1 = element1~next
  If element1 < .EL.END_OF_SOURCE Then Return
  If element1~ignorable           Then Signal Next1
  If element1~from == element1~to Then Signal Next1
  Return

Next2:
  element2 = element2~next
  If element2 < .EL.END_OF_SOURCE Then Return
  If element2~ignorable           Then Signal Next2
  If element2~from == element2~to Then Signal Next2
  Return


--------------------------------------------------------------------------------

Error:
 .Error~Say(Arg(1))
  Exit 1

--------------------------------------------------------------------------------

Help:
  Say .Resources[Help]~makeString        -
    ~caselessChangeStr("myName", myName) -
    ~caselessChangeStr("myHelp", myHelp)
  Exit 1

--------------------------------------------------------------------------------
-- Delegate parsing errors to the standard ErrorHandler                       --
--------------------------------------------------------------------------------

Syntax:
  co = condition("O")
  -- Not a 98.900? This is an application error
  If co~code \== 98.900 Then Do
   .Error~Say( "Error" co~code "in" co~program", line" co~position":" )
    Raise Propagate
  End
  Exit ErrorHandler( fullPath, source, co, itrace)

--------------------------------------------------------------------------------

::Requires "Rexx.Parser.cls"
::Requires "ErrorHandler.cls"
::Requires "CLISupport.cls"
::Requires "BaseClassesAndRoutines.cls"
::Requires "modules/print/print.cls"

--------------------------------------------------------------------------------

::Resource Help end "::End"
myname - Compare two Rexx files element-wise

Usage: myName [options] FILE1 FILE2

Options:
-xtr,--executor     Enable support for Executor
-e,  --experimental Enable Experimental features (also -exp)
     --help         Display this information
-it, --itrace       Print internal traceback on error
     --tutor        Enable TUTOR-flavored Unicode
 -u, --unicode      Enable TUTOR-flavored Unicode

The 'myname' program is part of the Rexx Parser package,
see https://rexx.epbcn.com/rexx-parser/. It is distributed under
the Apache 2.0 License (https://www.apache.org/licenses/LICENSE-2.0).

Copyright (c) 2024-2026 Josep Maria Blasco <josep.maria.blasco@epbcn.com>.

See myhelp for details.
::End