26
Thu, Dec
0 New Articles

Finally, Data Definitions in RPG Look "Modern"!

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

Are you still looking for reasons to move to free-format coding?

 

Editor's note: This excerpt is from chapter 10 of Evolve Your RPG Coding: Move from OPM to ILE ... and Beyond.

 

There's nothing worse for a programmer who has just come to RPG from a "modern" language than not being able to understand how data is defined in RPG. The fixed-format D-specs can be a real nightmare. (They were for me, when I started.) This is because you have to remember which letter corresponds to which data type, and the connection between the data type and its single-letter D-spec definition isn't always obvious. (You know what I mean …"Z" for timestamp?!) In the free-format version, programmers from both the "outside world" and "traditional RPG" find intuitive data-type definitions, as you'll see later in the examples.

 

While the syntax of control and file definition statements is similar to a "regular" free-format statement, some of the data definition statements require a structure that clearly marks the beginning and end of the definition. Let's pause for a moment to recall what types of data definitions exist in fixed-format RPG:

 

  • Standalone fields, defined by an "S" in position 24
  • Constants, defined by a "C" in the same position
  • Data structures, identified by the "DS" abbreviation in positions 24 and 25
  • Prototype and respective return values (if any), identified by "PR" in positions 24 and 25
  • The prototype interface, identified by "PI" in positions 24 and 25

 

These are very different types of data definitions, so it shouldn't come as a surprise that they require different coding. Let's start with the simplest: the standalone fields and the constants.

 

Make Your Variable Definitions Crystal Clear

Declaring a standalone field, more commonly known as a variable, in RPG is now remarkably similar to how this task is done in "modern" languages. For example, if I wanted to define a 10-character field named MyString, all I would have to type is this:

 

   DCL-S MyString CHAR(10);

 

Notice the syntax:

  • DCL-S indicates the type of definition, a standalone field.
  • The name of the variable can be (almost) as long as you want, because you're now free of the positional constraints.
  • The data type is CHAR(10), not "A," unambiguously stating the data type in the "modern language" way.

 

After the data type, you can specify any of the usual keywords, such as INZ and LIKE. By the way, LIKE's new syntax is also less cryptic! Here's an example:

 

   DCL-S W_Small_Amount Packed(11 : 2);

   DLC-S W_Large_Amount Like(W_Small_Amount : +2);

 

I mentioned that the variable names can be almost as long as you want. This is not new. In fixed format, you'd use an ellipsis ("…") when the space available for the variable name was not enough, remember? Well, in free format it's basically the same thing, but you need to keep in mind how the compiler determines where the name of the variable ends and its data-type keyword begins: there should be an empty space between them. This is particularly important when the variables have long names. For instance, back in chapter 4, I mentioned a procedure named Check_Item_In_Inv. Taking a cue from this, let's say I have a variable, defined in that procedure, named W_Is_Item_In_Inventory. Here are some correct and incorrect ways to define that variable in free format:

 

   Dcl-s W_Is_Item_In_Inventory... // This is incorrect syntax:

           Char(1);                 // This is assumed as part of the name

 

   Dcl-s W_Is_Item_In_Inventory Char(1); // This is correct syntax

 

   Dcl-s W_Is_Item_In_Inventory  

                                 Char(1); // Also correct syntax

   Dcl-s W_Is_Item_...

           In_Inventory Char(1);           // And this is also possible

 

In the first example, the compiler sees the ellipsis and assumes that the name of the variable continues in the next line, which means that CHAR(1) will be assumed to be part of the name. This will cause a syntax error because the data type is missing, and parentheses are not acceptable characters in a variable name. The other definitions are valid because the compiler can figure out where the variable name ends and where its data type keyword begins.

 

To help you figure out how to define fields, either as standalone fields or as part of data structures (discussed later), Table 10.1 lists the correspondence between the data type keywords used in free format and their fixed-format abbreviations.

 

Table 10.1: Free-Format Data-Type Keywords and Their Fixed-Format Counterparts

Data Type Name

Free-Format Keyword

Fixed-Format Abbreviation

Binary-Decimal

BINDEC(digits {: decimal-positions})

B

Character

CHAR(length)

A

Date

DATE{(format{separator})}

D

Float

FLOAT(bytes)

F

Graphic

GRAPH(length)

G

Indicator

IND

N

Integer

INT(digits)

I

Object

OBJECT{(*JAVA:class-name)}

O

Packed-Decimal

PACKED(digits {: decimal-positions})

P

Basing Pointer

POINTER{(*PROC)}

*

Procedure Pointer

POINTER{(*PROC)} PROCTPRT(name)

*

Time

TIME{(format{separator})}

T

Timestamp

TIMESTAMP

Z

UCS-2

UCS2(length)

C

Unsigned Integer

UNS(digits)

U

Variable-Length Character

VARCHAR(length {:2 | 4})

A

Variable-Length Graphic

VARGRAPH(length {:2 | 4})

G

Variable-Length UCS-2

VARUCS2(length {:2 | 4})

C

Zoned-Decimal

ZONED

S

 

At first glance, it would seem that there's a direct correspondence between the traditional single-letter abbreviations and the free-format keyword. In reality, however, there are some subtle differences:

  • DATE{(format{separator})}: Instead of defining a field as date and adding the DATFMT keyword, the date format is specified as the parameter to the DATE keyword. For instance, the following defines a date data type variable that uses the *YMD date format:

DCL-S W_MyDate Date(*YMD);

  • OBJECT{(*JAVA:class-name)}: Instead of defining a field as an object and adding the CLASS keyword, the class is specified as the parameter to the OBJECT keyword. For example, the following defines a Java class named MyClass in RPG, linked to the Java strClass class:

DCL-S MyClass OBJECT(*JAVA:strClass);.

  • POINTER{(*PROC)} PROCTPRT(name): Instead of defining a field as a pointer and adding the PROCPTR keyword, *PROC is specified as a parameter to the POINTER keyword. For instance, this line declares a pointer named Ptr, pointing to a procedure named MyProc:

DCL-S Ptr POINTER(*PROC) ProcPtr(MyProc);

  • TIME{(format{separator})}: Instead of defining a field as time and adding the TIMFMT keyword, the time format is specified as a parameter to the TIME keyword. This is similar to the DATE keyword. The following defines a time data type variable in *ISO format:

DCL-S W_MyTime Time(*ISO);

  • VARCHAR(length {:2 | 4}), VARGRAPH(length {:2 | 4}), and VARUCS2(length {:2 | 4}): Instead of defining a field as character, UCS-2, or graphic and adding the VARYING keyword, the field is defined using the VARCHAR, VARUCS2, or VARGRAPH keyword. The length {:2 | 4} part of the definition is related to the two- or four-byte prefix that stores the current length of the contents of the variable-length field. The size of the prefix is specified by the second parameter of VARCHAR, VARGRAPH, or VARUCS2. The parameter must be two or four. If you don't specify the prefix size, two is assumed if the specified length is between one and 65,535, or four if the length is greater than that. You can specify either prefix size for definitions whose lengths are between one and 65535, but for larger fields, only four is allowed.

 

In short, the new data-type definition keywords make the code less cryptic, therefore "friendlier" to new and old RPG programmers alike.

 

There's a New Way to Define Constants—and New Uses for Them

Constants are defined in a similar manner to standalone fields, with slight differences. Here's an example of the definition of a constant named C_MaxLines, set to a value of 100:

 

   DCL-C C_MaxLines CONST(100);

 

I simply replaced the DCL-S for DCL-C, removed the data-type definition (it's inferred by the compiler when the value of the constant is evaluated), and added the partially optional CONST keyword. It's "partially optional" because I need to specify the value, but I can do without the keyword itself.

 

This is another possible way of specifying the C_MaxLines constant:

 

   DCL-C C_MaxLines 100;

 

This is not new—you could do the same in fixed format. However, I suggest that you try to avoid it, because this "shortcut" doesn't improve readability—quite the contrary. What's new is the fact that you can use constants in other definitions. For instance, you can use constants to define the length of variables, as shown in the following example:

 

   DCL-C C_MaxLines CONST(100);

   DCL-S W_SomeText Char(127) Dim(C_MaxLines);

 

In this example, I'm declaring an array of 127-character strings with C_MaxLines (100) elements. Similarly, you can use named constants for file definitions:

 

   DCL-C C_Sales_Report_File 'SRPT';

   DCL-F Sales_Report Printer

                     OflInd(I_OverFlow)

                     ExtDesc(C_Sales_Report_File)

                     ExtFile(*ExtDesc);

 

Another novelty, which you might have noticed in the previous examples, is that you can now mix the specification types. I've shown two examples in which a data definition line (the declaration of the C_MaxLines and C_Sales_Report_File constants) appeared before other definitions. In the first example, this was already possible because variable or constant field definition belongs in D-specs. In the second example, I'm defining a file after defining a constant; in other words, I have a D-spec after an F-spec. This can be particularly useful whenever there's some sort of connection between files and externally described data structures, like this:

 

   DCL-F InvMst;

   DCL-DS InvMst_DS ExtName(InvMst : *Output);

 

As you can see from this example, a data structure declaration follows the same principles as standalone fields and constants: the data definition type that you use in positions 24-25 of the fixed-format line is used as a suffix to the "DCL-" string to form the operation code. This is a good way to remember which operation code to use when defining variables, constants, and data structures in full-fledged free format.

 

This example shows, arguably, the shortest possible definition of a data structure. I could swap the "ExtName…" for a "LikeDS…" and the definition would still be short, but this isn't always useful; sometimes, you want a tailor-made data structure. Let's see how to define a regular data structure, with the usual subfields that can potentially overlap each other.

 

Simplifying the Data Structure Definition

Defining a regular data structure requires a slightly more complex structure:

 

   DCL-DS W_MyDate_DS;

     W_Date Zoned(8:0);

     W_Year Zoned(4:0) Overlay(W_Date);

     W_Month Zoned(2:0) Overlay(W_Date : *Next);

     W_Day   Zoned(2:0) Overlay(W_Date : *Next);

   End-DS W_MyDate_DS;

 

Unlike the previous one-line declarations, this data structure is composed of multiple lines, like a regular data structure usually is. The logic here is that you define it like you'd write a subroutine. There's a DCL-DS line with the data structure name, which signals the beginning of the data structure declaration (equivalent to the subroutine's BegSR) and an END-DS line, which ends the declaration (the same as the EndSR line for a subroutine). In between, you define the data structure subfield names, respective data types, lengths, and how they "fit" in the data structure.

 

In case you're not familiar with the OVERLAY keyword, it overlays the storage of one subfield with another subfield of the data structure. Specifying OVERLAY(<name> : *NEXT) positions the subfield at the next available position within the overlaid field. In this particular case, the W_Month subfield definition overlays the fifth and sixth bytes of W_Date, because W_Year overlays the first four. In a free-format definition, the <name> parameter of the OVERLAY keyword cannot be the name of the data structure, as it could be in fixed format. To explicitly specify the starting position of a subfield within the data structure the "old-school" way, use the POS keyword instead.

 

Find out more in the book Evolve Your RPG Coding: Move from OPM to ILE ... and Beyond.

 

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: