Exspans Systems Inc Logo home
 
Forum
Sign up Calendar Latest Topics
 
 
 


Reply
  Author   Comment   Page 1 of 2      1   2   Next
zboxassist

Member
Registered:
Posts: 89
Reply with quote  #1 
Here is a nonsense script that demonstrates an infinite substitution loop and some unexpected substitution results:
VAR XX
VAR YY
VAR ZZ
LET XX='12'
LET YY='34'
LET ZZ='XXYYXX'
WTO '1 (XXYYXX)'
WTO '2 (ZZ)'
LET XX='YX'
WTO '3 (XXYYXX)'
LET YY='XY'
WTO '4 (XXYYXX)'
LET XX=SUBSTR(ZZ,4,2)
WTO '5 (XXYYXX)'
WTO '6 EXIT'

The result is:
- 15.06.08 TST2 .run test
- 15.06.08 TST2 S0305049 1 (1234XX)
- 15.06.08 TST2 S0305049 2 (1234XX)
- 15.06.08 TST2 S0305049 3 (YX34XX)
- 15.06.08 TST2 S0305049 4 (YXXYXX)
- 15.07.16 TST2 d t

WTO 5 never displayed. The second XX in WTO 1 and 2 did not substitute as '12'. The second XX in WTO 3 and 4 did not substitute as 'YX'. The generated XX in WTO 4 did not substitute as 'YX'.

__________________
zboxassist
0
automan

Avatar / Picture

Moderator
Registered:
Posts: 136
Reply with quote  #2 
It takes a bit of creativity to get this to happen. This is a different problem to the repetitive expansion out of bounds that some people were experiencing. The solution to this is less simple, but a test on some assigns to check the value being assigned to a variable against its name are planned.

If you take this situation

VAR A LEN 8
VAR B LEN 8
LET A = 'A'
LET B = 'A'

A will be null, because the current value of variable A is assigned to variable A. You cannot thus initialize a variable to its own name. So A would be null until something else was assigned to it, and when A is used in text replacement it would also be null. It requires the use of SUBSTR to get the characters of the name of a variable into another one. The solution is to check when a SUBSTR is performed to see if the text to be moved is the name of the recipient variable. If they match then the substitution will not be performed. These problems can be avoided by use of special characters, that do not normally appear in text to be a part of the name. There will be no enforcing of variable name standards, because there are legitimate reasons that someone may wish to perform complex replacement. Any language allows you to write endless loops. You can write one in COBOL, REXX or in GAL command lists. They do nothing to help solve the user problem, and users are generally sensible in their choice of names and instructions. They are usually trying to solve a problem not create one. You can create a mess in any language if you set your mind to it, so the actual mechanisms will not be taken away.

On the surface this - 15.06.08 TST2 S0305049 1 (1234XX) looks like a real problem and I will send myself a message to look into it later.
0
zboxassist

Member
Registered:
Posts: 89
Reply with quote  #3 
I do not think that monitoring a variable's value is the best way to prevent infinite substitution loops. I think a better way is to limit the number of times you scan for substitution to some arbitrary large number, say 9999 (preferably user settable). I have not tested the following, but I expect it would loop forever.

Script X
VAR A
VAR B
RUN Y SYNCH
LET B = 'A'

Script Y
LET A = 'B'
LET B = 'A'

In script Y, global variables A and B are not enabled for substitution. Therefore, in this script, there is no risk of a loop. I should be allowed to assign any value including names of variables.

Of course, there are many other creative ways to induce substitution loops. I think a scan limit is the easiest way to prevent them.

__________________
zboxassist
0
zboxassist

Member
Registered:
Posts: 89
Reply with quote  #4 
I think the user needs someway to dynamically control GAL substitution scanning.
Other languages have the same need. TSO clist offers the &NRSTR function. SAS has a NRSTR function.

__________________
zboxassist
0
automan

Avatar / Picture

Moderator
Registered:
Posts: 136
Reply with quote  #5 
- 15.06.08 TST2 S0305049 1 (1234XX)

This is now fixed.

I will start experiments with various techniques for limiting replacement. There are too many ways to assign values, and a lot of time could potentially be used up in replacement scanning verification. I actually dislike artificial limits, but would prefer to invent a method that will prevent looping at all. Without giving it much thought, and off the top of my head, I would bet the method I come up with will be mathematical.
0
automan

Avatar / Picture

Moderator
Registered:
Posts: 136
Reply with quote  #6 
I modified the command list to include an additional WTO after the SUBSTR.

000100 VAR XX LEN 2 LOCAL
000200 VAR YY
000300 VAR ZZ
000400 LET XX='12'
000500 LET YY='34'
000600 LET ZZ='XXYYXX'
000700 WTO '1 (XXYYXX)'
000800 WTO '2 (ZZ)'
000900 LET XX='YX'
001000 WTO '3 (XXYYXX)'
001100 LET YY='XY'
001200 WTO '4 (XXYYXX)'
001300 LET XX=SUBSTR(ZZ,4,2)
001400 WTO '5 AFTER SUBSTR'
001410 WTO '6 (XXYYXX)'
001500 WTO '7 EXIT'
001600 *

This is the result now:
- 12.06.16 STC00907 AMAN008I Environment Initialization is complete
- 12.06.16 STC00907 AUT0080I Online and ready
00- 12.07.09 >RUN LOOP
- 12.07.09 STC00907 1 (123412)
- 12.07.09 STC00907 2 (123412)
- 12.07.09 STC00907 3 (YX34YX)
- 12.07.09 STC00907 4 (YXXXYX)
- 12.07.09 STC00907 5 AFTER SUBSTR
- 12.07.09 STC00907 6 (12XY12)
- 12.07.09 STC00907 7 EXIT

0
zboxassist

Member
Registered:
Posts: 89
Reply with quote  #7 
I agree that arbitrary limits are not aesthetically pleasing. The person who creates computationally feasible mathematical method to prevent infinite loops exists perhaps should be nominated for the Abel Prize. Until then, I think we are stuck with setting an arbitrary limit to terminate the loop.

One method to experiment with:
VAR variable SCAN n or perhaps SCAN=n or SCAN(n)
SCAN 0 would exclude this variable from string substitution
SCAN 1 would allow this variable to be replaced in a string during the 1st scan only
SCAN n would allow this variable to be replaced in a string through the nth scan
The default SCAN n should be some arbitrarily large value like SCAN 9999 or larger

SCAN 0 would be useful to allow you to define a single character variable but exclude it from string substitution. For example:
VAR J SCAN 0 LOCAL


__________________
zboxassist
0
automan

Avatar / Picture

Moderator
Registered:
Posts: 136
Reply with quote  #8 
The idea of counting loops in this situation feels like thud and blunder programming. For every problem there are many ways to program it and I really don't like the waste of cycles inherent in counting an arbitrary number of loops. There is always a more elegant way. I was not suggesting that I could come up with a solution for all loop situations, but I have found a simple elegant way to solve this particular one.

I have added a couple WTO's to your original code suggestion to create a loop situation:

Here is command program 1. I called it LP01 and it is run by >RUN LP01 at the console. It declares 2 variables A and B. It then calls LP02 to place values in them.
****** ***************************** Top of Data ******************************
000100 VAR A
000200 VAR B
000210 WTO 'CALLING LP02'
000300 RUN LP02 SYNCH
000310 WTO 'RETURN FROM LP02'
000400 LET B = 'A'
000410 WTO 'AFTER LET'
000500 WTO 'LP01 B = A'
000600 WTO 'LP01 A = B'
****** **************************** Bottom of Data ****************************

This is command list program 2. Called LP02 and invoked from LP01.

****** ***************************** Top of Data ******************************
000100 LET A = 'B'
000200 LET B = 'A'
000500 WTO 'LP02 B = A'
****** **************************** Bottom of Data ****************************

This is the log of the output. In LP01 I added a WTO 'CALLING LP02' before invoking it. You see the CALLING is displayed as CLLING because A is uninitialized. I inserted a WTO AFTER LET. The A in AFTER was changed to a B, which was scanned and changed back to A, at which point the scanner gives up and moves on. Likewise in the last WTO.

- 15.54.30 STC01235 AMAN031I No scheduling will be performed
- 15.54.30 STC01235 AMAN008I Environment Initialization is complete
- 15.54.30 STC01235 AUT0080I Online and ready
- 15.54.39 >RUN LP01
- 15.54.39 STC01235 CLLING LP02
- 15.54.39 STC01235 LP02 B = A
- 15.54.39 STC01235 RETURN FROM LP02
- 15.54.39 STC01235 AFTER LET
- 15.54.39 STC01235 LP01 B = A
- 15.54.39 STC01235 LP01 A = B

After I implemented it, it occurred to me that I had used a very similar method for CONFIGs that contained dependent CONFIGs in a loop and complex dependent date definitions for the AWS definitions.

This particular solution has been implemented in the experimental V3.3 that is underway, but I would have it back leveled it is anyone has a genuine need for the enhanced string handling. But so far no one has complained of it. This in combination with the string limiting function makes the text replacement continue to work the way I envisioned it, and is pretty much bulletproof.

One thing I have had on the back burner is the idea of being able to display processes in loops and have commands to halt them. I have always told myself that people are going to find their errors in testing and development, but people are going to make mistakes, and they are sometimes even malicious.
0
zboxassist

Member
Registered:
Posts: 89
Reply with quote  #9 
I've got to think about it more, because I expected 000410 WTO 'AFTER LET' to display as BFTER LET.

I do like the SCAN count because it seems to be iron clad method to terminate infinite substitution loops; and it also gives you a way to define a variable without enabling replacement. Of course, there are many other kinds of loops that could still run wild. I'm not certain that your method is iron clad, but appears to be quite close. That said, for years, I've wanted commands to display process information, to suspend/resume processes, and to terminate processes. I'm not sure what kind of process information might be available: process id, process state (running, waiting, wait reason, etc.), start date-time, elapsed time, cpu time/percentage, I/O time/count, memory usage, etc. My guess is most of that information is not tracked (to keep overhead low, etc.). Having commands to identify looping processes and terminate them greatly reduces the need to prevent loops.

__________________
zboxassist
0
automan

Avatar / Picture

Moderator
Registered:
Posts: 136
Reply with quote  #10 
I am quite confident that in this kind of loop my method is solid. I do not want to actually show it here, because I thought it up and if someone else wants it for their software, they will have to think it up for themselves. I could have let the first substitution set it to BFTER and am still thinking about it. I can see reasons to leave it as is and to change it. If I allow the change to BFTER it may give the user better confidence that something happened. But how likely is someone to get into this situation?

I am never going to be able to stop someone writing

:LOOP
WTO "Looping"
GOTO LOOP

But if they do, I think they should be able to query and halt tasks. This kind of code could be written in any code segment. It could be scheduled, a command list, a message response. There are two ways of going about halting code. One is to simply make it branch to the exit point, another is to stop an detach a task. You are right that a lot of information is not tracked because simple performance and low overhead were design goals. However tracking of certain specific items could be used to identify runaway tasks. I will think about this and see if I can come up with something elegant, simple and consistent.

There are so many potential out of control situations a person can write for themselves, and you cannot protect them from everything. I had to deal with a situation once where someone had a command list that was run in response to a console message and one of the sources of that message was that command list. In those situations a counter might be just what is required.
0
zboxassist

Member
Registered:
Posts: 89
Reply with quote  #11 
I agree, you cannot and probably should attempt to prevent an intentional loop. What is really needed, is to help the lay user identify the unintentional looping problem (usually identified by the user as a hang). To me, this means a message should be displayed that says a substitution loop was stopped that contains additional information to help the user understand where the loop was, and why it was looping, If that kind of message is displayed, then it probably does not matter whether the final result was ATFER LET or BFTER LET. Of course, your method to detect the loop, may not provide information that would be helpful to the lay user, so the best you might could do is have a message that simply says a substitution loop was stopped.
__________________
zboxassist
0
Zamin

Avatar / Picture

Member
Registered:
Posts: 67
Reply with quote  #12 
From a users point of view, we don't care how pleasing the code is to the person who wrote it. We only care about it working or not. If someone can unintentionally write code that creates a loop internally, it should be handled and corrected. In the case of a substitution loop it seems that it takes deliberate thought and effort to make it happen, so just halting it should be fine. If a user is not seeing the output they expect they usually go and read the code they have written, and if they were capable of writing code like the example zboxassist suggested, they would soon be able to see what they were doing and ask questions about the result. On the other hand it is easy to write code with intentional loops, that run out of control because of errors or unforeseen circumstance. So being able to identify and stop tasks is more important than messages about halting internal replacement. Here is another kind of loop that you can write in GAL.

VAR &I NUM
VAR &J NUM
VAR &K NUM

LET &J = 1
LET &K = 1000
FOR &I = &J TO &K
. . . .
. . . .
LET &K = &K + 1
END

In this the terminator value is incremented inside the code loop.
0
zboxassist

Member
Registered:
Posts: 89
Reply with quote  #13 
Actually, it is surprising easy for a novice user to write a substitution loop. Frequently, they do not understand the recursive replacement process. They tend to use short words as their variable names. When those words are embedded in other strings or messages, they get bit.
__________________
zboxassist
0
automan

Avatar / Picture

Moderator
Registered:
Posts: 136
Reply with quote  #14 
I have seen that by recent examples. If you can make it fail and you bring it to my attention, I can get such items fixed.
0
zboxassist

Member
Registered:
Posts: 89
Reply with quote  #15 
You fix all sizes of problems ... Remember all the problems I was having with my 10K+ line REXX, AMGEN, that generated raw GAL code to do SSID and CONFIG processing. AutoMan's SSID and CONFIG managers are so much better.
__________________
zboxassist
0
Previous Topic | Next Topic
Print
Reply

Quick Navigation:


Create your own forum with Website Toolbox!