1.49k likes | 1.51k Views
Intermediate RPG Programming. Module 2. Agenda. This module consists of: Advanced Data Declarations More Operation Codes Subroutines & Modular Design Call with Prototype Subfiles Date and Time Manipulation Error Handling More BIFs. Advanced Data Declarations. Basic Data Types.
E N D
Intermediate RPG Programming Module 2
Agenda • This module consists of: • Advanced Data Declarations • More Operation Codes • Subroutines & Modular Design • Call with Prototype • Subfiles • Date and Time Manipulation • Error Handling • More BIFs
Basic Data Types • You have already seen
More Data Types • But there are also
More Data Types • Binary Fields are the predecessor of Integers • Same principle as integers but have a maximum limit on content • e.g. -9999 to 9999 • Use integers instead • Identified in a lot of API documentation • But you should still use integers • Floating Point is used for compatibility with other languages • e.g. passing parameters to a C function • Dates, Times, and Timestamps are discussed later in this module • Objects are discussed in Module 5 • Just a definition to enable interface to Java
Data Structures • A data structure is group of fields • Defined on D Specs • Define the data structure with a DS Definition Type (columns 24-25) • The DS name is optional • Define the subfields in the data structure • Definition Type columns of sub fields are blank D DataStuff DS D Name 30 D StrAddress 25 D City 15 D StateProv 10 D PostalCode 10
Re-defining Storage in a Data Structure • Bytes of storage may be redefined using different names and/or data types in a Data Structure • Use the OVERLAY keyword to identify sharing of the same storage • In this example • Day shares positions 1 to 2 of DATE • Month shares positions 3 to 4 of DATE • Year shares positions 5 to 8 of DATE • What are the values of Day, Month and Year? D DataStuff DS D Name 30 D Date 8S 0 D Day 2S 0 Overlay(Date:1) D Month 2S 0 Overlay(Date:3) D Year 4S 0 Overlay(Date:5) Date = 14051956;
More on OVERLAY • The OVERLAY keyword is flexible • Start position defaults to 1 • You can specify *NEXT instead of a start position • Can overlay the DS name as well as a sub-field name D DataStuff DS D Name 30 D Date 8S 0 D Day 2S 0 Overlay(Date) D Month 2S 0 Overlay(Date:*Next) D Year 4S 0 Overlay(Date:*Next) Date = 14052007;
Absolute Notation • The original means of defining data structures • Specify the From and To positions of each field • Length Notation offers advantages over Absolute Notation • Easier to decipher the definition of the subfields • Easier to decipher the layout of the data structure • Easier to change the layout of the data structure • Use of Absolute Notation is discouraged in new programs • You may see it in older style RPG programs D DataStuff DS D Name 1 30 D Date 31 38 0 D Day 31 32 0 D Month 33 34 0 D Year 35 38 0
Externally Described Data Structures - ExtName • Externally described data structures make use of externally described files • Compiler brings in the externally defined field definitions as data structure subfields • The file does not need to be defined on an F spec in the program • The EmployeeData DS contains 4 subfields • They are named: EmpID, Name, Birth and Joined • They have the same data type and size as described in the DDS for the Employee file D EmployeeData E DS ExtName(Employee) A A R EMPLOYEER A EMPID 5 0 A NAME 25 A BIRTH 8 0 A JOINED 8 0
Externally Described DS: LikeRec Keyword • Another way to define a DS using externally described file • The LIKEREC keyword defines a DS that has the same fields as the named record • This requires the file be declared on an F spec in the program • This option can be more flexible, especially for passing parameters between programs that consist of a record format • Field sequence matches the record buffer • This example produces the same subfields as the previous chart FEmployee UF E K Disk D EmployeeData DS LikeRec(EmployeeR)
Externally Described DS Details • You may not always want all fields from a file/record in the DS • You may only want input fields or output fields for a display file record • The record can be read directly into or written from the DS • Maybe you want only the key fields for a database file • This can be used as a Key Data Structure (KDS) • This provides a second way to use a multi-field key or partial key on a CHAIN or SETLL by using %KDS • Both EXTNAME and LIKEREC keywords take these optional keywords • *ALL, *INPUT, *OUTPUT, *KEY FMSTDSP CF E Workstn FPRODUCT F E Disk D SelectInput DS LikeRec( Select:*Input) D SelectOutput DS LikeRec( Select:*Output) D ProductKeys DS LikeRec(ProductRec:*Key) Read Select SelectInput; Write Select SelectOutPut; Chain %KDS(ProductKeys) ProductRec; SetLL %KDS(ProductKeys : 2 ) ProductRec
Qualified Data Names • The same field may not be defined in two data structures • Using the Qualified keyword on a DS • Means that all references to fields in that DS will be qualified • Qualification is through dot (.) notation (as in C and Java) • DSName.FieldName D Address DS Qualified D Street1 30 D Street2 30 D City 20 D State 2 D Zip 5 D ZipPlus 4 PrintCity = Address.City + ', ' + Address.State + ' ' + Address.Zip; If Address.ZipPlus <> *Blanks; PrintCity = PrintCity + '- ' + Address.ZipPlus; EndIf;
Create a Data Structure Like Another one • MailAddr and ShipAddr are LIKEDS(Address) • The subfield definitions from Address are copied to MailAddr & ShipAddr • MailAddr and ShipAddr are implicitly QUALIFIED • To include initialization (if any) use Inz(*LikeDS) D Address DS D Street1 30 D Street2 30 D City 20 D State 2 D Zip 5 D ZipPlus 4 D MailAddr DS LikeDS(Address) D ShipAddr DS LikeDS(Address) PrintCity = MailAddr.City + ', ' + MailAddr.State + ' ' + MailAddr.Zip; If MailAddr.ZipPlus <> *Blanks; PrintCity = PrintCity + '- ' + MailAddr.ZipPlus; EndIf;
Nested Data Structures • You can use LikeDS to define a DS in a DS! • A DS containing a nested DS must be Qualified • So multiple level qualification is needed for subfields of LikeDS structures D Address DS D Street1 30 D Street2 30 D City 20 D State 2 D Zip 5 D ZipPlus 4 D InvoiceInfo DS Qualified D MailAddr LikeDS(Address) D ShipAddr LikeDS(Address) PrintCity = InvoiceInfo.MailAddr.City + ', ' + InvoiceInfo.MailAddr.State + ' ' + InvoiceInfo.MailAddr.Zip; If InvoiceInfo.MailAddr.ZipPlus <> *Blanks; PrintCity = PrintCity + '- ' + InvoiceInfo.MailAddr.ZipPlus; EndIf;
Copying Data Between Data Structures • EVAL-CORR copies fields from one data structure to fields of the same name and compatible data definition in another data structure. • EVAL rules apply – data types must correspond • i.e. character to character, number to number • Source and destination fields may be different lengths • At least one of the data structures must be qualified • To ensure unique field names • H, M and R extenders may be specified • But they are only available in free format, there is not enough room for EVAL-CORR and an extender in the 10 character operation code in Extended Factor 2 • Compiler generates messages identifying which fields are and are not copied (and why)
EVAL-CORR Example • Note: • Balance and Name have different lengths • Area is not copied (same name but different data types) D Ds1 DS Qualified D Name 30A D Address1 30A D Balance 11P 2 D Area 5P 0 D Ds2 DS Qualified D Balance 13P 2 D Name 35A D City 30A D Area 5A Ds2.Balance = Ds1.Balance; Ds2.Name = Ds1.Name; Eval-Corr Ds2 = Ds1;
Initializing Data Structures • The contents of a data structure will be initialized to blanks if no INZ keyword is specified • A DS is treated as a character field • Bytes of any numeric sub-fields will be initialized to hex 40 • This would probably result in a decimal data error • Initialize DS sub-fields by specifying the Inz keyword for the DS • The sub-fields are initialized based on their individual data types • Sub-fields may be initialized individually • If other than the default initializations (e.g., blanks or zeroes) is needed D CompanyData DS Inz D CompanyName 30 D ExchangeRate 13P 5 D Other 8 Inz('CODED')
Special Data Structures • Special data structures may be defined in a program • An Indicator data structure associates a data structure with the indicators for a display or print file • The program status data structure provides information about the program • A File information data structures provides information about a file being used in the program
Associating the File with an Indicator DS • File keyword INDDS associates a data structure with a display file or printer file • The indicators defined in the display or print file (01-99) will be mapped by position to the named indicators in the INDDS • e.g., F3Exit is indicator 3 in the DDS so position 3 in the IndDS • They will NOT be mapped to the program indicators 01 to 99 FAll002D CF E WorkStn IndDs(WorkStnInd) D WorkStnInd DS D F3Exit N OverLay(WorkStnInd:3) D F5Refresh N OverLay(WorkStnInd:5) D ErrorField1 N OverLay(WorkStnInd:31) D ErrorField2 N OverLay(WorkStnInd:32) D SFLDsp N OverLay(WorkStnInd:51) D SFLDspCtl N OverLay(WorkStnInd:52) D SFLClr N OverLay(WorkStnInd:53) D SFLNxtChg N OverLay(WorkStnInd:54)
The INDARA Keyword • This is the DDS for a display file • Note the file-level INDARA keyword, which must be specified • This keyword dictates that the 99 indicators are placed in an indicator area that remains separate from the record buffer • A requirement if you want to use the INDDS keyword on an F spec A INDARA A CA03(03 'Exit') A CA05(05 'Refresh') * A R SUBREC SFL A 54 SFLNXTCHG A FIELD1 R B 5 5 A 31 DSPATR(RI PC) A FIELD2 R B 5 15 A 32 DSPATR(RI PC)
Program Status Data Structure • A program status data structure • It is identified by an SDS definition • There can only be one per program • Certain information may be identified by reserved values in place of from/to positions D ProgramStatus SDS Qualified D Status *Status D ProgramName *Proc D UserProfile 10 OverLay(WorkStnInd:254)
File Information Data Structures • An InfDS (Information DS) specified for each file • Must be unique for a file • A File Information DS is divided into • File Feedback (length is 80) • Open Feedback (length is 160) • Input/Output Feedback (length is 126) • Device Specific Feedback (length is variable) • Get Attributes Feedback (length is variable) FDisplay CF E WorkStn InfDS(DisplayInfDS) D DisplayInfDS DS Qualified D DisplayStatus *Status D LastFormat *Record D Row 3i 0 OverLay(DisplayInfDS:370) D Column 3i 0 OverLay(DisplayInfDS:371) D SFLRRN 5i 0 OverLay(DisplayInfDS:376) D SFLMinRRN 5i 0 OverLay(DisplayInfDS:378) D SFLNumRcds 5i 0 OverLay(DisplayInfDS:380)
What are Data Areas? • Not to be confused with Data Structures, a Data Area is an object on the system - object type *DTAARA • A Data Area is created using the CRTDTAARA CL command • A Data Area is deleted using the DLTDTAARA CL command • The contents of a data area may be viewed using the CL DSPDTAARA command • The contents of a data area may be changed using the CL CHGDTAARA command • Also by an RPG program, as we’ll see • Data Area may be used to: • Store basic information as opposed to using a file • As a means of storing "global values" • As a means of passing parameters for programs • A Data Area is a field that exists as an object
Basic Data Area Manipulation • Data Areas can be read into and written from RPG programs • Associate a data area with a field or DS using a DTAARA keyword • IN retrieves the contents of the data area to the associated field/DS • OUT writes the contents of the associated field/DS to the data area D ChequeNumber S 6 0 DtaAra(NEXTNUMBER) D CompanyName S 30 In *Lock ChequeNumber; ChequeNumber = ChequeNumber + 1; Out ChequeNumber;
Basic Data Area Manipulation • DTAARA keyword considerations • May be a literal for a full qualified object name • No value for DTAARA means the name of the field/DS is used • *VAR for 1st parameter means the value of the field or named constant in the second parameter is used for the data area name • You can refer to all defined data areas using *DTAARA • The UNLOCK operation can be used to unlock a data area • UNLOCK can also be used to unlock a record on a file D ChequeNumber S 6 0 DtaAra('MYLIB/MYAREA') D CompanyName S 30 DtaAra D ExchangeRate S 9 5 DtaAra(*Var:AreaName) D AreaName S 10 Inz('RATEINFO') In *Lock *DtaAra; Out *DtaAra; UnLock ChequeNumber; UnLock *DtaAra;
Data Areas and Data Structures • If a Data Area is used to store more then one field, you can use a data structure to re-define its contents • These are sometimes referred to as "Data Area Data Structures" D CompanyData DS DtaAra(COMPDATA) D CompanyName 30 D CompanyRef 10 In *Lock CompanyData; CompanyName = 'ComCon‘; CompanyRef = 'ABC007‘; Out CompanyData;
Accessing the Local Data Area (LDA) • Use the reserved name of *LDA to access the LDA • The LDA is unique to the job • A copy of the LDA is passed to any submitted jobs • Provides a means of passing data with a submitted job without the need to pass parameters D CompanyData DS DtaAra(*LDA) D CompanyName 30 D CompanyRef 10 In *Lock CompanyData; CompanyName = 'ComCon‘; CompanyRef = 'ABC007‘; Out CompanyData;
Arrays • An array is a group of data fields of identical size and type which are referenced using the same name • The array may be processed as a whole • Individual elements may be referenced using an index • Index is in parentheses after the array name • Index may be a numeric field or literal or expression • Index must be in the range 1 to the number of elements in the array • Arrays are defined on D Specifications • The DIM keyword identifies the definition as an array Arr Arr(1) Arr(2) Arr(3) Arr(4) D Arr S 5A Dim(4)
Defining Arrays • The 2 most commonly used types of array definitions are: • Run Time and Compile Time • They differ only in the way values are loaded to the array • Field data type and length definition applies to each element • DIM keyword identifies an array • Specify the number of elements in the array • Maximum number of elements is 32,767 • Keyword CTDATA identifies the array as a Compile Time array • In the absence of CTDATA, it is a Run Time array // Run Time Arrays D Values S 9 2 Dim(12) D Codes S Dim(500) Like(CusNo) // Compile Time Arrays D JulianDays S 3 0 Dim(12) CTData PerRcd(12) D MonthDays S 2 0 Dim(12) CTData PerRcd(12) D MonthNames S 9 Dim(12) CTData PerRcd(3)
Array Definition • Run time array example • The DIM keyword is required specifies the number of elements • Elements of the array are initialized to the data type default • May also use the INZ keyword to set the default • In this example • Values has twelve elements, each element is defined as packed (9 2) • Codes has 500 elements, each element is defined the same data type and size as the field CusNo • Optional keywords: ASCEND and DESCEND • Specifies whether the values in the array are in a specific order • Will not automatically sort the elements in this order, but if SORTA op code is used, this keyword determines sequence // Run Time Arrays D Values S 9 2 Dim(12) Ascend D Codes S Dim(500) Like(CusNo)
Array Definition • Compile time array example • Elements of the array are initialized to values stored at the end of the source member (more on the next page) • Identified by the CTDATA and (optionally) PERRCD keywords • PERRCD indicates the number of element values per line at the end of the source member • Optional ASCEND or DESCEND keyword may be used • As with Run Time, this does not ensure the appropriate sequence • It merely tells the compiler what the sequence is • Error condition will be caused if the data values are not in the appropriate sequence // Compile Time Arrays D JulianDays S 3 0 Dim(12) CTData PerRcd(12) D DeptNames S 15 Dim(3) CTData D MonthNames S 9 Dim(12) CTData PerRcd(3)
Compile Time Array Data • Compile time data is entered at the end of the source • i.e. after all logic code • Identify data using **CTDATA followed by the name of the array // Compile Time Arrays D JulianDays S 3 0 Dim(12) CTData PerRcd(12) D DeptNames S 15 Dim(3) CTData D MonthNames S 9 Dim(12) CTData PerRcd(3) **CTDATA JulianDays 000031059090120151181212243273304334 **CTDATA DeptNames Fabulous Dept 1 Name of Dept 2 Good Old Dept 3 **CTDATA MonthNames January February March April May June July August September October November December But there is a better way of doing this! (more later)
Using Data Structures for “Compile Time Data” • Instead of defining compile time arrays • and placing compile time data at the end of the program… D DaysPerMonth S 2 0 Dim(12) CTData PerRcd(12) ( Rest of Program ) **CTDATA DaysPerMonth 312831303130313130313031 • Define the data in a data structure • and overlay the array onto it… D MonthData DS D 12 Inz('312831303130') D 12 Inz('313130313031') D DaysPerMonth 2S 0 Dim(12) OverLay(MonthData)
Basic Array Operations • Operation may be repeated for all elements of an array • Use the array name without any index • Or use (*) for the index (preferred method) • Perform an operation on one element of an array • Use a numeric constant as an index or a numeric field or expression • Index must identify a valid element • Index starts at 1 (some other languages start with 0) • Run time error if index is invalid D Arr S 5i 0 Dim(5) D Inz(10) D i S 5i 0 Inz(3) Arr = 5; // All elements = 5 Arr(*) = 10; // all elements = 10 Arr(2) = 20; // 2nd element = 20 Arr(i) = 30; // 3rd element = 30
%ELEM and %XFOOT • %ELEM returns the number of elements in an array • Corresponds to the number defined on the DIM keyword • Should be used when processing all elements in an array • Should be used to ensure the highest index is not exceeded • %XFOOT totals the elements of a numeric array D Arr S 5i 0 Dim(5) D Total S 10i 0 // Using %ELEM For i = 1 to %Elem(Arr); Total = Total + Arr(i); EndFor; // Using %XFOOT Total = %XFoot(Arr);
%LOOKUP • %LOOKUP - look up an array element • %LOOKUP(arg : array {: startindex {: numelems}}) • Returns the index of the element that equals the look up argument • Returns 0 if not found • Data type of search argument and array must be the same • Numeric types may have different length/decimals • If ASCEND or DESCEND keyword is specified on the array • %LOOKUP does a binary search (much faster) • If data in the array is not sequenced as specified, incorrect results may occur • If sequence is not specified, it does a slower sequential search // Arr element values are 'AA' 'BB' 'CC' 'BB' 'AA' D Arr S 2 Dim(5) D i S 5i 0 i = %LookUp('CC' : Arr); // i = 3 i = %LookUp('AA' : Arr : 2); // i = 5 i = %LookUp('AA' : Arr : 2 : 3); // i = 0
%LOOKUPxx • There are other %LOOKUP BIFS that return an index • %LOOKUPLT for the value that is closest to but less than the search argument • %LOOKUPLE for an exact match, or the value that is closest to but less than the search argument • %LOOKUPGT for the value that is closest to but greater than the search argument • %LOOKUPGE for an exact match, or the value that is closest to but greater than the search argument • These 4 BIFS require an ASCEND or DESCEND keyword on the definition of the array • A binary search is used
%SUBARR • %SUBARR set/get portion of an array • %SUBARR(array:start-index{:number-of-elements}) • Start index and number of elements may be numeric fields or constants • The value must be within the number of elements in the array • May be used in any expression where an un-indexed array is allowed • Except %LOOKUPxx BIF and parameters passed by reference D ArrA S 5i 0 Dim(5) D ArrB S 5i 0 Dim(10) // set elements 2 to 5 = 10 %SubArr(ArrA : 2 : 4) = 10; // set elements 4 to 6 of ArrB = elements 2 to 4 of ArrA %Subarr(ArrB : 4 ) = %SubArr(ArrA : 2 : 3);
SORTA • SORTA sorts the elements in an array • Must specify the DESCEND keyword on the definition of the array if descending sequence is required • If no sequence specified on D spec, ascending sequence is used • If the array is not full, use %SUBARR to avoid sorting default values D AscendArrA S 5i 0 Dim(5) D AscendArrB S 5i 0 Dim(5) D DescendArr S 5i 0 Dim(5) Descend AscendArrA(1) = 10; AscendArrA(2) = 20; AscendArrB(*) = AscendArrA(*); DescendArr(*) = AscendArrA(*); // After this SortA stmt, elements will be 0, 0, 0, 10, 20 SortA AscendArrA; // After this SortA stmt, elements will be 10, 20, 0, 0, 0 SortA %Subarr(AscendArrB : 1: 2 ); // After this SortA stmt, elements will be 20, 10, 0, 0, 0 SortA DescendArr;
Data Structure Arrays • The DIM keyword can be specified at the DS level • Keyword QUALIFIED is also required • Note that it must be explicitly specified, unlike with LIKEDS • Subscripting works in the same way as for individual fields • Address(5) is the whole of the fifth element of the Address DS array • Address(5).City is the City field within that fifth element D Address DS DIM(20) QUALIFIED D Street1 30a D Street2 30a D City 20a D State 2a D Zip 5a D ZipPlus 4a If Address(5).City = 'Rochester'; Address(5).State = 'MN'; EndIf;
Multidimensional Arrays • If your DS contains an array ..... • You now have the effect of a multidimensional array • The names are subscripted just as you'd expect them to be • So - Address(5).Street(1) refers to the first element in the Street array within the fifth element of the Address DS array D Address DS Dim(20) Qualified D Street 30a Dim(2) D City 20a D State 2a D Zip 5a D ZipPlus 4a Address(5).Street(1) = *Blanks; : : : If Address(5).Street(2) = *Blanks; : : :
Another Example • The DS array SalesYear has ten elements • Each of which contains a 12 element array and a total field • Both sets of logic will sum up the elements in each SalesMonth array and place the total in the corresponding TotalYear field D SalesYear DS Dim(10) Qualified D SalesMonth 7p 2 Dim(12) D TotalYear 9p 2 Inz For i = 1 to %Elem(SalesByYear); SalesYear(i).TotalYear = %XFoot(SalesYear(i).SalesMonth); EndFor; For i = 1 to %Elem(SalesByYear); For j = 1 to %Elem(SalesByYear.Sales4Month); SalesYear(i).TotalYear = SalesYear(i).TotalYear + SalesYear(i).SalesMonth(j); EndFor; EndFor;
Entering the Fourth Dimension • You can create as many dimensions as you like but ... • An element of the top level DS still cannot exceed the 64K DS limit • In the example, changing Departments to DIM(11) breaks the limit • See the notes page for the size calculations • But increasing Divisions to (say) DIM(99) has no impact D Divisions DS Qualified Dim(5) D DivCode 2s 0 D Departments LikeDS(DeptData) Dim(10) D DeptData DS Based(p) Qualified D DeptCode 3s 0 D Products LikeDS(ProductData) Dim(99) D ProductData DS Based(p) Qualified D ProdCode 5s 0 D MonthsSales 9p 2 Dim(12) Divisions(1).Departments(1).Products(1).MonthsSales(1) = 0;
Assignment Operations • Assign an expression to a target • = The expression is assigned to the target • += The expression is added to the target • -= The expression is subtracted from the target • *= The target is multiplied by the expression • /= The target is divided by the expression • **= The target is assigned the target raised to the power of the expression • Note that the operator (+, -, etc.) goes before the = sign x = x + 1; x += 1; y = y * 10; y *= 10; z = z / (x + 2); z /= (x + 2);
If (a = 1); x = x + 1; ElseIf (a = 2); x = x + 2; ElseIf (a = 3); x = x + 3; EndIf; ELSEIF • ELSEIF is a combination of an ELSE and an IF If (a = 1); x = x + 1; Else; If (a = 2); x = x + 2; Else; If (a = 3); x = x + 3; EndIf; EndIf; EndIf;