RPG V - The Next Generation

Go down

RPG V - The Next Generation

Post  Archana K on Sun Jan 27, 2013 5:00 pm

A few years ago as IBM was working EGL and what is now called RDp, rumors started circulating about a new version of RPG. This new, fully free-format version would make it easier for IBM to add new features to the language while supporting 3rd-party add-ons improvements. This would mean you could install something like RPG xTools and the install routine would add-on RPG xTools' service programs so that they would be available implicitly to your code.

But the biggest change to an "RPG V" language is going totally free-format. RPG would finally become like C, C++, Java, JavaScript. PHP, Python, and other languages. Would that make it better? Probably not in and of itself, but with the columnar handcuffs off, RPG could certainly do whatever those smart IBM Canada folks can come up with.

To help things move along, I've composed a list of some of the changes to RPG along with a few improvements in the capabilities that I'd like to see in an "RPG V" implementation. There are in order of importance.

1. Comma as the Parameter Separator
How difficult is it to go from something like JavaScript or C, or C++ or EVERY OTHER LANGUAGE when coding something like this:

mysubproc( a, b, c);To RPG IV and have to code this:

mysubproc( a: b: c);The worse part is that the syntax checker doesn't catch the "error" when you use the commas. RPG requires colon separators because the old RPGII and RPGIII languages used the comma as a separator between an array name and an array index. To add a separator to those languages IBM had to select another character--they selected the colon.

Then when RPG IV was being designed, the dropped the comma notation for arrays and moved to a functional or parenthetical syntax:

arr,i became arr(i)But unfortunately they used the colon syntax as the parameter separator for functions and keywords. Since they dropped the array notation, the could have also dropped the colon notation in favor of a more traditional symbol--but you know how that story unfolds.

So my suggestion is when moving to an RPG V syntax, the number 1 priority should be to also migrate to comma-separator notation.

2. Free Format F and D Specifications
There is no reason to continue with fixed-format specs at any level. File Declaration Specifications and (data) Definition Specifications should be combined into a declarative operation/statement syntax. I've proposed this in the past, but basically it would be (dare I say it) as CL-like DCLF (for files) and DCL for everything else. Simple, flexible, expandable, and easy to remember.

DCLF sales mode(I) Dev(IFS) EXTFILE('/home/cozzi/sales.xml') TYPE(*XML);
DCL myArray Dim(25) Char(10);
DCL I Int;
DCL bigInt Int(8 );
DCL smallInt Int(2);
DCL amountDue Pkd(7,2) Inz(5.00);The idea is that the keyword is the declaration identifier (file, data item, perhaps others), and the first parameter is always the item being declared. Then, following the item name is zero or more keywords that further specify the item's attributes. Proper default values would need to be adopted as well. For example to declare the CUSTMAST file as an input file using all the default values, I would simply code the following:

DCLF CUSTMAST;The default would be a DB2 file opened for input (read-only). The file name would be the classic RPG style, where the CUSTMAST file on the library list would be opened; simple...

In addition the item defined by a DCLF would always be a file handle that could be passed as a parameter--eliminating the LIKEFILE syntax that so many people have difficulty comprehending.

Data Structures would easily migrate to free-format as well. We've seen how it can be done in CL--not perfect but good enough for CL, but for RPG V, I think we can do better.

DCL lineItem Struct Inz;
DCL item Char(5);
DCL desc varChar(50);
DCL price pkd(7,2);
DCL lineNo int;
DCL counter Int;
DCL myItem Like(lineItem) Inz;Unlike RPGIV, the LIKE keyword in RPG V would work for any type of data. We would not need LIKE, LIKEDS and LIKEFILE, just the LIKE keyword. They could also use REF or REFOBJ instead of LIKE and I'd be just as satisfied.

Note that the "END" keyword is used whenever an item is declared that is comprised of subitems. So in the case of Data Structures, Parameter Lists, or Object Classes, the END keyword would close off the group of related items. In the case where the LIKE keyword is used with a new data structure, the END keyword is not necessary but if you want to add additional items to a data structure or object class, then those declarations would require another keyword.

Certainly languages such as JavaScript, Java, C, and C++ that use the pair of curly brackets to denote begin/end have an advantage. But I think using this SQL-style naming convention for variable names, and extended it for data structures, classes (objects), and parameters (see below) makes it pretty viable.

3. Migrate P Specifications, I and O Specs to Free-format D Specifications
Since File and Definition specifications will be consolidated, why not also eliminate the other 3 types of fixed-format specs?

The Procedure definition specification would easily move to the DCLx model described in item 2, above.

DCL convert Proc EXPORT('Convert_Between_CCSIDs') ;
DCL rtnLength Int return value;
DCL inputValue Char(*) parm;
DCL inputLen Int parm const;
DCL outputValue Char(*) parm;
DCL outputLen Int parm const;
DCL rtnLength Int parm;
DCL fromCCSID Int Inz(819);
DCL toCCSID Int Inz(37);

