RPG and Arrays
Array processing in RPG
Built-in function %SUBARR returns a section of the specified array starting at start-index. The number of elements returned is specified by the optional number-of-elements parameter. If not specified, the number-of-elements defaults to the remainder of the array. The first parameter of %SUBARR must be an array. That is, a standalone field, data structure, or subfield defined as an array. The first parameter must not be a table name or procedure call. The code below illustrates a three hundred element array of 138-byte entries. The first 31 bytes are going to be used to order the sequence of the array entries, after the data has been loaded.
Fig. 1 . . D DS INZ D trlArry 138a DIM(300) D traSRT 31a Overlay(trlArry) D lodArry 4s 0 DIM(300) D DS INZ D trlData 138a D trxEBD 8s 0 Overlay(trlData) D trxEBT 6s 0 Overlay(trlData:*next) D trxGRP 5s 0 Overlay(trlData:*next) D trxLDT 8s 0 Overlay(trlData:*next) D trxLDN 4s 0 Overlay(trlData:*next) D trxTRL 4a Overlay(trlData:*next) D trxKDL 18a Overlay(trlData:*next) D trxPRD 12a Overlay(trlData:*next) D trxLBD 8s 0 Overlay(trlData:*next) D trxLBT 6s 0 Overlay(trlData:*next) D trxLPD 8s 0 Overlay(trlData:*next) D trxLPT 6s 0 Overlay(trlData:*next) D trxVCD 8s 0 Overlay(trlData:*next) D trxVCT 6s 0 Overlay(trlData:*next) D trxEPD 8s 0 Overlay(trlData:*next) D trxEPT 6s 0 Overlay(trlData:*next) D trxSCD 8s 0 Overlay(trlData:*next) D trxSCT 6s 0 Overlay(trlData:*next) D trxIND 1a Overlay(trlData:*next) D trxSTS 2a Overlay(trlData:*next)
The code below represents the process--the data structures are cleared (resetting the elements of the array). And an SQL cursor is opened to loop through the data records to load the data structure fields.
Fig. 2 . . Exec SQL Open TrlCursor; TrlCsrOpn = *On; CLEAR trlcDS ; CLEAR trlData; CLEAR prvData; CLEAR CurSchedule; CLEAR prvSchedule; CLEAR previousSts; Dou SQLSTT = SQLstsEOF OR trls > 299; Exec SQL Fetch TrlCursor Into :SelectedTRL, :SelectedLOD; If SQLSTT = SQLstsOK; // load trailer data into the data structure // When the data fields have been populated // increment the count and move the contents // of the array to the data structure TRLS += 1; trlArry(trls) = trlData; EndIf; EndDO; // Once the array has been loaded, sort the array // and load the subfile using the array elements If trls > 0; SORTA %subarr(traSRT:1:trls); EndIf;
Once the data has been moved to the DS fields, the resulting 138-bytes are pushed to the array. Then the array is sorted, based on the first 31-bytes rather than the entire array element using %SUBARR in conjunction with the SORTA Op code. This will be used to load a subfile for presentation, in the sequence required by the user. How the data is retrived and the sequence in which it was retrieved may be completely different than how the data is displayed.
Array as a Stack
The routines here were developed to mimic a push down stack. Commands entered from a command line were pushed to the stack, then when requested retrieved from the stack. The array served as a repository to push down the command entries as they were entered, then pop the top entry from the stack when requested. The code is archaic but the concept is valid.
Fig. 3 . . * An array is used for the command stack. This array is * defined as 100 elements, each 150 bytes in length. D STK S 150 DIM(100) COMMAND STACK *--------------------------------------------------------------------- * BEGIN of work fields added by CONNECTIONS 2000's CVTILERPG utility *--------------------------------------------------------------------- D N S 3 0 D R S 3 0 *--------------------------------------------------------------------- * END of work fields added by CONNECTIONS 2000's CVTILERPG utility *--------------------------------------------------------------------- *================================================================ * @PUSH - ADD TO STACK * Move previously executed command to stack. Check the stack * index (SI) and if the entry is greater than the top of the * stack (100) restack the array, else increment the index and * add the command to the top of the stack. Set the Retreival * Index (RI) to equal the SI. *================================================================ C @PUSH BEGSR B001 C IF SI >= #TOP 001 C EXSR @RESTK 001 C MOVE COMAND STK(SI) X001 C ELSE 001 C EVAL SI = SI + #ONE 001 C MOVEL COMAND STK(SI) E001 C ENDIF C EVAL RI = SI C ENDSR . . . *================================================================ * @POP - GET STACK DATA * Retrieve the last command from the stack. Retreive the last * stack entry and move it to the command field using the * Retreival Index (RI). Decrement the RI by one. *================================================================ C @POP BEGSR B001 C IF RI > *ZERO 001 C MOVE STK(RI) Z$CMD 001 C EVAL RI = RI - #ONE E001 C ENDIF C ENDSR . . . *================================================================ * @RESTK - RESET STACK ARRARY * Move array elements by 1, to make room for addtional entry *================================================================ C @RESTK BEGSR C EVAL N = 2 C EVAL R = 1 B001 C DOW N <= #TOP 001 C MOVE STK(N) STK(R) 001 C EVAL R = R + #ONE 001 C EVAL N = N + #ONE E001 C ENDDO C ENDSR
Requests to retrieve the entries work from the top down. The first index is decremented until the desired stack entry is found.
Array by Index
Fig. 4 . . P DateText B export D DateText PI 30A D DateType 1 CONST D DateIn 8S 0 CONST options(*nopass) D DateAlpha S 8 D DateCode S 1 D DateString S 30 D DateValue S 8S 0 D Date6E S 8 D Date8E S 10 D DayName S 10 D InvalidDate S n D MonthName S 10 D ThisMonth S 2s 0 D WeekDay S 3s 0 D DS D DayTable 70A Inz('Monday + D Tuesday + D Wednesday + D Thursday + D Friday + D Saturday + D Sunday ') D Days 10A Dim(7) Overlay(DayTable) D DS D MonthTable 120 Inz('January + D February + D March + D April + D May + D June + D July + D August + D September + D October + D November + D December ') D Months 10A DIM(12) overlay(MonthTable) D /free InvalidDate = *off ; IF %parms < 2 ; DateAlpha = %char(%date():*iso0) ; ELSE ; DateValue = DateIn ; InvalidDate = CheckDate(DateValue:'*ISO') ; IF not InvalidDate ; DateAlpha = %editc(DateValue:'X') ; ENDIF ; ENDIF ; IF not InvalidDate ; ThisMonth = %dec(%subst(DateAlpha:5:2):2:0) ; WeekDay = DayofWeek(%date(DateAlpha:*iso0)) ; DayName = Days(WeekDay) ; MonthName = Months(ThisMonth) ; DateString = *blanks ; DateCode = UpperCase(DateType:%size(DateType)) ; SELECT ; WHEN DateCode = 'D' ; DateString = DayName ; WHEN DateCode = 'F' ; DateString = %trim(DayName) + ', ' + %trim(MonthName) + ' ' + %trim(%subst(DateAlpha:7:2)) + ', ' + %trim(%subst(DateAlpha:1:4)) ; WHEN DateCode = 'I' ; Date8E = %char(%date():*iso) ; DateString = %trim(DayName) + ', ' + Date8E ; WHEN DateCode = 'M' ; DateString = MonthName ; WHEN DateCode = 'T' ; Date6E = %char(%date():*mdy) ; DateString = %trim(DayName) + ', ' + Date6E ; OTHER ; DateString = 'Unrecognized format.' ; ENDSL ; ELSE ; DateString = 'Invalid date requested.' ; ENDIF ; RETURN DateString ; /end-free P DateText E