• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Write Your Own SCANRPL Built-In Function

    November 28, 2012 Bob Cozzi

    Note: The code accompanying this article is available for download here.

    Until IBM i v7.1 has made a pervasive appearance on virtually all IBM systems, the cool new v7.1 updates to RPG IV are out of reach for many RPG developers. Fortunately, with IBM i v7.1, IBM has finally stopped “point release” updates to the RPG compiler, giving us the ability to use anything implemented on (for example) technology refresh 5 all the way back to TR1. Life is good for RPG developers today.

    If you’re a software developer or, like me, consulting with clients that have everything from v5r4 through the latest and greatest release of IBM i, you can only envy those who have nothing more than v7.1 to burden their development cycle. One of those cool v7.1 enhancements is the %SCANRPL (Scan and Replace) built-in function. For years we’ve had the %SCAN and %REPLACE built-in functions, but the %REPLACE really never caught on. Sure a few people used it, but it really didn’t make sense to those writing end-user business applications or doing program maintenance. Using two built-in functions to accomplish what seems like one task? Fahgettaboudit.

    To that end, back some years ago, I wrote a FINDREPLACE (Find and Replace) subprocedure in RPG IV that basically did what IBM introduced in v7.1, and more. But while the FINDREPLACE subprocedure is cool, it included too many find/replace options that I mimicked from Microsoft Word Find/Replace dialogue box, things like “Match Case” and “Whole Word Only.”

    With RPG IV at v7.1, we now have a design for a subprocedure that could work on v5r4 and later and then easily be ported to %SCANRPL, when everyone is on v7.1 or later.

    The RPG IV %SCANRPL built-in function has five parameters:

    %SCANRPL( scan-pattern   :   replacement-text   : scanned-variable 
      [: start-position [ : length ]] );
    

    1. Scan-pattern is the text you are searching for.
    2. Replacement-text is the text to insert into the scanned text in place of the scan-pattern.
    3. Scanned-variable is the text to be searched. This is normally a fixed-length field, but can also be a varying field.
    4. Start-position [optional] is the first character in the scanned variable to be searched for the scan pattern. The default start position is 1.
    5. Length [optional] is the number of bytes in the scanned variable to be searched for the scan pattern beginning with the start position.

    To construct an operating system level, agnostic version of SCANRPL, we need to carefully define the parameter list of a subprocedure; a subprocedure named SCANRPL (no leading percent sign).

    To do this, a quick look at the %SCANRPL parameters indicates that the first three are character parameters and the final two are integers. It should be relatively simple to define a prototype with these basic characteristics:

    D scanRPL         PR         65533A   Varying
    D                                     extProc('COZZI_scanAndReplace')
    D pattern                      256A   Const Varying
    D replacement                  256A   Const Varying
    D searchData                 65533A   Const Varying
    D searchStart                   10I 0 Const OPTIONS(*NOPASS)
    D searchLen                     10I 0 Const OPTIONS(*NOPASS)
    

    Since the IBM version of %SCANRPL does not modify any of the input parameters, I’ve included the CONST keyword for all of the parameters of the subprocedure. CONST makes it easier to pass values to subprocedures by doing some minimal conversion for you. In addition, since the scan-pattern and replacement-text is typically not that long, I’ve shortened these parameters to 256 characters and made them VARYING. Increase their lengths if you need to, but I’ve found this size to be good enough. The benefit of VARYING and CONST is that I can use the %LEN RPG built-in function to extract the length of the data passed on these parameters. This greatly simplifies things.

    The third parameter, searchData is the text that is searched for the pattern parameter. It, too, is CONST VARYING, but has a maximum length of 64k-ish. On v7.1, this limit is removed, and parameters may be declared with lengths of up to 16 MB, so this is one difference with SCANRPL (the subprocedure) versus %SCANRPL (the built-in function).

    The starting position and length (parameters 4 and 5) are both defined as 4-byte integers. RPG uses the interesting “10i 0” nomenclature to define 4-byte integers, and “5i 0” to define 2-byte integers. Again here, the CONST keyword allows the caller of this subprocedure to pass in an expression or a numeric literal or a variable. If that value isn’t identical to the parameter definition, CONST converts the value into a 4-byte integer that the subprocedure understands. Last, I’ve included the OPTIONS(*NOPASS) keyword. This tells the compiler that the caller does not need to specify either of these parameters. Only parameters that do not include OPTIONS(*NOPASS) are required.

    The last part of the SCANRPL subprocedure is the returned value. This is defined on the first line of code in a prototype of a subprocedure. It defines the data being sent back to the caller on a conditional statement, such as IF, or on an assignment statement, such as EVAL. In the context of our SCANRPL subprocedure, the returned value needs to have properties identical to that of the third parameter (searchData in our prototype).

    Without seeing the body or implementation of this subprocedure, this is how it would look in your code versus the native RPG IV %SCANRPL built-in function:

    Native RPG %SCANRPL Built-in Function:

    myName = %scanRPL('Bob' : 'Robert' : myName );
    

    Custom SCANRPL Subprocedure:

    myName = scanRPL('Bob' : 'Robert' : myName );
    

    The only difference is the percent sign for the built-in function versus no percent sign for the subprocedure. We could even take it on step further:

    /IF DEFINED(*V7R1M0) 
        myName = %scanRPL('Bob' : 'Robert' : myName ); 
    /ELSE
        myName = scanRPL('Bob' : 'Robert' : myName );
    /ENDIF
    

    In this example, if the compiler is targeting v7.1 it uses the native RPG %SCANRPL built-in function, otherwise it uses our custom subprocedure. This way when the code is finally compiled for v7.1 it automatically uses the %SCANRPL built-in function. Pretty cool, huh?

    What’s that? Oh, you want to see the body/implementation of the SCANRPL subprocedure? Okay, here’s the full source code, but note: The /INCLUDE at the top of the source is simply including the prototype for the SCANRPL subprocedure (which is listed earlier in this article), that way you can include this in a service program and use it in all your apps without duplicating it all over the place.

     /include qcpysrc,scanRPL
    
    *********************************************************
    **  ScanRPL - mimic the v7r1  %SCANRPL built-in function
    **  myName = %scanRPL('Bob' : 'Robert' : myName );
    **  myName = scanRPL('Bob' : 'Robert' : myName );
    *********************************************************
    D buffer          DS                  Qualified Inz
    D  data                      65533A   VARYING
    
    *********************************************************
    **  ScanRPL - mimic the v7r1  %SCANRPL built-in function
    *********************************************************
    P scanRpl         B                   Export
    D scanRpl         PI         65533A   Varying
    D pattern                      256A   Const Varying
    D replacement                  256A   Const Varying
    D searchedData               65533A   Const Varying
    D searchStart                   10I 0 Const OPTIONS(*NOPASS)
    D searchLen                     10I 0 Const OPTIONS(*NOPASS)
    
    D nPos            S             10I 0
    D findLen         S             10I 0
    D rplen           S             10I 0
    D start           S             10I 0
    D findStart       S             10I 0 Inz(1)
     /free
          findLen = %Len(searchedData);  // Length of data to be searched
          if (%Parms()>= 4 and %addr(searchStart) <> *NULL);
             if (searchStart > 0);
                findStart = searchStart;
             endif;
          endif;
          if (%Parms()>= 5 and %addr(searchLen) <> *NULL);
             if (searchLen > 0); // Overriding search length?
                findLen = searchLen;
             endif;
          endif;
    
          if (findLen = 0 or findLen > %len(searchedData));
              findLen = %len(searchedData);
          endif;
    
          buffer.data = searchedData;
          rplen = %len(replacement);
          nPos = %scan( pattern : buffer.data : findStart);
          dow (nPos > 0 and nPos <= %len(buffer.data));
             buffer.data =
                  %Replace(replacement:buffer.Data:nPos: %len(pattern));
             if ((nPos + rpLen) < %Len(buffer.data));
                nPos = %scan( pattern : buffer.data : nPos + rpLen);
             else;
                nPos = 0;
             endif;
          enddo;
          return buffer.Data;
     /end-free 
    P scanRpl         E
    

    I enjoy writing subprocedures that help me write applications faster. I have noticed that many RPG developers seem to prefer to embrace their legacy habits more than learning new techniques. For example, one developer told me, “I can use SEU and copy/paste my code faster than writing a subprocedure.” Another said, “I can’t see the /COPYs in my code, so I prefer using copy/paste in SEU.” Yikes! But more and more I see a new attitude among RPG developers, one that embraces new technologies, albeit at a bit slower adoption rate than I would prefer.

    Bob Cozzi is developer of COZTOOLS, the popular collection of CL and RPG functions. You can reach him at www.cozTools.com or via email at bob@coztools.com.



                         Post this story to del.icio.us
                   Post this story to Digg
        Post this story to Slashdot

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    WorksRight Software

    Do you need area code information?
    Do you need ZIP Code information?
    Do you need ZIP+4 information?
    Do you need city name information?
    Do you need county information?
    Do you need a nearest dealer locator system?

    We can HELP! We have affordable AS/400 software and data to do all of the above. Whether you need a simple city name retrieval system or a sophisticated CASS postal coding system, we have it for you!

    The ZIP/CITY system is based on 5-digit ZIP Codes. You can retrieve city names, state names, county names, area codes, time zones, latitude, longitude, and more just by knowing the ZIP Code. We supply information on all the latest area code changes. A nearest dealer locator function is also included. ZIP/CITY includes software, data, monthly updates, and unlimited support. The cost is $495 per year.

    PER/ZIP4 is a sophisticated CASS certified postal coding system for assigning ZIP Codes, ZIP+4, carrier route, and delivery point codes. PER/ZIP4 also provides county names and FIPS codes. PER/ZIP4 can be used interactively, in batch, and with callable programs. PER/ZIP4 includes software, data, monthly updates, and unlimited support. The cost is $3,900 for the first year, and $1,950 for renewal.

    Just call us and we’ll arrange for 30 days FREE use of either ZIP/CITY or PER/ZIP4.

    WorksRight Software, Inc.
    Phone: 601-856-8337
    Fax: 601-856-9432
    Email: software@worksright.com
    Website: www.worksright.com

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Sponsored Links

    ASNA:  Create great mobile apps with ILE RPG. Period.
    looksoftware:  Achieving the impossible with RPG Open Access. Live webcast Dec 4 & 5.
    ITJ Bookstore:  Bookstore BLOWOUT!! Up to 50% off all titles! Everything must go! Shop NOW

    IT Jungle Store Top Book Picks

    Bookstore Blowout! Up to 50% off all titles!

    The iSeries Express Web Implementer's Guide: Save 50%, Sale Price $29.50
    The iSeries Pocket Database Guide: Save 50%, Sale Price $29.50
    Easy Steps to Internet Programming for the System i: Save 50%, Sale Price $24.97
    The iSeries Pocket WebFacing Primer: Save 50%, Sale Price $19.50
    Migrating to WebSphere Express for iSeries: Save 50%, Sale Price $24.50
    Getting Started with WebSphere Express for iSeries: Save 50%, Sale Price $24.50
    The All-Everything Operating System: Save 50%, Sale Price $17.50
    The Best Joomla! Tutorial Ever!: Save 50%, Sale Price $9.98

    Jinfonet Speeds In-Memory OLAP with ‘Push Down’ Technology Power Systems Cloud Builders Get Huge Discounts

    Leave a Reply Cancel reply

Volume 12, Number 28 -- November 28, 2012
THIS ISSUE SPONSORED BY:

WorksRight Software
ProData Computer Services
Sirius Computer Solutions

Table of Contents

  • Write Your Own SCANRPL Built-In Function
  • Glenn Wants To Know More Facts About Special Values
  • Admin Alert: Strategically Using Power Systems’ Processor Trial Capacity On Demand

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • Liam Allan Shares What’s Coming Next With Code For IBM i
  • From Stable To Scalable: Visual LANSA 16 Powers IBM i Growth – Launching July 8
  • VS Code Will Be The Heart Of The Modern IBM i Platform
  • The AS/400: A 37-Year-Old Dog That Loves To Learn New Tricks
  • IBM i PTF Guide, Volume 27, Number 25
  • Meet The Next Gen Of IBMers Helping To Build IBM i
  • Looks Like IBM Is Building A Linux-Like PASE For IBM i After All
  • Will Independent IBM i Clouds Survive PowerVS?
  • Now, IBM Is Jacking Up Hardware Maintenance Prices
  • IBM i PTF Guide, Volume 27, Number 24

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle