Last Updated on 22 September 2019 by Roberto De Pedrini
This is a collection of FAQs and tips about IBM RPG Language collected from forums or IBM i related websites. We’ll try to update this post constantly with new questions, new answers, and new tips too. Feel free to use the comments area to add new tips or new questions… you are welcome!.
RPG-FAQ-001: RPG and recursive calls.
The problem of recursive calls of RPG programs has always been a developers’ Achilles heel until the arrival of the ILE and the abandonment of the primary RPG cycle.
Basically if I want the PGMA to call the PGMB and the PGMB to call the PGMA without going into recursion I have two possible ways:
- I complete the program with DFTACTGRP(-NO) ACTGRP(-NEW) , indicating it in the CTL-OPT specifications or as an option at compile time with CRTBNDRPG or CRTPGM …. in this case, a new Activation Group is created every time pgMA is called with suboptimal performance and wasted memory and resources.
- I create a program without primary RPG cycle (linear main program) … then with a procedure declared as MAIN … in this case, I’ll have to be careful to close files: without a real *INLR, the end of main procedure leaves open files and locks too:
example: opt-ctl Main(MyMainProc); dcl-pr MyMainProc ExtPgm('MYPGM'); dcl-proc Main; dcl-pi -N; ... Parameters if any end-pi ... Your code. end-proc;
Insights into this MCPress Online post “RPG Fundamentals: Work with linear main programs”
RPG-FAQ-002: RPG and Indicators … is it still relevant to use them?
Indicators in RPG no longer make sense … at least understood as indicators “IN55” or “IN(55), that is, in the numerical format of the same: they make the code cryptic for those who have not written it because they do not self-document … as a variable with its own name would do but of type “ind”.
The only thing that, in some way, keeps us tied to indicators are the attributes in DSPF Display Files or Printer Files PRTF … but even here there are tricks just to do without it.
I report below links to some interesting posts, even if old, that invite a smarter use of the indicators:
- IT Jungle – The New Basics: Indicators
- IT Jungle – An indicator by any other name
- QSYS400.com – Named indicator
- MC Press Online – Tech Tip: Eliminate Indicators in Dsiplay Program
RPG-FAQ-003: STEP (STEP) functions of STRDBG vs. Debug Rdi
When we Debug a program or service program with the DEBUG of Rational Rdi we have the following functions of STEP:
- F5 Step INTO
- F6 Step OVER
- F7 Step RETURN
Are they also available with the classic STRDBG?
Let’s start by saying that the difference between the STEP OVER and the STEP INTO is that the first one when it arrives on a program’s CALL or a Procedure’s call, executes the CALL or the Procedure and “stops” just after … the STEP INTO, as the word says, enters the called program or the called Procedure.
Step OVER and Step INTO also exist in STRDBG… Step Return no!
- F10 executes the STEP OVER … but we can also write the command STEP n-righe OVER …
- F22 executes the STEP INTO … but we can also write STEP n-lines INTO
- However, there is no equivalent to Rational Rdi’s STEP RETURN in the STRDBG environment.
- References :
- IT-Jungle Watch Your Data While Stepping Out With RDi Debug by Susan Gantner
- Debugging Programs, by Bhabani sankar Mohapatra
RPG-FAQ-004: STRDBG and SEP (Set Entry Point) as with Debug Rational Rdi?
With Rational Rdi it is very convenient to debug jobs in Batch … or web services called or jobs of other users by entering a Service Entry Point SEP. Is it possible to set an Entry Point with STRDBG as with the Rational Rdi Debug?
Yes, even if it’s not so simple… this IT-Jungle post “Debugging Server Jobs In Green Screen” by Susan Gantner explains it very well:
- STRDBG mypgm
- SBREAK line-number (or SBREAK line-number USER)
- SBMJOB or call to the program to be debugged
- Wait for the message “Service Entry Point…” to appear in the session where you entered the debug
- Press F1 to take the references to the JOB
- Open a second session and run a STRSRVJOB JOB(123456/FAQ400/MYPGM) indicating the references to the JOB above
- Run a STRDBG on the same program from this new session and you see the source stopped at the line indicated above
- Go back to the previous session and press ENTER to “free” the JOB
- Continue in the DEBUG with the other session!
RPG-FAQ-005: Where is my opened File in RPG
I’ve got the same name of one file in diferent libraries … there’s a way to determine the file/library opened by my F-Spec?
Try wiht INFDS, you can get Library and File name too.
Here’s an example.
DCL-F MYFILE PRINTER(132) INFDS(OPNFBK); DCL-DS OPNFBK; ODP_TYPE CHAR(2) POS(81); // ODP Type FILE_NAME CHAR(10) POS(83); // File name LIBRARY CHAR(10) POS(93); // Library name
RPG-FAQ-006: XML-INTO and RPG… howto?
You can find more information and some examples of RPG code and XML-INTO at Yusi4code Blog: “XML parsing in AS400 (IBM-i) using XML-INTO“
RPG-FAQ-007: Get IFS Object’s “creation date”
How can I get “creation date” for an IFS Object?
There’s an IFS API stat() to retrieve some object’s attributes … but if you need the “creation date” you have to take a look at Qp0lGetAttr()–Get Attributes API: see this example at Think400 website “CBX127 Change IFS attributes – CPP”
With stat() API you can get some other interesting attributes:
D stat PR 10I 0 ExtProc('stat')
D path * Value Options(*string)
D statDS DS Qualified Template
D st_mode 10U 0
D st_ino 10U 0
D st_nlink 5U 0
D st_reserved2 5U 0
D st_uid 10U 0
D st_gid 10U 0
D st_size 10I 0
D st_atime 10I 0
D st_mtime 10I 0
D st_ctime 10I 0
D st_dev 10U 0
D st_blksize 10U 0
D st_allocsize 10U 0
D st_objtype 11A
D st_reserved3 1A
D st_codepage 5U 0
D st_ccsid 5U 0
D st_rdev 10U 0
D st_nlink32 10U 0
D st_rdev64 20U 0
D st_dev64 20U 0
D st_reserved1 36A
D st_ino_gen_id 10U 0
D fileStats DS Likeds(statDS)
if stat('/path/to/file': fileStats) < 0;
// error handling
// ccsid now in fileStats.st_ccs
RPG-FAQ-008: Convert character Hex to Decimal
How can I convert a hex character string to the decimal value in RPG as in this online service ( https://www.binaryhexconverter.com/hex-to-decimal-converter ) ?
Try ctvch() API:
**free ctl-opt dftactgrp(*no); dcl-pr cvtch extproc('cvtch'); dest pointer value; src pointer value; len int(10) value; end-pr; dcl-s hexValue char (8) inz('00BC614E'); dcl-s binValue int (10); dcl-s len int(10); len = %len(hexValue); cvtch(%addr(binValue):%addr(he xValue):len); *inlr = *on;
Or with those API strol() and itoa(): you can choose radix… not only hex (16).
ctl-opt actgrp(*new) option(*srcstmt:*nodebugio); dcl-pr strtol int(10) extproc('strtol'); iString pointer value options(*string); oBuf pointer value; iRadix int(10) value; end-pr; dcl-s pdummy pointer; dcl-pr itoa extproc('__itoa'); iNum int(10) value; oBuf pointer value; iRadix int(10) value; end-pr; dcl-s buffer char(20); dcl-s value int(10); value = strtol( '00000000000000000000000000111101':%addr(pdummy): 2); dsply value; // Shows 61 itoa( value: %addr(buffer): 16); dsply buffer; // Shows 3d *inlr = *on;
REXX can do the same
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* XCALC EXP('REVERSE("String")') */ /* ______________________________ ______________________________ _ */ /* */ /* Yet another *FREEWARE* utility from Prime Suspect Software, */ /* creating slightly above average products for the */ /* enlightened masses since 1982. */ /* ______________________________ ______________________________ _ */ /* */ /* REXX Program Name... XCALC */ /* Programmer.......... Matt Sargent */ /* Internet Address.... M.SARGENT@GENIE.GEIS.COM */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ signal on syntax parse arg string parse value space(string) with "'"expression"'" interpret 'answer =' expression answer = strip(expression) '=' answer 'SNDPGMMSG MSG(&answer)' exit syntax: syntaxerr = errortext(rc) 'SNDPGMMSG MSG(&syntaxerr)' ================ CMD PROMPT('Expression Calculator') PARM KWD(EXP) TYPE(*CHAR) LEN(256) MIN(1) + CHOICE('Character value') + PROMPT('Mathmatical expression') ========= d2x() is the REXX function to convert Decimal to heXdecimal. The data conversions available in the AS400 implementation of REXX are: b2x() binary to hex x2b() hex to binary c2d() character to decimal (EBCDIC) d2c() decimal to character (EBCDIC) c2x() character to hex (EBCDIC) x2c() hex to character (EBCDIC) d2x() decimal to hex x2d() hex to decimal
If you need to extract numeric value from a packed string:( ITJungle “Extracting Zoned and Packed Decimal Values from Character Fields“)
D usrf01 ds D TypeCode 1 2s 0 D Category 3 4p 0 D Amount 5 8p 2 -- Get the amount checking is sign select dec( dec(substr(hex(substr(usrf01,5,4)),1,5)||'.'|| substr(hex(substr(usrf01,5,4)),6,2), 7,2) * (case when substr(hex(substr(usrf01,5,4)),8,1) = 'D' then -1 else 1 end), 7,2) as Price from usrfldpf
RPG-FAQ-009: Crypt e Decrypt in RPG (AES 128)
You can crypt and decrypt a string in RPG SQL Embedded using some SQL scalar functions.
SQL cipher and decipher functions are not only for Advanced Encryption Standard (AES) algorithm, but Triple DES (TDES) and RC2 too.
Let’s take a look to this simple SQL statement: we crypt and then decrypt a string in AES with a simple password
With mytext as ( select Encrypt_AES('This is my secret', 'Pa$$w0rd') as txtEncrypted from sysibm.sysdummy1) select Decrypt_char(txtEncrypted, 'Pa$$w0rd') from mytext;
In this example, we cipher a string in RPG with SQL Embedded … pay attention to the Encrypted variable length, the cipher algorithm generally give out a long string. Using a constant as a password string is not a good idea, store it in a table or in the ENCRYPTION PASSWORD special register.
DCL-S Text VarChar(20); DCL-S Encrypted VarChar(256); DCL-S Password VarChar(15) inz('yourPassWord') Text = 'Whatever Text' Exec SQL Set :Encrypted = Encrypt_AES(Text, PassWord);
If you don’t like SQL and you want to get hurt wit system’s API you can see at:
RPG-FAQ-010: API by example
If you need some examples and howtos about system’s API in RPG there is a great website by Carsten Flesburg: