Whats New and Exciting in RPG
Whats New and Exciting in RPG
Scott Klement
http://www.scottklement.com
This session is
organized by date…
i Next
IBM i 7.5
IBM i 7.4
IBM i 7.3
A chart at the end will
IBM i 7.2
detail the releases.
IBM i 7.1
2
IBM No Longer Waits For Next Release
• Prior to IBM i 7.1 ("V7R1") to get new RPG feature, you waited
for next release.
• Couldn't install it right away? Had to wait longer.
• Needed to support both newer and older releases? Wait longer.
• Could be 5+ years before you could use a feature you wanted.
4
Support in SEU
There is none.
SEU has not had updates since the release of IBM i 6.1
That was March 21 2008!
%PASSED
(Spring 2023) PTF for 7.5, 7.4
• %PASSED checks both if a given parameter was passed and wasn't *OMIT-ed.
• Previously would need to check %PARMS, %PARMNUM and %ADDR
dcl-pi *n; dcl-pi *n;
Old
New
// p1 is required, but *OMIT could be passed // p1 is required, but *OMIT could be passed
if %passed(p1); if %addr(p1) <> *null;
dsply ('Parameter p1 = ' + %char(p1)); dsply ('Parameter p1 = ' + %char(p1));
else; else;
dsply ('Parameter p1 is not available'); dsply ('Parameter p1 is not available');
endif; endif;
// p2 is optional // p2 is optional
if %passed(p2); if %parms >= %parmnum(p2);
dsply ('Parameter p2 = ' + p2); dsply ('Parameter p2 = ' + p2);
else; else;
dsply ('Parameter p2 is not available'); dsply ('Parameter p2 is not available');
endif; endif;
// p3 is optional, and *OMIT could be passed // p3 is optional, and *OMIT could be passed
if %passed(p3); if %parms >= %parmnum(p3) and %addr(p3) <> *null;
dsply ('Parameter p3 = ' + p3); dsply ('Parameter p3 = ' + p3);
else; else;
dsply ('Parameter p3 is not available'); dsply ('Parameter p3 is not available');
endif; endif;
6
%OMITTED
(Spring 2023) PTF for 7.5, 7.4
• %OMITTED checks if a given parameter was omitted (vs. not passed, etc.)
• Primarily useful to distinguish between no parameter passed vs. *OMIT passed.
• Equivalent to checking %parms() >= %parmnum(p2) and %addr(p2) = *null
dcl-pi *n;
p1 varchar(20) const options(*nopass : *omit);
end-pi;
SELECT/WHEN-IS/WHEN-IN
(Spring 2023) PTF for 7.5, 7.4
• The SELECT opcode now allows an expression to be provided after the opcode.
• WHEN-IN can be used to check if that expression is IN a list, range, array, etc.
• WHEN-IS can be used to check if it is equal to a value.
• Similar to the switch/case you see in some other languages.
dcl-pi *n;
customer packed(4: 0);
active ind;
end-pi;
<pcml version="8.0">
<program name="MYPGM" entrypoint="MYPGM">
<data name="customer" type="packed" length="4" precision="0" usage="inputoutput" />
<data name="active" type="char" length="1" boolean="true" usage="inputoutput" />
</program>
</pcml>
%SPLIT w/*ALLSEP
• %SPLIT was added in Spring 2021, but the *ALLSEP option is newer, Spring 2023!
10
RPGPPOPT w/Long Records
For example, suppose you compile from the IFS, and you have records that are long (maybe 200 characters
long – there is no limit in the IFS!)
This is because it preprocesses it into QTEMP/QSQLPRE – a source file, which has a limit of 100
characters per line.
11
OPTIONS(*CONVERT)
(Fall 2022) PTF for 7.5, 7.4
• OPTIONS(*CONVERT) on a prototyped parameter with CONST or VALUE will
automatically convert numbers, dates, times and timestamps to character. Pointers will be
treated like options(*string).
• Useful when a subprocedure may want data passed from different sources, and you don't
want to go to the extra level of implementing overloading.
WriteMsg(123);
WriteMsg(%date());
WriteMsg('Scott is cool!');
return;
dcl-proc WriteMsg;
dcl-pi *n;
msg varucs2(100) const options(*convert);
end-pi;
12
%CONCAT
(Fall 2022) in PTF for 7.5, 7.4
• %CONCAT will concatenate a list of items, joining them with a given separator.
• Alternately, you can specify *NONE if you do not wish to use a separator.
csv = %concat(',' : '1001' : 'Acme Inc' : 'Scott Klement' : '123 Main St');
// csv = '1001,Acme Inc,Scott Klement,123 Main St'
13
%CONCATARR
(Fall 2022) PTF for 7.5, 7.4
• Similar to %CONCAT, except %CONCATARR will concatenate the elements of an array.
data(1) = '1001';
data(2) = 'Acme Inc';
data(3) = 'Scott Klement';
data(4) = '123 Main St';
14
CHARCOUNT NATURAL
(Fall 2022) PTF for 7.5, 7.4
• When coding UTF-8 or UTF-16 data, the length of a character can vary. (UTF-8 characters
are 1-4 bytes long, UTF-16 are 2 or 4 bytes.)
• With CHARCOUNT(*NATURAL) BIFs like %SUBST, %SCAN, %XLATE and %SPLIT will
work with the number of characters (regardless of the byte size of each.)
• The old mode is called CHARCOUNT(*STDCHARSIZE) and the preceding BIFs will treat
the numbers as bytes (for CHAR) or double-bytes (for UCS-2) regardless of the length of
the individual character.
• Can specify ctl-opt (or h-spec) CHARCOUNT and CHARCOUNTTYPES
• Or /CHARCOUNT directive
• Or CHARCOUNT file keyword (dcl-f or f-spec)
• Or specify *NATURAL or *STDCHARSIZE on the BIF itself.
• The %CHARCOUNT BIF can be used to get the length in natural characters
string = 'ábcdë';
len = %len(string);
// len = 7 (á and ë are 2-byte characters)
len = %charcount(string);
// len = 5
15
CHARCOUNT NATURAL
dcl-s string varchar(20) ccsid(*utf8);
dcl-s string2 varchar(20);
string = 'ábcdë';
string = 'ábcdë';
/charcount stdcharsize
// these send *INFO messages that will appear in the job log
One common use of sending messages in RPG (aside from reporting errors and putting
information in the job log) is to load a "message subfile" (DDS MSGSFL)
**free A DSPSIZ(*DS3)
ctl-opt DFTACTGRP(*NO) ACTGRP(*NEW); A R MSGSFL
A SFL
dcl-f MSGSFL4D workstn; A SFLMSGRCD(15)
A MSGKEY SFLMSGKEY
dcl-ds sds PSDS; A PGMQ SFLPGMQ(10)
PgmQ *proc; A*
end-ds; A R MSGCTL
A SFLCTL(MSGSFL)
dcl-s num packed(4: 0); A SFLDSP
A SFLDSPCTL
snd-msg 'This is a test message' A SFLINZ
%target(PGMQ); A N99 SFLEND
A SFLSIZ(20)
write msgctl; A SFLPAG(5)
exfmt msgscn1; A PGMQ SFLPGMQ(10)
A R MSGSCN1
*inlr = *on; A OVERLAY
18
ON-EXCP
(Spring 2022) in 7.5, PTF for 7.4, 7.3
• ON-EXCP opcode works together with MONITOR to let you monitor for specific exception
messages (similar to MONMSG in CL)
dcl-pr QCMDEXC extpgm;
command char(32767) const;
length packed(15: 5) const;
igc char(3) const options(*nopass);
end-pr;
monitor;
QCMDEXC(cmd: %len(cmd));
on-excp 'CPF9801';
// file wasn't found
on-excp 'CPF9810';
// library wasn't found
endmon;
monitor;
QCMDEXC(cmd: %len(cmd));
on-excp 'CPF9801': 'CPF9810';
// Either the library or the file wasn't found
endmon; 19
dcl-pi *n varchar(30);
CustNo packed(7: 0) value;
end-pi;
end-proc;
monitor;
name = getCustomerName(custNo);
// got the name!
on-excp 'CPF9898';
// customer wasn't found
endmon;
20
%MAXARR / %MINARR
inv_amt(1) = 27700.95;
inv_amt(2) = 12345.67;
inv_amt(3) = -4;
lowest = %MINARR(inv_amt);
msg = 'Lowest total invoice: ' + %char(inv_amt(lowest));
highest = %MAXARR(inv_amt);
msg = 'Highest total invoice: ' + %char(inv_amt(highest));
21
22
DEBUG(*CONSTANTS)
(Fall 2021) in 7.5, PTF for 7.4, 7.3
• DEBUG(*CONSTANTS) is a CTL-OPT (or H-spec) keyword that lets you view
the values of constants while debugging.
23
myString = 'mIxEdcaSe';
myString = %lower(myString);
upperCase = %upper(myString);
titleCase = %lower(upperCase:2);
24
%SPLIT
(Spring 2021) in 7.5, PTF for 7.4, 7.3
• %SPLIT built-in function splits a string when a given substring is found.
• The result is an array of strings
array = %split(record:'|');
invoice.name = array(1);
invoice.amount = %dec(array(2):9:2);
In this example, two fields are stored in one string, separated by the pipe character.
%Split is used to split them into two array elements, which can then be assigned to
separate fields in a data structure.
25
FOR-EACH
(Fall 2020) in 7.5, PTF for 7.4, 7.3
• FOR-EACH loop opcode
Loops through all of the elements in an array. Can be used together with %SUBARR
26
FOR-EACH with %SPLIT
• Since %SPLIT returns an array, it can be used with a FOR-EACH loop
• In this example, "shelves" is a list of shelves separated by commas
• %SPLIT could be used in a similar manner to the way %LIST was used before.
endfor;
Split is very useful when reading IFS files in CSV, Tab or Pipe-Delimited format, or when a
database field or user input contains a delimited list of data.
27
%SPLIT w/*ALLSEP
(Spring 2023) PTF for 7.5, 7.4
• The %SPLIT built-in function now supports all separators via the *ALLSEP option.
• Without this option %SPLIT would ignore leading, trailing or consecutive separators.
Without *ALLSEP With *ALLSEP
dcl-s csv varchar(1000); dcl-s csv varchar(1000);
dcl-s fld varchar(20); dcl-s fld varchar(20);
if Qty IN %range(1:999);
msg = 'Quantity acceptable.';
endif;
Since %LIST returns a temporary array, it can also be used with the FOR-EACH
loop I discussed earlier.
30
Soooo Many Enhancements!
…and around 82 since SEU stopped being enhanced (yet, people still use it!)
89
Compile from Unicode Source (TGTCCSID compile keyword) ptf ptf ptf X
PCML 7.0 Support ptf ptf X
ALIGN(*FULL) ptf ptf X
%MIN and %MAX BIFs ptf ptf X
Support for Complex Qualified Names in %ELEM, %SIZE, DEALLOC and RESET ptf ptf X
%PROC BIF ptf ptf X
DATA-INTO opcode ptf ptf X
Nested Data Structures ptf ptf X
ON-EXIT section ptf ptf X
PSDS subfields for internal job id and system name ptf ptf X
SAMEPOS DS keyword ptf X
DIM(*CTDATA) X
Varying-dimension arrays X
93
During 7.5 Development Cycle
7.3 7.4 7.5
94
95
Get The Latest PTFs
7.3
You can install any of the features (if Compiler TGTRLS(*CURRENT) SI83429
available for your release of IBM i) by QOAR source files SI71517
installing these PTFs. Runtime SI83428
Debugger SI81625
There is no need to install separate
7.4
PTFs for each feature, these PTFs Compiler TGTRLS(*CURRENT) SI83497
(and their pre-requisites) include it all. Compiler TGTRLS(V7R3M0) SI83483
QOAR source files SI71518
Runtime SI83471
Debugger SI81626
7.5
Compiler TGTRLS(*CURRENT) SI83480
Compiler TGTRLS(V7R4M0) SI83496
Compiler TGTRLS(V7R3M0) SI83494
Runtime SI83468
96
This Presentation
Thank you!
97