To support this I would like to briefly give some glimpse at a tool that I have been developing, but because of my current time restrictions has not been proceeded to the stage where I would be able to hand it out to the public, but which could be used to easily analyze and exploit "label annotations" as discussed in this thread [thinking of this it would be very helpful when debugging programs and analyzing certain code segments using labels to become able to see e.g. which statements get executed (and which not) under which conditions].

The tool is currently named "tracetool" and takes advantage of the new TraceObject class. One intended application is to run any Rexx and ooRexx programs in trace mode, intercept the trace and store it as a trace log in a file for inspection and analysis. In case problems occur the trace log could be sent to the authors of the Rexx or ooRexx program for analysis.

In this application having the ability to place labels in programs the value of an analysis with "trace labels" would be enhanced considerably! The trace logs could be analyzed manually or by Rexx or ooRexx programs quite easily. (The tool as it is stands now is already able to analyze a trace log to find the deadlocked parts of an ooRexx program and mark all places that are deadlocked and all places where a wait on a guard lock takes place. This has only become possible because of the powerful trace keyword instruction in combination with the TraceObject class.)

To give a little example, here a Rexx program that gets run without and with 
"::options trace labels".

The program:

   parse source op_sys +1 . . s fileName=filespec("n",s) say "ob_sys:" op_sys 
"fileName:" fileName
   if op_sys='W' then do if random(0,1) then signal win else signal other end 
else do if
   random(0,1) then signal other else signal win end win: call winInfo fileName 
signal continue
   other: call otherInfo fileName continue: say "done." exit winInfo: procedure 
parse arg fileName
   say .context~name"|winInfo:" fileName return ::routine otherInfo parse arg 
fileName say
   .context~name"|otherInfo:" fileName

Running it a couple of times (to get random() to use both branches) without 
trace yields one of:

   G:\test\orx\trace\testLabel>testLabel.rex
   ob_sys: W fileName: testLabel.rex
   WININFO|winInfo: testLabel.rex
   done.

   ...

   G:\test\orx\trace\testLabel>testLabel.rex
   ob_sys: W fileName: testLabel.rex
   OTHERINFO|otherInfo: testLabel.rex
   done.

Running the same program adding "::options trace label" at the end a couple of times (to get random() to use both branches) yields one of:

   --- with "::options trace labels"

   G:\test\orx\trace\testLabel>testLabel.rex
   ob_sys: W fileName: testLabel.rex
        19 *-* win:
        29 *-*   winInfo:
   WININFO|winInfo: testLabel.rex
        25 *-* continue:
   done.

   ...

   G:\test\orx\trace\testLabel>testLabel.rex
   ob_sys: W fileName: testLabel.rex
        22 *-* other:
           >I> Routine "OTHERINFO" in package 
"G:\test\orx\trace\testLabel\testLabel.rex".
   OTHERINFO|otherInfo: testLabel.rex
           <I< Routine "OTHERINFO" in package 
"G:\test\orx\trace\testLabel\testLabel.rex".
        25 *-* continue:
   done.

So "trace label" shows each encountered label which differs in this example depending on the random(0,1) function value generated.

Using the original program (without an "::options trace labels" in it) the tool allows for running it with different trace options in effect, including "trace label", here an example ("-tl" means "trace labels"):

   G:\test\orx\trace\testLabel>tracetool -tl testLabel.rex

The output in the terminal may be:

   ob_sys: W fileName: testLabel.rex
   WININFO|winInfo: testLabel.rex
   done.

By default the trace log's file name will be in this case: "testLabel.rex_trace.xml" which we can feed to the tracetool to display the trace lines like this:

   G:\test\orx\trace\testLabel>tracetool -s testLabel.rex_trace.xml
           >I> Routine "testLabel.rex" in package "testLabel.rex".
        19 *-* win:
        29 *-*   winInfo:
        25 *-* continue:
           <I< Routine "testLabel.rex" in package "testLabel.rex".

If one wishes to get almost all trace information (which in this case is not 
really needed):

   G:\test\orx\trace\testLabel>tracetool -s -fm1 testLabel.rex_trace.xml
   #    1 | 15:46:31.443000 [R1   T2   I1   ]                          >I> Routine 
"testLabel.rex" in package "testLabel.rex".
   #    2 | 15:46:31.444000 [R1   T2   I1   ]                       19 *-* win:
   #    3 | 15:46:31.444000 [R1   T2   I2   ]                       29 *-*   
winInfo:
   #    4 | 15:46:31.445000 [R1   T2   I1   ]                       25 *-* 
continue:
   #    5 | 15:46:31.445000 [R1   T2   I1   ]                          <I< Routine 
"testLabel.rex" in package "testLabel.rex".

The created trace log will be by default xml encoded and will look like this (and could be analyzed by applying XSLT scripts or Rexx scripts etc.):

   <traceLog> <traceObject> <option>P</option> <number>1</number>
   <timestamp>2024-11-11T15:46:31.443000</timestamp> 
<interpreter>1</interpreter>
   <thread>2</thread> <invocation>1</invocation> <lineNr>1</lineNr> 
<callerStackFrame>
   <arguments></arguments> <executableId>FD17BD87</executableId>
   <executablePackage>REXX</executablePackage> <line>.nil</line> 
<name>CALL</name>
   <package>REXX</package> <scope>Routine</scope> <scopeId>FD17C3AB</scopeId>
   <scopePackage>REXX</scopePackage> <target>a Routine</target> 
<targetCanonicalName>a
   Routine</targetCanonicalName> <targetId>FB4680AF</targetId> 
<targetPackage>REXX</targetPackage>
   <targetPackageId>FD219897</targetPackageId> <traceLine> *-* Compiled method 
"CALL" with scope
   "Routine".</traceLine> <type>METHOD</type> </callerStackFrame> <stackFrame>
   <arguments></arguments> <executableId>FB4680AF</executableId>
   <executablePackage>testLabel.rex</executablePackage> <line>1</line> 
<name>testLabel.rex</name>
   <package>testLabel.rex</package> <target>.nil</target> <traceLine> 1 *-* 
parse source op_sys +1
   . . s</traceLine> <type>ROUTINE</type> </stackFrame> <traceLine> &gt;I&gt; 
Routine
   "testLabel.rex" in package "testLabel.rex".</traceLine> </traceObject> 
<traceObject>
   <option>P</option> <number>2</number> 
<timestamp>2024-11-11T15:46:31.444000</timestamp>
   <interpreter>1</interpreter> <thread>2</thread> <invocation>1</invocation> 
<lineNr>19</lineNr>
   <stackFrame> <arguments></arguments> <executableId>FB4680AF</executableId>
   <executablePackage>testLabel.rex</executablePackage> <line>19</line> 
<name>testLabel.rex</name>
   <package>testLabel.rex</package> <target>.nil</target> <traceLine> 19 *-* 
win:</traceLine>
   <type>ROUTINE</type> </stackFrame> <traceLine> 19 *-* win:</traceLine> 
</traceObject>
   <traceObject> <option>P</option> <number>3</number>
   <timestamp>2024-11-11T15:46:31.444000</timestamp> 
<interpreter>1</interpreter>
   <thread>2</thread> <invocation>2</invocation> <lineNr>29</lineNr> 
<stackFrame>
   <arguments>testLabel.rex</arguments> <executableId>FB4680AF</executableId>
   <executablePackage>testLabel.rex</executablePackage> <line>29</line> 
<name>WININFO</name>
   <package>testLabel.rex</package> <target>.nil</target> <traceLine> 29 *-* 
winInfo:</traceLine>
   <type>INTERNALCALL</type> </stackFrame> <traceLine> 29 *-* winInfo:</traceLine> 
</traceObject>
   <traceObject> <option>P</option> <number>4</number>
   <timestamp>2024-11-11T15:46:31.445000</timestamp> 
<interpreter>1</interpreter>
   <thread>2</thread> <invocation>1</invocation> <lineNr>25</lineNr> 
<stackFrame>
   <arguments></arguments> <executableId>FB4680AF</executableId>
   <executablePackage>testLabel.rex</executablePackage> <line>25</line> 
<name>testLabel.rex</name>
   <package>testLabel.rex</package> <target>.nil</target> <traceLine> 25 *-* 
continue:</traceLine>
   <type>ROUTINE</type> </stackFrame> <traceLine> 25 *-* continue:</traceLine> 
</traceObject>
   <traceObject> <option>P</option> <number>5</number>
   <timestamp>2024-11-11T15:46:31.445000</timestamp> 
<interpreter>1</interpreter>
   <thread>2</thread> <invocation>1</invocation> <lineNr>27</lineNr> 
<stackFrame>
   <arguments></arguments> <executableId>FB4680AF</executableId>
   <executablePackage>testLabel.rex</executablePackage> <line>27</line> 
<name>testLabel.rex</name>
   <package>testLabel.rex</package> <target>.nil</target> <traceLine> 27 *-* 
exit</traceLine>
   <type>ROUTINE</type> </stackFrame> <traceLine> &lt;I&lt; Routine 
"testLabel.rex" in package
"testLabel.rex".</traceLine> </traceObject> </traceLog>
The tool allows to create the logfile in json encoded format instead, e.g.

   [ { "option": "P", "number": 1, "timestamp": "2024-11-11T15:46:31.443000", 
"interpreter": 1,
   "thread": 2, "invocation": 1, "lineNr": 1, "callerStackFrame": { "arguments": 
"",
   "executableId": "FD17BD87", "executablePackage": "REXX", "line": null, "name": 
"CALL",
   "package": "REXX", "scope": "Routine", "scopeId": "FD17C3AB", "scopePackage": "REXX", 
"target":
   "a Routine", "targetCanonicalName": "a Routine", "targetId": "FB4680AF", 
"targetPackage":
   "REXX", "targetPackageId": "FD219897", "traceLine": " *-* Compiled method 
\"CALL\"with scope
   \"Routine\".", "type": "METHOD" }, "stackFrame": { "arguments": "", "executableId": 
"FB4680AF",
   "executablePackage": "testLabel.rex", "line": "1", "name": "testLabel.rex", 
"package":
   "testLabel.rex", "target": null, "traceLine": " 1 *-* parse source op_sys +1 . . s", 
"type":
   "ROUTINE" }, "traceLine": " >I> Routine \"testLabel.rex\"in package 
\"testLabel.rex\"." }, {
   "option": "P", "number": 2, "timestamp": "2024-11-11T15:46:31.444000", 
"interpreter": 1,
   "thread": 2, "invocation": 1, "lineNr": 19, "stackFrame": { "arguments": "", 
"executableId":
   "FB4680AF", "executablePackage": "testLabel.rex", "line": "19", "name": 
"testLabel.rex",
   "package": "testLabel.rex", "target": null, "traceLine": " 19 *-* win:", "type": 
"ROUTINE" },
   "traceLine": " 19 *-* win:" }, { "option": "P", "number": 3, "timestamp":
   "2024-11-11T15:46:31.444000", "interpreter": 1, "thread": 2, "invocation": 2, 
"lineNr": 29,
   "stackFrame": { "arguments": "testLabel.rex", "executableId": "FB4680AF", 
"executablePackage":
   "testLabel.rex", "line": "29", "name": "WININFO", "package": "testLabel.rex", 
"target": null,
   "traceLine": " 29 *-* winInfo:", "type": "INTERNALCALL" }, "traceLine": " 29 *-* 
winInfo:" }, {
   "option": "P", "number": 4, "timestamp": "2024-11-11T15:46:31.445000", 
"interpreter": 1,
   "thread": 2, "invocation": 1, "lineNr": 25, "stackFrame": { "arguments": "", 
"executableId":
   "FB4680AF", "executablePackage": "testLabel.rex", "line": "25", "name": 
"testLabel.rex",
   "package": "testLabel.rex", "target": null, "traceLine": " 25 *-* continue:", "type": 
"ROUTINE"
   }, "traceLine": " 25 *-* continue:" }, { "option": "P", "number": 5, 
"timestamp":
   "2024-11-11T15:46:31.445000", "interpreter": 1, "thread": 2, "invocation": 1, 
"lineNr": 27,
   "stackFrame": { "arguments": "", "executableId": "FB4680AF", 
"executablePackage":
   "testLabel.rex", "line": "27", "name": "testLabel.rex", "package": "testLabel.rex", 
"target":
   null, "traceLine": " 27 *-* exit", "type": "ROUTINE" }, "traceLine": " <I< 
Routine
   \"testLabel.rex\"in package \"testLabel.rex\"." } ]

or as a csv-file with a header line, e.g.

   
option,number,timestamp,interpreter,thread,invocation,lineNr,callerStackFrame,stackFrame,variable,receiver,receiverCanonicalName,receiverId,attributePool,scopeLockCount,isGuarded,hasScopeLock,isWaiting,isBlocked,traceLine
   "P","1","2024-11-11T15:46:31.443000","1","2","1","1","arguments: / 
executableId: FD17BD87 /
   executablePackage: REXX / line: .nil / name: CALL / package: REXX / scope: 
Routine / scopeId:
   FD17C3AB / scopePackage: REXX / target: a Routine / targetCanonicalName: a 
Routine / targetId:
   FB4680AF / targetPackage: REXX / targetPackageId: FD219897 / traceLine: *-* 
Compiled method
   ""CALL"" with scope ""Routine"". / type: METHOD / ","arguments: / 
executableId: FB4680AF /
   executablePackage: testLabel.rex / line: 1 / name: testLabel.rex / package: 
testLabel.rex /
   target: .nil / traceLine: 1 *-* parse source op_sys +1 . . s / type: ROUTINE / 
",,,,,,,,,,," >I>
   Routine ""testLabel.rex"" in package ""testLabel.rex""."
   "P","2","2024-11-11T15:46:31.444000","1","2","1","19",,"arguments: / 
executableId: FB4680AF /
   executablePackage: testLabel.rex / line: 19 / name: testLabel.rex / package: 
testLabel.rex /
   target: .nil / traceLine: 19 *-* win: / type: ROUTINE / ",,,,,,,,,,," 19 *-* 
win:"
   "P","3","2024-11-11T15:46:31.444000","1","2","2","29",,"arguments: 
testLabel.rex / executableId:
   FB4680AF / executablePackage: testLabel.rex / line: 29 / name: WININFO / 
package: testLabel.rex
   / target: .nil / traceLine: 29 *-* winInfo: / type: INTERNALCALL / 
",,,,,,,,,,," 29 *-*
   winInfo:" "P","4","2024-11-11T15:46:31.445000","1","2","1","25",,"arguments: 
/ executableId:
   FB4680AF / executablePackage: testLabel.rex / line: 25 / name: testLabel.rex 
/ package:
   testLabel.rex / target: .nil / traceLine: 25 *-* continue: / type: ROUTINE / 
",,,,,,,,,,," 25
   *-* continue:" 
"P","5","2024-11-11T15:46:31.445000","1","2","1","27",,"arguments: /
   executableId: FB4680AF / executablePackage: testLabel.rex / line: 27 / name: 
testLabel.rex /
   package: testLabel.rex / target: .nil / traceLine: 27 *-* exit / type: ROUTINE / 
",,,,,,,,,,,"
   <I< Routine ""testLabel.rex"" in package ""testLabel.rex""."

As you can see there is a lot of trace information made available in trace logs by tracetool in different encodings meant to allow anyone who has a need to analyze trace logs to do so.

Now, if it was possible in ooRexx to fully label all kind of areas/statements together with a tool like tracetool makes it possible to create programs that can quickly analyze and produce any kind of report, allowing one to even analyze the most complex Rexx programs.

---

So, whoever has a little time and has the knowledge to quickly adjust the ooRexx label keyword statement to allow for full labeling, please do so!

It would be much appreciated and a very helpful addition for Rexx programmers to debug Rexx or ooRexx programs.

---rony



On 25.10.2024 22:29, Rick McGuire wrote:

On Fri, Oct 25, 2024 at 4:24 PM Chip Davis <c...@aresti.com> wrote:

    And yet, Rick said, "So the question comes down to 1) disallow them if they 
appear in a
    location where they can't be branched to, or 2) allow them, but catch all 
attempts to branch
    to one in a bad location. From my standpoint, catching them at translation 
time and raising an
    error is much better than the disruption that would be caused to rework the 
internals to raise
    an error at run time. And the nice thing about raising an error up front is 
that it is always
    easier to lift a restriction later than try to impose one after the fact."

    "... the attempt to branch to them" is at execution time, and Rick has 
already deemed it a
    "disruption that would be caused to rework the internals to raise an error at 
run time", so
    that seems like a heavy lift to me.


I took a quick look at the code, the disruption is much less severe that I first thought and can even be done without causing problems with programs saved using rexxc.

Rick


    I still agree with JMB's "take".  "Belling the cat" at run-time sounds like 
a non-trivial effort.

    -Chip-

    On 10/25/2024 9:35 AM, Gilbert Barmwater wrote:

    I've read all the comments (so far) on this and the ones that had the most 
impact on my
    opinion were Mike's -
    "...it's the attempt to branch to them that should be flagged, not the 
label itself, which is
    just a label." - and Jeremy's - "Some users might be running code that they 
don't have source
    for - ie they've been supplied with the output from rexxc.  Why should they 
not be able to
    continue to run their programs?".  So I vote for allowing "trace only" 
labels but raising an
    error if an attempt is made to SIGNAL or CALL them.

    On 10/23/2024 9:31 AM, Josep Maria Blasco wrote:
    Hi all,

    There are some ongoing changes to the ooRexx interpreter that will strongly 
affect the
    language definition, in such a way that the 5.1.0 release may end up 
implementing a version
    of the language that does no longer allow us to hold true what is asserted 
in the landing
    page for the project:

        "Home of the Open Object Rexx Project. ooRexx is the open source 
version of IBM's Object
        REXX Interpreter. *It is upwardly compatible with classic REXX and will 
execute classic
        REXX programs unchanged*. The project is managed by the Rexx Language 
Association".


    In the preceding paragraph, I have highlighted the part that will become 
problematic if the
    ongoing changes consolidate. Namely,

      * Any program containing labels inside block instructions will 
immediately stop working
        (with syntax error 47.002 for DO/LOOP, 47.003 for IF, and 47.004 for 
SELECT).
      * Any program containing labels before the initial EXPOSE or USE LOCAL 
method instructions
        will fail (with 99.910 for USE LOCAL and 99.907 for EXPOSE).

    Please note that _these programs will stop working even if they never 
branch_ (i.e., SIGNAL
    or CALL) _to any of these labels_. Normal ("classic Rexx") semantics for 
such labels is to
    treat them as null clauses, except for tracing purposes: when TRACE Labels 
is in effect, the
    language processor

        Traces [...] labels passed during program execution. This is especially 
useful
        with debug mode, when the language processor pauses after each 
invocation or call
        (rexxref 2.29.1).


    If the ongoing changes consolidate into the 5.1.0 release, our claim of 
compatibility with
    classic Rexx will no longer be valid.

    My impression is that these changes should be reverted, but I understand 
that there has been
    a considerable amount of effort put by the developers in implementing these 
modifications,
    and therefore such a reversal should not be undertaken slightly.

    Please allow me to elaborate on the background behind these changes, to 
widen our
    perspective about the subject.

    *Statement of the problem*

    A label is a clause. Following TRL2 (and TRL1, in that respect), "more than 
one label may
    precede /any instruction/" (emphasis mine). Some interpreters seem to allow 
labels preceding
    /any clause/. To appreciate the difference between the two concepts, please 
consider the
    following small program:

        Trace L
        A: If 1 = 1
        B: Then
        C: Say "Hi"


    Object Rexx (6.00, ArcaOS) chokes on B:, but allows A: and C: (THEN is not 
an instruction by
    itself); Regina Rexx happily processes A:, B: and C: (and traces them, when 
asked); the
    current version of ooRexx refuses to run the above program, even if we 
eliminate the B:
    label (it produces a 47.3, 'Labels are not allowed within an IF block; found 
"C"').

    The ANSI standard defines labels inside a block instruction as 
"trace-only", and reserves
    errors 16.2 and 16.3 for the cases when a CALL or SIGNAL instruction tries 
to target one of
    these labels.

    The Errata for the Rexx standard explicitly corrects 6.3.2.14 and 6.3.2.19, 
stating "This
    disallows labels before the THEN keyword".

    Now the question is the following:
    *
    *
    *¿What variant of the language should ooRexx implement?*

    There was some discussion in the developers list (starting at
    https://sourceforge.net/p/oorexx/mailman/message/58813104/) about whether 
labels inside
    block instructions should be allowed to be called/branched to. The 
consensus was that this
    should not be allowed, putting ooRexx in line with the ANSI standard in 
this respect. I
    agree with that.

    There was also a discussion about whether labels should be allowed when/ 
they cannot be
    branched to/. The example used was relatively ambiguous, since it used a 
label before a THEN
    keyword:

        label: THEN


    ¿Why do I say that this is an ambiguous example? Because one might object 
to disallowing
    such a label, a) because THEN is not an instruction, or b) because THEN is 
part of an IF.
    Depending on how we understand the example, we will have two different 
versions of the language.

    *The main point is this*

    One may have good reasons to want to disallow labels before THEN and, at 
the same time,
    think that /instructions/ inside other instructions (i.e., /not/ clauses 
which are not
    instructions by themselves) deserve to have labels, even if they are, as 
the ANSI standard
    says, trace-only.

    *My take is the following*

    Labels before THEN, ELSE, WHEN, OTHERWISE or END should not be allowed. All 
other labels
    should be allowed, including before EXPOSE and USE LOCAL. SIGNALing or 
CALLing a label
    before EXPOSE or USE LOCAL, or a label inside an IF/DO/LOOP/SELECT should 
produce an error.

    *What do you all think?*

    This is important. We are about to change the definition of the language, 
making it
    potentially incompatible with many existing programs.

_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to