I am not sure how I missed this, two new compiler directives were added to RPG in IBM i 7.2, and I presume the equivalent 7.1 TRs: /SET and its opposite /RESTORE. I would have thought /RESET would have been a better choice than /RESTORE, but I am not IBM.
/SET will temporarily change, what I can only describe as, the definition of definitions. For example, if I want part of my program to use a different CCSID than the rest. Or perhaps I have a piece of code in a "copybook" (a source file member that is only ever /COPY-ed into another) that uses a different date and time format.
What can I change using the /SET:
- CCSID for alphanumeric definitions CCSID(*CHAR:ccsid)
- CCSID for graphic definitions CCSID(*GRAPH:ccsid)
- CCSID for UCS-2 definitions CCSID(*UCS2:ccsid)
- Date definitions DATFMT(date format)
- Time definitions TIMFMT(time format)
So let's dive into some code, these are the control options I will be using in my example programs:
01 **free 02 ctl-opt option(*srcstmt) datfmt(*iso) timfmt(*iso) ;
Line 1: I am programming this program in fully free format RPG, therefore, I need to start the source code with the **FREE. The code can now start in the first position as there are no columns. Fully free came as a PTF with IBM i 7.2 TR2 and 7.1 TR11, for more information see Trying fully free RPG
Line 2: I am defining for this program that the default date format will be ISO (YYYY-MM-DD), and the time format will also be ISO (HH.MM.SS) too.
Let's start with changing the CCSID of alphanumeric definitions:
03 dcl-s Test1 char(10) ccsid(*utf8) ; 04 /set ccsid(*char:*hex) 05 dcl-s Test2 char(10) ; 06 /restore ccsid(*char) 07 dcl-s Test3 char(10) ; 08 Test1 = 'abcdef' ; 09 Test2 = Test1 ; 10 Test3 = Test1 ; 11 dsply ('Test1 = ' + Test1) ; 12 dsply ('Test2 = ' + Test2) ; 13 dsply ('Test3 = ' + Test3) ;
Line 3: The stand alone variable Test1 is defined with the CCSID of *UTF8.
Line 4: Here I set the CCSID for character variables to hexadecimal. As this is fully free RPG the slash ( / ) is in the first position. If I had used an earlier form of RPG the slash would be in seventh column, and the RPG could start in the eighth position.
Line 5: I don't have to include a CCSID keyword in the definition of the stand alone variable Test2 as the CCSID has been set by the /SET.
Line 6: To restore the CCSID for character definitions I have to give the CCSID(*CHAR). The program will compile if I just have /RESTORE with nothing following, but the change by the /SET is not reset.
Line 7: Test3 has been defined after the /RESTORE to prove that the default definition has been restored.
Lines 8 - 10: Test1 has 'abcdef' moved to it, and Test2 and Test3 are in turn populated with the contents of Test1.
Lines 11 – 13: The contents of the three variables are shown using the DSPLY operation code. Which shows me:
DSPLY Test1 = abcdef DSPLY Test2 = /ÂÄÀÁÃ DSPLY Test3 = abcdef
This shows that Test2 contains the hexadecimal equivalent of Test1. As the /RESTORE came after Test2 and before Test3 the contents of Test3 are back to "normal", not hexadecimal.
I can also use the /SET to change the definition of date and time fields. I will use the same first two lines as I did in the previous example, the date and time format are both ISO. Now I can define my stand alone variables:
03 dcl-s Date1 date inz(d'2016-06-10') ; 04 dcl-s Time1 time inz(t'11.53.00') ; 05 /set datfmt(*mdy) timfmt(*usa) 06 dcl-s Date2 date ; 07 dcl-s Time2 time ; 08 /restore datfmt 09 dcl-s Date3 date ; 10 dcl-s Time3 time ; 11 /restore timfmt 12 dcl-s Time4 time ;
Line 3: Date1 is defined in ISO format as that is set in the control option, on line 2.
Line 4: Time1 is also defined in ISO format for the same reason.
Line 5: The /SET changes the definition of date variables to MDY and times USA.
Line 6: Date2 is defined as having the MDY format as it follow the set.
Line 7: Time2 is defined as having the USA format for the same reason.
Line 8: This /RESTORE only restores the date format. As the time format is not given it remains with the same definition give with the /SET on line 5.
Line 9: Date3 will have the default definition, ISO.
Line 10: Time3 will take its definition from the last /SET, line 5.
Line 11: This /RESTORE resets the time format to the program's default.
Line 12: Time4, as it follows the restore, will have the program's default definition, ISO.
The rest of the program just moves the date and time values to the various variables, and then their contents are displayed using the Display operation code:
13 Date2 = Date1 ; 14 Date3 = Date1 ; 15 Time2 = Time1 ; 16 Time3 = Time1 ; 17 Time4 = Time1 ; 18 dsply ('Date1 = ' + %char(Date1)) ; 19 dsply ('Time1 = ' + %char(Time1)) ; 20 dsply ('Date2 = ' + %char(Date2)) ; 21 dsply ('Time2 = ' + %char(Time2)) ; 22 dsply ('Date3 = ' + %char(Date3)) ; 23 dsply ('Time3 = ' + %char(Time3)) ; 24 dsply ('Time4 = ' + %char(Time4)) ;
I have to use the %CHAR built in function on each of the DSPLY lines to convert the value from a date or time to an alphanumeric value that can be included in the string to be displayed:
DSPLY Date1 = 2016-06-10 DSPLY Time1 = 11.53.00 DSPLY Date2 = 06/10/16 DSPLY Time2 = 11:53 AM DSPLY Date3 = 2016-06-10 DSPLY Time3 = 11:53 AM DSPLY Time4 = 11.53.00
Date1 and Time1 are the program's default, ISO. Date2 and Time2 show that the /SET has changed their definitions. Date3 is ISO as the /RESTORE reset the date format. But as it did not reset the time format, Time3 is still in USA format. Time4 occurs after the /RESTORE to reset the time format, therefore, it is in the program's default ISO.
When a /SET is used in a "copybook" a /RESTORE is assume at the end of the member. Here is a "copybook" I created for this example:
01 /set datfmt(*mdy) 02 D CopyDs DS qualified 03 D Date D
I have written this in fixed format to illustrate that the /SET does not care which kind of definition I use, and to illustrate that it is possible to insert fixed format code into a totally free RPG program. This "copybook" defines a data structure, CopyDs, on line 2, with one subfield a date, line 3. The /SET, line 1, defines that date fields will be in MDY format. There is no /RESTORE.
Now for the program, again I am using the same first two lines in the previous examples:
03 dcl-s Date1 date inz(d'2016-06-10') ; 04 /copy mylib/devsrc,copyrpg 05 dcl-s Date2 date ; 06 Date2 = Date1 ; 07 CopyDs.Date = Date1 ; 08 dsply ('Date1 = ' + %char(Date1)) ; 09 dsply ('CopyDs.Date = ' + %char(CopyDs.Date)) ; 10 dsply ('Date2 = ' + %char(Date2)) ;
This looks very similar to the previous example program I gave. Note that Date2 is defined after the /COPY, if the "copybook" does not have a default /RESTORE at its end then this date will be in MDY format.
When this program is run I see the following:
DSPLY Date1 = 2016-06-10 DSPLY CopyDs.Date = 06/10/16 DSPLY Date2 = 2016-06-10
Date2 displays a ISO, proving the assumed /RESTORE.
You can learn more about this from the IBM website:
This article was written for IBM i 7.2.