26
Thu, Dec
0 New Articles

Convert Case Revisited and Updated

RPG
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

The need to convert lowercase to uppercase or vice versa has long been an issue in the RPG world. With the APIs available to RPG developers today, creating a subprocedure to convert between cases is simply a matter of writing a subprocedure to simplify things. In 2002, I published an article on converting between cases using the XLATE opcode. In the last issue, I illustrated a similar technique in "Getting Started with Procedures."

A problem with the technique featured in those articles is that the conversion works only with the North American character set, a.k.a. coded character set ID (CCSID). In this issue, I want to expose how to do case conversion that is not tied to any particular character set or national language.

To do this, we have to write our own subprocedure, create a table for each CCSID, and call either QDCXLATE or the QlgConvertCase API.

According to the IBM Information Center, the QlgConvertCase API provides case conversion for single-byte, mixed-byte, and UCS2 (Universal Multiple-Octet Coded Character Set with 16 bits per character) character sets. For the mixed-byte character set data, only the single-byte portion of the data is converted. QlgConvertCase does not convert DBCS data.

"QlgConvertCase" may not exactly be an easy name to remember, nor easy to guess. To use it, I want to create a wrapper procedure named CVTCASE. The CVTCASE subprocedure is actually one I've used in RPG xTools for a couple of years now to do conversion quickly and without concern for national language support. In fact, the CvtToUpper() and CvtToLower() subprocedures in RPG xTools Version 5.0 call CVTCASE under the covers.

In this article, I'll expose the source code behind the xTools CVTCASE subprocedure and explain how it calls QlgConvertCase. That way, you can use it on your system regardless of whether or not you've licensed RPG xTools.

First Things First

Of course, the first thing we need to do is create a prototype for the QlgConvertCase API itself so that we can call it from our CVTCASE subprocedure. That prototype follows:

      *********************************************************
      ** C O N V E R T  C A S E
      *********************************************************
     D QlgCvtCase      PR                  ExtProc('QlgConvertCase')
     D  ctrlBlock                          Const LikeDS(FRCB_T)
     D  inString                  65535A   Const Options(*VARSIZE)
     D  OutString                 65535A   Options(*VARSIZE)
     D  Length                       10I 0 Const
     D  APIError                           LikeDS(QUSEC)

Since the QlgConvertCase API is a procedure itself, calling it is faster than calling a typical program. While many APIs that are programs (as opposed to procedures) are also stored in the OS/400 or i5/OS System Entry Point Table (SEPT), making them very fast to call, calling a procedure is always supposed to be faster than calling a program.

One side effect of procedure-based OS/400 APIs is that they often have mixed-case names. In order to prototype this kind of API, the EXTPROC keyword is used, with the name of the API enclosed in quotes, like so:

ExtProc('QlgConvertCase')

Make sure these types of API names appear in the proper uppercase/lowercase combination (as documented in the InfoCenter); otherwise, the compiler will not locate them during the bind phase of the compile.

The first parameter of QlgConvertCase is a function control block. The control block is a data structure that tells the API what you want to do. IBM designs this type of parameter in lieu of adding several additional parameters. You use this data structure to control whether you want to convert between cases. The control block data structure can be declared as follows:

      **  Control Block for the call to QglConvertCase.
     D FRCB            DS                  
     D  ReqType                      10I 0 Inz(1)
     D  CCSID                        10I 0 Inz(0)
     D  CvtTo                        10I 0 Inz(0)
     D  Reserved                     10A   Inz(*ALLX'00')

Since RPG IV in Version 5 of OS/400 includes qualified data structures and the LIKEDS keyword, it would be best to create a template of sorts rather than just declare the data structure. So the actual definition of this data structure is that of a data structure template, as follows:

      **  Control Block for the call to QglConvertCase.
     D FRCB_T          DS                  QUALIFIED 
     D                                     BASED(TEMPL_PTR)
     D  ReqType                      10I 0 
     D  CCSID                        10I 0 
     D  CvtTo                        10I 0 
     D  Reserved                     10A   

By declaring this data structure as a template, we can now use the LIKEDS keyword to define the data structure we want to use in our application and the parameter itself. Remember, a data structure template is simply a term, not a defined part of the RPG IV language definition. It is, however, so widely used that IBM is designing data structure templates into the language in an upcoming release.

The procedure we are creating is called CVTCASE. It accepts two parameters: (1) The text to be converted and (2) an optional parameter that controls whether to convert cases. If you enter a value of 0 or if the parameter is not specified, CVTCASE converts the input text to uppercase. A value of 1 causes it to convert to lowercase.

The following is the prototype for the CVTCASE subprocedure:

     D CvtCase         PR         65535A   Varying
     D  InString                  65535A   Const Varying
     D  nOption                       5I 0 Const OPTIONS(*NOPASS)

The first parameter, INSTRING, is a VARYING parameter and is also CONST. This means that the compiler will allow you to specify variable-length or nonvariable-length (i.e., regular) character fields for this parameter. Up to 64 K of data can be converted, although it is unlikely that you'll need to convert such a lengthy value.

To use this subprocedure, include the prototype (above) in the Definition specifications of your applications.

The body or implementation of the CVTCASE procedure isn't very complex, but it does some interesting things. First, it checks the length of the input string to verify that it contains some data. If it doesn't, it simply returns. But it doesn't return "nothing"; it returns the same string that was passed in. This ensures that nothing is destroyed and the caller gets back exactly what was sent in.

