Cut the Gordian Knot
April 4, 2012 Hey, Ted
I just love those BIFs that IBM added to RPG. I can’t understand why anybody would use old RPG op codes instead of the BIFs. But I’ve run into a brick wall with %SUBST. Help!
Allow me to explain Vince’s situation. He was assigned to revise a program someone else had written. The program reads a list of the file names in a certain directory on their network, and has to do other processing depending on file name extension (the part of the name following the last period).
Here’s a program similar to the one that Vince had to modify.
D FileName s 16a D Extension s 3a D Process s 3a /free *inlr = *on; Extension = %subst(FileName: %scan('.':FileName) + 1: 3); if Extension = 'XLS' or Extension = 'DWG'; Process = 'Yes'; else; Process = 'No'; endif; return;
The %SCAN function finds the location of the period in the file name and the %SUBST function extracts the three characters that follow it. The program was processing files with extensions of XLS, XLSX, and DWG.
Vince’s job was to add a new extension, SLDDRW, to the list of extensions to process. He revised his code like this:
D FileName s 16a D Extension s 6a D Process s 3a D /free *inlr = *on; Extension = %subst(FileName: %scan('.':FileName) + 1: 6); if Extension = 'XLS' or Extension = 'DWG' or Extension = 'XSLX' or Extension = 'SLDDRW'; Process = 'Yes'; else; Process = 'No'; endif; return;
The program worked fine during testing, but ended abnormally in production because the period within a long file name was four characters from the end of the FileName variable. Since the substring function extracts six characters, but only three characters followed the period, the program received message RNQ0100 (Length or start position is out of range for the string operation).
Vince was having trouble making a coherent IF statement that would take into account such things as the number of bytes after the period. ANDs and ORs are wonderful tools, but they can make for convoluted code.
I suggested he take another approach. Instead of trying to write a complicated logical expression full of %SUBST functions and logical operators that would produce the desired result, I suggested he write a function subprocedure to isolate the extension, which would be easy to test.
H dftactgrp(*no) actgrp(*caller) D FileName s 16a D Extension s 128a varying D Process s 3a D GetExtension pr 128a varying D inFileName 128a const /free *inlr = *on; Extension = GetExtension(FileName); if Extension = 'XLS' or Extension = 'DWG' or Extension = 'XSLX' or Extension = 'SLDDRW'; Process = 'Yes'; else; Process = 'No'; endif; return; /end-free * ========================================================= P GetExtension b D pi 128a varying D inFileName 128a const *** locals D DotLoc s 10i 0 D Dot c const('.') D EmptyString c const('') D Extension s 128a varying /free monitor; if inFileName = *blanks; return EmptyString; endif; DotLoc = %scan('.': InFileName); if DotLoc <= *zero; return EmptyString; endif; Extension = %trim(%subst(inFileName: DotLoc + 1)); dow '1'; DotLoc = %scan('.': Extension); if DotLoc <= *zero; return Extension; endif; Extension = %trim(%subst(Extension: DotLoc + 1)); enddo; on-error; return EmptyString; endmon; return Extension; /end-free P e
Vince reports that the program has worked correctly since.
I see a lot of code like this. Programmers commonly get so caught up in the mechanics of making the computer produce a desired result that they lose sight of the bigger picture. But that doesn’t mean you have to.