Typically, you'll be using one of the three "Step" commands to make the debugger execute the next instruction, and then pause after, so that you have time to observe the information about that instruction in the Results area. Each time you issue one of the "Step" commands, it will execute the next step of the current instruction. A simple REXX instruction may have only one step. But a complex REXX instruction will likely have more than one step. If so, you may need to issue the Step command several times for that instruction. As you do, the editor window will continue to highlight the line containing that instruction, and the Results area will accumulate the results of each step. After the last step is executed for a given instruction, the debugger displays <<Done>> in the Results area. When you click the Step button again, the editor window advances to (highlights) the next instruction and the debugger executes that instruction's first step. The Results area is cleared (of the preceding instruction's results) so that you can now observe the results of only this next instruction.
Let's take an example. We'll assume that the first instruction in the script is i = 5, and that you have just started the debugger (initially paused at the first instruction). You click on the debugger toolbar's "Step" button once. The instruction i = 5 is highlighted in the editor window, and the first step of this instruction is executed. The Results area then displays the results of that step. You should see the following in the Results window:
i = "5" <<Done>>The line i = 5 means that the variable named i was used in your instruction and its current value is shown after the equal sign. The value is shown between double quotes (although the quotes are not part of the actual value). This is just so that you can better see any leading or trailing spaces on the value. Indeed, since our instruction set i to the value 5, it makes sense why the debugger is confirming this.
It just so happens that this simple instruction has only one step, and so you'll see <<Done>>. Now you can click the Step button again to clear the Results window and advance to the first step of the next instruction.
Let's assume that the next instruction is p = i. You should see the following results:
i = "5" p = "5" <<Done>>The debugger is reporting that the variable named i is being used in this step, and its current value is 5. The variable named p is also being used in this step, and its current value is now 5 (since our instruction assigned it that value).
This instruction also has only one step, so if you click on the "Step" button again, it will advance to the next instruction. Let's assume that next instruction is i = i + p. You should see the following results:
i = "5" p = "5" Addition: 10 i = "10" <<Done>>The debugger is reporting that the variable named i is being used in this step, and its current value is 5. The variable named p is also being used in this step, and its current value is 5. The line starting with Addition means that a mathematical addition operation has been performed. In this case, we've added the values of i and p, and the result of that operation (ie, 5 + 5) is shown. Finally, the variable named i is being used once more in this step, and its current value is now 10 (since our instruction assigned it the value of that addition operation).
If you happen to reference a compound variable whose tail names are not all numeric, then tail name substitution is performed. The debugger will show this in the Results area by listing each tail name (that will be substituted) and showing its current value. The debugger also then shows the real name of the compound variable with tail name substitution, along with its current value. For example, let's say that we now have the instruction myvar.i.p = "hello". You should see the following in the Results area:
i = "10" p = "5" MYVAR.10.5 = "hello" <<Done>>Above, we've used the variables i and p as tail names in our compound variable myvar.i.p. So, the debugger first shows us the current values of those variables. They are 10 and 5, respectively. Then the debugger shows us the real name of our compound variable, after substituting those non-numeric tail names with their values. It is MYVAR.10.5. That is the real variable whose value is set to the string "hello".
Debugging a subroutine/function in your script
Let's assume that you have a subroutine or function within your script. You have labeled this subroutine/function MySub, and written it to return the value of the variable named SomeVar. Here is how your instructions may look:
MySub: RETURN SomeVarLet's say that you also make a call to this function, passing it the value of a variable named MyVar (which happens to have the value 10) and you assign the return of this function to a variable named AnotherVar. Here is our completed script:
MyVar = 10 AnotherVar = MySub(MyVar) EXIT MySub: RETURN SomeVarAs you may guess, the function call to MySub is going to involve more than one step since we have to execute all of the instructions in MySub before our instruction AnotherVar = MySub(MyVar) completes, and we move on to the EXIT instruction following it. Let's take the debugger through this script by clicking on the Step button and observe the results. (If you'd like, drag the mouse over the above snippet of REXX code and select Edit -> Copy from this help window. Now go over to a Rexx Center editor window, and Edit -> Paste the text into the editor. Now you can carry out each step below in Rexx Center's debugger as you read the example).
Select the Start debugger command. The debugger will start, paused at the first instruction. If you click upon the Step button, it will execute the first step of the this first instruction, and you will see the following in the Results area:
MYVAR = "10" <<Done>>
The debugger indicates that the variable named MYVAR is being referenced, and its current value is 10 (as you may expect).
There are no more steps to this instruction, so if you click upon the Step button, the debugger will advance to the next instruction, and execute its first step. The editor window will highlight that instruction and you should see the following in the Results window:
MYVAR = "10"Because this instruction involves a call to a subroutine/function, the first step is to evaluate the value of each argument being passed to that subroutine/function. Here, we have only one argument. The debugger shows that we're referencing the variable named MYVAR, and its current value is 10.
The debugger pauses after evaluating the arguments passed to a subroutine/function, but before actually diving into that subroutine/function. That's the end of this step. But this instruction is not yet done. (Notice that <<Done>> is not yet displayed). We still have to call MySub, execute all of its instructions, and return. Now click the Step button again, and the debugger will dive into MySub. You should see the following in the Results area:
MYVAR = "10" MYSUB() SIGL = "1"The editor window now jumps to the label of our subroutine, MySub, and highlights it. You'll notice that there is a blank line in the Results window, followed by the name of the subroutine called, in this case, MySub. MySub also indicates that the special SIGL variable has been set to the line number upon which MySub was called.
You'll also note that the Results area still shows the evaluated args that were passed to MySub. These are shown above the name of the subroutine. That's because we're not yet done with that instruction which called MySub. We still have more results to show for it... after we return from MySub.
If you click on the Step button, the editor window will advance to the first line of the subroutine, highlight it, and execute its first step. You should see the following:
MYVAR = "10" MYSUB() NOVALUE raised: SOMEVAR SOMEVAR = "SOMEVAR" <<Done>>Note that any previous results shown for MySub() are cleared away now that they're done. (So, you no longer see SIGL's value).
Here we have something interesting. You'll note that our script hasn't previously assigned the variable "SomeVar" any value. Whenever a variable is referenced, but has not yet been assigned a value, REXX raises the NOVALUE condition. The Results area indicates that the NOVALUE condition has been raised upon this instruction due to the variable named "SomeVar".
Since our script didn't trap NOVALUE via a preceding CATCH NOVALUE statement, then REXX does the default handling for this condition, which is to simply ignore it. The debugger has nevertheless informed us of this condition being raised.
And of course, since we have indeed referenced the variable "SomeVar", the Results area shows its current value, which is the name of the variable upper-cased. (Recall that when a REXX variable is not assigned any particular value, its "default value" is its name, upper-cased).
This instruction has only one step, so if you click the Step button again, the editor window advances to the next instruction in the subroutine. But of course, there is no more instructions in the subroutine because we have just done a RETURN instruction. So, the editor window returns to the instruction that called MySub. You should see that instruction highlighted again.
You'll also note that the Results area clears away the results of MySub, now that we're no longer executing instructions in MySub, and it proceeds to the next step of the current instruction. That step is to assign the return value of MySub to the variable named ANOTHERVAR. You'll notice that the debugger shows that MySub returned the value "SOMEVAR". It does this by displaying the name of the subroutine, followed by parentheses and a => symbol. The returned value is in double quotes, although they are not part of the actual value.
Finally, the debugger shows that the variable named ANOTHERVAR is referenced and its current value is now "SOMEVAR". That is the end of the final step of this instruction.
If you click on the Step button again, the editor window will advance to the next instruction, which is the EXIT instruction.
This EXIT instruction has only one step, so if you click upon the "Step" button, the script will end now.
Resizing the Debugger window
You can resize the Debugger window, or float it, or dock to any side of the main window, by manipulating it with the mouse, just like the Reference window.
When the Debugger window is docked, and you resize the main window itself, then the Debugger window is automatically resized appropriately.
You can hide the Debugger window by selecting "Debugger window" under the View menu.
PARSE, ARG, PULL
If your instruction contains a PULL, ARG, or PARSE keyword, the source value being parsed is shown. Also, if some token is thrown away, then the discarded token is displayed.
Consider the following script:
MyVar = 'This is some data' PARSE VAR MyVar token1 . token2 . EXITNote that we're throwing away the second and fourth pieces (ie, tokens) that we break off. If you Step through the PARSE instruction, this displays the following in the Results area:
MYVAR = "This is some data" TOKEN1 = "This" Token discarded: "is" TOKEN2 = "some" Token discarded: "data" <<Done>>First, because we are using a PARSE VAR instruction, with MYVAR being the source variable, the value of MYVAR is shown. This value is what is being parsed.
Next, the debugger shows that TOKEN1 is referenced and its value is now "This". (Again, the value is put in double quotes, although they are not part of the actual value, so that you can see any leading or trailing spaces on the value).
Next, the debugger shows that the token "is" is being discarded.
The debugger also shows that TOKEN2 is assigned the value "some" and the fourth token of "data" is discarded.
When using the PARSE ARG instruction, the debugger shows each argument that is being parsed. It is prefaced by Arg => and followed by the argument's value in double quotes (although the quotes are not part of the actual value). For example, assume that your script is called by some other script which passes you two arguments of alpha beta gamma delta and 1. Let's assume that your script is named test.rex. The call to your script may look like this:
/* Call text.rex, passing it 2 args of * "alpha beta gamma delta" and "1". */ CALL test("alpha beta gamma delta", 1)Now assume that your test.rex script has the following instruction in it:
/* Parse the first argument into 3 tokens, * named token.1, token.2, token.3 and toss away * any additional characters of it. Parse the * second argument into a variable named number, * and toss away any additional characters. * Ignore all other arguments. */ PARSE ARG token.1 token.2 token.3 . , number .When you Step through this PARSE ARG instruction, the Results area will show:
Arg => "alpha beta gamma delta" TOKEN.1 = "alpha" TOKEN.2 = "beta" TOKEN.3 = "gamma" Token discarded: "delta" Arg => "1" NUMBER = "1" <<Done>>If an argument to your script is omitted, then this is noted by the absense of any value after Arg =>. But the PARSE ARG statement nevertheless still parses omitted arguments as if they were empty strings. Consider if test.rex is called as so, with the second arg omitted:
/* Call text.rex, passing it 1 arg of * "alpha beta gamma delta". */ CALL test("alpha beta gamma delta")The Results area for the PARSE ARG instruction will show:
Arg => "alpha beta gamma delta" TOKEN.1 = "alpha" TOKEN.2 = "beta" TOKEN.3 = "gamma" Token discarded: "delta" Arg => NUMBER = "" <<Done>>
Comparisons
If you do a comparison between two items, then the result of that comparison is displayed (ie, TRUE or FALSE), preceded by the word "Comparison" and the operator used.
For example, assume that you have the following instruction comparing two variables named i and p where i has the value 5 and p has the value 10:
IF i = p THEN SAY "They are equal."If you step through this instruction, it will show the following RESULTS:
I = "5" P = "10" = Comparison: FALSE <<Done>>Of course, since we referenced both i and p, their values are shown. The line = Comparison: FALSE tells us that our comparison to see if they are equal is FALSE. (ie, They are not equal). And since they are not equal, then the SAY instruction does not get interpreted, so this instruction is done, as indicated by the Results area.
Now let's assume that we have the following instruction:
IF i \= p THEN SAY "They are not equal."If you click the step button once, it will show the following results:
I = "5" P = "10" \= Comparison: TRUEThe line \= Comparison: TRUE tells us that our comparison to see if they are not equal is TRUE. (ie, They are not equal). And since they are not equal, then the SAY instruction will get interpreted, so this test is not yet done, as indicated by the Results area. We have another step to this test. If you click the Step button again, the Results area will clear, and we will proceed to executing the first step of the following SAY instruction (ie, what comes after THEN).
Boolean operations
If you use a boolean operator between two items, then the result of that operation is displayed, preceded by the word "Boolean" and the operator used. Many times boolean operators are used to make multiple comparisons in an IF/THEN or WHEN/THEN instruction. For example, if you OR two expressions, and one of them happens to be TRUE, then the boolean result is TRUE (ie, 1).
Assume that we have a variable named MyVar1 whose value is "Hello", and another variable named MyVar2 whose value is "There". Let's examine the results for the following IF THEN instruction:
IF MyVar1 = "Hello" | MyVar2 = "" THEN NOPThis results in the following:
MYVAR1 = "Hello" = Comparison: TRUE MYVAR2 = "There" = Comparison: FALSE Boolean OR: TRUESince we referenced two variables (MyVar1 and MyVar2), their respective values of "Hello" and "There" are displayed. The results indicates that the first = comparison (between MyVar1 and the literal string "Hello") is TRUE. (ie, They are equal). The results indicates that the second = comparison (between MyVar2 and the literal string "") is FALSE. (ie, They are not equal).
Finally, since we are using a boolean OR operator to combine two expressions, the result of that operation is displayed. Since one of the expressions happens to be TRUE (ie, MyVar1 = "HELLO") then the result is TRUE.
Negation
If you reference an item prefixed with a '-' sign (ie, to make it negative), then that item's signed value is displayed, preceded by the word Negation to indicate that it is a numeric value with its sign applied.
For example, let's examine the results for the following instructions:
MyVar = 5 SAY -MyVarThis results in the following for the line SAY -MyVar:
MYVAR = "5" Negation: -5The debugger shows that there is a variable referenced whose value is 5 (ie, MyVar). Then, the negative sign is applied to that value, and this signed value is shown.