Next, it initializes the FRCB data structure. While the INZ keyword is also specified for the FRCB, the EVAL statement is used to copy all hex zeros (X'00') to the data structure. This ensures that the reserved area of the data structure is also set to zeros. The RESERVED subfield must contain hex zeros, according to the API documentation. Otherwise, the API may not function correctly. This is one of the major problems programmers have when calling APIs: not initializing the data structures properly.

Now, it calls the QlgConvertCase to do the conversion. It passes the input variable INSTRING directly to the API. This may seem odd, considering the API requires a fixed-length character field and INSTRING is a varying-length character field. However, the power of prototyping causes the INSTRING value to be formatted according to the called procedure's parameter description. That is, the compiler converts the varying-length field into a fixed-length field. It does this because the INSTRING parameter of the QlgConvertCase API is defined as CONST. The CONST keyword does a lot for you, including converting a variable whose base data type matches the parameter into the format required by the parameter definition; it will convert any type of character value into the fixed-length required by INSTRING. If it's a numeric parameter, as is the case with the LENGTH parameter, the only requirement is that the length specified when calling QlgConvertCase is numeric. The compiler converts it into (in this case) a 10i0 value.

Finally, the input string, now converted by QlgConvertCase, is returned to the caller. The RETURN operation does this, using the %SUBST (substring) built-in function. We only want to return as much data as we received. Otherwise, the return process does additional work copying the extra bytes and slows things down.

     *********************************************************
     **  C V T C A S E  - Convert between lower/uppercase
     **      Parameters:
     **                  InString - (Input) Text to convert
     **                  nOption  - (Input) Control Option
     **                                     0 = To Upper
     **                                     1 = To Lower
     **      Return Value: Converted input text.
     **      (c) Copyright 2002 by Robert Cozzi, Jr.
     **          All rights reserved.
     **          Part of the RPG xTools. Used by Permission.
     **          www.rpgxtools.com
     *********************************************************
     P CvtCase         B                   Export
     D CvtCase         PI         65535A   Varying
     D  InString                  65535A   Const Varying
     D  nOption                       5I 0 Const OPTIONS(*NOPASS)

     D OutString                  65535A   
      **  Control Block for the call to QglConvertCase.
     D FRCB            DS                  LikeDS(FRCB_T) Inz
      **  API Error Data Structure, required, but ignored.
     D APIErrorDS      S             16A   INZ(*ALLX'00')

     C                   if        %Len(%Trim(InString)) <= 0
     C                   return    InString 
     C                   endif

      **  Clear the FRCB data structure
     C                   Eval      FRCB=*ALLX'00'
      **  Tell the API that we want case conversion 
     C                   Eval      FRCB.ReqType = 1

      **  QlgCvtCase uses 0 to convert to uppercase and 1 for lower,
      **  which is passed into this procedure on the nOption parm.
      **  The parm value is copied to the FRCB.CvtTo subfield.
     C                   if        %Parms >= 2
     C                   Eval      CvtTo = nOption
     C                   endif

     C                   CallP     QlgCvtCase(FRCB : InString : 
     C                                OutString : %Len(InString) :
     C                                APIErrorDS)

     C                   return    %Subst(OutString:1:%Len(InString))
     CvtCase         E

Calling CVTCASE from RPG IV

To call the CVTCASE procedure, you need to make sure you've included the prototype for the procedure in your source code. This is best done via a /COPY or /INCLUDE (both work the same). Storing prototypes in a separate source member and /COPYing them into your code is the only correct way to use them.

Next, specify the value you want to convert as the first parameter, and optionally specify 1 or 0 for the second parameter. This controls the conversion effort. If the second parameter is not specified, '0' (convert to uppercase) is used as the default.

Here's an example of how to use CVTCASE to convert to uppercase the data in a field named USRPRF.

     C                   eval      USRPRF = CvtCase(USRPRF : 0)

Also, the second parameter is optional, so if you avoid specifying 0 or 1 for it, the subprocedure defaults to 0 (convert to uppercase). The following is an example of calling CVTCASE to convert to uppercase without specifying the second parameter.

     C                   eval      CompName = CvtCase(CompName)

This is a basic technique that creates a true conversion tool that respects the CCSID of the system on which it is running. So, for example, if it is run with the Spanish or North American CCSID, everything is converted properly.

One Final Word

To compile this procedure or any of your own applications, you will need two things. I've already mentioned that the prototype for CVTCASE needs to be included, but so does the QUSEC IBM-supplied data structure. That data structure is included in the QSYSINC library. To include it in your code, specify the following compiler directive:

      /INCLUDE QSYSINC/QRPGLESRC,QUSEC

If you do not have QSYSINC installed on your system, install it. If you can't install it on a timely basis, you can use the following data structure in lieu of the QSYSINC source member.

     D QUSEC           DS                  QUALIFIED
     D  ErrDS_Len                    10I 0 Inz(%size(QUSEC))
     D  ErrReturn_Len                10I 0 Inz
     D  CPFMSGID                      7A
     D  ErrReserved                   1A   Inz(X'00')

Bob Cozzi is a programmer/consultant, writer/author, and software developer of the RPG xTools, a popular add-on subprocedure library for RPG IV. His book The Modern RPG Language has been the most widely used RPG programming book for nearly two decades. He, along with others, speaks at and runs the highly-popular RPG World conference for RPG programmers.

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: