Published on System iNetwork (http://systeminetwork.com)
Club Tech iSeries Programming Tips Newsletter
By tzura
Created Jun 21 2001 - 04:00

THIS WEEK:
> Service Program to Convert Numbers to Words
> Freeware Utility to Scan Multiple Files for Multiple Strings
> V5R1 Brings Change: RPG IV %EOF BIF Behavior Change
> Follow-up: Authority Requirements for Producing an RPG IV Dump
> JDK Support on Release V5R1 of OS/400

Featured Tip:

SERVICE PROGRAM TO CONVERT NUMBERS TO WORDS
From time to time, I see requests for a routine to convert numbers to words, such as one that might be used in a program to print checks. Service program NbrToWords consists of a single procedure, CvtNbrToWords (Convert number to words), that does just that.

With service program NbrToWords, your applications needn't worry about the details of the conversion. Simply bind the service program to your application program, invoke procedure CvtNbrToWord passing a single numeric parameter, and receive the text in the return value. Note that the text is returned in lowercase, so after receiving the text, you must perform capitalization as necessary.

Procedure CvtNbrToWords supports numbers up to 15 digits (trillions) in length. The procedure accepts whole numbers only. For numbers containing decimal points (such as the values you print on checks), you invoke the procedure once for the whole number (e.g., dollars) and then again for the decimal portion (e.g., cents) of the number.

Service program NbrToWords follows:

 
      *  =============================================================
      *  =  Service program... NbrToWords                            =
      *  =  Description....... Service program to convert a number   =
      *  =                     to words                              =
      *  =                                                           =
      *  =  CrtRPGMod  Module( YourLib/NbrToWords )       +          =
      *  =             SrcFile( YourLib/YourSrcFile )                =
      *  =                                                           =
      *  =  CrtSrvPgm  SrvPgm( YourLib/NbrToWords )       +          =
      *  =             Export( *All )                     +          =
      *  =             ActGrp( *Caller )                             =
      *  =============================================================

     H NoMain

      *  -------------------------------------------------------------
      *  -  Procedure prototypes                                     -
      *  -------------------------------------------------------------

     D CvtNbrToWords   PR           200
     D                               15  0 Value

      *  -------------------------------------------------------------
      *  -  Global variables                                         -
      *  -------------------------------------------------------------

     D MaxGrps         C                   5

     D Words           S             13    Dim( 99 )
     D                                     CtData

     D Grps            S              8    Dim( MaxGrps )
     D                                     CtData

      *  =============================================================
      *  =  Procedure:   CvtNbrToWords                               =
      *  =  Description: Convert number to words                     =
      *  =============================================================

     P CvtNbrToWords   B                   Export

      *  -------------------------------------------------------------
      *  -  Procedure interface                                      -
      *  -------------------------------------------------------------

     D CvtNbrToWords   PI           200
     D  Nbr                          15  0 Value

      *  -------------------------------------------------------------
      *  -  Variable declarations                                    -
      *  -------------------------------------------------------------

     D AlphaNbr        S             15

     D WorkFld         DS
     D  Work3                         3
     D  Work2                         2    Overlay( Work3 : 2 )
     D  Work1                         1    Overlay( Work3 : 1 )

     D Count           S              5I 0
     D Pos             S              5I 0
     D Idx             S              5I 0

     D RtnWords        S            200    Inz( *Blank )

      *  -------------------------------------------------------------
      *  -  Convert number to words                                  -
      *  -------------------------------------------------------------

     C                   Select

     C                   When      Nbr = *Zero
     C                   Eval      RtnWords = 'zero'

     C                   Other
     C                   If        Nbr < *Zero
     C                   Eval      RtnWords = 'negative'
     C                   Eval      Nbr = Nbr * -1
     C                   EndIf

     C                   Move      Nbr           AlphaNbr

     C                   Do        MaxGrps       Count

     C                   Eval      Pos   = ( Count * 3 ) - 2

     C                   Eval      Work3 = %Subst( AlphaNbr :
     C                                             Pos      :
     C                                             3        )

     C                   If        Work3 <> '000'

     C                   If        Work1 <> '0'
     C                   Clear                   Idx
     C                   Move      Work1         Idx
     C                   Eval      RtnWords = %TrimR( RtnWords )     +
     C                                        ' '                    +
     C                                        %TrimR( Words( Idx ) ) +
     C                                        ' hundred'
     C                   EndIf

     C                   If        Work2 <> '00'
     C                   Clear                   Idx
     C                   Move      Work2         Idx
     C                   Eval      RtnWords = %TrimR( RtnWords )     +
     C                                        ' '                    +
     C                                        %TrimR( Words( Idx ) )
     C                   EndIf

     C                   Eval      RtnWords = %TrimR( RtnWords )    +
     C                                        ' '                   +
     C                                        %TrimR( Grps( Count ) )

     C                   EndIf

     C                   EndDo

     C                   EndSl

     C                   Eval      RtnWords = %Trim( RtnWords )

     C                   Return    RtnWords

     P CvtNbrToWords   E

** CtData Words
one
two
three
four
five
six
seven
eight
nine
ten
eleven
twelve
thirteen
fourteen
fifteen
sixteen
seventeen
eighteen
nineteen
twenty
twenty-one
twenty-two
twenty-three
twenty-four
twenty-five
twenty-six
twenty-seven
twenty-eight
twenty-nine
thirty
thirty-one
thirty-two
thirty-three
thirty-four
thirty-five
thirty-six
thirty-seven
thirty-eight
thirty-nine
forty
forty-one
forty-two
forty-three
forty-four
forty-five
forty-six
forty-seven
forty-eight
forty-nine
fifty
fifty-one
fifty-two
fifty-three
fifty-four
fifty-five
fifty-six
fifty-seven
fifty-eight
fifty-nine
sixty
sixty-one
sixty-two
sixty-three
sixty-four
sixty-five
sixty-six
sixty-seven
sixty-eight
sixty-nine
seventy
seventy-one
seventy-two
seventy-three
seventy-four
seventy-five
seventy-six
seventy-seven
seventy-eight
seventy-nine
eighty
eighty-one
eighty-two
eighty-three
eighty-four
eighty-five
eighty-six
eighty-seven
eighty-eight
eighty-nine
ninety
ninety-one
ninety-two
ninety-three
ninety-four
ninety-five
ninety-six
ninety-seven
ninety-eight
ninety-nine
** CtData Grps
trillion
billion
million
thousand

Here's a sample program, Example, that uses procedure CvtNbrToWords from service program NbrToWords:

      *  =============================================================
      *  =  Program....... Example                                   =
      *  =  Description... Convert numbers to words example          =
      *  =                                                           =
      *  =  CrtRPGMod  Module( YourLib/Example )          +          =
      *  =             SrcFile( YourLib/YourSrcFile )                =
      *  =                                                           =
      *  =  CrtPgm     Pgm( YourLib/Example )             +          =
      *  =             BndSrvPgm( YourLib/NbrToWords )               =
      *  =============================================================

      *  -------------------------------------------------------------
      *  -  Procedure prototypes                                     -
      *  -------------------------------------------------------------

     D CvtNbrToWords   PR           200
     D                               15  0 Value

      *  -------------------------------------------------------------
      *  -  Variable declarations                                    -
      *  -------------------------------------------------------------

     D MyNbr           S             10I 0
     D MyWords         S            200

      *  -------------------------------------------------------------
      *  -  Sample number-word-conversion                            -
      *  -------------------------------------------------------------

     C                   Eval      MyNbr   = 1234567898
     C                   Eval      MyWords = CvtNbrToWords( MyNbr )
     C                   Eval      *InLR   = *On

1. FREEWARE UTILITY TO SCAN MULTIPLE FILES FOR MULTIPLE STRINGS
If you find yourself with a need to scan multiple source files for a particular piece of information or for multiple pieces of information, Craig Rutledge has a freeware utility that might be of interest to you. Utility ScnMlt lets you specify up to nine files and 10 strings for which to search.

Another time saver is the ability to define groups of files to search. Once you define a group, you simply specify a group name in subsequent searches and ScnMlt searches the files you've assigned to the group. You can download ScnMlt at

http://www.alltel.net/~craigru/jcrcmd2.html#SCNMLT_tag [1].

2. V5R1 BRINGS CHANGE: RPG IV %EOF BIF BEHAVIOR CHANGE
Over the next few issues, I'll be pointing out important changes in V5R1 of which you should be aware. I'll begin by discussing a change in the way the %EOF BIF works in RPG IV.

Prior to V5R1, when a program uses %EOF(FileName) and an RPG IV program reads to the end-of-file, the SetLL, SetGT, and Chain operations do not reset the %EOF value. Even after one of these operations successfully repositions the file cursor, the %EOF BIF value is still '1', indicating an end-of-file condition.

With V5R1, this changes. Successful SetLL, SetGT, and Chain operations now reset the %EOF BIF value to '0' when %EOF(FileName) is used. The value will no longer indicate an end-of-file condition.

Note that this behavioral change occurs only when you specify the file name on the %EOF BIF. The SetLL, SetGT, and Chain operations do not affect the behavior of the %EOF BIF when used without the file name parameter.

3. FOLLOW-UP: AUTHORITY REQUIREMENTS FOR PRODUCING AN RPG IV DUMP
In the last issue of the Club Tech iSeries Programming Tips Newsletter, we showed you how to force an RPG IV dump. You should also be aware of the role that object authority plays in producing an RPG IV dump.

Unlike RPG III, which requires only *Use authority to successfully complete a Dump operation, RPG IV requires the user to have either *Change authority to the program or special authority *Service. If the user has less authority (e.g., *Use without *Service), the system produces only the indicator portion of the dump, failing with error message "Error occurred while retrieving variable data. Dump terminated." Obviously, the dump isn't very useful without the program variable listing.

One of our readers, Mike Pearson, wrote to tell us how this has an impact in his shop. In order to prevent users from changing anything about the programs, their security policy prohibits granting users *Change authority to programs. Instead, users have *Use authority to programs. Unfortunately, because their RPG error management routines have historically included the use of the RPG Dump operation, they have problems now that their applications are written in RPG IV. Dump operations now fail to complete and, without the program variable information, their dumps are worthless in diagnosing problems in an error situation.

I did some checking and found other shops that, in order to prevent users from manipulating programs, do not grant *Change authority to program objects and instead grant *Use authority. Though it certainly sounds like it would, *Change authority to a program object doesn't give users any authority to actually change or control that program object, however! Let me explain.

A comparison of the different levels of authority provided by *Change and *Use reveals that *Change authority adds additional data authorities (add, update, and delete rights), but no additional object authorities (both provide operational only). Data authorities define the operations users can perform on the contents of the object (e.g., records in a file). Program objects don't contain entries you can add, update, and delete, so these authorities are effectively meaningless with respect to program objects.

It is the object authorities (e.g., operational, management, existence, and alter) that define the operations (e.g., change attributes, rename, and delete the object) users can perform on the object itself. Since they provide the same level of object authorities (operational), both *Change and *Use authorities grant the same level of control over an object!

In other words, users will only be able to change or exercise control over a program object if you grant some additional object authorities (e.g., management, existence, alter). The bottom line is that you don't need to avoid *Change authority to prevent users from changing and controlling programs.

Now, the gotcha! There is a situation, potentially significant, in which you would want to specify *Use rather than *Change authority to a program object. To debug a program object, a user must have *Change authority to that object. In an environment in which users need to debug some, but not all, program objects, you would specify *Use authority to those program objects you wish to allow users to execute without the ability to debug. Of course, doing so means that the Dump operation in these objects no longer successfully completes. If, like Mike's shop, you've made the Dump operation part of your error management policy, this is critical.

Mike tells us that he has contacted IBM in an effort to convince those in charge that the RPG IV Dump operation should function as it did in RPG III (i.e., without the need additional authority). He also tells us that IBM's stance is that things are working as designed. He forwarded the following quote from information he says IBM Rochester sent him.

"OPM RPG and ILE RPG program use two different ways to gather dump information. OPM RPG programs use an internal RPG runtime routine. ILE RPG runtime use the system debug API's to gather this information. Since the API called by the ILE RPG runtime to dump an ILE program is owned by the system debugger, the API uses the same security checking as the system debugger, so the same rules apply: *CHANGE object authority or *USE object authority with *SERVICE special authority. This system debugger security requirement is documented in the AS/400 ILE Concepts manual, in the Chapter titled 'Debugging Considerations'."

I didn't find specific documentation in the ILE Concepts manual indicating the requirements for the RPG IV Dump operation (nor did I expect to find it). I did find documentation indicating the user must have *Change authority to a program object in order to add it to a debugging session. I suppose that with a lot of reading between the lines (and a telephone call to Rochester), one might come to the appropriate conclusion!

Mike reports that he is in the early phases of negotiation and that he plans to pursue this further with IBM in an effort to obtain a fix. Those who find this significant in their shop may also wish to contact IBM.

4. JDK SUPPORT ON RELEASE V5R1 OF OS/400
Q. Will JDK 1.3 run on release V5R1 of OS/400?

A. Yes. Release V5R1 supports 1.1.8, 1.2, and 1.3.

For more information, see the V5 InfoCenter at
http://publib.boulder.ibm.com/pubs/html/as400/v5r1/ic2924/info/rzaha/multjdk.htm [2].

The V5 Handbook information is at (search this page for "5722-JV1")
http://www-1.ibm.com/servers/eserver/iseries/handbook/v5r1/5486LPAD.htm#adprod [3].

© 2010 Penton Media, Inc.

Source URL: http://systeminetwork.com/node/60558

Links:
[1] http://www.alltel.net/~craigru/jcrcmd2.html#SCNMLT_tag
[2] http://publib.boulder.ibm.com/pubs/html/as400/v5r1/ic2924/info/rzaha/multjdk.htm
[3] http://www-1.ibm.com/servers/eserver/iseries/handbook/v5r1/5486LPAD.htm#adprod