Saturday, 22 August 2026

What Is a Library List in IBM i (AS400)?

If you've spent any time on an IBM i (AS/400) system, you've probably typed a command like WRKOBJ or called a program without specifying a library, and it just... worked. No QGPL/MYPGM, no full path — just MYPGM. That's the library list at work.

For anyone coming from a Windows or Unix background, this concept can feel unfamiliar at first. There's no single "current directory" the way you'd expect from a PC. Instead, IBM i uses a library list (*LIBL) — an ordered list of libraries that the system searches, in sequence, whenever you reference an object without qualifying it by library.

The Basic Idea

Every object on IBM i — a program, file, data area, whatever — lives inside a library. Libraries are themselves just a special type of object (*LIB) that hold other objects.

When you run a command or call a program without telling the system exactly which library to look in, IBM i doesn't guess randomly. It walks through your job's library list, library by library, in a fixed order, and uses the first matching object it finds.

You can see your current library list at any time with:

DSPLIBL

or interactively manage it with:

WRKLIBL

The Four Parts of a Library List

A job's library list isn't just one flat list — it's built from four distinct portions, always searched in this order:

  1. System portion — Libraries IBM i itself needs, most importantly QSYS, which holds core OS objects. This portion is controlled by the system value QSYSLIBL and can't be changed per-job.
  2. Product libraries — Reserved for licensed program products. Rarely touched manually.
  3. Current library — A single library tied to your job, typically set by your user profile or job description (CURLIB parameter). This is where the system looks for objects you create without specifying a library, and it's often the first place developers check.
  4. User portion — A list of up to 25 libraries that you or your job description define, searched in the order they were added. This is what most people mean when they casually say "my library list."

How Libraries Get Added

The user portion of the library list is usually built in one of these ways:

  • Job description (INLLIBL parameter) — sets the initial user library list when the job starts
  • ADDLIBLE — adds a library to your current job's library list
  • RMVLIBLE — removes one
  • CHGLIBL — replaces the entire user portion in one shot
  • EDTLIBL — lets you interactively edit it

These changes only affect the job you're running in — they don't touch anyone else's session or the system-wide defaults, unless you're changing a job description that other jobs are built from.

Answering the Real Question: If the Same Object Exists in Multiple Libraries, How Does IBM i Know Which One to Use?

This is the part that trips people up the most, and it's genuinely the whole point of the library list.

Say you have a file called CUSTMAST sitting in three different libraries: PRODLIB, TESTLIB, and MYLIB. If your program or command references CUSTMAST without qualifying it (i.e., you don't write PRODLIB/CUSTMAST), IBM i resolves it like this:

  1. It starts at the top of your library list — system libraries first, then product libraries, then your current library, then your user library list, in that exact order.
  2. It checks each library one at a time, asking "does this library contain an object named CUSTMAST of the type I'm looking for?"
  3. The very first match it finds wins. IBM i stops searching immediately — it does not check the remaining libraries, and it does not care whether a "better" or more recent copy of CUSTMAST exists further down the list.

So the answer, in short: IBM i doesn't pick the "right" copy — it picks the first copy it finds, based purely on the order of libraries in your library list. There's no timestamp comparison, no size comparison, no ownership logic. It's pure sequential search, top to bottom.

This has a very practical consequence: if TESTLIB happens to sit higher in your library list than PRODLIB, and both contain CUSTMAST, your program will silently pick up the test version — with zero warning that it did so. This is one of the most common (and most dangerous) sources of "it worked on my machine" bugs on IBM i. A developer tests against their own TESTLIB copy, everything looks fine, but in production the library list order is different and an entirely different object gets used.

Bypassing the Search Entirely

Of course, you can always sidestep the whole library list mechanism by fully qualifying the object:

PRODLIB/CUSTMAST

When you specify the library explicitly, IBM i doesn't search anything — it goes straight to that library. This is the safest approach for production programs, and it's why well-written IBM i applications tend to hard-code library qualification (or use library list conventions very deliberately) rather than relying on implicit resolution wherever correctness matters.

Why This Design Exists

It might seem odd at first, but the library list system is actually a clever piece of environment management. It lets the same program name, called the same way, resolve to different actual objects depending on context — without changing a single line of code:

  • A developer's library list might put DEVLIB first, so ADDLIBLE picks up their in-progress work.
  • A tester's library list might put TESTLIB first.
  • Production jobs are typically configured (via job description) to see only PRODLIB, with no dev or test libraries anywhere on the list.

This is essentially IBM i's built-in mechanism for environment switching — no separate deployment paths, no changing file references in code, just a different library list per job.

Quick Reference

Command Purpose
DSPLIBL Display your current library list
WRKLIBL Work with (interactively manage) your library list
ADDLIBLE Add a library to the user portion
RMVLIBLE Remove a library from the user portion
CHGLIBL Replace the entire user portion
EDTLIBL Interactively edit the user portion

The Takeaway

A library list is IBM i's answer to a question every multi-user, multi-environment system has to solve: when a name could mean several things, which one do you mean? IBM i's answer is refreshingly simple once you see it — a strict, ordered search, first match wins. Understanding that order (system, product, current library, user list) — and knowing that duplicate object names anywhere along that path are resolved by position, not by "correctness" — is one of the most important mental models you can build as an IBM i developer or operator.

Sunday, 2 August 2026

What Is a Subsystem in AS400 (IBM i)?

 If you've spent any time on an AS400 — or IBM i, as it's officially called today — you've probably run the command WRKSBS or WRKACTJOB and seen a bunch of names like QINTER, QBATCH, and QCTL sitting there. Those are subsystems. And if you're new to the platform, that word alone can be confusing, because "subsystem" doesn't map cleanly onto anything in Windows or Linux. So let's break down exactly what a subsystem is, why IBM designed things this way, and why it still matters today.

The simple definition

A subsystem is an operating environment within IBM i where jobs run. Think of it as a container — a dedicated space with its own memory pool, its own set of resources, and its own rules about what kind of work is allowed to run inside it.

Here's the important part: IBM i doesn't run all your jobs in one big shared space. Instead, it divides work into categories, and each category gets its own subsystem. Interactive jobs — the ones where a user is sitting at a 5250 screen typing commands — run in one subsystem. Batch jobs, the background processes that don't need a user watching them, run in another. Communications jobs, like the ones handling TCP/IP or FTP connections, often run in yet another.

Why does this separation exist?

This goes back to how IBM designed the System/38 and later the AS/400 in the first place. The idea was resource control and stability. If interactive users and batch jobs shared the exact same pool of memory and processing priority, a heavy batch job could easily choke out everyone typing on their terminals, and the whole system would feel sluggish for everyone.

By splitting work into subsystems, the system administrator can control exactly how much memory, how many active jobs, and what priority each type of work gets. Interactive users get responsiveness. Batch jobs get the resources they need without stepping on anyone's toes. And if one subsystem has a problem, it typically doesn't take down the entire machine.

The common subsystems you'll see

On a typical IBM i system, you'll usually find:

QCTL – the controlling subsystem. This is usually the first one that starts up, and it manages the console and overall system control.

QINTER – handles interactive jobs, meaning the sessions where users are actively working on 5250 screens.

QBATCH – handles batch jobs, the background processing work like report generation, data transfers, or scheduled jobs.

QCMN or QSYSWRK – handles communications-related work, like TCP/IP jobs, sockets, and various system tasks depending on the OS version.

QSPL – manages spooling, which is how the system handles print output and spooled files.

Many shops also create their own custom subsystems for specific applications, so that a particular piece of software gets its own isolated resource pool, separate from everything else running on the box.

How subsystems relate to jobs and job queues

Here's where it clicks together. When a batch job is submitted, it doesn't go straight into a subsystem. It first lands in a job queue. The subsystem is configured to look at specific job queues and pull work from them, based on rules the administrator has set up — like how many jobs can run at once, and what priority they get.

So the flow looks like this: a job gets submitted, it sits in a job queue, and the subsystem monitoring that job queue picks it up and runs it, provided there's room in the subsystem's active job pool.

This is also why you'll sometimes see a batch job sitting in a queue for a while, not doing anything. It's not stuck — it's just waiting for the subsystem to have available capacity to actually execute it.

Why this still matters in 2026

Even though IBM i has evolved a lot — with support for Java, PHP, open-source tooling, and integration with Linux partitions — the subsystem architecture is still the backbone of how work gets managed on the platform. If you're troubleshooting performance issues, tracking down why a job won't start, or trying to isolate a runaway application, understanding subsystems is often the first place to look.

Commands like WRKSBS, WRKSBSJOB, and WRKACTJOB are your window into this world, letting you see what's running, where, and how busy each subsystem's active job pool actually is.

Once you understand subsystems, a lot of AS400 job management suddenly makes a lot more sense — because almost everything the system does happens inside one.

Saturday, 25 July 2026

What is a Job in AS400 (IBM i)? Jobs, Job Queues & Job Logs Explained

If you're new to AS400, or IBM i, you may have heard terms like jobs, batch jobs, job queues, subsystems, and job logs. But what exactly is a job, and how does IBM i actually process the work we perform?

We'll understand the basics of IBM i jobs and look at interactive jobs, batch jobs, job queues, subsystems, and job logs. We'll also take a look at commands like WRKACTJOB, WRKJOB, and SBMJOB.

What Is a Job in IBM i?

The simplest way to understand a job is:

A job is a unit of work that IBM i manages and processes.

When you log in to IBM i using a 5250 terminal, your interactive session is associated with a job. When you run commands or programs, that work is performed in the context of your job.

Similarly, when you submit a batch process, IBM i creates a job to handle that work.

A job has identifying information such as a job number, user name, and job name. For example:

123456/USER1/MYJOB

This information is useful when troubleshooting because it allows us to identify and investigate a specific job.

Interactive Jobs

An interactive job is generally associated with a user directly interacting with the IBM i system.

For example, when you connect to IBM i using a 5250 emulator and enter commands or work with an application, you are working through an interactive job.

Batch Jobs

A batch job performs work without requiring continuous interaction from a user.

Batch jobs are commonly used for tasks such as:

  • Nightly processing
  • Generating reports
  • Billing
  • Database updates
  • Large-scale data processing

The SBMJOB command can be used to submit work as a batch job.

For example:

SBMJOB CMD(CALL PGM(MYLIB/MYPGM))

The exact command depends on the program or task you want to run, but the basic idea is that the work is submitted for batch processing.

What Is a Job Queue?

When a batch job is submitted, it may not start running immediately.

The job may first be placed on a job queue, where it waits until it can be processed.

A simple way to think about this is:

Submit Job → Job Queue → Job Processing

So, if someone says, "My batch job isn't running," one of the first things to determine is whether the job is actually running or whether it is waiting on a job queue.

What Is a Subsystem?

A subsystem provides an environment where jobs are processed and managed.

IBM i systems can have subsystems for different types of workloads, including interactive and batch processing.

You may have heard of subsystems such as:

QINTER

and

QBATCH.

The exact configuration varies between IBM i systems, but the important thing to remember is that jobs are processed within subsystems.

WRKACTJOB

One of the most useful commands for viewing jobs is:

WRKACTJOB

This stands for Work with Active Jobs.

It displays information about active jobs on the system, including details such as the job name, user, job number, job type, status, and subsystem.

You may see interactive jobs, batch jobs, and various system jobs.

WRKACTJOB is particularly useful when investigating what's currently happening on an IBM i system.

WRKJOB

Another useful command is:

WRKJOB

This stands for Work with Job.

It allows you to investigate a particular job and access information related to it.

Depending on the available options, you can examine details such as the job status, job log, call stack, and other job-related information.

What Is a Job Log?

The job log is one of the most important tools for troubleshooting IBM i applications.

During the life of a job, IBM i and the applications running within that job can generate messages.

These messages may indicate problems such as:

  • An object that doesn't exist
  • A file that cannot be found
  • A decimal data error
  • An authority problem
  • A record lock
  • Other application or system errors

If a program fails, one of the first things you should do is identify the relevant job and check its job log.

The job log can often provide the information needed to understand what actually happened.

The Big Picture

A simple way to understand IBM i job processing is:

User → Job → Job Queue → Subsystem → Processing → Job Log

An interactive session runs through an interactive job. A batch process can be submitted as a batch job, which may wait on a job queue before being processed by a subsystem.

If something goes wrong, the job and its job log can provide valuable information for troubleshooting.

Saturday, 12 October 2024

Basic CL Commands in IBM i (AS400)

When writing a Control Language Program (CLP) on IBM i (AS400), various CL commands are embedded within the program to interact with the system, manage processes, and communicate with users. Unlike some external commands like CRTCLPGM used for compiling programs, the commands used within a CLP program are designed to perform specific tasks during execution. In this article, we will cover essential commands typically used inside CLP programs, focusing on their purpose and practical usage in program flow.

Here are the basic CL commands we'll explore:

  1. WRKOBJ (Work with Objects)
  2. RUNSQLSTM (Run SQL Statements)
  3. SNDPGMMSG (Send Program Message)
  4. SNDMSG (Send Message)
  5. MONMSG (Monitor Message)

1. WRKOBJ (Work with Objects)

WRKOBJ is primarily an interactive command but can also be useful within CL programs when combined with object-checking commands such as CHKOBJ or DSPOBJD to verify the existence or state of system objects like files, programs, and libraries.

Usage in CLP Program

In CLP programs, you generally use commands like CHKOBJ to verify the existence of objects (which might be part of a pre-check step in your CLP), but you can use WRKOBJ outside of program control. Here's how CHKOBJ could work in place of WRKOBJ in a CLP program:

Syntax: CHKOBJ

CHKOBJ OBJ(LIBRARY/OBJECT) OBJTYPE(*FILE)

Example in CLP:

PGM /* Check if the object exists */ CHKOBJ OBJ(MYLIB/MYFILE) OBJTYPE(*FILE) MONMSG MSGID(CPF9801) EXEC(DO) /* If file does not exist, send a message and terminate */ SNDPGMMSG MSG('File MYFILE not found in MYLIB') TOPGMQ(*EXT) RETURN ENDDO /* If object exists, continue with further operations */ SNDPGMMSG MSG('Object found, proceeding') TOPGMQ(*EXT) /* Continue program logic */ ENDPGM

This example demonstrates how to check whether a file (MYFILE) exists in a specific library. If it doesn't, the program sends a message and stops further execution using the RETURN command. This is a basic and essential technique when working with objects within CLP programs.


2. RUNSQLSTM (Run SQL Statements)

The RUNSQLSTM command is used to execute SQL statements stored in a source member. SQL provides powerful capabilities for interacting with the database, and when you need to incorporate database manipulations within a CLP program, SQL statements can be called using RUNSQLSTM.

Syntax

RUNSQLSTM SRCFILE(LIBRARY/SOURCEFILE) SRCMBR(SOURCEMEMBER)

Example in CLP:

Let’s assume you need to update a database file in the middle of a CLP program. You could store the SQL command in a source member and call it from the CLP:

PGM /* Pre-checks and other logic */ /* Run an SQL statement to update records */ RUNSQLSTM SRCFILE(MYLIB/QSQLSRC) SRCMBR(UPDREC) SNDPGMMSG MSG('SQL statement executed successfully') TOPGMQ(*EXT) /* Further program logic */ ENDPGM

In this example, the SQL statement is stored in the source member UPDREC in the source physical file QSQLSRC. This technique is especially useful when working with complex SQL operations such as updates, inserts, or creating database objects directly from within a CLP program.


3. SNDPGMMSG (Send Program Message)

SNDPGMMSG is one of the most important commands used in CLP programs. It allows you to send messages to the external message queue or job log, which is crucial for informing users or operators about the status of the program. It replaces the deprecated DSPLY statement.

Syntax

SNDPGMMSG MSG('message text') TOPGMQ(*EXT)

Example in CLP:

PGM DCL VAR(&USERID) TYPE(*CHAR) LEN(10) /* Retrieve the current user profile */ RTVJOBA USER(&USERID) /* Send a message to the job log */ SNDPGMMSG MSG('Hello ' *CAT &USERID *TCAT ', Welcome!') TOPGMQ(*EXT) /* Continue with program execution */ ENDPGM

In this example, the program retrieves the current user profile using the RTVJOBA command and then sends a personalized message to the message queue using SNDPGMMSG. This is a practical way to send feedback to the user during execution.


4. SNDMSG (Send Message)

The SNDMSG command is used to send messages to other users or system operators. While SNDPGMMSG sends messages to the job log or message queue, SNDMSG communicates directly with users on the system, making it ideal for sending notifications.

Syntax

SNDMSG MSG('message text') TOUSR(user or group)

Example in CLP:

PGM /* Backup completed, notify the system administrator */ SNDMSG MSG('Backup process for MYLIB completed successfully.') TOUSR(SYSADMIN) /* Continue with further operations */ ENDPGM

In this example, once a task (such as a backup) is completed, the program sends a notification to the system administrator (SYSADMIN). This is a common pattern in CLP programs that handle system maintenance or batch processing.


5. MONMSG (Monitor Message)

MONMSG is used to monitor for specific errors or exceptions that occur during the execution of a command in a CLP program. When a monitored condition occurs (e.g., a missing object or failed operation), the program can handle the error gracefully by performing alternative actions, logging the error, or even terminating the process.

Syntax

MONMSG MSGID(message ID) EXEC(command or block of commands)

Example in CLP:

PGM /* Try to perform an operation */ DLTF FILE(MYLIB/MYFILE) MONMSG MSGID(CPF2105) EXEC(DO) /* If file not found, send a message */ SNDPGMMSG MSG('File not found, cannot delete') TOPGMQ(*EXT) ENDDO /* Continue with further operations */ ENDPGM

In this example, the program attempts to delete a file (DLTF), and if the file is not found (message ID CPF2105), the program handles the error by sending a message to the external message queue using SNDPGMMSG. MONMSG is critical in CLP programs to ensure smooth error handling.


Practical Example: Combining Commands in a CLP Program

Let’s now combine all these commands into a single, simple CLP program. This program checks for an object, runs an SQL statement, handles errors, and sends appropriate messages to both the job log and users.

PGM DCL VAR(&OBJEXISTS) TYPE(*CHAR) LEN(10) /* Check if the object exists */ CHKOBJ OBJ(MYLIB/MYFILE) OBJTYPE(*FILE) MONMSG MSGID(CPF9801) EXEC(DO) /* Object not found, send message */ SNDPGMMSG MSG('File MYFILE not found') TOPGMQ(*EXT) RETURN ENDDO /* If object exists, run SQL statement */ RUNSQLSTM SRCFILE(MYLIB/QSQLSRC) SRCMBR(UPDREC) MONMSG MSGID(SQLxxxx) EXEC(DO) /* Handle SQL errors */ SNDPGMMSG MSG('SQL execution failed') TOPGMQ(*EXT) RETURN ENDDO /* Notify user of successful completion */ SNDMSG MSG('MYLIB processing complete') TOUSR(SYSADMIN) ENDPGM

Explanation:

  • CHKOBJ checks whether the file MYFILE exists in the library MYLIB.
  • RUNSQLSTM executes an SQL statement stored in the source member UPDREC.
  • MONMSG captures any errors from the commands, sending appropriate messages.
  • SNDPGMMSG sends feedback to the job log, and SNDMSG notifies the system administrator when the process is completed.

Conclusion

The commands discussed—CHKOBJ, RUNSQLSTM, SNDPGMMSG, SNDMSG, and MONMSG—are fundamental to CL programming within IBM i. These commands allow for robust error handling, database manipulation, and user communication, all within a CLP program. Mastering these basic commands will enable you to write effective, efficient, and error-tolerant CL programs that interact with the system and users in meaningful ways.

In the next article, we will explore more advanced commands and techniques to expand your CL programming toolkit. Stay tuned!

Creating Your First CL Program on IBM i (AS400)

 A CL program is a series of IBM i commands that automate tasks, manage system operations, and handle user interactions. CL programs can call other programs, submit jobs, process files, and display messages, among many other things. Unlike general-purpose programming languages like Java or Python, CL is primarily focused on interacting with the IBM i operating system to control system-level operations.


Steps to Create Your First CL Program

To build your first CL program, we will follow these steps:

  1. Create a Source File and Member: The file will store your CL program.
  2. Write the CL Program: Learn the basic structure and commands.
  3. Compile the CL Program: Convert the source code into a runnable object.
  4. Run the CL Program: Execute the compiled program to see it in action.

Step 1: Create a Source File and Member

Before you start writing your CL program, you need to create a source member within a source physical file. The source file is where your program's source code is stored, and each program resides as a separate member in that file.

Option 1: Using SEU (Source Entry Utility) and PDM (Program Development Manager)

  1. Log in to your IBM i system via a terminal emulator (e.g., IBM i Access Client Solutions or TN5250J).

  2. Create a source physical file if one does not exist already. For CL programs, the common source file name is QCLSRC:

    CRTSRCPF FILE(LIBRARY/QCLSRC) RCDLEN(112)
  3. Once the source file is created, start PDM to create a new source member:

    STRPDM
  4. Select Option 3 (Work with members) and specify the QCLSRC file and the library where it resides.

  5. Create a new member by typing 2=Create next to an empty line, and give the member a name (e.g., MYCLPGM), with the source type CLP.

Option 2: Using Visual Studio Code with the "Code for i" Plugin

  1. Open Visual Studio Code with the Code for i plugin installed.
  2. Connect to your IBM i system by configuring the host, username, and password.
  3. Navigate to the library and source file (e.g., QCLSRC) within the Remote Explorer.
  4. Right-click and create a new member for your CL program.

Option 3: Using RDi (Rational Developer for i)

  1. Launch Rational Developer for i (RDi).
  2. Navigate to the Remote Systems Explorer (RSE).
  3. Right-click on the QCLSRC source file and select New > Member.
  4. Name the source member and set the type to CLP.

Step 2: Writing the CL Program

Every CL program follows a basic structure that begins with PGM and ends with ENDPGM. The PGM command defines the start of the program, while ENDPGM signifies its end.

Basic CL Program Structure

PGM /* Your program logic goes here */ ENDPGM

Example: A Simple "Hello, World" Program

We will create a program that sends a message to the user. Since the DSPLY statement cannot be used in CL, we will use the correct command SNDPGMMSG (Send Program Message) to display a message.

Here is how your first program might look:

PGM SNDPGMMSG MSG('Hello, World!') ENDPGM

Let’s break this down:

  • PGM: Marks the start of the program.
  • SNDPGMMSG MSG('Hello, World!'): Sends the message "Hello, World!" to the user.
  • ENDPGM: Marks the end of the program.

Writing Your Program

  • If you are using SEU, navigate to the source member you created, and enter the CL program directly in the editor.
  • If you are using RDi or VS Code, open the newly created member and start typing your CL code there. These modern tools will assist you with syntax highlighting and error detection.

Step 3: Compiling the CL Program

Once you’ve written your program, the next step is to compile it. Compiling translates your source code into an executable object that can run on the IBM i system.

The CRTCLPGM command is used to compile a CL program. Here’s how to compile your program, depending on your tool:

Option 1: Using SEU/PDM

  1. Exit SEU after saving your program.

  2. On the IBM i command line, enter the following command:

    CRTCLPGM PGM(LIBRARY/PROGRAM_NAME) SRCFILE(LIBRARY/QCLSRC)

    Replace LIBRARY with the name of the library where your source resides and PROGRAM_NAME with the name of the source member you created.

  3. Press Enter to compile. If there are no syntax errors, the program will be compiled and available to run.

Option 2: Using Visual Studio Code with Code for i

  1. Right-click on the source member in VS Code.
  2. Select Compile from the options. The Code for i plugin will automatically run the CRTCLPGM command for you.

Option 3: Using RDi

  1. Right-click on the source member and select Compile.
  2. RDi will run the CRTCLPGM command and display any errors or warnings in the Problems view.

Step 4: Running the CL Program

Now that your program is compiled, it’s time to run it.

Option 1: Running from the Command Line

To run your program directly from the IBM i command line, use the CALL command:

CALL PGM(LIBRARY/PROGRAM_NAME)

This will execute the program, and you should see the message "Hello, World!" displayed on the screen.

Option 2: Running from a Modern IDE (RDi or VS Code)

  • RDi: You can submit the program to run directly from the IDE by right-clicking on the source member and selecting Run.
  • VS Code: Use the Remote Command feature in the Code for i plugin to run your CL program remotely.

Verifying the Output

If your program executes successfully, the system will send the message "Hello, World!" to the job's message queue. You can view this message by checking the Message Queue of your job. For example:

  • From the command line, type:

    DSPJOBLOG

    This will display the job log where you can see the message sent by your program.


Debugging and Troubleshooting

If your program fails to compile or does not behave as expected, here are a few common issues and tips to resolve them:

  1. Syntax Errors: If the program doesn’t compile, the system will provide a detailed error message. Double-check your code for typos or missing commands.
  2. Program Not Found: If you try to run the program and receive an error stating "Program not found," ensure that the program was compiled correctly and that the PGM parameter in the CALL command matches the correct library and program name.
  3. Checking Messages: If the program runs but the output doesn’t appear, check the message queue using the DSPJOBLOG command to see if the message was successfully sent.

Conclusion

Congratulations! You’ve created, compiled, and run your first CL program on IBM i. This simple "Hello, World!" program has introduced you to the basic structure and steps involved in CL programming.

In this article, you’ve learned how to:

  • Create a source file and member to store your program.
  • Write a basic CL program using the correct command (SNDPGMMSG).
  • Compile the program using the CRTCLPGM command.
  • Run the program using the CALL command and check for output.

In the next article, we’ll dive deeper into the topic of Data Types and Variables in CL Programming, where you’ll learn how to manage and manipulate data within your programs. Stay tuned!

Setting Up Your Development Environment for CL Programming on IBM i

In this article, we will explore how to set up your development environment to begin working with Control Language Programming (CLP) on IBM i (formerly AS400). Setting up the right environment is essential for writing, testing, and running your CL programs efficiently. We’ll cover both legacy and modern tools, including SEU, RDi, Access Client Solutions, and the Visual Studio Code plugin “Code for i.”


Understanding the IBM i Development Ecosystem

IBM i is a robust and integrated platform with various tools for development, including legacy text-based tools like SEU, modern Integrated Development Environments (IDEs) like RDi, and even options for using popular editors like Visual Studio Code. Below are the main development tools available for CL programming on IBM i:

  1. Source Entry Utility (SEU): The traditional editor for writing CL programs.
  2. Program Development Manager (PDM): Utility for managing source members and libraries.
  3. Rational Developer for i (RDi): IBM's modern, Eclipse-based IDE for IBM i development.
  4. Visual Studio Code (VS Code): A popular code editor with the Code for i plugin, offering a modern interface for IBM i programming.
  5. Access Client Solutions (ACS): A GUI tool to access IBM i system functions.
  6. 5250 Terminal Emulation: A terminal interface for direct interaction with the system.

We’ll now discuss how to set up your environment using these tools.


Option 1: Setting Up with SEU and PDM (Legacy Tools)

Though SEU and PDM are considered legacy tools, they remain widely used for CL programming on IBM i. If you are working in an environment that still uses these tools, here’s how to get started.

Step 1: Logging into IBM i

You’ll need to log into the IBM i system using a terminal emulator:

  • IBM i Access Client Solutions (ACS): Provides a 5250 terminal emulator.
  • TN5250J: An open-source terminal emulator for accessing IBM i.

Step 2: Using PDM to Manage Source Members

To develop a CL program, first create a source member in a source physical file. PDM is used for managing these files.

  1. Enter STRPDM on the IBM i command line to start PDM:

    STRPDM
  2. In PDM, select Option 3 to work with source file members and create a new member in a source physical file like QCLSRC.

Step 3: Writing CL Programs with SEU

To write CL programs, use SEU. Once you’ve created the source member in PDM, type 2=Edit next to the member name to open SEU. This line-based editor allows you to input your CL code.

Here’s an example CL program using the correct statement to send a message:

PGM SNDPGMMSG MSG('Hello, World!') ENDPGM

Step 4: Compiling the CL Program

After writing your CL code, compile it with the CRTCLPGM command:

CRTCLPGM PGM(LIBRARY/PROGRAM_NAME) SRCFILE(LIBRARY/QCLSRC)

Option 2: Setting Up with Rational Developer for i (RDi)

Rational Developer for i (RDi) is IBM’s Eclipse-based IDE, offering a modern interface with code assistance, debugging, and more.

Step 1: Installing and Configuring RDi

Download and install RDi from IBM’s website. Once installed, configure your connection to IBM i through Remote Systems Explorer (RSE). After connecting, you can manage source files, members, and libraries through the IDE.

Step 2: Writing CL Programs in RDi

Once connected, create a new source member and write your CL programs using RDi’s powerful editor. Syntax highlighting and code suggestions make development easier.

For example:

PGM SNDPGMMSG MSG('Hello, World!') ENDPGM

Step 3: Compiling and Running the CL Program in RDi

RDi allows you to compile directly from the IDE. Right-click on the source member and select Compile to run the CRTCLPGM command and compile your program.


Option 3: Using Visual Studio Code with the "Code for i" Plugin

For those who prefer Visual Studio Code (VS Code), the Code for i plugin enables development on IBM i. This modern editor offers a lightweight and highly customizable environment.

Step 1: Installing Visual Studio Code and Code for i Plugin

  1. Download and install VS Code.
  2. Install the Code for i plugin from the VS Code extensions marketplace.

Step 2: Connecting to IBM i

Once the plugin is installed, configure the connection to your IBM i system by entering your system's hostname and credentials. This plugin allows you to browse libraries, edit source members, and compile programs directly within VS Code.

Step 3: Writing CL Programs in VS Code

Using the Code for i plugin, you can create and edit CL programs just like in RDi. Here’s an example CL program written in VS Code:

PGM SNDPGMMSG MSG('Hello, World!') ENDPGM

VS Code provides syntax highlighting and code completion for CL, making it a versatile tool for IBM i development.

Step 4: Compiling and Running CL Programs in VS Code

You can compile your CL programs directly from VS Code by using the built-in commands from the Code for i plugin, which automatically invokes the appropriate IBM i commands.


Option 4: Using IBM i Access Client Solutions (ACS)

IBM i Access Client Solutions (ACS) provides access to IBM i systems, including a 5250 terminal emulator and system management tools. You can also edit source members using ACS’s built-in editor.

Step 1: Installing and Configuring ACS

  1. Download IBM i Access Client Solutions from IBM’s website.
  2. Install ACS on your local machine and configure the connection to your IBM i system.

Step 2: Writing CL Programs in ACS

You can create and edit source members using either the terminal emulator or ACS’s Source Editor, which provides syntax highlighting.


Conclusion

Setting up your CL development environment on IBM i can be done using a variety of tools, from legacy options like SEU and PDM to modern IDEs such as RDi and even Visual Studio Code with the Code for i plugin. Each tool offers different strengths, allowing you to pick the one that best suits your workflow.

With this setup, you are ready to start writing, editing, and compiling CL programs. In our next article, we’ll take a deeper dive into Data Types and Variables in CL programming, covering how to manage and manipulate data effectively in your programs. Stay tuned!

Friday, 11 October 2024

CLP Syntax and Structure Overview

In this article, we will explore the fundamental syntax and structure of CLP (Control Language Programming) on IBM i (formerly AS400). Understanding the syntax is critical to writing CL programs that automate tasks, manage jobs, and interact with the system. This guide will walk you through the essential elements of CLP, including the structure of a CL program, the rules of syntax, and the core components you’ll use when writing your own CL programs.


Basic Structure of a CL Program

A CL program is a sequence of commands executed by the IBM i operating system to perform specific tasks. These tasks can range from managing files and data to submitting jobs and sending messages.

Here’s a simple overview of a CL program structure:

PGM /* Start of the program */ /* Declarations and initializations */ /* CL commands */ ENDPGM /* End of the program */

The two most important parts of every CL program are:

  • PGM: Marks the beginning of the program.
  • ENDPGM: Marks the end of the program.

Between these two statements, you will place your CL commands, variable declarations, and logic flow.


Key Components of CLP Syntax

  1. Commands: CL programs are driven by commands, which perform specific actions. Commands like SNDPGMMSG (Display), SNDMSG (Send Message), and SBMJOB (Submit Job) are the building blocks of a CL program.

    For example, here’s a simple command that displays a message on the screen:

    SNDPGMMSG MSG('Hello World!')
  2. Parameters: Many commands take one or more parameters that provide additional instructions. Parameters follow the command and are separated by spaces.

    For example, in the DSPLY command, the message 'Hello, World!' is the parameter being passed to the DSPLY command:

    SNDPGMMSG MSG('Hello World!')

    Some commands may have multiple parameters, which are often separated by commas:

    SNDMSG MSG('Processing completed') TOUSR(USER1)
  3. Variables: Variables are used in CL programs to store data for later use, such as user inputs, system values, or intermediate results.

    You can declare variables using the DCL (Declare) command. Variables can hold different types of data, including characters, numbers, and dates.

    Here’s an example of declaring a character variable:

    DCL VAR(&USERNAME) TYPE(*CHAR) LEN(10)
  4. Comments: Comments in CL programs are indicated by double slashes /* ... */. They can be placed on any line to describe what the program is doing. Comments are ignored by the system but are useful for developers to understand the code.

    Here’s an example of a comment:

    SNDPGMMSG MSG('Starting the program') /* Display start message */

CLP Command Syntax

Let’s break down the structure of a CL command. Each CL command generally follows this pattern:

COMMAND_NAME [parameters]
  • COMMAND_NAME: The name of the command (e.g., DSPLY, CRTCLPGM, SBMJOB).
  • parameters: The values or options passed to the command to define its behavior.

Commands in CL programs are written one per line, and their parameters can include strings, variables, or other system values.

Example 1: The SNMSGPGM Command

The DSPLY command is used to display a message on the screen. Here’s the basic syntax:

SNGMSGPGM MSG('Your message here')
  • message: This parameter is the text you want to display.

Example:

SNDMSGPGM MSG('Hello, welcome to the system!')

This will display the message: "Hello, welcome to the system!".

Example 2: The SBMJOB Command

The SBMJOB command is used to submit a job to the job queue for batch processing. This command can have several parameters to define the job name, user, job queue, etc.

SBMJOB CMD(CALL PGM(MYPROGRAM)) JOB(MYJOB) JOBQ(QBATCH)

In this example:

  • CMD(CALL PGM(MYPROGRAM)): Submits the job to call a program named MYPROGRAM.
  • JOB(MYJOB): Names the job MYJOB.
  • JOBQ(QBATCH): Specifies that the job should be submitted to the QBATCH job queue.

Declaring and Using Variables

Variables are crucial for holding values that can change during program execution. The DCL (Declare) command is used to declare variables in CL programs. Variables are typically named with an & symbol (e.g., &USERNAME, &RESULT).

Syntax for Declaring a Variable:

DCL VAR(&variable-name) TYPE(type) LEN(length)
  • VAR(&variable-name): The name of the variable.
  • TYPE(type): The data type, which can be:
    • *CHAR: Character string.
    • *DEC: Decimal number.
    • *LGL: Logical (true/false).
    • *INT: Integer number.
  • LEN(length): The length of the variable (relevant for character and decimal types).

Example:

DCL VAR(&USERNAME) TYPE(*CHAR) LEN(10) DCL VAR(&COUNTER) TYPE(*DEC) LEN(3 0)

In this example:

  • &USERNAME is a character variable with a length of 10.
  • &COUNTER is a decimal variable that can store values up to 999.

Assigning Values to Variables

You can assign values to variables using the CHGVAR (Change Variable) command.

CHGVAR VAR(&USERNAME) VALUE('JohnDoe') CHGVAR VAR(&COUNTER) VALUE(5)
  • CHGVAR VAR(&USERNAME) VALUE('JohnDoe'): Assigns the value 'JohnDoe' to the &USERNAME variable.
  • CHGVAR VAR(&COUNTER) VALUE(5): Sets the &COUNTER variable to 5.

Conditional Statements and Control Flow

In CL programs, you can control the flow of execution using conditional statements and loops. These are important for implementing logic in your programs.

IF Statement

The IF statement allows you to execute commands based on a condition.

IF COND(&COUNTER *EQ 5) THEN(SNDMSGPGM MSG('Counter is 5'))
  • COND(&COUNTER *EQ 5): The condition being evaluated (if &COUNTER equals 5).
  • THEN(SNDMSGPGM MSG('Counter is 5')): The command to execute if the condition is true.

DO and ENDDO Blocks

The DO block allows you to group multiple commands that should be executed together if a condition is met. The block ends with ENDDO.

IF COND(&COUNTER *LT 10) THEN(DO) CHGVAR VAR(&COUNTER) VALUE(&COUNTER + 1) SNDMSGPGM MSG('Counter incremented') ENDDO

In this example, if &COUNTER is less than 10, the program will increment the counter and display a message.


Handling Loops in CLP

CL programs support looping structures to repeatedly execute commands. Two common types of loops are DOWHILE and FOR.

DOWHILE Loop

A DOWHILE loop continues executing a block of commands as long as a condition remains true.

DOWHILE COND(&COUNTER *LT 5) CHGVAR VAR(&COUNTER) VALUE(&COUNTER + 1) SNGMSGPGM MSG('Loop iteration') ENDDO

This loop will continue until &COUNTER reaches 5.

FOR Loop

The FOR loop is another method of controlling repetitive execution, commonly used when you know the number of iterations.

FOR VAR(&I) FROM(1) TO(10) SNGMSGPGM MSG('Iteration') ENDFOR

This loop will iterate 10 times, displaying a message on each iteration.

More control flow statements can be found here: https://www.ibm.com/docs/en/i/7.5?topic=programming-controlling-processing-within-cl-program-cl-procedure


Monitoring for Errors: MONMSG

CL programs can monitor for errors using the MONMSG (Monitor Message) command. This allows you to handle exceptions gracefully instead of letting the program terminate unexpectedly.

PGM
MONMSG MSGID(CPF0000) EXEC(DO) SNGMSGPGM MSG('An error occurred') ENDDO /* Normal commands here */ ENDPGM
  • MONMSG MSGID(CPF0000): Monitors for any system message starting with CPF.
  • EXEC(DO): Executes the commands inside the block if an error occurs.

Best Practices for CLP Syntax and Structure

  1. Use Meaningful Variable Names: Choose variable names that reflect their purpose (e.g., &CUSTOMERNAME, &ORDERCOUNT).
  2. Indentation for Readability: Indent blocks of code inside DO/ENDDO and conditional statements for better readability.
  3. Comment Your Code: Add comments to explain the purpose of complex commands or logic.
  4. Monitor for Errors: Use MONMSG to handle potential errors and prevent program crashes.

Conclusion

The syntax and structure of CL programming are straightforward but powerful. With commands, variables, conditional logic, and loops, CL programs can automate complex tasks on IBM i. By following the guidelines and best practices outlined in this article, you are now equipped to start writing well-structured CL programs.

In the next article, we’ll dive deeper into Data Types and Variables in CL programming, covering how to use them effectively to manipulate data in your programs. Stay tuned for more! 

Thursday, 10 October 2024

Introduction to IBM i and CL

Welcome to the first step of your journey into CL programming! In this article, we will provide an in-depth introduction to IBM i, often known as AS400, and the role of CL (Control Language) within the system. By understanding the foundational concepts of IBM i and the role that CL plays in it, you’ll be well-equipped to begin writing your own CL programs.


What is IBM i?

IBM i is an operating system developed by IBM for its family of Power Systems hardware (formerly known as AS400). It is a robust, integrated, and highly secure platform widely used in enterprise environments for managing business-critical applications and data. The system has evolved over decades from its origins in the 1980s as the AS400, to becoming IBM iSeries, and is now referred to simply as IBM i.

IBM i is designed for both transactional and batch processing, supporting thousands of users simultaneously while ensuring high availability, reliability, and data integrity. It integrates a range of technologies, including databases, user interfaces, job scheduling, and networking, into one cohesive system. Companies across industries use it for enterprise resource planning (ERP), financial systems, and other critical applications.

Key Features of IBM i:

  • Integrated Relational Database (DB2 for i): The database is tightly integrated into the system, offering powerful data processing capabilities.
  • Object-Oriented Architecture: Everything in IBM i is an object, from files and programs to devices and jobs.
  • Security and Reliability: IBM i provides a high level of security, auditability, and operational stability, which makes it ideal for mission-critical applications.
  • Job Processing: The system is optimized for batch processing, job control, and multitasking operations.
  • Application Development Support: In addition to CL, IBM i supports a variety of programming languages, such as RPG, COBOL, Java, C, and C++.

What is CL (Control Language)?

CL, or Control Language, is a procedural language used primarily for interacting with the IBM i operating system. It is used to:

  • Automate repetitive tasks,
  • Control job flows,
  • Schedule batch jobs,
  • Manage system resources,
  • Execute commands that would otherwise be performed manually through the system’s command line interface.

CL scripts (also known as CL programs) are fundamental in managing the system’s behavior, controlling system jobs, and interacting with other system objects such as files, devices, and data queues.

The Role of CL in IBM i

  • Automation: Many tasks in IBM i, such as backups, reports, and data processing, can be automated through CL scripts.
  • Job Management: CL commands help manage jobs on the system, including starting, stopping, and monitoring them.
  • System Interaction: CL allows users and administrators to control the system programmatically rather than manually typing commands.
  • File and Database Handling: CL programs interact with the system’s database files, handling records, data queues, and objects efficiently.

In essence, CL acts as a glue between the user (or other programs) and the core functionality of the IBM i system, enabling robust automation and system control.


Understanding IBM i Objects

Before we dive into CL itself, it’s important to understand the concept of objects in IBM i. IBM i is built on an object-based architecture, where every component of the system is treated as an object.

Some common types of objects in IBM i include:

  • Programs (*PGM): Executable code, including CL programs and RPG applications.
  • Files (*FILE): Objects that hold data, including database files, source files, and device files.
  • Libraries (*LIB): Containers for grouping related objects.
  • Messages (*MSG): Messages sent between programs, jobs, or users.
  • Devices (*DEVD): Hardware resources like printers and disk drives.
  • User Profiles (*USRPRF): Objects representing system users and their permissions.

Libraries and Object Storage

In IBM i, objects are stored in libraries, which serve as logical containers for organizing resources. Libraries themselves are also objects, and there is a system library list that the operating system uses to search for objects. When working with CL, you’ll interact with libraries frequently as you manage the location and accessibility of various objects.


The Structure of a CL Program

A CL program is a sequence of CL commands that execute specific tasks. The structure is relatively simple, making it easy for both beginners and advanced users to pick up and automate tasks.

Here’s a basic structure of a CL program:

PGM /* Start of the CL program */ /* Variable declarations and initializations */ /* CL commands for processing */ ENDPGM /* End of the CL program */

Each line in a CL program typically begins with a CL command, followed by parameters. For example, a simple CL program to display a message on the screen might look like this:

PGM SNGMSGPGM PGM('Hello, World!') ENDPGM

This program uses the DSPLY command to display a message. We’ll explore such commands in more detail later in the series.


Command Entry and Prompting

IBM i provides several ways to execute CL commands:

  • Command Line: You can manually type commands at the command line (accessible via a terminal or emulator).
  • Programs: You can group multiple commands into a CL program, which can be executed as a single entity.
  • Batch Jobs: CL commands can be executed as part of a batch job, running in the background without user interaction.

One of the great features of CL is command prompting. When you type a command but aren't sure of its parameters, you can press F4, and IBM i will display a prompt with fields for all available parameters, helping you construct the command correctly.

For example, typing DSPLIB and pressing F4 will bring up a prompt for the Display Library command, where you can enter or select the parameters.


The Importance of CL in Daily Operations

For IBM i administrators, CL is indispensable. Here are some typical tasks that can be automated or controlled through CL:

  • Job Scheduling and Monitoring: Automating the execution of batch jobs using CL commands like SBMJOB (Submit Job).
  • Backup and Recovery: Automating system backups and restoring data using CL scripts.
  • File Management: Managing system files, moving data between environments, and processing files automatically.
  • Security and User Management: Managing user profiles, setting authorities, and auditing system activities through CL programs.

Many organizations with IBM i systems rely on CL for their critical processes. For instance, daily financial reports, system monitoring, and large-scale batch processing are often done using CL scripts.


Tools for Writing and Executing CL Programs

SEU (Source Entry Utility)

Historically, the Source Entry Utility (SEU) was used for writing CL programs. SEU is an editor for creating and maintaining source files on IBM i. However, it is now considered legacy, and most developers use more modern alternatives like RDi (Rational Developer for i).

RDi (Rational Developer for i)

Rational Developer for i is an Eclipse-based integrated development environment (IDE) that offers more robust features like code syntax highlighting, debugging tools, and an enhanced user experience compared to SEU.

PDM (Program Development Manager)

The Program Development Manager (PDM) is a tool used to manage source files, objects, and libraries. It allows developers to compile, run, and manage programs from a single interface.

Running CL Programs

Once written, a CL program can be compiled into an executable object using the CRTCLPGM command (Create CL Program). After compilation, it can be executed directly or scheduled to run in the background using commands like SBMJOB.


Conclusion

With this introduction to IBM i and Control Language (CL), you now have a solid understanding of the system and the role that CL plays. From managing jobs and automating tasks to controlling system resources, CL is an invaluable tool in the IBM i environment. As we progress, we’ll delve deeper into specific topics, starting with how to create your first CL program and exploring more advanced concepts.

In the next article, we’ll take our first steps by setting up the development environment and writing a basic CL program. Stay tuned as we start building your CL expertise from the ground up!

Introduction to CL Programming on IBM i (AS400)

Welcome to this comprehensive guide on CL Programming (CLP), the Command Language Programming used in IBM i (previously known as AS400). CL is an essential part of the IBM i platform, acting as a bridge between users and the system’s powerful features. Whether you're a beginner or have experience with IBM i, this guide will help you master the art of CL programming.

What is CL Programming?

CL (Control Language) is a scripting language designed to interact with the IBM i operating system. It's commonly used to automate tasks, control job flows, manage system resources, and execute system commands. Mastering CL helps you maximize the efficiency of an IBM i environment, especially when dealing with batch processing, job scheduling, or system management tasks.

Why Learn CL?

Learning CL is crucial for several reasons:

  • Efficient Job Control: Automating and controlling jobs on IBM i with CL can simplify workflows.
  • Integration with RPG: CL programs are often used in combination with RPG programs to handle system-level tasks, making it a versatile skill for IBM i professionals.
  • System Administration: CL scripts allow for task automation, monitoring, and resource management, making system administration much smoother.
  • Legacy Code Maintenance: Many businesses still use CL code. Understanding it helps maintain and modernize legacy systems.

Structure of this Tutorial

This blog will walk you through everything from basic concepts to advanced techniques. Below is a detailed index that will guide your learning journey. You can refer back to this page anytime to jump between topics.


Index: Comprehensive CL Programming Guide

1. Getting Started with CL Programming

  • Introduction to IBM i and CL
  • CLP Syntax and Structure Overview
  • Setting Up Your Development Environment
  • Creating Your First CL Program

2. Basic CL Commands

  • WRKOBJ (Work with Objects)
  • CRTCLPGM (Create CL Program)
  • RUNSQLSTM (Run SQL Statements)
  • SNDPGMMSG (Display Message)
  • SNDMSG (Send Message)

3. Working with Variables

  • Declaring and Initializing Variables
  • Using System-Defined Variables
  • Manipulating Variables in CL

4. Input/Output Operations

  • Reading and Writing to Data Areas
  • File I/O Operations in CL
  • Using Data Queues for Inter-Program Communication

5. Control Structures in CL

  • Conditional Statements: IF, ELSE, DO
  • Looping with DOWHILE and FOR
  • Error Handling with MONMSG (Monitor Message)

6. File Handling in CL

  • Handling Database Files in CL
  • Opening and Closing Files
  • Reading Records with RCVF (Receive File)
  • Updating and Writing Records in CL

7. Job and System Control

  • Submitting Jobs with SBMJOB
  • Controlling Jobs with WRKJOB and ENDJOB
  • Scheduling Jobs with WRKJOBSCDE
  • Working with Job Queues

8. Message Handling in CL

  • Sending and Receiving Messages in CL Programs
  • Handling System Messages
  • Using Message Queues for Communication

9. Error Handling and Debugging

  • Monitoring Errors with MONMSG
  • Debugging Techniques for CL Programs
  • Using STRDBG (Start Debug) to Test Programs
  • Handling System Errors and Program Failures

10. Subroutines and Modularity

  • Creating Subroutines in CL Programs
  • Best Practices for Modular CL Code
  • Using CALL and CALLSUBR to Invoke Procedures

11. Advanced Techniques

  • Using APIs in CL Programs
  • Integrating CL with RPG and COBOL
  • Using QShell Commands in CL
  • Handling Complex File Operations and Data Transfers

12. Working with System Objects

  • Object-Oriented Concepts in IBM i
  • Creating, Deleting, and Modifying Objects
  • Understanding Libraries, Files, and Members

13. System Security and CL

  • Working with User Profiles and Authorities
  • Auditing System Activities with CL
  • Automating Security-Related Tasks

14. Performance Optimization

  • Improving Performance of CL Programs
  • Batch Processing and Parallel Execution
  • Memory and Resource Management in CL

15. Real-World CL Examples

  • Automating Backup and Recovery Processes
  • Managing System Logs and Reports
  • Batch Processing of Financial Data
  • System Monitoring and Alerting with CL

16. Best Practices and Tips

  • Coding Standards for CL
  • Error Handling and Logging
  • Performance Tuning Techniques
  • Maintaining Legacy CL Code

Next Steps

In the upcoming articles, we will start by setting up the development environment, learning the syntax, and creating simple programs. Bookmark this page to stay updated as new sections are published, and feel free to explore the index to find topics of interest.

Whether you're preparing for a role in system administration, development, or support on IBM i, this guide will be your companion throughout the learning process. Let’s dive into CL programming and unlock the potential of IBM i!

Thursday, 3 October 2024

Basic Syntax Structure in Free Format RPG

 

Introduction

With the advent of free format RPG, the structure and syntax of the language have become far more intuitive and developer-friendly. No longer confined by the fixed columnar format of earlier RPG versions, free format allows programmers to write code in a modern, clean, and flexible style. This flexibility makes the language easier to learn, more readable, and more efficient in enterprise-level development on IBM i (AS/400).

In this article, we will cover the basic syntax structure in free format RPG, including:

  • Control options (ctl-opt)
  • Declaration specifications (dcl-s, dcl-c, dcl-f, dcl-pr, dcl-pi)
  • Operators and expressions
  • Flow control structures (if, select, loops, etc.)
  • Procedures and subprocedures
  • Comments and best practices for readability

By the end of this article, you will understand how free format RPG is structured and how to write clean, maintainable code.


1. Control Options (ctl-opt)

Control options in free format RPG are used to define global settings for the program. These settings apply to the entire RPG module and influence how the program behaves during compilation and execution. In older RPG versions, these were specified using header specifications (H-specs). However, in free format, the control options are declared with the ctl-opt keyword.

Common Control Options:

  • dftactgrp(*no): Disables the default activation group.
  • actgrp(*new): Specifies a new activation group for the program.
  • main(): Defines the entry point of the program.
  • debug(*yes): Enables debug options.
  • bnddir(): Specifies a binding directory for external procedures or service programs.

Example:

ctl-opt dftactgrp(*no) actgrp(*new) main(mainProc);

This example defines that the program will not use the default activation group, creates a new one, and specifies mainProc as the entry procedure of the program.


2. Declaration Specifications

Declarations are a critical part of any RPG program. They define variables, constants, files, procedures, and prototypes. In free format, declaration statements no longer need to adhere to column restrictions, and they are more expressive and readable.

2.1 Declaring Variables (dcl-s)

Variables in free format RPG are declared using the dcl-s (declare scalar) keyword, followed by the variable name, its data type, and optional initialization.

Example:

dcl-s customerName char(50); dcl-s totalAmount packed(9:2) inz(0); // Initialized to 0 dcl-s taxRate packed(5:2) inz(0.07); // Initialized to 7%

Here, we declare:

  • customerName: A character string of length 50.
  • totalAmount: A packed decimal with 9 digits, 2 decimal places, initialized to 0.
  • taxRate: A packed decimal with 5 digits, 2 decimal places, initialized to 0.07.

2.2 Declaring Constants (dcl-c)

Constants are defined using the dcl-c (declare constant) keyword. Constants, once defined, cannot be changed during the execution of the program.

Example:

dcl-c PiValue float(8) value(3.1415926535); dcl-c Message char(20) value('Welcome to RPG!');

In this example:

  • PiValue: A constant holding the value of Pi.
  • Message: A constant string initialized with the text "Welcome to RPG!".

2.3 Declaring Files (dcl-f)

Files (both input and output) are declared using the dcl-f (declare file) keyword. File declarations specify the access method (*input, *output, *update, etc.), and the file type (e.g., DISK, PRINTER, WORKSTN).

Example:

dcl-f CustomerFile usage(*input) keyed; dcl-f ReportFile printer oflind(*inof);
  • CustomerFile: Declares a file for input with keyed access (e.g., an index for direct access to records).
  • ReportFile: Declares a printer file used to generate reports, with an overflow indicator (*inof).

2.4 Declaring Prototypes (dcl-pr and dcl-pi)

Prototypes allow you to declare procedures that may be external or internal to the program. Prototypes help define the signature of a procedure—what parameters it takes and what value it returns.

  • dcl-pr: Declare procedure prototype.
  • dcl-pi: Declare procedure interface (the actual procedure).

Example:

// Procedure prototype dcl-pr CalculateTotalAmount packed(9:2); baseAmount packed(9:2); taxAmount packed(9:2); end-pr; // Procedure interface dcl-pi CalculateTotalAmount packed(9:2); baseAmount packed(9:2); taxAmount packed(9:2); end-pi;

In this example, we declare:

  • CalculateTotalAmount: A procedure that takes two packed decimal parameters (baseAmount and taxAmount) and returns a packed decimal with 9 digits and 2 decimal places.

3. Operators and Expressions

Free format RPG supports various operators to perform calculations, comparisons, and logical operations.

3.1 Arithmetic Operators:

  • +: Addition
  • -: Subtraction
  • *: Multiplication
  • /: Division

Example:

totalAmount = baseAmount + (baseAmount * taxRate);

This expression calculates the total amount by adding the tax to the base amount.

3.2 Comparison Operators:

  • =: Equal to
  • <>: Not equal to
  • >, <: Greater than, less than
  • >=, <=: Greater than or equal to, less than or equal to

Example:

if totalAmount > 1000; dsply 'Large order'; endif;

Here, the program checks if totalAmount is greater than 1000, and if so, displays a message.

3.3 Logical Operators:

  • and: Logical AND
  • or: Logical OR
  • not: Logical NOT

Example:

if isMember and hasDiscount; discountAmount = totalAmount * discountRate; endif;

This example calculates a discount only if both conditions—isMember and hasDiscount—are true.


4. Flow Control Structures

4.1 Conditional Statements: if, elseif, else

Conditional logic allows the program to make decisions based on conditions.

Example:

if orderValue > 1000; dsply 'High-value order'; elseif orderValue > 500; dsply 'Medium-value order'; else; dsply 'Low-value order'; endif;

The if block checks conditions in sequence and executes the appropriate block of code.

4.2 select / when

The select / when structure allows for multi-condition checks similar to a switch-case in other languages.

Example:

select; when orderType = 'A'; dsply 'Type A order'; when orderType = 'B'; dsply 'Type B order'; other; dsply 'Unknown order type'; endselect;

Here, select provides a way to handle different cases based on the value of orderType.

4.3 Loops: for, dow, dou

Loops allow for repetitive execution of code until a condition is met.

for Loop Example:

for counter = 1 to 10; dsply counter; endfor;

This loop runs from 1 to 10, displaying each value of counter.

dow (Do While) Example:

dow totalSales < targetSales; totalSales += dailySales; enddo;

The loop continues as long as totalSales is less than targetSales.

dou (Do Until) Example:

dou totalSales >= targetSales; totalSales += dailySales; enddo;

This loop runs until totalSales reaches or exceeds targetSales.


5. Procedures and Subprocedures

Procedures allow for modular programming by separating logic into reusable blocks of code.

Defining a Procedure:

dcl-proc CalculateDiscount; dcl-pi *n packed(9:2); baseAmount packed(9:2); discountRate packed(5:2); end-pi; return baseAmount * discountRate; end-proc;

Here, CalculateDiscount is a procedure that calculates the discount based on the base amount and the discount rate.

Calling a Procedure:

discount = CalculateDiscount(totalAmount : discountRate);

Procedures improve code organization and reusability.


6. Comments and Best Practices

Comments are essential for making the code readable and understandable by other developers or for future reference. In free format RPG, comments start with two slashes (//).

Example:

// Calculate total amount with tax totalAmount = baseAmount * (1 + taxRate);

Best Practices:

  • Use meaningful variable names: Variables like totalAmount and baseAmount convey their purpose clearly.
  • Break complex logic into procedures: Modularize your code using procedures and subprocedures.
  • Comment your code: Ensure that key logic is explained for readability and maintainability.

Conclusion

The basic syntax structure of free format RPG is clean, flexible, and modern, allowing developers to focus on business logic rather than syntax constraints. Understanding the basic components like control options, declarations, operators, and flow control structures is the foundation for mastering RPG in its free format style.

As you progress, you will see how this syntax forms the backbone of more complex applications and enterprise solutions on IBM i.