DCL iconv prototype('iconv'); // Prototype for iconv API.
DCL rtnCode Int return value;
DCL hConv Like(iconv_T) parm by Value;
DCL input Ptr parm by ref;
DCL inLen UINT parm by ref;
DCL output Ptr parm by ref;
DCL outLen UINT parm by ref;Note that the parameter lists (for either the procedure implementation or the prototype) do not require an END keyword. This is because parameter list entries need to have the PARM keyword or in the case of the return value, the RETURN keyword "RETURN VALUE" is also allowed and means the same thing.

When defining a parameter, the default is to pass by reference. The "BY REF" keyword may be included to explicitly declare them as by reference, but it is the default. The "BY VALUE" keyword indicates that the parameter is passed by value (similar to the way C passes things). The OPTIONS keyword is also supported and looks like it does in RPG IV, although there are new keywords that replace the old OPTIONS-style keyword. Here's an example:

DCL atoll prototype('atoll')
DCL rtnValue Int(8 ) return value;
DCL inputText String(TRIM) parm Const;The C language runtime function of Character to Integer (ATOLL) which is technically named "ASCII to Long Long Integer" converts character text contain numbers into an integer. It is similar to using %INT except it doesn't blow up if the text is blank (it returns 0 instead of blowing up).

The prototype for it in the new RPG V would look like the above code. The return value is a 20I0 value, which is INT(8 ) in RPG V. The first and only parameter is a C-style null-terminated string. We also want to trim off any trailing blanks so the RPG IV equivalent of "OPTIONS(*TRIM:*STRING) is specified.

The STRING keyword means "pass this character parameter as a C-style null-terminated string". Under RPG IV, you'd have to declare the parameter as a pointer (*) and then pass the point "by value" and then include the OPTIONS(*STRING) keyword. Phew! That's a lot. With RPG V, the data-type "string" means do all of this automatically, the inclusion of the TRIM option causes trailing blanks in the original value to be removed and the CONST keyword means its read-only so don't expect any changes to be returned on this parameter. The compiler is smart enough o figure out what you mean.

The CONST keyword on the INPUTTEXT parameter means that the parameter is the C-style "const char* string" type. Without the CONST keyword, the parameter is passed as "char* string" that is a plain C-style null-terminated string.

Input and Output Specifications
Input and Output specifications would no longer exist. Everything would be declared in the Declaration specifications. Existing EXTERNALLY DESCRIBED Input or Output specifications could survive for compatibility and simplicity, but program-described data would only be permitted on DCL statements.

Declaring an input record using DCL statements would be similar to declaring a Data Structure using DCL statements. There is some area for improved performance that could be implemented but for compatibility, IBM may choose to make things work the way they do today.

Output, on the other hand, hasn't really seen an improvement since the expanded the SPACE/SKIP "columns" to 3 positions some 15 year ago. If Output is moved to DCL statement, how would it look? Today with the Web Browser, PDF, MS Excel, XML and CSV being the major output targets for RPG code, I don't often think about what Printed Output on plain paper would look like.

Perhaps a DCL statement with a few output-oriented keywords would be introduced, SPACEB, SPACEA, SKIPB, SKIPA, etc. Someone else who is more in-tune with legacy PRINT FILES would probably need to talk to this issue.

4. Streamlined Subprocedure Naming
Take a look as this:

123456789101112131415 EXPORT SYMBOL("RPGOPEN_convertCharacter") .....D cvtChar PR 10I 0 extProc('RPGOPEN_convertCharacter') D input 1A OPTIONS(*VARSIZE) D inLen 10I 0 Const D output 1A OPTIONS(*VARSIZE) D outLen 10I 0 Const D fromCCSID 10I 0 Const OPTIONS(*NOPASS) D toCCSID 10I 0 Const OPTIONS(*NOPASS) .....P cvtChar B EXPORT .....D cvtChar PI 10I 0 .....P cvtChar E
No fewer than SIX locations contain the Subprocedure name; this is just nuts! Granted the PI line and the ending P spec don't technically require the proc name, it is strongly suggested for documentation purposes to include them. But look as this!

First we have the Binder Language EXPORT keyword. This keyword is typically stored in the QSRVSRC source file in a member with the same name as the service program containing the subprocedure. Here we identify the name of the subprocedure as it was exported. This is different from the name on the P specs and Procedure Interface line. In fact, there is no necessary connection between it and the name used in the source code.

That connection occurs on the Prototype. The EXTPROC keyword identifies the name that the subprocedure that matches the Prototype Name in columns 7 to 21. The name on the EXTPROC keyword is the Exported Name. The name by which the subprocedure is known. Note that this name does not match anything in the subprocedure body itself. Then there are the 4 instances of the Internal Name.

The Internal Name appears in columns 7 to 20 of the beginning and ending P specifications and optionally on the Procedure Interface (PI) statement. Now, RPG is a case-insensitive language, and this design is really the only practical solution. But it can be streamlined. Look as the same thing in RPG V:

DCL cvtChar Proc EXPORT('RPGOPEN_convertCharacter');
DCL rtnLength Int return value;
DCL inputValue Char(*) parm;
DCL inputLen Int parm const;
DCL outputValue Char(*) parm;
DCL outputLen Int parm const;
DCL rtnLength Int parm;
// body of subprocedure goes here.
endproc;No binder source needed, no prototype needed. The ENDPROC keyword (or simply "END" if IBM doesn't want to use ENDPROC) terminates the body of the Subprocedure implementation. The external name is identified by the EXPORT keyword itself. Binder source would still be needed when a Signature is generated for a service program.

There are additional keywords for the DCL PROC statement that control access to the subprocedure :

•PUBLIC (the default when EXPORT is specified) - exports the subprocedure from the module and subsequently its *SRVPGM so other programs may call it.
•PRIVATE - exports the subprocedure from the module but NOT from its *SRVPGM.
•PROTECT(ED) - (the default when EXPORT is NOT specified) the subprocedure is private to the module in which it is implemented. It is not exported.
Either of the PUBLIC and PRIVATE keywords may be specified with or without the EXPORT keyword--the PROTECT keyword may not be specifeid with EXPORT. Here a examples of these options (just the Proc line itself):

DCL cvtChar1 Proc PROTECT; // Subproc is Protected -- it is not exported from this module.
DCL cvtChar2 Proc; // Subproc is Protected -- same as using the PROTECT keyword.
DCL cvtChar3 Proc PUBLIC; // Subprocedure is PUBLIC and is exported as 'CVTCHAR3'
DCL cvtChar4 Proc EXPORT; // Subprocedure is PUBLIC -- same results as specifying only PUBLIC.
DCL cvtChar5 Proc EXPORT('RPGOPEN_convertCharacter'); // Subproc is Public, exported as 'RPGOPEN_convertCharacter'
DCL cvtChar6 Proc EXPORT PRIVATE; // Exported from this module, callable from within its parent *PGM or *SRVPGM.
// It is not callable from outside of the *PGM or *SRVPGM object.Prototyping is still necessary for subprocedures with case-sensitive name but I suppose a streamlined prototyping scheme could also be implemented. For example, to allow RPG V to call the C runtime function named 'atoll' (which has an all lowercase name) you wouldn't need to code the parameters, only the "header" for the prototype, as follows:

DCL charToNum prototype('atoll') extern;This prototype is named CHARTONUM and when used, calls the C runtime function named 'atoll'. The name is identified on the PROTOTYPE keyword. The EXTERN keyword says that this is an external subprocedure, go look for it in the Binding Directory and don't make me code the parameters.

An alternative syntax I thought of that might work is to have an external identifier keyword instead of a prototype reference.

DCL charToNum extern('atoll') proc; There's probably a better syntax but I'm hopeful that the folks at IBM Canada will come up with something as simple as these choices.

5. New Class of Built-in Functions
There are three areas of built-in functions that need to be added to RPG V over RPG IV:

1.Character Conversion
2.System Utilities
3.Enhanced Scanning

Character Conversion Built-in Functions
The ability to convert from ASCII to EBCDIC, from upper to lowercase and between CCSIDs should be built into the language. I recently wrote an article describing how to do CCSID conversion in RPGIV and incorporated it into the RPG Open runtime *SRVPGM. Read that article for details and how to download the code.

So many bad routines have been written to do these now fundamental tasks that its IBM's turn to implement them. In an RPG V, they should certainly be core functions.

System Utility Built-in Functions
I don't know how many thousands of shops have used my JOBLOG subprocedure, but it has become so common-place that there are actually shops using it who think it is part of RPG IV. It is note, I wrote it. It is a wrapper for the Qp0lzprintf API. I first introduced it in RPG xTools about 8 years ago, and then ported it to RPG Open and also published articles about it that contain the code. RPG xTools also include tools to send program messages and run CL commands. These types of things should be built-in functions in RPG and I'd love to see them in RPG V.

Enhanced Scanning Built-in Functions
Last time I checked, it 2011, not 1977 as the %SCAN function seems to think. That was the era when UPPERCASE ONLY DATA ENTRY AND DISPLAY FILES WAS THE NORMAL THING TO SEE. Today people write in mixed case and sometimes all lowercase. RPG V needs to support case-insensitive scanning (heck, RPGIII should support that!) and while we're at it, why not add regular express support (also built into RPG xTOols) to the language.

Conclusions on RPG VThere are many new features that could be added to an "RPG V" language. I'm sure you have other priorities, but I tend to stay focused on those core features that are useful to the widest possible install base.

Thanks to Mid-Range News.

Archana K

Posts : 76
Join date : 2013-01-27
Age : 27
Location : chennai

View user profile

Back to top Go down

Back to top

- Similar topics

Permissions in this forum:
You cannot reply to topics in this forum