Please forgive me if this post is showing up multiple times, I keep getting an error upon submission.
I have a Natural batch program I’m making changes to where I’m separating a field that is sometimes semicolon delimited, and then conditionally moving data from one array to another. It was abending with NAT1316, yet when I step through it using batch debug I can see the indexes are both at 1. Also, and here’s where it gets really weird, when I put in a display the program will execute just fine, I comment out the display and it abends again. (I put the rabbit hole comment in there as an experiment just to see if displaying the indexes was somehow, in some weird way doing something. Wasn’t.) And for a kicker, I created an online version of this logic to help me see what’s going on, and the online program works. : þ
Here’s my code, it’s abending on line 6230 with NAT1316 below but only without the display:
1 #GAID-IX (I2)
1 #MOVE-IX (I2)
1 #COUNT-GAID (I4)
1 #GAID-IN-ARRAY (A120/5)
1 #GAID-OUT-ARRAY (A120/5)
… the field being examined is part of a rather large input file but is defined as:
2 #GEO-ADDITIONAL-INPUT-DATA (A120)
6020 RESET INITIAL #COUNT-GAID #GAID-IN-ARRAY() #GAID-OUT-ARRAY()
6030 #GAID-IX #MOVE-IX
6040 EXAMINE #GEO-ADDITIONAL-INPUT-DATA FOR ‘;’
6050 GIVING NUMBER #COUNT-GAID
6060 IF #COUNT-GAID > 0
6070 SEPARATE #GEO-ADDITIONAL-INPUT-DATA INTO
6080 #GAID-IN-ARRAY(*)
6090 IGNORE WITH DELIMITERS ‘;’
6100 MOVE 1 TO #MOVE-IX
6110 FOR #GAID-IX 1 TO 5
6120 IF #MOVE-IX GE 5
6130 ESCAPE BOTTOM
6140 END-IF
6150 IF #GEO-HOUSE-NUM = *TRIM(#GAID-IN-ARRAY(#GAID-IX))
6160 ADD 1 TO #GAID-IX
6170 MOVE #GAID-IN-ARRAY(#GAID-IX) TO
6180 #GAID-OUT-ARRAY(#MOVE-IX)
6190 ADD 1 TO #MOVE-IX
6200 ELSE
6210 * DISPLAY ‘=’ #GAID-IX ‘=’ #MOVE-IX
6220 DISPLAY ‘WE WENT DOWN THE RABBIT HOLE’
6230 MOVE #GAID-IN-ARRAY(#GAID-IX) TO #GAID-OUT-ARRAY(#MOVE-IX)
6240 ADD 1 TO #MOVE-IX
6250 END-IF
6260 END-FOR
6270 ELSE
6280 MOVE #GEO-ADDITIONAL-INPUT-DATA TO #GAID-OUT-ARRAY(1)
6290 END-IF
The “online” version of the code that works is:
DEFINE DATA LOCAL
1 #IX (I2)
1 #MOVE-IX (I2)
1 #IN-ARRAY (A10/5)
1 #OUT-ARRAY (A10/5)
1 #CONTROL-NUM (A10)
1 #INPUT-DATA (A50) INIT <‘ONE; TWO; THREE’>
1 #COUNT (I4)
END-DEFINE
-
#IN-ARRAY(1) := ‘ONE’
-
#IN-ARRAY(2) := ‘TWO’
-
#IN-ARRAY(3) := ‘THREE’
-
#IN-ARRAY(4) := ‘FOUR’
-
#IN-ARRAY(5) := ‘FIVE’
#CONTROL-NUM := ‘TWO’
RESET INITIAL #IX #MOVE-IX #IN-ARRAY() #OUT-ARRAY() #COUNT
EXAMINE #INPUT-DATA FOR ‘;’ GIVING NUMBER #COUNT
IF #COUNT > 0
SEPARATE #INPUT-DATA INTO
#IN-ARRAY(*) IGNORE WITH DELIMITERS ‘;’
WRITE 'ARRAY BEFORE: ’ /
#IN-ARRAY(1) /
#IN-ARRAY(2) /
#IN-ARRAY(3) /
#IN-ARRAY(4) /
#IN-ARRAY(5)
MOVE 1 TO #MOVE-IX
FOR #IX 1 TO 5
IF #MOVE-IX GE 5
ESCAPE BOTTOM
END-IF
IF #CONTROL-NUM = *TRIM(#IN-ARRAY(#IX))
ADD 1 TO #IX
MOVE #IN-ARRAY(#IX) TO
#OUT-ARRAY(#MOVE-IX)
ADD 1 TO #MOVE-IX
ELSE
MOVE #IN-ARRAY(#IX) TO
#OUT-ARRAY(#MOVE-IX)
END-IF
IF #CONTROL-NUM = *TRIM(#IN-ARRAY(#IX))
ADD 1 TO #IX
MOVE #IN-ARRAY(#IX) TO
#OUT-ARRAY(#MOVE-IX)
ADD 1 TO #MOVE-IX
ELSE
MOVE #IN-ARRAY(#IX) TO
#OUT-ARRAY(#MOVE-IX)
ADD 1 TO #MOVE-IX
END-IF
END-FOR
WRITE 'ARRAY AFTER: ’ /
#OUT-ARRAY(1) /
#OUT-ARRAY(2) /
#OUT-ARRAY(3) /
#OUT-ARRAY(4) /
#OUT-ARRAY(5)
END-IF
END
not sure about the impact of the DISPLAY, but you have
FOR #IX = 1 TO 5
…
ADD 1 TO #IX
…
END-FOR
The FOR loop will increment your #IX variable. The impact of adding to it while inside the loop is undefined and a really bad practice.
in your code, you have:
6150 IF #GEO-HOUSE-NUM = *TRIM(#GAID-IN-ARRAY(#GAID-IX))
6160 ADD 1 TO #GAID-IX
6170 MOVE #GAID-IN-ARRAY(#GAID-IX) TO
6180 #GAID-OUT-ARRAY(#MOVE-IX)
If #GAID-IX is 1 when you execute line 6150, are you expecting to move the element after the matching element (2)? or the matched element (1)? If you really want the one after, what happens if #GAID-IX is 5 when you execute line 6150? #GAID-IN-ARRAY only has 5 occurrences, but by line 6170 the index is 6 and out of bounds.
At a minimum, 6160 should be something like #NEXT-IX := #GAID-IX + 1 so you can decide what to do if #NEXT-IX is greater than 5. Or check if #GAID-IX is 5 and decide what to do…
Thanks! I see what you mean. I removed everything inside there and just coded an “escape top” to get to the next instance of the #GAID-IN-ARRAY (yes, I want to process the entire array, not stop after I encounter something that matches #GEO-HOUSE-NUM):
6150 IF #GEO-HOUSE-NUM = *TRIM(#GAID-IN-ARRAY(#GAID-IX))
6160 ESCAPE TOP
6170 ELSE
It’s still abending with NAT1316, though, unless I leave a display in there.
Hi Rosie
It is hard to fully understand the logic in your prog on this late Friday afternoon
But I experimented a bit with your online prog, where I extended your input data to 6 entries, and then it also gets the out-of-index !
try:
1 #INPUT-DATA (A50) INIT <‘ONE; TWO; THREE; FOUR; FIVE; SIX’>
Then debugging might help you understand where the overrun is …
Finn
The input array won’t ever be more than five instances, it’s usually only one or two, on very rare occasions I’ve seen three. At the time of the abend, the indexes for #GAID-IX and #MOVE-IX are both at 1, so I do not see why I’d be getting an “Index not within array structure” error.
Also, I’m mystified as to why it would run with the display, and abend with the display commented out.
Do you have any error handling logic in your program? That might help track down the problem.
Adding an ON ERROR block allows you to capture data before the normal error handling takes over.
ON ERROR
WRITE '=' #GAID-IX
/ '=' #MOVE-IX
/ '=' #GEO-ADDITIONAL-INPUT-DATA
/ '=' #GAID-IN-ARRAY(*)
/ '=' #GAID-OUT-ARRAY(*)
END-ERROR
The other thing to be aware of is if your installation has the compiler optimizer turned on, the line numbers reported on errors can be off. I don’t think that is likely in this case, but something to be aware of when errors don’t make sense. You can compile the code without optimization by specifying the startup parameter OPT=OFF.
The Geo Addl Input Data field and two arrays are too long for a WRITE stmt, the indexes show:
#GAID-IX: 1
#MOVE-IX: 1
Using batch debug and peeking at the long fields, they show this:
#GEO-ADDITIONAL-INPUT-DATA (A120)
C/O AAADDD LINDEN; 0S072
#GAID-IN-ARRAY(1) A 120 C/O AAADDD LINDEN
#GAID-IN-ARRAY(2) A 120 0S072
#GAID-IN-ARRAY(3) A 120
#GAID-IN-ARRAY(4) A 120
#GAID-IN-ARRAY(5) A 120
#GAID-OUT-ARRAY(1) A 120
#GAID-OUT-ARRAY(2) A 120
#GAID-OUT-ARRAY(3) A 120
#GAID-OUT-ARRAY(4) A 120
#GAID-OUT-ARRAY(5) A 120
Does the attached code fairly represent the code you are having issues with? Is there test data you can add to the #TEST variable that reproduces your NAT1316 error?
NAT1316 issue.txt (4.74 KB)
The first INIT in your #TEST array is the data where my code abends, but ONLY in batch mode where I’m reading in an input file and executing the program using a Natural batch proc. If I run it in online mode the program executes just fine.
I’m not convinced it’s the data, or even my program, I think it’s an environmental thing since it works in online mode but not batch. But I’m posting in the forum in case there might be a difference in how to code between online and batch that I’m missing. It’s also possible there might be something up with the proc we use to execute our Natural batch programs.
I’ve emailed my Natural ADABAS DBAs about all of this, but only one is in the office this week so I expect he is fairly busy and hasn’t had a chance to review the issue yet.
I FIGURED IT OUT!!! Natural batch doesn’t like it when you do a trim on an array instance, dunno why, but I recoded the SEPARATE to do a LEFT JUSTIFIED (to take care of leading spaces), and then recoded the TRIM bit to just examine the array for #GEO-HOUSE-NUM giving an index, and if the index matches the #GAID-IX to escape top, otherwise move it to the out array. WORKS!!! doing my happy dance
what version of Natural are you using? When I tried my test program with batch in Natural v8.2.7.2, it ran without issue. If you are on a supported version of Natural, you could raise a support request (or have your DBAs do that) with the sample program that works online but gives NAT1316 in batch.
In any case, glad to hear you found a workaround.