Open PL/I 8.1 for UNIX

  • Start Here
  • CodeWatch Reference
  • Open PL/I Language Reference Manual
  • Open PL/I User's Guide
  • Copyright and Trademarks
  • Notations and Conventions


Start Here

Open PL/I is a robust and flexible development system for PL/I applications that enables you develop and run your PL/I solutions on UNIX.

  • Development Licensing
Parent topic: Open PL/I 8.1 for UNIX


Development Licensing

  • Licensing Concepts
  • Sentinel RMS license server
    Information on how to start and stop the remote license server.
  • Managing your licenses
    How to manage your licenses on the remote server using the License Administration tool.
  • Licensing Reference
Parent topic: Start Here


Licensing Concepts

  • Remote Development Licensing
    How Remote Development Option licensing works when using the Eclipse IDE with a remote server.
  • Using the Sentinel RMS License Server for Remote Development Option
    Guidance on using the Sentinel RMS license server with Remote Development Option.
  • Usage Log
Parent topic: Development Licensing


Remote Development Licensing

You need a license when you use the Eclipse IDE on you local Windows client machine to develop on a remote server.

The licensing system is hosted on the remote server. When you first use Eclipse on the client machine you will be prompted to enter the host name of the license server; this allows the client machine to obtain a license from the remote server.

Parent topic: Licensing Concepts


Using the Sentinel RMS License Server for Remote Development Option

The Remote Development Option requires that licenses are installed and administered on the the remote server.

The Sentinel RMS license server is installed automatically when Studio Enterprise Edition Remote Development Option is installed. The license server binaries and the license file will be installed under /var/microfocuslicensing.

Parent topic: Licensing Concepts


Usage Log

The licensing system creates a usage log file that details all licensing activity. In addition to monitoring usage, the file is a useful licensing diagnostic tool.

Log files are called lservrc.log. When they reach 10MB in size they are archived to lservrc.log.xxx where xxx is an incremental number for the archive file.

The files are located in var/microfocuslicensing/logs. As these files contain important and useful information, and, to maintain disk space, it is recommended that you manage these files accordingly.

Parent topic: Licensing Concepts


Sentinel RMS license server

  • To start the Sentinel RMS license server
    Steps to start the license server.
  • To stop the Sentinel RMS license server
    Steps on how to stop the license server.
Parent topic: Development Licensing


To start the Sentinel RMS license server

You need to be logged in as root user to perform this task.

You can start the license server by running lserv. The script startlserv.sh is supplied for use with Micro Focus products. It configures your environment and starts lserv with the appropriate options.

  1. Change to the licensing directory. From a command prompt enter:
    cd /var/microfocuslicensing/bin
  2. Run the start script. Enter:
    ./startlserv.sh
Parent topic: Sentinel RMS license server


To stop the Sentinel RMS license server

You need to be logged in as root user to perform this task.

The script stoplserv.sh is supplied for use with Micro Focus products. It configures your environment and stops lserv with the appropriate options.

  1. Change to the licensing directory. From a command prompt enter:
    cd /var/microfocuslicensing/bin
  2. Run the stop script. Enter:
    ./stoplserv.sh
Parent topic: Sentinel RMS license server


Managing your licenses

  • To start the Licensing System Administration tool
    Steps to start the Licensing Administration tool to manage your licenses.
  • To authorize your product
    Use your authorization code to authorize (license) your product.
  • To install licenses from a license file
    Install licenses in this manner if you have obtained licenses by manual authorization and you have a license file containing authorization codes.
  • To view installed licenses
    Check licences installed and their status.
  • To configure licenses
    Configure your license setup.
  • To revoke licenses
    Revoke your license if you want to use it on another machine.
Parent topic: Development Licensing


To start the Licensing System Administration tool

From a command prompt type:
java -jar cesadmintool.jar

The Micro Focus Licensing Administration menu will be displayed.

Parent topic: Managing your licenses
Related tasks
To authorize your product
To view installed licenses
To configure licenses
To install licenses from a license file
To revoke licenses
To obtain a commuter license
To return a commuter license


To authorize your product

  1. Start the Micro Focus License System Administration tool.
  2. Select the Online Authorize option by inputting the corresponding list number and pressing Enter.
  3. Enter you authorization code at the Authorization Code prompt and then press Enter.
Parent topic: Managing your licenses
Related tasks
To start the Licensing System Administration tool
To view installed licenses
To configure licenses
To install licenses from a license file
To revoke licenses
To obtain a commuter license
To return a commuter license


To install licenses from a license file

You must have write access on the license file that contains the authorization codes.

  1. Start the Micro Focus License System Administration tool.
  2. Select the Manual Licence Installation option by inputting the corresponding list number and pressing Enter.
  3. Enter the name of the license file at the File containing licenses? prompt.
Parent topic: Managing your licenses
Related tasks
To start the Licensing System Administration tool
To authorize your product
To view installed licenses
To configure licenses
To revoke licenses
To obtain a commuter license
To return a commuter license


To view installed licenses

  1. Start the Micro Focus License System Administration tool.
  2. Select the Check License Status option by inputting the corresponding list number and pressing Enter. A list of installed licenses will be displayed and will show:
    • The name of the product licensed
    • The type of license
    • The number of days before the license expires (applicable to trial licenses only)
    • Whether the license is hosted locally or a networked computer
Parent topic: Managing your licenses
Related tasks
To start the Licensing System Administration tool
To authorize your product
To configure licenses
To install licenses from a license file
To revoke licenses
To obtain a commuter license
To return a commuter license


To configure licenses

It is recommeded that you only update the license configuration with the assistance of Micro Focus SupportLine.

  1. Start the Micro Focus License System Administration tool.
  2. Select the Advanced Configuration Options option by inputting the corresponding list number and pressing Enter.

    A list of configurable items is displayed with the current values enclosed within square brackets. If more than one License server value is set a '*' is displayed.

  3. Select the option you want to change and press Enter.

    If you want to assign more than one value for License Server, enter a colon separated list.

    SERVER1:SERVER2:SERVER3
Parent topic: Managing your licenses
Related tasks
To start the Licensing System Administration tool
To authorize your product
To view installed licenses
To install licenses from a license file
To revoke licenses
To obtain a commuter license
To return a commuter license


To revoke licenses

  1. Start the Micro Focus License System Administration tool.
  2. Select the Revoke Licenses option by inputting the corresponding list number and pressing Enter.

    A list of authorized products stored on your local machine is displayed.

  3. Select the license you want to revoke and press Enter.

    A new authorization code will be supplied. Progress messages, including the filename containg the new code, are displayed.

Parent topic: Managing your licenses
Related tasks
To start the Licensing System Administration tool
To authorize your product
To view installed licenses
To configure licenses
To install licenses from a license file
To obtain a commuter license
To return a commuter license


Licensing Reference

  • UNIX and Linux Licensing Messages
    Messages you might encounter when working with licensing on a UNIX or Linux server.
Parent topic: Development Licensing


UNIX and Linux Licensing Messages

  • Error - Initalizing: Cannot find initialisation file
    The initialisation file /var/microfocus/licensing/bin/ces.ini is missing. Verify your installation with Micro Focus SupportLine.
  • Error - Unable to manage licenses in license manager that is not running on localhost
    You have a remote license server configured. You should install the licenses on that machine or configure your license server to be the local host.
  • Error [5]: Cannot talk to the license server on host "xxx.x.x.x". Server not running
    The /etc/hosts file might not contain an entry for hostname and IP address.
  • Error authorizing... Remote request error - The authorization code is invalid
    Check the authorization code you have entered against the code printed on your license card.
  • Unable to authorise ()
    The authorization code cannot be verified. The specific cause is given in the brackets. Depending on the nature of the message, further detail and instruction will accompany the message.
Parent topic: Licensing Reference


Error - Initalizing: Cannot find initialisation file

Parent topic: UNIX and Linux Licensing Messages


Error - Unable to manage licenses in license manager that is not running on localhost

Parent topic: UNIX and Linux Licensing Messages


Error [5]: Cannot talk to the license server on host "xxx.x.x.x". Server not running

Ensure that these values are added to the /etc/hosts file. You can find the hostname by typing hostame from a command prompt. To obtain the IP address, type /sbin/ipconfig from a command prompt.
Parent topic: UNIX and Linux Licensing Messages


Error authorizing... Remote request error - The authorization code is invalid

Parent topic: UNIX and Linux Licensing Messages


Unable to authorise ()

Parent topic: UNIX and Linux Licensing Messages


CodeWatch Reference

This book describes how to use CodeWatch, which provides interactive, source-level debugging capability for Open PL/I.

  • Overview
    This chapter provides an overview of the Micro Focus CodeWatch application.
  • Getting Started
    This chapter provides information to help get you up and running with CodeWatch. The following sections discuss program preparation, invoking the correct interface, CodeWatch files, multiple modules, and basic window and dialog navigation.
  • The Command-line Interface
    This chapter provides information on entering debugger commands. The command-line interface applies to the command-line version of the debugger (-classic), commands in action lists, and commands entered in the Command window of the graphical interface.
  • Debugging Concepts
    This chapter describes debugger concepts including action lists, pointers, environments, CodeWatch error messages, and program recovery.
  • CodeWatch Functionality
    This chapter describes the facilities that let you control the execution of your program, discusses environment control issues, explains how to examine, modify, and evaluate the contents of data items, and describes features such as the macro facility, debugger command files, and on-line help.
  • CodeWatch Commands
    This chapter lists and describes all of the CodeWatch commands in alphabetical order. The definitions consist of subsections that contain information on use, command syntax, a brief description, and a command-line example.
  • Debugging Open PL/I Programs
    This chapter describes CodeWatch features that relate to debugging PL/I programs and contains a sample command-line debugging session of an Open PL/I program. At the end of this chapter, the listing of the program used in the sample debugging session is provided. The source of the sample program is also available on the release media.
Parent topic: Open PL/I 8.1 for UNIX


Overview

  • Introduction
  • Summary of Features
Parent topic: CodeWatch Reference


Introduction

Effective source-level debugging can help shorten the time spent on finding programming errors. A program may behave abnormally even after being successfully compiled. Although such a program's syntax is correct, the program still contains programming errors, or bugs, that cause unpredictable consequences such as unintended changes to the values of variables, infinite loops, incorrect output, or abnormal program termination.

Debugging is the process of discovering these bugs and eliminating them. Source-level debugging involves examining and modifying the source language elements of a program while it executes.

CodeWatch is a powerful software development tool that can help you locate bugs in programs. There are two flavors of CodeWatch available: one with a command-line interface and one with a windows interface. The command-line version offers a traditional line-oriented interface allowing you to interactively enter commands from the keyboard. The windows interface offers at least two main windows: one that allows you to enter commands and one that allows you to view your source code. You access CodeWatch commands through pull-down menus and dialogs.

CodeWatch keeps track of variables, subroutines, and data types in terms of the symbols used in the source language. You can reference these items without having to consider the underlying machine language or architecture. You can use CodeWatch to access the source text of the program, to identify and reference program entities, and to detect errors in the program's algorithms and logic.

Parent topic: Overview


Summary of Features

The following is a list of CodeWatch features.

Controlling Program Execution

CodeWatch has control over the execution of the program. Program execution can be started at a specified point, stopped and resumed at different points, transferred from one point to another, and terminated at any point.

  • Breakpointing: Breakpoints can be set to suspend execution at specified source program statements. The status of the program can then be evaluated or modified.
  • Catching: Process control can be returned to the debugger when a given signal is generated.
  • Stepping: Program execution can be stepped by one or more source program statements at a time. The debugger can also step into, over, or out of a called procedure.
  • Tracing: Tracepoints can be set at statements or at procedure and block entries to track program execution.
  • Watchpointing: Watchpoints can be set to monitor given variables. When the contents of a watched variable change, program execution stops and control is returned to the debugger.

Examining the Source Program

CodeWatch allows you to examine the source program, find specified text strings, move to specified line numbers, and examine included source files.

Environment Control

CodeWatch allows you to set the evaluation environment it uses to provide scope for referencing a specific instance of a variable or statement.

Symbolic Access

The value of a variable can be examined and/or altered as program execution continues. Procedure entries and exits can be monitored at the debugger command level. Expressions can be evaluated using the Evaluate command.

Action Lists

One or more of the debugger commands can be combined and executed at step and breakpoints.

Macro Facility

Macros can be defined as a sequence of debugger commands that will be used repeatedly throughout a debugging session. The macros can then be used like any other debugger command.

Command Files

Debugger command files can be created with a text editor or by logging commands to a specified file during a debugging session. These command files can then be used to execute the predefined sequence of debugging commands automatically during a debugging session.

Issuing Error Messages

CodeWatch identifies error conditions and issues meaningful, complete sentence error messages.

Parent topic: Overview


Getting Started

  • Program Preparation
  • Invoking CodeWatch
  • Debugging a Program with Multiple Modules
  • Ending a Debugging Session
  • Getting Started with the Graphical Interface
Parent topic: CodeWatch Reference


Program Preparation

A program must be compiled using the -deb option before it can be run under the control of the debugger. This is because the compiler generates a data base file referred to as the STB file. This file contains symbolic information that the debugger needs to reference to manipulate source program symbols and entities; set breakpoints, tracepoints, and watchpoints; and control program execution. A program is referred to as being compiled in debug mode when one or more of the program modules have been compiled with the -deb option.

For example, a PL/I program contained in a source file named primes. pl1 is compiled in debug mode by entering the following command line:

mfplx primes.pl1 -deb
Parent topic: Getting Started


Invoking CodeWatch

Once the program has been compiled in debug mode and linked, you can use CodeWatch to debug your program. To invoke CodeWatch, use one of the following command formats:

Graphical Interface (Windows only)

cwgui [-e]
      [-srcpath [source_directory [:source_directory] ...]]
      [-stbpath [STB_directory [:STB_directory] ...]]
      [-path [directory [:directory] ...]]
      [-usrin filename]
      [-usrout filename]
      [-8bit]
      [program-name]
      [program-arguments]

Command Line Interface

cwcmd [-classic]
      [-x]
      [-e]
      [-srcpath [source_directory [:source_directory] ...]]
      [-stbpath [STB_directory [:STB_directory] ...]]
      [-path [directory [:directory] ...]]
      [-usrin filename]
      [-usrout filename]
      [-8bit]
      [program-name]
      [program-arguments]

where:

-e (echo) | Specifies that every debugger command entered will be echoed back to the terminal.
-srcpath, -stbpath, and -path | Specify directory paths to be searched for source and STB files. See In Search of Source and STB Files for more information.
usrin and -usrout | Specify files to redirect user program input from or output to, respectively. See "Redirecting User Program I/O" for more information.
8bit | Allows CodeWatch to treat an extended set of ASCII characters as printable. See "Extended ASCII Character Support" for more information.
program-name | Is the name of the executable file to be debugged. If the debugger is invoked without a program-name argument, the a.out file in the current directory will be used if it exists; otherwise, CodeWatch comes up "standalone."
program-arguments | Are command-line arguments to be passed to the program.

CodeWatch does not require a program-to-debug at startup time. If no program-to-debug is supplied to CodeWatch, CodeWatch comes up standalone. However, on UNIX systems, it will first look for a.out as the default program name. When CodeWatch comes up standalone, a LOAD or ATTACH command must be used to specify the program to be debugged.

  • The STB File
  • Searching for Source and STB Files
  • Redirecting User Program I/O
  • Extended ASCII Character Support
  • Start-up Files
Parent topic: Getting Started
Related information
In Search of Source and STB Files


The STB File

When a program source file is compiled in debug mode, a file called the STB file (symbol table file) is created, which contains important information needed by the debugger during the debugging session. The name of this file is constructed by replacing the extension of the source file name (for example, .pl1 for a PL/I program), with an .stb extension. This STB file is placed by default in the directory in which the compilation took place.

  • Compressed STB Files
Parent topic: Invoking CodeWatch


Compressed STB Files

Code Watch handles compressed STB files. If you wish to compress your STB files, do so, and the debugger will uncompress them when it needs to access them. This happens, for example, when you step into a new evaluation environment for which the STB file has been compressed. An STB file is only uncompressed once during a debug session and remains uncompressed until you quit the debugger.

When you quit the debugger, you will be given a list of STB files that have been uncompressed during the debug session. You will be asked whether or not you would like to re-compress the files.

When quitting the debugger, you need not wait while all the STB files are being re-compressed. The re-compression process is forked off into another process.

Debug sessions run by another user accessing the same set of STB files with which you are working will not compress or uncompress an STB file out from under you. When the debugger is in the process of uncompressing an STB file, it writes a lock file to the directory in which your STB files reside, telling other debugger processes to wait until the uncompression is finished (for that STB file).

Note:

To write the lock file and to do the actual uncompression you must have write permission to the directory in which your STB files exist.

It is possible to use a compression utility other than compress. To do this, you must set the following three environment variables:

CW_COMPRESS_COMMAND | Set this environment variable to the command used to compress the STB files.
CW_UNCOMPRESS_COMMAND | Set this environment variable to the command used to uncompress the STB files.
CW_COMPRESS_SUFFIX | Set this environment variable to the suffix that denotes that the file is compressed (.Z for the compress utility).

The following are command-line examples for setting these environment variables:

setenv CW_COMPRESS_COMMAND   pack
setenv CW_UNCOMPRESS_COMMAND unpack
setenv CW_COMPRESS_SUFFIX    .z

The following command-line switches are used for the handling of compressed STB files:

-nocompress | Tells the debugger not to look for compressed STB files. If you are not going to compress your STB files, this is a good switch to use, because it saves the debugger that extra time of looking for compressed STB files.
-forcecompress | Causes the debugger to re-compress automatically any files that have been uncompressed during the debug session, without prompting you when you Quit out of the debugger. In the command-line interface, you will still be given a list of which files will be re-compressed, but in the Windows interface you will not be given this information.
Parent topic: The STB File


Searching for Source and STB Files

After the program is linked and CodeWatch is invoked with the loaded executable file as an argument, the debugger requires access to both the program source file(s) and the STB file(s).

The source file(s) will, by default, be searched for first in the directory that was specified to the compiler (relative to the current directory), and if not found, then in the current directory.

The STB file(s) will, by default, be searched for first in the current directory (where they are created), and if they are not found, they will be searched for in the directory that was specified to the compiler. This is the exact opposite of the search algorithm used for source files.

It is possible through the use of debugger command-line arguments and/or environment variables to specify alternate directories in which to search for both source and STB files before the default directories are searched.

The CodeWatch options -srcpath and/or -stbpath, followed by a list of directory names separated by colons (:), may be given to specify a list of directories to be searched before any other directories are searched. These directory lists will be searched (in order) for source files and/or STB files, respectively. If a directory list starts with a colon, the current directory (.) is assumed to be first (a trailing colon is ignored). The -path option followed by a directory list will be used in place of the -srcpath option and/or the -stbpath option if one or both is not given.

If the source and/or STB files are not yet found after searching any directories specified when invoking CodeWatch, the debugger will search directories specified by environment variables in a similar manner. The environment variables CODEWATCH_SRCPATH and/or CODEWATCH_STBPATH may be set to a list of directory names, separated by colons. These directory lists will be searched (in order) for source files and/or STB files, respectively. The environment variable CODEWATCH_PATH followed by a directory list will be used in place of the CODEWATCH_SRCPATH environment variables and/or the CODEWATCH_STBPATH environment variables if one or both is not given.

For example, the following command:

cwgui -srcpath :/pl1progs/src:/src/pl1progs\ -stbpath /pl1progs/stb:/pl1progs/obj program-name

will cause the debugger to search for the source files in the following directories in order:

  1. /pl1progs/src
  2. /src/pl1progs
  3. The directory specified at compilation (if other than the current directory)
  4. The current directory (.)

The debugger will search for the STB files in the following directories in order:

  1. /pl1 progs/stb and /pl1 progs/obj
  2. The current directory (.)
  3. The directory specified at compilation (if other than the current directory)
Parent topic: Invoking CodeWatch


Redirecting User Program I/O

When a user program is run under CodeWatch, there are three ways to specify that input and/or output be directed to/from another file.

  • The command options -usrin and -usrout. Each of these takes a filename operand.
  • The ">" (output) and the "<" (input) parameters for the RELOAD command. See Reload for more information. Both of these parameters also take a filename operand.
  • The Stdin and Stdout edit fields in the Reload dialog.

When either the input or output is redirected, CodeWatch attempts to open the specified file(s) in the appropriate mode. If the open fails, CodeWatch prints an error message and exits.

Note:

When the program normally continues to completion (for example, by using the Continue or Step command) and is automatically reloaded by CodeWatch, output redirection is preserved in append mode, while using an explicit Reload resets output redirection to the terminal.

Parent topic: Invoking CodeWatch


Extended ASCII Character Support

Normally, the debugger considers a range of ASCII characters to be unprintable. When the debugger evaluates a given data item, a dot "." is printed instead of each character within that range. The "unprintable" ASCII range is usually any character whose ASCII value is less than 32, within the range of 127 to 159 inclusive, or greater than 254. When using the -8bit command-line option, the debugger will not assume that the ASCII characters within the range of 127 to 159 inclusive are unprintable. As a result, printable characters within the extended ASCII character set, which are supported by some terminals, are allowed to be printed. This is especially useful for terminals that support languages other than English.

Parent topic: Invoking CodeWatch


Start-up Files

Upon invocation of the debugger, a command file containing debugger commands is automatically executed, if present. The debugger searches for this file in the following locations in the given order:

  1. In the file specified by the environment variable CODEWATCH_INIT.
  2. In the file .codewatch in the user's current directory.
  3. In the file .codewatch in the user's home directory.

As soon as one of these files is found, the debugger commands contained within it are executed, after which normal interactive debugging may continue. It is not required that a start-up file exist.

Parent topic: Invoking CodeWatch


Debugging a Program with Multiple Modules

Not all source modules need to be compiled in debug mode to use CodeWatch. You may compile in debug mode only those modules you want to debug.

If you debug a program with multiple modules and the main program is compiled in debug mode, the initial environment will always be the main program module.

If the main program is not compiled in debug mode, the initial environment will be the first debug module specified in the link step.

The COBOL program amort.cob is an example of a program with multiple modules. To debug just the subprogram MPCALC, only mpcalc.cob needs to be compiled in debug mode. To do this, use the following command sequence:

$ lpicobol amort.cob
$ lpicobol mpcalc.cob -deb
$ ldcobol amort.o mpcalc.o -o amort
$ cwcmd amort
Note:

The dollar character ($) in this command sequence is the system prompt.

The debugger is then invoked and MPCALC is the initial evaluation environment.

Parent topic: Getting Started


Ending a Debugging Session

To end a debugging session, enter the QUIT command at the command-line prompt or select Exit from the File menu in the Windows interface.

Using either method causes normal termination of the debugger and the termination of your program. Once the debugging session has been terminated, the system prompt will be displayed.

Keyboard interrupts while the debugger is accepting commands are ignored, but a keyboard quit (for example, <Ctrl \>) will terminate the debugging session.

Programs that terminate normally while running under the control of CodeWatch will automatically be re-initialized with any explicitly set breakpoints, watchpoints, and tracepoints (and any associated action-lists) preserved, so that execution may start from the beginning if desired. However, breakpoints that may have been set in shared libraries will not reset if the library is not loaded at program setup. The exit status with which the program exited is given. Refer to your UNIX documentation (exit (2)) for more information.

Parent topic: Getting Started


Getting Started with the Graphical Interface

The Codewatch graphical display consists of a source window, output window, and edit-line used for command-line input, plus a set of user customizable buttons.

The Codewatch display is illustrated for the Windows and UNIX platforms in the following two figures.

CodeWatch Display - Windows.

CodeWatch Display - UNIX.

  • Getting Started
  • Selecting Text and Line Numbers
Parent topic: Getting Started


Getting Started

The CodeWatch graphical interface is a simple and intuitive, easy-to-use interface. It is easy to learn, while allowing more advanced users to debug programs efficiently.

The graphical interface is closely connected to the command-line interface. It uses source and output windows to display text and customizable buttons, which allow you to quickly execute and/or edit commands.

All of the commands that the command-line interface supports are also supported in much the same way via the graphical interface Edit-line.

From the Menu Bar, clicking on Commands, Help, or Buttons presents the same popup command menu. This menu is divided into items that comprise functionality groups, and then subitems that correspond to all of the supported commands for that group. Hence, it is easy to see the functionality and commands that CodeWatch supports for, say, Program Control, and either get help for a command, execute or edit a command, or add a new button corresponding to a command.

  • Buttons
Parent topic: Getting Started with the Graphical Interface


Buttons

Buttons are a mechanism for quickly entering a command either immediately or via the Edit-line. Under Buttons on the Menu Bar, Button Mode allows for quick execution of clicked buttons, or an edit/confirm mode that allows editing and/or confirmation of the command.

When you use the quick button mode, most buttons execute immediately, as does "Step," while buttons that require arguments always use Edit/Confirm mode.

Parent topic: Getting Started


Selecting Text and Line Numbers

Buttons that require a text string or line number operate in "quick" mode if the text or line number is selected prior to the button selection.

  • To select a particular line, double-click anywhere within the text on that line.
  • To select text, click and drag the mouse over the text to be selected.

Note that on some systems, double-clicking causes the next blank-delimited text string to be selected. In this case, both a text and line number have been selected, and CodeWatch will use each appropriately for upcoming button selections.

For example, suppose you wish to Break on line 27. Use the scroll bar in the source window to move line 27 into view (if necessary), double-click anywhere on line 27, and then click the Break button. Clicking the Break button without having previously selected a line would have resulted in the Edit/Confirm mode being used.

Since the Breakpoint command (usually) requires a line number, clicking on Edit in the popup menu will place the cursor in the Edit-line. Press Return to execute the final command.

Similarly, for commands that operate on text strings, selecting text as described above and clicking a button will cause the selected text to be used as an argument to the command. For example, selecting the text string "count" from the Source window and clicking the Evaluate button will cause the variable name "count" to be evaluated in the current environment.

Thus, selecting text and line numbers for use in conjunction with buttons (and in fact, any command selected from the Command Menu in the menu bar), is actually a shorthand way of entering commands via the Edit-line.

  • Help
Parent topic: Getting Started with the Graphical Interface


Help

You can find a complete description for each of the Codewatch commands in the CodeWatch Commands chapter or by accessing Help from the Menu Bar.

Parent topic: Selecting Text and Line Numbers


The Command-line Interface

  • Special Symbols
  • CodeWatch Commands and Options
  • Entering CodeWatch Commands
Parent topic: CodeWatch Reference


Special Symbols

CodeWatch commands may include certain symbols that have special meaning. The table below lists these symbols and their meanings.

Symbol
 | Definition
+ | Unary plus sign, and addition
- | Unary minus sign, and subtraction
= | Right-hand side qualifier for Let
; | Command separator
[ ] | Action-list delimiters
' or " | String delimiters (' or " depending on source language)
/ | Command option indicator
\ | Statement reference qualifier
% | Command line continuator, statement label indicator, procedure entry point, and exit point indicator
: | Activation number indicator
{ } | Logical expression delimiters
Parent topic: The Command-line Interface


CodeWatch Commands and Options

A debugger command is made up of one or two keywords. The debugger command line contains a debugger command and optional or required arguments, depending on the command.

In the general format for the command-line, optional items are enclosed in oversized, square brackets. Note that the regular-sized square brackets in the action-list argument are required delimiters.

The general command-line format is as follows:

command [ /option ] [ argument ] [[action-list]]

where:

command | Names the specific debugger action to be performed.
/option | Modifies the action of the command.
argument | Supplies required or optional information to the command.
[action-list] | Lists one or more debugger commands.

Two examples of debugger commands using special symbols follow:

BREAKPOINT 90 [EVALUATE var1; E var2]

This example sets a breakpoint at line 90. The program variables var1 and var2 will be evaluated when this breakpoint is encountered.

BREAKPOINT LABEL1 + 8; LBREAKPOINT /ALL

This example sets a breakpoint eight statements past the label LABEL1 and then lists all breakpoints.

  • Command Variations
Parent topic: The Command-line Interface


Command Variations

Many of the debugger commands allow a number of prefixes, which specify a variation of the command function. The table below contains an explanation of these prefixes.

Prefix
 | Description | Example | Description
Lcommand | Lists information on command. | LMACRO | Lists information on the current macro definition.
Dcommand | Sets the default values for command. | DSTEP | Sets the default values for the Step command.
Ncommand | Removes the instance of command. | NBREAKPOINT | Removes the breakpoints.
Parent topic: CodeWatch Commands and Options


Entering CodeWatch Commands

Commands may be entered in either upper case or lower case. The debugger is not case-sensitive except when processing quoted literals. Commands will be shown in upper case in all command-line examples.

Enter the commands at the keyboard in response to the command-line prompt (CodeWatch>). For example, the PRINT command displays the current line from the source program:

CodeWatch> PRINT

Several commands can be entered on a single line, separated by semicolons, as shown in the following example:

CodeWatch> BREAKPOINT 25; EVALUATE DISTANCE

Using abbreviations, the previous command line can also be written as:

CodeWatch> B 25; E DISTANCE

Commands are executed one at a time, from left to right. If any command causes an error message to be displayed, the rest of the command line may be discarded. If any command causes the program to resume execution, the rest of the command line will be executed when the debugger resumes control. For example, the following series of commands will be executed only until CONTINUE is reached. EVAL COUNT is not executed until a breakpoint or other condition returns control to the debugger.

CodeWatch> B 93; FIND COUNT; CONTINUE; EVAL COUNT

If a command line is too long for a single line, it can be continued on the next line by entering a space and a percent character (%) as the last character on the line, followed by a carriage return. The percent character is not part of the command. It simply informs the debugger that you want to continue entering commands. The debugger prompts with ". . . >" indicating it is ready for the continuation of command input. For example:

CodeWatch> BREAKPOINT 123 [ STEP IN; FIND EXPENSES; %
...> EVALUATE EXPENSES; CONTINUE ]
Parent topic: The Command-line Interface


Debugging Concepts

  • Using Action Lists
  • Pointer Concepts
  • Environment Concepts
  • CodeWatch Error Messages
  • Aborted Program Recovery
Parent topic: CodeWatch Reference


Using Action Lists

An action list is a set of one or more CodeWatch commands specified for execution at breakpoints, after steps, at watchpoints, at tracepoints, or as macro definitions. The command-line syntax requires action lists to be surrounded by square brackets ( [ ] ). The commands must be separated by semicolons. You may use spaces after semicolons to aid readability. The commands that you enter in an action list are not checked for correctness until they are executed. The command-line syntax for the action list is as follows:

[ command1; command2; ...; commandn ]

A typical action list that could be set at a breakpoint is as follows:

EVALUATE COUNTER; STEP; E DISTANCE; CONTINUE

In more advanced debugging, commonly used sequences of commands can be defined as an action list with the Macro facility. The single macro name can then be used repeatedly throughout the debugging session to refer to a complex series of actions.

Parent topic: Debugging Concepts
Related information
Macro


Pointer Concepts

The debugger maintains two conceptual pointers: the execution pointer and the source file pointer. This section explains these pointers and how they are used during a debugging session.

  • The Execution Pointer
  • The Source File Pointer
Parent topic: Debugging Concepts


The Execution Pointer

The debugger maintains a pointer to the current execution point. This is the point at which execution resumes or begins following a Step or Continue. The execution pointer is reset during execution of the program. The Reload command sets the execution pointer to the start of the program. Only a Goto or Return can directly reset the execution pointer. The WHERE command will display the current execution point. In the Windows interface, the highlighted line in the Source window indicates the current execution point.

Parent topic: Pointer Concepts


The Source File Pointer

The debugger also maintains a pointer to the line in the source file currently being displayed. The CodeWatch Source command changes the current source file being displayed. The POINT and PRINT commands change and display the source file pointer, respectively. The Environment command without any operands resets the source file pointer to the current execution point.

Parent topic: Pointer Concepts


Environment Concepts

The environment is a frame of reference for the debugger to identify program entities such as certain instances of statements and variables. This section explains these entities and how to refer to them in the context of a debugging session.

  • Program Blocks
  • Block Activation Numbers
  • Statement Identifiers
  • Referencing Included or Copied Files
Parent topic: Debugging Concepts


Program Blocks

Program blocks are units of code that provide scope and context for the debugger. Program blocks are defined according to the source language. Refer to the appropriate language chapter for language-specific definitions of program blocks.

Parent topic: Environment Concepts


Block Activation Numbers

Activation numbers pertain to only recursive procedures and to languages that allow recursive procedures.

A procedure is active when it has been called during program execution. Each new call to a procedure counts as a new activation. The activation number specifies a unique activation of a procedure when more than one activation exists. Multiple activations occur when a procedure is recursive (A calls A) or indirectly recursive (A calls B calls A). Activation numbers are either absolute or relative.

  • Absolute Activation Numbers
  • Relative Activation Numbers
  • Using Activation Numbers
Parent topic: Environment Concepts


Absolute Activation Numbers

An absolute activation number is simply a positive integer. Number 1 denotes the first activation of a procedure, number 2 the second, and so forth. To refer to an activation of a procedure using absolute activation numbers, the procedure name is followed by a colon (:) and the positive integer that denotes the activation.

Parent topic: Block Activation Numbers


Relative Activation Numbers

A relative activation number is either zero or a negative integer. A relative activation number specifies the number of activations to count backwards from the most recent activation. The number 0 denotes the most recent activation. The activation directly preceding the most recent activation is denoted by -1. For example, if there have been five activations of the procedure FACTORIAL, FACTORIAL:0 refers to the fifth activation and FACTORIAL:-2 refers to the third activation. This activation can also be referred to as FACTORIAL:3 (that is, using the absolute activation number 3).

Parent topic: Block Activation Numbers


Using Activation Numbers

Each activation of a procedure has its own distinct values for automatic (or local) data, and each activation may have different actual parameters or arguments. An activation number can be used to specify the environment for evaluating or displaying variables and procedure arguments. An activation number can also be used when setting a breakpoint in a particular activation of a procedure.

If the activation number is omitted from the name, the debugger uses a default of 0, the most recent activation. The only exception to this is Breakpoint, where omitting the activation number means that a breakpoint is to be taken on every activation of the procedure.

Parent topic: Block Activation Numbers


Statement Identifiers

Commands such as Breakpoint require identification of statements within the program being debugged. Statement identifiers are either source line numbers or statement labels.

  • Line Numbers
  • Labels
  • Line Number and Statement Offsets
  • Entry and Exit Points
  • Statement Qualification by Environment
Parent topic: Environment Concepts


Line Numbers

The simplest way to refer to a statement is by using its source line number, that is, the physical line number in the source file on which the statement starts.

If an unqualified source file line number is specified (no environment reference), the first executable statement on the specified line, if present, or the first executable line following that line is used by the debugger.

If a source file line number is qualified by an environment reference, for example, "SIFT\18", the translation of the line number to an executable statement is executed in the same manner as described for unqualified line numbers, except that the set of executable statements that the line number can be translated to is restricted to those contained in the specified environment block.

Parent topic: Statement Identifiers


Labels

The way to refer to a labeled statement is to use its statement label. For any language in which statement labels are numbers, such as Pascal or FORTRAN, a percent character (%) must be used in front of the statement label. For example, in the following Pascal code

325:
326: 9999: writeln('ERROR: INVALID DATA.');
327: end. {Program Terminates}

the statement references 326 and %9999 both refer to the writeln statement.

In the following PL/I code:

 9:  DUMMY
10:  %INCLUDE 'MYFILE.PL1';/*PL/I sample */
11:  CHKPAGE:
12:  if I = 66 then
13:        do; put skip; I = 0; goto DONEIT;
14:  end;
15:  I = I + 1; DONEIT: J = 0; K = 0;
16:  L = 0;

the CodeWatch commands B 11 and B CHKPAGE are equivalent, and both refer to statement number 11.

Parent topic: Statement Identifiers


Line Number and Statement Offsets

A line number offset can be used to locate a statement when it is not labeled or its source line number is unknown. A line number offset is formed by placing a plus character (+) followed by a positive integer after a source line number or a statement label. For example, line 15 in the example below can be referred to by the program as 11 + 4 or as CHKPAGE + 4. Of course, 15 + 0 refers to the same line.

 9:  DUMMY
10:  %INCLUDE 'MYFILE.PL1';/*PL/I sample */
11:  CHKPAGE:
12:  if I = 66 then
13:        do; put skip; I = 0; goto DONEIT;
14:  end;
15:  I = I + 1; DONEIT: J = 0; K = 0;
16:  L = 0;

A statement offset must be used to refer to an unlabeled statement that is not the first statement on a line. A statement offset is formed by placing a period followed by a positive integer (indicating the number of statements from the beginning of the line) after the line number offset. (If the line number offset equals zero, a plus character must be used.) For example, the K = 0 statement on line 15 of the example above can be referred to by the debugger as 15 + 0.2 or CHKPAGE + 4.2.

Parent topic: Statement Identifiers


Entry and Exit Points

Every procedure has two special statements: the entry point to and the exit point from the procedure. The entry point is the place during execution at which the procedure has been called, but before other prelude code has run. A procedure's entry point is referred to within CodeWatch by specifying the procedure name followed by a backslash (\) and %ENTRY (or simply %E), for example,

READ_INPUT\%ENTRY.

The entry point to the current activation of a procedure may simply be referred to as %ENTRY (or %E).

The exit point is the place after which the return value (if any) has been computed and the return statement has been executed. All local variables are still defined. An exit point is referred to by the procedure name followed by a backslash and %EXIT (or %Ex), for example,

READ_INPUT\%EXIT.

The exit point to the current activation of a procedure may be referred to by %EXIT (or %Ex).

Entry and exit points may not be referred to in conjunction with statement offsets.

Parent topic: Statement Identifiers


Statement Qualification by Environment

A statement reference may need to be qualified by a reference to the environment in which the statement occurs. This is done by putting the block name of the environment (with an optional activation number) and a backslash in front of the statement reference. For example:

PRINT_OUT\10

Using just the backslash without the block name refers to the environment containing the current execution point.

Parent topic: Statement Identifiers


Referencing Included or Copied Files

Many source programs have the contents of separate files inserted into the program at compilation. Programs written in PL/I, BASIC, C, FORTRAN, or Pascal use an include statement or directive for this purpose; COBOL programs use a COPY statement.

When the debugger encounters one of these statements in a program, you can display the contents of the included file by using Source followed by the filename cited in the INCLUDE directive. The lines in the file will be numbered consecutively from the first line in the file. To return to displaying lines from the source file containing the current environment, simply use the Source command with no arguments.

Support for include file handling has been added for Open PL/I. This applies to include files that contain executable code. The current set of functionality is implemented as follows:

  • Stepping "into" an include file, for example, when the next statement is a %INCLUDE directive, will cause the screen display to switch to the specified include file. Commands that deal with the source file, for example, PRINT, POINT, and so on, work as expected using the current include file.
  • Stepping "through" an include file is allowed.
  • Setting breakpoints within an include is not allowed. The setting of a breakpoint unambiguously refers to the original containing source file.
  • Stepping "over" an include file, for example, when the next statement is a %INCLUDE directive, is not explicitly allowed. This may be accomplished by setting a breakpoint in the containing source file, followed by the CONTINUE command.
  • Stepping "out of" an include file before its last statement is accomplished similarly to stepping "over," that is, by setting a breakpoint in the containing source file followed by the CONTINUE command.

Using the macro preprocessor mfpp with CodeWatch is also allowed. CodeWatch will use the original source file (rather than the expanded preprocessed output of mfpp). Stepping "through" macros works similarly to the include file support described above.

For LPI-BASIC, LPI-COBOL, LPI-FORTRAN, and LPI-Pascal, executable code contained within included files cannot be debugged with CodeWatch.

Parent topic: Environment Concepts
Related information
Examining the Source Program


CodeWatch Error Messages

When CodeWatch encounters an error condition, a message is displayed at your terminal. The following sections describe common CodeWatch error messages.

  • Start-up Warnings
  • Start-up Errors
  • Syntax Errors
  • Semantic Errors
Parent topic: Debugging Concepts


Start-up Warnings

When the debugger session begins, the debugger may issue several different kinds of warnings.

A warning may be issued if the source file is newer than the program and/or STB file. Out-of-date files may be present for any of the following reasons:

  • The program has been edited but not re-compiled.
  • The program has been re-compiled but not re-linked.
  • The wrong SRCPATH is being used.
  • The wrong STBPATH is being used.

The following is an example of this type of warning message.

**Warning** Source file newer than program and .stb files for main.

A warning may be issued if an STB file for a module compiled in debug mode is not found. This would be an error if the debugger could not find any STB files; however, the debugger will issue a warning only if one or more (but less than all) STB files are missing.

The following is an example of this type of warning message.

**Warning** No debug data for environment
         ** Source file "y.pl1"
         ** Symbol table file "y.stb"
Parent topic: CodeWatch Error Messages


Start-up Errors

When the debugging session cannot begin, the debugger will display an error message at invocation. This indicates that a filename required by CodeWatch is an error because one or more of the following is true:

  • It does not exist or is not in the current directory.
  • The program file specified to be debugged is not an executable file.
  • None of the program modules in the program file was generated from a compilation using the -deb option.
  • The necessary debugger information files cannot be found in any of the specified or default directories.
Parent topic: CodeWatch Error Messages
Related information
In Search of Source and STB Files


Syntax Errors

The debugger issues a message when the command syntax is incorrect. The error message contains at least three lines of text: the first lines describe the error, the second to last line echoes the command line as it was entered, and the last line contains a caret ( ^ ), indicating the approximate location of the error in the command line above. After displaying an error message, the debugger issues a prompt and waits for another command. The following are examples of the message feature:

CodeWatch> TYPEPRIMES
**Error** Invalid Command
TYPEPRIMES
^
CodeWatch> TRACE EMTRY
**Error** Syntax error
TRACE EMTRY
      ^
Parent topic: CodeWatch Error Messages


Semantic Errors

Semantic errors occur when the debugger cannot correctly interpret a command line because of an incorrect variable name, an invalid argument, or some similar problem. With some semantic errors, the command line is echoed and a caret ( ^ ) is placed under it indicating the approximate location of the error. Two samples are shown from the command-line interface, as follows:

CodeWatch> EVALUATE ths_prime
**Error** Undefined variable or built-in function
EVALUATE ths_prime
                  ^
CodeWatch> BREAKPOINT 100000
**Error**   Statement 100000 not found in procedure
Parent topic: CodeWatch Error Messages


Aborted Program Recovery

CodeWatch has the ability to recover from and to reasonably debug user programs that have stopped because of certain operating system errors. When this occurs, the following are indicated by the debugger:

  • The error that caused the program to stop.
  • The current user program counter (the machine address of the execution point).
  • The name of the routine in which the error occurred.

If the routine in which the program stopped was compiled in debug mode, the source file line number of the execution point at the time of the error will also be given. The current evaluation environment will automatically be set to this environment and the debugging session may continue.

If the routine in which the program stopped was not compiled in debug mode, the environment of the most recently called routine that was compiled in debug mode is indicated, and the current evaluation environment is set to that environment. In this case, most debugger actions are allowed, including continuing execution from the point at which the program received the error. Note that it is not legal to use the Step or Goto commands from a non-debug routine.

Whether or not program execution stops because of a signal depends on the CodeWatch default catch settings for the signal. In most cases, you can modify the behavior by using the CATCH command.

The STACK command can provide a stack traceback to indicate the sequence of subroutine calls up to the time of the error.

Parent topic: Debugging Concepts
Related information
Catch


CodeWatch Functionality

  • Program Control
  • Environment Control
  • Symbolic Access
  • Examining the Source Program
  • Other Features
Parent topic: CodeWatch Reference


Program Control

This section explains the CodeWatch facilities that are used to control program execution. You may control the execution of your program in the following ways:

  • Setting breakpoints to suspend program execution at any executable statement.
  • Catching signals to return process control to the debugger.
  • Stepping through one or more executable statements at a time.
  • Setting watchpoints to monitor changes in specified variables.
  • Tracing statements and entries, allowing you to monitor every executable statement and the entry and exit points of a program.
  • Breakpoints
  • Catching Signals
  • Statement Stepping
  • Tracepoints
  • Watchpoints
  • Controlling Program Execution
Parent topic: CodeWatch Functionality


Breakpoints

Breakpoints are used to suspend program execution at specified locations so that you may execute various debugging actions, such as evaluating variables, single statement stepping, and so on. The Breakpoint facility is used to set a breakpoint at a specified statement or to modify the characteristics of a breakpoint already set at that statement. Up to 64 breakpoints can be active at any one time. Breakpoints may be conditional and may have associated action lists (sequences of debugger commands to be executed when the breakpoint is incurred).

There are three pertinent commands to the Breakpoint facility: BREAKPOINT, NBREAKPOINT, and LBREAKPOINT:

  • The BREAKPOINT command is used for adding new breakpoints and modifying existing breakpoints.
  • The NBREAKPOINT command removes either a specified breakpoint or all breakpoints.
  • The LBREAKPOINT command lists information about breakpoints.
Parent topic: Program Control


Catching Signals

You may specify whether or not process control should return to the debugger when a specified signal is generated. This is done with the Catch facility. You may also specify whether or not the user program is to continue as if it had or had not incurred the given signal. This is done with the Ignore option.

There are three pertinent commands to the Catch facility: CATCH, NCATCH, and LCATCH:

  • The CATCH command specifies that a signal should be caught and allows you to specify whether or not the signal is to be ignored by the user program.
  • The NCATCH command specifies that the signal should not be caught.
  • The LCATCH command lists Catch settings for a specified signal or all signals.
Parent topic: Program Control


Statement Stepping

Program execution may be single stepped one or more source-level statements at a time. It is possible to set default stepping modes:

  • You may specify that a Step should, by default, step into or over a call to a subroutine.
  • You may specify a default Step action list to be executed every time the debugger executes a Step.
  • You may also specify that a Step to a user-defined breakpoint should either execute the default Step action list, the breakpoint action list, or both.

There are three pertinent commands to the Step facility: STEP, DSTEP, and LSTEP.

  • The STEP command starts program execution at the current location of the execution pointer and stops execution after one or a specified number of statements.
  • The DSTEP command allows you to modify the default stepping modes and action list.
  • The LSTEP command lists the current stepping modes and action lists.
Parent topic: Program Control


Tracepoints

Tracing enables information about all block entries and statements to be announced as the program executes. Entry tracing allows an action list to be associated and may be conditional.

There are three pertinent commands to the Trace facility: TRACE, LTRACE, and NTRACE.

  • The TRACE command enables statement or entry tracing.
  • The LTRACE command lists the current tracing mode.
  • The NTRACE command turns off statement or entry tracing.
Parent topic: Program Control


Watchpoints

Watchpoints are used to monitor specified variables. The Watchpoint facility is used to designate a given variable to be watched. When the contents of the watched variable change, program execution stops and control is returned to the debugger. Watchpoints may be conditional and may have associated action lists (sequences of debugger commands to be executed when the watchpoint is incurred).

There are three pertinent commands to the Watch facility: WATCH, NWATCH, and LWATCH.

  • The WATCH command is used for adding new watchpoints and modifying existing watchpoints.
  • The NWATCH command removes either a specified watchpoint or all watchpoints.
  • The LWATCH command lists information about watchpoints.
Parent topic: Program Control


Controlling Program Execution

During a debugging session, CodeWatch maintains an execution pointer, which tracks the current point of program execution. When execution of the program has been halted by a debugger action, the pointer maintains the location as the current execution point. The current execution point can always be determined using the WHERE command. This allows you to control the execution of the program by using one of several simple debugger facilities.

The CONTINUE command is used to begin program execution or to resume execution following a breakpoint or a step operation.

The GOTO command moves the execution pointer to a specified statement. Program execution resumes at this point when a Continue or Step is issued. The statement is specified by a line number, a simple statement label, or a statement label followed by a line number offset or statement offset. The named statement must exist in the current program block. Once the debugger has executed the Goto, it displays the new execution point.

The RELOAD command restarts the user program, preserving any explicitly set breakpoints, tracepoints, and watchpoints with associated action lists. A subsequent Continue or Step will start program execution from the beginning of the program.

The RETURN command transfers the current execution point to the exit point of the current procedure. If the procedure returns a value, an expression must be given indicating the value to be returned. For more information, see the section Modifying Return Values.

The QUIT command causes termination of the debugging session. Selecting the Exit item in the File menu is equivalent to issuing the QUIT command.

CodeWatch does not require a program-to-debug at startup time. If no program-to-debug is supplied to Code Watch, CodeWatch comes up standalone. However, on UNIX systems, it will first look for a.out as the default program name. When CodeWatch comes up standalone, a LOAD or ATTACH command must be used to specify the program to be debugged.

The LOAD command loads the symbol table from a specified file into CodeWatch as the primary executable for debugging. It also purges the internal CodeWatch symbol table of any previously loaded executables or shared libraries.

The ATTACH command attaches CodeWatch to the "pid" (a decimal number) and performs a LOAD command, as described above. Attached programs that call exit () or that die are not automatically reloaded. Use the RELOAD command for this.

Programs may also be attached at the time of invocation, for example,

cwcmd -pid 3268 myprog.out
Parent topic: Program Control
Related information
Modifying Return Values


Environment Control

In many cases during a debugging session, it is necessary to refer to an environment to establish a frame of reference for identifying variables or statement identifiers. An environment is simply a program block, which the program refers to by specifying the name of the block or any statement within the block. This allows the debugger to find a specific instance of a variable or statement. Usually, a simple block name is adequate to specify an environment. It refers to the most recent activation of that block. To establish some other activation of the block as an environment, use a block activation number.

An active environment exists on the program stack as a stack frame containing automatic data for the environment. However, environments that do not exist on the program stack can also be referenced; such environments are called inactive environments. For example, a procedure that has not been called, and thus has no stack frame, is inactive. Another example of an inactive environment is one that is referenced by a block name followed by an activation number that is higher than the current activation of the block. It is possible to examine static and external data in inactive environments and to set breakpoints in them. An active environment must be specified to examine automatic data or procedure arguments.

  • Changing Environments
  • Stack Traceback
Parent topic: CodeWatch Functionality


Changing Environments

The Environment facility sets the current evaluation environment to provide scope to the debugger for identifying variables and statements. The environment specified can be a simple block name or a block name followed by an activation number or a statement identifier. An activation number is used to establish as an environment or an activation of a block other than the most recent one. A statement identifier is merely a convenient means of identifying the block that immediately contains the statement. If the environment argument is not specified, the evaluation environment is set to the environment containing the current execution point.

Whenever the debugger continues after program execution pauses (for example for a breakpoint or single step) the evaluation environment is reset to the environment containing the current execution point.

There are two pertinent commands to the Environment facility: ENVIRONMENT and LENVIRONMENT. The ENVIRONMENT command is used to change environments. The LENVIRONMENT command is used for listing information about environments.

Parent topic: Environment Control


Stack Traceback

The STACK command is used to print a traceback of a specified number of stack frames.

Parent topic: Environment Control


Symbolic Access

This section describes the various methods and facilities to access, modify, and display symbolic information.

  • Variable Names
  • Expression Evaluation
  • Variable Assignment
  • Listing Arguments
  • Modifying Return Values
  • Accessing Declaration Types
Parent topic: CodeWatch Functionality


Variable Names

The rules for identifying variables in the debugger are almost the same as the rules defined for the evaluation language. The same naming conventions are used, and all type and scope rules apply. One exception is that an environment name followed by a backslash (\) may be used to reference a variable in another program block. The names of variables are case-sensitive or case-insensitive, depending on the language of the module in which they are contained.

  • Referencing Elements of Arrays
Parent topic: Symbolic Access


Referencing Elements of Arrays

Elements of arrays are referenced using the constructs of the source language. CodeWatch allows access to array slices in programs written in Open PL/I, LPI-C, LPI-COBOL, LPI-FORTRAN, and LPI-PASCAL. See the language-specific chapters for information about exact syntax.

Parent topic: Variable Names


Expression Evaluation

The Evaluate command is used to evaluate and print the resultant value of expressions in the source language program. When the expression is evaluated, appropriate conversions are performed. Various display mode options (binary, decimal, octal, hexadecimal, and so on) are available.

Parent topic: Symbolic Access


Variable Assignment

The resultant value of an expression may be assigned to a named variable in the user program. When the expression is evaluated, appropriate type conversions are performed according to the rules of the source language. The resultant value is assigned to the named variable. If the type conversion is illegal, the debugger will issue an error message.

The LET command is used for variable assignment.

Note:

If the current environment is within a module compiled by LPI-C, the LET command or Change dialog is equivalent to evaluating an assignment expression. (In C, assignments are merely expression operators with side effects.)

Parent topic: Symbolic Access


Listing Arguments

The Arguments command prints the arguments for an environment. The environment specified must be the name of an active procedure. If an environment argument is omitted, the debugger defaults to the current evaluation environment.

The ARGUMENTS command lists the arguments for the given (or default) environment.

Parent topic: Symbolic Access
Related information
Environment Control


Modifying Return Values

The Return facility allows you to set the return value of a procedure. Execution control is transferred to the exit point of the current procedure, and if an expression is specified, it is used as the return value for that procedure.

There are two pertinent commands to the Return facility: RETURN and LRETURN. The RETURN command transfers control to the exit point of the current procedure and allows you to set the return value. The LRETURN command lists the return value for the current procedure.

Parent topic: Symbolic Access


Accessing Declaration Types

The TYPE command prints the resultant data type of an expression in terms of the data descriptions of the current source language.

The TYPE command is used to access declaration types.

Parent topic: Symbolic Access


Examining the Source Program

This section describes the CodeWatch facilities for searching, printing, and displaying different locations in the source file(s).

  • String Search
  • Changing Source Files
  • The WHERE Command
  • The POINT Command
  • The PRINT Command
Parent topic: CodeWatch Functionality


String Search

The FIND command locates a line in the source file containing a specified text string.

Parent topic: Examining the Source Program


Changing Source Files

The Source facility allows you to change the source file being displayed or to list information about the source files in the executable being debugged.

There are two pertinent commands to the Source facility: SOURCE and LSOURCE. The SOURCE command allows you to change the source file to be displayed. The LSOURCE command lists information about source files in the user program.

Parent topic: Examining the Source Program


The WHERE Command

The WHERE command reports either a specified location or the current point of execution. The specified location may be a name of a routine, a line number, or a statement label.

Parent topic: Examining the Source Program


The POINT Command

The POINT command locates a line number within the debug source file and reports that line. If no line number is specified, the line corresponding to the current source file pointer is printed. The source file pointer is the pointer to the current line in the current source file.

In the graphical interface, double clicking on a line is equivalent to using the POINT command.

Parent topic: Examining the Source Program


The PRINT Command

The PRINT command prints a specified number of source lines from the current debug source file or prints the current source line.

Parent topic: Examining the Source Program


Other Features

This section describes additional features of CodeWatch.

  • Command Macros
  • Debugger Command Files
  • On-line Help
Parent topic: CodeWatch Functionality


Command Macros

The Macro facility is used to define a macro as shorthand for a series of debugger commands that may be reused during the debugging session. Sixty-four macros may be defined at any one time. The series of debugger commands is specified as an action list. Once a macro has been defined, its name may be used just like any other debugger command name. The macro in the command line is replaced by the debugger commands specified in the action list. Those commands are executed normally.

Note:

Do not choose a macro name that is the same as a debugger command name because the macro name will override the debugger command for that debugging session.

If the last (or only) command in the series of debugger commands does not end with a semicolon, any additional arguments that appear on the command line after the macro name are supplied as arguments to the last command in the macro definition.

There are three pertinent commands to the Macro facility: MACRO, LMACRO, and NMACRO. The MACRO command creates new macros. The LMACRO command lists macros. The NMACRO command deletes macros.

Parent topic: Other Features
Related information
Using Action Lists


Debugger Command Files

The SAVE command writes out commands to a specified disk file to reset all current breakpoint, watchpoint, and/or macro settings for use in a later debugging session. The file can be read in by using the Read command.

The READ command is used to execute debugger command files, displaying each command to the screen as the command is executed.

The LOG command can be used to create debugger command files by causing all subsequent debugger commands to be logged to a specified file.

Parent topic: Other Features


On-line Help

Both the command-line interface and the graphical interface have a help facility. Click Help in the menu bar, or use the HELP command.

The HELP command with no parameters lists all of the available CodeWatch commands. If the HELP command is followed by command-name, help text for that command is displayed. If you need help for a specific command, you may specify the appropriate abbreviation for that command rather than the full command name.

Parent topic: Other Features
Related information
Help


CodeWatch Commands

  • Arguments
  • Attach
  • Breakpoint
  • Call
  • Catch
  • Commandline
  • Continue
  • Detach
  • Dstep
  • Environment
  • Evaluate
  • Find
  • Goto
  • Help
  • Kill
  • Lbreakpoint
  • Lcatch
  • Lenvironment
  • Let
  • Lmacro
  • Load
  • Log
  • Lreturn
  • Lsource
  • Lstep
  • Ltrace
  • Lwatch
  • Macro
  • Nbreakpoint
  • Ncatch
  • Nload
  • Nlog
  • Nmacro
  • Nmap
  • Nshlib
  • Ntrace
  • Nwatch
  • Peek
  • Point
  • Poke
  • Print
  • Read
  • Registers
  • Reload
  • Return
  • Save
  • Shlib
  • Source
  • Stack
  • Step
  • Trace Entry
  • Trace Statement
  • Type
  • Watch
  • Where
  • !
Parent topic: CodeWatch Reference


Arguments

Use

Prints the arguments of a specified procedure environment.

Command Syntax

ARGUMENTS [environment]

where:

environment
Name of an active procedure

Description

The ARGUMENTS command prints the arguments to a named procedure environment. The procedure environment can be any program block.

If the environment name is omitted, the debugger defaults to the current evaluation environment.

Example

In this example, the arguments to the "sift" procedure are displayed.

CodeWatch> ARGUMENTS sift
N = 10 { fixed binary (31) }
Parent topic: CodeWatch Commands
Related information
Environment Control
Environment
Evaluate
Let
Stack


Attach

Use

Attaches CodeWatch to a "pid" and executes a LOAD command.

Command Syntax

ATTACH pid filename

where:

pid
A decimal process identification number.
filename
Name of a file to be loaded

Description

The ATTACH command attaches CodeWatch to the pid (a decimal number) and performs a LOAD command. Attached programs that call exit () or that die are not automatically reloaded. Use the RELOAD command for this.

Programs may also be attached at the time of invocation, for example, cwcmd -pid 3268 myprog.out

Example:

CodeWatch> ATTACH 3768 myprog.out
Parent topic: CodeWatch Commands
Related information
Detach
Kill
Load
Nload


Breakpoint

Use

Suspends program execution to allow for debugger actions.

Command Syntax

BREAKPOINT [statement-id]
           [[action-list]]
           [/IF {logical-expr} [/ELSE[action-list]]]
           [/SKIP=n]
           [/IGNORE  |  /NIGNORE [/ALL]]
           [/SILENT  | /NSILENT]

where:

statement-id
Identifies the statement at which the breakpoint will be set or modified
action-list
Specifies a set of one or more CodeWatch commands separated by semicolons.
logical-expr
Can be any expression that may occur in the source language program, including references to simple as well as aggregate (such as array, record, and structure elements) type variables, returning a boolean value.

Description

The BREAKPOINT command is used to set a breakpoint at a specified statement or to modify the characteristics of a breakpoint already set at that statement. If the statement identifier is not specified, the breakpoint will be set at the current execution point; that is, the statement to be executed when program execution is resumed. The maximum number of breakpoints that can be active at one time is 64.

Breakpoints can be set at the entry point (%ENTRY) of external routines that have or have not been compiled in debug mode and at lines containing executable statements within routines that have been compiled in debug mode. Lines containing only comments or declarations, or only the keyword ELSE (else), are not valid breakpoint locations. If you try to set a breakpoint at one of these locations, the debugger will set the breakpoint at the first executable statement after the one named in the command.

Example

In the following example, a breakpoint is set at the entry point of the READ_INPUT procedure with an action list evaluating the value of MAXV.

CodeWatch> B READ_INPUT\%ENTRY [E MAXV]
CodeWatch> C
Break at PRIMES.READ_INPUT\%ENTRY
MAXV =                10 {fixed binary (31)}

In the following example, a conditional breakpoint is set on line 94. Program execution will stop if the variable COUNT is greater than 3; otherwise, the debugger will evaluate COUNT and continue.

CodeWatch> B SIFT\94 /IF {COUNT>3} /ELSE [E COUNT]
CodeWatch> CONTINUE
COUNT =              1 {fixed binary (31)}
COUNT =              2 {fixed binary (31)}
COUNT =              3 {fixed binary (31)}
Break at PRIMES.SIFT\94
  • Breaking at Specific Activations of a Block
  • Breakpoints with Action Lists
  • Skipping Multiple Iterations of a Breakpoint
  • Temporarily Ignoring Breakpoints
  • Suppressing the Breakpoint Message
  • Conditional Watchpoints
  • Incurring Breakpoints
Parent topic: CodeWatch Commands
Related information
Continue
Goto
Lbreakpoint
Nbreakpoint
Read
Save
Watch


Breaking at Specific Activations of a Block

If the statement identifier is qualified by a block name with an explicit activation number, the breakpoint applies only to that activation. If a block activation number is not specified, the breakpoint will be taken on every activation of the specified statement. The numbered activation may be higher than the most recent activation of the block. Relative activation numbers are converted to absolute activation numbers when the breakpoint is set.

Parent topic: Breakpoint
Related information
Block Activation Numbers


Breakpoints with Action Lists

If an action list is specified, it is set as the action to be performed when the breakpoint is taken. To remove an action list using command-line syntax, simply specify a null action-list, that is [ ]. To remove an action list using the Breakpoint dialog, simply delete the text in the Action List edit field. An action list of CONTINUE causes the breakpoint to act like a simple tracepoint; at each execution of the statement a message identifies the statement and execution continues.

Parent topic: Breakpoint


Skipping Multiple Iterations of a Breakpoint

A breakpoint counter is associated with each breakpoint. When the breakpoint is created, the counter is set to zero; each time the breakpoint is encountered the counter is incremented by one. All breakpoint counters are set to zero when the program is reloaded.

If a skip count is specified, a breakpoint skip counter is set to the value specified, causing the breakpoint to be skipped that number of times. Once the breakpoint skip counter is set, it remains in effect until its value decreases to zero.

Parent topic: Breakpoint


Temporarily Ignoring Breakpoints

If the Ignore option is specified, the breakpoint is flagged to be ignored and is not executed when it is encountered. The Ignore option is useful to temporarily disable a breakpoint. Turning off the Ignore flag sets the breakpoint in effect again. This is done by specifying the /NIGNORE option. It is possible to set all breakpoints to be ignored or not ignored. This is done by specifying the option /ALL in conjunction with /IGNORE or /NIGNORE.

Parent topic: Breakpoint


Suppressing the Breakpoint Message

When a breakpoint is encountered, CodeWatch normally prints a message specifying the line at which the breakpoint is set. This message can be suppressed by using the Silent option; this is especially useful if a debug-time "patch" is desired within your program. To create a patch, set a breakpoint at the beginning of the code that causes the program error. The breakpoint should include the Silent option and an action list that performs a work-around assignment ending with a GOTO command (to circumvent the program error) and a CONTINUE command. The debugger will then perform the specified action list at the breakpoint and continue execution without any interaction.

Parent topic: Breakpoint


Conditional Watchpoints

A conditional expression may be used to qualify the breakpoint; it must be the last option on the command line. When a breakpoint with the If option is set, the executing program will be suspended and the debugger will be activated whenever the breakpoint is encountered. The IF condition is then evaluated. The evaluation always takes place in the environment and language of the program statement. If the IF condition is false, program execution continues and the breakpoint is never reported. If the IF condition is true, the debugger incurs a breakpoint as usual.

Parent topic: Breakpoint


Incurring Breakpoints

When a breakpoint with a conditional expression is set at a particular program statement, the executing program will be suspended and the debugger will be activated whenever that program statement is about to be executed. The following will then occur:

  • The condition is evaluated; the evaluation always takes place in the environment and language of the program statement. If the condition is false and the Else action list has not been specified, program execution continues. If the condition is false and the Else action list has been specified, the Else action list is executed and program execution continues. If the condition is true, the debugger performs the following actions:
    • The breakpoint counter is incremented.
    • If the Ignore flag is on for this breakpoint, execution continues.
    • If the skip count for this breakpoint is non-zero, the count is decremented and execution continues. However, the skip count for an Ignored breakpoint is not affected.
    • The debugger reports an announcement of the breakpoint.
    • If an action list is specified, it is executed. The action list may specify that program execution is to continue.
Parent topic: Breakpoint


Call

Use

Calls a user procedure or function.

Command Syntax

CALL subroutine-name [(argument-list)]

where:

subroutine-name
Is a block name that may or may not return a value
argument-list
Is a list of variable names and/or constants separated by commas

Description

The CALL command will set up any given arguments and perform a subroutine call to the specified subroutine (function or procedure). If a breakpoint is set within a called subroutine (or in a routine which it in turn calls), then it is taken as usual. In this case, a new debugger prompt is used to indicate that a different level of debugger invocation has been entered. At this point, debugging can continue as usual, including stack tracebacks (with traceback only to the called routine), and calling another routine, thus entering yet a higher debugger invocation level. In this way, there is no change in the debugging environments across subroutine calls.

If the called subroutine is a function, the return value of the function will be printed at the end of the call. Functions may also be called through the use of Evaluate and Let, for example,

LET x = foo(y) * z

or:

EVALUATE foo(x) * foo(goo(y,foo(123))) / z

Functions that are defined or declared in the current execution environment may be called. In this case, the number and type of arguments given will be checked against the declaration or definition of the subroutine. If they do not match, an error will be given and the call will not be made.

It is not required that called functions be compiled in debug mode. If they are not, however, it will not be possible to set breakpoints within that function. The calling conventions of the source language of the environment from which the call is being made are properly upheld (for example, call-by-value versus call-by-reference).

Non-local Gotos within a called function are legal and executed only if the target is within an environment that has been called (that is, activated) subsequent to the initial call. If it is not, an error will be given and the call aborted.

The CALL command will not accept as an argument block names containing characters not allowed in a variable name for the source language of the current scope.

The maximum number of arguments allowed to be passed to a called routine is 240.

Illegal non-local Gotos within a called function do generate an appropriate error message and abort the call. However, the user program is terminated and must be reloaded using Reload to continue debugging.

Example

The following call takes no arguments.

CodeWatch> CALL page_in_info ()

The following is a function call returning an integer.

CodeWatch> CALL get_user_id(name)
174    { int }

The following is the same call as in the previous example, except that a breakpoint is incurred at the entry point of get_user_id.

CodeWatch> CALL get_user_id(name)
Break at get_user_id\%ENTRY
DEB(1:get_user_id)>

Related Commands

  • Evaluate
  • Let
Parent topic: CodeWatch Commands
Related information
Evaluate
Let


Catch

Use

Returns process control to the debugger when the given signal is generated.

Command Syntax

CATCH {/DEFAULT | [/NIGNORE|/IGNORE] signal}

where:

signal
Can be either a signal name mnemonic (such as SIGALRM, SIGINT, and so on) or the signal number corresponding to that mnemonic. Signal names may be specified in either uppercase or lowercase letters

Description

The occurrence of a signal that is set to be caught and ignored will cause process control to return to the debugger. When the child (user) process is subsequently resumed (for example, by using Step or Continue), it will continue as if it had not incurred the given signal. The occurrence of a signal that is set to be caught and not ignored (/NIGNORE), will cause process control to return to the debugger. When the child process is subsequently resumed, it will continue as if it had incurred the given signal. The occurrence of a signal that is not set to be caught will not cause process control to return to the debugger.

By default, certain signals are caught by the debugger. The Default option will reset all CATCH settings back to the debugger's default settings.

Use the command LCATCH /ALL to get a list of current signal settings.

Note: The signals SIGILL and SIGTRAP are permanently set to be ignored by the debugger. These are special signals because they are used by the debugger for breakpointing. You cannot modify the settings for these two signals.

Example

In the following example, process control will return from the child process to the debugger when SIGALRM is generated.

CodeWatch> CATCH /IGNORE SIGALRM
Changing SIGALRM to be caught and ignored.

When the child process resumes, it will ignore the SIGALRM and continue as if it had never generated a SIGALRM.

In the following example, the number 28 represents the signal SIGWINCH. Process control will return from the child process to the debugger when a SIGWINCH is generated.

CodeWatch> CATCH /NIGNORE 28
Changing SIGWINCH to be caught and not ignored.

When the child process resumes, it will recognize the signal SIGWINCH and continue as if it had incurred a SIGWINCH.

Parent topic: CodeWatch Commands
Related information
Lcatch
Ncatch


Commandline

Use

Displays CodeWatch command-line arguments.

Command Syntax

COMMANDLINE

Description

The COMMANDLINE command displays the command-line arguments specified to the user program. Command- line arguments may be specified to the user program either on the CodeWatch command line upon invocation of the debugger, or by using the RELOAD command.

Example

In the following two separate examples, the command-line arguments are displayed. Note that the primes executable file being debugged takes no command-line arguments, whereas the myprog executable file was invoked with two command-line arguments.

CodeWatch> COMMANDLINE
Command line : "primes"

CodeWatch> COMMANDLINE
Command line : "myprog" "-b" "-verbose"
Parent topic: CodeWatch Commands
Related information
Reload


Continue

Use

Begins or continues program execution.

Command Syntax

CONTINUE

Description

The CONTINUE command is used to begin program execution initially or following a reload operation, or to resume program execution following a breakpoint or a step operation.

The CONTINUE command is often the last command in an action-list.

Example

In this example, program execution is continued until the breakpoint is encountered.

CodeWatch> CONTINUE
Break at PRIMES.READ_INPUT\%ENTRY

In the following example, a breakpoint is set at line 119 of the main program and a watchpoint is set on the variable n with an action list to continue program execution. The debugger will report when the contents of n have changed.

CodeWatch> BREAKPOINT 119
CodeWatch> WATCH n /ACTION [C]
CodeWatch> CONTINUE

Input maximum prime boundary: 10
Program Stopped due to a Watchpoint
Watched variable N modified about line PRIMES\118
New Value: 10 {fixed bin (31))
Break at PRIME\119
Parent topic: CodeWatch Commands
Related information
Breakpoint
Watch


Detach

Use

Detaches from the currently attached process.

Command Syntax

DETACH

Description

Detaches CodeWatch from the currently attached process.

Note: The DETACH command may not be supported on some systems.
Parent topic: CodeWatch Commands
Related information
Attach
Kill
Load
Nload


Dstep

Use

Sets the default mode and/or action-list for Step.

Command Syntax

DSTEP [ IN|OVER ]
      [ BACTION | SACTION | BOTH ]
      [ [action-list] ]

where:

action-list
Specifies a set of one or more CodeWatch commands separated by semicolons

Description

The DSTEP command sets the default stepping mode to either In or Over called routines and/or sets the default action-list for Step. If Dstep is not used, Over is the default stepping mode.

The Baction, Saction, and Both default stepping modes are intended to be used to step to a user-specified breakpoint. You may specify that the breakpoint action list be executed (Baction), the default step action list be executed (Saction), or both action lists be executed (Both).

Example

In the following example, the default stepping mode is set to In and the PRINT command is set as the default action to be executed at each step. When the subsequent Step is executed, the current execution point is displayed and the current source line is printed.

CodeWatch> DSTEP IN [PRINT]
CodeWatch> STEP
Step at PRIMES.SIFT\%ENTRY
  76: sift: procedure(n);
Parent topic: CodeWatch Commands
Related information
Lstep
Step


Environment

Use

Sets the current evaluation environment.

Command Syntax

ENVIRONMENT [environment]

where:

environment
Can be a simple block name or a block name followed by an activation number or a statement identifier

Description

The ENVIRONMENT command sets the current evaluation environment to provide scope to the debugger for identifying variables and statements.

An activation number is used to establish, as an environment, an activation of a block other than the most recent one. If the environment argument is not specified, the evaluation environment is set to the environment containing the current execution point, and the current source file pointer is set to the current execution point. Whenever the environment changes during program execution, the evaluation environment is reset to the environment containing the current execution point.

Example

In the following example, the current evaluation environment is changed to PRIMES, and then it is reset to the previous evaluation environment by using Environment without any arguments.

CodeWatch> ENVIRONMENT PRIMES
CodeWatch> E n
N =                5 {fixed binary (31)}
CodeWatch> ENV
Environment reset to PRIMES.READ_INPUT
Parent topic: CodeWatch Commands
Related information
Lenvironment


Evaluate

Use

Evaluates and prints the resultant value of expressions.

Command Syntax

EVALUATE [[/display mode] expression]
EVALUATE [[/display mode]
         [     /NSDM    |    /NSMF  |
               /SDM     |    /SMF   |
               /SM      |    /NSM   |
               /DM      |    /MF    |
               /ALL     |    /INTERNAL]
         [     /DERIVED ]
         [     /PRIVATE    | /PUBLIC  |
               /PROTECTED  |  /ACCESSIBLE ]…

EVALUATE [/STRING c-char-ptr]
EVALUATE [/MACRO c-macro-defn]

where:

display mode
One of ASCII, BIT, FLOAT, HEX, INTEGER, or OCTAL
expression
Can be any expression that may occur in the source language program, including references to simple as well as aggregate (such as array, record, and structure elements) type variables
c-char-ptr
Is a C expression whose resultant type is char *
c-macro-defn
Is a C preprocessor macro definition name

Description

The EVALUATE command is used to evaluate and print the resultant value of expressions in the source language program. If the expression is omitted, Evaluate uses the previous expression that was evaluated. If no previous expression was evaluated, an error message is generated.

The display mode is the mode in which the value of the expression is to be printed. The valid display modes are Ascii, Bit, Float, Hex, Integer, and Octal. The display modes are defined in the table below.

Display
 | Mode Definition
AScii | Displays the value as a series of Ascii characters.
Bit | Displays each bit in the value as a 1 or a zero.
Float | Displays the value as a single-precision floating-point number.
Hex | Displays the value as a series of hexadecimal numbers.
Integer | Displays the value as a series of signed decimal numbers.
Octal | Displays the value as a series of unsigned octal numbers.

Example

In this example, the value of data items in the SIFT routine is evaluated.

CodeWatch> EVALUATE THIS_PRIME
THIS_PRIME =         7 {fixed binary (31))

In this example, a cross section of the array PRIMES from 1 to count -1, where count equals 4, is evaluated.

CodeWatch> EVALUATE PRIMES (1 : count - 1)
PRIMES(1) =              1 {fixed binary (31))
PRIMES(2) =              2 {fixed binary (31))
PRIMES(3) =              3 {fixed binary (31))
  • Changing Values of Variables
  • Array Evaluation
  • C Preprocessor Macros
  • Dereferencing C char Pointers
  • C Function Calls
Parent topic: CodeWatch Commands
Related information
Call
Let
Type


Changing Values of Variables

Using the command-line interface, it is possible to change the value of simple variables using the LET command.

Parent topic: Evaluate
Related information
Let


Array Evaluation

Array evaluation and array slice evaluation is possible depending on the language of the current environment. All of the language-specific chapters in this manual have an "Array Evaluation" section that describes how each particular language evaluates arrays.

Parent topic: Evaluate


C Preprocessor Macros

Using CodeWatch, it is possible to evaluate C preprocessor macro definitions. This is because the LPI-C compilers contains an integrated preprocessor rather than use a stand-alone separate preprocessor. This allows information about preprocessor macro definitions to be passed along to the debugger. The EVALUATE and TYPE commands will display the macro definition of the specified name.

In the case of name conflicts (that is, when a preprocessor macro definition follows a declaration or definition of a variable in the source file), then the debugger will display information about both the macro and the variable. If only information about the macro definition is desired, then you may specify the Macro option.

The display mode option has no effect on the display of a preprocessor macro definition. If the macro displayed is passed parameters, they are reported as <mac-param-1>, <mac-param-2>, and so on.

Parent topic: Evaluate


Dereferencing C char Pointers

The String option may be used to dereference C char pointers; This allows you to evaluate the null-terminated sequence of characters to which a C pointer points.

Parent topic: Evaluate


C Function Calls

If the expression to be evaluated includes a function call, then a subroutine call to the specified function will be made. Breakpoints are disabled during function calls when using the EVALUATE command. If you want a breakpoint in a called routine to be incurred, use the CALL command.

Parent topic: Evaluate


Find

Use

Locates and prints a specified string.

Command Syntax

FIND [/IGNORE] [string]

where:

string
Is a sequence of characters

Description

The FIND command locates a line in the source file containing a specified string and reports that line.

Quotation marks may be used to delimit the string but they are not required. If the string is not specified, the default value will be the string specified in the previous Find. If there is no string specified in the first instance of Find, an error message will be generated.

The debugger finds the first occurrence of the string after the current file position in the source file, then prints the line containing that occurrence of the string. By default, Find is case-sensitive, so that string "ABC" differs from "abc" and "Abc". When the ignore case option is turned on with Find, it is case-insensitive, so that the string "ABC" is the same as the string "abc" and "Abc".

If the string is not found, the current source file pointer is positioned at the last line of the user program.

Example

In this example, the string "main" is located.

CodeWatch> FIND main
 108:       /* main procedure */

If the string is not identical in terms of case to the string in the source file, it will not be found. For example:

CodeWatch> FIND MAIN
String not found: "MAIN"

In the following example, the search is case-insensitive.

CodeWatch> FIND /IGNORE MAIN
 108:       /* main procedure */
Parent topic: CodeWatch Commands
Related information
Point
Print


Goto

Use

Moves the execution pointer to a specified statement.

Command Syntax

GOTO statement-id

where:

statement-id
Can be a line number, a simple statement label, or a statement label followed by a line number offset or statement offset

Description

The GOTO command moves the execution pointer to a specified statement. Program execution resumes at this point when a Continue or Step is issued. The named statement must exist in the current program block.

Note:

It is not valid to put an activation number on the statement-id. If the activation number of an existing previous block invocation is put on the statement-id, it is ignored; otherwise, the following error message is displayed:

specified activation does not
             exist

It is not possible to use Goto to go to the %EXIT point of a block. The RETURN command, however, can be used to go to the %EXIT point.

When a Goto is executed, the debugger displays the current execution point.

Example

In this example, the execution point is changed to line 21 from the previous execution point as displayed by the Where command.

CodeWatch> WHERE
Current execution point is PRIMES.READ_INPUT\%ENTRY
CodeWatch> GOTO 21
Execution point is now PRIMES.READ_INPUT\21
Parent topic: CodeWatch Commands
Related information
Where
Continue
Step


Help

Use

Displays help text for debugger commands.

Command Syntax

HELP [command-name]

where:

command-name
Is the full spelling of a CodeWatch command or its accepted abbreviation

Description

The HELP command with no parameters lists all of the available CodeWatch commands. If the HELP command is followed by command-name, help text for that command is displayed.

Example

The following is an excerpt of the text displayed when invoking the HELP command with the BREAKPOINT command name abbreviation.

CodeWatch> HELP B
The BREAKPOINT command suspends execution to allow for debugger actions.

Command Syntax
         Breakpoint [ statement-id ]
                    [[action-list] ]
                    [/IF { logical-expr } [/ELse [action-list] ]]
                    [/Skip=n]
                    [/Ignore | /Nlgnore [/All]]
                    [/SILent | /NSILent]
Parent topic: CodeWatch Commands


Kill

Use

Kills the current child process.

Command Syntax

KILL

Description

Kills the current child process, and purges the CodeWatch internal symbol table.

Example

CodeWatch> KILL
Parent topic: CodeWatch Commands
Related information
Attach
Detach
Load
Nload


Lbreakpoint

Use

Lists information on breakpoints.

Command Syntax

LBREAKPOINT  [statement-id|/ALL ]

where:

statement-id
Names the statement at which the breakpoint is to be listed

Description

The LBREAKPOINT command lists information on a single breakpoint or on all breakpoints.

If the statement identifier is omitted, information is listed on the breakpoint at the current execution point. If /ALL is specified, information is listed on all breakpoints. The information listed includes the skip count, execution count (the number of times the breakpoint has been encountered) and any specified action-list.

Example

In this example, all breakpoints are listed.

CodeWatch> LBREAKPOINT /ALL
Break set at PRIMES\114 (count = 1)
Break set at PRIMES\119 (count = 2)
Break set at PRIMES.READ_INPUT\%ENTRY (count=1) [E maxv;]
Break set at PRIMES.ISPRIME\%ENTRY (count = 1)
Parent topic: CodeWatch Commands
Related information
Breakpoint
Nbreakpoint


Lcatch

Use

Lists Catch settings for a given signal.

Command Syntax

LCATCH [/ALL | signal]

where:

signal
Can be either a signal name mnemonic (such as SIGALRM, SIGINT, and so on) or the signal number corresponding to that signal. Signal names may be specified in either uppercase or lowercase letters. If neither a signal name nor /ALL command is specified, all of the signals currently set to be caught are displayed

Description

The LCATCH command with no arguments lists all of the signals that are currently set to be caught. When used with the /ALL option, LCATCH lists two sets of signals, those that are currently set to be caught and those that are currently set to not be caught. The LCATCH command, with a signal name specified, lists Catch settings for that given signal.

Example

In the following example, the current Catch settings for the signal SIGALRM are listed.

CodeWatch> LCATCH SIGALRM
SIGALRM not being caught.

In this example, the signals currently set to be caught and those that are set not to be caught are listed.

CodeWatch> LCATCH /ALL

CATCHing signals:

SIGINT SIGQUIT SIGILL SIGTRAP SIGIOT SIGEMT SIGFPE
SIGKILL SIGBUS SIGSEGV SIGSYS SIGPIPE SIGTERM SIGURG
SIGSTOP SIGTTIN SIGTTOU SIGIO SIGXCPU SICXFSZ SIGPROF
SIGVTALRM

Not CATCHing signals:
SIGHUP SIGALRM SIGTSTP SIGCONT SIGCHLD SIGWINCH SIGLOST
SIGUSR2
Parent topic: CodeWatch Commands
Related information
Catch
Ncatch


Lenvironment

Use

Lists the current evaluation environment.

Command Syntax

LENVIRONMENT [/ALL ] [/FULL]

Description

The LENVIRONMENT command lists the current evaluation environment.

The All option lists all environments within the source file.

The Full option lists the current environment, the first and last source file line numbers in that environment, and the text offsets for the beginning and end of code in that environment. The offsets correspond to those found in the expanded listing generated by the Compiler.

Example

In this example, the current evaluation environment displayed is PRIMES.READ_INPUT.

CodeWatch> LENVIRONMENT
Evaluation environment is PRIMES.READ_INPUT
Parent topic: CodeWatch Commands
Related information
Environment


Let

Use

Assigns a value of an expression to a name.

Command Syntax

LET name = expression

where:

name
Is the name of any variable or destination construct (such as a substring or based reference in PL/I) that occurs in the source language program
expression
Can be any expression allowed by the source language whose value can be converted to the data type of the named variable

Description

The LET command assigns a value of an expression to a name. When the expression is evaluated, appropriate type conversions are performed. The resultant value is assigned to the named variable. If the type conversion is illegal, the debugger will issue an error message.

The value of a character string constant can be changed by enclosing the expression within single or double quotation marks, depending on the source language.

In C, assignments are merely expression operators with side effects. Therefore, Evaluate provides the same functionality as Let in other languages.

Breakpoints are disabled during function calls using the LET command. If you want a breakpoint in a called routine to be incurred, use the CALL command.

Example

In this example, the value of MAXV is assigned a new value (MAXV/ 2).

CodeWatch> EVALUATE MAXV
MAXV =             10 {fixed binary (31))
CodeWatch> LET MAXV = MAXV/2
CodeWatch> EVALUATE MAXV
MAXV =              5 [fixed binary (31))
Parent topic: CodeWatch Commands
Related information
Arguments
Call
Evaluate


Lmacro

Use

Lists the macro definitions.

Command Syntax

LMACRO { macro1, macro2, ..., macron | /ALL }

Description

The LMACRO command lists the definition of one or more specified macros or the definitions for all currently defined macros. The debugger lists the action-list that was defined for the macro. Either the indicated macro-name(s) or /ALL must be specified.

Example

In this example, all of the macro definitions are listed.

CodeWatch> LMACRO /ALL
FIG = [FIND /IGNORE]
INFO = [LB /A; LENV; LMA /A; WHERE]
Parent topic: CodeWatch Commands
Related information
Macro
Nmacro


Load

Use

Loads the symbol table from a specified file as the primary executable file.

Command Syntax

LOAD filename

Description

The LOAD command loads the symbol table from filename into CodeWatch as the primary executable file for debugging. It also purges the internal CodeWatch symbol table of any previously loaded executable files or shared libraries.

Example

CodeWatch> LOAD myprog.out
Parent topic: CodeWatch Commands
Related information
Attach
Detach
Kill
Nload


Log

Use

Logs debugger commands and, optionally, output to a specified file or files.

Command Syntax

LOG [/FuLL]filename

where:

filename
Is the pathname of any file allowing write permission to the user

Description

The Log command causes all subsequent debugger commands to be appended to the specified file.

The /FULL option specifies that all output from the debugger be logged to the specified file in addition to all debugger commands. It is possible to log commands to one file and commands-and-output to another file. This would be done by the commands:

CodeWatch> LOG filel
CodeWatch> LOG /FULL file2

The NLOG command takes an optional file name that tells the debugger which log session to stop. If no file name is given, the debugger will first check if commands are being logged to a file (no /FULL). If so, that log session is stopped. If there is no such log session, the debugger checks to see if commands-and-output to a file (/FULL) are being logged. If so, that log session is stopped.

Example

CodeWatch> LOG temp
CodeWatch> FIND Main
77 REM       ** Main Program **
CodeWatch> BREAKPOINT 89
CodeWatch> PRINT 20
   77:            REM    ** Main Program **
   78:            INTEGER max_value, max_primes, n
   79:            REM      REAL a
   80:
   81:            max_value  = 1000
   82:            max_primes = 500
CodeWatch> NLOG
Ending debugger command logging to "temp"
CodeWatch> !cat temp
FIND Main
BREAKPOINT 89
PRINT 20
Parent topic: CodeWatch Commands
Related information
Nlog
Read


Lreturn

Use

Lists the return value of a function.

Command Syntax

LRETURN

Description

When the current execution point is at the exit point of a function, Lreturn prints the value to be returned by the function.

Example

In this example, the return value for the PRIMES function is listed.

CodeWatch> LRETURN
Return value for PRIMES is 15 {fixed binary (31)}
Parent topic: CodeWatch Commands
Related information
Return


Lsource

Use

Prints the name of the current source file being displayed.

Command Syntax

LSOURCE [/ALL] [/FULL]

The All, Full, Both, and Map buttons access the Lsource dialog. The Lsource dialog is for information only and no action may be executed. Specifying the Both button is the same as specifying both the /ALL and /FULL command-line options.

Description

The LSOURCE command prints the name of the source file currently being displayed as well as the time and date of its creation. If the source file being displayed does not contain the current evaluation environment, Lsource also displays the source file that does contain the current evaluation environment.

If the Full option is specified, the name of the symbol table file associated with the source file containing the current evaluation environment will also be displayed. If the All option is specified, all of the source files in the program being debugged that were compiled in debug mode will be displayed.

Example

In this example, the name of the symbol table file associated with the source file containing the current evaluation environment, the source file, and the source file currently being displayed are listed.

CodeWatch> LSOURCE
Current display source file is "primes.pl1" (PL/I) Apr 11 11:06:51 1991
Parent topic: CodeWatch Commands
Related information
Source


Lstep

Use

Lists the current stepping mode and the default action-list.

Command Syntax

LSTEP

Description

The LSTEP command lists the current mode of stepping, that is, either In or Over, the default action-list, and the default action-list to be executed when stepping to a breakpoint.

Example

In this example, the default stepping mode is in, the step action-list contains the Print command, and the action-list that will be executed upon stepping to a user breakpoint is the step action (Print).

CodeWatch> LSTEP
Step IN; Execute STEP action
Action = [PRINT;]
Parent topic: CodeWatch Commands
Related information
Dstep
Step


Ltrace

Use

Lists the current tracing mode.

Command Syntax

LTRACE

Description

The LTRACE command lists the current mode of tracing, that is, statement and/or entry.

Example

In this example, the current tracing mode is listed. Note that no conditional expression is specified.

CodeWatch> LTRACE
TRACE ENTRY [C;] /IF {}
Parent topic: CodeWatch Commands
Related information
Ntrace
Trace Entry
Trace Statement


Lwatch

Use

Lists information on watchpoints.

Command Syntax

LWATCH {variable|/ALL}

where:

variable
Specifies a variable in the source program

Description

The LWATCH command lists information on the given watchpoint. If /ALL is specified, information is listed on all watchpoints. The information listed includes the skip count, execution count (the number of times the watchpoint has been incurred), specified switch settings, and any specified action-list.

Example

In the following example, all of the existing watchpoints are listed.

CodeWatch> LWATCH /ALL
Watchpoint set for N (count = 1) /NSILENT /NIGNORE [C;]
Parent topic: CodeWatch Commands
Related information
Nwatch
Watch


Macro

Use

Defines a macro.

Command Syntax

MACRO macro-name = [action-list]

where:

action-list
Specifies a set of one or more CodeWatch commands separated by semicolons

Description

The MACRO command is used to define a macro as shorthand for an action-list. Sixty-four macros can be defined at any one time.

Note: Do not choose a macro name that is the same as a debugger command name, because the macro name will override the debugger command.

The action-list is specified in the usual way.

Once a macro has been defined, its name may be used just like any other debugger command name. The macro in the command line is replaced by the debugger commands specified in the action-list. Those commands are then executed normally.

If the last (or only) command in the action-list does not end with a semicolon, any additional arguments to that command can appear on a command line after the macro name. For example, suppose the following macro has been defined:

FOO = [ LET A = A + ]

The command FOO 3 can then be entered to add 3 to A.

Example

In this example, the macro info is defined that lists all breakpoints, the current evaluation environment, all macros, and the current execution point.

CodeWatch> MACRO info = [LB /ALL; LENV; LMACRO /ALL; WHERE]
CodeWatch> info
Break set at PRIME\118 (count = 2)
Break set at PRIMES.READ_INPUT\%ENTRY
Break set at PRIME.ISPRIME\%ENTRY (COUNT = 1)
Evaluation environment is PRIMES.ISPRIME
   info = [LB /ALL; LENV; LMA /ALL; WHERE]
Current execution point is PRIMES.ISPRIME\%EXIT

In the following example, the macro fig is defined to perform a case-insensitive search for the string you wish to specify as an argument.

CodeWatch> MACRO fig = [FIND /IGNORE]
CodeWatch> fig MAIN
  /* Main program */
Parent topic: CodeWatch Commands
Related information
Using Action Lists
Lmacro
Nmacro
Read
Save


Nbreakpoint

Use

Removes breakpoints.

Command Syntax

N BREAKPOINT [statement-id | /ALL ]

where:

statement-id
Is used to name the statement at which the breakpoint is to be removed

Description

The NBREAKPOINT command removes the breakpoint at the specified statement.

If the statement-id is omitted, the breakpoint at the current execution point is removed. If /ALL is specified, all breakpoints currently set are removed.

Example

In the following example, the breakpoint at line 94 is removed.

CodeWatch> NB 94

In the following example, all breakpoints are removed.

CodeWatch> NBREAKPOINT /ALL
Parent topic: CodeWatch Commands
Related information
Breakpoint
Lbreakpoint


Ncatch

Use

Prevents process control from returning to the debugger when the given signal is generated.

Command Syntax

NCATCH signal

where:

signal
Can be either a signal name mnemonic (such as SIGALRM, SIGINT, and so on) or the signal number corresponding to that signal. Signal names may be specified in either uppercase or lowercase

Description

The NCATCH command prevents process control from returning to the debugger when the given signal is generated. The child (user) process continues without interruption, as if the given signal had been generated. This implies that user-defined handlers will be executed.

Example

In the following example, the process control will not return from the child process to the debugger when a SIGALRM is generated.

CodeWatch> NCATCH SIGALRM
Changing SIGALRM to now not be caught.

As a result, Ncatch allows the child process to continue uninterrupted when a SIGALRM is generated. If the user process has its own signal handler for a SIGALRM, that signal handler will be executed.

Parent topic: CodeWatch Commands
Related information
Catch
Lcatch


Nload

Use

Kills the current child process.

Command Syntax

NLOAD

Description

Kills the current child process and purges the CodeWatch internal symbol table.

Example

CodeWatch> NLOAD
Parent topic: CodeWatch Commands
Related information
Attach
Detach
Kill
Load


Nlog

Use

Stops the logging of debugger commands and/or commands-and-output to a file or files.

Command Syntax

NLOG [filename]

where:

filename
Is the name of a log file specified in a previous LOG command

Description

The NLOG command ceases logging of debugger commands or commands-and-output to a file or files specified in the previous LOG command.

Example

CodeWatch> LOG temp
CodeWatch> FIND Main
77  REM      ** Main Program **
CodeWatch> BREAKPOINT 89
CodeWatch> PRINT 20
   77:           REM      ** Main Program **
   78:            INTEGER max_value, max_primes, n
   79:           REM      REAL a
   80:
   81:            max_value  = 1000
   82:            max_primes = 500
CodeWatch> NLOG
Ending debugger command logging to "temp"
The file "temp" will contain
CodeWatch> !cat temp
FIND Main
BREAKPOINT 89
PRINT 20
Parent topic: CodeWatch Commands
Related information
Log
Read


Nmacro

Use

Removes macro definitions.

Command Syntax

NMACRO {macro1, macro2, …, macron, | /ALL }

Description

The NMACRO command removes the definition of one or more specified macros or the definitions of all currently defined macros. Either the specific macro name(s) or /ALL must be specified.

Example

In this example, the macro named info is removed.

CodeWatch> NMACRO info

In this example, all macro definitions are removed.

CodeWatch> NMACRO /ALL
Parent topic: CodeWatch Commands
Related information
Lmacro
Macro


Nmap

Use

Reads the dynamic loader map and displays information about the currently loaded shared libraries.

Description

Shared library debugging has these limitations: CodeWatch does not dynamically monitor the dynamic load map. If a shared library is loaded into CodeWatch via the SHLIB command, and that library is being programmatically loaded and unloaded, you must manually load and unload the symbols via SHLIB and NSHLIB, since there is no guarantee that the library will always be mapped to the same virtual address. However, use of the NMAP command and noting load addresses will indicate whether this is actually necessary.

Parent topic: CodeWatch Commands


Nshlib

Use

Purges the symbols of the shared library specified by slibfile from the CodeWatch internal symbol table.

Parent topic: CodeWatch Commands


Ntrace

Use

Disables entry or statement tracing.

Command Syntax

NTRACE {ENTRY | STATEMENT}

Description

The NTRACE command disables entry or statement tracing. If ENTRY is specified, any action-list and condition are removed as well.

Example

In this example, TRACE STATEMENT is disabled.

CodeWatch> NTRACE STATEMENT
Parent topic: CodeWatch Commands
Related information
Ltrace
Trace Entry
Trace Statement


Nwatch

Use

Removes watchpoints.

Command Syntax

NWATCH {variable|/ALL}

where:

variable
Specifies the variable being watched

Description

The NWATCH command removes the watchpoint for the given variable. If /ALL is specified, all watchpoints currently set are removed.

Example

In the following example, the watchpoint for the variable n is removed from the current listing.

CodeWatch> LWATCH /ALL
Watchpoint set for n (count = 1) /NSILENT /NIGNORE [C;]
CodeWatch> NWATCH n
CodeWatch> LWATCH /ALL
No watchpoints are currently set.
Parent topic: CodeWatch Commands
Related information
Lwatch
Watch


Peek

Use

Displays the contents of a specified area of user memory in a specified format.

Command Syntax

PEEK [/TEXT  | /DATA]
     [/HEX   | /DECIMAL  | /OCTAL]
     [/LONG  | /SHORT    | /BYTE]
     [/count] address

where:

count
Is a numeric constant
address
Is a numeric constant. (For format information, see the following Description section.)

Description

The PEEK command displays the contents of a designated amount of user program memory in a designated format starting at a given address.

If the Text option is specified, the user text segment of the program is read. If the Data option is specified, the user data segment of the program is read. The Data option is the default.

The base of the displayed memory may be specified as being hexadecimal, decimal, or octal, depending on the options Hex, Decimal, or Octal, respectively. Hex is the default.

The size of each displayed memory unit may be specified as being 4 bytes (32 bits), 2 bytes (16 bits), or 1 byte (8 bits) by specifying the options Long, Short, or Byte, respectively. When the option Byte is specified, the ASCII representation of the byte is also displayed. Long is the default.

The number of memory units to be displayed may be specified by using the Count option. This consists of a slash "/" followed by a decimal number. A count of one is the default.

The format of the given address may be either hexadecimal, decimal, or octal, depending on how it is written. A hexadecimal number must begin with a 0x or 0X or contain at least one of the hexadecimal digits "a" through "f" (case in-sensitive). An octal number must begin with a 0 and contain only octal digits "0" through "7". A decimal number may contain only any of the decimal digits "0" through "9".

Example

The following PEEK command displays five lines (4-bytes) in hexadecimal format beginning at address 0x23d8.

CodeWatch> PEEK /5 0x23d8
0x000023D8: 0x4E4141EE
0x000023DC: 0xFFE42F08
0x000023E0: 0x6100FDF6
0x000023E4: 0x584F4E71
0x000023E8: 0x4E71F236
Parent topic: CodeWatch Commands
Related information
Evaluate
Poke
Watch


Point

Use

Resets and displays the source file pointer within the current source file.

Command Syntax

POINT [+n|–n|n]

where:

n
Is the line number you specify

Description

The POINT command relocates the source file pointer within the current source file and prints that line.

If a sign is specified, the debugger relocates the source file pointer to the line that is n lines before (–) or after (+) the current source file pointer. Otherwise, the debugger relocates the source file pointer to the line specified by n. The debugger then prints out the new pointed to line. If n is omitted, the source file pointer is reset to the current execution point, and that line is printed.

Example

In the following example, the source file pointer is reset to line 116 and displayed.

CodeWatch> POINT 116
  116:  call read input (n);

In this example, the source file pointer is reset to two lines before the current source file pointer, and that line is displayed.

CodeWatch> POINT -2
  114:  put skip (2);
Parent topic: CodeWatch Commands
Related information
Print


Poke

Use

Changes the contents of a specified area of user memory in a specified format.

Command Syntax

POKE [/TEXT | /DATA]
     [/FLOAT| /DOUBLE| /LD]
     [/LONG | /SHORT | /BYTE]
     address-expr, data-expr

where:

address-expr
Is an expression specifying the memory location to examine. (To find the syntax of an address expression, type HELP Dis.)
data-expr
Is an expression specifying the section of memory Poke changes. The data segment is the default

Description

The /BYTE, /SHORT, and /LONG options, used with integer values, specify the size of memory to be altered (1, 2, or 4 bytes, respectively). /LONG is the default.

The /FLOAT, /DOUBLE, and /LD options, used with floating point values, specify the size of memory to be altered (4, 8, or 12 bytes, respectively).

Example

The following POKE command stores the hexadecimal value 99 at address 0x7FFFE480.

CodeWatch> POKE /TEXT 0x7FFFE48 99
Parent topic: CodeWatch Commands
Related information
Evaluate
Peek
Watch


Print

Use

Terminates a debugging session.

Command Syntax

QUIT

Description

Quit causes termination of the debugging session. Selecting the Exit item in the File menu is equivalent to issuing the QUIT command.

Example

This example shows the message the debugger displays as it exits.

CodeWatch> QUIT
CodeWatch Quit ... Bye!
Parent topic: CodeWatch Commands
Related information
Save


Read

Use

Reads and executes debugger commands from a specified file.

Command Syntax

READ filename

where:

filename
Is any file containing debugger commands. If the file is not in the current working directory, its pathname must be specified

Description

The READ command is used to execute debugger commands, which are contained in the specified filename. Each command is printed to the terminal as it is executed. Seven levels of Read commands may be nested in debugger command files.

Example

In this example, debugger commands are read in from a file called dbg. After all the commands are read and executed, the debugger prompts for the next command to be entered.

CodeWatch> READ dbg
**** Reading commands from "dbg" ...
CodeWatch> BREAKPOINT PRIMES\119 /SKIP=0
CodeWatch> BREAKPOINT PRIMES.READ_INPUT\%ENTRY /SKIP=0 [e maxv;]
CodeWatch> BREAKPOINT PRIMES.ISPRIME\%ENTRY /SKIP=0
CodeWatch> BREAKPOINT PRIMES.PRINT_OUT\60 /SKIP=0
CodeWatch> BREAKPOINT PRIMES.PRINT_OUT\59 /SKIP=0
CodeWatch> MACRO info=[ lb /a;lenv;lma /a; where ]
CodeWatch>
**** Done reading commands from "dbg"
Parent topic: CodeWatch Commands
Related information
Log
Nlog
Save


Registers

Use

Displays the contents of the general machine registers.

Command Syntax

REGISTERS

Description

The REGISTERS command displays the contents of all the machine registers as long hexadecimal values. Floating-point registers may or may not be displayed, depending on the target.

Example

The following input from the REGISTERS command is target-specific and may not match what is displayed on your system.

CodeWatch> REGISTERS

D0: 0x0000003C D1: 0x00000004 D2: 0x00000001 D3:0x00000000
D4: 0x00000000 D5: 0x00000000 D6: 0x00000000 D7:0x00000000
A0: 0x0EFFFD94 A1: 0x0002037C A2: 0x00000000 A3:0x0EFFFDC8
A4: 0x0EFFFDD0 A5: 0x00000000 A6: 0x0EFFFDB0 A7:0x0EFFFD90
SR: 0x00000000 PC: 0x000023D8

FO: 0x7FFF0000FFFFFFFFFFFFFFFF F1: 0x7FFF0000FFFFFFFFFFFFFFFF
F2: 0x7FFF0000FFFFFFFFFFFFFFFF F3: 0x7FFF0000FFFFFFFFFFFFFFFF
F4: 0x7FFF0000FFFFFFFFFFFFFFFF F5: 0x7FFF0000FFFFFFFFFFFFFFFF
F6: 0x7FFF0000FFFFFFFFFFFFFFFF F7: 0x7FFF0000FFFFFFFFFFFFFFFF

FPCR: 0x0000F400 FPSR: 0x00000000 FPIAR: 0x00000000
Parent topic: CodeWatch Commands


Reload

Use

Reloads the user program.

Command Syntax

RELOAD [/ARGUMENTS command-line-arguments]
       [/NEWARG command-line-arguments]
       [< filename]
       [> filename]

where:

command-line-arguments
Is a list of text strings to be passed to the user program as its arguments. This must be the last option on the RELOAD command line
filename
Is the pathname of any file

Description

The RELOAD command will reinitialize the user program while preserving any explicitly set breakpoints and any associated action lists. All breakpoint counters will be reset to zero.

A subsequent Continue or Step will execute the user program from the beginning.

Example

In this example, the debugging session is restarted in the original evaluation environment, with all breakpoints preserved and without returning to the system level.

CodeWatch> RELOAD
Command line : "primes"
Reloading..ok
Initial evaluation environment is PRIMES:(inactive)
CodeWatch>

In this example, user program output is redirected to the file primes.out

CodeWatch> RELOAD > primes.out
Reloading..ok
Initial evaluation environment is PRIMES:(inactive)
CodeWatch>
  • Changing Command-line Arguments
  • Redirecting User Program I/O
  • Redirecting I/O Back to the Terminal
Parent topic: CodeWatch Commands
Related information
Arguments
Continue
Step


Changing Command-line Arguments

If the Arguments option is not specified, the program will be initialized with the command-line arguments specified when CodeWatch was invoked. If the Arguments option is specified, the given arguments will be used as command-line arguments to the reinitialized program. If more than one argument is specified, they must be separated by a space. These command-line arguments will be in effect until the next time the program reloads.

If you want to permanently change the command-line arguments of the program being debugged, that is, for the remainder of the debugging session, this is possible using the /NEWARG command-line option. This specifies that the given command-line arguments be used for the remainder of the debugging session. These may be reset by again using the /ARGUMENTS or /NEWARG command-line options.

Parent topic: Reload


Redirecting User Program I/O

User program input may be redirected by either specifying the command-line option < filename or by entering a file name in the Stdin edit field of the Reload dialog box.

User program output may be redirected by either specifying the command-line option > filename or by entering a file name in the Stdout edit field of the Reload dialog box. Any error opening filename for either input or output will result in an error message and CodeWatch exiting.

Note:

In the RELOAD command-line syntax, there must be a space between the "<" or the ">" and the file name.

By default, user input and output is redirected to and from the xterm window from which CodeWatch was invoked. However, this may be changed using the RELOAD command.

Parent topic: Reload


Redirecting I/O Back to the Terminal

It is possible to redirect input or output back to the terminal after having redirected it elsewhere. To do this, specify the following:

RELOAD < /dev/tty

or:

RELOAD > /dev/tty

for input and output, respectively.

Parent topic: Reload


Return

Use

Transfers the execution pointer to the exit point of the current procedure and allows a return value to be set.

Command Syntax

RETURN [expression]

where:

expression
Can be any expression that may occur in the source language program, including references to simple as well as aggregate (such as array, record, and structure elements) type variables

Description

The RETURN command transfers the current execution pointer to the exit point (%EXIT) of the current procedure. If the procedure returns a value, an expression indicating the return value must be given. An expression should not be given if the procedure does not return a value.

If the current execution point is already at the exit point of the current procedure, no action is taken if the procedure does not return a value, or the return value is set to the given expression if the procedure does return a value.

Example

In this example, the return value of the ISPRIME routine is set to "15".

CodeWatch> RETURN 15
CodeWatch> LRETURN
Return value for PRIMES.ISPRIME is 15 {fixed binary(31)}
Parent topic: CodeWatch Commands
Related information
Lreturn


Save

Use

Writes out commands to reset all currently set breakpoints, watchpoints, and/or macros to a specified file.

Command Syntax

SAVE [{/BREAKPOINT |/WATCH |/MACRO}…|/ALL]
     filename

where:

filename
Is the specified file that will contain the breakpoints, watchpoints, and/or macros settings

Description

The SAVE command writes out commands to a specified disk file to reset all current breakpoint, watchpoint, and/or macro settings for use in a later debugging session. The file can be read in by using the READ command.

If no options or the All option is specified, commands to reproduce all breakpoint, watchpoint, and macro settings will be written to the specified file.

If the Breakpoint option is specified, the breakpoint commands for all current breakpoint settings will be written to the specified file. If the Watch option is specified, the watchpoint commands for all current watchpoint settings will be written to the specified file. If the Macro option is specified, the macro commands for all current macros will be written to the specified file. Any combination of Breakpoint, Watch, and Macro may be used.

The SAVE command will create, not append, the specified file. If the file already exists, the Save will fail and an error will be issued. For more information, see the section Read.

Example

In this example, two debugging sessions are used to demonstrate the SAVE command. In the first session, macros, breakpoints, and watchpoints are saved in the dbg file; in the second session, the saved commands are read from the dbg file.

Session one:

$ cwcmd primes
CodeWatch setting up "primes". Wait...

CodeWatch> BREAKPOINT PRIMES\114
CodeWatch> BREAKPOINT PRIMES\119
CodeWatch> BREAKPOINT PRIMES.READ_INPUT\%ENTRY [E maxv;]
CodeWatch> BREAKPOINT PRIMES.ISPRIME\%ENTRY
CodeWatch> WATCH N /ACTION [C;]
CodeWatch> MACRO fig = [FIND /IGNORE]
CodeWatch> MACRO info=[ LB /A;LENV;LMA /A; WHERE ]
CodeWatch> SAVE dbg
Environment saved to file "dbg"
CodeWatch> QUIT

Session two:

$ cwcmd primes
CodeWatch setting up "primes". Wait...

CodeWatch> READ dbg
**** Reading commands from "dbg" ...
CodeWatch> BREAKPOINT PRIMES\114 /SKIP=0
CodeWatch> BREAKPOINT PRIMES\119 /SKIP=0
CodeWatch> BREAKPOINT PRIMES.READ_INPUT\%ENTRY /SKIP=0 [E maxv;]
CodeWatch> BREAKPOINT PRIMES.ISPRIME\%ENTRY /SKIP=0
CodeWatch> WATCH N /ACTION [C;]
CodeWatch> MACRO fig = [FIND /IGNORE]
CodeWatch> MACRO info = [ LB /A;LENV;LMA /A; WHERE ]
CodeWatch>
**** Done reading commands from "dbg"
Parent topic: CodeWatch Commands
Related information
Read
Breakpoint
Macro
Watch


Shlib

Use

Loads the symbols from the specified shared library, slibfile, into the CodeWatch internal symbol table.

Description

If slibfile was compiled using the -deb option, the command ENV will enable the display of the shared library source and other normal symbolic debugging.

If slibfile is specified with a simple filename, such as file.sl, CodeWatch first searches the current directory for this shared library. Failing that, it uses the search path indicated by the LD_LIBRARY_PATH environment variable on Solaris 2 (which is the same variable that is used by the dynamic loader). If the -L option was used at link time to specify library locations, slibfile must specify the full pathname for the shared library.

Parent topic: CodeWatch Commands


Source

Use

Changes the current source file to be displayed.

Command Syntax

SOURCE [filename]

where:

filename
Is the name of the source file to be displayed

Description

The SOURCE command changes the source file to be displayed. This may be used, for instance, when you want to look at the contents of "COPY" or "INCLUDE" files. Referencing these files is discussed in the section Referencing Included or Copied Files in the chapter Debugging Concepts.

If the filename is omitted, the current source file is set to the source file associated with the current execution point. The current source file pointer is not explicitly set. To reset the current source file pointer to the current execution pointer, use Environment without any arguments.

Activation of the SOURCE command applies to the current debugger action only. Its effect is lost when the program resumes execution; that is, the current source file is set to the source file associated with the current execution point.

Example

In the following example, the source file from which lines are to be displayed is var.in. The LSOURCE command prints the name of the current source file as well as the name of the source file for the current environment, because it is different.

CodeWatch> SOURCE var.in
CodeWatch> LSOURCE
Current display source file is "var.in"
Source file of current environment is "x.pl1"
Current display source file is "var.in" (PL/I) Apr 11 11 :06 :51 1991
Parent topic: CodeWatch Commands
Related information
Referencing Included or Copied Files
Lsource


Stack

Use

Displays information on a specified number of stack frames.

Command Syntax

STACK [nframes|/ALL]
      [/FULL]
      [/ARGUMENTS]
      [/LOCALS]

where:

nframes
Is an integer specifying the count of the most recent stack frames to be displayed

Description

The STACK command is used to display information on a specified number of stack frames.

If the All option is specified, all stack frames back to your main program are displayed. There are typically a number of system start-up routines called before your main program. The frames for these start-up routines will not be displayed unless the Full option is specified. The Full option is useful only if specified in conjunction with a specified Count or the All option. If neither a specified Count nor the All option is present, only the current stack frame is displayed.

If the Arguments option is specified, the arguments to each procedure are displayed.

If the Locals option is specified, all local variables for each stack frame are displayed.

Example

In this example, information is displayed on all stack frames and the arguments to each procedure.

CodeWatch> STACK /ARGUMENT /ALL

Stack contains 5 frame(s).
Current execution point is PRIMES.SIFT\94

5: Owner is "PRIMES.SIFT"
   Arguments:
     N = 10 {fixed binary (31)}
   Called from PRIMES\119

4: Owner is "PRIMES"
   Arguments: None
   Main program
Parent topic: CodeWatch Commands
Related information
Arguments
Environment


Step

Use

Executes a specified number of statements.

Command Syntax

STEP [OUT]
     [IN|OVER]
     [count]
     [[action-list]]

where:

count
Is an integer specifying the number of statements to be executed

Description

action-list specifies a set of one or more CodeWatch commands separated by semicolons.

The STEP command starts program execution at the current location of the execution pointer and stops execution after one or a specified number of statements.

To execute a single statement, use Step with no options specified. To execute a number of statements, specify a count parameter.

If Step Out is specified, the debugger steps to the exit point of the current routine. If Step Out is specified with a count parameter, the first step is to the exit point of the current routine, and each step thereafter is to a succeeding statement in the calling routine. Thus, if the execution pointer is in a called routine and you want to step to the next executable statement in the calling routine, issue STEP OUT 2. The first step is to the exit point of the current routine, and the second step returns and steps forward in the calling routine. If the execution pointer is already at the exit point of the called routine, issuing Step Out causes the execution pointer to step to the exit point of the calling routine.

If Step In is specified and the current execution point is at a subroutine call, the debugger steps to the entry point of the called routine. If Step In is specified with a count parameter, the entry point is the first step, the first executable statement is another, and so on.

If Step Over is specified, the debugger steps over calls to routines. Step Over is the default mode for the STEP command.

If an action-list is present, it is performed at the last step and is set as the action to be taken for any other Step. To remove the Step action-list, supply a null action-list as an argument to Step. Use the DSTEP command to do this without stepping.

At the completion of a step operation, the debugger issues a message indicating the current execution point in the following format:

Step at x

where x is the location of the current execution point, that is, the statement that is about to be executed.

Note:

Step cannot be used when the current execution point of the user program is at a non-local Goto.

Example

In the following example, the default stepping mode is set to step in and the stepping action-list is set to print the current source line. Two step commands are executed (the second command with a count of 2).

CodeWatch> DSTEP IN [P]
CodeWatch> STEP
Step at PRIMES.SIFT\95
  95: primes(count) = this_prime;
CodeWatch> S 2
Step at PRIMES.SIFT\97
  97: do while (k < n);

In the following example, the debugger steps out of the sift routine.

CodeWatch> STEP OUT
Number of primes found was (prime) 5

1  2  3    5  7

Step at PRIMES.SIFT\%EXIT
  106: end sift;
Parent topic: CodeWatch Commands
Related information
Continue
Dstep
Lstep


Trace Entry

Use

Displays all procedure and block entries information during program execution.

Command Syntax

TRACE ENTRY [[action-list]]
            [/IF {logical-expr}]

where:

action-list
Specifies a set of one or more CodeWatch commands separated by semicolons
logical-expr
Can be any expression that may occur in the source language program, including references to simple as well as aggregate (such as array, record, and structure elements) type variables, returning a boolean value

Description

Tracing enables information about all procedure and block entries to be reported as the program executes.

The TRACE ENTRY command sets tracepoints, which enable tracing of all procedure and block entries by printing a message each time a procedure or block is entered.

When entry tracing is enabled, the debugger will be activated as each procedure or block is entered, and activated again as each procedure or block is exited. The specified action-list applies only to the entry tracepoint; exit tracepoints always print a message and continue.

If an action-list is specified, the debugger will process the commands and print the results. If an action-list is omitted, a default action-list of [CONTINUE] is supplied. A common action-list is [ARGUMENTS; CONTINUE]. An action-list may not refer to statements or variables in a way that is dependent on scope. To take a breakpoint and enter interactive debugging at each entry, supply an explicit null action-list, that is, TRACE ENTRY [ ] .

If a conditional expression is specified, each time an entry point is reached, the value of the expression is evaluated, and if it is true, the message is printed; if it is false, no message is printed.

Example

In the following example, entry tracing is turned on and program execution is continued.

CodeWatch> TRACE ENTRY
CodeWatch> C
Input maximum prime boundary: 10
**** PRIMES.READ_INPUT\%EXIT
Break at PRIMES\119
  • Animating the Program in the Source Window
Parent topic: CodeWatch Commands
Related information
Continue
Ltrace
Ntrace
Trace Statement


Animating the Program in the Source Window

In the graphical interface, the TRACE ENTRY command is especially useful because it allows you to watch your code execute. Rather than simply issuing a message as entry and exit points are reached, CodeWatch updates the Source window with the source file for the current environment and highlights the line corresponding to each entry or exit point.

Parent topic: Trace Entry


Trace Statement

Use

Displays each source statement as it is executed.

Command Syntax

TRACE STATEMENT

Description

The TRACE STATEMENT command sets tracepoints, which enable the tracing of every statement by printing a message identifying the statement.

At each statement, if there is no other action to be performed (that is, if there is no breakpoint, entry trace, single step action, and so on), the identifying message is printed and execution continues.

Example

In the following example, statement tracing is turned on and program execution is continued.

CodeWatch> TRACE STATEMENT
CodeWatch> CONTINUE
**** PRIMES\112
**** PRIMES\113
Break at PRIMES\114
  • Animating the Program in the Source Window
Parent topic: CodeWatch Commands
Related information
Continue
Ltrace
Ntrace
Trace Entry


Animating the Program in the Source Window

In the graphical interface, the Trace Statement command is especially useful because it allows you to watch your code execute. Rather than simply issuing a message as statements are reached, CodeWatch updates the Source window with the source file for the current environment and highlights each line as it executes.

Parent topic: Trace Statement


Type

Use

Displays the resultant type of an expression.

Command Syntax

TYPE [/FULL] expression

where:

expression
Can be any expression that may occur in the source language program, including references to simple as well as aggregate (such as array, record, and structure elements) type variables

Description

The TYPE command prints the resultant type of an expression.

If the expression refers to a structure or record, the Full option can be used to display the entire structure or record.

Example

In the following example, declaration information about various data items is displayed.

CodeWatch> TYPE COUNT
COUNT fixed binary (31) automatic
CodeWatch> TY FLAGS
FLAGS(1:1000) bit (1) automatic
Parent topic: CodeWatch Commands


Watch

Use

Sets watchpoints on specified variables.

Command Syntax

WATCH variable
      [/SILENT|/NSILENT]
      [/IGNORE|/NIGNORE]
      [/SKIP=n]
      [/ACTION[action-list]
      [/IF{logical-expr}]

where:

variable
Specifies the variable to be watched
n
Is the value you assign to the skip counter
action-list
Specifies a set of one or more CodeWatch commands separated by semicolons
logical-expr
Can be any expression that may occur in the source language program, including references to simple as well as aggregate (such as array, record, and structure elements) type variables, returning a boolean value

Description

Watchpoints are used to monitor any changes to data. The WATCH command designates the given variable to be watched. When the contents of the watched variable change, program execution stops and control is returned to the debugger.

  • Suppressing the Watchpoint Message
  • Temporarily Ignoring Watchpoints
  • Skipping a Watchpoint Multiple Times
  • Watchpoints with Action Lists
  • Conditional Watchpoints
  • Incurring Watchpoints
Parent topic: CodeWatch Commands


Suppressing the Watchpoint Message

The Silent option will not output modified variables when a watchpoint is encountered; the output simply reports that the program has stopped because of a watchpoint. Turning off the Silent option allows the debugger to output the modified variable, the location of the change, and the old and new values of the watched variable.

Parent topic: Watch


Temporarily Ignoring Watchpoints

The Ignore option allows the debugger to disregard a watched variable. In other words, when the given watchpoint is encountered, it will not be reported and the program will continue without interruption. Turning off the Ignore option allows the debugger to recognize and report any occurrence of the given watchpoint.

Parent topic: Watch


Skipping a Watchpoint Multiple Times

A watchpoint counter is associated with each watchpoint. When the watchpoint is created, the counter is set to zero; each time the watchpoint is incurred, the counter is incremented by one. When a program is reloaded, all counters are set to zero.

The Skip option assigns a watchpoint skip counter to the given variable, which is set to the value you specify. As a result, the watchpoint will be skipped the specified number of times. Once the watchpoint skip counter is set, it remains in effect until the value decreases (resets) to zero.

Parent topic: Watch


Watchpoints with Action Lists

An action-list is one or more debugger commands separated by a semicolon, which may specify that program execution is to continue. Any specified action-list is executed when a watchpoint is incurred.

Note:

It is not necessary to enclose the action list for the Watch dialog in square brackets (as is necessary for the command syntax).

Parent topic: Watch


Conditional Watchpoints

A conditional expression may be used to qualify the watchpoint; it must be the last option on the command line. When a watchpoint with the If option is set, the executing program will be suspended and the debugger will be activated whenever the watched variable is changed. The IF condition is then evaluated. The evaluation always takes place in the environment and language of the program statement. If the IF condition is false, program execution continues and the watchpoint is never reported. If the IF condition is true, the debugger incurs a watchpoint as usual.

Parent topic: Watch


Incurring Watchpoints

Description

A watchpoint is incurred when a watched variable has changed, the skip counter is either zero or not specified, and the Ignore option is not specified. When a watchpoint is encountered, the following occurs:

  • If an IF condition is specified, it is evaluated.
  • The watchpoint counter is incremented.
  • If the Ignore option is set for the given watchpoint, execution continues.
  • If the skip count for this watchpoint is non-zero, the count is decremented and execution is continued; the skip count for an ignored watchpoint is not affected.
  • The debugger announces the occurrence of the watchpoint. Output from the WATCH command includes the block name, the activation number, the line number where the change occurred, and the new and old hexadecimal values of the variable.
  • If an action-list is specified, it is executed.
  • The debugger prompt appears on the screen.

Example

In the following example, a watchpoint is set on variable n with an action-list to continue program execution. The value of n is input from the user.

CodeWatch> WATCH n /ACTION [C]
CodeWatch> CONTINUE

Input maximum prime boundary: 10
Program Stopped due to a Watchpoint
Watched variable N modified about line PRIMES\118
New Value: 10 {fixed binary (31)}
Break at PRIME\119
Parent topic: Watch
Related information
Lwatch
Nwatch
Read
Save


Where

Use

Displays either the current execution point or the location of a specified statement.

Command Syntax

WHERE [statement-id]

where:

statement-id
Is a statement label or a source line number

Description

The WHERE command prints a location as the name of a routine followed by a statement label.

If the statement identifier is a statement label, the name of the routine containing the label and the source line number of the label are printed. If the statement identifier is a source line number, the name of the routine is printed. If the statement identifier argument is omitted, the name of the routine and the line number of the current execution point are printed.

Example

In the following example, the next executable statement is located and the location is displayed.

CodeWatch> WHERE 108
Line 108 is not an executable statement ...
WHERE using statement PRIMES\112 instead.
PRIMES\112

In this example, the current execution point is displayed.

CodeWatch> WHERE
Current execution point is PRIMES.READ_INPUT\%ENTRY
Parent topic: CodeWatch Commands
Related information
Lenvironment
Point


!

Use

Invokes the host operating system command interpreter to perform a specified command. This command is available only on UNIX systems.

Command Syntax

! command
(Press <Return> to continue)

Description

The ! command invokes the command interpreter to read the remainder of the line following the ! command. Refer to your UNIX documentation for information on UNIX commands.

The ! command followed by the UNIX sh command pushes to a new command interpreter. To return to the debugger, type <Ctrl D> or exit.

Example

In this example, the UNIX pwd command is invoked, which lists the current working directory.

CodeWatch> !pwd
/usr/hicks/pllprogs
Parent topic: CodeWatch Commands


Debugging Open PL/I Programs

  • Program Blocks
  • Built-in Function Support
  • Referencing Arrays and Aggregate Structures
  • Support for Open PL/I Include Files
  • Sample CodeWatch Session Using Open PL/I
  • Program Listing
Parent topic: CodeWatch Reference


Program Blocks

Program blocks are units of code that provide scope and context for the debugger. An Open PL/I program block is a procedure block or a BEGIN block.

  • Block Names
  • Referencing Nested Blocks
Parent topic: Debugging Open PL/I Programs


Block Names

A procedure block is referred to by the name of that procedure. A begin block is referred to by its label (if present) or by the string %BEGIN followed immediately by the line number on which the block begins. For example, an unlabeled begin block that starts on line 119 of the source file is referred to as %BEGIN119.

Parent topic: Program Blocks


Referencing Nested Blocks

Open PL/I program blocks may be nested. Rules for naming nested blocks are as follows:

  1. If a block defined within the compilation unit is contained within or contains the debugger's current evaluation environment, the block may be referred to simply by its name. The name may need to be qualified to make it unique within the external procedure.

    If the block contains the debugger's current evaluation environment, the search for the referenced block begins from the current environment and continues through each successive containing (parent) block until the referenced block is found.

  2. If a block is in some other external procedure, it must be qualified with at least the external procedure name, and it may require further qualification. Furthermore, a fully qualified name to a block in some other external procedure may be the same as a partially qualified block name in the current procedure. To force the debugger to search outside the current procedure, qualify the block name with %EXTERN. (This is seldom necessary if ambiguous naming is avoided.)

    For example:

    A: proc;        /* 1 */        B: proc;             /* 8 */
  B: proc;      /* 2 */          C: proc;           /* 9 */
    C: proc;    /* 3 */            D: proc;         /* 10 */
      D: proc;  /* 4 */            end D;
      end D;                     end C;
    end C;                         B: proc;         /* 11 */
  end B;                             A: proc;       /* 12 */
  C: proc:      /* 5 */                A: proc      /* 13 */
    B: proc;    /* 6 */                  B: proc;   /* 14 */
      C:proc;   /* 7 */                  end B;
      end C;                           end A;
    end B;                           end A;
  end C;                           end B;
end A;                          end B;

The following describes how each block can be referenced given the current evaluation environment in the external procedure %EXTERN.A (block 1).

Block
 | Reference
1 | A or %EXTERN.A
2 | A.B, B, or %EXTERN.A.B
3 | B.C, A.B.C, or %EXTERN.A.B.C.
4 | D, C.D, B.C.D, A.B.C.D, %EXTERN.A.B.C.D, B.D, A.B.D, %EXTERN.A.B.D, A.D, or %EXTERN.A.D
5 | C, A.C, or %EXTERN.A.C
6 | C.B, A.C.B, or %EXTERN.A.C.B
7 | C.C, C.B.C, A.C.C, %EXTERN.A.C.C, A.C.B.C, or %EXTERN.A.C.B.C
8 | %EXTERN.B
9 | %EXTERN.B.C
10 | %EXTERN.B.D, or %EXTERN.B.C.D
11 | B.B or %EXTERN.B.B
12 | B.B.A or %EXTERN.B.B.A
13 | B.A.AB.B.A.A, %EXTERN.B.A.A, or %EXTERN.B.B.A.A
14 | B.B.B B.A.B B.A.A.B, B.B.A.B, %EXTERN.B.B.B, %EXTERN.B.A.B, %EXTERN.B.A.A.B, %EXTERN.B.B.A.B, or%EXTERN.B.B.A.A.B

If the current evaluation environment is in the internal procedure block %EXTERN.A.B.C.D (block 4), the following is true in the debugger:

B | refers to block 2
B.C | refers to block 3
C | refers to block 3
%EXTERN.B.A | is an ambiguous reference (block 12 or 13)
%EXTERN.B.B.A | refers to block 12
%EXTERN.B.C | refers to block 9

If the current evaluation environment is in the external procedure block %EXTERN.B (block 8), the following is true in the debugger:

A.B.C.D | refers to block 1
A | is an ambiguous reference (block 12 or 13)
B | refers to block 11
B.A | refers to block 12
A.B | refers to block 14
B.A.B | refers to block 14
Parent topic: Program Blocks


Built-in Function Support

The following PL/I built-in functions are supported by CodeWatch:

ADD | COLLATE | HBOUND | NULL
ADDR | COPY | HIGH | RANK
BINARY | DECIMAL | LBOUND | SUBSTR
BIT | DIMENSION | LENGTH | TRIM
BYTE | FIXED | LOW | UNSPEC
CHARACTER | FLOAT | MULTIPLY | VERIFY

The following abbreviations for PL/I built-in functions are recognized:

  • BIN for BINARY
  • CHAR for CHARACTER
  • DEC for DECIMAL
  • DIM for DIMENSION
Parent topic: Debugging Open PL/I Programs


Referencing Arrays and Aggregate Structures

Arrays and aggregate structures can be referenced in their entirety by referring to them by their array or structure name, or individual subfields or members can be referenced using the conventional PL/I syntax, as in REC_NAME.FIELD. A subfield can be referenced directly as long as its name is unique.

A specified range of an array can be evaluated using the following command-line syntax:

EVALUATE array-name [m:n]

or

EVALUATE array-name (m:n)

where m is the starting point of the array range and n is the ending point of the array range.

An asterisk (*) specifies that all elements of a dimension are to be evaluated. For example:

EVALUATE array-name[*,3:5]

or

EVALUATE array-name(*,3:5)

displays the third through fifth columns of all the rows in a two-dimensional array.

Specifying only the array name for PL/I will cause the evaluation of every element of every dimension of the array. Similarly, specifying a structure, record, or group name will cause the evaluation of every member of the group.

Parent topic: Debugging Open PL/I Programs


Support for Open PL/I Include Files

The following list describes the rules applying to CodeWatch support for Open PL/I include files. This support applies to include files that contain executable code. The rules are as follows:

  • Stepping into an include file, for example, when the next statement is a %INCLUDE directive, will cause the screen display to switch to the specified include file.
  • Commands that deal with the source file, such as PRINT and POINT, work as expected when using the current include file.
  • Stepping through an include file is allowed.
  • Setting breakpoints within an include file is NOT allowed. The setting of a breakpoint unambiguously refers to the original containing source file.
  • Stepping over an include file, for example, when the next statement is a %INCLUDE directive, is not explicitly allowed. This may may be accomplished by setting a breakpoint in the containing source file followed by the CONTINUE command.
  • Stepping out of an include file before its last statement is accomplished similarly to stepping over, that is, by setting a breakpoint in the containing source file followed by the CONTINUE command.
  • Using CodeWatch with the Open PL/I Macro Preprocessor
Parent topic: Debugging Open PL/I Programs


Using CodeWatch with the Open PL/I Macro Preprocessor

CodeWatch can be used with PL/I programs to which the Open PL/I macro preprocessor mfpp has been applied. CodeWatch uses the original source file (rather than the expanded preprocessed output of mfpp). Stepping through macros works similarly to the include file support described for include files.

Parent topic: Support for Open PL/I Include Files


Sample CodeWatch Session Using Open PL/I

This debugging session illustrates how to use the commands and features of CodeWatch when debugging programs compiled with Open PL/I. Following the session is the source listing of the sample PL/I program. The source file for this program is also available on the CodeWatch installation media.

The sample program, primes.pl1, calculates the number of prime numbers within a given range, but it doesn't do it very well. There is a bug somewhere that causes the program to print out too many values. Observe the following output:

*** Sieve of Eratosthenes ***

Input maximum prime boundary:
10
Number of primes found was     6
1      2      3      5      7      11

The program had been compiled using the -deb option to produce the necessary information for the debugger and the -l option to produce a listing file. It was then linked using Ipild. For example,

mfpli primes.pl1 -deb -l
ldpli primes.o -o primes

In this sample session, comments (which are not part of the session) are the bullet items. The system prompt is $. Note that user-supplied text is in bold typewriter font. For clarity, the abbreviated form of the command is used only after the command has been previously spelled out in its entirety.

  • Invoke CodeWatch at the system prompt.
    $ cwcmd primes

******************************************************************************
* CodeWatch, 08.00                                                           *
* ----------------                                                           *
* Copyright 2009 Micro Focus (IP) Limited                                    *
******************************************************************************
Initial evaluation environment is PRIMES:(inactive)
  • Find the string "main".
    CodeWatch> FIND main
  109:    /* main procedure */
  • Print 20 lines.
    CodeWatch> PRINT 15
109       /* main procedure */
110
111       declare n fixed binary(31);
112
113       put skip;
114       put list (' *** Sieve of Eratosthenes ***');
115       put skip (2);
116
117       call read_input(n);
118
119       do while (n > 1);
120          call sift(n);
121          call read_input(n);
122       end;
123
124   end;
  • The program calls read_input on line 117 to get user input, so set a break at line 119 to see if things are still working correctly.
    CodeWatch> BREAK 119
  • Continue to the breakpoint. The program will request input; enter 10.
    CodeWatch> CONTINUE

*** Sieve of Eratosthenes ***

Input maximum prime boundary:
10
Break at PRIMES\119
  • Print a line of text. Evaluate n, which is the variable read in on line 117.
    CodeWatch> P
  119: do while (n > 1);
CodeWatch> EVALUATE n
N = 10 {fixed binary (31)}
  • Access the declaration type of n.
    CodeWatch> TYPE n
N fixed binary (31) automatic
  • Everything seems to be fine. Set the default stepping action list to print one line and Step.
    CodeWatch> DSTEP [P]
CodeWatch> STEP
Step at PRIMES\120
  120:      call sift(n);
  • Step into sift and see what's happening there.
    CodeWatch> S IN
Step at PRIMES.SIFT\%ENTRY
   77: sift: procedure (n);
  • Use the ARGUMENTS command to see the arguments to this routine.
    CodeWatch> ARGUMENTS
N = 10 {fixed binary (31)}
  • Do a stack traceback.
    CodeWatch> STACK /ALL

Stack contains 5 frame(s).
Current execution point is PRIMES.SIFT\%ENTRY

5: Owner is "PRIMES.SIFT"
      Called from PRIMES\120
4: Owner is "PRIMES"
      Main program
  • To demonstrate statement tracing, set the source file pointer to line 98 and print five lines.
    CodeWatch> POINT 98
   98:         do while (k < n);
CodeWatch> P 5
   98:         do while (k < n);
   99:           /* cancel all multiples */
  100:           flags(k) = FALSE;
  101:           k = k + this_prime;
  102:         end;
  • Set a break at line 100, which will put you in the middle of this small loop. Continue.
    CodeWatch> B 100
CodeWatch> C
Break at PRIMES.SIFT\100
  • Set statement tracing and continue twice. Each statement is reported as it is executed.
    CodeWatch> TRACE STATEMENT
CodeWatch> C
**** PRIMES.SIFT\101
**** PRIMES.SIFT\102
**** PRIMES.SIFT\98
Break at PRIMES.SIFT\100
CodeWatch> C
**** PRIMES.SIFT\101
**** PRIMES.SIFT\102
**** PRIMES.SIFT\98
Break at PRIMES.SIFT\100
  • Set a macro "fig" to do FIND/IGNORE. This will be useful; by default, the FIND command is case-sensitive. The /IGNORE option ignores case.
    CodeWatch> MACRO fig.=[FIND /IGNORE]
CodeWatch> fig PRINT_OUT
  105:    call print_out(primes,count);  /* should be count - 1 */
  • Break at line 105 (the call to print_out). Turn off statement tracing and delete the breakpoint at the current line (NBREAK with no parameter deletes the breakpoint at the current line). Continue to the call to print_out.
    CodeWatch> B 105
CodeWatch> NTRACE S
CodeWatch> NBREAK
CodeWatch> C
Break at PRIMES.SIFT\105
  • Evaluate count, which you are about to pass to print_out.
    CodeWatch> E count
COUNT = 6 {fixed binary (31)}
  • Six prime numbers are found. That's not right. Only five should have been found: 1, 2, 3, 5, and 7. Set a break at the entry point of sift, reload the program and continue execution (twice) to get back to the entry of sift. (Enter 10 again for input.)
    CodeWatch> B sift\%ENTRY
CodeWatch> RELOAD
Command line : "primes"
Reloading..ok
Initial evaluation environment is PRIMES:(inactive)
CodeWatch> C

*** Sieve of Eratosthenes ***

Input maximum prime boundary:
10
Break at PRIMES\119
CodeWatch> C
Break at PRIMES.SIFT\%ENTRY
  • Step once and print 15 lines.
    CodeWatch> S
Step at PRIMES.SIFT\85
   85:    do I = 1 to n;
CodeWatch> P 15
   85:    do I = 1 to n;
   86:      flags(I) = TRUE;
   87:    end;
   88:
   89:    count = 1;
   90:    primes(1) = 1;
   91:
   92:    do I = 1 to n;
   93:      if flags(I) = TRUE then do;
   94:        this_prime = I + 1;
   95:        count = count + 1;
   96:        primes(count) = this_prime;
   97:        k = I + this_prime;
   98:        do while (k < n);
   99:          /* cancel all multiples */
  • Set a break at line 95. This is a conditional breakpoint with an ELSE action list. The debugger will not break at line 95 unless count > 4. It will instead evaluate count and continue on. Continue.
    CodeWatch> B 95 /IF {count > 4} /ELSE [E count]
CodeWatch> C
COUNT = 1 {fixed binary (31)}
COUNT = 2 {fixed binary (31)}
COUNT = 3 {fixed binary (31)}
COUNT = 4 {fixed binary (31)}
Break at PRIMES.SIFT\95
  • Delete this breakpoint. Continue and print one line.
    CodeWatch> NB
CodeWatch> C;P
Break at PRIMES.SIFT\105
 105: call print_out(primes,count); /* should be count - 1 */
  • Back at the call to print_out. Evaluate count. Assign count-1 to count and continue. (Enter 10 again for input.)
    CodeWatch> E count
COUNT 6 {fixed binary (31)}
CodeWatch> LET count=count-1
CodeWatch> C
Number of primes found was            (prime itself)    5

1      2      3      5      7

Input maximum prime boundary:
10
Break at PRIMES\119
  • This appears to be the solution. Reload the program and delete all breakpoints.
    CodeWatch> R
Command line : "primes"
Reloading..ok
Initial evaluation environment is PRIMES:(inactive)
CodeWatch> NBREAK /ALL
  • You can do a run-time patch to the program, without even exiting the debugger. This is a temporary fix to see what source changes you may need to make. This breakpoint will not report itself (/SILENT); it will simply execute its action list and continue. Continue program execution. Try 10 and 100 for user input. Exit the program by entering 0.
    CodeWatch> B 105 /SILENT [LET count=count-1;C]
CodeWatch> C

*** Sieve of Eratosthenes ***

Input maximum prime boundary:
10
Number of primes found was      (prime itself)     5

1      2      3      5      7

Input maximum prime boundary:
100
Number of primes found was   26
1      2      3      5      7      11     13     17     19     23
29     31     37     41     43     47     53     59     61     67
71     73     79     83     89     97

Input maximum prime boundary:
0
Program exited with status 0
Reloading..ok
Initial evaluation environment is PRIMES:(inactive)
  • So now you know that if you change line 105 of primes. pl1 from:
    call print_out(primes,count);

    to:

    call print_out(primes,count-1);

    the program will work just fine! Quit out of the debugger session.

    CodeWatch> QUIT
CodeWatch Quit...Bye!
Parent topic: Debugging Open PL/I Programs


Program Listing

Compiler:  Open PL/I 08.00.B2 - Copyright (c) 2009 Micro Focus (IP) Limited
Date/Time: December 11, 2009 (15:35:27)
File:      primes.pl1
Directory: C:\Program Files\Micro Focus\Open PLI 8.0\EXAMPLES\OPEN-PLI
Options:   deb l noopt Pentium obj primes.obj list primes.lst
       1   /* Sieve of Eratosthenes: Copyright (c) 2009 Micro Focus (IP) Limited */
       2
       3   primes: procedure options (main);
       4
       5   %replace FALSE      by '0'B;
       6   %replace TRUE       by '1'B;
       7
       8   %replace MAX_VALUE  by 1000;
       9   %replace MAX_PRIMES by  500;
      10
      11
      12   read_input: procedure (maxv);
      13
      14       declare maxv fixed binary(31);
      15       declare instring char(4) varying;
      16
      17       declare ok bit(1);
      18
      19       ok = FALSE;
      20
      21       do while (^ok);
      22           put list ('Input maximum prime boundary:');
      23           put skip;
      24           get list (instring);
      25           maxv = decimal(instring);
      26           if maxv > MAX_VALUE then do;
      27               put list ('Value too big.  Try again.');
      28               put skip;
      29           end;
      30           else do;
      31               ok = TRUE;
      32           end;
      33       end;
      34
      35   end read_input;
      36
      37   isprime: procedure (number,values,total) returns (fixed binary(31));
      38
      39       declare number                fixed binary(31),
      40                   values(1:MAX_PRIMES)  fixed binary(31),
      41           total                 fixed binary(31);
      42       declare n                     fixed binary(31);
      43
      44           do n = 1 to total;
      45           if number = values(n) then
      46                  return (number);
      47           end;
      48
      49           return(-1);
      50
      51   end isprime;
      52
      53   print_out: procedure (values,total);
      54
      55       declare values(1:MAX_PRIMES) fixed binary(31),
      56           total                fixed binary(31);
      57
      58       declare i fixed binary(15);
      59
      60       put list ('Number of primes found was');
      61       if isprime (total,values,total) >= 0 then
      62           put list(' (prime itself)');
      63       put edit (total) (F(4));
      64       put skip (2);
      65
      66       do i = 1 to total;
      67           put edit (values(i)) (F(7));
      68           if mod(i,10) = 0 then do;
      69               put skip;
      70           end;
      71       end;
      72
      73       put skip (2);
      74
      75   end print_out;
      76
      77   sift: procedure (n);
      78
      79       declare n fixed binary(31);
      80
      81       declare (i, k, count, this_prime) fixed binary(31),
      82           flags(1:MAX_VALUE) bit(1),
      83           primes(1:MAX_PRIMES) fixed binary(31);
      84
      85       do i = 1 to n;
      86           flags(i) = TRUE;
      87       end;
      88
      89       count = 1;
      90       primes(1) = 1;
      91
      92       do i = 1 to n;
      93           if flags(i) = TRUE then do;
      94               this_prime = i + 1;
      95               count = count + 1;
      96               primes(count) = this_prime;
      97               k = i + this_prime;
      98               do while (k < n);
      99                   /* cancel all multiples */
     100                   flags(k) = FALSE;
     101                   k = k + this_prime;
     102               end;
     103           end;
     104       end;
     105       call print_out(primes,count);  /* should be count - 1 */
     106
     107   end sift;
     108
     109       /* main procedure */
     110
     111       declare n fixed binary(31);
     112
     113       put skip;
     114       put list ('*** Sieve of Eratosthenes ***');
     115       put skip (2);
     116
     117       call read_input(n);
     118
     119       do while (n > 1);
     120           call sift(n);
     121           call read_input(n);
     122       end;
     123
     124   end;
Parent topic: Debugging Open PL/I Programs


Open PL/I Language Reference Manual

This book provides a reference to the language used in Micro Focus Open PL/I.

  • Language Concepts
    This chapter provides an overview of the Open PL/I language, explaining the following basic concepts: program structure and statement syntax, block structure, variables, files, input and output.
  • Data Types
    This chapter discusses the various data types that are available to you in Open PL/I.
  • Storage Classes
    This chapter describes storage classes and how they are used.
  • Declarations and Attributes
    This chapter explains how label prefixes and DECLARE statements are used for declarations, and also describes the attributes that can be used in a DECLARE statement.
  • References
    This chapter describes each type of reference and the rules and basic steps involved in resolving references.
  • Expressions
    This chapter explains expressions and how they are used.
  • Data Type Conversions
    This chapter defines the conversions that result from assignments to arithmetic variables, bit-string variables, and pictured variables.
  • Statements
    This chapter defines the Open PL/I statements. The statements are presented in alphabetical order by name.
  • Open PL/I Built-ins
    This chapter defines the built-in functions and subroutines provided by Open PL/I.
  • Open PL/I Macro Preprocessor
  • Features Unsupported by Open PL/I
    A list of features that are currently unsupported by Open PL/I.
  • Glossary
    This chapter provides definitions for terms used in the Open PL/I manuals.
Parent topic: Open PL/I 8.1 for UNIX


Language Concepts

  • Statements
  • Names
  • Constants
  • Punctuation
  • Comments
  • Statement Sub-Groups
  • Text Replacement and Insertion Statements
  • Modules
  • Blocks
  • BEGIN Blocks
  • Variables
  • Files
  • Input and Output
Parent topic: Open PL/I Language Reference Manual


Statements

Open PL/I is a block-structured language. Each block consists of a group of statements. Statements are used to declare constants and variables, and to express actions to be performed by your program. For example:

READ FILE (G) INTO (Y) ;

In this example, the READ statement reads the next record in file G into storage Y.

Each Open PL/I statement consists of a series of elements ending with a semicolon. These elements can be PL/I keywords, user-specified identifiers, literal constants, or punctuation symbols.

Parent topic: Language Concepts


Names

A name used to denote part of a statement such as a verb, option, or clause, is called a keyword. All statements, except the assignment statement, begin with a keyword that identifies the purpose of the statement. In the previous example, READ, FILE, and INTO are keywords.

Examples:

GOTO L;
CALL S(B,C,D);
RETURN;
STOP;
DO K = 1 TO 11;
TO = 20; /* ASSIGNMENT STATEMENT*/

There are no reserved words in Open PL/I. For instance, in the last example, TO names a storage location.

A name is also used to denote an object operated upon by the program, such as a variable, file, or label. These names are known as identifiers. Their meanings are established by a declaration. In the example given previously,

READ FILE (G) INTO (Y) ;

G and Y are identifiers.

The following examples show how names can be used either to establish an object to be operated on or to denote part of a statement.

DECLARE X(5) FIXED;
L: X(3) = 25;

In the previous examples, both X and L are identifiers, but DECLARE and FIXED are keywords. X is declared by a DECLARE statement; L is implicitly declared as a label.

A name consists of any combination of the following:

  • letters
  • digits
  • _ (underscore character)
  • @ (at sign character)
  • # (pound sign character)
  • $ (dollar sign character)
  • a sequence of any of the above characters

The following rules apply for the creation of names.

  • Any of the alphanumeric characters A through Z, a through z, and 0 through 9 can be used.
  • A name must not contain more than 32 characters.
  • Names cannot contain blanks or hyphens.

Examples:

STREET_NAME
@BETA
#Y7
C
$7

Names can be written using both uppercase and lowercase letters.

By default, all lowercase letters are interpreted as their uppercase equivalents. The -lowercase compiler option causes the reverse of this behavior. Refer to the Open PL/I User's Guide for more information on this option.

There are no reserved names in Open PL/I; names that are used as keywords, such as READ or INTO, can also be identifiers. However, this practice makes programs difficult to read and should be avoided whenever possible.

  • Declarations of Names
  • References to Names
Parent topic: Language Concepts
Related information
Open PL/I User's Guide


Declarations of Names

The meaning of a name is normally determined by its declaration. However, in some cases a name can be implicitly declared by the context in which it is used. (For more information, see the sections Compiler-supplied Defaults and DEFAULT .) The declaration of a name consists of a user-specified identifier and the attributes of that name.

Open PL/I permits two kinds of explicit declarations: the DECLARE statement and the label prefix.

The DECLARE statement declares the names of files, variables, and external procedures. A DECLARE statement can appear anywhere within the program, except as part of a compound statement. Regardless of where it appears, DECLARE is not an executable statement and has no effect except to establish the meaning of names.

Examples:

DECLARE F FILE;
DECLARE A(5) FLOAT;
DECLARE (I,J,K) FIXED BINARY(15);

In the previous examples, F is declared as the name of a file constant; A is declared as a floating-point array variable; and I, J, and K are declared as integer variables.

A label, also called a label prefix, is a user-specified identifier that names a statement so that it can be referenced elsewhere in your program. The label comes before the statement and is terminated with a colon (:).

Examples:

F: FORMAT(F(8,2),A(5));
P: PROCEDURE;
L: READ FILE(F) INTO(X);

In these examples, F is declared as a format name, P as a procedure name, and L as a statement label.

Labels can appear on all Open PL/I statements except DECLARE statements, target statements of ON statements (called ON-units), ELSE or THEN clauses in IF statements, and WHEN or OTHERWISE clauses in SELECT statements.

Parent topic: Names
Related information
Compiler-supplied Defaults
DEFAULT
ON


References to Names

Use of a name in any context, other than in a declaration, constitutes a reference to the name. To determine the meaning of the reference, the Compiler searches for a declaration of the name. This search resolves the reference by associating it with a declaration. For example:

DECLARE A FIXED BINARY(15);
DECLARE B FLOAT;

B = B+1;

A = A+1;

In the previous example, the Compiler knows that it must generate a floating-point add for B+1 because it has resolved the reference B to the second DECLARE statement. Likewise, it knows that it must generate an integer add for A+1 because it has resolved the reference A to the first DECLARE statement.

Parent topic: Names
Related information
Reference Resolution


Constants

A constant is a sequence of characters that represents a particular, unchanging value. In Open PL/I, five kinds of constants are permissible:

  • Literal constants

    These are actual numbers or strings written in the source program. Literal constants are restricted to character strings, bit strings, and fixed- or floating-point numbers.

  • Label constants

    These are established using a label prefix in the source program that declares a name either as the name of a format or a procedure, or as a statement label. Label constants cannot be declared in a DECLARE statement.

  • File and entry constants

    These constants are typically established by DECLARE statements. File constants are identifiers declared with the FILE attribute to describe the type of input/output to be performed on a file. Entry constants are used to invoke procedures at certain entry points.

  • Replace constants

    These are identifiers that are to be changed with the %REPLACE statement. Like literal constants, constant identifiers can also be character strings, bit strings, and fixed- or floating-point decimal numbers.

  • Named constants

    These constants are scalar identifiers that are declared by the VALUE attribute. They can be declared for arithmetic data, string data, and for pointers and offsets.

Examples:

Constant | Type
25 | Integer constant
7.5 | Fixed-point decimal constant
3.12E-01 | Floating-point decimal constant
'How are you?' | Character-string constant
'1'B | Bit-string constant (binary notation)
'1011'B | Bit-string constant (binary notation)
'775'B3 | Bit-string constant (octal notation)
'A7O'B4 | Bit-string constant (hexadecimal notation)
STARTUPD: | Label constant
%REPLACE TABLE_SIZE BY 350; | TABLE_SIZE is an identifier to be replaced by an integer constant
DECLARE E ENTRY; | E is an entry constant
DECLARE F FILE; | F is a file constant

For a table showing the expansion of nonbinary notation into binary notation, see the section Bit-String Data.

Arithmetic constants represent decimal values, whereas binary arithmetic values have no constant representation. Nevertheless, any decimal constant can be converted easily to a binary value by using it in a context that expects a binary arithmetic value.

As a result of Open PL/I language rules, all constants that appear as floating-point numbers in a source program are actually of type float decimal and are subject to the rules of float decimal arithmetic.

A character-string constant can contain any character, except that, if an apostrophe is required within a character-string constant, it is written as two apostrophes. For example,

'He said, "I''m fine."'
Note:

The double quotation mark character is not equivalent to a single quotation mark or two adjacent single quotation marks and has no more significance than any other character within a constant.

In Open PL/I, the maximum size of a string constant is 256 characters or bits (for details, see the section Open PL/I Compiler Implementation Limits). The Compiler checks this limit after bit-string constants written in the B2, B3, or B4 format have been expanded. Refer to the data type descriptions in the chapter Language Concepts in your Open PL/I User's Guide for the maximum size limits for floating- and fixed-point data.

A named constant is similar to a scalar declaration with the appropriate data attributes, plus the VALUE attribute. The VALUE attribute signifies this identifier is named constant, with all of the attributes taken as applied to the declaration.

Named constants differ from simple constants in that they retain the attributes from the declaration. For example,

declare i fixed bin (15) value(1);
declare j fixed bin (15);

j = 1;    /* 1 is fixed decimal, requires conversion */
j = i;    /* i is fixed bin (15), no conversion (integer 1 assigned, not "i" ) */

or string data items, the length is determined from the length of the string value when the length is not specified.

declare string char value ('abcdef') ; /* string is char(6) */

In Open-PLI, named constants can be declared as arithmetic or string; pointers and offsets are not yet supported. In Open-PLI, the named constants may be declared before or after it is used, and the same scoping rules as any declaration apply.

Example:

cool: proc options(main);

   dcl pname char (16) value (procedurename());

   dcl flag bit(1) aligned static init(true);

   dcl true bit(1) value ('1'b);
   dcl false bit(1) value('0'b);

   dcl myarr (n) fixed bin (15);

   dcl n fixed bin(15) value (800);

   dcl arr (k/3) fixed bin (15) static init (k+1, k, k+3);

   dcl arr1 (100+100) fixed bin (15);
   dcl arr2 (n+100) fixed bin (15);

   dcl i fixed bin (15);
   dcl k fixed bin (15) value (9);

   if flag then
       put skip list ('Named Constants are ', pname);

   put skip list(arr);

   i = n + 100;
   arr1 (k) = 99;

   put skip list (size(arr1), size(arr2), i, arr1(K*2-K));

   put skip list(arr);
end;

Named Constants are     COOL
       10               9              12
      400            1800             900              99
       10               9              12
Parent topic: Language Concepts
Related information
Text Replacement and Insertion Statements
Bit-String Data
Open PL/I Compiler Implementation Limits
B-Format
Language Concepts


Punctuation

In Open PL/I, punctuation symbols are either operators or separators.

Operators define the arithmetic or comparative operations to be performed on expressions in a statement. The table below lists the Open PL/I operators.

Symbol | Meaning
+ | Addition or the plus prefix
- | Subtraction or the minus prefix
* | Multiplication
** | Exponentiation
/ | Division
^ or ~ | Logical NOT
| or ! | Logical OR
& | Logical AND
> | Greater than
< | Less than
= | Equal to
^> or –> | Not greater than
^< or –< | Not less than
^= or ~= | Not equal to
>= | Greater than or equal to
<= | Less than or equal to
|| or !! | String concatenation
–> | Pointer resolution

Separators delimit and separate identifiers, keywords, and constants in statements. The table below lists the Open PL/I separators.

Symbol
 | Meaning
( ) | Encloses lists, defines order of expression evaluation, separates names of statements and options from specific keywords
, (comma) | Separates subscripts and procedure arguments, separates identifiers in a structure name, and precedes the BY NAME option
' (single quote) | Delimits bit strings and character strings
. (period) | Specifies a decimal point. Connects elements of a qualified name
: | Terminates a procedure name or a statement label
; | Delimits statements

Names and constants may be separated from one another by one or more blanks, or tabs, rather than by separators. Additional blanks surrounding punctuation symbols are optional. In the following examples, blanks are represented by boxes ( Blank representation).

Examples of blank usage

The first statement requires no blanks because each name is separated from the next by a punctuation symbol. The second statement shows the optional use of extra blanks. The third statement shows optional blanks surrounding the equal symbol (=) and after the semicolon, the remaining blanks being required blanks.

Note that when an arithmetic constant is followed by a name, at least one blank or punctuation symbol is required to separate the arithmetic constant from the name.

Parent topic: Language Concepts


Comments

Comments are used to document an Open PL/I program. A comment can appear anywhere that a blank can appear and is equivalent to a blank. Comments cannot be nested. The general form of a comment is:

/*Comments open with a slash* and close with a *slash */

For example,

/*HERE IS A COMMENT*/
IF A<25 /* HERE IS ANOTHER ONE */ THEN
/*HERE IS AN /* ERRONEOUS */ COMMENT */

The final comment is invalid because comments cannot be nested; it ends at the first * / in the line and the Compiler attempts to interpret COMMENT */ as code and produces an error message.

The Compiler puts an asterisk (*) into the line number field of the listing file for each line on which a comment is continued from a preceding line. This convention can be used to determine if some text was accidentally included in a comment.

Comments can continue over any number of lines of program text; thus, if the */ is omitted from a comment, all program text up to the next */ is considered part of the comment. This causes part of the program to be ignored by the Compiler and may cause it to produce misleading error messages. The same problem occurs if a character-string or bit-string constant is not terminated with an apostrophe.

Parent topic: Language Concepts


Statement Sub-Groups

This section introduces certain Open PL/I statements that, alone or in conjunction with other statements, provide specific capabilities within Open PL/I.

  • Compound Statements
  • Statements that Alter the Order of Execution
  • Statement that Handles Exception Conditions
Parent topic: Language Concepts
Related information
Statements


Compound Statements

Open PL/I has four compound statements:

  • IF
  • ON
  • DO
  • SELECT

They are called compound statements because they each contain other statements.

  • IF Statement
  • ON Statement
  • DO Statement
  • SELECT Statement
Parent topic: Statement Sub-Groups


IF Statement

The IF statement tests an expression and performs a specified action if the result of the expression is true. Its general form is:

IF expression
    THEN statement;
    [ELSE statement];

where expression is any valid expression that yields a scalar bit-string value, and statement is any unlabeled statement (except DECLARE, END, ENTRY, FORMAT, or PROCEDURE) or an unlabeled DO-group or BEGIN block. For example:

IF A>B
    THEN READ FILE (F) INTO (X);

In this example, the IF statement contains the READ statement. If the expression A>B is true, the READ statement executes.

The IF statement needs no semicolon of its own because each statement contained within it has its own semicolon. IF statements can be nested, as shown in the following example.

IF A>B
    THEN IF D<C
        THEN READ FILE(F) INTO(X);
        ELSE STOP;

In this example, the second IF statement has both a THEN clause and an ELSE clause. An ELSE clause always corresponds to the THEN clause that immediately precedes it. The first IF statement has only a THEN clause. If you want to STOP when A ^> B, you may provide a null ELSE clause to the innermost IF, forcing the ELSE STOP to be associated with the first IF. It is preferable to use structured IF, THEN, and DO statements to accomplish this, as shown in the following example.

IF A>B THEN DO;
    IF D<C THEN READ FILE(F) INTO (X);
    END;
ELSE STOP;
Parent topic: Compound Statements


ON Statement

The ON statement defines the action to be taken when a specific condition is signaled during the execution of a program. Its general form is:

ON condition–name ON-unit,

or

ON condition–name SYSTEM

where:

condition-name is ANYCONDITION, AREA, ATTENTION, CONDITION(name), CONVERSION, ENDFILE(f), ENDPAGE(f), ERROR, FINISH, KEY(f), OVERFLOW, RECORD(f), SIZE, UNDEFINEDFILE(f), UNDERFLOW, USERCONDITION(expression), USERCONDITION(SS$_UNWIND), or ZERODIVIDE.

ON-unit is a BEGIN block or any statement other than DECLARE, DEFAULT, DO, END, ENTRY, FORMAT, LEAVE, OTHERWISE, PROCEDURE, RETURN, or SELECT.

The keyword SYSTEM indicates that, instead of executing user-specified code in the ON-unit, a system-generated message describing the condition is displayed and the ERROR condition is signaled. For example:

ON ENDFILE (F )
    BEGIN;
       .
       .
       .
    END;

In this example, the block of statements between the BEGIN and END statement executes if the end-of-file condition is reached.

ON is a compound statement, but it cannot be nested. The ON statement's use in responding to exceptional conditions is explained more fully in the section Statement that Handles Exception Conditions.

Parent topic: Compound Statements
Related information
Statement that Handles Exception Conditions


DO Statement

The DO statement begins a sequence of statements to be executed in a group, called a DO-group. Its general form is:

DO;
  .
  .
  .
END;

For example:

IF B < C THEN DO;
   PUT LIST ('ADDED DATA REQUIRED');
   GET LIST (VALUE);
   B = B + VALUE;
   END;

In this example, the PUT LIST, GET LIST, and assignment statements execute if B < C.

DO statements can contain IF statements, other DO-groups, RETURN statements, or GOTO statements that alter the order of execution.

Parent topic: Compound Statements


SELECT Statement

The SELECT statement tests a series of expressions and performs the action specified with the first true test, or the action associated with the OTHERWISE clause (if present) and none of the tests evaluates true. Its general form is:

SELECT[select-expression];
    WHEN (e1[,e2[,e3[...]]])    action_1;
    WHEN (e4[,e5[,e6[...]]])    action_2;
       .
       .
       .
    [OTHERWISE action_m;]
END;

where select-expression and e1, e2... are valid expressions, and each action is a single or compound statement or a BEGIN block. For example:

SELECT;
    WHEN (F=40) G=G+1;
    WHEN (F=50) IF G > 0 THEN G=G+2;
       .
       .
       .
    OTHERWISE DO;
              .
              .
              .
              END;
END;

This example shows the SELECT statement used with the expression omitted. When the expression is omitted from the SELECT statement, each WHEN clause expression is evaluated and converted, if necessary, to a bit string. The action after the WHEN clause is performed if the resulting bit string is nonzero. In the above example, if F=40 is true, the action G=G+1 is executed and the SELECT group is exited. If F=50 is true, the IF statement is executed and the SELECT group is exited. If more than one WHEN statement is true, the action associated with the first true WHEN clause is executed. If no WHEN clauses are true, the DO group associated with the OTHERWISE clause is executed.

When control reaches a SELECT statement with a select–expression present, the select-expression is evaluated and its value saved. Next, the expressions in the WHEN clauses are evaluated in the order in which they appear, and each value is compared with the value of select–expression. If a value is found that is equal to the value of select–expression, the action following the corresponding WHEN clause is performed, and no further WHEN clause expressions are evaluated. If none of the expressions in the WHEN clauses is equal to the select–expression, the action specified after the OTHERWISE clause is executed unconditionally. for more information, see the section SELECT in the chapter Statements.

Parent topic: Compound Statements
Related information
SELECT


Statements that Alter the Order of Execution

Statements are typically executed in the order in which they are written; however, certain statements control the order of execution of the program. These statements are GOTO (used with a statement label), IF, and DO.

The GOTO statement causes control to be transferred to a labeled statement in the current procedure or in another active procedure. Its general form is:

GOTO label–reference[OTHERWISE];

or

GO TO label–reference[OTHERWISE];

where:

label–reference is a label constant or an expression that, when evaluated, yields a label value. (A label value denotes a statement in the program.) For example:

A = 5;
   GOTO L2;
L1:
   B = 7;
     .
     .
     .
L2:
   B = 4;

In this example, A is assigned 5 and B is assigned 4. The statements beginning with label L1 can be executed only if a GOTO statement transfers control to the label L1.

Although labels are a convenient means to represent a specific location in a program, programs that contain many labels are generally more difficult to read and modify. The use of labels and GOTOs can be avoided or minimized by using the compound statements IF and DO to control the order of statement execution.

The DO statement causes all statements between the DO statement and its corresponding END statement to be executed a number of times as determined by the form of the DO statement.

Parent topic: Statement Sub-Groups


Statement that Handles Exception Conditions

The ON statement gives your Open PL/I programs the ability to respond to exception conditions that occur during the execution of a program, such as end-of-file, or computational errors such as division by zero. For example:

ON ERROR
   BEGIN;
      .
      .
      .
   END;

Execution of the ON statement establishes the ON-unit as a block of statements that are executed if the specified condition occurs. If the specified condition occurs after the ON statement is executed, processing is interrupted and the specified ON–unit is executed. In the above example, the block of statements between the BEGIN and END statements are established as the ON–unit, which executes if the ERROR condition occurs. Execution of the ON statement does not cause immediate execution of the ON-unit.

An ON-unit is established within its containing block's current activation and remains established until that block returns to its caller, or until another ON-unit is established for the same condition within the same block activation, or until the ON-unit is reverted using the REVERT statement.

If one of the possible conditions occurs during the execution of a block, and that block does not have an established ON-unit for that condition, the calling block's ON-unit is used to respond to the condition. If the calling block has no established ON-unit for the condition, its caller's ON-unit is used, and so on. If no ancestor has an ON-unit for the condition, a default action is taken. Except for the ENDPAGE, FINISH, and UNDERFLOW conditions, this default action ends program execution and issues a run-time error message.

ON-units for the ERROR condition cannot resume execution of the statement in which the error was detected.

Parent topic: Statement Sub-Groups


Text Replacement and Insertion Statements

When a program module is being compiled, the Compiler is able to recognize and evaluate two statements that alter the program text: %INCLUDE and %REPLACE. Both of these statements can be used anywhere within a procedure or source file to simplify the job of writing programs.

Other statements that alter program text are described in Open PL/I Macro Preprocessor.

  • The %INCLUDE Statement
  • The %REPLACE Statement
Parent topic: Language Concepts
Related information
Open PL/I Macro Preprocessor


The %INCLUDE Statement

The %INCLUDE statement incorporates text from other files into the current source file during compilation. The general form of this statement is:

%INCLUDE filename[,filename]...;

where:

filename is one of the following:

  • A character string
  • An Open PL/I name
  • An Open PL/I name enclosed in parentheses

The specified filename is used to locate a text file whose content is inserted into the program text in place of the %INCLUDE statement.

Your selection of one of these forms in combination with the presence or absence of the -ipath compiler option affects the search pattern used in locating files to be included. For more information, see the section %INCLUDE in the chapter Statements.

Note:

The Open PL/I Macro Preprocessor has its own %INCLUDE statement. Its use is documented in the appendix Open PL/I Macro Preprocessor.

Parent topic: Text Replacement and Insertion Statements
Related information
%INCLUDE
Open PL/I Macro Preprocessor


The %REPLACE Statement

The %REPLACE statement specifies that an identifier is to be replaced by a specified constant or other name during compilation. The general form of this statement is:

%REPLACE name BY constant-or-name;

Beginning at the point at which the %REPLACE statement is encountered, each occurrence of name that follows the %REPLACE statement is replaced by the specified constant or other name until the end of compilation.

The %REPLACE statement is often used to supply the sizes of tables or to give names to special constants whose meaning would not otherwise be obvious. For example:

%REPLACE TRUE BY '1'B;
%REPLACE TABLE_SIZE BY 400;
%REPLACE MOTOR_POOL BY 5;
%REPLACE X BY -3.0E0;
DECLARE X(TABLE_SIZE) FIXED STATIC;
DO K = 1 TO TABLE_SIZE;
IF DEPARTMENT_NUMBER = MOTOR_POOL
   THEN DO;
    .
    .
    .

Both the %REPLACE and %INCLUDE statements operate on the program text without regard to the meaning of the text.

The %REPLACE statement substitutes all subsequent occurrences of the name without regard to the block structure of the module, as explained in the section Blocks.

Parent topic: Text Replacement and Insertion Statements
Related information
Blocks


Modules

One or more external procedures can be present within a single Open PL/I source file. All external procedures within a source file will be compiled by the Compiler into a single object file.

A module is defined as a single compilation unit, a source file that is compiled into object code. A module consists of one or more external procedures.

A source file may contain declarations that appear outside the scope of any external procedure, as long as all variables that appear in such declarations are BASED, STATIC, or DEFINED. A variable that is defined this way is known within the scope of all external procedures. If a declaration is provided with the EXTERNAL attribute, it will be known outside the source file.

A source file may also contain %REPLACE statements and declarations of named constants (for example, file and entry constants) before the first external procedure.

The following example illustrates a source file that has declarations and %REPLACE statements preceding the first external procedure. There are two procedures (GETREC and PUTREC) in the source file that can be used as part of the program. By default, Open PL/I declares these entry constants, GETREC and PUTREC, with the EXTERNAL attribute; therefore, a procedure from another module outside of this source file can invoke GETREC or PUTREC. If a procedure in another module needs to reference GETREC and PUTREC, they must be declared within that module with the attributes ENTRY and EXTERNAL.

At the top of this source file are other items (REC, NAME, ADDRESS) that are hidden from any procedures compiled in other modules, and are known only to GETREC and PUTREC. Because Open PL/I, by default, provides file constant declarations with the EXTERNAL attribute, the file DATA_BASE can be known in other modules.

%REPLACE DATA_SIZE BY 80;
DECLARE 1 REC BASED
            2 NAME CHAR(40),
            2 ADDRESS CHAR(DATA_SIZE);
DECLARE DATA_BASE KEYED FILE UPDATE;

GETREC: PROCEDURE(P);
DECLARE P POINTER;
READ FILE(DATA_BASE) INTO(P->REC);
END GETREC;

PUTREC: PROCEDURE(P);
   DECLARE P POINTER;
    REWRITE FILE(DATA_BASE) FROM(P->REC);
END PUTREC;
Parent topic: Language Concepts


Blocks

PL/I is a block-structured language. Just as certain language elements make up statements, groups of statements make up blocks. Two types of blocks exist in Open PL/I:

  • Procedure blocks
  • BEGIN blocks

A procedure block is the basic executable program unit of Open PL/I and is made up of a group of statements contained within the limits of a pair of statements, PROCEDURE and END.

A BEGIN block is a program unit into which control flows during the typical execution of a procedure. The statements within a BEGIN block are contained within the limits of a pair of statements, BEGIN and END.

Whenever a procedure block or BEGIN block is entered, a block activation is created for that block. The block activation consists of the allocation of storage for the variables declared within the block and the system information that links that block to the previous block in the activation chain.

The following sections provide detailed information on procedure and BEGIN blocks and activation of these blocks.

  • Procedure Blocks
Parent topic: Language Concepts


Procedure Blocks

A procedure is a sequence of statements beginning with a PROCEDURE statement and ending with an END statement. The purpose of a procedure is to "package" a set of executable statements and declarations to form a block that can be executed from several places in the program simply by calling it. Because a procedure defines a block of statements, it is typically called a procedure block. The following example shows two procedure blocks, A and B:

A: PROCEDURE;
      .
      .
      .
   END A;

B: PROCEDURE;
      .
      .
      .
   END B;

Procedures contained within other procedures are called nested or internal procedures. Procedures not contained within other procedures are called external procedures. A program module consists of one or more external procedures. For example:

A: PROCEDURE;
      .
      .
      .
   B: PROCEDURE;
             .
             .
             .
   END B;
   C: PROCEDURE
      .
      .
      .
      D: PROCEDURE;
             .
             .
             .
      END D;
   END C;
END A;

In this example, Procedure A is external, and procedures B and C are nested within it. Procedure D is nested within procedure C.

  • Scope
  • Calls and Returns
  • Parameters and Arguments
  • Block Activation and Recursion
  • Guidelines for Using Procedures
Parent topic: Blocks


Scope

Each procedure block establishes a distinct region of the program text called "scope," throughout which the names declared within that procedure block are known. The scope of a name is defined as the region of the program in which the name has meaning and can be referenced.

The scope of a name includes the procedure in which the name is declared and all procedures contained within that procedure, except those contained procedures in which the same name is redeclared. For example:

A: PROCEDURE;
   DECLARE (X,Y) FLOAT;
      .
      .
      .
   B: PROCEDURE;
      DECLARE X FILE;
      DECLARE Z FIXED;
            .
            .
            .
   END B;
END A;

In this example, the scope of Y includes both procedure A and procedure B. The scope of X as a float is only procedure A. The scope of X as a file is procedure B. The scope of Z is procedure B. Z cannot be referenced from within procedure A. The scope of the procedure name B includes both procedure A and procedure B.

Parent topic: Procedure Blocks


Calls and Returns

Statements within a procedure block are executed only when the procedure block is called from another procedure block. The CALL statement enables procedure calling. For example:

A: PROCEDURE;
      .
      .
      .
   CALL B;
      .
      .
      .
B: PROCEDURE;
      .
      .
      .
   END B;
      .
      .
      .
   END A;

In this example, procedure B is executed only when it is called from procedure A. Procedure A resumes execution at the statement following the call when B is completed.

A procedure returns to its caller either by executing its END statement or by executing a RETURN statement, as shown in the following example:

A: PROCEDURE;
      .
      .
      .
   IF X<0 THEN RETURN;
      .
      .
      .
   END A;

Control does not "flow" into a procedure; that is, if control reaches a statement immediately preceding a procedure declaration, then (unless the statement is a control-flow statement such as GOTO) control will automatically skip to the statement following the declared procedure.

Parent topic: Procedure Blocks


Parameters and Arguments

The usefulness of a procedure block is increased greatly if it can be made to operate on different values each time it is called. Arguments and parameters enable such operation.

Arguments are the values passed to a procedure block at invocation. Parameters are the names used by the invoked procedure block to refer to these arguments.

Open PL/I typically passes an argument to an invoked procedure by referencing its storage address.

For example:

   CALL P(A,B);
      .
      .
      .
   CALL P(D,E);
      .
      .
      .
P: PROCEDURE(X,Y);
      .
      .
      .
   PUT FILE (F) LIST(X,Y);
      .
      .
      .
   END P;

In this example, A and B are arguments of the first call to the procedure P. While P is executing as a result of the first call, the argument A is said to correspond to the parameter X and the argument B corresponds to the parameter Y. While P is executing as a result of the second call, D corresponds to X and E corresponds to Y.

When an argument is a variable, the actual address of the variable is passed to the called procedure. This allows the invoked procedure to change the value of the argument.

When an argument is a constant or an expression, a temporary location is used to store the current value of the argument, and the address of that temporary location is passed to the called procedure.

Parent topic: Procedure Blocks


Block Activation and Recursion

Each time a procedure block is called, it is said to be active, and it remains active until it returns from the call (or until a non-local GOTO transfers control to a containing block activation). Such procedure activation has an associated block of storage allocated on a stack. This block of storage is called a stack frame, and it is used to hold information (such as the location to which control should return from the activation) that is unique to each procedure activation.

The stack frame contains storage for the automatic data declared within the block. Thus, each activation of the block has its own copy of the automatic data.

If procedure A calls procedure B, the stack frame associated with the activation of A is pushed down by the stack frame associated with the activation of B. When B returns, its stack frame is popped from the stack and the stack frame of A is then the current stack frame.

If procedure A calls itself directly or indirectly by invoking a chain of procedures in which A is again called, A is said to be a recursive procedure. For example:

A: PROCEDURE RECURSIVE;
      .
      .
      .
   CALL A;
      .
      .
      .
   END A;

The following example shows a program that makes a copy of a tree structure using block activation and recursion principles.

   .
   .
NEW = COPY(OLD);
   .
   .
COPY: PROCEDURE(IN) RETURNS(POINTER)| RECURSIVE;
      DECLARE     (IN,OUT) POINTER;
      DECLARE     1 RECORD BASED,
                        2 FIELD1 FLOAT,
                        2 FIELD2 FLOAT,
                        2 DAUGHTER POINTER,
                        2 SON POINTER;
DECLARE NULL BUILTIN;

IF IN = NULL THEN RETURN(NULL);
ALLOCATE RECORD SET(OUT);
OUT->RECORD.FIELD1 = IN->RECORD.FIELD1;
OUT->RECORD.FIELD2 = IN->RECORD.FIELD2; OUT->RECORD.DAUGHTER =
      COPY(IN->RECORD.DAUGHTER);
OUT->RECORD.SON = COPY(IN->RECORD.SON);
RETURN(OUT);

END COPY;

As demonstrated in this example, each record of the original tree structure may be linked using pointers to a SON record and/or a DAUGHTER record. Either the SON or the DAUGHTER field may contain a null pointer value. COPY is called with a pointer to the root in the original tree structure. It returns a pointer to the root in a new tree structure that is a copy of the original. Each activation of the COPY procedure has its own instance of the variables IN and OUT.

For additional information about recursive procedures, see the section Entry Data in the chapter Data Types.

Parent topic: Procedure Blocks
Related information
Entry Data


Guidelines for Using Procedures

Procedures are a natural division of the program and therefore provide the best mechanism to represent program modularity. The program should be organized or structured as a set of modules, each of which is written as a procedure.

Adhere to the following guidelines when using procedures:

  • Write procedures with minimal dependence on their ability to access the values of their containing procedure. All such use of nonlocal variables should be clearly documented by comments in both the declaring and the using procedures.
  • Write procedures that are used only from within a given procedure as internal procedures within the calling procedure. Write internal procedures following the executable statements of the containing procedure.
  • Make each procedure as small as possible to enable understanding of program logic.
Parent topic: Procedure Blocks


BEGIN Blocks

A BEGIN block is a sequence of Open PL/I statements into which control flows during the routine execution of a program. A BEGIN block differs from a procedure in that it is invoked by executing its BEGIN statement, it cannot have any parameters, and it always returns by executing its END statement. In addition, execution of a RETURN statement within a BEGIN block returns to the caller of the procedure that immediately contains the BEGIN block. And, unlike a procedure, a BEGIN block can be used as the ON–unit of an ON statement.

The BEGIN block groups a set of program statements and defines a scope for the names declared within it. Generally, the reason for using a BEGIN block is to create a new scope and/or a new block activation. BEGIN blocks can contain DO-groups, SELECT groups, DECLARE statements, and procedures, as well as other BEGIN blocks.

The statements of a BEGIN block are bounded by BEGIN and END statements, as shown in the following example:

BEGIN;
   .
   .
   .
END;

Since the BEGIN block contains declarations and ON-units, as well as executable statements, it can be used to permit temporary redefinitions of names and exception handlers, as well as to provide a means of allocating and freeing AUTOMATIC variables within it. (For additional information about AUTOMATIC variables, see the section Storage Classes.) For example:

DECLARE SUM FIXED BINARY;
   .
   .
   .
BEGIN;
DECLARE SUM FILE;
DECLARE X(1000) FLOAT;
   .
   .
   .
END;

In this example, SUM is redeclared within the BEGIN block so that it can be used as a file. A large array X is declared within the BEGIN block and is allocated storage only during the execution of the BEGIN block.

Parent topic: Language Concepts
Related information
Storage Classes


Variables

A variable is a named object that is capable of holding values. Each variable has two properties:

Data type
Determines the kind of values a variable holds.
Storage class
Determines the duration of a variable's existence and how it is referenced.
  • Data Types and Conversion
  • Storage Classes
Parent topic: Language Concepts


Data Types and Conversion

Each variable must be declared to have a data type. Except for cases under control of the DEFAULT statement, failure to specify a data type causes the Compiler to issue a warning and to give the variable a data type of Fixed Binary(15) if its name begins with any of the letters I through N; otherwise, the variable is given a data type of Float Decimal(6).

A complete discussion of data types is contained in the chapter Data Types. The following examples show several data types available in Open PL/I.

Examples:

DECLARE A FLOAT DECIMAL(7);
DECLARE N FIXED BINARY(15);
DECLARE C CHARACTER(30);
DECLARE B BIT(1);

In these examples, variable A is capable of holding any floating-point decimal value with mantissa of up to 7 digits and exponent of up to 3 digits; variable N is capable of holding any binary integer value between -32768 and +32767 inclusive; variable C is capable of holding any string of 30 characters; and variable B is capable of holding either '1'B or '0'B.

Although each variable is capable of holding values of only a specific data type, the Open PL/I language provides a complete set of operations that convert values from one data type to another. Whenever a value is assigned to a variable, it is first converted to the data type of the variable, as illustrated in the following examples (which refer to the declarations in the previous examples).

Examples:

A = 1; /* converts 1 to FLOAT DECIMAL(7) */
N = 2.5; /* converts 2.5 to the FIXED BIN(15) integer 2 */
C = -4.5; /* converts -4.5 to a character string */
B = 0; /* converts integer 0 to '0'B */

For a complete discussion of data type conversions, see the chapter Data Type Conversions.

Parent topic: Variables
Related information
Data Types
Data Type Conversions


Storage Classes

A variable's storage class determines when and for how long storage is to be allocated for the variable. Since this storage holds the variable's value, the storage class of a variable determines how long the variable retains its value.

The Open PL/I language permits the following six storage classes, which are fully explained in the chapter Storage Classes.

  • AUTOMATIC
  • BASED
  • CONTROLLED
  • DEFINED
  • STATIC (INTERNAL or EXTERNAL)
  • parameter

Unless declared otherwise, a variable's storage class is AUTOMATIC, meaning that it is allocated storage each time its immediately enclosing scope becomes active (as happens during a procedure call or the execution of a BEGIN statement. Exiting the scope frees this allocated storage (as happens at procedure or BEGIN block termination). Consequently, AUTOMATIC variables do not retain their values after deactivation of the block in which they are contained.

If a variable must retain its value between calls of its containing procedure, it should be declared to have the STATIC storage class. For example:

DECLARE K FIXED BINARY STATIC;
DECLARE TABLE(4) CHARACTER(5)
      STATIC INITIAL('A','B','C','D');

In this example, each element of the array TABLE is given an initial value.

Storage for STATIC variables is allocated prior to program execution by the Compiler and linker. Consequently, the length (precision) of each STATIC variable must be constant at compile time.

Parent topic: Variables
Related information
Storage Classes


Files

In Open PL/I, a file is a source of input data or a target for data output. Files are referenced in I/O statements by using a file name declared with the FILE attribute. The file reference actually refers to a file constant or to a file variable that has been assigned a value.

Each file used by the program must be declared in exactly one module in the program. That module must either declare the file with the GLOBALDEF attribute or must be compiled with the -defext option.

  • File Constants
  • File Variables
  • Using Environment Variables
Parent topic: Language Concepts


File Constants

A file constant is an identifier declared with the FILE attribute and without the VARIABLE attribute. For example:

DECLARE F FILE;

In this example, F is the name of a file constant.

A file constant cannot be the target of an assignment operation, and is external, by default. (For a discussion of assignment statements, see the chapter Statements.)

Each file constant is associated with a block of static storage called a file control block. The file control block retains information about the current status of the file while the file is open. In effect, the file constant is a pointer to, or a designator of, a file control block. File constants require the use of the -defext compiler option.

Each file control block's file identifier (ID) is the NAME of its associated file constant. The file ID in the previous example is F. This ID is used as the default TITLE of the file when it is being opened.

Parent topic: Files
Related information
Statements


File Variables

A file variable is a variable that can be assigned file values. A file variable can be given a value by receiving a file constant passed as an argument, by receiving a file constant as the value of a function, or by simple assignment. A file variable is declared with the VARIABLE attribute. For example:

DECLARE G FILE;
DECLARE F FILE;
DECLARE V FILE VARIABLE;

V=F;
...
V=G;

In this example, F and G are file constants, each of which has an associated file control block. V is a file variable that can be assigned file values. After the first assignment, both F and V designate the same file control block. Any operation performed on V is equivalent to the same operation performed on F. After the second assignment, any operation performed on V is equivalent to the same operation performed on G, because both V and G designate the same file control block.

A file name used as a parameter is a file variable and designates the same file control block as its corresponding argument.

Parent topic: Files


Using Environment Variables

To determine the system name of a file to match with a PL/I file, Open PL/I uses the name specified in the TITLE option of the OPEN statement. If the TITLE option is omitted, Open PL/I uses, by default, the name of the file constant or file variable in the PL/I program (shifted to uppercase). You can, instead, use system environment variables to easily specify the system names of files at run-time. The environment variable must be named in this fashion:

LPI_name system-filename

where:

name is the TITLE-specified or default name indicated by the program.

Examples:

DECLARE DATA2 UPDATE FILE;   OPEN FILE(DATA2) /* no title */;
DECLARE FACTS STREAM FILE;   OPEN FILE(FACTS) TITLE('Report');

If you do not use environment variables to connect these openings with systems files, the following system names will be assumed for the files: DATA2 and Report.

Instead, prior to running the application, you could set environment variables as follows, causing the specified system files to be used. (Any directories used in the path names must exist.)

setenv LPI_DATA2 /dir1/dir2/master.data
setenv LPI_Report /doc/reports/deptA/week23.rep

In the second example, LPI_Report was used rather than LPI_FACTS, because of the TITLE option in that file's OPEN statement.

Parent topic: Files


Input and Output

Open PL/I provides two types of Input/Output processing: stream I/O and record I/O. Each type of I/O has its own statements, and each type operates on its own kind of files. Open PL/I can process more than 32,767 records per file and supports UNIX named pipes, which enables the reading and writing of massive data sets - greater than 2 GB - something not normally permitted in UNIX I/O.

A stream file is a sequence of characters organized into lines and pages. When reading or writing a file using stream I/O, the data is treated as if it formed a continuous stream of ASCII characters. Stream files are written by PUT statements and are read by GET statements.

A record file is a set of discrete records that are accessible either sequentially or by keys. When reading or writing a file using record I/O, only one record is processed upon the execution of the I/O statement. Record files are read and written by READ, WRITE, REWRITE, and DELETE statements.

The following sections provide detailed information on the two types of input and output processing available through Open PL/I: stream I/O and record I/O.

  • Stream I/O
  • Record I/O
Parent topic: Language Concepts


Stream I/O

Stream I/O treats data in the external file as a stream of ASCII characters. In a stream I/O operation, a list of program variables is associated with actual input or output fields of data.

Two forms of stream I/O statements exist:

  • List-directed stream I/O, as performed by the GET LIST and PUT LIST statements.
  • Edit-directed stream I/O, as performed by the GET EDIT and PUT EDIT statements.

In both list-directed and edit-directed stream I/O, the files are written by the PUT statement and are read by the GET statement. In edit-directed stream I/O, data is transmitted to or from a stream file under the control of a format-list. In list-directed stream I/O, data is transmitted to and from the stream file without a format-list. In edit-directed stream I/O, format-lists can be part of the GET or PUT statement or can be given by a FORMAT statement.

Execution of a GET or PUT statement transmits data from or to the current line of a stream file and may not consume or produce an entire line of the stream file. Several PUT statements can be used to build a given line, or a single PUT statement can be used to output several lines. Similarly, several GET statements can read values from a given line, or a single GET statement can be used to read one or more lines. Lines read from a disk file are not modified by Open PL/I in any way; however, lines read from all other devices have trailing blanks removed and have one blank appended to the end of each line that is read by a GET statement. This blank ensures that a field typed at the beginning of a line is not appended to a field typed at the end of the previous line.

Each stream file has an associated line size that is determined when the file is opened. Lines of an output file contain n characters, where n is the line size of the file. (For more information, see the discussion of the LINESIZE option in the section Stream File Attributes.) A shorter line can be created by using the SKIP option on a PUT statement, as shown in the following example of a list-directed stream I/O statement. The shorter lines are padded to the right with blanks to obtain a length of n characters. For example:

PUT FILE(F) SKIP LIST(A,B,C);
PUT FILE(F) SKIP;

In this example, the current line (consisting of data previously output) is output and one or more new lines containing the values of A, B, and C are created. The second PUT statement forces the last line containing A, B, and C to be output and starts a new line. The SKIP option is always executed before any new data is transmitted.

On input, each line can be of any length up to the value of the line size. Execution of a GET statement reads from the current line until a new line is reached, the new line is ignored, and execution continues reading values and lines until the list of variables has been read. A SKIP option can be used to force a new line to be read prior to reading any values, as shown in the following example.

GET FILE(F) LIST(A,B,C);
GET FILE(F) LIST(D);
GET FILE(F) SKIP LIST(X,Y);

In the previous example, A, B, and C are read from the current line or from as many lines as are necessary. D is read from the same line as C, unless C happened to be the last value on its line. The SKIP option skips to a new line and consequently ignores any values remaining on the line after the value received by D. X and Y are read from the line that is current after the SKIP option, as well as any additional, necessary lines.

The PAGE option can be used in a PUT statement to begin a new page prior to transmitting any values, as shown in the following example.

PUT FILE(F) PAGE LIST(A,B,C);

For a complete discussion of GET, PUT, and FORMAT statements, see the chapter Statements.

Note:

Standard PL/I, in a stream file, does not provide a way to read a variable-length input line from the current position to a newline indicator. Open PL/I provides two nonstandard methods to read all characters from current position to new line into a character varying variable: a READ statement and an edit-directed GET statement. To read a variable-length line with a GET statement, you must use an A-format without a field width.

  • List-Directed Stream I/O
  • Data-Directed Stream I/O
  • Edit-Directed Stream I/O
  • Terminal I/O on a Stream File
Parent topic: Input and Output
Related information
Stream File Attributes
Statements
READ
A-Format


List-Directed Stream I/O

Values transmitted by list-directed stream I/O are separated by blanks or commas on input and by blanks on output. Each value is transmitted in a readable format determined by the value's data type.

In a GET LIST operation, Open PL/I automatically converts ASCII input data to the data types of the variables specified in the GET LIST statement. In a PUT LIST operation, Open PL/I converts a computational expression to its ASCII equivalent for output.

The following example of simple terminal output demonstrates list-directed stream I/O:

PUT LIST(A,B);

In this example, if A is an integer declared fixed binary whose current value is -75, and B is a character-string declared character(5) whose current value is HAT Boxes, the example produces:

in the current output line of file F. The field boxes -75 is produced by converting the fixed binary(15) integer to a character-string. The many blanks allow for the maximum possible value, plus sign and decimal point and leading 0 for fractional values, as explained in the section Arithmetic to Character-String Conversion in the chapter Data Type Conversions. A single blank separates the value of A from the value of B. The last blank separates B from the next field.

For input, list-directed I/O considers each blank or comma as a field terminator. Excess commas are not allowed. Excess blanks within a field to be assigned to an arithmetic variable are ignored. Such fields must simply contain a valid constant, as could be written in the text of a program.

A field to be assigned to a character-string variable may contain a character-string constant, as written in the text of a program, or it may contain a sequence of any characters. In the latter case, the sequence begins with the first non-blank character in the field and ends with the character immediately preceding the next comma or blank, as shown in the following example of a GET LIST operation. Note that character sequences containing blanks or commas that are to be treated as a unit must be enclosed in single quotation marks ("). For example:

GET FILE(F) LIST(A,B);

In this example, if A is fixed binary(15) and B is character(5), the following lines have the indicated effect on the values of A and B.

Line | A | B
boxes | 5 | boxes
boxes | -4 5 | boxes
boxes | -4 5 | abc-4
Parent topic: Stream I/O
Related information
Arithmetic to Character-String Conversion


Data-Directed Stream I/O

Data-directed stream I/O is similar to list-directed stream I/O. The difference is that with data-directed stream I/O, the actual Open PL/I program names of the data values are included in the stream file along with the values. For example, if your program contains the structure:

DECLARE 1 STRUC,
            2 NUM(2) FIXED BIN(15) INIT(255,-432),
            2 TEXT CHAR(4) INIT('abcd');

and outputs this data with a PUT DATA statement, the characters emitted for STRUC would be:

STRUC.NUM(1)     255  STRUC.NUM(2)=   -432 STRUC.TEXT='abcd' ;

Each data value is preceded by the fully-qualified and specifically subscripted PL/I program name of that data value, as shown. The values themselves are formatted as they would be by a PUT LIST statement, except that character values are always enclosed in quotes.

Parent topic: Stream I/O


Edit-Directed Stream I/O

Values transmitted by edit-directed stream I/O are transmitted into fixed-length fields whose length and content are controlled by data-formats. Data-formats specifically control the type of conversion to be performed and the number of characters or digits in an input or output field. Each data-format corresponds to an element of the GET or PUT statement's value list and causes that value to be converted and transmitted. For example:

PUT FILE(F) EDIT(A,B) (F(7,2),A(6));

In this example, if A is declared fixed binary(15) and has a current value of -45, and B is declared character(4) and has a current value of HAT box, the following is written into the current line of file F.

Control formats can be used to force new lines and skip parts of lines, as shown in the next example. If there are more format items than values to be transmitted in the statement's I/O list, the extra format items are ignored. For example:

PUT FILE(F) EDIT(A,B) (X(3),F(7,2),SKIP,X(4),A(6),SKIP);

Using the same values of A and B as in the previous example, the above statement produces the following:

In this example, the first line is placed at the end of the current line, and the second line starts a new output line. The PUT statement does not start another new line, because B was the last item output; hence, the PUT statement terminated before the second SKIP was executed.

Edit-directed input requires that each input line be described precisely by the controlling format. If the current input line contains fewer characters than are required to satisfy the format, additional lines are read until the format is satisfied, as shown in the following example.

GET FILE(F) EDIT (X) (A(80));

In this example, if X is declared as character(100) and the current line contains only 60 characters, the 60 characters are read, a new line is read, processing advances to the next line, and 20 additional characters are read from that line. The 80 characters thus read are then assigned to X, and 20 blanks are used to pad the value of X on the right.

Parent topic: Stream I/O


Terminal I/O on a Stream File

If a terminal device is opened as a stream file, the file is unlike any other stream file in the following respects:

  • Each PUT statement transmits data to the device without waiting for the line to be filled.
  • A GET statement resets the current column position used by subsequent PUT statements.
  • Stream File Attributes
  • Print Files
Parent topic: Stream I/O


Stream File Attributes

The following attributes are appropriate for use with stream files. Some may be used in either the DECLARE statement for the file constant or in the OPEN statement, others only in the OPEN statement.

Attribute | Permitted in Specification
STREAM | DECLARE or OPEN
INPUT | DECLARE or OPEN
OUTPUT | DECLARE or OPEN
PRINT | DECLARE or OPEN
LINESIZE | OPEN
PAGESIZE | OPEN
TITLE | OPEN

The use of PRINT implies STREAM OUTPUT. If neither INPUT, OUTPUT, nor PRINT is specified, INPUT is assumed. LINESIZE and PAGESIZE can be used only for PRINT files. If neither STREAM nor RECORD is specified, the default is STREAM. (See the section Record I/O.) STREAM and RECORD are mutually exclusive, as are INPUT and OUTPUT. If attributes are specified both in the DECLARE statement and the OPEN statement for a file, the attributes used are the combination of those in the two statements. The combination may include only one of each mutually exclusive set.

The TITLE option is used to associate a file as declared in the PL/I program with a file or device as known to the operating system. In the following examples of OPEN statements, the quoted text in the TITLE options specifies the system filename or device name to be used in I/O operations with the opening of the PL/I file indicated by the FILE option. If the TITLE option is not specified in an OPEN statement, the declared name of the file constant is used as the default title.

The LINESIZE option is used in an OPEN statement to specify the maximum number of characters that can be output in a single line for a STREAM file. If no line size is specified, a default line size is assumed. For more information on LINESIZE, see the section PUT in the chapter Statements.

The LINESIZE option can appear in the OPEN statement only and is valid only with STREAM OUTPUT files. During output, a newline will be inserted whenever the column position equals (LINESIZE+1). The SKIP or LINE options with a PUT statement cause a newline character to be inserted and the column position to be reset. The COLUMN format with a PUT EDIT statement may cause a newline to be inserted.

The default may vary according to the file name or device. In Open PL/I, the default value of the LINESIZE option is 120.

The PAGESIZE option is used in an OPEN statement to specify the maximum number of lines that can be written to a print file without signaling the ENDPAGE condition. If no page size is specified, a default page size is supplied. In Open PL/I, the default value of the PAGESIZE option is 60.

If a GET or PUT statement is executed on a file that has not been opened, the file is implicitly opened as a STREAM file using the declared name of the file constant as the title. A file so opened by a GET statement is opened as an INPUT file, one so opened by a PUT statement is opened as an OUTPUT file.

You can add text to any existing stream file (any ASCII file) by using the -APPEND option in the TITLE option of the OPEN statement. Thus, if the file you wish to append to is named "logfile," open it with the following TITLE option:

TITLE('logfile -APPEND')

Any subsequent PUT statements to this file simply append their output to the end of the file.

  • Examples:
Parent topic: Terminal I/O on a Stream File
Related information
Record I/O
PUT
TITLE Options


Examples:

OPEN FILE(F) OUTPUT TITLE('thedata');

OPEN FILE(TTY) TITLE('CONSOLE')
   STREAM INPUT;

OPEN FILE(PTR) TITLE('LPT1')
   STREAM OUTPUT PRINT LINESIZE(132)
   PAGESIZE(60);

OPEN FILE(MSG_FILE) INPUT;
                  /* The default title is 'MSG_FILE' */
Parent topic: Stream File Attributes


Print Files

An output stream file opened with the PRINT attribute indicates that the file is a print file. When a file is declared as a print file, the LINESIZE and PAGESIZE options may be specified at file opening to designate the maximum width of an output line and the maximum number of lines per page. The current line number and current page number of the print file can also be accessed using the PAGENO and LINENO built-in functions.

The LINENO built-in function allows you to access the current line number of an output stream file opened with the PRINT attribute. Each time a line is written to the output stream, the line number is incremented by one. Each new line is initially positioned so that the next item is written to column 1 of the line.

The PAGENO built-in function lets you read the current page number of an output stream file opened with the PRINT attribute. The current page number can be set using the PAGENO pseudo-variable. The ENDPAGE condition is signaled when the line to be written has a line number that is the page size plus one, or when a SKIP option positions the file to (or past) page size + 1.

Each time a new page is written, the line number is reset to one and the page number is incremented by one.

If an ON-unit for the ENDPAGE condition does not write a new page, the line number is allowed to increase indefinitely until a new page is written. The ENDPAGE condition is signaled only when the line to be written has a line number that is one greater than the page size.

A new page is written only by a PAGE option of a PUT statement, by a PAGE format-item, and by the default ON-unit for the ENDPAGE condition.

In Open PL/I, tab stops are set every eight columns for a stream file that has the PRINT attribute.

Parent topic: Terminal I/O on a Stream File


Record I/O

In Record I/O, file data is treated in terms of records. Record files are used with the READ, WRITE, REWRITE, and DELETE statements. Execution of one of these statements transmits one record to or from the file and updates the current position of the file.

A record is a contiguous set of bytes of data in the file. The records of the file may all be of the same fixed length, as specified when the file is created, or they may be of varying lengths. Certain files with variable-length records require that a maximum length be specified when the file is created.

The data bytes that comprise a record file may be ASCII characters, but they may also be any kind of binary data, including being paired as halfwords, grouped as binary fullwords or double words, grouped as packed-decimal strings, or considered as bit fields of any length.

Record files may be keyed or not. If a record file does not have keys, its records can be accessed only in sequential order as they exist in the file, one after the other from the beginning of the file to the end. Open PL/I supports two keyed access methods: indexed (VSAM) I/O, which is based on character-string keys, and relative record I/O, which is based on integer record numbers.

  • Record File Attributes
  • Consecutive Record I/O
  • Indexed Record I/O
  • Relative Record I/O
  • REGIONAL(1) Record I/O
  • TITLE Options
Parent topic: Input and Output


Record File Attributes

The following attributes are appropriate for use with record files. Some may be used in either the DECLARE statement for the file constant or in the OPEN statement, others only in the OPEN statement. Some attributes, if present, imply the presence of certain others.

Attribute | Permitted in Specification | Implied
RECORD | DECLARE or OPEN |
INPUT | DECLARE or OPEN |
OUTPUT | DECLARE or OPEN |
UPDATE | DECLARE or OPEN | RECORD
SEQUENTIAL | DECLARE or OPEN | RECORD
KEYED | DECLARE or OPEN | RECORD
DIRECT | DECLARE or OPEN | RECORD KEYED
ENVIRONMENT | DECLARE |
TITLE | OPEN |

If neither INPUT, OUTPUT, nor UPDATE is specified, INPUT is assumed. If neither SEQUENTIAL nor DIRECT is specified, SEQUENTIAL is assumed. If neither STREAM nor RECORD is specified, the default is STREAM. (See the section Stream I/O.) The following sets of attributes are mutually exclusive:

  • STREAM and RECORD
  • INPUT, OUTPUT, and UPDATE
  • SEQUENTIAL and DIRECT

If attributes are specified both in the DECLARE statement and the OPEN statement for a file, the attributes used are the combination of those in the two statements. The combination may include only one of each mutually exclusive set.

The TITLE option is used to associate a file as declared in the PL/I program with a file as known to the operating system. In the following examples of OPEN statements, the quoted text in the TITLE options specifies the system filename to be used in I/O operations with this opening of the PL/I file indicated by the FILE option. If the TITLE option is not specified in an OPEN statement, the declared name of the file constant is used as the default title.

Examples:

OPEN FILE(F) RECORD OUTPUT TITLE('thedata');

OPEN FILE(F) RECORD INPUT; /* The default title is 'F' */

If a READ, WRITE, REWRITE, or DELETE statement is executed on a file that has not been opened, the file is implicitly opened as a RECORD file using the declared name of the file constant as the title. The attributes assigned to the file implicitly opened depend on the I/O statement used, as indicated below:

Record I/O Statement | Assigned Attributes
READ | RECORD INPUT
WRITE | RECORD OUTPUT
REWRITE | RECORD UPDATE
DELETE | RECORD UPDATE

Record input and output operations are restricted to files opened with certain attributes. These restrictions are shown in the following table:

File Attributes | Permitted I/O Operations
INPUT | READ
OUTPUT | WRITE
UPDATE | READ, WRITE, REWRITE, DELETE

If a file opened for INPUT or UPDATE does not exist, an error is signaled.

If a file opened for OUTPUT does not exist, a file is created. If the file has been opened as DIRECT or KEYED SEQUENTIAL, a keyed file is created; otherwise, a non-keyed file is created.

If a file opened for OUTPUT already exists, it is deleted and a new file is created.

However, if the -APPEND option is specified in opening the file, an existing file can be opened for OUTPUT. You can add records to an existing record file by using the -APPEND option in the TITLE option of the OPEN statement. Thus, if the file you wish to append to is named "logfile," open it with the following TITLE option:

TITLE ('logfile -APPEND')

Any subsequent WRITE statements to this file simply append their output to the end of the file.

A REWRITE statement replaces an existing record in an UPDATE file with a new record. A DELETE statement basically removes an existing record from an UPDATE file. A WRITE to an existing record and a READ from a nonexistent record are not allowed. A WRITE to a record past EOF will append the record to the end of the file. A DELETE or REWRITE of a nonexistent record signals a KEY condition. (For further information, see the description of KEY in the section ON in the chapter Statements.)

Record I/O statements copy the storage of a variable to or from a record in a file (except in the case of READ operations using locate mode I/O, see below).

No conversion is performed and no check is made to ensure that the data being read is of the proper type to store into the variable. The variables used in INTO or FROM options cannot be unaligned bit strings or structures consisting entirely of unaligned bit strings, because such variables normally share a portion of their storage with other members of the same array or structure. Also, an expression cannot be used in a FROM or INTO option.

Note:

Structures with the UNION attribute cannot be used as variables in READ, WRITE, PUT, and GET statements.

READ operations can be performed in two "modes": move mode and locate mode. A READ statement that specifies the INTO option causes the input data to be stored directly into the variable referenced by the INTO option. This is called a "move mode" READ. A READ statement that specifies the SET option instead of the INTO option causes the input data to be stored in an unnamed storage buffer and causes the address of this buffer to be assigned to the pointer variable referenced by the SET option. This is called a "locate mode" READ.

A complete discussion of record I/O statements is found in the chapter Statements.

Examples:

READ FILE(CUSTOMERS) KEY(CUST_ID) INTO(CUST_RECORD);
PUT SKIP LIST(CUST_RECORD.NAME);
READ FILE(CUSTOMERS) KEY(CUST_ID) SET(CPTR);
PUT SKIP LIST(CPTR->BASED_RECORD.NAME);
Parent topic: Record I/O
Related information
Stream I/O
TITLE Options
ON
Statements


Consecutive Record I/O

A record file without keys is called a consecutive file. The records of such a file can be read only in the same sequential order in which they were written. Thus, a consecutive file can be read only one record after the other, starting with the first record in the file. A record of a consecutive file can be rewritten, but only immediately after it has been read.

A consecutive file is declared by including the CONSECUTIVE option of the ENVIRONMENT attribute. For example,

DECLARE ULOG RECORD OUTPUT FILE
        ENVIRONMENT(CONSECUTIVE RECSIZE(130));

In this example the RECSIZE option causes all records to be of length 130 bytes. If RECSIZE is omitted, variable length records may be written. In the latter case, there is no information automatically recorded in the file to indicate the length of the records. A program reading the file must have the ability to know how many bytes to read with each READ statement.

Example:

CONFILE: PROCEDURE OPTIONS(MAIN);

   DECLARE TEST RECORD OUTPUT FILE ENV(CONSECUTIVE);
   DECLARE REC1 CHAR(5) INIT('AAAAA');
   DECLARE REC2 CHAR(10) INIT('BEEBBBBBBB');

   OPEN FILE(TEST) TITLE('testdata');
   WRITE FILE(TEST) FROM(REC1);
   WRITE FILE(TEST) FROM(REC2);
   WRITE FILE(TEST) FROM(REC1);
   CLOSE FILE(TEST);

END CONFILE;

The file testdata resulting from this program will contain the following 20 bytes:

AAAAABBBBBBBBBBAAAAA
Note:

Open PL/I has an older method of accomplishing the same thing. It is done by using the TITLE option of the OPEN statement rather than the ENVIRONMENT attribute of the DECLARE statement. The following illustrates the old method.

DECLARE RECORD TEST OUTPUT FILE;
OPEN FILE (TEST) TITLE ('testfile -SAM');
Parent topic: Record I/O
Related information
TITLE Options


Indexed Record I/O

Open PL/I's indexed I/O, also called VSAM (Virtual Storage Access Method), involves the use of character-string keys that are stored in the records of the file. Every record has a key, and the keys are ordered lexicographically in an index that is associated with the file. The records can be accessed randomly by specifying the key of the desired record, or they can be accessed sequentially according to the order of the keys, or they can be accessed by a combination of these methods, as illustrated in the following table:.

File Attributes | Permitted Access
SEQUENTIAL | SEQUENTIAL only
DIRECT | KEYED only
KEYED SEQUENTIAL | SEQUENTIAL and/or KEYED in combination

An INDEXED (equivalently, VSAM) file is declared by including either the INDEXED or the VSAM option of the ENVIRONMENT attribute. For example,

DECLARE MASTER RECORD OUTPUT FILE
   ENVIRONMENT(VSAM KEYLOC(1)
   KEYLENGTH(12) RECSIZE(130));

The KEYLOC option specifies the byte position of the first byte of the key in the records, counting the first byte as KEYLOC(1). The KEYLENGTH option specifies the number of characters in the key. RECSIZE specifies the record length or, in the case of a file of variable-length records, it specifies the maximum record length.

Actually, it is necessary to specify RECSIZE, KEYLOC, and KEYLENGTH for a file only when it is created. Programs that read or update an existing indexed file do not need to include these options, although they may. Open PL/I can determine these characteristics from an existing file. If you are using full IBM mode, file header information is used when opening a VSAM file for output, rather than requiring you to specify RECSIZE, KEYLOC, or KEYLENGTH with the ENVIRONMENT attribute.

There are a number of options that can be specified with the ENVIRONMENT attribute. These options are described in the table below. This table also lists a number of options that are not needed or not supported in Open PL/I, but which a user may expect to find based on experience with other compilers.

Option
 | Description
ASCII | The ASCII option is assumed in Open PL/I.
BKWD | Specifies backward processing for indexed files read in the SEQUENTIAL mode; that is, sequential processing will start with the current record (or last, by default) in the file and proceed to previous records.
BUFFERS | The BUFFERS option is not needed in Open PL/I. If it is used, the Compiler ignores it.
BUFOFF | The BUFOFF option is not needed in Open PL/I. If it is used, the Compiler ignores it.
BUFND | The BUFND option is not needed in Open PL/I. If it is used, the Compiler ignores it.
BUFNI | The BUFNI option is not needed in Open PL/I. If it is used, the Compiler ignores it.
BUFSP | The BUFSP option is not needed in Open PL/I. If it is used, the Compiler ignores it.
CONSECUTIVE | Specifies a file with consecutive organization. For related information, see the description of the -defext compiler option in your Open PL/I User's Guide.
CTLASA | The CTLASA option is ignored.
CTL360 | The CTL360 option is not implemented in Open PL/I. If it is used, the Compiler issues a warning.
F | FB | FS | FBS | Specifies record format, where F = fixed length, B = blocked, and S = standard. Open PL/I treats any such specification as though it were F alone — fixed length.
GENKEY | Specifies a generic key, a character string that is a prefix of a key. A READ with a KEY clause returns the first record whose key is greater than or equal to the string specified by the KEY clause. A subsequent sequential READ (no KEY clause) will return the next record greater than the current record.
INDEXAREA(n) | The INDEXAREA option is not needed in Open PL/I. If it is used, the Compiler ignores it.
INDEXED | Specifies a file with indexed organization. For related information, see the description of the -defext compiler option in your Open PL/I User's Guide.
KEYLENGTH(n) | Specifies the length, n, of the embedded key for indexed files. KEYLENGTH can be specified only when INDEXED or VSAM is specified.
KEYLOC(n) | Specifies the starting location of an embedded key in a record. n must be within the limits: 1 ? n ? recordsize – keylength + 1. The default KEYLOC value is 1. KEYLOC can be specified only when INDEXED or VSAM is specified. Note: Be sure that KEYLOC considers the 2-byte prefix generated by specification of the SCALARVARYING option.
LEAVE | The LEAVE option is not needed in Open PL/I. If it is used, the Compiler ignores it.
MINRECSIZE(n) | Specifies the minimum record length, n. n must be an integer. This option allows for better disk space utilization. The MINRECSIZE option is required with V (variable-length) record formats. It is ignored for F (fixed-length) record formats. The values specified for the KEYLOC and KEYLENGTH options must be within the value specified by the MINRECSIZE option. For more information on the MINRECSIZE option, see below.
NCP(n) | The NCP option is not applicable in Open PL/I. Open PL/I treats INDEXED files the same as VSAM files.
NOWRITE | The NOWRITE option is not needed in Open PL/I. If it is used, the Compiler ignores it.
PASSWORD(pwd) | The PASSWORD option is not implemented in Open PL/I. If it is used, the Compiler issues a warning.
RECSIZE(n) | Specifies the maximum record length, n. n must be an integer.
REGIONAL(1 | 2 | 3) | The REGIONAL(1) option specifies files whose records are identified by their region numbers. The REGIONAL(2) and REGIONAL(3) options are not implemented in Open PL/I. If they are used, the Compiler flags it as an error.
REUSE | The REUSE option specifies that an OUTPUT file associated with a VSAM data set is to be used as a work file. .
SCALARVARYING | Used for the input and output of varying length records. SCALARVARYING enables the recognition of a two-byte prefix that specifies the current length of the records. Note: Be sure that KEYLOC considers the 2-byte prefix generated by specification of the SCALARVARYING option.
SIS | The SIS option is not needed in Open PL/I. If it is used, the Compiler ignores it.
SKIP | The SKIP option is not needed in Open PL/I. If it is used, the Compiler ignores it.
TP(MIR) | The TP(MIR) option is not implemented in Open PL/I. If it is used, the Compiler flags it as an error.
TRKOFL | The TRKOFL option is not needed in Open PL/I. If it is used, the Compiler ignores it.
U | D | DB | Specifies record format. Open PL/I treats any such specification as though it were F – fixed length.
V | VB | VS | VBS | Specifies record format, where V = variable length, B = blocked, and S = spanned. Open PL/I treats any such specification as though it were V.
VSAM | Specifies files organized for the virtual storage access method (VSAM). For related information, see the description of the -defext compiler option in your Open PL/I User's Guide.

A random access read of a record in an indexed (VSAM) file opened with the INPUT or UPDATE attribute is accomplished by a READ statement that includes the KEY option. For example,

READ FILE(PARTS) INTO(PART_REC) KEY(PART_NUM);

A sequential read reads the next record of the file after the last one read — using the key ordering — or the first record of the file, if no record has previously been read. For a sequential READ statement, the KEY option is omitted.

If a record has previously been read from a file opened with the UPDATE attribute, and no other intervening I/O operation has been performed, a REWRITE without key may be executed. In this case, the previously read record is overwritten with the new value. For example,

READ FILE(PARTS) INTO(PART_REC) KEY(PART_NUM);
PART_REC = NEW VALUE;
REWRITE FILE(PARTS) FROM(PART_REC);

However, a record of an indexed file can be randomly updated by specifying the KEYFROM option in the REWRITE statement. For example,

REWRITE FILE(PARTS) FROM(PART_REC) KEYFROM('12XJ04');

If an indexed file has been opened with the OUTPUT or UPDATE attribute, a WRITE statement using the KEYFROM option can be used to add new records to the file. The WRITE statement without KEYFROM is used to sequentially add new records to a file.

The DELETE statement can be used to remove records from an indexed file opened with the UPDATE attribute. The KEY option must be used to delete a record.

All keys used in an indexed (VSAM) file must by of type CHARACTER. If a KEY or KEYFROM option references a value that is not of type CHARACTER, the value is converted to CHARACTER before the I/O operation begins. Note that keys of type PICTURE are converted to CHARACTER without any actual change in the key contents. (See the chapter Data Type Conversions.)

An indexed (VSAM) file can have either fixed-length or variable-length records. The records are fixed-length if the F option is used with the ENVIRONMENT attribute when the file is created; they are variable-length if the V option is used. (See the table above.) If neither F nor V is specified, F is assumed.

In a fixed-length record file, all records must have the same length, which is the length specified by the RECSIZE option of the ENVIRONMENT attribute when the file was created. For a variable-length record file, RECSIZE specifies the maximum record length that is permitted in the file. The MINRECSIZE option must also be specified for a variable-length record file. This value specifies the minimum length that all records in the file must have. The keys of the file must be contained within this minimum portion of the file.

The SCALARVARYING option specifies that there is a two-byte prefix on all records in the data file. A user must take this into account when specifying the KEYLOC value. The KEYLOC value is the absolute byte position of the record starting at 1. This option can be used on either F or V record formats. It allows for more general use of character varying records in I/O statements, although character records can also be transmitted. When a character varying item is used in a WRITE or REWRITE statement, the two-byte prefix is retained with the record as it gets written out to the data file, if the SCALARVARYING option is set. Without the SCALARVARYING option, the prefix is not written; in this case, the remainder of the record is undefined beyond its current length. When a character record is written, a prefix will be added if SCALARVARYING option is set. The SCALARVARYING option lets you write and read records smaller then your max record size, without getting the RECORD condition. It also is useful when doing locate mode I/O.

When setting KEYLOC, it is very important to "compensate" for the two-byte prefix when the SCALARVARYING option is used.

The use of V type records provide a way to transmit partial records. Open PL/I does not require control bytes in the record for this support. The run-time system will automatically retain information concerning the number of bytes transmitted. Since no control information is needed in the record, the user should not change KEYLOC based on the record type. Only the SCALARVARYING option has impact on the KEYLOC location.

Although the PL/I language does not provide a mechanism by which multiple keys can be specified for a file, Open PL/I does provide a means for accessing data via multiple keys. After an indexed file has been created using one key (which is called the primary key), you can use the utility Ipivsam to add additional indexes (that is, keys) to the file. In the PL/I program each different key version of the data must be declared as a separate file. However, all of these declared files can actually be referencing the same set of data. For example,

DECLARE EMPFILE1 RECORD UPDATE FILE
   ENV(VSAM KEYLOC(1) KEYLENGTH(6) RECSIZE(145));
DECLARE EMPFILE2 RECORD UPDATE FILE
   ENV(VSAM KEYLOC(31) KEYLENGTH(3) RECSIZE(145) GENKEY);
DECLARE 1 EMP_
   2 EMP_ID       (CHAR(6),
   2 NAME         (CHAR(24),
   2 DEPARTMT     (CHAR(3),
   ...

OPEN FILE(CUSTFILE1) TITLE('employee');
OPEN FILE(CUSTFILE2) TITLE('employee');
                        /* same file, different key */

The following example program illustrates the use of the ENVIRONMENT variable and its options for I/O on a file with VSAM organization.

/* Example of VSAM I/O */

TEST: PROCEDURE OPTIONS(MAIN);

   %REPLACE TRUE BY '1'B; %REPLACE FALSE BY '0'B;

   DECLARE DB FILE ENV(VSAM KEYLOC(21) KEYLENGTH(120) RECSIZE(244));
   DECLARE DBG FILE ENV(INDEXED GENKEY KEYLOC(21)
      KEYLENGTH(120) RECSIZE(244));

   DECLARE 1 DB_RECORD,
      2 HEADER     CHAR(20),
      2 DBKEY      CHAR(120),
      2 STUFF      CHAR(100),
      2 NUMBER     FIXED BIN(31);

   DECLARE I FIXED BIN(31);
   DECLARE CS CHAR(26) STATIC
                     INIT('THEQUICKBROWNFXJMPSVLAZYDG');
   DECLARE C(26) CHAR DEFINED(CS);
   DECLARE LETTERS CHAR(30);

   /* CREATE DB */
   OPEN FILE(DB) RECORD KEYED SEQUENTIAL OUTPUT
               TITLE('MYFILE1');
   HEADER = 'DATA RECORD HEADER';
   STUFF = COPY('ABCDE',20);
   DO I = 1 TO 26;
      NUMBER = I;
      DBKEY = '@'||C(I) ||COPY('@',118);
      WRITE FILE(DB) FROM(DB_RECORD) KEYFROM(DBKEY);
      END;
   CLOSE FILE(DB);

   /* TRY A GENERIC READ THEN MOVE SEQUENTIALLY THRU THE FILE */
   OPEN FILE(DBG) RECORD KEYED SEQUENTIAL INPUT
               TITLE('MYFILE1');
   ON ENDFILE(DBG) GOTO EXIT_1;
   READ FILE(DBG) KEY('@') INTO(DB_RECORD);
   LETTERS = SUBSTR(DBKEY,2,1);
   DO WHILE(TRUE);
      READ FILE(DBG) INTO(DB_RECORD);
      LETTERS = TRIM(LETTERS) ||SUBSTR(DBKEY,2,1);
      END;
EXIT_1:
   CLOSE FILE(DBG);
   PUT EDIT(LETTERS)(A);
   IF LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' THEN
      PUT SKIP LIST('TEST PASSES');
   ELSE PUT SKIP LIST('TEST FAILS');

   PUT SKIP;
END TEST;
Parent topic: Record I/O
Related information
Open PL/I User's Guide
Data Type Conversions


Relative Record I/O

Open PL/I also provides an I/O method for accessing consecutive files by a numeric key representing the relative record numbers of the records in the file. This is called relative record I/O. It can be used only with files of fixed-length records, and it cannot be used with indexed (VSAM) files.

Relative record I/O files are regarded as keyed files, but the keys are not stored in the file. They are just the ordinal numbers of the records in the file. The keys must be positive integers. Any value used in a KEY or KEYFROM option of an I/O statement must be an integer or be capable of conversion to an integer.

The ENVIRONMENT attribute is not used in the declaration of a relative record I/O file. Instead, such a file is specified by using an extension of the TITLE option of the OPEN statement. The format of this TITLE option is as follows:

TITLE('filename -DAM n')

where n is the length of the records in the file. The length n includes two bytes that are normally added to the beginning of each record. This halfword is used to record special information about the file.(See the section TITLE Options.)

In general, the same set of PL/I I/O operations can be used with relative record I/O files as with indexed files.

A relative record I/O file can be created using an additional extension in the TITLE option, as follows:

TITLE('filename -DAM n -NOSIZE')

The -NOSIZE option indicates that the two-byte special field is not to be added to the data records. If -NOSIZE is specified for a file, the DELETE statement cannot be used with the file.

Parent topic: Record I/O
Related information
TITLE Options


REGIONAL(1) Record I/O

A REGIONAL(1) file does not have keys recorded in the records. Instead, each record is identified by its region number, which is an unsigned integer. The keys for a REGIONAL(1) file may be character strings consisting only of decimal digits, possibly preceded by leading spaces (which are interpreted as zeros), or the keys can be of integer type.

A REGIONAL(1) file contains data records and dummy records. A dummy record is identified by having a first byte with the hex value FF. Dummy records represent records that have been deleted or whose region numbers have been skipped over when the file was first created. You can also create them explicitly by writing a record whose first byte has the value hex FF. Dummy records are not ignored when the REGIONAL(1) file is read. An Open PL/I program reading a REGIONAL(1) file must be designed to deal with dummy records. You can replace dummy records with valid data records.

You can create a REGIONAL(1) file only by use of DIRECT OUTPUT mode using keyed WRITE statements. The records must be written in ascending region number order, but you may skip over region numbers. When a region number is skipped, a dummy record is written in its place. The KEY condition is raised if you attempt to write records other than in increasing sequence or if you attempt to write a record with a duplicate key.

An existing REGIONAL(1) file can be accessed in SEQUENTIAL INPUT or UPDATE mode, or in DIRECT INPUT or UPDATE mode. (Opening the file in OUTPUT mode causes the existing file to be overwritten.)

If a REGIONAL(1) file is opened for SEQUENTIAL access (INPUT or UP_ DATE), the records are retrieved in ascending order of their region numbers. Dummy records are retrieved as well as valid data records. With SEQUENTIAL INPUT, you can read all records of the file in ascending region number order; with SEQUENTIAL UPDATE, you can so read all records and update those you choose (including changing dummy records to valid data records, and valid data records to dummy records). The rules for sequential READ and REWRITE for REGIONAL(1) are the same as for CONSECUTIVE files.

A REGIONAL(1) file can be opened for INPUT or UPDATE in DIRECT access mode, in which case keyed READ, WRITE, REWRITE, and DELETE statements can be used. READ accesses dummy records as well as valid data records. WRITE and REWRITE are equivalent; either replaces an existing record (data or dummy record) with a replacement record (again, either a data or a dummy record). DELETE converts the record with the specified region number into a dummy record.

  • Example of REGIONAL(1) I/O
Parent topic: Record I/O


Example of REGIONAL(1) I/O

/* This program creates and updates a REGIONAL(1) file */

sample: procedure options(main);
   declare File1 file environment(regional(1) recsize(20));/*requires -defext
   declare Buffer char(20);
   declare FirstByte char(1) defined(Buffer);
   declare Key char(4) varying;
   declare Eof bit;

   put skip list('Creating REGIONAL(1) file with records 1, 5 and 9.');
   open file(File1) output;
   Buffer = copy('1',size(Buffer));
   write file (File1) from(Buffer) keyfrom (1);
   Buffer = copy('5',size(Buffer));
   write file (File1) from(Buffer) keyfrom (5);
   Buffer = copy('9',size(Buffer));
   write file (File1) from(Buffer) keyfrom (9);
   close file(File1);

   open file(File1) update;
   on endfile(File1) Eof = '1'b1;
   Eof '0'b1;       /* Initialize */
   put skip list('Reading file and updating the even numbered records.');
   read file(File1) into(Buffer) keyto(Key);
   do while (^Eof);
     if unspec(FirstByte) = 'FF'b4 then do;  /* dummy record */
       if (mod(fixed(Key,15),2) = 0) then do;  /* change even number ones *
       Buffer = 'rewritten';
       rewrite file(File1) from (Buffer);  /* rewrite current record */
       end;
     end;
    read file(File1) into (Buffer) keyto(Key);
    end;
   Eof = '0'b1; /* Reset */
   put skip(2) list ('Reading and displaying all records in file.');
   Key = '1';
   read file(File1) into(Buffer) key(Key);     /* direct read */
   do while (^Eof);
      if unspec(FirstByte) = 'FF'b4 then put skip list(Key,'<dummy record>');
      else put skip list(Key,Buffer);
      read file(File1) into(Buffer) keyto(Key);  /* sequential read */
      end;
   close file(File1);
   put skip;
end sample;

You can compile, link, execute, and display the output of the above sample program with the following commands:

mfplx sample.pl1 -defext -o sample.out
sample.out

The output is as follows:

Creating REGIONAL(1) file with records 1, 5 and 9.
Reading file and updating the even numbered records.

Reading and displaying all records in file.
1       11111111111111111111
2       rewritten
3       <dummy record>
4       rewritten
5       55555555555555555555
6       rewritten
7       <dummy record>
8       rewritten
9       99999999999999999999
Parent topic: REGIONAL(1) Record I/O


TITLE Options

Open PL/I supports a number of non-standard TITLE options that can be used to indicate the type of file being opened. These are as follows:

-SAM [n]

-DAM [n]

-NOSIZE

-APPEND [n]

-DELABORT [n]

where n is an integer indicating that the file has fixed-length records of length n bytes.

These options are included in the operand of the TITLE option immediately following the filename and separated from it by one or more spaces, as shown in the following examples:

TITLE('recfile.dat       -SAM 80')
TITLE('keyfile -DAM')

The -SAM and -APPEND options can be used with stream files, in which case the length, if specified, is ignored. -SAM is never required for stream files.

-SAM [n] specifies that the file is a consecutive file. If n is specified when the file is created, the file is created with records of fixed length n. The maximum value for n is 131,017 bytes. If n is not specified when the file is created, records written to the file can be of any length and of varying lengths. If -SAM is used when opening a file for OUTPUT, if the file already exists, it is deleted and a new file is created.

-DAM [n] specifies that the file is a relative record I/O file. If n is specified when the file is created, the file is created with records of fixed length n. If n is not specified when the file is created, the file is created as a variable-length record file. If -NOSIZE is not also specified, this length n includes the two bytes that are added as a halfword of length information at the beginning of each record.

-NOSIZE can be used alone or in combination with -DAM [n]. It specifies that the length halfword is not included at the beginning of each record. If -NOSIZE is used without -DAM [n], -DAM is implied.

-APPEND [n] has the same meaning as -SAM, except that when used in opening a file for OUTPUT, it causes an already existing file to be appended to rather than replaced.

-DELABORT causes the file to be deleted when it is closed.

If a file is opened for OUTPUT and none of these TITLE options is specified, and there is no ENVIRONMENT attribute in the file declaration, if the opening is for a DIRECT file, -DAM is assumed, and if the opening is not for a DIRECT file, -SAM is assumed.

Parent topic: Record I/O


Data Types

  • Introduction
  • Arithmetic Data
  • Picture Data
  • Character-String Data
  • Bit-String Data
  • Area Data
  • Locator Data
  • Label Data
  • Entry Data
  • File Data
  • Arrays
  • Structures
  • Arrays of Structures
  • Data Size and Alignment
Parent topic: Open PL/I Language Reference Manual


Introduction

Each value has a data type that determines which operations can be performed on the value and the way in which the value is represented in storage.

Data types are declared for variables, function results, named constants (such as files), and external procedures. They are also used with the ENTRY attribute to describe the data type of each parameter of a procedure.

Data types are declared using the following attributes:

Computational Data | Non-Computational Data
FIXED BINARY | POINTER
FIXED DECIMAL | LABEL
FLOAT BINARY | ENTRY
FLOAT DECIMAL | FILE
PICTURE | OFFSET
CHARACTER | AREA
CHARACTER VARYING |
BIT |

The attributes in the first column represent data items whose values can be manipulated by arithmetic or string operations and are therefore computational. The attributes in the second column refer to data used within a program for control structures and linkage and are therefore non-computational.

The data type of a value produced by an expression is determined by the operands and the built-in functions within the expression. The data type of a constant is determined by the syntax of the constant.

A variable capable of storing only one value, such as an integer or a character string, at any one time is called a scalar variable. An array variable is a collection of variables all of the same type. For example, an array might consist of 20 individual character strings. The variables contained in the array are called elements of the array. These elements all have the same name as the array. They are ordered by a numeric index, or perhaps several indices, and they are referenced by use of these indices. A structure variable is a collection of variables of arbitrarily mixed types. The variables contained in a structure are called members of the structure. The members each have their own name. A member may be referenced by its name alone, or its name may be qualified by the structure name to distinguish it from a member of another structure. A structure can contain subordinate structures as members, as well as array members and scalar members. Also, the elements of an array can be structures.

This chapter discusses each data type, beginning with computational data types.

Parent topic: Data Types
Related information
ENTRY
Types of Operators
Open PL/I Built-Ins


Arithmetic Data

Each arithmetic value is characterized by a base (binary or decimal), a scale (fixed-point or floating-point), and a precision (the number of digits in the value). These three properties collectively constitute the data type of the arithmetic value.

The data type of arithmetic values is expressed using the following attributes:

  • FIXED BINARY(p) and FIXED DECIMAL(p,q) for fixed-point data
  • FLOAT BINARY(p) and FLOAT DECIMAL(p) for floating-point data

where p is the precision and q is the number of fractional digits in the precision.

Each implementation of PL/I imposes limits on the maximum values of p and q, and these limits typically differ for each combination of base and scale. Refer to your Open PL/I User's Guide for information on the default precision and maximum precision for each arithmetic data type in Open PL/I.

  • Fixed-Point Binary Literals
  • Floating-Point Binary Literals
  • Fixed-Point Data
  • Floating-Point Data
Parent topic: Data Types


Fixed-Point Binary Literals

Fixed-point binary literals are treated the same way as fixed-point decimal literals. Examples of fixed-point binary literals are:

1000b, 1000.101B
Parent topic: Arithmetic Data


Floating-Point Binary Literals

The IBM compiler converts binary floating-point literals to short floating-point values if the precision is less than 21. However, Open PL/I ignores precision, and always converts the string to a floating-point decimal with the maximum permitted precision. Examples of floating-point binary literals are:

1000E201b, 1000.101E2B
Parent topic: Arithmetic Data


Fixed-Point Data

Fixed-point numbers contain p digits. For fixed-point decimal numbers, q of those digits may be fractional digits. Fixed-point binary numbers are always integers (q =0). For example:

DECLARE K FIXED BINARY(15);
DECLARE D FIXED DECIMAL(7,2);

In this example, the values of K are fixed-point integers with 15 binary digits. Therefore, K can hold any value in the range -32768 to +32767 or -(2**?15) to (2**?15)-1. The values of D are fixed-point numbers with seven decimal digits, two of which are fractional digits. Therefore, D can hold any value in the range -99999.99 to +99999.99.

Because most computers operate most efficiently with binary integers, fixed binary variables should be used whenever possible. The relative efficiency of fixed binary variables used as subscripts, string lengths, DO index variables, and so forth is very significant.

Refer to your Open PL/I User's Guide for a description of the -Iongint compiler option, which alters the default precision of fixed binary variables from 15 to 31.

Fixed decimal values generally require more bits of storage and are often more computationally complex than values represented in binary, but fixed decimal values are more efficiently converted to and from an external form (for example, at input and output). In certain instances, fixed decimal values may also be less prone to rounding error than their binary counterparts.

An attempt to calculate a fixed decimal value too large to be supported results in a signal of the ERROR condition. An attempt to calculate a fixed binary value too large to be supported will not result in any error and may cause unexpected results. For rules on precision and scale, see the chapter Data Type Conversions.

Operations involving both decimal and binary values always produce a binary result value. However, if the operation must yield a result that has a fractional part, the result is decimal.

If a fixed-point value is converted to a character string or bit string, the length of the string is determined by the declared precision of the fixed-point value p. For a discussion of the conversion rules, see the chapter Data Type Conversions.

Fixed-point values are never rounded unless explicitly rounded by the use of a built-in function. Assignment to a fixed-point variable truncates excess low-order digits. All possible roundings can be performed by using the CEIL, FLOOR, TRUNC, or ROUND built-in functions.

Fixed-point decimal values are always stored as an accurate representation of decimal fractions. A fixed-point decimal value of 10.50 is never represented as 10.49.

Fixed-point constants are written as decimal numbers with or without a decimal point, as shown in the following examples:

5
4.5
4100.01

If a fixed-point constant contains a decimal point, it is considered to be a scaled fixed-point value and is stored and accessed like a fixed decimal variable. Fixed-point constants without a decimal point are integer constants and can be used safely in operations with any other arithmetic value, regardless of that value's base or scale. It is advisable to always write integer constants without a decimal point.

The precision of a fixed-point constant is the number of digits in the constant.

Parent topic: Arithmetic Data
Related information
Open PL/I User's Guide
Data Type Conversions
Open PL/I Built-Ins


Floating-Point Data

Floating-point data is used to represent values whose magnitudes are too great or too small to be represented by fixed-point data. It may also be used to minimize precision loss in calculations where terms differ considerably in magnitude.

Unexpected results may appear when using floating-point values. The limited precision of floating-point variables and the fact that they cannot precisely represent most fractional values combine to produce behavior in a program that may seem strange. Furthermore, the floating-point implementation on many machines carries more precision in intermediate results than is strictly required by the rules of PL/I. Also, floating-point variables and constants are usually limited to only one or two actual internal precision values. For example, most implementations of the IEEE floating-point standard allow only "short" (23-bit) and "long" (52-bit) floating-point values. Finally, precise results may vary depending on the level of program optimization.

For example, consider the following program:

SAMPLE: PROCEDURE OPTIONS (MAIN);
DECLARE
   (F,G)    FLOAT BINARY (23);
   F = 3111;
   G = .14;
   IF F + G ^= 3111.14 THEN
      PUT LIST ('UNEQUAL RESULT');
END SAMPLE;

This program will actually print the UNEQUAL RESULT message when run on many machines, because the constant .14 and 3111.14 are not precisely representable as floating-point binary numbers. The assignment of .14 to G puts about 23 bits of precision of the constant into the variable. On most implementations, the sum is computed with an actual precision of 52 or more bits, preserving the 23 bits of precision that apply to the fractional part. However, that sum is being compared to the constant 3111.14. The constant will have 23 or 52 bits of precision. (In fact, a strict implementation of the rules of the language requires only that it have 20 bits of precision; for more information, see the chapter Data Type Conversions.) If 3111.14 is represented as a short floating-point number, 14 of the 23 bits of precision are taken up to represent 3111 and hence only 9 bits of the fraction appear in the constant. This will not result in an equal comparison to the constant 3111.14. If the constant is a long floating-point number, 38 of the 25 precision bits will be fractional and the comparison will still fail.

One attempt to fix this might be to change the program as follows:

SAMPLE: PROCEDURE OPTIONS (MAIN);
DECLARE
   (F, G, H) FLOAT BINARY (23);
   RESULT    FLOAT BINARY (23) STATIC INITIAL (3111.14)
   F = 3111;
   G = .14;
   H = F + G
   IF H ^= 3111.14 THEN
      PUT LIST ('UNEQUAL RESULT')
END SAMPLE;

This appears to truncate the sum to a "real" 23 bits of precision and to compare it to a constant of known precision. This will normally work. However, in the presence of optimization, the value of F + G may be used without reducing its precision through storing it in H and then reloading it.

Thus, as a general rule, comparing floating-point numbers for equality and inequality does not work reliably. Instead, check for equality using the following method:

ABS(FIRST-SECOND) < EPSILON

where the constant EPSILON must be chosen considering the goal of the application.

Floating-point numbers consist of a mantissa m, a base b, and an exponent e. A floating-point number is represented in the following format:

m*b**e

The mantissa m is a fraction containing at least p digits. The value of b and the possible range of e are defined by each implementation (for information on this implementation, refer to your Open PL/I User's Guide); however, if the base is binary, m contains the equivalent of at least p binary digits, and if the base is decimal, m contains the equivalent of at least p decimal digits. For example:

DECLARE X FLOAT BINARY(23);
DECLARE Y FLOAT DECIMAL(7);

In this example, the values of X are floating-point numbers whose mantissa contains the equivalent of at least 23 binary digits. The values of Y are floating-point numbers whose mantissa contains the equivalent of at least 7 decimal digits.

The representation of floating-point values in storage also depends on the implementation. An implementation may represent the mantissa in any base that it chooses, provided that it contains an equivalent of at least p binary or p decimal digits. On some computers, decimal floating-point values are represented by using a decimal mantissa, while other implementations use a binary or hexadecimal mantissa for all floating-point numbers.

Open PL/I represents floating-point decimal using a decimal mantissa and decimal exponent, and represents floating-point binary using a binary mantissa and binary exponent. For more information, refer to your Open PL/I User's Guide.

Because floating-point values may be represented in either base, and because excess digits may be lost during calculations, floating-point values may be approximate. However, any integer value that is converted to floating-point and converted back to integer retains its original value. Likewise, the floating-point calculations of addition, subtraction, and multiplication, when performed on integer values, produce integer values.

Floating-point constants are written as fixed-point constants followed by an exponent, as shown in the following examples:

5E+02
4.5E1
100E-04
.001E-04
0E0

Floating-point constants have a decimal precision of p, where p is the number of digits in the fixed-point constant. For example, 4.5E1 has a precision of 2.

When fixed-point constants such as 1.5 are used in operations with floating-point values, they should be written with an exponent to avoid run-time conversion of fixed-point decimal values to floating-point.

If floating-point values are converted to character strings or bit strings, the length of the resulting string is determined by p, not by the actual value. For a discussion of conversion rules, see the chapter Data Type Conversions.

Caution is necessary when using floating-point constants in arithmetic expressions. Floating-point constants are considered to be of type Float Decimal, and the rules for the precision of arithmetic results specify that the precision of the result of a floating-point operation is the maximum of the precisions of the operands. Consider the following example:

SAMPLE2: PROCEDURE OPTIONS(MAIN);
DECLARE
   X FLOAT BIN(52);
   X = 1E0 + .4999E0;
   PUT SKIP LIST(X);
END SAMPLE2;

The answer printed by this program is, surprisingly, .500000000000000E+000. This is because the two constants are Float Decimal with precisions of 1 and 4, respectively. The addition is performed and the result is converted to Float Decimal(4); the intermediate result of 1.4999 is rounded to 4 decimal digits, and the result is converted to Float Binary and stored in X. An attempt to correct this might be to change the expression to read

X = BINARY(1E0) + BINARY(.4999E0);

This does the computation in Float Binary. However, this converts the first constant to Float Bin(4) and the second to Float Bin(14), and does the computation in short floating-point on most machines. The short floating-point result is lengthened to Float Bin(52) and is then stored in X, giving an answer of 1.499900013208389E+000. The correct fix is to use the two-argument form of the BINARY built-in function:

X = BINARY(1E0,52) + BINARY(.4999E0,52);

This produces long floating-point constants and the computation is done with maximal precision, printing 1.499900000000000E+000. Another solution would be to rewrite the constants using trailing zeros to indicate a more precise constant:

X = 1.0000000000000000E0 + .4999000000000000E0;

This also gives 1.499900000000000E+000, since the computation is done in large enough precision and the result is converted directly to a high-precision floating-point value.

In general, when using floating-point constants in arithmetic expressions with floating-point variables, the precision of the result can be controlled by using the FLOAT and BINARY built-in functions on the operands. The results of operations on two floating-point constants may not be what is expected.

Exponentiation, MOD, and all transcendental functions (including SORT) operations on floating-point decimal data are actually performed using the floating-point binary operations. Thus, the range of the operands and the results of these operations are limited to the ranges for floating-point binary numbers.

Parent topic: Arithmetic Data
Related information
Data Type Conversions
Open PL/I User's Guide


Picture Data

Picture data represents fixed-point decimal values that are stored internally as character strings. The strings contain the characters that represent the numeric values in a specified-format (as indicated by special embedded symbols, such as a period or a comma).

Picture data is best used to manipulate a quantity arithmetically and then print or display its value using a special output format.

A pictured value is any value whose data type is either declared by a PICTURE attribute or is acquired by the P format in a FORMAT statement. Picture characters are the special characters that make up the picture specification in the PICTURE attribute and in the P format item. Following are examples of picture specifications declared by the PICTURE attribute:

DECLARE F PICTURE '$ZZ,ZZZV.99CR';
DECLARE G PICTURE '$$$,$$$V.99-';
DECLARE H PICTURE '$**,***V.999';
DECLARE I PICTURE '----9V.999';
DECLARE J PICTURE '9999V9999S';

If the value -1234.56 was assigned to each of the variables in these examples, the resulting picture values would be as follows:

Repetition factors can be used for sequences of identical picture characters. For example, the following declaration of J is equivalent to the one given above:

DECLARE J PICTURE '(4)9V(4)9S';
  • Picture Characters
  • Rules for Using Picture Data
  • Picture Repetition Factors
Parent topic: Data Types


Picture Characters

Picture characters can affect the numeric interpretation and/or the character representation of the value by marking the position occupied by decimal digits. The picture characters fall into the following categories:

Category | Character | Description
decimal place character | V | Affects the numeric interpretation of the value only. The decimal point character is not actually stored.
digit characters | 9, Z, *, Y | Mark the positions occupied by decimal digits and affect both the numeric interpretation and character representation of the value.
encoded sign characters | T, I, R | Represent a digit that has the sign of the value encoded in the same position with the digit, thereby affecting both the numeric interpretation and character representation of the value. These characters can be used wherever the digit specifier '9' is valid.
drifting characters | $, +, –, S | Used to indicate digits, and also symbols to be inserted in the internal representation of a character. (See the section Drifting Characters and Strings.)
insertion characters | Namely the decimal point (.), comma (,), slash (/), and space (B) | Inserted between digits to indicate that characters are inserted in the internal representation of the pictured value. Drifting characters also function as insertion characters when they are used singly.
credit and debit | CR, DB | Always specified as two-character symbols. (See the section Credit and Debit Characters.)

The following list explains the meaning of each picture character.

Character | Meaning
V Indicates the position of the "assumed" decimal point. All digit positions to the right of the 'V' are fractional digits.

Any value assigned to a pictured value is first scaled so that its decimal point is aligned with the 'V'. Only one 'V' character can appear in a picture. If a picture does not contain the 'V' character, it is assumed to be at the right end of the picture, implying an integer value.
B, ./ Indicate the positions at which a space (B), comma, decimal point, or slash, respectively, are inserted. These picture characters are inserted into the pictured value only if they are preceded by a nonzero digit or if they are preceded by a '9' or 'V' picture character. If they are not inserted, a zero suppression character (a blank) or an asterisk (*) is inserted instead.

If an asterisk or drifting string occupies the position preceding the insertion character and that position corresponds to a leading zero, the asterisk or drifting string character also suppresses the insertion character.

The 'V' and decimal point (.) must be adjacent to one another to ensure that the decimal point is in the same position in both the numeric and character interpretations. The period should follow the 'V' to ensure that it will be in the correct location and will appear whenever any fractional digit is significant.
Z Indicates a decimal digit with leading zero suppression.

The 'Z' causes zero suppression using a blank as the suppression character. A 'Z' must not be preceded by a '9' or a drifting string. A picture containing a 'Z' must also not contain an asterisk (*).

If 'Z' picture characters appear to the left of 'V', all leading zeros in positions corresponding to those 'Z' characters are suppressed. Nonzero digits and significant zeros are never suppressed. Suppressed zeros are represented by spaces.

If a 'Z' appears to the right of 'V', all digits in the value must be indicated by 'Z' characters. Fractional zeros are then suppressed only if all fractional digits are zero and all integer digits are suppressed. In this case, the internal representation contains only spaces in the digit positions.

Note:

Refer to the examples in the section Rules for Using Picture Data.
* Indicates a decimal digit with leading zero suppression. The '*' causes zero suppression using an asterisk as the suppression character. An '*' must not be preceded by a '9' or a drifting string. A picture containing an '*' must also not contain a 'Z'.

The rules for '*' are otherwise the same as those for 'Z'.
S Indicates the position of the plus sign (+) or minus sign (-), which may or may not be drifting. The 'S' causes the plus sign to be inserted if the numeric value is greater than or equal to zero, and causes the minus sign to be inserted if the value is less than zero.

If an 'S' occurs more than once in a picture, the entire field of 'S's is a drifting string and can only contain a 'V' and one or more 'B' , '.' or '/' picture characters. Such a field cannot be preceded by a '9', 'Z', or '*', and if it contains a 'V' followed by one or more 'S's, it cannot be followed by a '9'.

The total number of digits represented by a drifting string is one less than the number of 'S's in the field. The digits are zero suppressed and a sign of '+' or '-' is inserted immediately preceding the most significant digit of the value.

A single 'S' causes a sign of '+' or '-' to be inserted into the pictured value, at the location implied by the position of 'S' in the picture.
+ Indicates the position of the plus sign (+) to be inserted if the numeric value is greater than or equal to zero. Operates exactly like 'S', except that the sign of negative values is indicated by a blank.
– Indicates the position of the minus sign (–) to be inserted if the numeric value is less than zero. Operates exactly like 'S', except that the sign of positive values is indicated by a blank.
$ Indicates the position of the dollar sign ($) to be inserted. Operates like 'S', except that a '$' is inserted instead of either sign.
9 | Indicates a decimal digit, including leading zeros. The position occupied by '9' always contains a decimal digit, regardless of whether the digit is, or is not, significant in the numeric interpretation of the pictured value.
Y | Indicates the position of a decimal digit in which the zero digit is always suppressed by a blank, regardless of the position of 'Y' relative to other picture characters.
CR | Indicates the position at which 'CR' is inserted if the number is less than zero. These two characters must appear as a pair on the rightmost end of the picture. They are replaced by two blanks in internal representation if the value is not negative.
DB | Indicates the position at which 'DB' is inserted if the number is less than zero. Like 'CR,' these two characters must appear as a pair, may only appear on the rightmost end of the picture, and are replaced by two blanks in internal representation if the value is not negative.
T | Indicates the position of a decimal digit with an encoded plus or minus sign. The digit contains an encoded plus sign if the numeric value is greater than or equal to zero and an encoded minus sign if the value is less than zero. (See Table 2-1 for representations of encoded sign digits.)
I | Indicates the position of a decimal digit with an encoded plus sign if the numeric value is greater than or equal to zero. If the value is less than zero, the position contains an ordinary digit.
R | Indicates the position of a decimal digit with, possibly, an encoded minus sign if the numeric value is less than zero. If the value is greater than or equal to zero, the position contains an ordinary digit.

Digit | ASCII Character | Digit | ASCII Character
–0 | } | +0 | {
–1 | J | +1 | A
–2 | K | +2 | B
–3 | L | +3 | C
–4 | M | +4 | D
–5 | N | +5 | E
–6 | O | +6 | F
–7 | P | +7 | G
–8 | Q | +8 | H
–9 | R | +9 | I
  • Drifting Characters and Strings
  • Credit and Debit Characters
Parent topic: Picture Data
Related information
Drifting Characters and Strings
Credit and Debit Characters
Rules for Using Picture Data


Drifting Characters and Strings

Used alone in a picture, one drifting character marks the position where a special symbol or space is to be inserted. It does not affect the value's numeric interpretation. In this context, the character must appear either before or after all characters that specify digit positions.

If a series of n (n >1) drifting characters appears in a picture, the rightmost n-1 of the characters in the series also specify digit positions. If the digit is a leading zero, the leading zero is suppressed, and the leftmost character "drifts" to the right. In internal representation, the character appears either in the position of the last drifting character in the series or immediately to the left of the first significant digit, whichever comes first. In this context, the n-1 drifting characters also define a portion of the numeric precision of the picture variable, because they describe at least some positions occupied by decimal digits.

A drifting string is a series of more than one of the same drifting character. Only one drifting string can be used in a picture; other drifting characters can be used only individually to designate insertion characters, not digits.

The 'Z' and '*' characters cannot appear to the right of a drifting string.

A digit position cannot be specified to the left of a drifting string.

The following rules apply to insertion characters embedded in a drifting string:

  • If the drifting string contains an insertion character, the insertion character is inserted in the internal representation only if a significant digit appears to its left. In the position of the insertion character, a space appears if the leftmost significant digit is more than one position to the right; the drifting symbol appears if the next position to the right contains the leftmost significant digit.
  • If the drifting string contains a 'V' character, all digit positions to the right of the 'V' (the fractional digits) must also be part of the drifting string. Insignificant fractional digits are suppressed only if all integral and fractional digits are zeros; if so, they are replaced by spaces in the internal representation. If any digit is not zero, all fractional digits appear as actual digits.
  • Insertion characters that appear to the immediate right of a drifting string are considered part of the drifting string.
Note:

Refer to the examples in the section Rules for Using Picture Data.

Parent topic: Picture Characters
Related information
Rules for Using Picture Data


Credit and Debit Characters

Regardless of which character pair is included, 'CR' or 'DB', that character pair appears in the internal representation if the numeric value is less than zero. If the numeric value is greater than or equal to zero, the associated positions in the internal representation contain two spaces.

The credit and debit characters are always inserted with the same case used in the picture; for example, if lowercase 'db' is used in the picture, then lowercase letters are inserted into the pictured value, and if the combination of uppercase and lowercase characters, such as 'Db', is used, 'Db' is inserted into the pictured value. The 'CR' and 'DB' character pairs cannot be used in the same picture, and neither pair can be used in the same picture with any other character that specifies the sign of the value, namely, 'S', '+', '–' and the encoded-sign characters ('T', 'I', 'R').

Parent topic: Picture Characters


Rules for Using Picture Data

The rules for using picture data are as follows:

  1. A picture cannot contain more than one sign character ('+', '–', 'S', 'T', 'I', 'R', 'CR', or 'DB') unless all such sign characters are part of a drifting string.
  2. When a zero value is assigned to a pictured variable and the picture does not contain at least one '9', the entire pictured value is filled with blanks or with asterisks (*), depending on which zero-suppression character was used.
  3. When a nonzero value is assigned to a pictured variable, and the 'V' is followed by zero-suppression characters or by part of a drifting string, the 'V' stops zero suppression. For example:
    DECLARE A PICTURE 'ZZZV.ZZ';
DECLARE B PICTURE '***V.**CR';

    In this example, a value of . 01 assigned to A and B produces boxes and . boxes. A value of zero assigned to A and B produces boxes and ********.

  4. If a 'V' is not given, a 'V' is implied at the rightmost end of the picture.
  5. Each '9', 'Z', or '*' is considered to be a digit of precision. Within a drifting string each 'S', '+', '–', or '$', except the first one, is considered to be a digit of precision. All digits of precision following the 'V' are fractional digits. For example:
    DECLARE A PICTURE 'ZZZV.ZZ'
DECLARE B PICTURE '---V.z--'

    In this example, A has a precision of (5,2), while B has a precision of (4,2).

  6. Negative values cannot be assigned to a pictured variable unless the picture contains a 'CR', 'DB', '–', or 'S'. An error condition is signaled if a negative value is assigned to a pictured variable that does not contain 'S', '+', '–', 'T', 'I', 'R', 'CR', or 'DB'.
  7. Values assigned to pictured variables are truncated and aligned with the `V' as they would be when assigned to a fixed decimal variable of the equivalent precision.
  8. Used in contexts that expect an arithmetic value, or used with a relational operator, pictured values are converted to fixed-point decimal values with a precision p and q that are determined by the picture.
  9. A pictured value is operated upon as if it were a character-string value only when it is assigned to a character-string variable, and when it is an operand of the concatenate operator or of a built-in function that expects character-string operands. In all other contexts, pictured values are operated upon as if they were fixed-point decimal values.

Following are more examples of picture format output.

Example | Data | Picture | Output
1 | 12345.60 | $SSSSSSSSV.99 | $ boxes +12345.60
2 | 1.23 | **********V.99 | .********1.23
3 | 1.23 | ZZZZZZZZZZV.99S | boxes 1.23
4 | 1234.56 | Z.ZZZ ZZZV,99 | boxes 1.234,56
5 | 11011111 | 9999B9999 | 1101 boxes 1111
6 | 011335 | **/**/** | *1/13/35
7 | 1234567890 | 999999999V.99 | 234567890.00
8 | .33 | ZV.ZZ | box .33
9 | .75 | ZV.ZZ | box .75
10 | 1234567.89 | $999,999,999V.99DB | $001,234,567.89
11 | -1234567.89 | $999,999,999V.99CR | $001,234,567.89CR
12 | 1023 | YYYYY | 1 23

In example 1, '$' is a static character because it appears only once, whereas 'S' is a drifting character because it appears all the way to the decimal.

In examples 2, 3, and 4, the characters 'Z' and '*' are zero-suppression characters. The asterisk prints wherever a zero or blank would have printed, and the 'Z' substitutes blanks.

In example 5 the insertion character 'B' results in a space (blank). A blank is inserted wherever the 'B' appears in the picture format unless it is in a field of zero-suppression characters that are suppressing zeros at the time.

In example 7, the appearance of the character '9' results in the printing of a digit. All digits 0 through 9 are printed, except the leading one, which is truncated.

In examples 8 and 9, the character 'V', once encountered, turns off suppression; all characters after the 'V' are printed. Note that in Example 8, 'V' is not used before the decimal point, so the point is turned off, not on.

Examples 10 and 11 show the result of positive and negative data applied to pictures that contain either 'CR' or 'DB'.

Parent topic: Picture Data


Picture Repetition Factors

A picture repetition factor is an integer specifying the number of times the following picture character is to be repeated. The repetition factor is enclosed within parentheses (there can be no blanks within the parentheses). If the value of the repetition is 0, the following picture character is ignored. For example:

pic '(4)9V(2)9'

is the same as

pic '9999V99'
Parent topic: Picture Data


Character-String Data

A character-string value is a sequence of characters. The number of characters in a sequence is called the length of the sequence. In Open PL/I, the maximum length of a string value is 32767 bytes or characters.

A character-string of zero length is called a null string.

Note:

Any string produced as an intermediate result requires storage allocated either on the stack or in the system storage area used to support the ALLOCATE statement. Allocation of a large temporary storage block that exceeds the amount of available storage results in a signal of the ERROR condition.

A character-string variable or character-string valued function is declared with the following attributes:

CHARACTER(n)

or

CHARACTER(n) VARYING

where n is an integer valued expression that specifies the maximum length of all string values that can be held by the variable or returned by the function.

The VARYING attribute causes the string variable or function to hold or return values of varying lengths. Internally, the length of the varying string is recorded along with the value. Varying strings are not padded to assume their maximum length, n. The representation of a varying string variable in storage is such that any string up to n characters may be held by the variable, and the length of the current string is retained as part of the value.

Without the VARYING attribute, a string variable or function always holds or returns values of length n. An assignment to a nonvarying string always extends short values with blanks on the right to make them n characters long.

Assignments of a string of more than n characters to either a VARYING or a nonvarying string variable cause only the leftmost n characters to be assigned and excess characters to be truncated.

Character-string values are compared from left to right using the collating sequence of the computer. Strings of unequal length are compared by effectively extending the shorter string with blanks on the right.

Nonvarying character-string variables always occupy exactly n bytes of storage. As elements of arrays or members of a structure, they begin on the next available byte and are not aligned on word or other storage address boundaries. This permits an array of nonvarying characters to be stored and accessed as if it were a single string. See the section Storage Sharing in the chapter Storage Classes.

Varying character-string variables always occupy n+2 bytes of storage. The first 2 bytes contain an integer L (0 <= L <= n) that specifies the length of the string value currently stored in the variable. The string text occupies the first L bytes of the storage following the 2 length bytes. The value of the last n–L bytes of the variable is undefined. The alignment of varying character strings is specified in your Open PL/I User's Guide. The value L can be accessed using the LENGTH built-in function. An array of varying character strings cannot be accessed as if it were a single character string.

A character-string constant is written in the following format:

'Any characters except quote'

If an apostrophe is required within the constant, it must be written as an adjacent pair of apostrophes.

Examples:

'ABC'
'He said, "I don"t know."'
''

In these examples, the second string displays a pair of single quotation marks used within the text string "don't". This text string also shows that the double quotation mark is insignificant as a delimiter of a character-string constant. The string in the last example is a null string.

  • String Repetition Factors
Parent topic: Data Types
Related information
Storage Sharing
Open PL/I User's Guide


String Repetition Factors

Repetition factors can be used with character and bit strings. For example:

(4)'Abc'

is equivalent to a character constant where 'Abc' is repeated four times, 'AbcAbcAbcAbc'

and

(4) '10'B

is equivalent to

'10101010'B

The maximum string repetition factor is 32767.

Parent topic: Character-String Data
Related information
Picture Repetition Factors


Bit-String Data

A bit-string is a sequence of binary digits (bits). The number of bits in the sequence is called the length of the value.

A bit-string of zero length is called a null string.

A bit-string variable or bit-string valued function is declared with the following attributes:

BIT(n)

or

BIT(n) ALIGNED | UNALIGNED

where n is an integer valued expression that specifies the maximum length of all string values that can be held by the variable or returned by the function.

If a value of less than n bits is assigned to a bit-string variable, the variable is extended on the right with zero bits to make it n bits long. If a value of more than n bits is assigned, only the leftmost n bits are stored, and the excess bits are truncated.

The ALIGNED attribute causes the associated bit-string variable to be aligned on the storage boundary (described in your Open PL/I User's Guide) so as to make it more efficiently accessed. This attribute may also cause the variable to occupy more than n bits, but it does not increase the size of values that can be stored in the variable.

The UNALIGNED attribute causes the associated bit-string variable to be aligned at the next available bit so as to reduce storage requirements. If neither ALIGNED nor UNALIGNED is specified, UNALIGNED is assumed by default.

In the following structure declaration,

DECLARE 1 S ALIGNED,
        2 A BIT(3),
        2 B BIT(7) UNALIGNED,
        2 C BIT(1) UNALIGNED;
        2 D BIT(5);

the bit strings are stored as follows:

Stored Bit Strings

In this example the A and D strings are aligned because they inherit the ALIGNED attribute from the structure declaration. A bit string occupies a full byte. If the structure S had been declared with the UNALIGNED attribute, the A and D strings would be unaligned.

Bit-string values are compared from left to right, a bit at a time until an inequality is found. The shorter operand is effectively extended by zero bits on the right to make it the length of the other operand for purposes of comparison.

A bit-string is not a word of storage in a computer and is not an arithmetic value. It is a sequence of bits that is always operated upon from left to right, just as a character string is operated upon from left to right.

A bit-string constant is written as a quoted string of zeros and ones followed by a B.

A bit string of length one is a boolean value with the possible values of '0'B and '1'B, which denote false and true, respectively.

Note: No assumptions should be made about the form in which a bit-string is stored.

Examples:

'1'B
'10110'B
'O'B
''B

The last string in the previous set of examples is a null bit string.

Bit-string constants may also be written using a string of characters to represent the bit string:

'character string'Bn

where n is 1, 2, 3, or 4 and is the number of bits each character represents. The table below gives the set of permissible characters and shows the corresponding bit-string values. In this table, a '–' indicates 'invalid.'

Character
 | B or B1 | B2 | B3 | B4
0 | 0 | 00 | 000 | 0000
1 | 1 | 01 | 001 | 0001
2 | – | 10 | 010 | 0010
3 | – | 11 | 011 | 0011
4 | – | – | 100 | 0100
5 | – | – | 101 | 0101
6 | – | – | 110 | 0110
7 | – | – | 111 | 0111
8 | – | – | – | 1000
9 | – | – | – | 1001
A | – | – | – | 1010
B | – | – | – | 1011
C | - | - | _ | 1100
D | – | – | – | 1101
E | – | – | – | 1110
F | – | – | – | 1111

For example:

Bit-String | Equivalent Value
'073'B3 | '000111011'B
'A04'134 | '101000000100'B
Parent topic: Data Types


Area Data

An area is a region of storage in which based variables can be allocated and freed. Area variables can have any storage class and may be scalars or arrays. Explicit declaration with an area attribute has the following format:

AREA[(exp [REFER (variable)])]

or

AREA (*)

The exp used with the area attribute specifies the number of bytes reserved for the area. This size is rounded up to an 8-byte boundary as necessary.

For an area with the STATIC storage class, the size must be an integer constant.

For areas having the AUTOMATIC, CONTROLLED, or BASED storage classes, the size is defined by an integer expression; if an area is a member of a BASED structure, however, the size specification can use the REFER option.

If neither expression nor asterisk is specified, the default size is 1000 bytes. For example,

DECLARE AREA1   AREA(4096),
   AREA2        AREA,
   1 S       BASED,
   2 X       FIXED BIN(15),
   2 AREA3(1024 REFER(X));

An alternate way to declare an AREA is implicitly, through its use in the following contexts:

  • The IN option of an ALLOCATE statement. For example:
    ALLOCATE X IN(A1);
  • The OFFSET attribute of an offset variable declaration. For example:
    DECLARE 0 OFFSET(A1);

Area variables are always aligned on 8-byte boundaries. The UNALIGNED attribute is not applicable to AREA variables.

Only based variables can be allocated in an area. Use of an area allows related items to be allocated and freed only in that region of storage reserved for the area. The area can be assigned or transmitted as a unit, complete with all the allocations it contains. To preserve the desired alignment constraints in the area, the size of any allocation within the area is always rounded to an 8-byte boundary.

The amount of reserved storage that is actually in use is known as the "extent" of the area. When first allocated (prior to any allocation in it), the extent of the area is zero. The maximum extent is represented by the "area size." When a based variable is allocated or freed, the extent of the area is updated to reflect the change in the amount of storage in use. In addition, when a based variable is freed, the storage it occupied is added to a chain of available storage blocks within the area. The area extent and the free chain are maintained in an 8-byte control block, adjacent to the space reserved for the area.

Areas may be assigned and passed as arguments. However, areas cannot be compared or otherwise have any operators applied to them.

When an area variable is assigned to another, all allocations in the target area are freed and the extent of the target area is set equal to that of the source area.

The AREA condition is raised for an illegal area assignment detected at run-time. This situation occurs if the maximum size of the source area exceeds that of the target area. The AREA condition is also raised when an attempt is made to allocate a based variable within an area that has too little free storage to accommodate it. For more information about the AREA condition, see the "Area" section in the section ON in the chapter Statements.

Offset variables are used to indicate the locations of based variables within the area. See the discussion in the section Offset Data.

Parent topic: Data Types
Related information
ON
Offset Data


Locator Data

Locator data is data whose purpose is to specify the location of other, usually based or controlled, data. Open PL/I supports two types of locator data: pointers and offsets.

  • Pointer Data
  • Offset Data
Parent topic: Data Types


Pointer Data

A pointer value is the address of a variable's storage. For example:

DECLARE K FIXED BINARY(15);
DECLARE A(5) FIXED BINARY(15);
DECLARE P POINTER;
   .
   .
   .
P = ADDR(A(K));

In this example, P is a pointer variable that is capable of holding the address of any variable, with the possible exception of unaligned bit strings (for more information, see your Open PL/I User's Guide). The assignment statement uses the ADDR built-in function to calculate the address of A (K) and assigns that address as the value of P.

A pointer is used with a template to access the storage to which it points. For example:

DECLARE X FIXED BINARY(15) BASED;
   .
   .
   .
P->X = 10;

In this example, X is a based variable (that is, a template) describing a fixed-point binary integer. P is the pointer variable from the example at the beginning of this section. The assignment assigns 10 to A (K).

Pointers are often used to locate the storage of dynamically allocated based variables as described in the section Based Variables in the chapter Storage Classes, but may provide a mechanism for accessing another variable's storage, as shown in the previous two examples.

The null pointer value is produced by the NULL built-in function. It is a unique value that does not address any variable and is used to indicate that a pointer variable does not currently address anything, as shown in the following example:

DECLARE CHAIN_HEAD POINTER;
   .
   .
   .
CHAIN_HEAD = NULL();

The internal representation of NULL is determined by the -setnull compiler option. For more information on compiler options, see your Open PL/I User's Guide.

Pointer values may be assigned, compared for equality or inequality, passed as arguments, and returned from functions, but no calculations or conversions can be performed on them. They cannot be transmitted in stream I/O.

If the variable whose storage is addressed by a pointer value is freed, the pointer value should no longer be used. Use of such a pointer to access the storage causes unpredictable results.

The ADDR built-in function must not be used to calculate the address of an unaligned bit data. Consequently, when such a restriction is imposed, pointer values never address unaligned bit-string data. However, all other data can always be addressed by a pointer, regardless of the addressing capabilities of the computer.

Note:

The based variable that is used as a template normally must have the same data type as the variable addressed by the pointer. Violations of this rule cause unpredictable results. Programs that violate this rule and produce "correct" results may fail when compiled with optimization enabled or may fail when moved to another implementation of PL/I.

A pointer value cannot be represented by a constant. However, the NULL built-in function can be used in any context, including an INITIAL attribute, where a constant might be desired.

Parent topic: Locator Data
Related information
Open PL/I User's Guide
Based Variables
Storage Sharing


Offset Data

The OFFSET attribute describes a locator data type that is used to specify the location of a based variable within an area. The format of the OFFSET attribute is:

OFFSET [(area-variable)]

An offset variable is a locator used only in conjunction with an area variable. The value of an offset variable specifies the location of a based variable within an area, relative to the beginning of the area. Since an offset value specifies a relative location, the value remains valid even when the area is assigned to another region of storage.

To use an offset variable to identify a particular based variable, the offset variable must be associated with an area. For example:

DECLARE A   AREA,
        O   OFFSET(A),
        X   FIXED BASED(O),
        Z   OFFSET,
        P   POINTER;

ALLOCATE X IN(A) SET(O);
X = 5;                  /* Implies area and offset */

This association can be done in the declaration by specifying the area variable, as shown in the previous example. This type of declaration has the convenience of implicitly referring to the associated area whenever a reference is made to the offset variable used as a locator.

When an offset value is assigned to or compared with another offset variable, only its actual value is used — the implicit area reference is ignored. However, when used as a locator, or when compared to or assigned to a pointer, the offset value is implicitly converted to a pointer by generating an address derived from the offset value combined with the address of the area with which it is associated. If this association was not done in the declaration, it can still be done using the POINTER built-in function:

P = POINTER(Z, A);   /* offset Z was not associated with
                           area A in its declaration */

Note that, if the offset variable did not have an area association in its declaration, then it is only with the POINTER built-in function that the offset variable can be used as a locator to address a variable within an area. For more information, see the description of the POINTER built-in function in the section POINTER in the chapter Open PL/I Built-Ins.

An OFFSET variable may be assigned a value in the following ways:

  • With the ALLOCATE statement

    For example:

    DECLARE X    FIXED BIN(31 BASED(01),
       Al    AREA,
       01    OFFSET(A1);

ALLOCATE X;     /*sets 01 = to the offset
                   of X in area A1 */

    Since the locator for X and the associated area of 01 are both specified in their respective declarations, the previous ALLOCATE statement is equivalent to:

    ALLOCATE X IN(A1) SET(01);
  • By assignment of another locator (offset or pointer) value
  • By assignment of the NULL() built-in function
  • By assignment of the OFFSET built-in function, which complements the POINTER built-in function (see the section POINTER in the chapter Open PL/I Built-Ins).
Parent topic: Locator Data
Related information
POINTER


Label Data

A label prefix on a statement, other than a PROCEDURE or FORMAT statement, is a declaration of a statement label.

The LABEL attribute can be used to declare variables and functions whose values are labels. For example:

A: PROCEDURE;
   DECLARE L LABEL;
      .
      .
      .
   L1:
      .
      .
      .
   L = L1;

In this example, the label variable L is assigned a statement label value. A subsequent GOTO L; would transfer control to the statement labeled L1.

A label value is a descriptor that consists of two parts. One part designates a statement (the instructions compiled for the statement) and the other part designates a stack frame of the block that immediately contains the statement. In the previous example, the assignment of L1 to L assigns a designator to the statement labeled L1 as part one of L, and assigns a designator to the current stack frame of procedure A as part two of L. The execution of a subsequent GOTO statement uses the stack frame designator only if the GOTO statement is executed in a block activation other than that indicated by the label value. For example:

A: PROCEDURE;
   DECLARE L LABEL;
      .
      .
      .
   L1:
      .
      .
      .
   L = L1;
      .
      .
      .
   GOTO L;
      .
      .
      .
   B: PROCEDURE;
      .
      .
      .
      GOTO L;
           .
           .
           .

In this example, execution of the first GOTO statement simply transfers control to L1 because it occurs within the same block activation in which L1 was assigned to L (and consequently, the stack frame component of L designates the stack frame that is current when the GOTO statement is executed). However, execution of the second GOTO statement occurs within a block activation other than that whose designator was assigned to L. Execution of the second GOTO statement first uses the stack frame designator of L to terminate the block activation of B and restore the block activation of A. The second GOTO statement then transfers control to the statement labeled L1. If A were a recursive procedure with more than one activation, the statement GOTO L in B would restore the most recent activation of A. Note that a label variable that is given L as a value will denote the activation of A current at the moment L is assigned, which may not be A's most recent activation. Use of a label variable after its associated block has exited may cause unpredictable results.

A single, optionally signed integer constant in the range -32768 to +32767 may be used to subscript a label. An array of labels is declared by the occurrence of subscripted labels. The elements of the array are all the subscripted labels having the same name and appearing within the same block. The highest subscript used is the upper bound of the array. The lowest subscript used is the lower bound of the array. The number of integers between the lower bound and the upper bound, inclusive, is the extent of the array. The array contains one element of each integer in the extent, although there may not be a subscripted label corresponding to the element. If you refer to an undefined element, the result is unpredictable. For example:

      GOTO CASE(K);
CASE(1):
   .
   .
   .
CASE(2):
   .
   .
   .
CASE(3):
   .
   .
   .
CASE(6):
   .
   .
   .

In this example, CASE is a one-dimensional array of statement labels containing six elements. Elements 4 and 5 are undefined and should not be used. Using an undefined element produces unpredictable results.

Label prefixes on PROCEDURE, FORMAT, BEGIN, and ENTRY statements cannot be subscripted.

Because the label array is declared by label prefixes, it cannot also be declared as a LABEL variable by appearing in a DECLARE statement.

Label values may be assigned, compared for equality or inequality, passed as arguments, and returned from functions, but no calculations or conversions can be performed on them. You may specify potential label values that can be assigned to a LABEL variable. They cannot be transmitted in stream I/O.

Parent topic: Data Types


Entry Data

Entry constants and variables are used to invoke procedures through specific entry points. Entry values specify entry points and block activations of procedures.

  • Entry Constants
  • Entry Variables
  • Entry Values
Parent topic: Data Types


Entry Constants

Entry constants are declared by labels or by PROCEDURE or ENTRY statements.

The leftmost label on a PROCEDURE statement is a declaration of the primary entry point of a procedure. Secondary entry points are established by the ENTRY statement. Names of external procedures that are not part of the compiled module must be declared using an ENTRY attribute and, if they are functions, a RETURNS attribute. For example:

DECLARE E ENTRY(FIXED BINARY(15), POINTER);
DECLARE F ENTRY((5) FLOAT DECIMAL(7))
   RETURNS(FLOAT DECIMAL(7));

In this example, E is declared as a procedure name that requires two arguments and that must be called as a subroutine by a CALL statement. F is declared as a procedure name that must be referenced as a function. F requires an array of five Float Decimal(7) values as its arguments and returns a Float Decimal(7) result.

Procedures, other than external procedures that are not part of the compiled module, are declared by their PROCEDURE statement and cannot be declared in a DECLARE statement.

Failure to declare a referenced external procedure that is part of another program module results in error messages from the Compiler.

Parent topic: Entry Data


Entry Variables

Entry variables are variables, including parameters, that take entry values.

The ENTRY attribute together with the VARIABLE attribute can be used to declare variables whose values are entry values. The ENTRY attribute can be used in a RETURNS attribute to indicate that a function returns entry values. For example:

A: PROCEDURE;
      .
      .
      .
   DECLARE E ENTRY VARIABLE;
      .
      .
      .
   E = A;

In this example, E is an entry variable that is capable of being assigned any entry value. The assignment causes the value of E to become a descriptor of the procedure named A.

Any parameter attribute or RETURNS attribute specified as part of an ENTRY attribute has no effect on the values that can be assigned to the ENTRY variable. However, when the entry variable is called, the value that it currently holds must designate a PROCEDURE statement whose parameters and RETURNS option match those given in the declaration of the entry variable.

In the previous example, a program that calls E as a function or calls E with arguments is invalid and produces unpredictable results.

Parent topic: Entry Data


Entry Values

Like a label value, an entry value is a descriptor containing two parts. The first part designates an entry point of a procedure, and the second part designates a stack frame of the block in which the procedure is declared. The second part of an ENTRY value that designates an external procedure is null.

The second part of the entry value is relevant only when there is more than one activation of a given procedure, as is the case with recursive procedures; otherwise, an entry value can be considered simply as a designator of an entry point.

Entry values can be assigned, compared for equality or inequality, passed as arguments, and returned from functions, but no calculations or conversions can be performed on them, and they cannot be transmitted in stream I/O.

The following discussion explains the second part of the entry value, called the stack frame designator.

  • The Stack Frame Designator
Parent topic: Entry Data


The Stack Frame Designator

If a procedure references variables local to its containing procedure, the inner procedure must be given a designator to the outer procedure's stack frame for it to be able to access the outer procedure's variables. The designator to the outer procedure's stack frame is the stack frame designator.

Except when the outer procedure has been activated recursively, only one stack frame for the outer procedure exists. The existing stack frame is the one that is always used when the inner procedure references variables declared in the outer procedure.

If the outer procedure has been activated recursively, the entry value used to call the inner procedure determines which stack frame is to be used when the inner procedure references the outer procedure's variables. For example:

A: PROCEDURE RECURSIVE;
   DECLARE X FIXED BINARY(15);
   DECLARE E ENTRY VARIABLE STATIC;
   IF FIRST-TIME
      THEN E=B;
      ELSE CALL F;
   CALL G;
.
.
.
B: PROCEDURE;
      .
      .
      .
      X=5;

In this example, assume that A calls G and that G calls A, then A calls F, and F calls the entry value held by E. When E is called, an activation of B results, because B was assigned to E. When that activation of B references X, two stack frames containing an instance of X exist. Two stack frames exist because two calls of A are still active. However, because the first of these two activations of A assigned B to E, E contains a designator to the first stack frame of A. Consequently, B assigns 5 to the first instance of X. If B were called directly from A, B would always use the most recent stack frame of A when referencing X.

An older stack frame is used only when an entry name is assigned to an entry variable or passed as an argument to an entry parameter. When the entry name is thus passed or assigned, the current stack frame of its containing block is assigned as the second component of the entry value produced by that assignment.

If the procedure name being assigned or passed as an argument is not declared within the block that is assigning or passing it, but is declared in a containing block, the containing block's stack frame is found using the same principle as was used to find X in the previous example. Once found, a designator to that stack frame is assigned as part two of the entry value.

Each stack frame for a block A has a designator to a stack frame of the block that contains A. That designator is the designator that was supplied as the second part of the entry value used to activate A. Unless the activation of A was the result of calling an entry variable or entry parameter, and unless recursion has been used, the stack frame thus designated is also the immediately preceding stack frame.

Parent topic: Entry Values


File Data

A file constant is represented by a file control block, which is an internal data structure maintained by Open PL/I. A file control block can be opened or closed and can thereby be connected to various files and devices known to the operating system. For example:

DECLARE F FILE;

In this example, F is a file constant that designates a file control block. That file control block can be opened, closed, and used to perform I/O on files and devices known to the operating system.

A file variable is represented internally as a longword containing a pointer to a file control block. When evaluated, the value of the file variable is the address of the associated file's control block.

A file variable is capable of being assigned any file value; it is declared using both the FILE and VARIABLE attributes. For example:

DECLARE G FILE VARIABLE;
DECLARE F FILE;
   .
   .
   .
   G = F;

In the previous example, G is a file variable assigned the value of the file constant F. After the assignment, operations on G are equivalent to operations on F because they both designate the file control block belonging to F.

File values may be assigned, compared for equality or inequality, passed as arguments, or returned from functions; however, no calculations or conversions can be performed on them, and they cannot be transmitted by stream l/o.

Parent topic: Data Types
Related information
File Constants


Arrays

An array is an ordered set of values all having the same data type. Elements of an array are referenced by their position within the array. Each array has a specified number of dimensions and each dimension has a specified lower and upper bound. The default low bound of a dimension is 1.

Array elements are stored in row-major order. The successive elements of a row are stored in adjacent memory locations. In arrays with more than two dimensions, the net effect is that when the elements are accessed in their storage order, the rightmost subscript varies most rapidly.

Examples:

DECLARE A(1:4) FIXED BINARY(15);
DECLARE B(0:3,0:5) FLOAT BINARY(21);
DECLARE C(-2:10) CHARACTER(5);
DECLARE D(25,4,2) POINTER;

In these examples, A is a one-dimensional array capable of holding fixed-point binary values. The lower bound is 1, the upper bound is 4, and the number of elements is 4.

B is a two-dimensional array capable of holding floating-point binary values. Both lower bounds are zero, and the upper bounds are 3 and 5. Therefore, B has 4 rows of 6 columns each.

C is a one-dimensional array capable of holding character-string values each of which has 5 characters. Its lower bound is -2 and its upper bound is 10, giving it a total of 13 elements.

D is a three-dimensional array capable of holding pointer values. Because no lower bounds are given, they are assumed to be 1. The array has a total of 200 elements organized as 25 planes, each of which is 4 rows in length and 2 columns in width.

The maximum number of array dimensions is 8. An array bound may be any number in the range -2^31 to 2^31 -1. Array bounds are also subject to the following restrictions:

  • The lower bound must be less than or equal to the upper bound.
  • The value (upper bound — lower bound) must be less than 2^31 -1.
  • The total size of the array must be less than 2^31 bytes. For information on calculating the size of an individual array element, see your Open PL/I User's Guide.
Note: The particular implementation of PL/I or the underlying operating system may also impose restrictions on the size of an individual data item, or on the total sizes of static and/or automatic data regions. For more information, see your Open PL/I User's Guide.

The bounds of AUTOMATIC, DEFINED, CONTROLLED, or BASED arrays may be specified by integer-valued expressions, as explained in the chapter Storage Classes. The bounds of STATIC arrays must be integer constants. The bounds of parameter arrays can be either integer constants or an asterisk (*). If an asterisk is given as the bound of a parameter array, it represents both the lower and upper bound and means that the actual bounds of the corresponding array argument are to be used as the bounds of the array parameter. For example:

DECLARE A(0:5) FIXED BINARY;
CALL P(A);
   .
   .
   .
P: PROCEDURE(X);
   DECLARE X(*) FIXED BINARY;
      .
      .
      .

During the call of P in the previous example, the bounds of X are (0:5), and any reference to X is a reference to A.

The elements of an array are referenced using as many subscripts as the array has dimensions. For example:

DECLARE A(-2:5,4,3) FIXED BINARY;

In this example, a reference to A (-2 ,1,1) is a reference to the element in the first column of the first row in the first plane. A reference to A (3,2,1) is a reference to the element in the first column of the second row in the sixth plane.

A subscript of an array must be an integer valued expression. The use of fixed-point fractions or floating-point values as subscripts results in an error message from the Compiler. However, such values can be converted to integer values by use of the TRUNC, CEIL, FLOOR, or ROUND built-in functions.

Each subscript must lie within the range specified by its corresponding lower and upper bound. Unless subscript range checking has been requested, the Compiler does not produce code to check the range of subscript values. If checking is requested, any subscript that exceeds its range results in a signal of the ERROR condition.

Subscripted references to array elements can be used in any context that permits a variable reference.

A cross-section of an array may be referenced by using an asterisk as a subscript. The asterisk refers to the entire range of the corresponding dimension (lower bound through upper bound). In the previous example, a reference to A (*,1,1), refers to the first-row, first-column elements in all eight planes. A reference to A ( *, *,*), refers to all 96 elements of the array.

Array cross-sections may be transmitted in stream or record I/O, passed as arguments, and assigned to other arrays of the same size and shape.

Parent topic: Data Types
Related information
Storage Classes


Structures

A structure is a hierarchically ordered set of values that may be of different data types. The immediate components of a structure are called members of the structure. A structure that is itself a member of another structure is called a substructure. A structure that is not a substructure is called a major structure.

The hierarchical organization of a structure is specified by using level-numbers, as shown in the following example:

DECLARE 1 S,
      2 A FIXED BINARY,
      2 B FLOAT BINARY,
      2 T,
            3 P POINTER,
            3 Q CHARACTER(10);

In this example, S is a major structure, also called a level-one structure. All major structures must have a level-number of 1. The members of S are A, B, and T. T is a substructure with members P and Q.

Members normally have a level-number that is 1 greater than their containing structure; however, they may be given any level-number that is greater than the level-number of their containing structure and less than the level-numbers they contain. For example:

DECLARE 1 S,
      20 A FIXED BINARY,
      20 B FLOAT BINARY,
      20 T,
            30 P POINTER,
            30 Q CHARACTER(10);

The structure shown in this example is equivalent to the structure shown in the example immediately preceding it.

An entire structure may be transmitted in stream or record I/O, passed as an argument, or assigned to another structure of identical size and shape and having members of corresponding identical data types, but no conversions or calculations can be performed on entire structures.

If a structure contains one or more members with a variable size, place all such members at the end of the structure following all the members with a fixed size. This placement improves the addressing of the fixed size members.

Members of structures can be referenced in any context that permits a reference to a variable. If a member's name is not otherwise declared in the same scope (that is, in the same block or containing block), the member may be referenced by its name alone.

The name of a member must be unique within its immediately containing structure, but may be used as the name of members of other structures or as the name of a nonmember. If a member's name has been used for more than one object, each reference to the member must be sufficiently qualified by the names of its containing structures to uniquely identify the intended member. In a qualified reference, the names used are listed in their hierarchical order, separated by periods. For example:

DECLARE        A FIXED BINARY;
DECLARE        1 S,
                  2 A FLOAT BINARY,
                  2 T,
                     3 A POINTER;

In this example, a reference to A is a reference to the fixed-point variable. A reference to S.A is a reference to the floating-point variable. A reference to T.A or S.T.A is a reference to the pointer variable.

Use of the major structure name as a qualifier is recommended. It is also advisable to avoid using the same member name more than once anywhere within the major structure or any contained structures. For more information, see the section Reference Resolution in the chapter References.

A structure may have the UNION attribute applied to it, which causes all immediate members of that structure to occupy the same memory locations. For more information, see the chapter Declarations and Attributes.

Parent topic: Data Types
Related information
Reference Resolution
Declarations and Attributes


Arrays of Structures

Structures, like other variables, can be declared as arrays and can contain arrays as members. For example:

DECLARE 1 S(5),
      2 A FIXED BINARY,
      2 B(4) FLOAT BINARY,
      2 T(3),
            3 P POINTER,
            3 Q(6) CHARACTER(10);

In this example, S is an array of 5 structures. Each structure contains a fixed- point member followed by an array of 4 floating-point values, followed by an array of 3 substructures. Each substructure contains a pointer variable followed by an array of 6 character-string variables. The entire structure contains 5 occurrences of A, 20 occurrences of B, 15 occurrences of T, 15 occurrences of P, and 90 occurrences of Q.

Each member of a structure array is itself an array because there exist as many instances of the member as there are elements in the structure array. If a member is an array in its own right because it has its own dimension information (as do B, T, and Q in the previous example), the array inherits the additional dimensions from its containing structures. For instance, in the previous example, Q is a three-dimensional array whose bounds are (5,3,6).

Any member of a dimensioned structure is an array and must be referenced using a subscript for each of its dimensions. The subscripts may be written anywhere within the structure-qualified reference, but it is preferable to write each subscript immediately following the name to which it applies. Using the previous example to illustrate this recommended programming practice:

S(K) .A | is a reference to the Kth element of A
S(K) .B(J) | is equivalent to B (K, J)
S(K) .T(J) .Q(I) | is equivalent to S.T.Q (K, J, I) or S.T(K,J) .Q(I) or S(K,J, I) .T.Q,

It is not possible to use an asterisk to reference an entire extent (cross section) of a structure array.

Members of dimensioned structures can be used only as arrays in stream I/O and as arguments to array parameters whose bounds have been specified as asterisks. They cannot be assigned, used in record I/O, used in ADDR or DEFINED, or passed to parameters with constant bounds.

Subscripted references to members of dimensioned structures can be used in any context that permits a variable reference.

Parent topic: Data Types


Data Size and Alignment

Refer to your Open PL/I User's Guide for the size and alignment of each Open PL/I data type.

Data not contained in a structure or array is allocated on a word or double word boundary, except for Character(1) and Bit(1) aligned data, which is allocated on a byte boundary.

  • ALIGNED and UNALIGNED Attributes
Parent topic: Data Types
Related information
Open PL/I User's Guide


ALIGNED and UNALIGNED Attributes

ALIGNED and UNALIGNED are optional data type attributes that control the storage boundary of data.

ALIGNED allows the Compiler to align the data on an implementation-defined storage boundary, with the possible side effect that more bits of storage are used than specified by the declared length. (Refer to your Open PL/I User's Guide for more information.)

UNALIGNED allows the Compiler to align the data on the next byte boundary (or, in the case of fixed-length bit strings, the next bit) rather than on implementation-defined storage boundaries. This can reduce storage requirements.

ALIGNED or UNALIGNED can be specified for scalar, array, or structure variables. The application of either attribute to a structure is equivalent to applying the attribute to all contained elements that do not have explicit alignment declaration. Operations on ALIGNED data tend to be more efficient; operations on UNALIGNED data usually are slower. They are considered part of the data type for purposes of argument/parameter matching and storage sharing.

The UNALIGNED attribute is the default for character and bit data types, while ALIGNED is the default for all other data types.

The UNALIGNED attribute has no effect with an AREA variable, which is always aligned on an 8-byte boundary.

Parent topic: Data Size and Alignment
Related information
Parameter Storage Class
Storage Sharing
Bit-String Data


Storage Classes

  • Introduction
  • Automatic Storage
  • Static Storage
  • Based Variables
  • Controlled Variables
  • Defined Variables
  • Parameter Storage Class
  • Storage Sharing
Parent topic: Open PL/I Language Reference Manual


Introduction

Every variable has a storage class that determines how and when storage is allocated for it. A variable's storage class specifically determines whether storage will be allocated for it at compile time or dynamically during program execution.

Storage classes are declared for all variables, except those used as parameters, using one of the following attributes:

  • AUTOMATIC
  • STATIC
  • BASED
  • CONTROLLED
  • DEFINED

If no storage class is specified for a variable declared in a procedure, other than a parameter variable, the default is AUTOMATIC. If a variable is declared outside the scope of all external procedures in a source module, the default storage class is STATIC.

A parameter shares storage with its argument. As such, the storage class is ultimately determined by that of the associated argument. For convenience, a parameter may be considered to have a distinct "parameter" storage class.

A variable's storage size is determined by its extents. A string variable's extent is its declared length. An array variable's extents are determined from the number of its dimensions and the range of its subscript bounds. The extents of both types of variables are evaluated when storage is allocated for the variable. The permitted forms for extents differ for each storage class and are described during the discussions of each storage class.

Parent topic: Storage Classes


Automatic Storage

Storage for an automatic variable is allocated with each activation of the procedure or the BEGIN block in which the variable is declared. Storage is allocated within the stack frame that represents that block activation. If a block is activated recursively, each of its stack frames contains a distinct instance of all automatic variables declared in that block.

When a block activation ends, its stack frame is popped from the stack, thereby freeing the storage of all automatic variables allocated within it. This phenomenon normally occurs when a procedure returns to its caller or when a BEGIN block executes its END statement; however, it also occurs when a GOTO statement transfers control back to a previous block activation. In the latter case, all block activations between the one to which control is transferred and the one in which the GOTO was executed are ended. Their stack frames are popped from the stack, releasing the storage for all of their automatic variables. The INITIAL attribute can be specified in the declaration of an automatic variable to initialize the variable.

Extents of automatic character string and array variables may be specified as integer valued expressions, provided these do not contain references to other non-static variables declared in the same block. Extent expressions for these automatic variables are evaluated each time the containing block is activated. The extent expression values are saved in the stack frame and effectively fix the size of the automatic variable for that block activation. Subsequent assignment to a variable used as an extent does not affect the size of the associated automatic variable. For example:

DECLARE STRING_SIZE FIXED;
   .
   .
   .
COPY: BEGIN;
DECLARE TEXT CHARACTER(STRING_SIZE);

When the BEGIN block in this example is activated, the extent of TEXT is evaluated. The variable is allocated storage depending on the value of STRING_SIZE, which must be a valid integer value. For example:

DECLARE A(N) FIXED;
   .
   .
   .
N = 10; /* WILL NOT AFFECT THE SIZE OF ARRAY A */

In this example, the size of A is determined upon entry to the containing block by evaluating N and storing its value in the stack frame. The assignment to N does not change the size of A. Upon entry to the block, N must have a correct value and must not be a non-static variable declared in this block. Use of the HBOUND built-in function within this block activation would return the original value of N that was saved in the stack frame.

Parent topic: Storage Classes
Related information
INITIAL
HBOUND Function


Static Storage

Storage for a static variable is allocated by the Compiler and/or linker prior to program execution. Storage remains allocated throughout program execution.

Only one instance of a static variable's storage is allocated, regardless of whether the variable is declared in a recursive procedure. Values assigned to a static variable are retained between calls to the procedure in which the variable is declared.

All extents specified for static character string, 8-bit area variables, and array variables must be constants.

Static variables can be declared with the INTERNAL or EXTERNAL attribute. If neither attribute is specified, INTERNAL is assumed.

An internal static variable is known in its containing block and in all contained blocks, except those blocks in which the same name is redeclared. This is the normal scope rule that applies to all other variables.

An external static variable is known in its containing block and in all contained blocks, except those blocks in which the same name is redeclared. However, all declarations of the same name that have the EXTERNAL attribute, including those in separate modules of the program, share the same storage and must specify identical attributes, including any initial values. External static variables are known and shared by all program modules in a manner similar to the common variables of FORTRAN, except that each external static variable is shared independently of others.

Parent topic: Storage Classes
Related information
INTERNAL
EXTERNAL


Based Variables

The BASED attribute defines a template for storage that will be accessed through the use of a locator. A based variable differs from all other variables in the sense that it is a description of storage, but does not have storage of its own. Since it has no storage, it has no address. For example:

DECLARE X CHARACTER(30) BASED;
DECLARE P POINTER;
   .
   .
   .
P->X = 'ABC';

In this example, assume that an address or pointer value has been assigned to P. The reference P–>X is called a pointer qualified reference, and it enables assignment to the storage addressed by P as if that storage contained a character-string variable like X.

A pointer value can be obtained in two primary ways: from the address of a variable's storage as calculated and returned by the ADDR built-in function, or from the address of storage obtained dynamically by the ALLOCATE statement. For example:

DECLARE K FIXED BINARY(15);
DECLARE X(5) FLOAT BINARY;
DECLARE Y FLOAT BINARY BASED;
DECLARE P POINTER;
   .
   .
   .
P = ADDR(X(K));
P->Y = 10;

In this example, P is assigned the address of X (K) , which is returned by the ADDR built-in function. The second assignment places the value 10 in the storage location given by P in a manner prescribed by the template Y, effectively assigning 10 to X (K) .

A third way to obtain a pointer value is with the POINTER built-in function, which may be used to convert an area offset value to a pointer.

The indiscriminate use of pointers to access the storage of other variables should be discouraged because of the possibilities of unexpected assignment side effects and because the excessive use of pointers makes a program hard to read. Please also note that no checking is performed to ensure that the based variable provides a data description compatible with the declaration of the reference storage. For instance, the statement P–>Y = 10 might produce undesirable results if Y were declared as a data type incompatible with the data type of elements in X. For a discussion of storage sharing using based variables, see the section Storage Sharing.

The ALLOCATE statement uses a based variable to allocate a block of storage that can later be accessed by a based variable together with the locator returned by the ALLOCATE statement. For example:

DECLARE P POINTER;
DECLARE X(C,N) CHAR BASED(P);
N = 10;
C = 10;
ALLOCATE X SET(P);
   .
   .
   .
P -> X(10,5) = 'A';

In the preceding example, the ALLOCATE statement allocates a storage block of sufficient size to hold a two-dimensional array of 100 one-byte character values and assigns a pointer to that block of storage to P . P–>X thereafter is a reference to that block of storage as an array of 100 one-byte character values.

Based variables can be subscripted just like any other variable. Referring again to the previous example, the statement P–> X (10,5) = ' A' assigns the character 'A' to the element in row 10 and column 5 of the array qualified by P. Since the pointer variable may also be an array, it too can be subscripted. For example:

DECLARE P(3) POINTER;
DECLARE X(10) FLOAT BASED;
   .
   .
   .
ALLOCATE X SET(P(K));

In the preceding example, P (K)–>X refers to the entire array of ten floating-point elements qualified by the Kth pointer element of P. Likewise, P (K) –>X (J) refers to the Jth element of the floating-point array qualified by the Kth element of pointer array P.

The ALLOCATE statement is the only context in which a based variable can be used without an explicit or implicit locator qualifier. In this context, the based variable is used to describe how much storage is to be allocated.

Implicit locator qualification is a shorthand notation that can be used in cases where many of the references to a based variable use the same pointer. For example:

DECLARE X(10) FLOAT BASED(P);
DECLARE P POINTER;
   .
   .
   .
ALLOCATE X SET(P);

Because X was declared to be based on P in the previous example, unqualified references to X such as X (K) , X (5), or X are implicitly qualified by P and are equivalent to P–>X (K) , P–>X (5) , and P–>X. Any explicit qualification, such as Q–>X, may be used to temporarily override the implicit qualification and is unaffected by the specification of P in BASED (P) .

The extents of a based variable may be specified as integer valued expressions. The extents are evaluated for each allocation of the variable and for each reference of the variable. The extents are not captured when storage is allocated by an ALLOCATE statement. The extent expression can reference variables declared in the same block, as long as those variables have a value before the based variable is referenced. Changing the value of a variable referenced by an extent expression changes the extent of the based variable. For example:

DECLARE X(N) CHARACTER(1) BASED;

N = 10;
ALLOCATE X SET(P);
   .
   .
   .
N = M;
P->X(5) = 'A';

In this example, the ALLOCATE statement allocates an array of ten elements. The value of M must be greater than or equal to five and less than or equal to ten; otherwise, the reference to P–>x (5) is invalid and may cause unpredictable results.

A block of storage previously allocated by an ALLOCATE statement can be freed by a FREE statement. For example:

FREE P->X;

Once freed, the storage can no longer be accessed, and any attempt to use a pointer such as P that points to the block produces unpredictable results.

Note:

The storage obtained by an ALLOCATE statement is freed only by an explicit FREE. If a program continually allocates memory without freeing it, the program may run out of space at run-time.

Used with the ALLOCATE statement, based variables are powerful tools for applications in which the size of arrays or strings is not known at block entry and must be determined at run-time. Based variable allocations also supply a means for the dynamic creation of graph structure nodes (which may be linked by pointers to produce list and tree structures). See the example of a based structure in the section Block Activation and Recursion.

It is desirable to restrict the extent of based variables to constant values whenever possible to avoid unexpected side effects and to improve program readability. If the extent must be variable, it is preferable to avoid the use of extent expressions when declaring based variables for the same reasons. The size of the based variable is evaluated for each reference to the variable.

Parent topic: Storage Classes
Related information
POINTER Function
Storage Sharing
Block Activation and Recursion


Controlled Variables

The CONTROLLED attribute specifies a variable whose storage is dynamically allocated and freed in generations, independent of block boundaries. Controlled variables are allocated only when specified in an ALLOCATE statement. After being allocated, a controlled variable remains allocated until a FREE statement names the variable.

A reference to a controlled variable refers to the generation of the variable created by the most recent ALLOCATE statement. The FREE statement frees the most recent generation of the controlled variable, exposing the previous generation. For example:

DECLARE STACK (STACK_ITEM_SIZE) CHAR(32) CTL;
DECLARE STACK_ITEM_SIZE FIXED BIN;
DECLARE I FIXED BIN;

   /* Push a first stack item. */
   STACK_ITEM_SIZE = 4;
   ALLOCATE STACK;

   DO I = 1 TO STACK_ITEM_SIZE;
      STACK(I) = CHAR(I) || '_1';
   END;

   /* Push a second stack item. */
   STACK_ITEM_SIZE = 3;
   ALLOCATE STACK;

   DO I = 1 TO STACK_ITEM_SIZE;
      STACK(I) = CHAR(I) || '_2';
   END;

   PUT SKIP LIST ('Print second item on the stack');
   PUT SKIP LIST (STACK);

   /* Pop the last element on the stack. */
   FREE STACK;

   PUT SKIP LIST ('Print first item on the stack');
   PUT SKIP LIST (STACK);

   /* Pop the last element on the stack.
      The stack is empty now. */
   FREE STACK;

CONTROLLED variables can be declared with asterisk (*) extents, and when such a variable is allocated, its extents can be made explicit by the use of the ALLOCATE statement with specified attributes. CONTROLLED variables can also be declared with explicit extents (constant or variable), and these explicit extents can be overridden by use of the ALLOCATE statement with specified attributes.

It is also possible to specify attributes with asterisk extents in the ALLOCATE statement. This causes the extents to be copied from the corresponding extents used for the previous alloctiaon of the same CONTROLLED variable. If an asterisk is specified in the ALLOCATE statement for one dimension of a variable, it must be specified for all dimensions of that variable.

If level numbers are specified, the first variable in the ALLOCATE statement must be specified with a level-num of 1 and be declared as a level-1 structure, and in this case, all members of the structure must be included in the ALLOCATE statement just as they appear in the declaration of the structure.

Any bound, length, size, or initial value specified in the ALLOCATE statement overrides the corresponding attribute specified in the declaration of the variable. A bound, length, or size can be specified in the ALLOCATE statement with an asterisk, and, in this case, the bound, length, or size is taken from the current generation of that CONTROLLED variable. If a bound, length, size, or initial value specified in the ALLOCATE statement contains a reference to the variable being allocated, the reference is to the current generation of the variable.

Evaluations of expressions for bounds, lengths, sizes, and initial values during the execution of the ALLOCATE statement are done according to the normal rules for PL/I references, and must be capable of logical execution (that is, without circularity). Evaluations depending on the existence of a prior generation of a variable require that that generation has previously been allocated.

Controlled variables provide an easy way to implement a stack, because only the most recent generation is available to the program. The ALLOCATE statement is equivalent to a push operation and the FREE statement is equivalent to a pop operation. The ALLOCATION built-in function is used to determine the number of generations of a controlled variable that are available.

Examples

DECLARE 1 A CONTROLLED,
     2 B CHAR(*),
     2 C CHAR(20),
     2 D(2) FIXED BIN(31),
     2 E(4,4) CHAR(*),
     2 F FIXED BIN(31);
...
ALLOCATE 1 A, 2 B CHAR(12), 2 C, 2 D(6), 2 E CHAR(3), 2 F INIT(128);
...
ALLOCATE 1 A, 2 B CHAR(12), 2 C CHAR(10), 2 D(D(1)), 2 E CHAR(3), 2 F;

In this example, the structure A is first allocated with member B of length 12, with array member D with dimension (6) instead of the declared (2), array member E with its declared dimensions of (4,4) and element lengths of 3, and member F with an initioal value of 128. The second generation of A is allocated with member C of length only 10 and with the dimension of array member D the value contained in the first generation of A.D(1).

DECLARE X(*,*) CONTROLLED;
ALLOCATE X(3,7);
ALLOCATE X(*,*);

In the second allocation of array X, the bounds are implicitly (3,7), as derived from the previous allocation.

Parent topic: Storage Classes


Defined Variables

A defined variable is one for which no storage is allocated. Instead, the variable shares the storage of a specified basis variable.

A defined variable is declared with the DEFINED attribute, which also specifies the basis variable. Any reference to the defined variable is a reference to all or part of the storage of the basis variable.

When the declaration of a variable includes the DEFINED attribute, that variable's description applies to the storage associated with the basis variable. For example:

DECLARE A(5) CHARACTER(1);
DECLARE X CHARACTER(5) DEFINED(A);

In this example, X is a defined character-string variable of length 5. X shares storage with, and is an alternate description of, the array A. Similarly, the following statement:

X = 'abcde';

assigns 'a' to A (1) , 'b' to A(2), and so on.

The extents of a defined variable can be integer valued expressions. They are evaluated upon block entry and stored in the stack frame just like the extents of automatic variables. Such an extent expression must not contain a reference to any non-static variable declared in the same block.

For additional information on defined variables, see the section Storage Sharing, which discusses the rules for giving alternate descriptions of storage.

Parent topic: Storage Classes
Related information
Storage Sharing


Parameter Storage Class

A parameter shares storage with its argument. As such, the storage class is ultimately determined by that of the associated argument. Technically, the parameter variable itself is an AUTOMATIC variable containing the address of the corresponding argument. For convenience, a parameter may be considered to have a distinct "parameter" storage class. For example:

DECLARE X FLOAT;
CALL P (X);
   .
   .
   .
P: PROCEDURE (Y);
      DECLARE Y FLOAT;

In this example, X is an argument and Y is a parameter variable. A parameter variable is declared within a procedure declaration and receives a value when that procedure is invoked. Simple Open PL/I variable arguments are passed by reference.

A parameter has a data type, perhaps a data type with extents, and in the simplest case, an argument passed to the parameter will have the same data type and extents as the parameter. If this is not the case, Open PL/I will, whenever possible, convert the argument to a value with the same data type and extents as the parameter and pass that value to the parameter.

In the absence of specifications to the contrary, when a variable is passed as an argument to a parameter with matching data type and extents, the argument is passed "by reference." This means that it is the address of the actual variable itself that is passed as the argument, and the parameter is sharing storage with this variable. Hence, any assignment to the parameter is actually changing the argument variable itself.

In other cases — that is, when the argument is a variable whose data type and extents do not match the parameter, or when the argument is an expression, a constant, a function reference, or a simple variable enclosed in parentheses — the argument is passed "by value." This means that the value of the 'argument is converted as described above and stored in a temporary location. It is the address of this temporary location that is passed as the argument. Hence, any assignment to the parameter can have no effect on any variable in the calling procedure.

The precision of arithmetic data is part of its data type. This means that a Float Decimal(7) variable cannot be passed by reference to anything except a Float Decimal(7) parameter. The VARYING and ALIGNED attributes, as well as the declared string length, are part of a string variable's data type and must match those of the corresponding parameter for the parameter to share storage with the actual argument (true pass-by-reference). A picture variable can be passed by reference only if the corresponding parameter has an identical picture. The ALIGNED and UNALIGNED attributes of non-string arguments and parameters must match.

The VALUE attribute is an argument-passing attribute that indicates that the value and not the address of the parameter has been passed to the procedure.

An array parameter with constant extents can be passed only those array arguments that have identical constant extents and an identical data type. A parameter structure can be passed only a structure or substructure of identical size, shape, and component data types. Array or structure arguments cannot be passed by value.

The ANY attribute is an argument-passing attribute that specifies, for a parameter, that the corresponding argument can be of any data type.

A procedure that has a character or bit-string parameter with a constant length may be called with string arguments of variable length or differing constant length. Since all such arguments are passed by value, they are effectively converted to the length of the parameter. For example:

CALL P(A,(B));

In this example, A is passed by reference if it matches its corresponding parameter and is passed by value if it does not. B is always passed by value.

If the argument is an expression, function reference, built-in function reference, constant, parenthetical variable reference, or a reference to a variable whose data type does not match that of the parameter, the argument is copied to a temporary block of storage in the caller's stack frame and is said to be passed by value. The value of the variable in the caller will not be modified if it is passed by value. Actually, the address of the temporary is passed, and the parameter shares the storage allocated to the temporary.

The extents of a parameter can be either integer constants or asterisks (*). If the parameter's extents are integer constants, any argument to be passed by reference must have identical constant extents. If the parameter's extents are asterisks, its corresponding argument may have extents of any value. In the latter case, the extents of the parameter are those of its corresponding argument. For example:

DECLARE A(10) FLOAT;
DECLARE B(25) FLOAT;
   .
   .
   .
CALL P(A);
   .
   .
   .
CALL P(B);
   .
   .
   .
P: PROCEDURE(X);
   DECLARE X(*) FLOAT;

During the first call in this example, the extents of X are (1:10). During the second call, they are (1:25).

Parent topic: Storage Classes
Related information
Value
ANY


Storage Sharing

Open PL/I provides two storage classes that are explicitly designed to permit storage locations to be shared by several variables. These storage classes are BASED and DEFINED. (Use of the UNION attribute also allows variables to explicitly share storage.)

Based variables are allocated no storage when they are declared. Instead, they serve to determine storage to be allocated by an ALLOCATE statement or to describe storage qualified by a pointer reference.

Defined variables use the storage of a specified basis variable. A defined variable is declared with the DEFINED attribute, which also specifies the basis variable.

A defined variable and its basis reference must satisfy one of the following criteria in order to share storage:

  1. All variables sharing storage have identical data types.
  2. All variables sharing storage are nonvarying character strings and therefore are suitable for character-string overlay defining.
  3. All variables sharing storage are unaligned bit strings and therefore are suitable for bit-string overlay defining.

A variable is suitable for overlay defining if it consists entirely of characters or bits that are packed into adjacent storage without gaps. (Gaps can be caused by the alignment of data in user-defined structures.)Variables suited for overlay defining are arrays, structures containing only the required type of string data, or scalar string variables. For example:

DECLARE X(4,4) CHARACTER(1);
DECLARE Y(16) CHARACTER(1) DEFINED(X);
DECLARE Z CHARACTER(5) DEFINED(X);
DECLARE 1 S BASED,
   2 A CHARACTER(8),
   2 B CHARACTER(8);

In this example, X has a block of storage containing 16 characters. The entire block is shared by Y, but Z shares only the first 5 characters of the block. S could be used to access all 16 characters, while S.A could be used to access the first 8, and S.B could be used to access the last 8. A based character string of more than 16 characters would produce undefined results, but a string of 16 or fewer characters could be used. A similar example could be constructed using all unaligned bit data.

Storage sharing of other data types requires that the data types match exactly, but an element of an array can be shared with a nonarray variable of the same data type. Similarly, a member of a structure can be shared with a nonmember of the same data type.

Members of structures that have the attribute UNION also share physical storage locations with one another. A UNION is a variation of a structure in which all immediate members occupy the same physical storage location. Unions provide capabilities similar to those of defined variables. The UNION attribute, which can be used only in conjunction with a level number in a structure declaration, signifies that all immediate members of the major or minor designated structure occupy the same storage. An immediate member is any member having a level number greater than its containing structure but not greater than the level number of its fellow members. Typically, an immediate member has a level number that is one greater than its containing structure. (For more information on this attribute, see the section Union.)

Arrays can share storage with other arrays only if they have the same data type and/or are equivalent left-to-right. Structures can share storage with other structures only if they are equivalent, left-to-right, to the structure whose storage is being shared.

Left-to-right equivalence means that the sharing structures must be valid descriptions of the left part of the storage being shared. To be a valid description of the left part of storage, the sharing structures must have identical members up to and including all members contained anywhere within the last level-two item being shared. If any part of a level-two item is to be shared, all of it must be shared. For example:

DECLARE   1 S,  DECLARE  1 T BASED,  DECLARE  1 U BASED,
          2 A,           2 A,                 2 A,
          2 B,           2 B,                 2 B,
          3 C,           3 C,                 3 C;
          3 D;           3 D;
          2 E;

In this example, a reference to T.B.C is a valid reference to S.B.C, but a reference to U.B.C is not valid, because the declaration of U does not describe the entire level-two item S.B.

A picture variable can share storage only with other picture variables that have identical pictures.

As is the case for argument/parameter matching, the ALIGNED, UNALIGNED, and VARYING attributes and the declared length of a string variable are part of its data type and must match, unless the strings qualify for string overlay sharing.

The base, scale, and precision of arithmetic variables must always match if they are to share storage.

Parent topic: Storage Classes
Related information
Union


Declarations and Attributes

  • Introduction
  • Label Prefixes
  • DECLARE Statements
  • Attributes of DECLARE Statements
Parent topic: Open PL/I Language Reference Manual


Introduction

All variables in an Open PL/I program (except those under the control of the DEFAULT statement) must be declared. Each name, except the name of a built-in function, must be declared using a DECLARE statement (or if it is a label, by using the label as a statement prefix).

Each declaration is associated with a scope or region of the program in which a reference to the associated name is valid. The scope of a declaration includes the block in which it is declared and all nested blocks, except those in which the name has been redeclared.

Identifier attributes used in DECLARE statements are specified by either keyword or syntax. A name declared with the EXTERNAL attribute has the same scope rule as any other name, except that the object identified by that name is unique throughout the entire program. All declarations of a given name that have the EXTERNAL attribute identify the same object. Only files, static variables, and names of external procedures can have the EXTERNAL attribute. Files and procedures acquire the attribute by default, but static variables have internal scope unless they are explicitly declared with the EXTERNAL attribute.

A given name cannot be declared more than once within the same block, unless it is declared as the name of a structure member. In that case, the name may be redeclared within the same block, provided no two members at the same level of the same structure have the same name. (See the section Scope.)

Parent topic: Declarations and Attributes
Related information
Scope


Label Prefixes

A label prefix declares a name as a procedure name, format name, or statement label, depending on the type of statement to which the prefix is attached.

A label prefix on a PROCEDURE statement declares a name as a procedure name. The name is declared in the block that contains the PROCEDURE statement, and its scope is that containing block and all blocks contained by the procedure. The declaration lists each parameter referenced by the PROCEDURE statement, as well as the data type specified by any RETURNS option in the PROCEDURE statement. For example:

E: PROCEDURE(A,B) RETURNS(POINTER);
   DECLARE A FIXED BINARY;
   DECLARE B FLOAT DECIMAL;

In this example, E is declared as a procedure name in the block that contains the PROCEDURE statement. The attributes of that declaration are RETURNS(pointer) and ENTRY(fixed binary, float decimal).

The label prefix on a FORMAT statement declares a name as a format name. The name is declared in the block that contains the FORMAT statement and all contained blocks. A format name is not a statement label and cannot be used in a GOTO statement. A format name can be used only in a format statement.

The label prefix of a PROCEDURE or FORMAT statement cannot be sub- scripted.

A label prefix attached to statements other than PROCEDURE or FORMAT statements declares a name as a statement label. The declaration is established in the block that contains the statement to which the prefix is attached. For example, a label prefix attached to a BEGIN statement is declared in the block that contains the BEGIN statement and its scope is that containing block and all blocks contained by the BEGIN statement.

The label prefix of a PROCEDURE or FORMAT statement cannot be sub- scripted; however, label prefixes attached to statements other than PROCEDURE or FORMAT may be subscripted by a single optionally signed integer constant. Within its scope, all occurrences of a given name used in this manner must be subscripted, and all such prefixes collectively constitute a declaration of the name as an array of statement labels. For example:

   GOTO CASE(K);
CASE(1):
   .
   .
   .
CASE(2):
   .
   .
   .
CASE(3):
   .
   .
   .
CASE(6):
   .
   .
   .

In this example, CASE is declared as an array of statement labels whose bounds are (1:6) and whose fourth and fifth elements are undefined. Defining arrays with undefined elements is not recommended, as it produces unpredictable results.

An array of statement labels cannot be used as an array value, but its elements can be used in any context that permits a statement label.

Procedure names, format names, and statement labels cannot be declared in a DECLARE statement in the same block, except that the names may be used as the structure member names.

Names of external procedures that are part of another program module must be declared by a DECLARE statement if they are to be referenced by the current program module. (For more information, see the section Modules.) Only external procedure names can be declared by a DECLARE statement.

Parent topic: Declarations and Attributes
Related information
FORMAT
Modules


DECLARE Statements

A DECLARE statement declares one or more names by giving the attributes or properties of the named objects. A DECLARE statement is not an executable statement. It may appear as a part of a WHEN or OTHERWISE clause in a SELECT statement; anywhere within a procedure or BEGIN block, except as the THEN clause or ELSE clause of an IF statement; or as an ON-unit of an ON statement.

For the sake of readability, all DECLARE statements belonging to a given block should be placed at the beginning of that block, rather than among the executable statements.

  • Recommended Forms
  • The General Form
  • Defaults
  • Attribute Consistency
Parent topic: Declarations and Attributes


Recommended Forms

This section describes the recommended forms of the DECLARE statement within the following statement categories: simple declarations, factored declarations, and structure declarations.

  • Simple Declarations
  • Factored Declarations
  • Structure Declarations
Parent topic: DECLARE Statements


Simple Declarations

A simple declaration defines a single name and describes its attributes. Its recommended form is:

DECLARE name a?1 a?2 a?n;

where name is the declared name and a1 through an are attributes. For example:

DECLARE A FIXED BINARY(15);
DECLARE B CHARACTER(10) VARYING STATIC INITIAL('ABC');
DECLARE C DIMENSION(5) FLOAT DECIMAL(7);

The last statement in this example could also be given without the keyword DIMENSION by using the following format:

DECLARE C(5) FLOAT DECIMAL(7);
Parent topic: Recommended Forms


Factored Declarations

Factored declarations define two or more names having the same attributes. The recommended form of a factored declaration is:

DECLARE (name-1[,name-2]…)a?1 a?2…a?n;

where each name is declared to have all of the attributes a?1 through a?n. In factored declarations, the names must be enclosed in parentheses.

Examples:

DECLARE (A,B,C) FIXED BINARY(15);
DECLARE (P,Q) POINTER STATIC INITIAL(NULL);
DECLARE (X,Y)(5) FLOAT DECIMAL(7);

The last example is equivalent to the following statement:

DECLARE (X,Y) DIMENSION(5) FLOAT DECIMAL(7);

The bounds must be the first attribute in an attribute list if they appear without the DIMENSION keyword.

Parent topic: Recommended Forms


Structure Declarations

The declaration of a structure defines the organization of the structure and the names of members at each level of the structure. The general form of this declaration is:

DECLARE 1 structure_name a?1 a?2 … a?n,
       k member_name-1 a?1 a?2 … a?n,
       k member_name-2 a?1 a?2 …. a?n,
           .
           .
           .
       k member_name–m a?1 a?2 … a?n;

where each member_name specifies a member of the structure preceded by a level-number, k, and where the level-number of each member must be greater than the level-number of its containing structure, equal to level-numbers of members at the same level, and less than the level-numbers of members it contains. The major structure name is declared as structure level 1.

The only attributes given to the structure itself are storage class, ALIGNED, UNALIGNED, DIMENSION, REFER, and UNION. Each member is declared to have all attributes following its name up to the next comma or up to the end of the statement. For example:

DECLARE 1 S    STATIC,
            2  A(5) FLOAT DECIMAL(7),
            2  B  FIXED BINARY(15),
            2  C,
                  3 D   POINTER,
                  3 E   CHARACTER(10) INITIAL('ABC');

In this example, S is a static structure with members A, B, and C. C is a substructure with members D and E. Initial attributes can be given to elementary members of static structures, but not to structures themselves.

Parent topic: Recommended Forms


The General Form

Following is the general form of the DECLARE statement:

DECLAREd?1[,d?2 …];

or

DCL d?1 [,d?2 …];

where each d is:

[k]name a?1 a?2 … a?n

or

[k](d?1[,d?2]…)a?1 a?2 … a?n

where k is an optional level number, each a is an attribute, and name is a name to be declared.

Examples:

DECLARE ((A FIXED, B FLOAT) DECIMAL, C BIT) STATIC;
DECLARE 1 S STATIC, 2 (A FIXED, B FLOAT) INITIAL(0);

These examples illustrate more factored declarations, as indicated by the fact that the DECLARE statements contain parenthetical lists of names. Factored declarations can be transformed into nonfactored declarations by copying the level number and attribute list of the innermost set of parentheses onto each name contained within the parentheses, removing the parentheses, and repeating this process with the next set of parentheses.

After defactoring, the previous examples are:

DECLARE A FIXED DECIMAL STATIC;
DECLARE B FLOAT DECIMAL STATIC;
DECLARE C BIT STATIC;
DECLARE 1 S STATIC,
      2 A FIXED INITIAL(0),
      2 B FLOAT INITIAL(0);

Factored declarations, other than as shown in the recommended form (see the section Factored Declarations) are generally more difficult to read than their unfactored equivalents.

If defactoring produces more than one level number for a given name, even if the level numbers are equal, the factored declaration is invalid and causes the Compiler to issue an error message.

Specification of duplicate attributes containing more than a simple keyword is also invalid, even when the attributes are exact duplicates.

Parent topic: DECLARE Statements
Related information
Factored Declarations


Defaults

If the attributes specified for a name in a DECLARE statement are incomplete, the missing attributes can be supplied either by the Compiler or by the user with the DEFAULT statement.

  • Compiler-supplied Defaults
  • The Default Statement
Parent topic: DECLARE Statements


Compiler-supplied Defaults

The Compiler supplies the required additional attributes, as follows:

Specified | Missing | Supplied
binary | fixed | float | fixed
decimal | fixed | float | fixed
fixed | binary | decimal | decimal
float | binary | decimal | decimal
static | internal | external | internal
bit | length | length of one
character | length | length of one
area | size | size of 1000

Defaults are also supplied for the following conditions.

  • STATIC is supplied if EXTERNAL is specified without a storage class and the declared name is not an entry or file constant.
  • AUTOMATIC is supplied if the name is the name of a nonparameter variable that is not a member of a structure and no storage class was specified.
  • The default precision is supplied if precision is not specified for arithmetic data. For information on the Open PL/I default precisions, see your Open PL/I User's Guide.
  • VARIABLE is supplied if a storage class, array bounds, or member's level number is specified with FILE or ENTRY.
  • EXTERNAL is supplied if FILE or ENTRY is specified and VARIABLE is neither specified nor supplied under the previous rule. In this case, the named object is a constant rather than a variable.
  • UNALIGNED is supplied for bit-string data; ALIGNED for all other types of data.
Parent topic: Defaults
Related information
Open PL/I User's Guide


The Default Statement

You can change Compiler-supplied defaults, or you can apply a completely new set of default attributes, using the DEFAULT statement.

Parent topic: Defaults
Related information
DEFAULT


Attribute Consistency

After default attributes have been supplied, each declaration is checked by the Compiler for consistency and completeness.

If no data type is specified, either explicitly or by the DEFAULT statement, the declaration is invalid and incomplete. The Compiler issues an error message and supplies a type of Fixed Binary(15) for names beginning with any of the letters I through N, and Float Decimal(6) for names beginning with any other alphabetic character.

A declaration is inconsistent and invalid if it specifies more than one data type or more than one storage class.

These are the valid data types:
  • Fixed Binary(p)
  • Fixed Decimal(p[,q])
  • Float Binary(p)
  • Float Decimal(p)
  • Picture
  • Character(n) [Varying]
  • Bit(n)[Aligned]
  • Pointer
  • Offset
  • Area
  • Label
  • Entry [returns][variable]
  • File [variable]
  • Builtin
  • Structure
These are the valid storage classes:
  • automatic
  • based or based(pointer-reference)
  • static internal
  • defined(reference)
  • parameter
  • member of structure

A declaration is also inconsistent and invalid if it violates the following attribute-specific restrictions:

  • A name declared with the BUILTIN attribute cannot have any other attribute.
  • A name declared with the FILE or ENTRY attribute, but without the VARIABLE attribute, is a named constant, not a variable, and its scope is external. (Recall, however, that the presence of a storage class, an array bound, or a member's level-number causes the VARIABLE attribute to be supplied by default to declarations containing the ENTRY and FILE attributes.)
Parent topic: DECLARE Statements


Attributes of DECLARE Statements

This section describes, in alphabetical order, the attributes that are permitted in a DECLARE statement.

The discussion of each attribute assumes that the attributes have been made complete by the application of defaults, as described in the section Defaults.

Each attribute discussed in this section falls into one of the following categories:

  • Arithmetic or string data attributes, which define arithmetic or string data.
    • ALIGNED
    • BIGENDIAN
    • BINARY
    • BIT
    • CHARACTER
    • DECIMAL
    • FIXED
    • FLOAT
    • NATIVE
    • NONNATIVE
    • PICTURE
    • REAL
    • UNALIGNED
    • VARYING
  • Data type attributes, which apply to program data not used for computation.
    • AREA
    • CONDITION
    • DIMENSION
    • ENTRY
    • EXCLUSIVE
    • FILE
    • LABEL
    • LIKE
    • OFFSET
    • POINTER
    • TYPE
  • Storage class and scope attributes, which control the allocation and storage use for a data variable and define the variable's scope.
    • AUTOMATIC
    • BASED
    • CONTROLLED
    • CONNECTED
    • DEFINED
    • EXTERNAL
    • GLOBALDEF
    • GLOBALREF
    • INITIAL
    • INTERNAL
    • POSITION
    • REFER
    • STATIC
    • UNION
  • File description attributes, which can be applied to file constants or may be used in OPEN statements (except ENVIRONMENT, which can be used only in the DECLARE statement).
    • DIRECT
    • ENVIRONMENT
    • INPUT
    • KEYED
    • OUTPUT
    • PRINT
    • RECORD
    • SEQUENTIAL
    • STREAM
  • Entry name attributes, which can be applied to identifiers of entry points. These include:
    • BUILTIN
    • ENTRY
    • IRREDUCIBLE
    • OPTIONS(DESCRIPTOR)
    • OPTIONS(NODESCRIPTOR)
    • OPTIONS(VARIABLE)
    • REDUCIBLE
    • RETURNS
    • VARIABLE
  • Argument-passing attributes, which describe parameters of external procedures. These include:
    • ANY
    • VALUE
Note:

File description attributes specified in a DECLARE statement apply to all openings of the file control block associated with the file constant. For further discussion of these attributes, see the sections Input and Output in the chapter Language Concepts and OPEN in the chapter Statements.

  • ALIGNED
  • ANY
  • AREA
  • AUTOMATIC
  • BASED
  • BIGENDIAN
  • BINARY
  • BIT
  • BUILTIN
  • CHARACTER
  • CONDITION
  • CONNECTED
  • CONTROLLED
  • DECIMAL
  • DEFINED
  • DIMENSION
  • DIRECT
  • ENTRY
  • ENVIRONMENT
  • EXCLUSIVE
  • EXTERNAL
  • FILE
  • FIXED
  • FLOAT
  • GLOBALDEF
  • GLOBALREF
  • INITIAL
  • INPUT
  • INTERNAL
  • IRREDUCIBLE
  • KEYED
  • LABEL
  • LIKE
  • NATIVE
  • NONNATIVE
  • OFFSET
  • OPTIONS(DESCRIPTOR)
  • OPTIONS(NODESCRIPTOR)
  • OPTIONS(VARIABLE)
  • OUTPUT
  • PICTURE
  • POINTER
  • POSITION
  • PRINT
  • READONLY
  • REAL
  • RECORD
  • REDUCIBLE
  • REFER
  • RETURNS
  • SEQUENTIAL
  • STATIC
  • STREAM
  • TYPE
  • UNALIGNED
  • UNION
  • UPDATE
  • VALUE
  • VARIABLE
  • VARYING
Parent topic: Declarations and Attributes
Related information
Defaults
Input and Output
OPEN


ALIGNED

ALIGNED is a data type attribute that controls the storage boundary of data.

ALIGNED is an optional part of the data type specification. Its presence allows the Compiler to align the data on an implementation-defined storage boundary, with the possible side effect that more bits or bytes of storage are used than specified by the declared length.

Parent topic: Attributes of DECLARE Statements
Related information
ALIGNED and UNALIGNED Attributes
Bit-String Data


ANY

The ANY attribute specifies that the corresponding argument for a parameter can be of any data type. The ANY attribute is applicable only to the declaration of entry names and is valid only in a parameter descriptor. ANY is not valid as an attribute in a PROCEDURE or ENTRY statement.

Parent topic: Attributes of DECLARE Statements
Related information
ENTRY


AREA

AREA is a non-computational data type attribute used to define a region of storage in which based variables can be allocated and freed. The format is:

AREA[(exp[REFER(variable)])]

or

AREA(*)

For a complete description of area data and the use of the AREA attribute, see the section Area Data in the chapter Data Types.

Parent topic: Attributes of DECLARE Statements
Related information
Area Data


AUTOMATIC

Abbreviation: AUTO

AUTOMATIC is a storage class attribute that specifies that the declared name is a variable that is allocated storage with each activation of its containing procedure or BEGIN block.

The AUTOMATIC attribute is supplied by default to any name of a non-parameter variable that is not a member of a structure and that has no storage class.

Parent topic: Attributes of DECLARE Statements
Related information
Automatic Storage


BASED

BASED is a storage class attribute that specifies that the declared name is a based variable. Its format is:

BASED[(r)]

In the optional form, r is a reference to a locator variable or a locator-valued function that serves as the default (implicit) locator qualifier for unqualified references to the name.

Parent topic: Attributes of DECLARE Statements
Related information
Based Variables


BIGENDIAN

BIGENDIAN is a data type attribute (applying to Fixed Binary items only) that specifies the internal storage for a data item is MSB first (or MSB "left -to- right"). This attribute is applicable only to Little-Endian machine architectures (such as Intel). For Big-Endian architectures, this attribute is ignored.

Example:

dcl flag fixed bin (15) static initial (1) bigendian;
Parent topic: Attributes of DECLARE Statements


BINARY

Abbreviation: BIN

BINARY is an arithmetic data type attribute that specifies that the base is binary. Its format is:

BINARY[(p)]

The precision p may be supplied with the BINARY attribute or with the FIXED or FLOAT attribute, but it cannot be specified twice. The precision p must be a positive integer. If no precision is specified, a default precision is supplied. For information on the default precisions, see your Open PL/I User's Guide and the section DEFAULT in the chapter Statements.

If BINARY is specified without FIXED or FLOAT, FIXED is assumed.

When used with FIXED, BINARY specifies integer arithmetic values that contain at least p bits.

When used with FLOAT, BINARY specifies floating-point arithmetic values that have a mantissa that contains the equivalent of at least p bits.

Parent topic: Attributes of DECLARE Statements
Related information
DEFAULT
Arithmetic Data


BIT

BIT is a bit-string data type attribute that identifies a variable as a bit-string variable. Its format is:

BIT[(n)]

Length n is an extent expression or integer constant, depending on the storage class of the declared name. The length n must be a non-negative integer constant or an expression that evaluates to a non-negative integer. A default length of 1 is supplied if no length is given.

For more information on BIT, see the chapter Storage Classes and the section Bit-String Data in the chapter Data Types.

Parent topic: Attributes of DECLARE Statements
Related information
Storage Classes
Bit-String Data


BUILTIN

BUILTIN is an entry name attribute that indicates that the declared name is a built-in function. Unless an empty argument list is used in a reference to a built-in function having no parameters, the function must be declared with the BUILTIN attribute.

BUILTIN can be used to redeclare a built-in function name that was declared as something else in an outer block. The declared name must be one of the names given in the chapter Open PL/I Built–Ins.

Parent topic: Attributes of DECLARE Statements
Related information
Open PL/I Built–Ins


CHARACTER

Abbreviation: CHAR

CHARACTER is a character-string data type attribute that identifies a variable as a character-string variable. Its format is:

CHARACTER[(n)]

Length n is an extent expression or integer constant, depending on the storage class of the declared name. The length n must be a non-negative integer constant or an expression that evaluates to a non-negative integer. A default length of 1 is supplied if no length is specified. For a discussion of storage classes, see the chapter Storage Classes and the section Character-String Data in the chapter Data Types.

Parent topic: Attributes of DECLARE Statements
Related information
Storage Classes
Character-String Data


CONDITION

Abbreviation: COND

CONDITION is an attribute that indicates that the declared name is a condition name. Its format is:

CONDITION

Condition names can be used only in ON, SIGNAL, or REVERT statements. The default scope of condition name is external. Note that a name that appears with the CONDITION condition in an ON, SIGNAL, or REVERT statement is contextually declared to be a condition name.

Parent topic: Attributes of DECLARE Statements
Related information
ON


CONNECTED

Abbreviation: CONN

The CONNECTED attribute may be used only for parameters. It cannot be specified for a member of a structure and it cannot be specified for CONTROLLED parameters. The CONNECTED attribute asserts that any argument passed to the parameter is in connected storage.

Parent topic: Attributes of DECLARE Statements


CONTROLLED

Abbreviation: CTL

CONTROLLED is a storage class attribute that specifies a variable whose storage is dynamically allocated and freed in generations. Its format is:

CONTROLLED
Parent topic: Attributes of DECLARE Statements
Related information
Controlled Variables


DECIMAL

Abbreviation: DEC

DECIMAL is an arithmetic data type attribute that specifies that the base is decimal. Its format is:

DECIMAL[(p[,q])]

The precision p,q (q is optional and represents fractional digits) may be supplied with the DECIMAL attribute or with the FIXED or FLOAT attribute, but it cannot be specified twice. The precision p and the scale q (if specified) must be positive integers. If a precision or scale is not specified, a default is assumed. For more information on default precisions, see your Open PL/I User's Guide and the section DEFAULT in the chapter Statements.

If DECIMAL is supplied without FIXED or FLOAT, FIXED is the default. If FIXED or FLOAT is specified without BINARY or DECIMAL, DECIMAL is the default.

When used with FIXED, DECIMAL specifies fixed-point arithmetic values that contain at least p decimal digits. If q is specified, p minus q digits are integral digits and q digits are fractional digits. If q is omitted, q = 0 is assumed. These values are integers containing at most p decimal digits.

When used with FLOAT, DECIMAL specifies floating-point arithmetic values whose mantissa contains the equivalent of at least p decimal digits. In this case, q cannot be specified.

Parent topic: Attributes of DECLARE Statements
Related information
DEFAULT
Arithmetic Data


DEFINED

Abbreviation: DEF

DEFINED is a storage class attribute that specifies that the declared name is a defined variable that shares storage with a basis variable. Its format is:

DEFINED(r)

where r is the basis variable.

Parent topic: Attributes of DECLARE Statements
Related information
Defined Variables


DIMENSION

Abbreviation: DIM

DIMENSION is an attribute that specifies that a declared name is an array and defines the number and extent of its dimensions. Its format is:

DIMENSION(b1[,b2]…)

Each b represents one bound pair, which specifies the number of elements in a single dimension of the array. Each bound pair specifies an optional lower bound (lb) and a requisite upper bound (hb) for that dimension. A bound pair can be specified as follows.

* | The asterisk format of a bound pair, when used to define a parameter for a procedure or function, specifies that both the upper and lower bound of this dimension are to be taken from the corresponding array argument. If one bound pair is specified as asterisks, all bound pairs must be specified as asterisks.
lb:hb | This format specifies the minimum and maximum subscripts that can be used for the dimension. lb is an extent expression or optionally signed integer constant, depending on the storage class of the array, which specifies the lower bound of the dimension. Like lb, hb is either an extent expression or an optionally signed integer constant, depending on the storage class. It specifies the upper bound of the dimension.
hb | This format specifies only the upper bound of the dimension. The lower bound is assumed to be 1.

For example:

DECLARE X(5) FLOAT;
DECLARE Y DIMENSION(5) FLOAT;

In this example, both X and Y are arrays of five floating-point values.

The DIMENSION attribute is normally written immediately after the variable's name and is written without the DIMENSION keyword.

When specified with the FILE or ENTRY attributes, DIMENSION causes the associated name to become a variable rather than a named constant.

Parent topic: Attributes of DECLARE Statements


DIRECT

DIRECT is a file description attribute that indicates that a file can be accessed nonsequentially, that is, by key or by relative record number.

The DIRECT attribute may be given either in the declaration of a file constant or in an OPEN statement. It must not be specified in the declaration of a file variable.

Parent topic: Attributes of DECLARE Statements


ENTRY

ENTRY is a data type attribute that declares a constant or variable whose value is an entry point, and describes the attributes of the parameters, if any, that are declared for the entry point. Its format is:

ENTRY [([parameter-list])]

where parameter-list is:

()|parameter-descriptor[,parameter-descriptor]...

where parameter-descriptor is:

attribute[attribute] ... |*|,|structure-descriptor

where structure-descriptor is:

1 [attribute] ... ,level[attribute] ... [,level[attribute]] ...

An arbitrary parameter-descriptor can be indicated by use of an asterisk ( * ) or by a blank parameter-descriptor position, as indicated by the commas. For example,

ENTRY(FIXED BIN, , FLOAT  /* Three parameters. The
                          second is of any data type. */
ENTRY(FIXED BIN, * ,FLOAT)/* Three parameters. The
                          second is of any data type. */
ENTRY(, , ,)   /* Four parameters of any data type. */
ENTRY()        /* No parameters allowed. */
ENTRY          /* Any number of parameters is allowed. */

The ENTRY attribute without the RETURNS option has an implicit RETURNS data type. It is determined by the I–n rule. External entries with the implicit RETURNS can be called as functions or procedures.

Open PL/I does not require that if any entry statement in a multiple entry procedure has a RETURNS option, then all entries must have one.

ENTRY can be used with or without the VARIABLE attribute. Used without the VARIABLE attribute, the ENTRY attribute declares a constant that is the name of an external procedure. In this case, each p is a list of attributes that is either identical to the attributes specified for the corresponding parameter in the external procedure, or is ANY. For example:

DECLARE E ENTRY(FIXED BINARY(15), POINTER);

In this example, E refers to a procedure that accepts a fixed binary and a pointer argument.

Used with the VARIABLE attribute, the ENTRY attribute specifies that the declared name is a variable of the data type entry, which can be assigned any procedure name. When the entry variable is called, it must hold an entry value that designates a PROCEDURE statement whose parameters have attributes that are identical (unless the attribute is ANY) to the corresponding attributes given by p1, p2, and so forth. Using the declaration for E from the previous example, a compatible procedure declaration would be as follows:

E: PROCEDURE(X,Y);
   DECLARE X FIXED BINARY(15);
   DECLARE Y POINTER;

If a PROCEDURE statement has one or more parameters that are structures, the ENTRY attribute used to declare the procedure name must have a set of attributes for each member of the structure, including all substructures, as shown in the following example:

DECLARE E ENTRY(1,2 FIXED, 2 FLOAT, POINTER);

In the previous example, E is a procedure having two parameters; the first parameter is a structure with two members, and the second parameter is a pointer. The parameter attributes given in the ENTRY attribute include the level numbers and attributes of all members, as well as the level number and attributes of the parameter structure.

All string lengths or array bounds given in an ENTRY attribute must be exactly the same as those given in the parameters of the PROCEDURE statement. Programs that violate this rule may produce unpredictable results.

The ENTRY attribute can be used with the ANY, OPTIONS(VARIABLE), RETURNS(returns_descriptor), and VALUE options according to the following format:

DECLARE
   entry_nameENTRY[(parameter_descriptor[VALUE]…)]
        [OPTIONS(VARIABLE)]
        [RETURNS(returns_descriptor)];

The RETURNS attribute is required for entry points that are invoked by function references and is invalid for procedures invoked by CALL statements. Parameter descriptors are not allowed if the ENTRY attribute is within a RETURNS descriptor.

The parameter descriptor lists attributes for each parameter and must include either the data type of the parameter or the attribute ANY. The VALUE attribute indicates that the corresponding argument is to be passed by immediate value. The OPTIONS(VARIABLE) option indicates that the specified external procedure can be invoked with a variable number of arguments. The following options can be specified as part of the OPTIONS(VARIABLE) attribute when declaring an ENTRY:

  • ASSEMBLER NOMAP [map-list]
  • COBOL NOMAPIN [map-list]
  • FORTRAN NOMAPOUT [map-list]
  • INTER NOEXECOPS
  • TASK RETCODE

The RETURNS(retums_descriptor) option gives the data type attributes of the function value returned for an entry invoked as a function reference. The VARIABLE attribute is not valid in a parameter descriptor or in a RETURNS descriptor.

The VALUE attribute can be used in an ENTRY declaration in conjunction with the data types Fixed Binary, Pointer, Character, Aligned Bit, Entry, or Float Binary. For more information, see the section VALUE.

If the ANY attribute is included as a parameter descriptor, the argument that corresponds to that parameter descriptor can be of any data type. If the argument is a variable, its address is passed to the called procedure. If the argument is a constant or an expression, a dummy argument is created and its address is passed to the called procedure. The following conversions take place when creating the dummy argument:

Written Data Type | Dummy Data Type
Bit (Unaligned) | Bit(n) Aligned, where n is the length of the string
Fixed Binary or Fixed Decimal(p,O) | Fixed Binary(31)
Char Varying | Char(n), where n is the length of the string

For more information, see the chapter Storage Classes and your Open PL/I User's Guide.

The OPTIONS(VARIABLE) attribute is used to indicate that it is valid for a discrepancy to exist between the number of parameter descriptors in the declaration of the procedure and the number of arguments in the argument list used to call the procedure.

The following rules apply when using the OPTIONS(VARIABLE) option:

  • If a procedure is called with more arguments than there are parameter descriptors, the trailing arguments are passed using the attributes of the last parameter descriptor. In this case, use of at least one parameter descriptor is required.
  • If a procedure is called with some arguments omitted, a null pointer is passed to the called routine in place of the missing argument. (The null pointer indicates an omitted argument.) An argument is considered to be omitted if two commas are found adjacent to one another in a call to a procedure, or if a comma comes after the left parenthesis or before the right parenthesis; that is, ( , a, ) indicates two missing arguments.
  • If a procedure is called with more arguments than there are parameter descriptors, and the trailing arguments are omitted (as indicated by adjacent commas), a null pointer is passed for each of the omitted arguments.

The following examples show how the ENTRY attribute can be used with the VALUE, ANY, OPTIONS(VARIABLE), and RETURNS(retums_descriptor) options. For a further description of these options, refer to each option by name within this chapter.

The following example causes the value of A to be converted to Fixed Binary(31) and the immediate value (25) to be passed directly to P5, followed by an immediate value representing the address of A:

DECLARE
   P5 ENTRY (FIXED BIN(31) VALUE, POINTER VALUE),
   A FIXED BIN(15),
   B POINTER;
   A = 25;
   B = ADDR (A);
   CALL P5(A,B);

The following example illustrates the use of the ENTRY attribute with the OPTIONS( VARIABLE) and ANY options:

DECLARE
   P1 ENTRY (FIXED BINARY(15), ANY) OPTIONS(VARIABLE),
   A FIXED BINARY(15),
   B FLOAT BINARY(23),
   C CHARACTER(1);
CALL P1(A, B);
CALL P1(A, C, B);

In the previous example, the second parameter descriptor is declared as ANY. In the first call to P1, B, a Float Binary(23) variable is the second argument passed; in the second call to P1, C, a Char(1) variable is passed. In both calls, the variable is passed by reference. Since the OPTIONS(VARIABLE) attribute is used, the second call to P1 passes argument three, B, using the attribute for parameter descriptor two, ANY. In the second call, the variable B is passed by reference.

The following example illustrates a procedure called with some arguments omitted.

DECLARE
   P2 ENTRY (FIXED BINARY(15), FIXED BINARY(15),
      FIXED BINARY(15)) OPTIONS(VARIABLE),
   (A,B) FIXED BINARY(15);

CALL P2(A, ,B);

In the previous example, the arguments to be passed are A, a missing argument, and B. This configuration causes the address of A to be passed, followed by a null value, followed by the address of B.

The following example illustrates a procedure called with more arguments than there are parameter descriptors:

DECLARE
   P3 ENTRY (FIXED BINARY(15),FIXED BINARY(15))
      OPTIONS(VARIABLE),
   (A,B) FIXED BINARY(15),
   C FLOAT BINARY(31);
CALL P3 (A, B, ,);
CALL P3 (A, B, C);

In the previous example, the first call to P3 is declared with two parameter descriptors and called with four arguments, the last two being null. The addresses of the last two arguments will be represented by null values. The second call to P3 passes C as a Fixed Binary(15), since it is a trailing argument and is passed with the attribute of the last parameter descriptor. This configuration requires that C be converted from Float Binary to Fixed Binary, and that the address of the resulting temporary be passed.

The following example illustrates constants and expressions being passed with the ANY option:

DECLARE P4 ENTRY (ANY,ANY),
   ( A, B ) FIXED BINARY(15);
CALL P4( 3, 'ABC');
CALL P4( '1'B, AB );

In the first call to P4, the constant 3 will be converted to Fixed Binary(31) and the address of the temporary variable containing the converted value will be passed as the first argument; the character-string constant 'ABC' will be converted to Character(3) and its temporary address passed as the second argument. In the second call to P4, the bit-string constant '1' B will be converted to Bit(1) Aligned, AB will be converted to Fixed Binary(31), and the respective addresses of the temporaries will be passed to P4.

The following example illustrates the use of the RETURNS(retums_descriptor) option:

DECLARE F ENTRY(FIXED) RETURNS(POINTER);
DECLARE G ENTRY(FLOAT)
   RETURNS(CHARACTER(32)VARYING);

In this example, F is declared as the name of a function procedure that returns pointer values. G is declared as the name of a function procedure that returns varying character-string values whose maximum length is 32 characters.

Parent topic: Attributes of DECLARE Statements
Related information
Storage Classes


ENVIRONMENT

Abbreviation: ENV

The ENVIRONMENT attribute and its options specify many record characteristics that are not part of the PL/I language. Its format is:

ENVIRONMENT(options–list)

options-list can contain any of a number options specifying record characteristics. For example,

ENVIRONMENT(VSAM KEYLOC(1) KEYLENGTH(12));

The ENVIRONMENT attribute is not supported for use with a STREAM file.

Parent topic: Attributes of DECLARE Statements
Related information
Record I/O


EXCLUSIVE

Abbreviation: EXCL

The EXCLUSIVE attribute specifies that the records in a file can be locked when accessed by one process to prevent access by another process. When the EXCLUSIVE attribute is used, the entire file is locked.

Parent topic: Attributes of DECLARE Statements


EXTERNAL

Abbreviation: EXT

EXTERNAL is a scope attribute that specifies that the declared name has external scope. This means that all declarations of this name anywhere in the program that also have the EXTERNAL attribute identify the same object.

The EXTERNAL attribute can be used only in the declaration of variables whose storage class is STATIC or CONTROLLED. (It can be redundantly specified for variables of storage classes GLOBALDEF and GLOBALREF, which are implicitly EXTERNAL STATIC.) If EXTERNAL is specified for a variable and no storage class attribute is specified, STATIC is supplied by default. Its format is:

EXTERNAL[(global_name)]

global_name is either a character-string constant or a %REPLACE name for a character string constant. global_name is used by the linker when references are made to the entry. Open PL/I makes no restrictions on the contents of global_name, but the underlying operating system may have restrictions.

EXTERNAL must be specified when the entry is declared in another module. EXTERNAL(global_name) is specified as an option either on a PROCEDURE statement or on an ENTRY statement.

By using the EXTERNAL(global_name) option, an alternative name can be specified for an external entry constant. Instead of the usual entry constant name, the alternative name (global_name) is used to invoke the procedure at the entry point.

OZS: PROCEDURE;
      DECLARE PROC1 ENTRY;
      DECLARE ALSO_PROC1 ENTRY EXTERNAL('PROC1');
      DECLARE PROC2 ENTRY EXTERNAL('ILL.EGAL');
      CALL PROC1;
      CALL ALSO_PROC1;
      CALL PROC2;
      END OZS;

      /*======== A SEPARATE MODULE ========*/

      PROC1: PROCEDURE;

      PROC2: ENTRY EXTERNAL('ILL.EGAL');

      END PROC1;

In this example, the program declares explicitly the entry constants PROC1 and PROC2.

Parent topic: Attributes of DECLARE Statements


FILE

FILE is a data type attribute. Used without the VARIABLE attribute, it specifies that the declared name is a file identifier having external scope and an associated file control block that can be used to perform I/O on files and devices known to the operating system. In this case, the EXTERNAL attribute and any of the file description attributes RECORD, STREAM, INPUT, OUTPUT, UPDATE, KEYED, DIRECT, SEQUENTIAL, and PRINT may also be specified. Any file description attributes specified in the declaration are merged with attributes supplied by the OPEN statement or attributes implied by the I/O statement that implicitly opens the file control block.

Used with the VARIABLE attribute, FILE specifies that the declared name is a file variable that can be assigned file values. In this case, the file description attributes cannot be supplied because a file variable has no associated file control block until a file value is assigned to it. File description attributes are attributes of a file control block and are not attributes of a file value or file variable.

Some attributes for a name declared implicitly can be determined from the context in which the name appears. These cases are called contextual declarations. A name that appears in a FILE option, or in an ON, SIGNAL, or REVERT statement for a condition that requires a file name, is given the FILE attribute. For example,

OPEN FILE(F);
WRITE FILE(W) FROM(BUF);
READ FILE®) INTO(BUF);
CLOSE FILE©);

In all four above cases the names used with the FILE option will be implicitly declared as having File data type.

Parent topic: Attributes of DECLARE Statements


FIXED

FIXED is an arithmetic data type attribute that defines a fixed-point arithmetic variable. Its format is:

FIXED[(p[,q])]

The precision p,q (q is optional and represents fractional digits) may be supplied with this attribute or with the BINARY or DECIMAL attribute, but it cannot be specified twice. The precision p and the scale q (if specified) must be positive integers. If a precision or scale is not specified, a default is assumed. If FIXED is specified without BINARY or DECIMAL, DECIMAL is assumed. For details on precisions, see your Open PL/I User's Guide and the section DEFAULT in the chapter Statements.

When used with BINARY, FIXED specifies integer arithmetic values that contain at least p bits. In this case, q must not be specified.

When used with DECIMAL, FIXED specifies fixed-point arithmetic values that contain at least p decimal digits. If q is specified, p minus q digits are integral digits and q digits are fractional digits. If q is omitted, q = 0 is assumed. These values are integers containing at least p decimal digits.

Parent topic: Attributes of DECLARE Statements
Related information
DEFAULT
Arithmetic Data


FLOAT

FLOAT is an arithmetic data type attribute that defines a floating-point arithmetic value. Its format is:

FLOAT[(p)]

The precision p may be supplied with this attribute or with the BINARY or DECIMAL attribute, but it cannot be specified twice. The precision p must be a positive integer. If a precision is not specified, a default precision is assumed. for information on the Open PL/I default precisions, see your Open PL/I User's Guide and the section DEFAULT in the chapter Statements.

If FLOAT is specified without BINARY or DECIMAL, DECIMAL is the default. If BINARY or DECIMAL is supplied without FIXED or FLOAT, FIXED is the default.

When used with BINARY, FLOAT specifies floating-point arithmetic values whose mantissa contains the equivalent of at least p bits.

When used with DECIMAL, FLOAT specifies floating-point arithmetic values whose mantissa contains the equivalent of at least p decimal digits.

Parent topic: Attributes of DECLARE Statements
Related information
DEFAULT
Arithmetic Data


GLOBALDEF

GLOBALDEF is a storage class and scope attribute that declares an external variable or external file constant and causes storage to be allocated for the variable or constant. Its format is:

GLOBALDEF [(name)]

where name is an identifier that is accepted as legal syntax for compatibility with other Open PL/I extensions, but is ignored, having no effect.

For variables, the GLOBALDEF attribute implies the EXTERNAL and STATIC attributes. For file constants, it implies the EXTERNAL attribute. A given variable or file constant may be declared with the GLOBALDEF attribute in only one procedure.

Parent topic: Attributes of DECLARE Statements


GLOBALREF

GLOBALREF is a storage class and scope attribute that declares a global symbol, which is defined in an external procedure either with the GLOBALDEF attribute or, if the external procedure is written in another programming language, with its equivalent in that language. Its format is:

GLOBALREF [(name)]

where name is an identifier that is accepted as legal syntax for compatibility with other Open PL/I extensions, but is ignored, having no effect.

The GLOBALREF attribute implies the EXTERNAL and STATIC attributes. A variable may be declared with the GLOBALREF attribute in as many procedures as desired. Unlike GLOBALDEF, GLOBALREF does not cause actual storage to be allocated for the external variable, but allows access to the storage that was allocated by some other external procedure.

If GLOBALREF is present, any INITIAL attribute for the variable is ignored.

P1: PROCEDURE;         P2: PROCEDURE;
DECLARE                   DECLARE
   XVAR FIXED BIN(15)        XVAR FIXED BIN(15)
      GLOBALDEF;             GLOBALREF;
XVAR = 23;             IF XVAR > 0 THEN XVAR = 100;
CALL P2;               .
.                      .
.                      .
.

In this example, XVAR is declared with the GLOBALDEF attribute in procedure P1 and is assigned storage as a result. The value 23 is assigned to XVAR. Procedure P2 has declared XVAR with the GLOBALREF attribute and will access the same memory location allocated by P1 . Procedure P2 can test and/or change the value of XVAR.

Parent topic: Attributes of DECLARE Statements


INITIAL

Abbreviation: INIT

INITIAL is a storage class attribute that specifies the initial value of a variable or member of a structure. The INITIAL attribute has two formats. The first specifies an initial constant, expression, or variable whose value is assigned to a variable when storage is allocated to it. The second format specifies that the CALL option invokes a procedure to perform initialization at allocation. The variable is initialized by assignment during the execution of the called routine, rather than by the routine being invoked as a function that returns a value to the point of invocation. The formats of the INITIAL attribute are:

Format 1:

INITIAL(item[,item]…)

where item is:

*|constant|variable|expression|iteration-spec

where iteration-spec is:

(iteration-factor) iteration-item

where iteration-item is:

*|constant|variable|expression

where iteration-factor is:

*|expression

where constant is:

arithmetic-constant|bit-constant|character-constant|
entry-constant1 label-constant

In the context of item or iteration-item, asterisk ( * ) specifies that the element is to be left uninitialized.

In the context of iteration-factor, asterisk (* ) specifies that the entire array is to be initialized with the iteration-item.

For static variables, any value specified in an INITIAL attribute is assigned at the time the program is first loaded into memory for execution.

For automatic variables, which are allocated at each activation of the declaring block, any specified initial value is assigned at the time of each allocation.

For based and controlled variables, which are allocated at the execution of ALLOCATE statements, any specified initial value is assigned at the time of each allocation.

The INITIAL attribute may not be used with variables of storage classes other than those mentioned above.

Only constant values with no operations can be specified in the INITIAL attribute for static variables, with the following exceptions:

  • The NULL() built-in function can be used to initialize a static pointer variable.
  • Expressions containing concatenated string constants can be used to initialize static string variables. For example:
    DECLARE STRING CHAR(5) STATIC INIT ('LIA' || 'NT');

Format 2:

INITIAL CALL entry(arg[,arg]…)

The INITIAL call cannot be used to initialize static data.

  • Examples of the INITIAL Attribute
Parent topic: Attributes of DECLARE Statements


Examples of the INITIAL Attribute

The following example will initialize all elements of 3x3 matrix A with the exception of its diagonal elements A (1,1), A(2,2), and A(3,3):

DECLARE A(3,3) FIXED BIN INIT(*,(3)0,*,(3)0,*);

The following example will initialize all elements of array B to the value of the expression (X+10 ) where X is a procedure parameter.

SUB; PROCEDURE(X);
DECLARE X FIXED BIN(15);
DECLARE B(5) FLOAT BIN INIT((HBOUND(B,1))(X+10));

The following example demonstrates the usage of asterisk repeat factor and will initialize the entire array Z to the value of 1.0.

SUB1: PROCEDURE(DIM);
DECLARE DIM FIXED BIN(15);
DECLARE Z(DIM) FLOAT BIN(23) INIT((*)1.0);

The INITIAL CALL is used to initialize automatic, based, or controlled variables by calling an external entry. The following is an example.

TEST: PROCEDURE OPTIONS(MAIN);

/* Initialize all elements of array TEN */
   DECLARE TEN(10) FIXED BIN(15)
      INIT CALL INITIALIZE(ADDR(TEN),HBOUND(TEN,1));

INITIALIZE: PROCEDURE(P,DIM);

DECLARE
   P           POINTER,
   DIM         FIXED BIN(15);
DECLARE
   I           FIXED BIN,
   ARRAY(1000) FIXED BIN(15) BASED;

   DO I = 1 TO DIM;
      P->ARRAY(I)=75;
   END;

END INITIALIZE;
END TEST;
Parent topic: INITIAL


INPUT

INPUT is a file description attribute that specifies that a file will be used for input.

The INPUT attribute may be given in the declaration of a file constant or in an OPEN statement. It must not be specified in the declaration of a file variable.

File description attributes specified in a DECLARE statement apply to all openings of the file control block associated with the file constant.

Parent topic: Attributes of DECLARE Statements
Related information
Input and Output
OPEN


INTERNAL

Abbreviation: INT

INTERNAL is a scope attribute that limits the scope of a variable to the block in which it is defined.

The INTERNAL attribute may be given with any storage class attribute or to parameters, but it has no significance since these variables always have internal scope. If STATIC is used without INTERNAL or EXTERNAL, INTERNAL is the default.

Parent topic: Attributes of DECLARE Statements


IRREDUCIBLE

Abbreviation: IRRED

IRREDUCIBLE is an attribute sometimes used by IBM mainframe PL/I programs. It is not needed by Open PL/I. It is simply parsed and otherwise ignored.

Parent topic: Attributes of DECLARE Statements


KEYED

KEYED is a file description attribute that indicates that records in a specified file may be accessed randomly. The KEYED attribute implies the RECORD attribute.

KEYED may be given in the declaration of a file constant or in an OPEN statement. It must not be specified in the declaration of a file variable.

Parent topic: Attributes of DECLARE Statements
Related information
OPEN


LABEL

LABEL is a data type attribute that specifies label values. When used in the declaration of a name, it specifies that the declared name is a label variable. When used in an ENTRY attribute, it specifies that the corresponding parameter is a label variable, and when used in a RETURNS attribute, it specifies that the procedure returns label values.

For a discussion of label values, see the section Label Data in the chapter Data Types.

Parent topic: Attributes of DECLARE Statements
Related information
Label Data


LIKE

LIKE specifies that the variable being declared has the same structure as the referenced variable. Its format is:

LIKE reference

where reference is a reference to a structure variable.

The variable being declared must be a structure variable. LIKE causes it to have exactly the same members, in name and attributes, as the referenced structure variable. Only the level numbers are changed as needed to adapt to the variable being declared.

In the following example, structure members are duplicated from one declaration to another by way of the LIKE attribute:

DECLARE 1 TEMPLATE BASED,
   2 NAME CHAR(45),
   2 SALARY FIXED BIN(15),
   2 EMP_NO FIXED BIN(15);
DECLARE 1 EMPLOYEE_INFO(1000) LIKE TEMPLATE;

Duplication of the members from TEMPLATE expands the declaration of EMPLOYEE_INFO, with the result that the declaration of EMPLOYEE_INFO is equivalent to:

DECLARE 1 EMPLOYEE_INFO(1000),
   2 NAME CHAR(45),
   2 SALARY FIXED BIN(15),
   2 EMP_NO FIXED BIN(15);

The referenced variable can be a major or a minor structure. It may be qualified, but may not be pointer-qualified. The following restrictions apply to the referenced variable:

  • It must be known in the block containing the LIKE attribute specification.
  • It cannot be subscripted.
  • It cannot contain a REFER variable.
  • Neither the referenced variable nor any of its substructures can be declared with the LIKE attribute.
  • It cannot be a substructure of a structure declared with the LIKE attribute.

The function of the LIKE attribute is similar to that of the TYPE attribute . With LIKE, the storage class of the referenced structure is not carried over to the created structure (same as TYPE). However, neither are the alignment attributes and/or dimensions of the referenced variable carried over (unlike TYPE). Only the alignment and dimensions of substructures and elements of the referenced variable are carried over.

Note: Open PL/I structure mapping adds padding bytes between the elements of aligned structures. To avoid this, add the UNALIGNED attribute to LIKE structures that need it.
Parent topic: Attributes of DECLARE Statements
Related information
TYPE


NATIVE

NATIVE is a data type attribute (applying to Fixed Binary items only) that specifies the internal storage for the data item is LSB first (or MSB "right -to- left"). This attribute is applicable only to Little-Endian machine architectures (such as Intel), and is the default if not specified. For Big-endian architectures, this attribute is ignored.

Example:

dcl flag fixed bin (15) static initial (1) native;
Parent topic: Attributes of DECLARE Statements


NONNATIVE

NONNATIVE is equivalent to BIGENDIAN.

Example:

dcl flag fixed bin (15) static initial (1) nonnative;
Parent topic: Attributes of DECLARE Statements
Related information
BIGENDIAN


OFFSET

The OFFSET attribute defines a locator data type used to specify the relative location of a based variable within an area. The format is:

OFFSET[(area–variable)]

For a complete description of offset data and the use of the OFFSET attribute, see the sections Offset Data and Area Data in the chapter Data Types.

Parent topic: Attributes of DECLARE Statements
Related information
Offset Data
Area Data


OPTIONS(DESCRIPTOR)

OPTIONS(DESCRIPTOR) is an entry name attribute. It specifies that argument descriptors will be passed to this entry by callers. This is the default for entry names. Argument descriptors are used to pass specific details about actual parameters in cases where parameter declarations contain CHAR(*) or DIMENSION(*) attributes.

Parent topic: Attributes of DECLARE Statements


OPTIONS(NODESCRIPTOR)

OPTIONS(NODESCRIPTOR) is an entry name attribute. It specifies that argument descriptors will not be passed to this entry by callers. Argument descriptors are used to pass specific details about actual parameters in cases where parameter declarations contain CHAR(*) or DIMENSION(*) attributes. The OPTIONS(NODESCRIPTOR) attribute is normally used to suppress the generation and passing of the descriptor(s) to a non-PL/I procedure.

Note:

OPTIONS(ASM) and OPTIONS(COBOL) are equivalent to OPTIONS(NODESCRIPTOR).

Parent topic: Attributes of DECLARE Statements


OPTIONS(VARIABLE)

OPTIONS(VARIABLE) is an entry name attribute that indicates, for an ENTRY descriptor, that a specified external procedure can be invoked with a variable number of arguments; a discrepancy may exist between the number of parameter descriptors in the declaration of the procedure and the number of arguments in the argument list used to call the procedure.

OPTIONS(VARIABLE) attribute is parsed and is otherwise ignored. It is an invalid attribute for a PROCEDURE or ENTRY statement, as opposed to the ENTRY attribute.

Parent topic: Attributes of DECLARE Statements
Related information
ENTRY


OUTPUT

OUTPUT is a file description attribute that indicates that data should be written to, and not read from, the associated file or device.

The OUTPUT attribute may be given in the declaration of a file constant or in an OPEN statement. It must not be specified in the declaration of a file variable.

Parent topic: Attributes of DECLARE Statements
Related information
OPEN


PICTURE

Abbreviation: PIC

PICTURE is a data type attribute that specifies pictured values. Its format is:

PICTURE'p'

The picture 'p' contains an image of the data and specifies the editing to be performed each time a value is assigned to a pictured variable. It also governs the conversion of pictured values to fixed-point decimal values.

For a discussion of pictured data and the picture characters, see the section Picture Data in the chapter Data Types.

Parent topic: Attributes of DECLARE Statements
Related information
Picture Data


POINTER

Abbreviation: PTR

POINTER is a data type attribute that specifies pointer values. A pointer value is the address of a variable and is discussed in the section Pointer Data in the chapter Data Types.

Parent topic: Attributes of DECLARE Statements
Related information
Pointer Data


POSITION

Abbreviation: POS

POSITION is an attribute that is used in conjunction with the DEFINED attribute. It specifies the bit or character within the basis variable at which the defined variable is to begin. Its format is:

POSITION(expression)

where expression is an integer expression that specifies the position relative to the start of the basis variable. The range of the expression is from 1 to n, where n is defined as:

n = basis_length – defined_length+1

where basis_length is the length of the basis variable in bits or characters and defined_length is the length of the defined variable in bits or characters.

Both the defined variable and the basis variable must be fixed-length bit strings, fixed-length character strings, pictured variables, or aggregates containing any of these data types.

In the following example, the two DO-groups accomplish the same purpose. The second makes use of the POSITION attribute:

DECLARE X CHARACTER(200);
DECLARE Y CHARACTER(1) DEF X POS(I);

DO I = 1 to 200;
   IF SUBSTR(x,i,1) = '?' THEN
      CALL ERROR();

DO I = 1 to 200;
   IF Y = '?' THEN   /* Uses position attributes */
      CALL ERROR();
Parent topic: Attributes of DECLARE Statements


PRINT

PRINT is a file description attribute used to declare a print file.

PRINT may be given in the declaration of a file constant or in an OPEN statement, but it must not be specified in the declaration of a file variable.

Parent topic: Attributes of DECLARE Statements
Related information
OPEN


READONLY

The READONLY attribute is parsed and is otherwise ignored. This is a compatibility feature to allow Open PL/I programs written for other systems to compile without error.

Parent topic: Attributes of DECLARE Statements


REAL

REAL is an arithmetic data type attribute. It specifies that the associated variable is used for real numbers (that is, single-part numbers, as opposed to complex). Arithmetic variables are assumed to be REAL by default.

Parent topic: Attributes of DECLARE Statements


RECORD

RECORD is a file description attribute that indicates that data in an input or output file is made up of separate records, and that the file will be processed by record I/O statements.

RECORD may be given in the declaration of a file constant or may be given in an OPEN statement. It must not be specified in the declaration of a file variable.

Parent topic: Attributes of DECLARE Statements
Related information
OPEN


REDUCIBLE

Abbreviation: RED

REDUCIBLE is an attribute sometimes used by IBM mainframe PL/I programs. It is not needed by Open PL/I. It is simply parsed and otherwise ignored.

Parent topic: Attributes of DECLARE Statements


REFER

REFER is an attribute of a based structure that specifies that the value of one member is used to determine the amount of storage space allocated for another member of the same structure. Its format is:

expressionREFER(variable)

where expression is evaluated and converted to Fixed Binary (15) and is the initial extent when the based structure is allocated. Variables used in the expression being evaluated as operands must not belong to the member containing the REFER attribute.

variable must be a variable contained by the structure being allocated and defined prior to the extent whose size it determines. For example:

DECLARE 1 STRUC BASED(P),
      2 I FIXED BINARY,
      2 A CHARACTER(20 REFER(I));

Multiple REFER attributes are allowed in the declaration of a structure.

Parent topic: Attributes of DECLARE Statements


RETURNS

RETURNS is an entry name attribute that specifies that the entry value designates a function procedure that returns a value of data type t, where t is a list of attributes that specify a data type. Its format is:

RETURNS[(t)];

For example:

DECLARE F ENTRY(FIXED) RETURNS(POINTER);
DECLARE G ENTRY(FLOAT)
      RETURNS(CHARACTER(32)VARYING);

In this example, F is declared as the name of a function procedure that returns pointer values. G is declared as the name of a function procedure that returns varying character-string values whose maximum length is 32 characters.

Any string length given in a RETURNS attribute must be an integer constant. The only attributes that can be given in a RETURNS attribute are data type attributes. DIMENSION or level numbers cannot be given, because functions cannot return arrays or structures.

Parent topic: Attributes of DECLARE Statements
Related information
ENTRY


SEQUENTIAL

Abbreviation: SEQL

SEQUENTIAL is a file description attribute that indicates that records in the file will be accessed sequentially.

SEQUENTIAL may be given in the declaration of a file constant or in an OPEN statement. It must not be specified in the declaration of a file variable.

Parent topic: Attributes of DECLARE Statements
Related information
OPEN


STATIC

STATIC is a storage class attribute that specifies that the storage for the declared variable is allocated by the Compiler and/or linker prior to program execution and remains allocated throughout program execution. The default attribute is AUTOMATIC.

Parent topic: Attributes of DECLARE Statements
Related information
Static Storage


STREAM

STREAM is a file description attribute that indicates that the file consists of ASCII characters and will be processed using the GET and PUT statements.

The STREAM attribute may be given in the declaration of a file constant or in an OPEN statement, but it cannot be specified in the declaration of a file variable.

Parent topic: Attributes of DECLARE Statements
Related information
OPEN


TYPE

The TYPE attribute allows a declaration to inherit structure members and attributes from another declaration. It has the following format, where reference is a reference to a variable:

TYPE(reference)

If, for example, a variable INTEGER is declared as fixed binary, another variable that needs to be declared as fixed binary can be declared as TYPE (INTEGER) instead. For example:

DECLARE INTEGER   FIXED BIN(31);    /* TYPE DEFINITION */
DECLARE CODE      TYPE(INTEGER);    /* TYPED VARIABLE */

In this example, Open PL/I copies the attributes from INTEGER to CODE, which makes the declaration of CODE become the following:

DECLARE CODE   FIXED BIN(31);

In the previous example, INTEGER is referred to as a type definition and CODE is referred to as a typed variable. A type definition is a normal variable declaration. It can be given the based storage class, because storage will not be allocated for the type definition.

In the following example, structure members are duplicated from one declaration to another by way of the TYPE attribute:

DECLARE 1 TEMPLATE BASED, /* TYPE DEFINITION */
   2 NAME CHAR(45),
   2 SALARY FIXED BIN(15),
   2 EMP_NO FIXED BIN(15);
DECLARE EMPLOYEE_INFO TYPE(TEMPLATE); /* TYPED VARIABLE */

Duplication of the members from TEMPLATE expands the declaration of EMPLOYEE_INFO, with the result that the declaration of EMPLOYEE_INFO is now:

DECLARE 1 EMPLOYEE_INFO
   2 NAME CHAR(45),
   2 SALARY FIXED BIN(15),
   2 EMP_NO FIXED BIN(15);

The TYPE attribute can be used in any of the following locations:

  • Within a variable declaration.
  • Within a parameter declaration.
  • As a parameter description within the explicit declaration of an ENTRY constant or ENTRY variable.
  • Within a RETURNS option of a PROCEDURE or ENTRY statement.
  • As a RETURNS attribute of an ENTRY declaration.

The following example illustrates all uses of the TYPE attribute:

/*----------- TYPE DEFINITION -----------*/
/* (LINE MAY ALSO BE USED AS A VARIABLE) */
DECLARE LINE CHAR(80) VARYING;
/*---------------------------------------*/

/* VARIABLE DECLARATION */
DECLARE FORMAT_LINE TYPE(LINE);

/* PARAMETER DECLARATION */
DECLARE PARAM TYPE(LINE);

/* PARAMETER DESCRIPTOR */
DECLARE WRITE_LINE ENTRY(TYPE(LINE));

/* RETURNS OPTION IN PROCEDURE STATEMENT */
GET_LINE: PROC RETURNS(TYPE(LINE));

/* RETURNS OPTION IN ENTRY STATEMENT */
READ_LINE: ENTRY RETURNS(TYPE(LINE));

/* RETURNS ATTRIBUTE IN DECLARE STATEMENT */
DECLARE GET_LINE ENTRY RETURNS(TYPE(LINE));

A typed variable can inherit only the following attributes from its type definition (storage class is not inherited):

  • ALIGNED
  • BINARY
  • BIT
  • CHARACTER
  • DECIMAL
  • ENTRY
  • FILE
  • FIXED
  • FLOAT
  • LABEL
  • PICTURE
  • OPTIONS
  • POINTER
  • RETURNS
  • UNALIGNED
  • UNION
  • VARIABLE
  • VARYING
  • string length
  • arithmetic precision
  • array dimensions.
  • TYPE Attribute Extensions
  • TYPE and Extent Expressions
  • Using the TYPE Attribute
  • Examples of the TYPE Attribute
Parent topic: Attributes of DECLARE Statements


TYPE Attribute Extensions

The TYPE attribute can be used to declare a function that returns an aggregate (that is, array or structure) result. For example:

/* TYPE DEFINITION */
DECLARE ARRAY(10) CHAR(80),
   1 STRUCTURE,
      2 LEVEL1 BINARY(15)
      2 LEVEL2 BINARY(15)
DECLARE       FUNCTION1 ENTRY RETURNS(TYPE(ARRAY));
   FUNCTION2 ENTRY RETURNS(TYPE(STRUCTURE));
Note:

All extents in the type definition of the function must have constant values. For example, the dimension attribute of ARRAY (10) in the preceding declaration could not be a variable.

The TYPE attribute also allows an aggregate variable to be passed by value in one of the following two situations:

  • When a typed variable (enclosed in parentheses) is used in an argument list (see the following example).
  • When a function reference used as an argument has a RETURNS value that is declared with the TYPE attribute (see the following example).
      DECLARE XARR(10) FIXED BIN(15)
          YYR TYPE( XARR ),
          RTE ENTRY( TYPE(XARR) ),
          FCA ENTRY RETURNS( TYPE(XARR) );
CALL RTE( (XARR) );  /* CASE 1 */
CALL RTE( (YYR) );   /* CASE 1 */
CALL RTE( (FCA()) ); /* CASE 2 */

The parameter in the called routine must have the same TYPE attribute as the argument. In the above example, RTE's parameter has the attribute TYPE (XARR) (see the third line). This TYPE attribute is the same TYPE attribute that is used by the arguments in the subsequent calls to RTE (see the last 3 lines).

All extents in a type definition must have constant values when an aggregate variable is passed by value. For example, in the preceding program fragment, XARR. could not be declared as:

DECLARE N FIXED BINARY(31) INIT(10);
DECLARE XARR(N) FIXED BIN(15),
      .
      .
      .

Dimensions (array bounds) can be specified on either the type definition or the typed variable, but not on both. For example, the following declaration of an array of arrays is invalid:

DECLARE XXX(10) CHAR(80), /* VALID */
   YYY TYPE( XXX ),
/* VALID */
   ZZZ(10) TYPE( XX );
/* INVALID -- ARRAY OF ARRAYS */
Parent topic: TYPE


TYPE and Extent Expressions

Any extent expressions are inherited by a typed variable from that typed variable's type definition, as illustrated by the following example. A typed variable's dimensions and element lengths are dependent on the current values of the extent expressions.

/* TYPE DEFINITION */
DECLARE CHARX(N,N) CHAR( LENGTH(STRING) ) BASED,
   N FIXED BINARY(15),
   STRING CHAR(80) VARYING;
/* TYPED VARIABLE */
DECLARE ARRAY TYPE(CHARX) BASED;

The evaluation of extents when the array is referenced follows the same rules that apply to the evaluation of based variables. In the following example, the variable array is declared in a different block from CHARX:

/*--------------------------------------------------*/
START:      PROCEDURE;
   DECLARE CHARX(N,N) CHAR( LENGTH(STRING) ) BASED,
      N FIXED BINARY(15),
      STRING CHAR(80) VARYING;
      .
      .
      .
/*--------------------------------------------------*/
NEXT: PROCEDURE;
   DECLARE ARRAY TYPE(CHARX) BASED,
      N FIXED BINARY(15),
      STRING CHAR(80) VARYING;
      .
      .
      .
END NEXT;

/*--------------------------------------------------*/
      .
      .
      .
END START;
/*--------------------------------------------------*/

In the preceding example, Open PL/I uses the declarations in procedure NEXT to evaluate the extent expressions of ARRAY. Declarations in the current block are always used to evaluate extent expressions, even for variables that have not been declared with the TYPE attribute. (In the preceding example, if procedure NEXT did not declare N and STRING, those variable declarations in procedure START would be used.)

If the REFER option is used in a type definition, the following are true:

  • If the type definition is a structure that has the BASED attribute with a REFER option, the BASED attribute for the corresponding typed variable must be specified.

    For example, in the following program fragment, VAR1 is a type definition, and VAR2 is a corresponding typed variable. The BASED attribute and a REFER option are specified in the declaration of VAR1. Therefore, the BASED attribute must be specified in the VAR2 declaration.

    DECLARE N FIXED BIN(15);

/* TYPE DEFINITION: */
DECLARE 1 VAR1 BASED,
        2 SIZE FIXED BIN(15),
        2 ITEMS( N REFER(VAR1.SIZE) ) CHAR(80);

DECLARE VAR2 TYPE(VAR1) BASED;

    when expanded yields:

    DECLARE 1 VAR2 BASED,
        2 SIZE FIXED BIN(15),
        2 ITEMS (N REFER (VAR2.SIZE)) CHAR(80);
  • A variable declared with a REFER extent cannot be used as a type definition.

    For example, in the previous program fragment, VAR1.ITEMS cannot be used as a type definition.

  • The reference in REFER(reference) must indicate a variable declared in the type definition (structure).

    For example, in the previous program fragment, VAR1.SIZE is the reference in the REFER option and must be a member of VAR1, the type definition. In addition, the expanded form of the VAR2 declaration contains a substitution of VAR2.SIZE for VAR1.SIZE as the REFER(reference).

Parent topic: TYPE


Using the TYPE Attribute

The reference in TYPE(reference) cannot:

  • Be pointer-qualified
  • Be a constant
  • Possess a subscript list or argument list

For example, the following declarations are invalid:

DECLARE MYFILE FILE STREAM OUTPUT PRINT;
DECLARE ZZZ TYPE( P -> Q );      /* INVALID -
                                 POINTER-QUALIFIED */
DECLARE URFILE TYPE( MYFILE );   /* INVALID - MYFILE IS
                                    CONSTANT */
DECLARE XXX TYPE( AAA(8) );      /* INVALID - HAS
                                    SUBSCRIPT LIST */
DECLARE YYY TYPE( FUN( ) );      /* INVALID -
                                    HAS ARGUMENT LIST */

The type definition cannot have the TYPE attribute, nor can it be any of the following:

  • A parameter
  • A member
  • Any structure declared with the TYPE attribute.

For example, the following declarations are invalid:

EXPROC: PROCEDURE( XYZ );
   DECLARE XYZ FIXED BIN(15),
      AAA TYPE( XYZ );/* INVALID - XYZ IS A PARAMETER */

   DECLARE INT FIXED BIN(15),
      B TYPE(INT),
      Y TYPE(B); /* INVALID - B IS TYPED */

   DECLARE 1 STRUCA,
      2 PROG TYPE (INT),
      2 NAMES CHAR(80);
      STRUCT1 TYPE(STRUCA),
      STRUCT2 TYPE(STRUCT1.NAMES); /* INVALID - NAMES IS
                                 IN TYPED STRUCTURE */

The reference in TYPE(reference) must not directly or indirectly refer to the variable that is declared, because then a circular definition will be created.

For example, the following declarations are invalid:

DECLARE 1 PROG,
   2 MOD CHAR(80),
   2 INT FIXED BIN(15),
   2 STRUCZ TYPE(PROG);/* INVALID - DIRECTLY CIRCULAR */

DECLARE 1 STRUCA,
   2 MOD CHAR(80),
   2 INT FIXED BIN(15),
   2 STRUCA TYPE(STRUCB); /* INVALID - INDIRECTLY
                           CIRCULAR */

DECLARE 1 STRUCB,
   2 MOD CHAR(80),
   2 INT CHAR(80),
   2 STRUCA TYPE(STRUCA); /*INVALID - INDIRECTLY
                           CIRCULAR */
Parent topic: TYPE


Examples of the TYPE Attribute

The following declarations are examples of other ways the TYPE attribute can be used:

DECLARE INT FIXED BIN(31);

/* DEFINE AN OPERATION ON CHARACTERS */
DECLARE RADIANS ENTRY( TYPE(INT), TYPE(INT) )
RETURNS( TYPE(INT) );

/* DEFINE ABSTRACT DATA TYPE */
DECLARE 1 LIST,
      2 HEAD POINTER,
   2 TAIL POINTER;

/* DEFINE OPERATION ON 'LISTS' */
DECLARE EXTEND_LIST ENTRY( TYPE(LIST),POINTER )
       RETURNS( TYPE(LIST) );

/* DEFINE AN ABSTRACT DATA TYPE */
DECLARE 1 COMPLEX_INTEGER,
   2 REAL TYPE( INTEGER ),
   2 IMAGINARY TYPE( INTEGER );

/* DEFINE OPERATIONS ON COMPLEX_INTEGER */
DECLARE (CIADD, CISUB, CIDIV, CIMUL)
   ENTRY( TYPE(COMPLEX_INTEGER),
            TYPE(COMPLEX_INTEGER) )
   RETURNS( TYPE(COMPLEX_INTEGER) );
Parent topic: TYPE


UNALIGNED

Abbreviation: UNAL

UNALIGNED is a data type attribute that controls the storage boundary of data.

UNALIGNED is an optional part of the data type specification. Its presence allows the Compiler to align the data at the next available bit or byte, rather than on implementation-defined storage boundaries. This can reduce storage requirements.

Parent topic: Attributes of DECLARE Statements
Related information
ALIGNED and UNALIGNED Attributes
Bit-String Data


UNION

UNION is an attribute applied to a structure, which causes all immediate members of that structure to occupy the same memory locations. An immediate member is any member having a level number greater than its containing structure, equal to the level number of its fellow members, and less than the level of members it contains. Typically, an immediate member has a level number that is one greater than its containing structure.

All members of a UNION will start at the same address. If extra bytes are required for proper alignment of one member, those bytes will appear before the beginning of the structure, that is, before all other members. The size of the UNION will be the size of its largest member.

In the following example, the 30-character ADDRESS_STRING and the members of ADDRESS_PIECES occupy the same memory. Changing ADDRESS_PIECES.CITY changes ADDRESS_STRING:

DECLARE
   1 ADDRESS UNION,
      2 ADDRESS_STRING CHARACTER(30),
      2 ADDRESS_PIECES,
            3 NUMBER CHARACTER(6),
            3 STREET CHARACTER(12),
            3 CITY CHARACTER(12);

In the following example, the data can be examined as 16 individual bits or as a single entity comprising one fixed binary number.

1 NUMBER UNION,
   2 FIXED_NUM FIXED BINARY(15),
   2 FIXED_NUM_BIT BIT(16);
Note: Code based on a particular representation of data types is highly machine-dependent and should be used cautiously.
Parent topic: Attributes of DECLARE Statements
Related information
Storage Sharing


UPDATE

UPDATE is a file description attribute that indicates that the file with which it is associated is to be used for both input and output.

UPDATE may be given in the declaration of a file constant or in an OPEN statement, but it must not be specified in the declaration of a file variable.

Parent topic: Attributes of DECLARE Statements
Related information
OPEN


VALUE

VALUE can be used as an attribute in an ENTRY declaration, or can be applied to a parameter.

  • When used in a parameter descriptor in an ENTRY declaration, the VALUE attribute is a storage class and scope attribute that specifies that the corresponding argument is to be passed by immediate value. (For more information on using VALUE in a parameter descriptor, see the section ENTRY.)
  • If applied to a parameter, the VALUE attribute is an argument-passing attribute. (As an argument-passing attribute, VALUE indicates that the value and not the address of the parameter has been passed to the procedure. A new value assigned to a parameter with the VALUE attribute does not change the value of the argument in calling procedures.)

The VALUE attribute may only be applied to a parameter and parameter descriptors of the following types:

Fixed Binary(n) | where n ? 31
Float Binary(n) | where n ? 23 (when calling PL/I)
Float Binary(n) | where n ? 52 (when calling non-PL/I)
Aligned Bit(n) | where n ? 32
Character |
Pointer |
Entry |

The VALUE attribute is ignored if it is applied to a variable that is not a parameter.

If a parameter is multi-positional (appears in one or more of the PROCEDURE and ENTRY statements in a particular procedure) it may not have the VALUE attribute applied to it.

When a procedure is called from an Open PL/I procedure, the VALUE attribute should be applied only to a parameter whose corresponding parameter descriptor was also declared with VALUE in the calling procedure's ENTRY declaration in the called procedure. For example:

P: PROCEDURE( A, B, Q);
DECLARE
   A FIXED BIN(31) VALUE,
   (B,C) FIXED BIN(15),
   Q POINTER VALUE,
   X FIXED BIN(15) BASED (Q);
B = A + 2;
A = 2 * B;
C = X;
ALLOCATE X SET(Q);
X = A + C;
END;

In this example, the value passed by A is incremented by 2 and returned to the calling procedure through B. The assignment of 2 * B to A does not affect the calling procedure; the value of the first argument of the CALL is unchanged by the assignment to A in the called procedure. Similarly, the value of the argument in the calling procedure that corresponds to Q is not changed by the ALLOCATE statement.

Parent topic: Attributes of DECLARE Statements
Related information
ENTRY


VARIABLE

VARIABLE is an entry name attribute that specifies that the declared name is a file or entry variable rather than a file name or procedure name.

Parent topic: Attributes of DECLARE Statements
Related information
Entry Data
File Data
ENTRY


VARYING

Abbreviation: VAR

VARYING is a character-string data type attribute that specifies that the string values may have any length that does not exceed the declared length.

For more information on this attribute, see the section Character-String Data in the chapter Data Types.

Parent topic: Attributes of DECLARE Statements
Related information
Character-String Data


References

  • Introduction
  • Simple and Subscripted References
  • Structure Qualified References
  • Locator Qualified References
  • Procedure References
  • Built-In Function References
  • Variable References
  • Reference Resolution
Parent topic: Open PL/I Language Reference Manual


Introduction

A reference is the declared name of a variable or constant, along with any subscript list, pointer qualifier (–>), or structure qualifier necessary to indicate its purpose. References to procedures or built-in functions may also include an argument list.

Examples:

X
Y(5,K)
F(Z*5+B,SQRT(Z))
P->S.A(K)
Q.NEXT->NODE.FIELD1

The first example is a simple reference, and the second is a subscripted reference. The third example is a reference to a procedure. The fourth and fifth examples are pointer qualified references.

A reference is associated with a declaration according to the scope of the declared name. The process of associating a reference with a declaration is called reference resolution, and it occurs during compilation of the program.

Parent topic: References


Simple and Subscripted References

A simple reference is a name without any subscripts, pointer qualifiers, structure names, or argument lists.

A subscripted reference is a name that has been declared as an array, followed by a parenthetical list of subscript expressions. Each subscript expression must produce an integer fixed-point value that lies within the lower and upper bounds specified for that dimension in the array declaration. The number of subscript expressions must be equal to the number of dimensions.

An asterisk subscript refers to the entire array bounds range for the corresponding dimension. Subscripts containing asterisks do not refer to a single data item. Thus, such references are array expressions, not element expressions.

A cross-section of an array may reference two or more elements that are not stored adjacently in memory. Such storage is referred to as non-connected storage.

DECLARE A(5,5) FLOAT;
DECLARE B(10) FLOAT;
   .
   .
   .
A(K*2,*) = B(1);
A(*,*) = 5;

In the preceding example, both A (K*2,*) and B (1) are subscripted references; K is a simple reference. A(*,*) references the entire array and A(K*2,*) references the entire 2Kth row.

Parent topic: References


Structure Qualified References

Because the names of structure members (with the exception of the major structure name) can be redeclared or reused within the same block, their scopes overlap. If a member's name has been redeclared within the same block, any reference to that member must be qualified by the name of its containing structure. If the containing structure's name has been redeclared within the same block, it must be qualified, in turn, by the name of its containing structure until an unambiguous reference is created.

A structure qualified reference is a sequence of names written left-to-right in order of increasing level-numbers. The names are separated by periods, and blanks may be written around the periods. The sequence need not include all containing structure names, but it must include sufficient names to make the reference unique. For example:

DECLARE       1  S,
     2          A  FIXED,
     2          B,
     3          A  FLOAT,
     3          C  FLOAT;

In this example, a reference to A is ambiguous because the scope of A FLOAT overlaps the scope of A FIXED. A structure qualified reference to S.A refers to A FIXED. A structure qualified reference to B.A refers to A FLOAT, as does S.B.A.

A structure qualified reference that includes the name of each containing structure from the major structure down to the member is a fully qualified reference. If the name of one or more of the containing structures is omitted, the reference is a partially qualified reference. In the previous example, B.A is a partially qualified reference, and S.B.A is a fully qualified reference, as are S.A, S.B, and S.B.C.

Subscripts can be used anywhere within a structure qualified reference, but it is best to write each set of subscripts immediately following the name that has the corresponding bounds declared for it. For example:

DECLARE     1   S(10),
     2        A    FIXED,
     2        B(3)    FLOAT,
     2        C(3),
     3        D   POINTER;

In the previous example, a reference to S(K).A and a reference to S.A(K) are equivalent, but a reference to S(K).A is preferred. Other recommended references are S(K).B(J) and S(K).C(J).

Parent topic: References


Locator Qualified References

A reference to a based variable may be qualified by a reference to a pointer or offset variable. For example:

DECLARE A(10) FLOAT BASED;
DECLARE P POINTER;

In this example, P –>A and P –>A(K) are pointer qualified references to the based variable A.

Since a pointer variable may itself be based, multiple qualification is possible. For example:

DECLARE     1 NODE BASED,
            2 NEXT POINTER,
            2 VALUE FLOAT;
DECLARE HEAD POINTER;

In this example, HEAD –>NODE.NEXT–>NODE.VALUE is a pointer qualified reference to NODE.VALUE. It is qualified by NODE.NEXT, which is, in turn, qualified by HEAD.

Pointer-valued functions and pointer-valued built-in functions may also be used as pointer qualifiers.

DECLARE NEXT_NODE ENTRY RETURNS(POINTER);

In this example, NEXT_NODE() –>NODE.VALUE is a pointer qualified reference to NODE.VALUE whose qualifier is a function reference.

When addressing data allocated in an area, an offset variable can be used as a locator qualifier in the same fashion as the pointer is in the above examples. The offset value will be implicitly converted to a pointer value by adding the address of the area specified in the OFFSET attribute of its declaration.

Parent topic: References
Related information
Offset Data


Procedure References

A procedure reference is any reference followed by an argument list consisting of a parenthetical list of expressions separated by commas or followed by an empty argument list (). A procedure reference that returns a value is called a function reference. A procedure reference that does not return a value is called a subroutine reference.

If an argument list or empty argument list is given, the referenced name must be declared as an entry either by appearing as a label prefix on a PROCEDURE statement or by a DECLARE statement. Unless the reference is part of a CALL statement, the referenced entry must return a value. If the reference is part of a CALL statement, the entry must not return a value; therefore, a procedure that returns a value must always be called as a function, and a procedure that does not return a value must always be called as a subroutine.

A name declared as an entry is called only when it is referenced with an argument list or when it is called by a CALL statement. A function that has no parameters must be referenced with an empty argument list.

Except when it is part of a CALL statement, a reference to an entry written without an argument list is a reference to the entry value, rather than a function reference that calls the entry.

The following example demonstrates a range of procedure references.

DECLARE F ENTRY RETURNS(POINTER);
DECLARE G ENTRY(FIXED) RETURNS(FLOAT);
DECLARE V ENTRY VARIABLE RETURNS(POINTER);
DECLARE P POINTER, X FLOAT;
   .
   .
   .
P = F();
V = F;
X = G(0);

In this example, a reference to F() calls F and produces a pointer value. A reference to F is a reference to the entry value of F and can be assigned to the entry variable V. A reference to G is also a reference to an entry value and does not call G. G is called by references containing an argument list.

An array of entry variables may be referenced with subscripts and with an argument list. In this case, the argument list follows the subscript fist, as shown in the following example:

DECLARE E(5) ENTRY(FIXED) VARIABLE
      RETURNS(POINTER);

According to E's declaration, E is a reference to the entire array of entry values. E (k) (j) is a pointer valued function reference that calls E (kf, passing it the argument j. E (k) is an entry value that may be passed to an entry parameter or assigned to an entry variable. If E had been declared without parameters, E (k) would have to be invoked using an empty argument list — E(k) () .

Parent topic: References


Built-In Function References

A reference to a built-in function always produces the value of that function and is never an entry value. Built-in functions cannot be assigned to entry variables or passed as arguments to entry valued parameters.

Built-in functions that take arguments do not have to be declared, but built-in functions that take no arguments, such as NULL and ONCODE, must either be referenced with an empty argument list () or must be declared with the BUILTIN attribute.

Parent topic: References


Variable References

A reference to a variable may occur in a context that expects a value, or it may occur in a context that assigns a value to the variable. If a value is expected, the variable must have previously been assigned a value or must be a variable declared with the INITIAL attribute. A reference to the value of a variable that has no value produces unpredictable results.

The left side of an assignment operator or the format-list of a GET statement causes assignment to a variable. Using a variable as the argument to a procedure or function call may also cause assignment to the variable if the corresponding parameter is given a value. The ADDR, HBOUND, LBOUND, DIMENSION, and LENGTH built-in functions reference a variable but do not expect a value. (However, LENGTH of a varying string variable does require that the string variable have a value.) A variable passed by reference to a parameter does not need to have a value if the parameter is not expected to have a value upon entry to its procedure. The record I/O statements copy a variable's storage and do not require the variable to have a value.

Parent topic: References


Reference Resolution

The following is the sequence of steps taken by the Compiler to resolve references:

  1. Determine the initial block in which the search for the declaration begins.
  2. Find the referenced declaration and the block to which it belongs. Find the activation associated with that block.
  3. Evaluate the locator qualifier (if any) to obtain a pointer value.
  4. Evaluate the basis reference (if the reference is to a defined variable) and pointer.
  5. Determine all the extents (if any) of the referenced variables.
  6. Interpret the subscripts (if any).
  7. Invoke the procedure (if any).

Remember the following points when preparing for reference resolution:

  • A fully or partially qualified structure reference is applicable to declarations of structures that include the same hierarchy of names as is used in the structure reference. A simple or subscripted reference to a name is applicable to any declaration of the name.
  • A reference is resolved by finding the innermost block that contains any applicable declaration. If no containing block has an applicable declaration, the reference is invalid. If the block has only one applicable declaration, the reference is resolved to that declaration. If the block has more than one applicable declaration, the reference must be fully qualified to cite only one declaration in that block; otherwise, the reference is ambiguous and invalid.
  • Once a block containing an applicable declaration is found, no containing blocks are searched in an attempt to resolve a reference.
  • The presence of subscripts, arguments, or a locator qualifier has no effect on the resolution of a reference and cannot make an ambiguous reference unique.
  • A simple or subscripted reference to a name X is considered to be a fully qualified reference to a nonmember declaration of X. This means that if a member and a nonmember are declared to have the name X in the same block, a reference to X is resolved to the nonmember. The member must be referenced using a structure qualified reference.
Parent topic: References


Expressions

  • Introduction
  • Order of Evaluation
  • Array Expressions
  • Types of Operators
Parent topic: Open PL/I Language Reference Manual


Introduction

An expression is a representation of a value or of the computation of a value. Expressions are classified as either element (scalar) expressions or array expressions.

Element expressions represent element values, including elementary names within a structure or a subscripted name that specifies a single element of an array. Array expressions represent either an entire array or a cross-section of an array. Element variables and array variables may be used in the same expression.

Expressions are used for the following reasons:

  • To indicate constant values or scalar variables. For example:
    D = 40;
  • To perform algebraic or logical calculations on constants or variables. For example:
    A = B + 10;
  • To compare values of two or more expressions and obtain a Boolean result. For example:
    IF C < D THEN E = 12;
  • To concatenate bit-string or character-string values. For example:
    ADDRESS = CITY | STATE;

All expressions, except for single constants and references, are made up of an operator and one or more operands. An operator requires specific types of operands (arithmetic, character-string, or bit-string) and produces a result of a specific type. Operands can be constants, variable references, user-defined function references, built-in function references, or other expressions that match the type required by the operator.

Operators can be either infix or prefix. An infix operator is written between its two operands, and a prefix operator is written in front of its operands, as shown in the following table of operators.

Operator | Category | Example
+ – * / ** | arithmetic infix | B+C
+ – | arithmetic prefix | -C
= ^= > < >= <= ^< ^> | relational | B=C
| or & | bit-string infix | BIC
^ | bit-string prefix | ^C
|| or !! | concatenate | B||C

One expression can contain both an infix and a prefix operator. For example:

A*-B
Note:

Open PL/I supports the use of a tilde (~) as an operator symbol equivalent to a caret (^).

Open PL/I supports the use of an exclamation point (!) as an operator symbol equivalent to a single bar (|), and a double exclamation point (!!) as equivalent to a double bar (||).

Parent topic: Expressions


Order of Evaluation

When an expression contains more than one operator, the order in which each expression is evaluated is determined by the presence or absence of parentheses and by the priority of the expression's operators.

The following table shows the operators in order of descending priority. Operators listed on the same line have equal priority.

Operators
**
^ – (prefix unary operators)
*/
+ – (binary operators)
|| or !!
= ^= > < >= <= ^< ^>
&
|
Note:

Open PL/I supports the use of a tilde (~) as an operator symbol equivalent to a caret (^).

Open PL/I supports the use of an exclamation point (!) as an operator symbol equivalent to a single bar (|), and a double exclamation point (!!) as equivalent to a double bar (||).

In expressions without parentheses, operators are evaluated in order of decreasing priority. For example:

B**3+C<D

is evaluated as:

((B**3)+C)<D

Operations of equal priority without parentheses are generally evaluated from left to right. For example:

A*B/C

is evaluated as:

(A*B)/C

The only exception to this rule is the prefix operators and the exponentiation operator (**), which are evaluated from right to left. For example:

A**B**C

is evaluated as:

A**(B**C)

If the expression contains parentheses, the expression within the parentheses is evaluated first according to the previous rules of priority. Its resulting value is used as a single operand. For example:

A+B*C

is evaluated as:

A+(B*C)

because * has higher priority than +; however, parentheses can be used to force another order:

(A+B)*C

If the result of an expression can be determined without evaluating all of its operands, the operands are not necessarily evaluated. A program that depends on all operands being evaluated is invalid and may produce unexpected results when compiled with optimization enabled, or when moved to another implementation of PL/I. Likewise, a program that depends on some operands not being evaluated is invalid. For example:

IF A = 0 | B/A = 5 THEN …

In this example, the Compiler can evaluate B/A before checking to see if A = 0, and the complete expression may produce a ZERODIVIDE condition. However, the order of evaluation is not guaranteed by the Compiler. In particular, if A is in fact 0, the value B/A may or may not be computed. This optimization, in which parts of a conditional expression may cause other "unnecessary" parts not to be evaluated, is called "short circuit evaluation." Such evaluation is done at the discretion of the Compiler and its optimizer. To force A = 0 to be evaluated first, rewrite the example as follows:

IF A ^= 0 THEN
   IF B/A ^= 5 THEN
      GOTO L;
      .
      .
      .
   L:

The remainder of this chapter describes each type of operator.

Parent topic: Expressions


Array Expressions

Array expressions can be used only in assignment statements. The result of the evaluation of an array expression is an array. Operations on arrays are performed element by element in row-major order. All arrays referred to in an array expression must have identical dimensions and bounds. Arithmetic operators excluding ** can be used for operators for array cross-sections.

Array expressions may include any of the following:

  • Prefix and/or infix operators
  • Element variables
  • Array variables
  • Constants

The operation and data conversion rules are the same as for element expressions.

  • Prefix Operators and Arrays
  • Infix Operators and Arrays
  • Array and Element Operations
  • Array and Array Operations
Parent topic: Expressions


Prefix Operators and Arrays

An array expression that contains prefix operators results in an array with identical bounds, with each element reflecting the result of the operation performed on the original element. For example:

Array A before operation | Operation | Array A after operation
1 | 2 | -3 | -A | -1 | -2 | 3
4 | 5 | 6 |  | -4 | -5 | -6
7 | 8 | -9 |  | -7 | -8 | 9
Parent topic: Array Expressions


Infix Operators and Arrays

Array expressions contain an array, an infix operator, and either an element or another array. The result of such an expression is an array with identical bounds and dimensions that reflect the result of the operation on the elements of the original array.

Parent topic: Array Expressions


Array and Element Operations

An array expression that contains an infix operator, array, and element results in an array with identical bounds, with each element reflecting the result of the operation performed on the original array element and the single element. For example:

Array A before operation | Operation | Array A after operation
1 | 2 | -3 | A = A * 2 | 2 | 4 | -6
4 | 5 | 6 |  | 8 | 10 | 12

The element operand may be an element of the array:

Array A before operation | Operation | Array A after operation
1 | 2 | -3 | A = A * A(1,3) | -3 | -6 | 9
4 | 5 | 6 |  | 36 | 45 | 54

In the preceding example, the element A(1,3) was -3 in the original array. When that element was operated on and resulted in 9, 9 was used in the operations on the rest of the array.

Parent topic: Array Expressions


Array and Array Operations

An array expression that contains an infix operator and two arrays results in an array with identical bounds, with each element reflecting the result of the operation performed on the corresponding elements of the original arrays. For example:

Array A | * | Array B | = | Result
1 | 2 | -3 |  | 2 | 3 | 4 | 2 | 6 | -12
4 | 5 | 6 |  | 5 | 6 | 7 | 20 | 30 | 42
Note:

This is not the same as mathematical matrix multiplication.

Parent topic: Array Expressions


Types of Operators

The types of operators are arithmetic, relational, bit-string, and concatenate.

  • Arithmetic Operators
  • Relational Operators
  • Bit-String Operators
  • The Concatenate Operator
Parent topic: Expressions


Arithmetic Operators

The arithmetic operators and the operations they stand for are:

Operator | Operation
prefix + | Plus
prefix – | Minus
+ | Addition
– | Subtraction
* | Multiplication
/ | Division
** | Exponentiation

There are also compound assignment operators. These are:

+= -= *= /=

Each of the following pairs of statements are equivalent:

a = a + b;
a += b;
a = a - b ;
a -= b;
a = a * b;
a *= b;
a = a / b;
a /= b;

The arithmetic operators require arithmetic operands. Although these operands can be of different arithmetic types, all operations must be performed on objects of the same type. Pictured values are converted to fixed decimal values, but other nonarithmetic values must be converted to arithmetic values by one of the conversion built-in functions, such as BINARY, DECIMAL, FIXED, or FLOAT.

If the data types of two operands of an infix operator (other than **) differ, the operands are converted to a common arithmetic data type, as shown in the following table.

One Operand | Other Operand | Common Operand
fixed | float | float
binary | decimal | binary (for floating-point or integer result)
binary | decimal | decimal (for fixed-point noninteger result)

All arithmetic operations except for exponentiation are performed in the derived type of the two operands. (For the precision resulting from the conversion of an operand to its derived type, see the table in Arithmetic to Arithmetic Conversion.) Though two converted operands may have the same derived base and scale, they may each have different values for p and q (scale and base, respectively).

All arithmetic operations, including exponentiation, produce a result that has the same data type as the type in which the operations are performed. In all operations but exponentiation, the data type is derived.

If an arithmetic operation is performed in floating point, the precision of the result is the maximum of the precisions of the two operands for binary operators, and is equal to the precision of the operand for unary operators. If this is not the desired result precision, use the FLOAT() built–in function to increase the precision of one or both of the operands.

An exponentiation operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

The remainder of this topic defines a series of rules, called fixed-point precision rules, which effectively allow the result of an expression to be formed by aligning the decimal points of the two operands to produce a fixed-point result. The number of digits in the result is always limited by the maximum number of digits allowed by the implementation for the result base; however, as many fractional digits as are allowed by the implementation are preserved, except for the result of divide. (For details on this implementation, see your Open PL/I User's Guide.) For divide, all integer quotient digits are preserved and as many fractional digits as can be allowed by the implementation are preserved.

The results of all arithmetic operations, except for exponentiation, always have a precision that is the maximum of the precisions of the converted operands.

The rules for determining the precision of the results of arithmetic expressions are as follows:

  1. Plus and minus produce a result whose data type is the same as the converted operand.
  2. Add and subtract of fixed-point values produce a fixed-point result whose base is the common base and whose precision is:
    FIXED(P,Q)±FIXED(R,S)

    and yields

    P=MIN(N,1+MAX(P-Q,R-S)+MAX(Q,S))
Q=MAX(Q,S)

    where:

    N is the implementation's maximum allowed precision for fixed-point values of the result base (described in your Open PL/I User's Guide).

    (P,Q) is the converted precision of the first operand

    (R,S) is the converted precision of the second operand

  3. For integer operands (Q=0 and S=0), the result precision formula reduces to:
    FIXED(P,0)±FIXED(R,0)

    and yields

    P=MIN(N,1+MAX(P,R))
Q=0
  4. Multiplication of fixed-point values produces a fixed-point result whose base is the common base and whose precision is:
    FIXED(P,Q)*FIXED(R,S)

    and yields

P=MIN(N,P+R+1) Q=Q+S

    where:

    N is the implementation's maximum allowed precision for fixed-point values of the result base (described in your Open PL/I User's Guide).

    (P,Q) is the converted precision of the first operand,

    (R,S) is the converted precision of the second operand

  5. For integer operands (Q=0 and S=0), the result precision formula reduces to:
    FIXED(P,0)/FIXED(R,0)

    and yields

    P=MIN(N,P+R+1)
Q=0
  6. Division of fixed-point values is possible only if both operands are fixed decimal. The result is a fixed decimal value of precision:
    FIXED(P,Q)/FIXED(R,S)

    and yields

P=N
Q=N-P+Q-S

    where:

    N is the maximum fixed-point decimal precision

    (P,Q) is the precision of the first operand

    (R,S) is the precision of the second operand

  7. For integer operands (Q=0 and S=0), the previous formula reduces to:
    FIXED(P,0)/FIXED(R,0)

    and yields

    P=N
Q=N-P

    The formula produces a result quotient that has sufficient precision for all integral digits of the quotient and as many fractional digits as are allowed by the implementation (for Open PL/I's limits, see your Open PL/I User's Guide).

  8. The result of a division operation may have a large fractional part, and in such instances, may not be able to be added or multiplied with another value because alignment of the decimal point with the other value produces a result that is too big for LPI-PLI to support.
  9. The ADD, DIVIDE, and MULTIPLY built-in functions can be used to add, divide, and multiply fixed-point binary values, as well as fixed-point decimal values. These functions provide you with control over the result precision. See the section DECIMAL Function in the chapter Open PL/I Built-Ins.
  10. Exponentiation produces a result whose base, scale, and precision depends on the operands. The result is determined as follows:

    Case 1:

    If the first operand is fixed-point and the second operand is an integer constant whose value is Y, and if (P+1)*Y-1 does not exceed N, the result is a fixed-point value whose base is that of the first operand and whose precision is:

    FIXED(P,Q)**Y     /* Y is an integer constant */

    and yields

    P=(P+1)*Y-1
Q=Q*Y
P<=N

    where N is the maximum precision allowed for fixed-point values of the base of the first operand, (P,Q) is the precision of the first operand, and Y is the value of the second operand.

    Case 2:

    If the second operand is a fixed-point integer value, but Case 1 does not apply, the result is a floating-point value whose base is the base of the first operand and whose precision is:

    P=MIN(N,P)

    where N is the maximum precision allowed for floating-point values of the resulting base and P is the precision of the first operand.

    Case 3:

    If neither Case 1 nor Case 2 applies, the result is a floating-point value having the common base and whose precision is:

    P=MIN(N,MAX(P,R))

    where N is the maximum precision allowed for floating values having the result base, P is the converted precision of the first operand, and R is the converted precision of the second operand.

  11. The result of exponentiation is normally the first operand raised to the power of the second operand. The following are exceptions to this general rule.

    Given X is the value of operand one and Y is the value of operand two:

    • If X = 0 and Y <= 0, ERROR is signaled.
    • If X< 0 and Case 1 does not apply, ERROR is signaled.
Parent topic: Types of Operators
Related information
DECIMAL Function
Arithmetic to Arithmetic Conversion


Relational Operators

The relational operators and the operations they stand for are as follows:

Operators | Operations
= | Equal
^= | Not equal
> | Greater than
< | Less than
>= | Greater than or equal to
<= | Less than or equal to
^< | Not less than (equivalent to >=)
^> | Not greater than (equivalent to <=)
Note:

Open PL/I supports the use of a tilde (~) as an operator symbol equivalent to a caret (^).

The relational operators test the relationship of two operands. The result is always a Boolean value (a bit string of length 1). If the comparison is true, the resulting value is '1'B; if the comparison is false, the resulting value is '0'B. All relational operators are infix operators.

All operands used with relational operators must be scalar. If either operand is an arithmetic value or a pictured value, the operands are converted to a common arithmetic type as if they were operands of an add operator. If one operand is a pointer value and the other is an offset value, the offset is converted to a pointer, but only for = and ^= comparisons. In all other cases, the data types of the two operands must be equivalent.

When determining if two data types are equivalent, the ALIGNED, VARYING, RETURNS, UNALIGNED, VARIABLE, and string length attributes are ignored. Label, entry, file, and pointer data may be compared only for equality or inequality. Arithmetic and string data may be compared using any relational operator.

Arithmetic and pictured values are compared algebraically.

Character-string values are compared from left-to-right one character at a time until an inequality is found. The shorter value is effectively extended on the right with blank characters to make it the length of the longer value. Characters are compared using the collating sequence of the computer.

Bit-string values are compared from left-to-right one bit at a time until an inequality is found. The shorter value is effectively extended with zero bits on its right until it is the length of the longer value.

Pointer values are equal only if they address the same storage location.

Label and entry values are equal only if they designate the same statement and the same stack frame.

File values are equal only if they designate the same file control block.

Only comparisons of = and ^= are allowed for offset values. Area variables cannot be compared.

Parent topic: Types of Operators


Bit-String Operators

The bit-string operators and the operations they stand for are as follows:

Operators | Operations
& | and
| | inclusive or
^ | not (complement)
Note:

Open PL/I supports the use of a tilde (~) as an operator symbol equivalent to a caret (^).

Open PL/I supports the use of an exclamation point (!) as an operator symbol equivalent to a single bar (|).

Bit-string operators require bit-string operands. Operands of other data types must be converted to bit-string values using the BIT built-in function.

The infix operators & and | operate on operands of dissimilar length by effectively extending the shorter value to the length of the longer value. This is done by appending zero bits to the right end of the shorter value.

The result of ^ is a bit string whose bits are the complement of the bits in the operand; that is, each 0 bit becomes a 1 bit and each 1 bit becomes a 0 bit.

The result of & and | is a bit string whose length is that of the larger operand. Each bit of the result is listed as follows:

First Operand | Second Operand | & | |
0 | 0 | 0 | 0
0 | 1 | 0 | 1
1 | 0 | 0 | 1
1 | 1 | 1 | 1

For instance, if X is '01011'B and Y is '11001'B, ^X produces '10100'B, X&Y produces '01001'B, and X | Y produces '11011'B. X&'11'B would produce '01000'B.

Parent topic: Types of Operators
Related information
BIT Function


The Concatenate Operator

The concatenate operator, || or !!, is used to concatenate two strings to produce a string result.

The compound assignment operator ||= is also supported. The following two statements are equivalent:

s = s || s1;
s ||= s1;

If both operands are bit strings, the concatenate operator produces a bit-string result; otherwise, both operands are converted to character strings, and a character-string result is produced.

The length of the string result is the sum of the lengths of the converted operands, as shown in the following example:

A = 'ABC';
B = 'XYZ';

In the previous example, A | | B produces 'ABCXYZ ', and A | ! 5 produces 'ABC 5'. The conversion rule that produces the blanks is explained in the topic Arithmetic to Character-String Conversion in the chapter Data Type Conversions.

Parent topic: Types of Operators
Related information
Arithmetic to Character-String Conversion


Data Type Conversions

  • Introduction
  • Arithmetic to Arithmetic Conversion
  • Arithmetic to Bit-String Conversion
  • Arithmetic to Character-String Conversion
  • Bit-String to Arithmetic Conversion
  • Bit-String to Character-String Conversion
  • Character-String to Arithmetic Conversion
  • Character-String to Bit-String Conversion
  • Format Controlled Conversion
  • Pictured to Arithmetic Conversion
  • Pictured to Bit-String Conversion
  • Pictured to Character-String Conversion
  • Conversion to Pictured Data
Parent topic: Open PL/I Language Reference Manual


Introduction

Each arithmetic, pictured, or string value can be converted to another value whose data type is any other arithmetic, pictured, or string data type. Conversion is not possible for data other than arithmetic, pictured, or string data.

Conversions occur as a result of using the assignment, arithmetic, relational, or concatenate operators; from the use of certain built-in functions; from GET/ PUT statements during parameter passing; and from statement options such as KEY and KEYFROM.

Each conversion begins with a source value to be converted and a complete or partial data type called the target data type. The target data type is determined by the context that caused the conversion. For example, the data type of the variable on the left side of the assignment operator provides the target data type for the conversion that is to be performed for that assignment. A partial target data type may result from the use of a conversion built-in function such as FIXED, FLOAT, BINARY, DECIMAL, BIT, or CHARACTER, as well as from other contexts, such as the use of arithmetic operators.

The conversion rules described in the section Arithmetic Operators define the target data type for conversions that result from arithmetic or relational operators. The section The Concatenate Operator gives the target data type for conversions that result from using the concatenate operator. Conversion between pointers and offsets is discussed in the section Locator Data.

The following table shows the specific conversions described in this chapter.

Data Type | Conversion
Arithmetic | Arithmetic to Arithmetic Arithmetic to Bit string Arithmetic to Character string
String | Bit string to Arithmetic Bit string to Character string Character string to Arithmetic Character string to Bit string Format Controlled
Pictured | Pictured to Arithmetic Pictured to Bit string Pictured to Character string Conversion to Pictured Data

The CEIL function used in many of the conversion rules gives the smallest integer that is greater than or equal to the function's argument. For example,

CEIL(1.1)

produces the value two.

Parent topic: Data Type Conversions
Related information
Arithmetic Operators
The Concatenate Operator
Locator Data


Arithmetic to Arithmetic Conversion

Arithmetic to arithmetic conversion assigns any arithmetic data type to any other arithmetic data type. This type of conversion occurs most frequently as a result of using operands of differing arithmetic types in an arithmetic or relational operation. In all cases, the target base and scale are supplied by the conversion rules of the operator or built-in function, but the target precision is not supplied.

If a target precision is not supplied, it is determined from the data type of the source value (listed vertically) and the target base and scale (listed horizontally), as shown in the table below.

Target Base And Scale, Precision r[,s] | Source Base And Scale, Precision p[,q]
 | Fixed Binary | Fixed Decimal | Float Binary | Float Decimal
Fixed Binary | r = p | r = MIN(CEIL (p*3.32)+1,n) | * | *
Fixed Decimal | r= MIN(CEIL(p/3.32)+1, n) | r= p | * | *
Float Binary | s=0 r =MIN(p,n) | s = q r= MIN (CEIL(p*3.32),n) | r= p | r=MIN(CEIL(p*3.32),n)
Float Decimal | r=MIN (CEIL(p/3.32),n) | r=MIN(p,n) | r = MIN (CEIL(p/3.32),n) | r= p
* | These conversions arise only in cases where the target precision is explicitly known, as in the case of assignment to a fixed-point variable.
n | The maximum number of digits allowed by Open PL/I for the target base and scale. For precision limits, see your Open PL/I User's Guide.

Conversion of a fixed-point decimal value containing a fraction to floating-point or vice versa produces an approximate value. The result is the number in the target scale and precision that is closest to the source value and is produced by rounding at the last binary or decimal digit position.

Conversion of a fixed-point decimal value containing a fraction to a fixed-point value with no fraction or fewer fractional digits results in truncation of excess digits without rounding. Rounding can be performed by using the ROUND, CEIL, FLOOR, or TRUNC built-in functions, as described in the chapter Open PL/I Built-ins.

If the target precision does not provide sufficient digits to hold all integral digits of the converted value, the program is in error. This error is not detected by Open PL/I and may or may not be detected by another implementation of PL/I. If detected, the ERROR condition is signaled. If undetected, the program produces unpredictable results. Programs that contain this undetected error and produce "correct" results may fail when moved to another implementation of PL/I.

The following shows the target precisions given, in the table above, for some common source values and target data types. Note that for some implementations, the target precision may be limited to a value smaller than what is shown here.

Source | Target
Fixed Binary(15) | Fixed Decimal(6,0)
Fixed Binary(31) | Fixed Decimal(11,0)
Float Binary(21) | Float Decimal(7)
Float Binary(52) | Float Decimal(16)
Fixed Decimal(4) | Fixed Binary(15)
Fixed Decimal(7) | Fixed Binary(25)
Float Decimal(6) | Float Binary(20)
Float Decimal(15) | Float Binary(50)
Parent topic: Data Type Conversions
Related information
Open PL/I Built-ins


Arithmetic to Bit-String Conversion

Arithmetic to bit-string conversion converts the absolute value of an arithmetic value to a bit string, but may not produce the result you expect.

The arithmetic source value is first converted to fixed binary(K) where K is determined by the source data type, as shown in the following table.

Source Data Type | Value of K
Fixed Decimal(P,Q) | MIN(N,MAX(CEIL((P-Q)*3.32),0))
Float Decimal(P) | MIN(N,CEIL(P*3.32))
Fixed Binary(P) | (P)
Float Binary(P) | MIN(N,P)

The absolute value of the resulting integer is considered to be a bit string of length K. If the context that caused the conversion supplied a target length, this bit string is extended on the right with zero bits to make it the length of a longer target, or excess bits are truncated from the right to make it the length of a shorter target. The program is in error and may produce unpredictable results if the value of the source is too large to be converted to an integer of precision (K). For example, if V is a Fixed Binary(15) variable with the value of 5, its value when converted to a bit string of length 15 is '000000000000101'B. If the target is Bit(16), the result is '0000000000001010'B, because padding occurs on the right. If the target is Bit(5), the result is '00000'B, because all excess bits are truncated from the right.

Parent topic: Data Type Conversions


Arithmetic to Character-String Conversion

Arithmetic to character-string conversion often arises during list-directed stream output, concatenation, or during assignment to a character string.

The arithmetic source value is first converted to a decimal value having the same scale as the source and with a decimal precision determined by the target precision data shown in the table in Arithmetic to Arithmetic Conversion.

The decimal value whose precision is now (p,q) is then converted to a character string whose value is given by one of the following cases:

  • Case 1
  • Case 2
  • Case 3
Parent topic: Data Type Conversions
Related information
Arithmetic to Arithmetic Conversion


Case 1

If the decimal value is floating-point, the length of the resulting character string is p+n+4, and its value consists of a minus if the value is negative or a blank if it is not negative, followed by the most significant digit of the mantissa, followed by a decimal point, followed by p-1 digits of the mantissa, followed by the letter E, followed by the sign of the exponent, followed by n exponent digits. The number of exponent digits depends on the implementation, but is constant for a given implementation. In Open PL/I, three exponent digits are produced.

  • Examples
Parent topic: Arithmetic to Character-String Conversion


Examples

The values in the above examples could result from conversion of a Float Binary(21) value. Seven digits are produced, because Float Binary(21) converts to Float Decimal(7). For more information, see the table in Arithmetic to Arithmetic Conversion.

Parent topic: Case 1
Related information
Arithmetic to Arithmetic Conversion


Case 2

If the decimal value is fixed-point with no fraction (q=0), the length of the resulting character string is p+3, and its value consists of sufficient blanks to fill the p+3 character result, followed by a minus if the value is negative, followed by the p digits of the decimal value with no leading zeros (the value zero has one zero digit).

  • Examples
Parent topic: Arithmetic to Character-String Conversion


Examples

The values in the previous examples could result from conversion of a Fixed Binary(15) value. The result is nine characters long, because Fixed Binary(15) converts to Fixed Decimal(6), and the result is 6+3 characters long.

Parent topic: Case 2


Case 3

If the decimal value is fixed-point with a fraction (q^=0), the length of the resulting character string is p+3, and its value consists of leading blanks (if needed to fill the p+3 character result) followed by a minus if the value is negative, followed by p-q integral digits with no leading zeros (fractions and the value zero have one integral zero digit), followed by a decimal point, followed by q fractional digits.

  • Examples
Parent topic: Arithmetic to Character-String Conversion


Examples

The values in the previous examples could result from converting a Fixed Decimal(5,2) value.

The extra three characters produced for fixed-point values are intended to allow room for a sign, a zero, and a decimal point.

Parent topic: Case 3


Bit-String to Arithmetic Conversion

Bit-string to arithmetic conversion assigns a bit string to any arithmetic data type.

Bit-string to arithmetic conversion produces reasonable results and permits bit strings to be used to hold positive integers. However, because arithmetic operators require arithmetic operands, the BINARY or DECIMAL built-in function should be used to produce an explicit conversion of a bit-string value to a binary or decimal integer value.

The conversion is invalid if the length of the source bit string exceeds N where N is the maximum precision allowed by the implementation for fixed-point binary values. For the maximum precision allowed by Open PL/I, see your Open PL/I User's Guide.

If no target base or scale is given by the context that caused the conversion, fixed binary is supplied by default. If a target precision is not given, the maximum precision allowed for the target base and scale is supplied.

The rightmost bit of the source value is considered to be the units position of a positive binary integer value of precision p, where p is the length of the source bit-string value. The value of that binary integer is then converted to conform to the base, scale, and precision of the target using the normal rules for arithmetic to arithmetic conversion. A null bit-string value converts to zero, as shown in the following examples.

Source | Result
'101'B | 5
"B | 0
'0000'B | 0
Parent topic: Data Type Conversions
Related information
Arithmetic to Arithmetic Conversion


Bit-String to Character-String Conversion

Bit-string to character-string conversion converts a bit-string value to a character-string value of the same length as the bit string. Each bit of the bit string is converted to a 0 or 1 character in the resulting character string. A null bit string is converted to a null character string.

Source | Result
'0'B | '0'
"B | "
'1011'B | '1011'

If the context that caused the conversion gives a target length, the character string is truncated to conform to a shorter target or is padded on the right with blanks to conform to a longer target.

Parent topic: Data Type Conversions


Character-String to Arithmetic Conversion

Character-string to arithmetic conversion converts a character string to any arithmetic data type.

If the context that caused the conversion does not give a target base or scale, fixed or decimal is supplied by default. If it does not supply a target precision, the maximum precision allowed by the implementation for the target base and scale is supplied. For the maximum precision allowed by Open PL/I, see your Open PL/I User's Guide.

If the source character-string value is a null string or if it contains all blanks, the value of the result is zero; otherwise, the source string must contain a valid optionally signed constant surrounded by optional blanks. The constant is converted to conform to the data type of the target using the normal rules for arithmetic to arithmetic conversion.

Source | Result
boxes | 5
 | -7
 | 0

The results in the previous example would be produced by converting a Character(6) source value to a fixed-point integer result value.

Parent topic: Data Type Conversions
Related information
Arithmetic to Arithmetic Conversion


Character-String to Bit-String Conversion

Character-string to bit-string conversion converts a string of 0 and 1 characters to the 0s and 1s of a bit string. A character-string source value that contains any characters other than 0 and 1, including spaces, cannot be converted to a bit-string value; any attempt to perform such a conversion results in a signal of the ERROR condition.

A character-string value is converted to a bit-string value of the same length as the character string. Each character is converted to a 0 or a 1 bit in the resulting bit string. A null character string is converted to a null bit string.

If the context that caused the conversion gives a target length (for example, assignment to a bit-string variable or use of the BIT built-in function with two arguments), the converted bit string is padded on the right with zero bits to conform to the longer target, or the rightmost excess bits are truncated to conform to a shorter target.

Source | Result
" | "B
'010'S | '010'B
' ' | invalid, ERROR signaled
Parent topic: Data Type Conversions


Format Controlled Conversion

Format controlled conversions occur only when a format list is used by a GET or PUT statement to control the conversion of data between the program and an input or output stream, and to control positioning within those streams.

An input conversion occurs when a field of an input line is converted to a value specified by a data format. That value is then assigned to a variable given by the format list of the GET statement. If the data type of the variable differs from the data type of the value produced by the format, an additional conversion results from the assignment.

An output conversion occurs when a value given in the format list of a PUT statement is converted to an output field by a format item.

The following sections describe the five data format items that are used for input and output of data in various formats. These data format items comprise the format specifications that are included in your GET or PUT statements.

  • F-Format
  • E-Format
  • A-Format
  • B-Format
  • P-Format
Parent topic: Data Type Conversions


F-Format

The F-Format is used for fixed-point formats, as shown in the following:

F(w) or F(w,d)

where:

w is an integer constant that specifies the width of the field

d is an integer constant that specifies the number of fractional digits in the field.

  • Input Conversion
  • Output Conversion
Parent topic: Format Controlled Conversion


Input Conversion

For F-Format input conversion, a field of w characters from the input line is converted to a fixed-point decimal value of precision (p,q). If the field contains a decimal point, q is the number of digits following the decimal point; otherwise, q is the value of d or is zero if d is omitted. If the field contains all blanks, the result value is zero, and p is the value of MIN(n,w) where n is the maximum precision allowed by the implementation for fixed-point decimal data. (For the maximum precision allowed by Open PL/I, see your Open PL/I User's Guide.) If the field does not consist entirely of blanks, it must contain an optionally signed fixed-point constant with optional leading and/or trailing blanks. In that case, p is the precision of the constant. If an invalid field is read, the Compiler signals ERROR.

Field | Result | Precision
boxe | 0 | (5,1)
-700 boxes | -70.0 | (3,1)
boxes 0 | 0 | (1,0)
25.6 boxes | 25 | (2,0)
boxes 5E+1 | invalid |
Parent topic: F-Format
Related information
Open PL/I User's Guide


Output Conversion

For F-Format output conversion, an arithmetic or string value from the format list of a PUT statement is converted to a fixed-point decimal value that is then rounded and formatted as a character string of w characters containing a value with d fractional digits.

If d = 0, or if d is omitted, the source value is converted to a fixed-point decimal value with no fractional digits, and the resulting integer value is placed, right-justified, in the field of w blank characters with leading zeros suppressed. (The value zero has one zero digit.) For negative values, the first significant digit is preceded by a minus sign. If the value and its sign cannot fit in w characters, the ERROR condition is signaled.

The following results are produced by an F(4) format.

Value | Result
0 | boxes 0
25 | boxes 25
-8 | boxes -8
13.5 | boxes 14
17.08 | boxes 17
1000 | 1000
-1000 | invalid

If d^= 0, the source value is converted to a fixed-point decimal value with d+1 fractional digits. The value is rounded by adding 5 to the last fractional digit; the last fractional digit is then deleted. The resulting value is placed, right-justified, in a field of w characters with leading integral zero digits suppressed by blanks (fractional values and zero have one integral zero digit). The leading digit is preceded by a minus sign if the value is negative. If the value, its decimal point, and its sign cannot fit in w characters, the ERROR condition is signaled. For the maximum precision allowed by Open PL/I, see your Open PL/I User's Guide.

The following results are produced by an F(5,2) format.

Source | Field
0 | boxes 0.00
-1 | -1.00
.005 | boxes 0.01
.0005 | boxes 0.00
10 | 10.00
-10 | invalid
Parent topic: F-Format
Related information
Open PL/I User's Guide


E-Format

The E-Format is used for floating-point formats, as shown in the following.

E(w)

or

E(w,d)

where:

w is an integer constant that specifies the width of the field

d is an integer constant that specifies the number of fractional digits in the field. If d is omitted, d = O.

  • Input Conversion
  • Output Conversion
Parent topic: Format Controlled Conversion


Input Conversion

For E-Format input conversion, a field of w characters from the input line is converted to a floating-point decimal value of precision p. If the field contains a decimal point and/or an exponent, the value of d is ignored; otherwise, d indicates that the last d digits in the field are fractional digits. If a field contains all blanks, p is MIN(n,w), where n is the maximum precision allowed by the implementation for floating-point decimal values; otherwise, p is the precision of the constant contained within the field. The field must either be all blank or must contain an optionally signed fixed-point or floating-point constant preceded or followed by optional blanks.

The following results are produced by an E(6,1) format.

Field | Result
boxes | 0E0
boxes -1 boxes | -0.1E0
-25E10 | -25E10
boxes 7.41 boxes | 7.41E0
boxes 150 boxes | 15E0
Parent topic: E-Format


Output Conversion

For E-Format output conversion, an arithmetic or string value from a PUT statement's list is converted to a floating-point decimal value and placed, right-justified, in a field of w blanks.

The result field contains a minus sign if the value is negative, followed by the most significant digit of the mantissa, followed by a decimal point, followed by d digits of the mantissa (if d is omitted, it is taken to be p-1), followed by the letter E, followed by the sign of the exponent, followed by n exponent digits, where n is an implementation defined constant. For the maximum precision allowed by Open PL/I, see your Open PL/I User's Guide.

If the value and its sign cannot fit in w characters, the ERROR condition is signaled.

The following results are produced by both forms of the E-format.

Value | Format | Field
0 | E(10,3) | 0.000E+000
-15 | E(10,3) | -1.500E+001
12345678 | E(10,3) | 1.234E+0 07
7.3E-10 | E(10,3) | 7.300E-010
0 | E(14) | boxes 0.000000 E+000
-25 | E(14) | boxes -2.500000E+001

The last two examples assume that the precision of the value to be converted is 7, giving a default value of 6 for d.

Parent topic: E-Format
Related information
Open PL/I User's Guide


A-Format

The A-Format is used for character-string formats, as shown in the following:

A or A(w)

where w is an integer constant that specifies the width of a field.

  • Input Conversion
  • Output Conversion
Parent topic: Format Controlled Conversion


Input Conversion

For A-Format input conversion, w must be specified (unless the A-Format is used to read a variable-length line, as explained below). The result is a character string containing the next w characters from the input stream file.

The A-Format is used without a field width to read a variable-length line. The A-Format reads the content of the current line, starting with the current column and ending with the end of the line, then sets the column position so that the next operation will read a new line.

Parent topic: A-Format


Output Conversion

For A-Format output conversion, an arithmetic or string value given by the PUT statement's format list is converted to a character string using the normal rules for conversion to character string. If w is omitted, it is taken to be the length of the character string. The string is placed, left-justified, in a field of w blanks.

Parent topic: A-Format


B-Format

The B-Format is used for bit-string formats, as shown in the following:

B or B(w)
B1 or B1(w)
B2 or B2(w)
B3 or B3(w)
B4 or B4(w)

where w is an integer constant that specifies the width of a field.

  • Input Conversion
  • Output Conversion
Parent topic: Format Controlled Conversion


Input Conversion

For B-Format input conversion, w must be specified. The next w characters from the input stream are converted to a bit string, just as if they had appeared in a bit-string constant that was followed by B, B1, B2, B3, or B4. For a list of the valid characters and their translation to bits, see Bit-String Data. If the field of w characters contains an invalid character (including blank), the ERROR condition is signaled.

Parent topic: B-Format
Related information
Bit-String Data


Output Conversion

For B-Format output conversion, an arithmetic or string value given by the PUT statement's format list is converted to a bit string using the normal rules for conversion to bit strings. The resulting bit string is then padded on the left with sufficient zero bits to make it a multiple of k bits in length, where kis the 1, 2, 3, or 4 following the B in the format code. The padded bit string is then converted to a character string of length n, where n is the length of the padded string divided by k. (All k bits are converted to one character, as shown in the table in Bit-String Data.) If w is omitted, w is the length of the character string. The character string is right-justified in a field of w blanks. w must be sufficient to hold all of the characters in the string.

The following results are produced by the various forms of the B-Format.

Value | Format | Field
'00'B | B | 00
'1'B | B(4) | boxes 1
"B | B(4) | boxes
'1101'B | B2(2) | 31
'110101'B | B3(2) | 65
'10011101'B | B4(2) | 9D
'10111'B | B2(4) | boxes 113
Parent topic: B-Format
Related information
Bit-String Data


P-Format

The P-Format is used for the input or output of data in a pictured format.

P 'picture'

where picture must be a valid picture as described in the section Picture Data in the chapter Data Types.

  • Input Conversion
  • Output Conversion
Parent topic: Format Controlled Conversion
Related information
Picture Data


Input Conversion

For P-Format input, the next field of w characters is assigned as a pictured value to the variable in the GET statement's format list. The number of characters, w, is the number of characters in the picture, excluding any V characters.

Parent topic: P-Format


Output Conversion

For P-Format output conversion, an arithmetic or string value from the PUT statement's format list is converted to a fixed-point decimal value described by the picture. The decimal value is then edited into an output field of w characters as if an assignment had been made to the pictured field. For a discussion of picture controlled conversion, see the section Conversion to Pictured Data.

Parent topic: P-Format
Related information
Conversion to Pictured Data


Pictured to Arithmetic Conversion

When a pictured value is converted to an arithmetic value, it is first converted to a fixed-point decimal value whose precision is determined by the picture, as described in the section Picture Data in the chapter Data Types.

If the context that caused the conversion specified a different data type, the fixed-point value is converted to another value that conforms to the required data type using the normal rules for arithmetic to arithmetic conversion.

Parent topic: Data Type Conversions
Related information
Picture Data


Pictured to Bit-String Conversion

Pictured data is converted to bit-string data by first converting the pictured value to a fixed-point decimal value and then converting the decimal value to a bit string using the rules given previously in the section Arithmetic to Bit-String Conversion.

Parent topic: Data Type Conversions
Related information
Arithmetic to Bit-String Conversion


Pictured to Character-String Conversion

Pictured data is character-string data and is not converted when used in a context that expects character-string data.

Parent topic: Data Type Conversions


Conversion to Pictured Data

When an arithmetic or string value is converted to a pictured value, it is first converted to a fixed-point decimal value described by the picture, as explained in the section Picture Data in the chapter Data Types. The decimal value is then edited into a character string of length w, where w is the number of characters in the picture, excluding any 'V' characters.

If the fixed-point decimal value described by the picture is not sufficient to retain all digits to the left of the decimal point, the program may be in error and could produce unpredictable results. Excess fractional digits are truncated.

The fixed-point decimal value is formed into the pictured result value under control of the picture edit characters, as described in Picture Data in the chapter Data Types.

If the fixed-point value is zero and the picture does not contain at least one '9' character, the result is a field of w blanks or w asterisks, depending on which zero-suppression picture characters were used.

Negative values cannot be edited unless the picture contains at least one sign picture character. If this rule is violated, the ERROR condition is signaled.

Value | Picture | Result
5.2 | ZZZVZZ | boxes 520
0.01 | ZZZVZZ | boxes 01
0 | ZZZ | boxes
1234 | ZZZZV | 1234
12345 | 99999 | 12345
123 | 99999 | 00123
-105.02 | $**,***V.99 | invalid
-105.02 | $**,***V.99CR | $***105.02CR
-75 | ––––V–– | boxes -7500
75 | ––––V–– | boxes 7500
-20 | -999 | -020
20 | -999 | boxes 020
-275.03 | $$$$$V.99- | boxes $275.03-
25.01 | $$$$$V.99- | boxes $25.01 boxes
-7.5 | $$,$$$V.99DB | boxes $7.50DB
0 | -****V. ** | ********
5 | -****V.** | ****5.00
-75 | -****V.** | -**75.00
.75 | Z.VZZ | boxes 75
.75 | ZV.ZZ | boxes .75
0 | ZZ$ | boxes
Parent topic: Data Type Conversions
Related information
Picture Data


Statements

  • Introduction
  • ALLOCATE
  • Assignment
  • BEGIN
  • CALL
  • CLOSE
  • DECLARE
  • DEFAULT
  • DELAY
  • DELETE
  • DISPLAY
  • DO
  • END
  • ENTRY
  • FORMAT
  • FREE
  • GET
  • GOTO
  • IF
  • %INCLUDE
  • LEAVE
  • %LIST
  • %NOLIST
  • NULL
  • ON
  • OPEN
  • %OPTION
  • %PAGE
  • %POP
  • %PRINT
  • %NOPRINT
  • PROCEDURE
  • %PROCESS
  • *PROCESS
  • %PUSH
  • PUT
  • READ
  • %REPLACE
  • RETURN
  • REVERT
  • REWRITE
  • SELECT
  • SIGNAL
  • %SKIP
  • STOP
  • WRITE
  • %XINCLUDE
Parent topic: Open PL/I Language Reference Manual


Introduction

Each statement definition consists of the following subsections: purpose, syntax, parameters, description (the effect of executing the statement), examples (one or more examples of the statement's usage), and restrictions (any limitations on using the statement). In most cases, the statement is described in the context of the example(s) given in the Example section of the statement definition.

Where one statement has several different forms, each form of the statement is presented. The header lists the main statement with the variation of that statement following it. For example:

The previous example shows the header for the INT pseudovariable assignment, which is one type of assignment statement.

Statements may be prefixed by one or more statement labels. A statement label is a name followed by a colon (:). The name can be specified with a subscript. For example:

DCL_TOP: DECLARE (A,B) FIXED BINARY(31)
...
LL(1): READ FILE(F) INTO(REC(1)); GOTO NAME_X;
LL(2): READ FILE(F) INTO(REC(2)); GOTO NAME_Y;
...
NAME_X: NAME_Y: A = B + 1

Square brackets used in the syntax diagrams indicate optional parts of statements and are not part of statement punctuation. Unless a label prefix is required by a statement, it is not shown in the syntax diagram of the statement.

Parent topic: Statements


ALLOCATE

Purpose:

Allocates a block of storage for the values described by a based or controlled variable. The ALLOCATE statement also permits the assignment of explicit attributes to CONTROLLED variables at the time of allocation.

Syntax:

ALLOCATE var_ref [IN
             (area_ref)] [SET(loc_ref)] [, var_ref [IN ( area_ref)]
             [SET( loc_ref)]]...

For CONTROLLED variables:

ALLOCATE based-or-controlled-alloc[, based-or-controlled-alloc]...;

where based-or-controlled-alloc is:

Parameters:

var_ref
One or more references to a based or controlled nonmember variable or variables.
loc_ref
Specifies the locator variable (for based variables) to which the storage location is assigned if the SET option is chosen.
area_ref
Identifies the area in which the based storage is allocated if the IN option is used.
cvar_ref
A CONTROLLED variable

The dimension-attribute can be specified only for variables that are declared with a dimension-attribute, and it must specify the same number of dimensions as in the declaration.

The CHARACTER, BIT, and AREA attributes can be specified only for variables that are declared with the same attribute.

For more detailed information on BASED and CONTROLLED variables and their use with ALLOCATE statements, see the sections Based Variables and Controlled Variables in the chapter Storage Classes.

Description:

The ALLOCATE statement allocates a block of storage for the values described by a based variable.

The SET option and the IN option are not required in an ALLOCATE statement. If used, they can be specified in either order.

If the SET option is used in conjunction with any var_ref, the address of the allocated storage will be stored in the specified loc_ref for that var_ref. The SET option cannot be used when controlled variables are allocated.

If the SET option is not used, the allocated address will be stored in the locator reference that was assigned with the based variable when it was declared. If no locator reference was assigned with the based variable, an error occurs.

If the IN option is used, or if the SET option specifies an offset variable, the allocation occurs in an area. If the IN option is omitted and the SET option specifies an offset variable, that variable must, in its declaration, have been associated with an area. See the description of the OFFSET attribute in the section OFFSET in the chapter Declarations and Attributes.

Example:

Example 1

DECLARE
   1 A_STRUCT BASED (A_PTR),
      2 A_MEMBER FIXED BIN(15);

DECLARE (A_PTR, B_PTR, C_PTR) POINTER;

DECLARE
   1 B_STRUCT BASED (B_PTR),
      2 B_MEMBER FIXED BIN(15);

DECLARE
   1 C_STRUCT BASED (C_PTR);
      2 C_MEMBER FLOAT BIN(23);

DECLARE (P,Q) POINTER;

ALLOCATE A_STRUCT;
A_STRUCT.A_MEMBER = 5;
ALLOCATE B_STRUCT SET (P), C_STRUCT SET(Q);

In the preceding example, A_STRUCT is allocated, and since no SET option was specified and A_STRUCT was declared as based on A PTR, the allocated address is stored in A_PTR. When B_STRUCT is allocated, the SET option specifies that P is to be assigned the allocated address. When B_STRUCT and C_STRUCT are allocated, the SET options cause the addresses of the allocated storage for them to be assigned to P and Q, respectively.

Example 2

DECLARE (A, B)      AREA;
DECLARE A1          CHAR(20) BASED;
DECLARE A2          CHAR(20) BASED(02);
DECLARE A3          CHAR(20) BASED(03);
DECLARE (01, 02)    OFFSET(A);
DECLARE 03          OFFSET;
DECLARE (P1, P3)    POINTER;

ALLOCATE A1 SET(P1);

ALLOCATE A1 SET(01);

ALLOCATE A2;

ALLOCATE A3 IN(B);
P3 = POINTER(03, B);

In Example 2 above, the first allocation of A1 is not in an area because the locator reference in the SET option specifies a pointer variable. The second allocation of A1 occurs in area A, because the locator in the SET option specifies an offset variable associated with area A. The allocation of A2 again occurs in area A, because A2 is based on offset variable 02, which was associated with area A in its declaration. The IN option causes the allocation of A3 to occur in area B. (Note that, in order to address A3, the POINTER built-in function must be used, because 03 was not declared with an area association).

Restrictions

None.

Parent topic: Statements
Related information
Based Variables
Controlled Variables
OFFSET


Assignment

Purpose

Assigns a value to one or more specified variables.

Syntax

target[,targetn]… =expression[,BY NAME];

Parameters:

target(s)
Either variable references or pseudovariables.
expression
Any valid expression.

Description

The assignment statement evaluates expression and assigns its value to the specified variable or variables.

The assignment statement evaluates the target references and the expression in an unspecified order, converts the expression's value to the data type of each target, and then assigns the converted value to each of the targets in turn (in left-to-right order). For the rules for converting data types, see the chapter Data Type Conversions.

Assignments to a bit-string or character-string target that is shorter than the converted source value cause truncation of the rightmost bits or characters of the source value.

Assignments to nonvarying character-string targets result in padding of the converted source value on the right with sufficient blanks to make it the length of the target.

Assignments to a varying character-string target cause the target to obtain the current length of the newly assigned value.

Assignments to bit-string targets result in padding of the source value on the right with sufficient zero bits to make it the length of the target.

The value of expression can be assigned to more than one target. If the assignment is a structure assignment using the BY NAME option, such a multiple assignment affects only those elementary items that have names in common in all of the structures on both sides of the statement.

The BY NAME option is used in structure assignments to assign to the target structure only the values of those items in the structures specified in expression that have names in common with items contained in the target. The BY NAME option can be used only when the right-hand side contains at least one structure. In such a case, the BY NAME structure assignment is equivalent to a series of scalar or array assignments. There is one such assignment for each scalar or array member of the target structure for which the following condition is true: every structure referenced in the right-hand side has a corresponding scalar or array member whose full structure name (except for the top-level structure name) is identical to the target member's full structure name (except for its top-level structure name). These separate assignments are generated in the order in which the scalar and array members occur in the target structure. For example:

DECLARE 1 STRUC1,
   2 A … ,
   2 B,
      3 M … ,
      3 N … ,
      3 O … ,
   2 C … ,
   2 D … ;

DECLARE 1 STRUC2,
   5 C … ,
   5 D … ,
   5 B,
      10 L … ,
      10 M … ,
      10 O … ;

DECLARE 1 STRUC3,
   2 A … ,
   2 D … ,
   2 C … ,
   2 E,
      3 M … ,
      3 N … ,
      3 O … ,
   2B,
      3 M … ,
      3 N … ;

STRUC1 = STRUC2 + STRUC3, BY NAME;

This assignment is equivalent to the series of assignments:

STRUC1.B.M = STRUC2.B.M + STRUC3.B.M;
STRUC1.C = STRUC2.C + STRUC3.C;
STRUC1.D = STRUC2.D + STRUC3.D;

Examples

A = B+C;
A,B = B*C;   /*A and B will each have the value of B*C */
X(K) = 5;
P->NODE.VALUE = SQRT(X(J));
SUBSTR(S,I,J) = 'ABC';

Restriction

In case of array assignment, each target variable must be an array. The right-hand side can be an array or element expression. If the right-hand side contains an array, its shape must be identical to the shape of the target array.

In case of structure assignment, each target variable must be a structure. The right-hand side can be a structure or element expression. If the right-hand side contains a structure, its shape must be identical to the shape of the target structure.

Because the target and the expression are evaluated in an unspecified order, functions or ON-units called during these evaluations may be affected by possible side effects, such as assignments to subscripts or pointers used in the target reference or freeing the target's storage. Likewise, the storage of the target must not be freed by the execution of a function or ON-unit called during evaluation of the expression.

Programs that depend on the order of evaluation may fail when moved to other implementations of PL/I.

  • Assignment - INT Pseudovariable
  • Assignment - ONCHAR Pseudovariable
  • Assignment - ONSOURCE Pseudovariable
  • Assignment - PAGENO
  • Assignment - POSINT Pseudovariable
  • Assignment - STRING Pseudovariable
  • Assignment - SUBSTR Pseudovariable
  • Assignment - UNSPEC
Parent topic: Statements
Related information
Data Type Conversions


Assignment - INT Pseudovariable

Purpose

Assigns a signed integer value to specified storage.

Syntax

INT(reference[, position[, length]]) =
             expression

Parameters:

reference
A reference to connected storage; reference cannot be an array, structure, or named constant.
position
A positive integer value specifying the position of the first bit in the field.
length
A positive integer value in the range 0 – 32 specifying the length of the field.

Description

The INT pseudovariable assigns a signed integer value to specified storage. expression is converted to Fixed Bin(31). The internal representation of the resulting integer value is then assigned to the storage specified by the arguments to INT.

If position is specified, its minimum value is 1 and its maximum value is the length in bits of the storage specified by reference. If positionis omitted, the default value is 1.

If length is specified, its minimum value is 0 and its maximum value is the length in bits of the storage specified by reference, less the value of position. If length is omitted, the default value is equal to the number of bits from the bit indicated by position to the end of the storage specified by reference.

INT and POSINT are identical pseudovariables, except that POSINT assigns an unsigned integer.

The result of this pseudovariable is dependent on the native byte ordering of the hardware you are using. For this reason, the use of this function may not be portable across different platforms.

Restrictions

None.

Parent topic: Assignment
Related information
POSINT


Assignment - ONCHAR Pseudovariable

Purpose

Sets the current value of the ONCHAR built-in function.

Syntax

ONCHAR() = string

or

ONCHAR = string

The second syntax form can be used only when ONCHAR has been explicitly declared using the BUILTIN attribute.

Parameters

string
An expression that is converted to a character string of length 1.

Description

The ONCHAR pseudovariable is used to replace the invalid character that caused the CONVERSION condition to be raised. This new character is used when the conversion is attempted again.

The ONCHAR pseudovariable is valid only in the context of a CONVERSION ON-unit. In all other cases the ONCHAR pseudovariable is ignored.

Example

DCL I FIXED BIN(15);
ON CONVERSION BEGIN;
   ONCHAR() = '0';
END;

I ='34Z9';
PUT LIST(I);

In the above example, an invalid character, 'Z,' is changed to '0'; therefore, the program will display an integer value of 3409.

Restrictions

None.

Parent topic: Assignment


Assignment - ONSOURCE Pseudovariable

Purpose

Sets the current value of the ONSOURCE built-in function.

Syntax

ONSOURCE() = string

or

ONSOURCE = string

The second syntax form can be used only when ONSOURCE has been explicitly declared using the BUILTIN attribute.

Parameters

string
An expression that is converted to a character string. If the length of the field that caused the CONVERSION condition is greater than the length of string, string is padded with blanks. If the length of the field is less than the length of string, string is truncated to match the field length.

Description

The ONSOURCE pseudovariable is used to replace the invalid string that caused the CONVERSION condition to be raised. This new string is used when the conversion is attempted again.

The ONSOURCE pseudovariable is valid only in the context of a CONVERSION ON-unit. In all other cases, the ONSOURCE pseudovariable is ignored.

Example:

DCL I FIXED BIN(15);
ON CONVERSION BEGIN;
   ONSOURCE() = '0';
END;

I = STRING VALUE;
PUT LIST(I);

If STRING_VALUE contains an invalid character, use of the ONSOURCE pseudovariable in the above example resets STRING_VALUE to zero. Therefore, the program will display an integer value of 0.

Restrictions

None.

Parent topic: Assignment


Assignment - PAGENO

Purpose

Changes the current page number that serves as the value of the PAGENO built-in function.

Syntax

PAGENO(f) = e;

Parameters

f
A reference to a file constant, or to a file variable that has been assigned a file constant value.
e
Any valid expression.

Description

The PAGENO pseudovariable refers to the page number of the referenced print file.

Assignment to the PAGENO pseudovariable modifies the current page number by causing the expression e to be evaluated and converted to a binary integer value of default precision, then assigned as the current page number of the file identified by f. (For details on default precisions, see your Open PL/I User's Guide.)

The file must be open and must describe a STREAM OUTPUT PRINT file.

The PAGENO assignment does not cause any additional pages to be output to the file; it simply changes the current page number that serves as the value of the PAGENO built-in function.

Example

DECLARE F FILE;
   .
   .
   .
PAGENO(F) = 10;

Restrictions

None.

Parent topic: Assignment


Assignment - POSINT Pseudovariable

Purpose

Assigns an integer value to specified storage.

Syntax

POSINT(expression1[,position[,length]]) = expression2

Parameters

expression1
A reference to connected storage; expression1 cannot be an array, structure, or named constant.
position
A positive integer value specifying the position of the first bit in the field.
length
A positive integer value in the range 0 – 32 specifying the length of the field.
expression2
Any expression that evaluates to an integer.

Description

The POSINT pseudovariable assigns an integer value to specified storage. expression2 is converted to Fixed Bin(31). The internal representation of the resulting integer value is then assigned to the storage specified by the arguments to POSINT

If position is specified, its minimum value is 1 and its maximum value is the length in bits of the storage specified by expression1. If position is omitted, the default value is 1.

If length is specified, its minimum value is 0 and its maximum value is the length in bits of the storage specified by expression1, less the value of position. If length is omitted, the default value is equal to the number of bits from the bit indicated by position to the end of the storage specified by expression1.

POSINT and INT are identical pseudovariables, except that INT assigns a signed integer.

The result of this pseudovariable is dependent on the native byte ordering of the hardware you are using. For this reason, the use of this function may not be portable across different platforms.

Restrictions

None.

Parent topic: Assignment
Related information
INT


Assignment - STRING Pseudovariable

Purpose

Assigns the converted value of the expression e to r, as if r were a nonvarying string variable whose length is the total number of characters or bits in the variable identified by r.

Syntax

STRING(r)=e;

Parameters

r
A reference to a string, array, or structure variable that is also suitable for string overlay storage sharing, as described in the section Storage Sharing in the chapter Storage Classes.
e
Any valid expression.

Description

The STRING pseudovariable interprets an appropriate reference as a reference to a fixed-length string.

The STRING assignment assigns the converted value of the expression e to r, as if r were a nonvarying string variable whose length is the total number of characters or bits in the variable identified by r. The STRING assignment can modify an entire aggregate with a single string assignment or assign the aggregate to a pictured variable as if it were a character-string variable.

Example

DECLARE A(5) CHARACTER(1);
   .
   .
   .
STRING(A) = 'ABCDE';

After the previous assignment, A (1) has the value of 'A' , A (2 ) has the value of 'B', and so forth.

Restrictions

None.

Parent topic: Assignment
Related information
Storage Sharing


Assignment - SUBSTR Pseudovariable

Purpose

Modifies only the substring.

Syntax

SUBSTR(r,i,j)=e;
SUBSTR(r,i)=e;

or

SUBSTR(array,i,j)=string_value;

Parameters

r
A reference to a character or bit-string variable.
I
A fixed-point integer-valued expression; the index of the first character or bit in r to change.
j
A fixed-point integer-valued expression; the number of bits or characters to be changed.
e
An expression that can be converted to a character string or bit string.
array
A character or bit string array, as in: susbtr (array(i,j) = string_value;

Description

The SUBSTR pseudovariable refers to a substring of a specific string variable reference.

Assignment to the SUBSTR pseudovariable modifies only the substring portion of r. If r identifies a varying string, the substring assignment does not modify the length component of that string.

If r identifies a varying string, w is the current length of r. If r identifies a nonvarying string, w is the declared length of the string variable. If j is omitted, j is assumed to be w-I+1. The value of e is assigned to the substring according to the assignment rules for nonvarying strings.

Example

DECLARE S CHARACTER(10);
   .
   .
   .
SUBSTR(S,3,4) = 'ABC';

After the assignment, the 3rd character of S is 'A', the 4th is 'B', the 5th is 'C', and the 6th is blank. The other characters of S are unchanged by the assignment.

Restrictions

The following restrictions on I, j, and w must be satisfied or the program may be in error, causing the ERROR condition to be generated if compiled with subscript checking enabled, or unpredictable results if compiled without subscript checking enabled.

1<=I<=w
I+j-1<=w
j>0

The previous restrictions ensure that I is the index of a character or bit within the string, and that a substring of j characters or bits beginning with the Ith character or bit can be accessed without exceeding the length of the string. These formulas also ensure that I is less than or equal to the length of string r if j=0. If j is omitted, the substring begins with the Ith character or bit and extends to the end of the string. No other portion of the target string is affected by the assignment.

The substring described by I and j is assigned the converted value of the expression e as if the substring were a nonvarying string.

Parent topic: Assignment


Assignment - UNSPEC

Purpose

Evaluates and converts an expression to a bit string.

Syntax

UNSPEC(r)=e;

Parameters

r
A reference to any variable except an array or structure.
e
Any valid expression.

Description

The UNSPEC pseudovariable interprets any reference to a scalar variable as a reference to a bit string.

Assignment to the UNSPEC pseudovariable evaluates and converts the expression e to an implementation-defined bit string that is copied into the storage of r (For more information, see your Open PL/I User's Guide.) Subsequent use of r is invalid unless the bit string is a valid value for that variable.

Use of the UNSPEC pseudovariable is discouraged, since it relies heavily on particulars of the PL/I implementation and, as such, may prove to be an obstacle to portability.

Example

UNSPEC©) = '0'B;

After the previous assignment, C contains all zero bits.

Restrictions

None.

Parent topic: Assignment


BEGIN

Purpose

Groups a set of program statements and defines a scope for the names declared within it.

Syntax

BEGIN[ORDER|REORDER];

Description

The BEGIN statement defines a begin block and indicates the start of that block. The block must end with an END statement.

The BEGIN statement is an executable statement that may appear as a THEN clause or as an ELSE clause of an IF statement, as an ON-unit of an ON statement, or as a simple statement anywhere in a procedure.

When the BEGIN statement executes, it activates the begin block. The block activation terminates when the corresponding END statement executes, when a RETURN statement executes (which terminates the enclosing procedure), or when a GOTO statement that references a label external to the block executes.

Since the execution of a BEGIN statement incurs the additional time and space overhead needed to set up a block activation, a simple DO group is preferred for elementary statement bracketing. Note, however, that the DO group cannot serve as an ON-unit, nor does it introduce a new scope for declarations. The BEGIN statement must be used in such instances.

ORDER and REORDER are options sometimes used for optimization in IBM mainframe PL/I programs. They are not needed by Open PL/I; these options are simply parsed and otherwise ignored by Open PL/I.

Example

BEGIN;
   .
   .
   .
END;
ON ERROR
   BEGIN;
      .
      .
      .
   END;

Restrictions

None.

Parent topic: Statements


CALL

Purpose

Transfers control to an entry point of a procedure and optionally passes arguments to the procedure.

Syntax

CALL reference[([argument][,argument]…)];

Parameters

reference
Identifies an entry name, entry variable, or entry-valued function.
argument
An expression

Description

The CALL statement transfers control to an entry point of a procedure and optionally passes arguments to the procedure.

Execution of a CALL statement activates the procedure block identified by a reference, which can be an entry name, entry variable, or entry-valued function. The procedure designated by that entry value is called and passed any arguments given with the reference. The procedure thus activated must not have a RETURNS option and must have the same number of parameters as the reference has arguments, unless the declaration of the ENTRY name includes the OPTIONS(VARIABLE) attribute. A procedure with no argument can be called using a reference with an empty argument list () or no argument list. If the procedure is called with an argument list, each argument in that list is evaluated and, if necessary, converted to the data type of the corresponding parameter. For a discussion of argument passing and parameters, see the section Parameter Storage Class in the chapter Storage Classes.

The order in which arguments and other components of the reference in a CALL statement are evaluated is unspecified.

Example

DECLARE E ENTRY (FIXED BINARY, FIXED BINARY, FLOAT BIN);
DECLARE F ENTRY;
DECLARE G ENTRY;
CALL E(A,B,5+X);
CALL F;
CALL G();

Restrictions

None.

Parent topic: Statements
Related information
Parameter Storage Class


CLOSE

Purpose

Disassociates a file value from the physical file with which it was associated when it was opened.

Syntax

CLOSE FILE(reference)[ENVIRONMENT(LEAVE|REREAD)]
[,FILE(reference)[ENVIRONMENT(LEAVE|REREAD)]]…;

Abbreviation(s): ENV for ENVIRONMENT.

Parameters

reference
Identifies one or more file constants, file variables, or file-valued functions.
ENVIRONMENT
An option used by IBM PL/I programs to control disposition of magnetic tapes after the file is closed. Open PL/I simply parses and otherwise ignores this option.

Description

The CLOSE statement disassociates an Open PL/I file value from the physical file with which it was associated when it was opened.

Execution of a CLOSE statement closes the files identified by the references. Once closed, the files can be reopened and given different file attributes. It can also be used to designate a different operating system file or device.

Closing a closed file has no effect and is not an error.

Upon program termination (including abnormal termination), files not closed will be implicitly closed.

Example

CLOSE FILE(F);
CLOSE FILE(G(K));
CLOSE FILE (L), FILE (M);

Restrictions

None.

Parent topic: Statements


DECLARE

Purpose

Specifies the attributes associated with names.

Syntax

DECLARE declaration[,declaration]…;

Abbreviation(s): DCL for DECLARE.

Parameters

declaration

One or more declarations consisting of an identifier and attributes. The format of each declaration is:

[level]identifier[(bound-pair,…)][attribute…]

or

[level](declaration,…)[(bound-pair,…)] [attribute…]

where:

level specifies the relationship of members of structures

bound-pair specifies the dimensions of arrays

attribute specifies one or more attributes of the identifier

If a level is specified, it must be written first in the declaration.

If a bound-pair is used, it must be in parentheses and must immediately follow the identifier or the parenthetical list of declarations.

The format of the DECLARE statement varies according to the number and nature of the items being declared. For example, the DECLARE statement can list one identifier and optionally specify a level, bound-pair list, and other attributes for that identifier. Or the statement can include, in parentheses, a list of declarations to which the level and all subsequent levels apply. The declarations in the second case can be simple identifiers or can include attributes that are specific to individual identifiers.

Description

The DECLARE statement specifies the attributes associated with names. This statement has five formats:

  • Simple declarations
  • Declarations outside of procedures
  • Multiple declarations
  • Factored declarations
  • Array declarations.

Each of these formats is described separately in the following sections. (for more information on attributes, see the chapter Declarations and Attributes.)

Restrictions

A DECLARE statement cannot be used as a THEN clause or ELSE clause of an IF statement or as the ON-unit of an ON statement. A DECLARE statement cannot be used in a WHEN or OTHERWISE clause of a SELECT statement.

  • DECLARE - Array Format
  • DECLARE - Factored Format
  • DECLARE - Multiple Format
  • DECLARE - Outside of Procedure Format
  • DECLARE - Simple Format
  • DECLARE - Structure Format
Parent topic: Statements
Related information
Declarations and Attributes


DECLARE - Array Format

Purpose

Specifies the dimensions of the array and the bounds of each dimension.

Syntax

DECLARE identifier(bound-pair,…)[attribute…];

Or

DECLARE(declaration,…)(bound-pair,…)[attribute…];

Parameters

Each bound-pair has the format:

[lower-bound:]upper-bound

or

*

Description

The declaration of an array specifies the dimensions of the array and the bounds of each dimension.

One bound-pair is specified for each dimension of the array. The number of elements per dimension is defined by the bound pair. The extent of the array is the product of the numbers of elements in its dimensions. If the lower bound is omitted, the lower bound for that dimension is 1 by default.

The asterisk (*) can be used as the bound pair when arrays are declared as parameters of a procedure. The asterisk causes the indicated parameter subscript to be the same bound pair as the corresponding argument subscript. (If one dimension is specified with an asterisk, then all dimensions must be so specified.)

Example

DECLARE SALARIES(200) FIXED DECIMAL(6,2);

In the previous example, the DECLARE statement declares a 200-element array with the identifier SALARIES. Each element of the array is a fixed-point decimal number with a total of six digits, two of which are fractional.

The identifier in the previous statement can be replaced with a list of declarations, to declare several objects with the same attributes, as shown in the following example:

DECLARE (SALARIES,PAYMENTS) (100) FIXED DECIMAL(6,2);

This declaration declares SALARIES and the array PAYMENTS with the same dimensions and the same type.

DECLARE TOTALS(*,*) FIXED BINARY(15);

This declaration declares TOTALS with two subscripts, each with variable extents. Note that TOTALS must be a parameter.

Restrictions

Up to eight subscripts can be used to reference the elements of an array. For example:

DECLARE TOTALS(*,*) FIXED BINARY(15);

This declaration declares TOTALS with two subscripts, each with variable extents. Note that TOTALS must be a parameter.

Parent topic: DECLARE


DECLARE - Factored Format

Purpose

Allows two or more names that have the same attribute to be combined into a single, factored declaration.

Syntax

DECLARE(identifier[,identifier…])[attribute…];

Parameters

Names that share common attributes can be placed within parentheses and must be separated with commas. The attributes that follow the parenthetical list of names are applied to all of the named identifiers.

You can also specify, within the parentheses, attributes that are unique to specific variable names using the following format:

DECLARE(identifier[attribute]…,identifier[attribute]…)attribute…;

Description

When two or more names have the same attribute, you can combine the declarations into a single, factored declaration. (For more information on attributes, see the chapter Declarations and Attributes.)

Example

DECLARE (COUNTER, RATE, INDEX) FIXED BINARY (6) INITIAL (0);

In this example, the variables COUNTER, RATE, and INDEX share the attributes FIXED BINARY (6) and are given the initial value of zero.

DECLARE (INFILE INPUT RECORD, OUTFILE OUTPUT STREAM) FILE;

In this example, the DECLARE statement declared INFILE as a RECORD INPUT file and OUTFILE as an OUTPUT STREAM file.

Parentheses can be nested, as shown in the following example.

DECLARE ((INFILE INPUT, OUTFILE OUTPUT) RECORD, SYSFILE STREAM) FILE;

In this example, the DECLARE statement declares INFILE as a RECORD INPUT file, OUTFILE as a RECORD OUTPUT file, and SYSFILE as a STREAM INPUT file (STREAM implies INPUT).

Restrictions

None.

Parent topic: DECLARE
Related information
Declarations and Attributes


DECLARE - Multiple Format

Purpose

Defines two or more names and their individual attributes.

Syntax

DECLARE identifier[attribute…][,identifier[attribute…]]…;

Description

Multiple declarations define two or more names and their individual attributes. (for more information on attributes, see the chapter Declarations and Attributes.)

Each set of names and its attributes must be separated from other sets of names and their attributes by a comma. A semicolon must follow the last name.

Example

DECLARE COUNTER FIXED BINARY (6),
   TEXT_STRING CHARACTER (79) VARYING,
   Y FILE;

In this example, the variable COUNTER is declared with the data type attribute FIXED and BINARY (6), the variable TEXT_STRING is declared with the attribute CHARACTER (79) and VARYING, and the variable Y is declared with the data type attribute FILE .

Restrictions

None.

Parent topic: DECLARE
Related information
Declarations and Attributes


DECLARE - Outside of Procedure Format

Purpose

Allows a variable to be declared outside of any procedure and to be visible within all procedures contained in the module.

Syntax

DECLARE identifier[attribute];

Description

A variable can be declared outside of any procedure and will be visible within all procedures contained in the module (for more information, see the section Modules in the chapter Language Concepts). If no storage class is specified, STATIC is supplied by default.

The storage class for declarations outside of procedures cannot be AUTOMATIC.

Example

DECLARE B STATIC FIXED BINARY(31);
   .
   .
   .
SECOND: PROCEDURE;
   DECLARE C FIXED BINARY (31);
      .
      .
      .
THIRD: PROCEDURE;
   DECLARE D FIXED BINARY(31);
      .
      .
      .
END THIRD;
END SECOND;

In this example, variable B can be referenced from both the SECOND and the THIRD procedure.

Restrictions

None.

Parent topic: DECLARE
Related information
Modules


DECLARE - Simple Format

Purpose

Defines one name and describes its attributes.

Syntax

DECLARE identifier[attribute];

Parameters

identifier
A user-supplied name of 1 – 32 characters that is unique within the current block and can consist of any alphanumeric character A through Z, a through z, 0 through 9, @, #, $, and _, but must begin with a letter, dollar sign ($), at sign (@), or underscore (_).
attribute
One or more valid attributes of the name, each of which must be separated by a space, but can appear in any order.

Description

A simple declaration defines one name and describes its attributes. (For more information on attributes, see the chapter Declarations and Attributes.)

Example

DECLARE COUNTER FIXED BINARY (8);
DECLARE TEXT_STRING CHARACTER (60) VARYING BASED (P);

In this example, the variable COUNTER is declared with the data type attribute FIXED and BINARY (8) , and the variable TEXT_STRING is declared with the attribute CHARACTER (60), VARYING, and BASED (P).

Restrictions

None.

Parent topic: DECLARE
Related information
Declarations and Attributes


DECLARE - Structure Format

Purpose

Defines the organization of the structure and the names of members at each level of the structure.

Syntax

DECLARE declaration[,…];

Parameters

Each declaration is:

level identifier[(bound-pair)][(,…bound-pair)][attribute…]

or

level(declaration)[,…(declaration)][(bound-pair)][(,…bound-pair)][attribute…]

Description

The declaration of a structure defines the organization of the structure and the names of members at each level of the structure. Each declaration specifies a member of the structure and must be preceded by a level-number. A single variable can be declared at a particular level, or the level can contain one or more complete declarations, including declarations of arrays or other structures. The major structure name is declared as structure level 1. Minor members must be declared with level-numbers greater than 1.

Example

DECLARE 1 PAYROLL,
   2 NAME,
      3 LAST CHARACTER(70) VARYING,
      3 FIRST CHARACTER(70) VARYING,
   2 SALARY FIXED DECIMAL(6,2);

The following statement declares a structure named PAYROLL, whose last name can be accessed with a qualified reference:

PAYROLL.NAME.LAST = 'JONES';

Since the last and first names have the same attributes, the same structure can be declared as follows:

DECLARE 1 PAYROLL,
   2 NAME,
      3 (LAST,FIRST) CHARACTER(70) VARYING
   2 SALARY FIXED DECIMAL(6,2);

The following example shows a declaration containing the UNION attribute.

DECLARE 1 CONSUMER_INFO,
   .
   .
   .
      3 PHONE_DATA UNION,
            4 PHONE_NUMBER CHARACTER (13),
            4 ELEMENTS,
               5 LEFT_PAREN CHARACTER (1),
               5 AREA_CODE CHARACTER (3),
               5 RIGHT_PAREN CHARACTER (1),
               5 EXCHANGE CHARACTER (3),
               5 HYPHEN CHARACTER (1),
               5 ACTUAL_NUMBER CHARACTER (4),
      3 ADDRESS_DATA,
            .
            .
            .

In this example, the UNION attribute associated with the declaration of PHONE_DATA's immediate members (PHONE_NUMBER and ELEMENTS) share the same storage, so any change to PHONE NUMBER also changes one or more members of ELEMENTS. Conversely, changing a member of ELEMENTS also changes PHONE_NUMBER. However, the UNION attribute does not apply to the members of ADDRESS_DATA, because these members are not immediate members of PHONE_DATA. The members of ADDRESS_DATA occupy separate storage, as is typical for structure members.

Restrictions

None.

Parent topic: DECLARE


DEFAULT

Purpose

Specifies data attribute defaults in cases where attribute sets are incomplete.

Syntax

DEFAULT simple-spec|factored-spec[,simple-spec|factored-spec]…;

where simple-spec is:

RANGE(letter[:letter][,letter[:letter]…)attribute-spec;

or

RANGE(*)[attribute-spec];

where factored-spec is:

(simple-spec|factored-spec[,simple-spec|factored-spec]…)[attribute-spec]

where attribute-spec is:

[attribute-list][VALUE(value-spec[,value-spec]…)

where attribute-list is a list of attributes separated by at least one space.

attribute[ attribute]…

where attribute is:

ALIGNED | AREA | AUTOMATIC | BASED | BINARY | BIT | CHARACTER | CONTROLLED
             | DECIMAL | DEFINED | DIMENSION | ENTRY | EXTERNAL | FILE | FIXED | FLOAT | INITIAL | INTERNAL | LABEL
             | OFFSET | PICTURE | POINTER | STATIC | VARYING | UNALIGNED | VARIABLE

where value-spec is:

CHARACTER(length)|BIT(length)|AREA(size)|numeric-spec

where numeric-spec is:

FIXED|FLOAT|BINARY|DECIMAL[(precision[,scale])]

Abbreviation(s):

  • DEC for DECIMAL
  • DFT for DEFAULT
  • AUTO for AUTOMATIC
  • BIN for BINARY
  • CHAR for CHARACTER
  • CTL for CONTROLLED
  • EXT for EXTERNAL
  • INIT for INITIAL
  • INT for INTERNAL
  • PIC for PICTURE
  • PTR for POINTER
  • VAR for VARYING

Parameters

RANGE (letter:letter)
Specifies that the defaults apply to names with initial letters that either correspond to the two letters specified or to any letters between the two in alphabetic sequence. The letters given in the specification must be in increasing alphabetic order.
RANGE (letter)
Specifies that the defaults apply to names beginning with the letter specified.
RANGE (*)
Specifies that the defaults apply to all names.
VALUE
Establishes default rules for a string length and numeric precision. The only attributes that the VALUE option can influence are length and precision. Other attributes in the option, such as FIXED or DECIMAL, merely indicate which attributes the value is associated with.
Note:

A length or precision specification can be made only in the VALUE clause. They may not be specified with the attributes in attribute-list.

Description

Specifies data attribute defaults in cases where declared attribute sets are incomplete. Any attributes not suppled by the DEFAULT statement for any incomplete explicit, contextual, or implicit declarations are supplied by the Open PL/I default rules. (See the section Compiler-supplied Defaults in the chapter Declarations and Attributes.)

Structure elements are given default attributes according to the name of the element, not the qualified structure element name. The DEFAULT statement cannot be used to declare a structure.

You can use more than one DEFAULT statement within a block. The scope of a DEFAULT statement includes the block in which it occurs and all nested blocks, except those which include another DEFAULT statement with the same range or which are contained in a block having a DEFAULT statement with the same range.

Note the following special case of a DEFAULT statement that is used to restore language-specified defaults in the containing block:

MAIN: PROCEDURE;
DEFAULT RANGE (a:d) FIXED DECIMAL
   VALUE (FIXED DECIMAL(10,2));
DCL CL_INDEX;
   BEGIN;
   DEFAULT RANGE (*);
   DCL C_INTERNAL FIXED DECIMAL;
   END;
END MAIN:

in the previous example, the CL_INDEX in the MAIN routine will have precision and scale of (10,2) in accordance with the DEFAULT statement specification, while the C_INTERNAL variable will have a language default precision (5,0).

Example

DEFAULT RANGE (l:m) FLOAT;
DECLARE (low, medium) BINARY;

/*In this case both variables, low and medium, will be declared as FLOAT BINARY(23).*/

DFT RANGE (*) STATIC;
DECLARE (x,y) FIXED BINARY(15) INITIAL (0);
DECLARE t FLOAT DECIMAL AUTOMATIC;

/* In this example both x and y will have STATIC storage class, while t will have AUTOMATIC storage class due to its explicit storage class declaration. */

DEFAULT RANGE (t) VALUE (CHARACTER(6));
DCL tony CHAR;
DCL tiger CHAR(20);

This statement specifies that all character variables whose name begins with the letter t have the length of 10 characters. Here, tony will have length 6, while tiger will have its explicitly specified length of 20.

Restrictions

None.

Parent topic: Statements
Related information
Compiler-supplied Defaults


DELAY

Purpose

Delays execution for a specified length of time.

Syntax

DELAY(expression)

Parameters

expression is evaluated and converted to a Fixed Binary(31) value.

Description

The DELAY statement delays execution for a length of time equal to the number of milliseconds specified by expression, rounded to the nearest whole second.

Example

/* Both of the following statements suspend /*
/* execution for one second. */

DELAY (10**3);
DELAY (800);
Parent topic: Statements


DELETE

Purpose

Deletes a record from a DIRECT UPDATE or a KEYED SEQUENTIAL UPDATE file.

Syntax

DELETE FILE(reference)[KEY(e)];

Parameters

reference
Identifies a file value that has been opened with the DIRECT UPDATE or KEYED SEQUENTIAL UPDATE attributes.
e
Any valid key expression.

Description

The DELETE statement deletes a record from a DIRECT UPDATE or a KEYED SEQUENTIAL UPDATE file. For both DIRECT UPDATE and KEYED SEQUENTIAL UPDATE files, the key expression is evaluated and converted to the appropriate form. For an indexed (VSAM) file, the key expression is converted to CHARACTER. For a relative record I/O file, it is converted to a positive integer. For indexed (VSAM) files, if the KEY clause is omitted, the last record read is deleted. The KEY clause is required for relative record I/O files. If a record with that key does not exist, the KEY condition is signaled. Return from a KEY condition ON-unit resumes execution with the statement following the DELETE statement. (For more information on record I/O, see the section Input and Output in the chapter Language Concepts.)

Example

DELETE FILE(F) KEY('203XJ42');

Restrictions

None.

Parent topic: Statements
Related information
Input and Output


DISPLAY

Purpose

Displays a message on the user’s screen and optionally requests a response.

Syntax

DISPLAY (expression) [REPLY char-ref]

Parameters

expression
Is converted, where necessary, to a character string. This character string is displayed. It can contain mixed character data. If the expression has the GRAPHIC attribute, it is not converted.
char-ref
Specifies a character reference that receives the user-entered response. The response can contain CHARACTER, GRAPHIC, or mixed data.

Description

The DISPLAY statement displays a message on the user’s screen and optionally requests the user to enter a response to the message.

Example

display ('Communication link established.');

displays the message:

Communication link established.

Restrictions

The REPLY option suspends program execution until the user enters a response.

If GRAPHIC data is entered in the REPLY, it is received as character data that contains mixed data. Such character data can be converted to GRAPHIC data using the GRAPHIC BUILTIN.

Note:

The REPLY parameter is supported when running Open PL/I under the control of Enterprise Server.

Parent topic: Statements


DO

Purpose

Begins a sequence of statements to be executed as a group, possibly to be executed iteratively.

Syntax

DO [while-until-spec]|[index = iteration-spec[,iteration-spec]…];

where while-until-spec is:

WHILE(test-expression)[UNTIL(test-expression)]

or

UNTIL(test-expression)[WHILE(test-expression)]

and where

iteration-spec is:

start[to-by-spec|repeat-spec][while-until-spec]

where

to-by-spec is:

TO finish[BY increment]

or

BY increment[TO finish]

and where repeat-spec is:

REPEAT next

Parameters

test-expression
Any expression that yields a scalar bit string value of length >= 1. If any bit of the value is 1, the test-expression is true; otherwise, it is false. test-expression must be enclosed in parentheses.
index
A reference to a scalar variable.
start, next, finish, and increment
Expressions valid for assignment to index.

Description

The DO statement begins a sequence of statements to be executed in a group. The group ends with the nonexecutable statement END.

A DO-group is executed a variable number of times under the control of its DO statement.

A DO statement cannot be used as an ON-unit, but can appear anywhere within a procedure or BEGIN block, including a THEN or ELSE clause of an IF statement or as an object of a WHEN or OTHERWISE clause.

The following sections explain each DO statement. In all of these discussions, you can assume that the DO-group neither transfers control out of the group nor skips statements within the group when the statements of the group are executed once, twice, n times, and so on. However, any DO-group can contain IF statements, other DO-groups, RETURN, or GOTO statements that alter the order of execution.

Control cannot be transferred initially into a non-simple DO-group except by executing that DO-group's DO statement. Also, if control is transferred out of a non-simple DO-group (other than by a procedure or function call), control cannot generally be transferred back into the group. Violation of these rules causes unpredictable results.

  • Simple DO Statement
  • DO WHILE and DO UNTIL Statements
  • DO REPEAT Statement
  • Iterative DO Statement
  • DO List Statement
  • Complex Iterative DO Statement
Parent topic: Statements


Simple DO Statement

Description

The simple DO statement causes the statements in the DO-group to be executed one time only. Control may be transferred into a simple DO-group by a GOTO statement, but this should be avoided in structured programming.

Example

IF C < D THEN DO;
   PUT LIST ('More data needed');
   GET LIST (VALUE);
   C = C + VALUE;
   END;
Parent topic: DO


DO WHILE and DO UNTIL Statements

Description

The DO WHILE statement causes the statements in the DO-group to be executed in a loop, provided the condition specified in the test expression is satisfied. When the condition is not true, the statements in the DO-group are not executed, and control passes to the statement following the END statement.

Execution of a DO WHILE statement causes the test expression to be evaluated to produce a value b, which must be a bit-string of length greater than or equal to one.

The test expression will be considered true if any of the bits in the string are one, and will be considered false only when all bits are zero.

If b is true, the statements of the group are executed; when the corresponding END statement is executed, control is transferred back to evaluate the test expression again, and the new value of b is tested. If b is false, the statements in the group are not executed, and execution resumes with the statement following the END statement.

The DO UNTIL statement causes a group of statements to execute until a certain condition is satisfied. As long as the condition is false, the group is repeated.

The test-expression is evaluated after each execution of the DO-group. For the DO-group to be repeated, the expression must have a false value. If the expression has a true value, control passes to the next executable statement following the END statement that terminates the DO-group.

The DO UNTIL option resembles the DO WHILE option, in that both options evaluate the status of test expressions; however, the DO WHILE option checks the test expression's value at the beginning of the DO-group, whereas the DO UNTIL statement checks its value at the end of the DO-group. Consequently, a DO-group containing a DO UNTIL statement with no WHILE clause will always be executed at least one time, but a DO-group containing a DO WHILE statement may never be executed.

Example

DO WHILE(EOF = 0);/* an end of file ON-unit sets EOF = 1 */
   READ FILE(F) INTO(REC);
   END;

DO UNTIL(B = 1);
   ARRAY(B) = B;
   B = B - 1;
   END;

DO WHILE(EOF = 0) UNTIL(SUBSTR(REC,1,6) = 'marker');
   READ FILE(F) INTO(REC);
   END;
Parent topic: DO


DO REPEAT Statement

Description

The DO REPEAT statement executes a DO-group repetitively for different values of a variable.

The variable is assigned a start value that is used on the first iteration of the group. The REPEAT expression is evaluated before each subsequent iteration, and its result is assigned to the variable. If a WHILE option is included, the WHILE expression is evaluated before each iteration, including the first. If an UNTIL option is included, the UNTIL expression is evaluated at the end of each iteration. Unless the WHILE or UNTIL option is present, the loop repeats indefinitely.

The DO REPEAT statement causes the start expression to be evaluated and assigned to the index variable. If the WHILE option is given, the test expression is evaluated to produce a value b, which must be a bit-string of length greater than or equal to one. (See the section DO WHILE and DO UNTIL Statements.) If b is false, execution resumes with the statement following the corresponding END statement. If b is true or if a WHILE option is not given, the statements of the group are executed. When control reaches the END statement, if the UNTIL option is given, the test expression is evaluated to produce a value b. If b is true, execution resumes with the statement following the corresponding END statement. Otherwise, the next expression contained in the REPEAT option is evaluated and assigned to the index variable. Any WHILE option is again evaluated; if the value is true or the WHILE is omitted, the group is executed again.

index must be a reference to a variable whose data type makes it a suitable target for assignment of both start and next. Both start and next may be expressions of any data type, provided they both can be assigned to index.

The index reference is not completely reevaluated each time a next value is assigned to it. The original values of any subscripts, pointer qualifiers, or string lengths used in index are used in all subsequent assignments of next values. The next and test expressions are completely reevaluated each time.

The index variable must not be an array or structure, but it can be a reference to an element of an array or a member of a structure.

Example

DECLARE (HEAD,P) POINTER;
DECLARE 1 NODE BASED;
   2 VALUE FLOAT;
   2 NEXT POINTER;
DO P = HEAD REPEAT(P->NODE.NEXT) WHILE(P^=NULL);
   .
   .
   .
END;

The previous DO-group is executed repeatedly for each non-null pointer in the chain of nodes rooted in the pointer HEAD.

Parent topic: DO
Related information
DO WHILE and DO UNTIL Statements


Iterative DO Statement

Description

The iterative DO statement identifies a variable whose value controls the execution of the DO-group and defines the conditions under which the control variable is to be modified and tested.

Execution of an iterative DO causes the start, finish, and increment expressions, as well as the index reference, to be evaluated in an unspecified order. Once evaluated, the finish and increment values are used throughout execution of the group and are not reevaluated. The subscripts, pointers, and so on, in the index reference are also not reevaluated.

The start value is converted, if necessary, to the data type of the index variable, and the converted value is assigned to the index variable.

If a WHILE option is given, the test-expression is evaluated to produce a value b that must be a bit-string of length greater than or equal to one. (See the section DO WHILE and DO UNTIL Statements.) If b is false, execution resumes with the statement following the END statement.

If b is true or a WHILE option is not given, the value of the index variable is compared to the finish value. If the increment is positive or zero, and if the index value is greater than the finish value, execution resumes with the statement following the END statement.

If the increment is negative and the index value is less than the finish value, execution resumes with the statement following the END statement.

If none of the above conditions caused execution of the group to end, the statements of the group are executed. If an UNTIL option is given, the test-expression is evaluated to produce a value b that must be a bit string of length 1. If b is true, execution resumes with the statement following the END statement, the increment value is added to the index variable, and any WHILE test is reevaluated. The new values of b and index are then used to determine if the group should be executed again.

The TO and BY options may be given in any order followed by the WHILE or UNTIL options. Either of the TO or the BY options may be omitted. If the BY option is omitted, a default increment of one is supplied. If the TO option is omitted, index is not compared against limit and the group repeats indefinitely unless stopped by the WHILE or UNTIL option. If both the TO option and the WHILE option are omitted, the DO-group repeats indefinitely. Both the WHILE and UNTIL options may be specified.

Example

DO K = 1 TO 10;
   .
   .  /* EXECUTES 10 TIMES */
   .
END;

DO K = 10 TO 1 BY -1;
   .
   .  /* EXECUTES 10 TIMES */
   .
END;

DO K = 1 TO 1 BY -1;
   .
   .  /* EXECUTES 1 TIME */
   .
END;

DO K = 1 TO 10 WHILE(B<0);
   .
   .
   .
END;

In this last example, the DO-group executes 10 times or until B ? 0, whichever comes first.

DO A(J) = B+1 TO N BY -M WHILE(T);
   .
   .
   .
END;

In the previous example, the DO-group executes [B-N+2/M] times or until T becomes false, whichever comes first. All executions of the DO-group use the same element of A as the index, even if J has been altered by the execution of the group. These executions also all use the initial values of B+1, N and -M. However, T is repeatedly evaluated.

Parent topic: DO
Related information
DO WHILE and DO UNTIL Statements


DO List Statement

Description

A special form of iterative DO statement is one in which none of the TO, BY, or REPEAT options are used, but in which multiple instances of the start expression are specified. In this case the DO-group is executed once for each specified start value.

Example

DO name 'Bob', 'Ann', 'Fred', 'Joan', 'Sue';
      READ FILE(F) KEY(name) INTO(REC);
      CALL SEND_REPT;
      END;
Parent topic: DO


Complex Iterative DO Statement

Description

An iterative DO statement can include multiple instances of the iteration-spec. The DO list statement described above is a simple example of this. When multiple instances of the iteration-spec are specified, the DO-group is first executed as many times as required to satisfy the conditions for the first iteration-spec, then as many times as required for the second iteration-spec, and so on, until all instances of the iteration-spec have been used.

Example

DO J = 1 TO 9 WHILE(B(J) ^-= 'xx'), J = 16 TO 20 BY 2;
      READ FILE(F) INTO(REC);
      B(J) = SUBSTR(REC,6,2);
      END;

If none of the first eight records read by this loop produce B (J) = 'xx', entries B (1) through B (9) , plus B (16) , B (18) , and B (20) , are set by the loop. If, for example, the third record read produces B (J) = 'xx', only entries B (1) through B (3) , plus B (16) , B (18) , and B (20) are set.

Parent topic: DO


END

Purpose

Terminates a block or group headed by the most recent DO, PROCEDURE, SELECT, or BEGIN statement.

Syntax

END [statement_label];

Parameters

statement_label
The label prefix of the corresponding statement.

Description

The END statement terminates a block or group headed by the most recent DO, PROCEDURE, SELECT, or BEGIN statement.

Execution of an END statement that closes a DO-group may cause the group to be repeated, depending on the DO statement that heads the group. (Refer to previous sections of this chapter regarding DO statements.)

Execution of an END statement that closes a PROCEDURE statement is valid only if the PROCEDURE statement does not contain a RETURNS option. Open PL/I or another implementation of PL/I might not diagnose all violations of this requirement. The END statement ends the current block activation and returns control to the statement following the CALL statement that called the procedure.

Execution of an END statement that closes a BEGIN block ends the current block activation and resumes execution of the previous block activation with the statement following the END statement. If the BEGIN block is an ON-unit, control returns to the source of the signal. This return is not possible if the ON-unit has been established for the ERROR condition; an attempt to return to the source of the ERROR condition stops execution of the program and produces a run-time error message.

An END statement can have a label prefix and can be referenced by a GOTO statement, including GOTO statements contained within the DO-group or block that is closed by the END statement.

If a name is given, it must be the same name as occurs in the label prefix of the corresponding DO, BEGIN, or PROCEDURE statement. If the name is not the same, the Compiler issues an error message.

An END statement cannot appear as a THEN, ELSE, WHEN, or OTHERWISE clause or as an ON-unit.

Example

P: PROCEDURE;
   DO K=1 TO 10;
      .
      .
      .
   END;
   END P;

If control passes to an END statement that implicitly closes a repetitive DO group, no further repetitions of the DO group occur. It is equivalent to a branch out of the DO group.

Restrictions

None.

Parent topic: Statements


ENTRY

Purpose

Defines an alternate entry point to a procedure.

Syntax

name:ENTRY[(parameter,…)][RETURNS(returns-descriptor)][EXTERNAL|INTERNAL];

Parameters

name
Identifies the entry point.
parameter
Represents any parameters required by the procedure at this entry point.

Description

The scope of name is external if the ENTRY statement is contained in an external procedure. The scope of name is internal if the ENTRY statement is contained in an internal procedure.

The RETURNS option is required for entry points that are invoked by function references and provides the data type attributes of the function value returned. The RETURNS option is invalid for entry points procedures that are invoked by CALL statements.

The COBOL NOMAP [map-list] option

The FORTRAN NOMAPIN [map-list] option

The TASK NOMAPOUT [map-list] option

The NOEXECOPS option

The OPTION(BYTEADDR) option can be used to ensure the passing of byte addresses, even for items allocated on a bit boundary. When this option is not specified, Open PL/I passes bit addresses for unaligned bit strings. When this option is specified, Open PL/I passes just the address of the first byte of unaligned bit strings.

Only one of EXTERNAL or INTERNAL may be specified and only on top-level procedures, that is, those that are not contained within the scope of any other procedure. If EXTERNAL is given, the procedure will be external to the current file being compiled and can be called by other separately compiled procedures. This is the default. If INTERNAL is given, the procedure can be called only by other procedures within the current compilation. Its name is not made available outside this file.

For more information, see the sections Entry Data in the chapter Data Types and ENTRY in the chapter Declarations and Attributes.

Example

FILE_MANAGER: PROCEDURE;
DECLARE 1 FILE_IOCB BASED (IOCB_PTR),
      .
      .
      .
OPEN: ENTRY (IOCB_PTR, FILE_PTR, OPEN_MODE);
      .
      .
      .
RETURN;
CLOSE: ENTRY(IOCB_PTR);
      .
      .
      .
RETURN;
READ_RECORD: ENTRY (IOCB_PTR, BUFFER_PTR, READ_COUNT);
.
.
.
END;

FILE_MANAGER is a single procedure that has been designed to process three kinds of calls:

  • A call to open a file.
  • A call to read a record from the file.
  • A call to close the file.

A separate entry has been created for each kind of call, each with its own parameters.

Restrictions

ENTRY statements are not allowed in BEGIN blocks, ON-units, or DO groups, except for simple DOs.

Parent topic: Statements
Related information
Entry Data
ENTRY


FORMAT

Purpose

Controls the transmission of data to and from a stream I/O file by a GET or PUT statement.

Syntax

name:FORMAT(format-list);

Parameters

name
An unsubscripted label prefix that is not a statement label and cannot be used by a GOTO statement.
format-list
A list of format specification items.

Description

The FORMAT statement describes the format-specification list to be used by the GET or PUT statement to control the transmission of data to and from a stream I/O file or string. The FORMAT statement has no effect unless it occurs as a consequence of executing the GET or PUT statement.

The format list consists of a list of format items separated by commas. Each format item can be preceded by an optional repetition factor. The repetition factor is either an expression enclosed in parentheses or an integer. The repeat count must be separated from the item by at least one space for all but the parenthetical format list. The value of the repetition factor must be greater than zero and less than 255.

The format items are:

  • (format-list)
  • A(w) or A
  • B(w) or B
  • B1 (w) or B1
  • B2(w) or B2
  • B3(w) or B3
  • B4(w) or B4
  • E(w) or E(vv,d)
  • F(w) or F(w,d)
  • P 'Picture'
  • R (name)
  • COLUMN(n) or COL(n)
  • LINE(n)
  • PAGE
  • SKIP or SKIP(n)
  • TAB or TAB(n)
  • X(n) or X

(format-list) is a parenthetical format list used as a format item; A–P are data format items; and each w, d, or n is an integer constant or an expression whose value k must be 0<=k<=255, unless further restricted by the definition of a particular format item.

Each time control passes to a format list, all format items between the last used format item and the next data format item are evaluated. The next data format item is then used to control the conversion of the data being transmitted to or from the stream file.

If control reaches the end of a format list in a FORMAT statement, it returns to the R-format that transferred control to the FORMAT statement.

If control reaches the end of a format list in a GET or PUT statement, and one or more values are still to be transmitted in the statement's I/O list, control transfers to the beginning of the format list. If there are more format items than values to be transmitted in the statement's I/O list, the extra format items are ignored.

Each format item is described as follows. (Examples of the FORMAT statement are included in the format item descriptions.)

  • The parenthetical format list (format-list)

    When a parenthetical format list is used as a format item, it is used as many times as specified by its repeat count.

    F: FORMAT(F(10,4),2(A(5),E(14,3)),SKIP);

    This example is equivalent to:

    F: FORMAT(F(10,4),A(5),E(14,3),A(5),E(14,3),SKIP);
  • The data format items (A, B, B1, B2, B3, B4, E, F, and P)

    The data format items A, B, B1, B2, B3, B4, E, F, and P control the transmission and conversion of a value to or from a stream file. Each data format causes w characters to be read from an input stream or written to an output stream, where w is the field width given in the format or calculated during the conversion. (For additional information, see the chapter Data Type Conversions.)

    If fewer than w characters remain in an input line, any characters remaining on that line are read and a fresh line is obtained. Additional characters are then read from the fresh line so that a total of w characters are read.

    If fewer than w characters remain in an output line, as many characters as fit are written on that line and a fresh line is begun. Any remaining characters are written onto the line so that a total of w characters are written.

    For a detailed description of how each data format controls conversion of a value, see the section Format Controlled Conversion in the chapter Data Type Conversions .

  • R(label)

    The R(label) format item indicates that format items are to be acquired from the FORMAT statement at the specified label. That is, the R(label) format item transfers control to the format list of the FORMAT statement whose name appears in the R-format.

    The effect of this transfer is as if the format list of the FORMAT statement were called as a subroutine; when the remote format list is exhausted, control returns to the format item following the R-format.

    F: FORMAT(A,X(3));
PUT EDIT(P,Q) (R(F),E(14,3));

    In the previous example, the value of P is transmitted by the A-format contained in the FORMAT statement. Transmission of Q finishes the remote format list by evaluating the X control format and returns to use the E-format to transmit the value of Q. This is equivalent to the following:

    PUT EDIT(P,Q) (A,X(3),E(14,3));
  • COLUMN(n) or COL(n)

    The COLUMN or COL format item puts blanks into an output stream or skips characters of an input stream so that the next character is read or written into column n of a line.

    The COLUMN format is valid for files only.

    If the current output line contains exactly n-1 characters, no output is performed and the next output begins in column n of the current line.

    If the current output line contains less than n-1 characters and n is less than or equal to the line size, sufficient blanks are placed into the current line to cause the next output to begin in column n.

    If the current output line contains less than n-1 characters and n is greater than the line size of this file, the current line is written and a new line is begun. The next output begins in column 1 of the new line.

    If the current output line already contains more than n characters, it is written to the stream file and a new line is begun. If n is greater than the line size of this file, no blanks are placed into the new line; otherwise, n-1 blanks are placed into the new line, causing the next output to begin in column n of the line.

    If the current input line is positioned such that the next character to be read is located in column n, no characters are skipped.

    If the current input line is positioned such that the current column is less than column n and n does not exceed the size of the current line, sufficient characters of the line are skipped so that the next input occurs from column n.

    If the current input line is positioned such that the current column is less than column n, but n exceeds the size of the current line, or if the current column is greater than column n, a fresh line is read. If n exceeds the size of the fresh line, no characters are skipped and the next input occurs from column 1; otherwise, n-1 characters are skipped, causing the next input to occur from column n.

    The value n must be greater than zero.

    Example:

    COL(n) | COLUMN | LINENO | NEW COLUMN | NEW LINENO
    25 | 25 | 1 | 25 | 1
    24 | 25 | 1 | 24 | 2
    26 | 25 | 1 | 26 | 1
    30 | 25 | 1 | 1 | 2

    The previous examples assume a linesize, s, that is 26?s?30.

  • LINE(n)

    The LINE format item sets a print file to a specific line; therefore, it can be used only to control output to a stream file that has been opened with the PRINT attribute and that, consequently, has a page size.

    The LINE format item is valid for print files only; it positions the stream file to a specified line relative to the top of a page.

    If the current line number is less than n and n does not exceed the page size, sufficient lines are written to the output so that the current line is line number n.

    If the current line number is greater than n or if n exceeds the page size, the remainder of the page is filled with blank lines and the ENDPAGE condition is signaled, unless the current line number already exceeds the page size. In that case, a new page is begun without signaling the ENDPAGE condition.

    If n equals the current line and the current column is one, no output occurs. If n equals the current line, but the current column is not one, the ENDPAGE condition is signaled, unless the current line number already exceeds the page size. In that case, a new page is begun without signaling the ENDPAGE condition.

    The value n must be greater than zero.

  • PAGE

    The PAGE format item is used with print files to begin a new page. It can be used only to control output to a stream file that has been opened with the PRINT attribute.

    The PAGE format item positions the stream to the top of a new page and thereby resets the line number to one and increases the page number by one.

  • SKIP(n) or SKIP

    The SKIP format item sets a stream file to a new position relative to the current line. It can be used only with input and output files.

    The SKIP format item applied to an input stream skips the rest of the current input line and n-1 subsequent lines; that is, it skips over n line boundaries.

    A SKIP format applied to an output stream writes the current line and n-1 empty lines; that is, it writes n line boundaries.

    If n is omitted, a value of one is supplied. The value of n must be greater than zero. If the value of n is less than or equal to zero, the SKIP option is ignored.

    If the output stream file has been opened with the PRINT attribute, and if the total number of lines written as a result of the SKIP format item would exceed the page size, the current line is written, followed by sufficient empty lines to fill the page, and the ENDPAGE condition is signaled.

  • TAB(n) or TAB

    The TAB format item sets a print file to a specified tab stop n. It can be used only to control output to a stream file opened with the PRINT attribute.

    The TAB format item causes sufficient blanks to be placed into the current line to position it to the nth tab stop relative to the current column of the line. The relative positions of tabs are implementation-defined (8 characters apart in this implementation). Other implementations may differ and may in fact not place tab stops at constant intervals.

    If the current column is a tab stop, the TAB format item produces sufficient blanks to cause the next output to begin at the next tab stop.

    If n tab stops do not remain on the current line, the current line is written and a new line begun. If the first tab stop is not column 1, sufficient blanks are placed into this line to position it to the first tab stop.

    If TAB format items are used, line size must not be less than the first tab stop. If n is omitted, a default value of one is supplied.

    The value of n must be greater than zero.

    If either of the two preceding rules are violated, a line feed is inserted and data continues to be transmitted.

  • X(n) or X

    The X format item writes n blanks to an output file or skips n positions in an input file. If n is omitted, the default value of n is 1. The X format item is valid with both the FILE and STRING options of the GET EDIT and PUT EDIT statements.

    If fewer than n characters remain in the current line, the remaining characters are skipped on input or written as blanks on output, and additional characters are skipped or written as blanks on the next line so that a total of n characters are written or skipped.

    The value of n must be greater than zero.

Restrictions

None.

Parent topic: Statements
Related information
Data Type Conversions
Format Controlled Conversion


FREE

Purpose

Frees the storage that was allocated for a based or controlled variable identified by reference.

Syntax

FREE reference[IN(area-reference)]…;

Parameters

reference
One or more references to based or controlled variables.
area-reference
A reference to a scalar or subscripted area variable.

Description

The FREE statement frees all blocks of storage that were allocated for based or controlled variables identified by reference.

If the reference is not locator-qualified in the FREE statement, the variable will be implicitly qualified using the locator from the declaration of the based variable. If the declaration had no locator, the FREE statement is in error.

If the allocation to be freed occurred in an area, either the IN clause must be specified or the based variable must be qualified by an offset variable that was associated with an area in its declaration.

The locator qualifier used explicitly or implicitly by the reference must point to a block of storage allocated by execution of an ALLOCATE statement. The results are unpredictable when a FREE statement is used on a based or controlled variable that has not had storage allocated for it by an ALLOCATE statement.

The reference must not be subscripted and must identify a nonmember based or controlled variable whose size, shape, and component data types are the same as were used when the storage was allocated.

When a FREE statement has freed storage allocated for a controlled variable, the next most recent allocation for that variable is made available and subsequent references refer to that allocation.

When a FREE statement has freed storage allocated for a based variable, that block of storage must no longer be referenced. Any pointers that address the block are invalid and must not be used. Violation of this rule produces unpredictable results.

Example

In the following example, the FREE statement frees the storage block allocated by the ALLOCATE statement.

DECLARE TABLE(100) FLOAT BASED;
DECLARE P POINTER;
   .
   .
   .
ALLOCATE TABLE SET(P);
   .
   .
   .
FREE P->TABLE;

In the following example, the FREE statement frees an AREA.

DECLARE ITEM1    BIN BASED(O1);
DECLARE ITEM2    BIN BASED(02);
DECLARE ITEM3    BIN BASED;
DECLARE A        AREA(64);
DECLARE 01       OFFSET(A);
DECLARE 02       OFFSET;
DECLARE 03       OFFSET;

ALLOCATE ITEM1;               /* implicitly in area A;
                                 implicitly set 01 */

ALLOCATE ITEM2 IN(A);         /* explicitly in area A;
                                 implicitly set 02 */

ALLOCATE ITEM3 IN(A) SET(03); /* explicitly in area A;
                                 explicitly set 03 */

FREE ITEM1;                   /* both implicit */

FREE ITEM2 IN(A);             /* IN is required */

FREE 03->ITEM3 IN(A);         /* Locator and IN required */

Restrictions

None.

Parent topic: Statements


GET

Purpose

Gets data from an input stream that is either a stream file or a character-string expression.

Syntax

GET [FILE(f)][SKIP[(n)]][LIST](input-list);

or

GET [FILE(f)][SKIP[(n)]]EDIT(input-list)(format-list)[(input-list)(format-list)]…;

or

GET STRING(s)[LIST](input-list);

or

GET STRING(s) EDIT(input-list)(format-list)[(input-list)(format-list)]…;

If neither LIST nor EDIT is specified, LIST is assumed. In this default case, the

input-list must occur immediately after the word GET.

Parameters

input-list is input-item [,input-item]...

An input-item is either:

variable-reference

or

(input-list iterative-DO)

No comma separates the iterative-DO from its associated input list.

An input list consisting of one iterative-DO has two sets of parentheses, as shown in the following example:

GET LIST (((ARR(I,J) DO I = 1 TO 5) DO J = 1 TO 5))

Each variable reference may be either an array reference, structure reference, or scalar variable reference. Structures with the UNION attribute cannot be used as variables in a GET statement.

The options may appear in any order.

Description

The GET statement gets data from an input stream that is either a stream file or a character-string expression. The input file may be declared either with the STREAM attribute or with the default SYSIN, commonly associated with the user's default input device.

The GET statement has several forms, which include the following options: format-list, FILE, SKIP, STRING, and LIST, or EDIT.

format-list
Specifies a list of format items separated by commas.
FILE
References a file value whose associated file has either been opened as a STREAM input file, or is closed. If closed, the file is opened by the GET statement, as described in the section Stream I/O in the chapter Language Concepts, and given the STREAM and INPUT attributes.
STRING
Specifies that the input item is a character-string expression. The STRING option cannot be used with the FILE or SKIP option.
SKIP
Advances the input file a specified number of lines before processing the input list. The expression in the SKIP option must produce a positive fixed-point integer value n. The SKIP option skips across n line boundaries and resets the current column to one.
LIST
Specifies list-directed input.
EDIT
Specifies edit-directed input.

The FILE, SKIP, and LIST options or the FILE, SKIP, and EDIT options may be given in any order, but a format list is contained in the EDIT option and must immediately follow the input list. If SKIP is given without (n), a value of one is supplied. If FILE is not given, FILE(SYSIN) is supplied by default.

After any SKIP option has been evaluated, the input list is evaluated together with any format list.

The input list is evaluated from left-to-right. Each variable reference may be an array reference, structure reference, or scalar variable reference.

A scalar variable reference causes one value to be transmitted from the input stream and, if EDIT is specified, it uses one data format. An array variable causes n values to be transmitted, where n is the number of elements in the array. If EDIT is specified, it uses n data formats. Values are transmitted to the array in row-major order, as defined in the section Arrays in the chapter Data Types. A structure variable causes all members of the structure and members of all contained substructures to receive a value. The values are transmitted in left-to-right order. If EDIT is specified, each value requires a data format.

Only arithmetic, pictured, and string values can be transmitted by a GET statement. In Open PL/I, the maximum length of a string value transmitted by a GET statement is 256 bits for bit strings or 256 characters for character strings.

A parenthetical input list containing an iterative-DO transmits values under control of the iterative-DO as if it were a DO-group.

The number of lines read by a GET statement is determined by the size of the list, the SKIP option, and any control formats given in the format list. However, unless control items or SKIP forces new lines to be read, transmission begins with the current position of the current line and uses as many lines as are necessary to satisfy the input list.

The maximum length of any line in the input file is limited to the larger of 258 or the value of the LINESIZE option (specified in the OPEN statement) plus 2. If a line in the file is longer than this limit, the GET processing will truncate it with no run-time warning.

Examples

The following example shows a GET statement whose input list consists of one iterative-DO.

GET FILE(F) LIST((A(K),B(K) DO K = 1 TO 10))

Note that this is the same as:

DO K = 1 TO 10;
   GET FILE(F) LIST(A(K),B(K));
END;

The following example shows a GET statement whose parenthetical input-list contains an iterative-DO, which transmits values under control of the iterative- DO as if it were a DO-group.

DECLARE A(10) FLOAT;
DECLARE (B,C) FLOAT;
   .
   .
   .
GET FILE(F) LIST(A,B,C);
GET FILE(F) EDIT(A(K),K,B(K)) (3 E(14,6));
GET FILE(F) LIST(B,(A(K) DO K = 1 TO 5),C);

In this example, the first GET statement transmits 10 values to the array A and then transmits values to B and C in that order. The second GET statement transmits a value to A (K) , transmits a value to K, and then transmits a value to B (K) using the new value of K as a subscript. All three values are transmitted using the same E-format. The third GET statement transmits a value to B, transmits values to A(1),A(2),A(3),A(4), and A(5), and to C in that order.

The following example shows a GET statement with the STRING option.

GET EDIT (NAME.FIRST,NAME.LAST) (A(8),X(3),A(20))
STRING('Deborah M. Park                ');

In this example, the GET statement assigns the character string 'Deborah box ' to the structure NAME.FIRST, skips the middle initial, periods, and space, and assigns the character string 'Park boxes ' to NAME.LAST. Blanks may be used to separate items in list-directed I/O, but for edit-directed I/O they are interpreted differently for character strings. For example, the same example would be interpreted as follows for edit-directed I/O with the format (A (10) , X (3) , A(20)):

For list-directed I/O, the following example:

GET LIST(NAME.FIRST, NAME.LAST)
STRING('Deborah M. Park                ');

would assign 'Deborah' to NAME.FIRST and 'M.' to NAME.LAST.

The following sections contain additional information on the EDIT and LIST options.

  • Edit-Directed Input
  • List-Directed Input
Parent topic: Statements
Related information
Stream I/O
Arrays


Edit-Directed Input

The EDIT option of the GET statement specifies edit-directed input.

The GET EDIT statement uses a format list to control scanning of the input stream and conversion of fields. Each field is first converted under control of a data format and the converted value is then assigned to the corresponding list variable. An additional conversion may occur as part of that assignment.

For a description of each data format conversion, see the section Format Controlled Conversion in the chapter Data Type Conversions, and for a description of format-list evaluation, see the section FORMAT Statement.

GET FILE(F) EDIT(A,B,C) (E(14,3),SKIP,F(10));
GET FILE(F) EDIT(D) (A(10));

In this example, A is assigned the field converted by E (14,3) , a new line is read by SKIP, B is assigned the field converted by F (10) , and C is assigned the next field converted by E (14, 3). The SKIP is not evaluated a second time, because no variables remain in the list. D receives a value from the field converted by A (10) . That field is the 10 characters that immediately follow the second field that was converted by E (14, 3) and assigned to C. Note that the A-Format is used without a field width to read a variable-length line, as discussed in the section A-Format in the chapter Data Type Conversions.

When multiple (input-list) (format-list) pairs are specified, this is equivalent to specifying all the input items consecutively in one list, then all the format items consecutively in one list.

Parent topic: GET
Related information
Format Controlled Conversion
FORMAT Statement
A-Format


List-Directed Input

The LIST option of the GET statement specifies list-directed input.

The GET LIST statement causes each value expected by the input list to be read from the stream file without the use of a format item.

For list-directed input, the stream file must contain a sequence of fields, each of which is followed by a blank or a comma. Excess blanks may occur between fields.

A field whose value is to be assigned to an arithmetic, pictured, or bit-string variable X must contain an optionally signed constant of the same form as could appear on the right side of an assignment statement whose target was X.

A field whose value is to be assigned to a character-string variable begins with the next non-blank character in the stream and ends with the character immediately before the next blank or comma. However, the field can be delimited by single quote characters, and in this case it can contain embedded blanks and commas. If single quote delimiters are used, two adjacent single quotes are interpreted as one single quote in the field's value.

Parent topic: GET


GOTO

Purpose

Transfers control to a labeled statement in the current procedure or in another active procedure.

Syntax

GOTOlabel-reference[OTHERWISE];

Alternate form: GO TO for GOTO

Abbreviation(s): OTHER for OTHERWISE.

Parameters

label-reference
Identifies a label value.

Description

The GOTO statement transfers control to a labeled statement in the current procedure or in another active procedure.

If the label value is a label variable or label-valued function, its value must designate a statement in the current procedure block or in a containing procedure block. The value must also designate a stack frame belonging to a Nock activation of that block.

If the statement to which control is transferred is not within the current block, the current block activation is ended, as are all previous block activations back to the block containing the statement. That block activation is made current, and control is transferred to the statement.

The OTHERWISE option can be used only with a subscripted GOTO statement. A subscripted GOTO statement is defined as a statement directing control to a label that is subscripted.

References to an invalid subscripted label in a GOTO statement are generally considered to be errors. For example, ALABEL ( 1 ) in the second example below, is an undefined member of the array, and ALABEL ( 3 ) is a member that is out of bounds of the array.

However, the OTHERWISE option can be used to cause control to pass to the statement that follows the GOTO statement if the element referred to is not a valid member of the array of label constants.

For a more complete discussion of label values, see the section Label Data in the chapter Data Types.

Example

GOTO L;
GOTO CASE(K);
GO TO L;

The following example contains an array of subscripted label constants called ALABEL. The GOTO statement directs control to the statement that accompanies the subscripted label ALABEL (2) .

ALABEL(0): STATEMENT;
ALABEL(2): STATEMENT;
   X = 2; GOTO ALABEL( X );

The following program sample presents the variable I used as a subscript in a GOTO statement that is subscripted on the third line. If the reference ALABEL ( I ) is not valid, the OTHERWISE option causes control to pass directly to the PUT LIST statement on the fourth line.

NEXT: GET LIST (I);
   GOTO ALABEL (I) OTHERWISE;
   PUT LIST( "INVALID");
   GOTO NEXT;

ALABEL( 1 ):
   .
   .
   .
GOTO NEXT;

ALABEL( 2 ):
   .
   .
   .
GOTO NEXT;

Restrictions

None.

Parent topic: Statements
Related information
Label Data


IF

Purpose

Conditionally executes code based on a test expression.

Syntax

IF test-expression THEN clause[;ELSEclause];

Parameters

test-expression
Any expression that results in a scalar bit string value of length ?1. The test-expression is considered true if any bit in the string is one; the expression is considered false only when all bits are zero.
clause
Either a BEGIN block, DO-group, or statement other than END, PROCEDURE, DECLARE, or FORMAT.

Description

The IF statement evaluates the test-expression. If the expression is true, the THEN clause is executed; otherwise, the ELSE clause, if present, is executed.

When an IF statement is used as a THEN or ELSE clause of another IF statement, any ELSE is always matched with the nearest unmatched preceding THEN.

test-expressions in IF statements may produce bit(n) values, where n>1. In this case, the test expression will be considered true if any of the bits in the string are 1 and false only when all bits are 0.

Example

IF A>B
   THEN IF C>D
      THEN X = 5;
      ELSE X = 10;

In this example, the ELSE clause is associated with IF C > D THEN X = 5 ;

To associate an ELSE with the first THEN, you may write an ELSE or an empty ELSE with the second THEN, as shown in the following examples.

IF A>B;
   IF C>D THEN X=5;
   ELSE;
ELSE X = 10;

or

IF A>B THEN DO;
   IF C>D THEN X=5;
   END;
ELSE X = 10;

Restrictions

None.

Parent topic: Statements


%INCLUDE

Purpose

Incorporates text from other files into the current source file during compilation.

Syntax

%INCLUDE filename[,filename]…;

Parameters

filename
One of the following: a character string, an Open PL/I name, or an Open PL/I name enclosed in parentheses.

The specified filename is used to locate a text file whose content is inserted into the program text in place of the %INCLUDE statement.

Description

The %INCLUDE statement incorporates text from other files into the current source file during compilation.

The %INCLUDE statement can appear in place of a name, constant, or punctuation symbol. The included text may contain additional %INCLUDE statements. %INCLUDE statements normally contain declarations that are common to more than one program module.

Open PL/I searches for a file to satisfy the %INCLUDE statement according to the following rules. (See the section Compiler Options in the chapter Using Open PL/I in your Open PL/I User's Guide).

In the following rules, we use the term "absolute directory path" for a path specifier beginning with a slash (/), such as /tmp/inc, and "relative directory path" for other path specifiers, such as sys/ or .. /.

  • When the %INCLUDE 'filename'; form is used; that is, the quoted filename form:
    • filename may be more than just a simple PL/I identifier. For example, it may contain the commonly used "." (period) character, as in,
      %INCLUDE 'fiiename.pl1.inc';

      It may also contain a directory path, as in,

      %INCLUDE '/pl1/src/inc/filename';
    • If the %INCLUDE statement specifies an absolute directory path, the indicated file will be sought in the specified directory and that directory only.
    • If the %INCLUDE statement does not specify an absolute directory path and the -ipath option is not specified, the indicated file is sought in the current working directory.
    • If the %INCLUDE statement does not specify an absolute directory path and the -ipath option is specified, the indicated file is sought in the directories specified by the -ipath option. These directories are searched in the order in which they are specified. If the file is not found in these directories, a final check is made for it in the current working directory.
    • When the quoted filename form is used, the -isuffix option is never used.
    • When the quoted filename form is used, Open PL/I searches for the file using the character case of each letter of filename exactly as specified. That is, the filename is not converted to uppercase, and no additional searches using other cases are conducted.
  • When the %INCLUDE filename; or the equivalent %INCLUDE (filename), form is used:
    • If the -ipath option is not specified, the indicated file is sought in the current working directory.
    • If the -ipath option is specified, the indicated file is sought in the directories specified by the -ipath option. These directories are searched in the order in which they are specified. If the file is not found in these directories, a final check is made for it in the current working directory.
    • If the -isuffix option is used in the compiler invocation, the character string specified in the -isuffix option is appended to filename before the file search is conducted. For example, if -isuffix.inc is specified, the file to be searched for is filename.inc.

      In this case, with the filename not in quotes, Open PL/I first searches for the file with filename in uppercase characters; that is, FILENAME. If that search fails, Open PL/I tries again using lowercase letters.

Example

%INCLUDE 'FILE1.IN','FILE2.IN','FILE3.IN';

%INCLUDE FILE4,'FILE5',(FILE6),(FILE7);

%INCLUDE 'TOTAL.IN';

In the previous examples, the contents of the files referenced by FILEn, and so on, and by 'TOTAL.IN' will be copied into the current file at compile time.

DECLARE I
%INCLUDE 'FDCL.IN'; STATIC INITIAL (0);

Assuming that the file referenced by ' FDCL.IN ' contains the single line FIXED BINARY (31) , this example is equivalent to the following:

DECLARE I FIXED BINARY (31) STATIC INITIAL (0);

Restrictions

None.

Parent topic: Statements
Related information
Compiler Options


LEAVE

Purpose

Transfers control out of the immediately containing DO-group or the containing DO-group whose label is specified with the statement.

Syntax

LEAVE [label-reference];

Parameters

label-reference
A reference to a label on a DO statement that heads a containing DO-group. The label reference must be a label constant or a subscripted label constant for which the subscript is specified with an integer constant.

Description

The LEAVE statement transfers control out of the immediately containing DO-group or the containing DO-group whose label is specified with the statement.

Execution of a LEAVE statement with no label reference transfers control to the first statement following the END statement that ends the immediately controlling DO-group. If the LEAVE statement has a label, control is passed to the first executable statement after the END statement for the corresponding DO label indicated in the LEAVE statement. In this manner, the LEAVE statement serves as an alternate means to end the execution of a DO-group.

A LEAVE statement with a label reference can cause several nested DO-groups to be ended as control transfers outside the referenced DO-group.

Example

In the following example, the LEAVE statement, shown without a label reference, transfers control directly to the PUT statement if the condition in the IF statement is satisfied.

DO K = 9 TO 91;
   .
   .
   .
   IF COMMAND = 'QUIT' THEN LEAVE;
   .
   .
   .
END;
PUT LIST ('Job finished');

In the next example, the LEAVE statement, shown with a label reference, transfers control to the first statement following the END statement that ends LOOP2:

LOOP2: DO WHILE (MORE);
   .
   .
   .
   LOOP3: DO J = 2 TO 5;
   .
   .
   .
      IF QUAN(J) > 150 THEN LEAVE LOOP2;
   END;     /* Loop 3 */
   .
   .
   .
END;       /* Loop 2 */

Restrictions

The LEAVE statement must be contained within a DO-group and must be in the same block as the DO statement to which it refers.

If the LEAVE statement has a label reference, it must refer to a label on a DO statement that heads a DO-group that contains the LEAVE statement. The LEAVE statement must be in the same block as the labeled DO statement.

The label reference cannot be a label variable or a subscripted label constant.

Parent topic: Statements


%LIST

Purpose

Causes the Compiler to resume placement of listing information to the list file.

Syntax

%LIST;

Description

The %LIST statement causes the Compiler to resume placement of listing information to the list file.

Restrictions

None.

Parent topic: Statements


%NOLIST

Purpose

Stops the placement of listing information to the list file.

Syntax

%NOLIST;

Description

The %NOLIST statement stops the placement of listing information to the list file.

Restrictions

None.

Parent topic: Statements


NULL

Purpose

Placeholder statement.

Syntax

;

Description

The NULL statement performs no action, but is used to provide null THEN or ELSE clauses in IF statements, null ON-units in ON statements, or to allow multiple label prefixes.

Example

A:;
B:;
C: ON ENDPAGE (F);

In this example, the ON statement has a null ON-unit and is preceded by two labeled null statements, effectively giving the ON statement three labels. However, these labels do not compare equally because they designate different statements.

Restrictions

None.

Parent topic: Statements


ON

Purpose

Identifies the action to be taken when a particular condition is raised during execution of a program.

Syntax

ON condition-name ON-unit;

or

ON condition-name SYSTEM;

Parameters

condition-name
ANYCONDITION, AREA, ATTENTION, CONDITION(name), CONVERSION, ENDFILE(f), ENDPAGE(f), ERROR, FINISH, FIXEDOVERFLOW, KEY(f), OVERFLOW, RECORD(f), SIZE, UNDEFINEDFILE(f), UNDERFLOW, USERCONDITION (expression), USERCONDITION(SS$_UNWIND), VAXCONDITION (expression), or ZERODIVIDE.
ON-unit
A BEGIN block or a statement other than PROCEDURE, DO, END, DECLARE, FORMAT, or RETURN, which may include the CALL RESIGNAL statement.
Note:

Abbreviation(s):

  • ATTN for ATTENTION
  • COND for CONDITION
  • CONV for CONVERSION
  • OFL for OVERFLOW
  • UFL for UNDERFLOW
  • UNDF for UNDEFINEDFILE
  • ZDIV for ZERODIVIDE

Description

The ON statement identifies the action to be taken when a particular condition is signaled during execution of a program.

The ON statement is executable and must be executed before the statement that signals the specified condition.

Execution of the ON statement establishes the ON-unit as if it were a procedure that is to be called when the condition is signaled. It does not execute the ON-unit.

If an ON-unit for this condition has already been established in the current block activation, it is replaced by this ON-unit.

During its execution, an ON-unit can do any of the following:

  • Handle the condition, then return control to the point at which the condition was signaled.
  • Resignal the condition and ask Open PL/I to find another ON-unit to handle the condition.
  • Execute a nonlocal GOTO statement, which causes Open PL/I to unwind the call stack.
  • End the program.

An ON-unit remains established until it is replaced by another, until it is reverted by a REVERT statement, or until the block activation in which it was established is ended.

When a condition is signaled, each block activation, beginning with the current block activation, is examined to see if it has an established ON-unit for the condition. If it does not, the previous block activation is examined until an ON-unit for the condition is found. If no ON-unit exists, a default ON-unit is invoked. The default ON-unit for ENDFILE signals the ERROR condition. The default ON-unit for ENDPAGE puts a new page; that is, it is equivalent to executing a PUT PAGE statement. The default ON-unit for FINISH returns control to the point in the program following the location where the signal occurred. The default ON-unit for all the other conditions signal the ERROR condition which, if not handled by an ON-unit for ERROR, causes an error diagnostic to display and then halts the program.

The consequence of this mechanism is that a block may establish its own ON-unit for a condition or may choose to let its caller's ON-unit handle the condition. Any ON-unit established by a block is reverted to when the block returns to its caller or is otherwise terminated.

A signal causes an ON-unit to be called just as if it were a procedure that had no parameters. The block activation resulting from this call is terminated when the ON-unit executes a GOTO or executes its END statement. In the latter case, control returns to the source of the signal.

A GOTO executed within an ON-unit and transferring control out of the ON-unit terminates the block activation of the ON-unit and any block activations back to, but not including, the activation of the block to which control is transferred.

The ON-conditions ENDFILE, ENDPAGE, KEY, and UNDEFINEDFILE are uniquely established for each file control block and are always written with a reference f that must identify a file value. The condition so referenced is effectively qualified by the file control block associated with f. Thus, ENDFILE(g) and ENDFILE(h) are different conditions if g and h identify different file control blocks, but they are the same condition if g and h identify the same file control block.

Just before these conditions are signaled, the value of the ONFILE built-in function is set to the file ID of the file control block for which the condition is being signaled. An ON-unit must not have a label prefix.

Unless otherwise specified, the default ON-units for the following conditions signal the ERROR condition which, if not caught, will print a message and end the execution of the program.

The SYSTEM keyword indicates that instead of executing the code in the ON-unit, a message describing the condition is printed and the ERROR condition is raised.

The ON condition SYSTEM statement can be useful when the user is trying to prevent an infinite loop in the exception handler when, for instance, an ERROR condition is raised in an ERROR ON-unit .

ON ERROR BEGIN;
        ON ERROR SYSTEM;
.
.
.
END;

If in the above example, the code following the ON ERROR SYSTEM statement causes an error exception, the program will be terminated after the message describing the error condition is printed.

The ON conditions are described as follows.

  • ANYCONDITION

    The ANYCONDITION ON-unit handles any signaled condition that cannot be handled by any other ON-unit. The ANYCONDITION ON-unit executes after every other ON-unit established in the block has been examined and found not to match the signaled condition.

  • AREA

    The AREA condition is raised when an attempt is made to allocate a based variable within an area that has too little free storage to accommodate it. The ON-unit for the AREA condition (for example, for a based area) can change the value of the pointer qualifying the area reference to point to a different area, where the allocation will be attempted again; or it can write out the area and reset it to empty.

    The AREA condition is also raised when an area assignment is attempted where the maximum size of the source area exceeds that of the target area.

  • ATTENTION

    The ATTENTION condition is raised when you signal attention at the terminal during program execution. This condition interrupts processing to enter an ATTENTION ON-unit.

    Upon return from an ATTENTION ON-unit, processing resumes at the point in the program immediately after the point at which the interrupt occurred.

  • CONDITION(name)

    The CONDITION condition is signaled by a SIGNAL statement that specifies the appropriate name. The name specified in the SIGNAL statement specifies which CONDITION condition is to be signaled. Note that the name specified in the CONDITION should be a condition name.

    This condition allows the user to establish an ON-unit that will be executed whenever a SIGNAL statement is executed specifying CONDITION and a name that matches the name in the ON statement.

    The following is an example of an ON CONDITION statement:

    ON CONDITION(OVERDRAFT) BEGIN;

   PUT SKIP LIST('ACCOUNT HAD AN OVERDRAFT ON'||DATE())');

END;
.
.
.
IF ACCOUNT_BALANCE < TOTAL WITHDRAWAL THEN SIGNAL CONDITION(OVERDRAFT);
  • CONVERSION

    The CONVERSION condition is signaled whenever an invalid conversion is attempted on character data. This attempt can be made during direct assignment of character data to numeric variable or during an input/output operation. For example, this condition can be raised when a character value that is being converted to a Fixed Binary value contains non-numeric characters, or if a character other than 0 or 1 is being converted to a bit data type.

    All conversions of character data are carried out character-by-character in a left-to-right sequence. The condition is raised for every invalid character.

    When an invalid character is encountered, the invalid character can be replaced within the ON-unit by using the ONSOURCE or ONCHAR pseudovariables.

    Upon return from a CONVERSION ON-unit, the program will retry the conversion if the ONSOURCE or ONCHAR pseudovariable has been used. If the error is not corrected, the ERROR condition is raised and control is passed back to the code that caused the exception to occur.

  • ENDFILE(f)

    The ENDFILE condition is signaled when an attempt is made to read past the end of a file. The end-of-file status of the file control block remains set so that subsequent reads also cause the signal to occur.

    Returning from the ON-unit transfers control to the statement following the GET or READ statement.

  • ENDPAGE(f)

    The ENDPAGE condition is signaled when the line to be written has a line number that is one greater than the page size or when a line number option that specifies a line number less then the current line number is issued for the STREAM OUTPUT PRINT file identified by f.

    If an ON-unit returns without writing a new page, the line number of the file increases indefinitely and the ENDPAGE condition is not signaled by subsequent output. However, if a new page is written by the ON-unit or at any time later, it resets the line number and allows ENDPAGE to be signaled the next time that the line number is one greater than the page size.

    Returning from the ON-unit returns to the point where the signal occurred and any additional output is then written to the stream.

    The default ON-unit puts a new page and returns.

  • ERROR

    The ERROR condition is signaled whenever the implementation detects an error. Just prior to signaling the condition, the value of the ONCODE built-in function is set to an implementation-defined integer value that serves as an error code that indicates which error occurred. (For more information, see your Open PL/I User's Guide.)

    Returning from the ON-unit produces an error message and ends program execution by executing a STOP statement.

    The default ON-unit writes an error message on an implementation-defined error file and executes a STOP statement. (For more information, see your Open PL/I User's Guide.)

    The following is an example of an ON ERROR statement.

    ON ERROR BEGIN;
   PUT SKIP LIST ('AN UNIDENTIFIED ERROR OCCURRED');
END;
  • FINISH

    The FINISH condition handles the following conditions:

    • A STOP statement has been executed.
    • The main procedure has executed a RETURN statement or END statement.
    • The program is exiting because of an error condition not handled by any ON-unit.

    The default ON-unit does nothing and simply returns. If an ON FINISH ON-unit executes a STOP statement, the result is undefined.

  • FIXEDOVERFLOW

    Open PL/I accepts the syntax for the ON FIXEDOVERFLOW statement. However, since there is not adequate hardware support for this condition on the computers supported by Open PL/I, the FIXEDOVERFLOW condition is never raised (unless explicitly raised by the SIGNAL statement).

  • KEY(f)

    The KEY condition is signaled when a READ, REWRITE, or DELETE statement containing a KEY option cannot find a record with the specified key. It is also signaled by a WRITE statement whose KEYFROM option specifies a key of an existing record.

    Just before the condition is signaled, the key value is assigned as the value to be returned by the ONKEY built-in function.

    Returning from the ON-unit resumes execution with the statement following the record I/O statement.

    The following is an example of the ON KEY(f) statement.

    ON KEY(OUTFILE) BEGIN;
   PUT SKIP LIST('INVALID KEY SPECIFIED FOR OUTFILE');
   PUT SKIP LIST('KEY WAS'||ONKEY());
END;
  • OVERFLOW

    The OVERFLOW condition is signaled when the result of an arithmetic operation on a floating-point value exceeds the maximum value that can be represented.

    The maximum values for decimal float values and binary float numbers are described in your Open PL/I User's Guide.

    Returning from the ON-unit produces an error message and ends program execution by executing a STOP statement.

  • RECORD(f)

    The RECORD condition can be raised during a READ, WRITE, or REWRITE operation. This condition is raised when:

    • The record variable is smaller than the record size. This may occur for one of the following reasons.
      • The record is larger than the variable in a READ INTO statement. The remainder of the record is lost.
      • The record length specified for a file with fixed-length records is larger than the variable in a WRITE or REWRITE statement. The remainder of the record is undefined. If the variable is a varying-length string, the RECORD condition is not raised if the SCALARVARYING option is applied to the file.
    • The record variable is larger than the record size. This may occur for one of the following reasons.
      1. The record length specified for a file with fixed-length records is smaller than the variable in a READ INTO statement. The remainder of the variable is undefined. If the variable is a varying-length string, the RECORD condition is not raised if the SCALARVARYING option is applied to the file.
      2. The maximum record length is smaller than the variable in a WRITE or REWRITE statement. The remainder of the variable is lost.
      3. The variable in a WRITE or REWRITE statement indicates a zero length. No transmission occurs. If the variable is a varying-length string, the RECORD condition is not raised if the SCALARVARYING option is applied to the file.
    • The record variable length is either zero or too short to contain the embedded key. This occurs because the variable in a WRITE or REWRITE statement is too short to contain the embedded key.
  • SIZE

    The SIZE is disabled by default. Because Open PL/I does not support condition prefixes, which is the language mechanism by which this behavior is enabled, an alternate method is provided.

    The following Open-PLI runtime call is exposed as built-in subroutine:
    call P$SZCOND(1);  /*  enables the SIZE condition */
call P$SZCOND(0);  /*  disables the SIZE condition */
  • UNDEFINEDFILE(f)

    The UNDEFINEDFILE condition is signaled when an error occurs while attempting to open a file.

    Returning from the ON-unit transfers control to the statement following the OPEN statement.

  • UNDERFLOW

    The UNDERFLOW condition is signaled when the absolute value of the result of an arithmetic operation on a floating-point value is smaller than the minimum value that can be represented. (See your Open PL/I User's Guide.)

    The default ON-unit simply returns. The value resulting from an operation that causes the UNDERFLOW condition is set to zero.

  • USERCONDITION (expression)

    The USERCONDITION (expression) ON-unit handles the condition specified by expression, which must be evaluated to an integer. This ON-unit is invoked in response to execution of the SIGNAL USERCONDITION statement matching the expression value. For more information, see the section SIGNAL Statement.

    The USERCONDITION condition may be signaled using the SIGNAL statement. The value of the expression specified as the USERCONDITION is determined when the ON statement is executed, and not when the condition is signaled. A range of numbers specified in your Open PL/I User's Guide will be allocated for system use.

  • USERCONDITION (SS$_UNWIND)

    The USERCONDITION (SS$_UNWIND) ON-unit handles the condition that is signaled by an UNWIND condition. An UNWIND condition occurs when a nonlocal GOTO forces execution to proceed from a previous block which, in turn, causes frames to be removed from the call stack.

    This is a special case of USERCONDITION (expression). The name SS$_UNWIND is available as a GLOBALREF and must be declared as such.

  • VAXCONDITION (expression)

    The VAXCONDITION (expression) ON-unit is synonymous with the USERCONDITION (expression) ON-unit, and is provided for ease of program conversion. An ON-unit for one can be used to catch a SIGNAL of either.

  • ZERODIVIDE

    The ZERODIVIDE condition is signaled when the divisor in a division operation has a value of zero. The resulting value is undefined.

    Returning from the ON-unit produces an error message and ends program execution by executing a STOP statement.

Restrictions

None.

Parent topic: Statements
Related information
Statement that Handles Exceptional Conditions
SIGNAL Statement


OPEN

Purpose

Causes the file identified by file_id to be opened with the attributes specified. .

Syntax

OPEN file_attribute_list[,file_attribute_list]…;

Parameters

file_attribute_list must include the FILE(file_id) option. It may include any of the following: [TITLE(s)] [LINESIZE(n)] [PAGESIZE(m)] [STREAM] [RECORD] [INPUT] [OUTPUT] [UPDATE] [PRINT] [KEYED] [SEQUENTIAL] [DIRECT], where:
file_id
One or more references to the files to be opened, and bracketed items are file attributes.
s
The name by which the operating system knows the file(s).
n
The maximum number of characters that can be output in a single line for the STREAM file.
m
The maximum number of lines that can be written to the print file without signaling the ENDPAGE condition.

These attributes, including FILE(file_id), may be in any order.

Description

Execution of the OPEN statement causes the file identified by file_id to be opened with the attributes specified in the OPEN statement.

The FILE option must be specified and file_id must be a reference that produces a file value. If the file identified by file_id is already open, the OPEN statement is ignored, even if its attributes disagree with those of the already opened file. The program in which file_id is declared should be compiled with the -defext compiler option. For more information on compiler options, see your Open PL/I User's Guide

The OPEN statement opens each specified file with a specified set of attributes that describe both the file and the file access method. The options and attributes may be specified in any order. If specified, line size n and pagesize m must be expressions that produce positive integer values. The default value of the LINESIZE option is 120, and the default value of the PAGESIZE option is 60.

For indexed or VSAM files, the record size is specified in the ENVIRONMENT options in the declaration of the file.

Example

OPEN FILE(F) STREAM INPUT;
OPEN FILE(F) TITLE ('MASTER_FILE.NEW') UPDATE;
OPEN FILE(G) LINESIZE(80) PAGESIZE(60) STREAM OUTPUT PRINT;

Restrictions

None.

Parent topic: Statements
Related information
Input and Output


%OPTION

%OPTION is accepted without a diagnostic message and ignored for now.
Parent topic: Statements


%PAGE

Purpose

Causes the statement following the %PAGE statement in the program listing to be printed on the first line of the next page.

Syntax

%PAGE;

Description

The %PAGE statement causes the statement following the %PAGE statement in the program listing to be printed on the first line of the next page of the listing file.

Restrictions

None.

Parent topic: Statements


%POP

Purpose

Restores the previously pushed status of %PRINT, %NORPINT, %LIST and %NOLIST from the push-down stack.

Syntax

%POP;

Description

%POP allows you to restore the status of %PRINT, %NOPRINT, %LIST and %NOLIST saved by a %PUSH directive.

%POP is commonly used in included files and macros.

Parent topic: Statements
Related reference
%PRINT
%LIST
%NOPRINT
%NOLIST
%PUSH


%PRINT

%PRINT is a synonym for %LIST.

Parent topic: Statements
Related reference
%LIST


%NOPRINT

%NOPRINT is a synonym for %NOLIST.

Parent topic: Statements
Related reference
%NOLIST


PROCEDURE

Purpose

Defines the start of a procedure block and specifies the parameters of the procedure, if any.

Syntax

name:PROCEDURE[(parameter-list][RETURNS(t)][EXTERNAL|INTERNAL]
             [RECURSIVE][ORDER|REORDER][REDUCIBLE|IRREDUCIBLE]
             [OPTIONS(options-list)];
Note:

Abbreviation(s):

  • PROC for PROCEDURE
  • EXT for EXTERNAL
  • INT for INTERNAL
  • RED for REDUCIBLE
  • IRRED for IRREDUCIBLE

Parameters

parameter-list
One or more parameters, separated by commas, which are expected by the procedure when it is activated. Each parameter specifies the name of a variable declared in the procedure headed by the PROCEDURE statement.
t
A list of data type attributes.
options-list
May be MAIN or VARIABLE.

Options may be specified in any order.

Description

The PROCEDURE statement defines the start of a procedure block and specifies the parameters of the procedure, if any. If the procedure is invoked as a function, the PROCEDURE statement also specifies the data type attributes of the value that the function returns to its point of invocation. Execution of a PROCEDURE statement as a consequence of the normal flow of control from the previous statement has no effect and execution resumes with the statement following the procedure's END statement.

The PROCEDURE statement must have a label prefix that declares the name of the procedure. The label declares the primary entry point. That declaration is established in the block that contains the PROCEDURE statement, and consequently makes the name known in that block and in all contained blocks. The procedure's END statement may contain the name of the procedure so that it can be easily identified as the closing END statement. (See the section END Statement.)

Each name in the parameter-list must be declared within the procedure, must not be a member of a structure, and must not be declared with a storage class attribute.

Every call to a procedure not declared with the OPTIONS(VARIABLE) attribute must be made with an argument list containing the same number of arguments as there are parameters in the parameter list, and each argument must be capable of being passed either by reference or by value to its corresponding parameter.

If a RETURNS option is not specified, the procedure must always be called by a CALL statement, and it must not contain any RETURN statements that specify a return value.

If a RETURNS option is specified, t must be a set of data type attributes that specify a scalar value. All values returned by the procedure are converted to this data type prior to being returned as the function value of the procedure. All RETURN statements must specify a return value and the procedure must not execute its own END statement. All calls to the procedure must result from the evaluation of a function reference.

Only one of EXTERNAL or INTERNAL may be specified and only on top-level procedures, that is, those procedures that are not contained within the scope of any other procedure. If EXTERNAL is given, the procedure will be external to the current file being compiled and can be called by other separately compiled procedures. This is the default. If INTERNAL is given, the procedure can only be called by other procedures within the current compilation. Its name is not made available outside this file.

OPTIONS(MAIN) explicitly defines the routine where execution of the program begins. Only one OPTIONS(MAIN) statement is allowed within a program. In a linked executable program, one and only one procedure must be so identified as the main procedure. See the section Main Procedure in the chapter Language Concepts in your Open PL/I User's Guide.

ORDER and REORDER are options sometimes used for optimization in IBM mainframe PL/I programs. Similarly, REDUCIBLE and IRREDUCIBLE are attributes sometimes used by IBM mainframe PL/I programs. None of these are needed by Open PL/I. These options are simply parsed and otherwise ignored by Open PL/I.

The COBOL NOMAP [map-list] option

The FORTRAN NOMAPIN [map-list] option

The TASK NOMAPOUT [map-list] option

The NOEXECOPS option

The OPTION(BYTEADDR) option can be used to ensure the passing of byte addresses, even for items allocated on a bit boundary. When this option is not specified, Open PL/I passes bit addresses for unaligned bit strings. When this option is specified, Open PL/I passes just the address of the first byte of unaligned bit strings.

The word RECURSIVE may be supplied for purposes of documentation. All Open PL/I procedures are capable of recursive use, provided they follow standard recursive programming requirements, such as not using STATIC data.

Procedures may contain other procedures and BEGIN blocks, as well as any other statements.

Example

P: PROCEDURE(A,B) RETURNS(FIXED BINARY(15));
   DECLARE(A,B) FLOAT;
   DECLARE C FIXED BINARY(15);
   .
   .
   .
   RETURN ©);
   END P;

Q:PROCEDURE(X) RECURSIVE;
   DECLARE X CHARACTER(*);
   .
   .
   .
   CALL Q('HELLO');
   END Q;

Restrictions

None.

Parent topic: Statements
Related information
END Statement
Parameter Storage Class
Main Procedure


%PROCESS

Purpose

Specifies the following set of compiler options: MARGINS, NAMES, OR ('|'), NOT ('^')

Syntax

%PROCESS [compiler-option] ...;

Parameters

MARGINS
Sets the margins within which characters of the source file are interpreted as source code and outside which all characters are ignored by the Compiler. The statement may be inserted anywhere within the source file. The limits apply to all source code following the %PROCESS MARGINS statement until another %PROCESS MARGINS statement is encountered or until the file ends. If tabs are used, each tab is counted as a single character.
Note: The same effect may be achieved for an entire source file by using the -margins compiler option switch. For more information, see your Open PL/I User's Guide.
%PROCESS[MARGINS l,r[,p]];
I
The column number of the leftmost character to be interpreted as source code.
r
The column number of the rightmost character to be interpreted as source code.
p
The column number of the pointer control character. This is currently ignored by the Open PL/I Compiler.
NAMES
Defines the extralingual characters that are allowed in identifiers.
%PROCESS NAMES ('#@$' '#@$')
OR ('|')
Accepts up to seven optional string characters which may be used as the OR symbol.
NOT ('^')
Accepts up to seven optional string characters which may be used as the NOT symbol.

Example

%PROCESS MARGINS (5,55) OR('!|') NOT('^~')
In this example, only the text contained between columns 5 and 55 of the source line will be interpreted by the Compiler; however, the source listing will contain the whole source line. ! and | will be interpreted as the OR symbol and ^ and ~ will be interpreted as the NOT symbol.

Restrictions

None.

Parent topic: Statements


*PROCESS

A synonym for % PROCESS.
Parent topic: Statements
Related reference
%PROCESS


%PUSH

Purpose

Saves the current status of %PRINT, %NORPINT, %LIST and %NOLIST in a push-down stack.

Syntax

%PUSH;

Description

%PUSH allows you to save the current status of %PRINT, %NOPRINT, and %LIST and %NOLIST in a push-down stack on a last-in, first-out basis.

%PUSH is commonly used in included files and macros.

Parent topic: Statements
Related reference
%PRINT
%LIST
%NOPRINT
%NOLIST
%POP


PUT

Purpose

Transfers data from the program to the output stream.

Syntax

PUT[FILE(f)][SKIP[(n)]][LINE(m)][PAGE][list];

or

PUT STRING(r)[list];

Parameters

list
[LIST](output-list)

or

DATA (output-list)

or

EDIT(output-list) (format-list)[(output-list) (format-list)]...

output-list
output-item [,output-item]...
output-item
expression

or

(output-list iterative-DO)

If specified:

n and m
Expressions that produce integer values.
f
A reference that produces a file value.
r
A reference to a character-string variable that is the output stream.

For the definition of a format list, see the section FORMAT Statement.

No comma separates an iterative-DO from its output-list.

An output-list containing one iterative-DO has two sets of parentheses, as shown in the following example:

PUT LIST (((ARR(I,J) DO I = 1 TO 5) DO J = 1 TO 5))

A parenthetical output-list containing an iterative-DO transmits values under control of the iterative-DO, as if it were a DO-group.

If none of LIST, DATA, EDIT is specified, LIST is assumed. In this default case, the output-list must occur immediately after the word PUT.

Description

The PUT statement transfers data from the program to the output stream. The output stream can be either a stream file or a character-string variable.

The PUT statement has several forms that include the following options: format-list, FILE, SKIP, STRING, LINE, PAGE, and LIST, DATA, or EDIT.

The options may be given in any order, but the format-list is part of the EDIT option and must always immediately follow the output-list.

The FILE option must reference a file value whose associated file control block has either been opened as a STREAM OUTPUT file or is closed. If closed, it is opened automatically by the PUT statement and with the attributes STREAM OUTPUT LINESIZE(80). If the FILE option is omitted, FILE(SYSPRINT) is supplied by default. When SYSPRINT is opened, it acquires the PRINT attribute by default. Note that the LINESIZE value for an implicit OPEN differs from that in an explicit OPEN where the LINESIZE option is omitted.

The SKIP option positions the output file at the start of a new line. The expression in the SKIP option must produce a positive integer value n. The option writes n lines, beginning with the current line so that any subsequent output begins on a new line. If SKIP is given without n, a value of one is supplied by default.

The STRING option specifies that the output item is a referenced character-string variable rather than a file. The STRING option cannot be used with FILE, LINE, PAGE, or SKIP. The target of the PUT STRING operation must have sufficient space allocated to store the entire result of the operation, including any spaces, semicolons, and quotation marks added by the PUT LIST or PUT DATA processing. If the target does not have enough space, the ERROR condition is signaled.

The LINE option positions the stream file to a specific line relative to the top of the page. Subsequent output begins on that line. The LINE option is evaluated as if it were a LINE format; see the section LINE(n). If n is less than the current line position, the ENDPAGE condition is signaled.

If both SKIP and LINE are specified, LINE is evaluated first.

The PAGE option positions the output file at the start of a new page so that subsequent output begins on line one of that page. If the PAGE and LINE options are both given, PAGE is evaluated first.

SKIP, PAGE, and LINE are always evaluated prior to writing any output produced by the PUT statement, regardless of their position in the PUT statement. If the output from a statement does not share its last line with subsequent output, two statements must be used. (See the section Examples.)

The output-list is evaluated from left-to-right. Each expression may be either an array reference, structure reference, or scalar-valued expression. Structures with the UNION attribute cannot be used as variables in a PUT statement.

A scalar value causes one value to be transmitted to the output stream and, if EDIT is specified, uses one data format. An array variable causes n values to be transmitted, where n is the number of elements in the array. If EDIT is specified, it uses n data formats. Values are transmitted from the array in row-major order, as defined in the section Arrays in the chapter Data Types. A structure variable causes all members of the structure and members of all contained substructures to transmit a value. The values are transmitted in left-to-right order. If EDIT is specified, each value requires a data format.

Only arithmetic, pictured, or string values can be transmitted by a PUT statement.

The number of lines written by a PUT statement is determined by the number of values specified by the output-list, as well as by the SKIP, LINE, and PAGE options, and any control formats given in the format list. However, unless control items or options force new lines to be written, transmission begins with the current position of the current line and uses as many lines as are necessary to satisfy the output list.

  • List-Directed Output
  • Data-Directed Output
Parent topic: Statements
Related information
FORMAT Statement
LINE(n)
Arrays


List-Directed Output

The LIST option specifies list-directed output.

The PUT LIST statement causes each value specified by the output list to be written to the stream file without the use of a format item. Each value to be output is converted to a character-string value using the normal rules for converting to a character string given in the chapter Data Type Conversions.

If the original output value is a bit string, the resulting character string is enclosed in quotation marks and a B is appended to its right end.

Parent topic: PUT
Related information
Data Type Conversions


Data-Directed Output

The DATA option specifies data-directed output.

The PUT DATA statement is equivalent to the PUT LIST statement, with the following differences:

  • An output-list item can be a scalar, element, array, or structure reference, not an expression. The reference may contain structure qualifiers and subscripts, but may not be locator qualified.
  • The dataname of each reference is written along with the value. This is done in the form dataname=value. If the value is an array, each element is written with its array name and the actual value of its subscript(s). If the value is a structure, each elementary member is written with its dataname fully qualified and with all subscripts at the end.
  • The dataname=value combinations are separated by spaces except when writing to a PRINT file, when each such item will be aligned on a TAB stop. A semicolon is written following the last value.
  • The data values are written, in most cases, just as they are in PUT LIST. However, for character data, the data value is always enclosed in quotes when it is written out.
  • A based variable in the output-list must be declared with an explicit pointer.
  • Edit-Directed Output
Parent topic: PUT


Edit-Directed Output

The EDIT option specifies edit-directed output.

The PUT EDIT statement uses a format list to control the position of the output stream and the conversion of the values specified by the output list. Each output value is converted under control of a data format, and the resulting characters are written to the output stream.

When multiple (output-list) (format-list) pairs are specified, this is equivalent to specifying all the output items consecutively in one list, then all the format items consecutively in one list.

For a description of each data format conversion, see the section Format Controlled Conversion in the chapter Data Type Conversions, and for a description of format list evaluation, see the section FORMAT Statement.

PUT FILE(F) EDIT(A,B,C) (E(14,3),SKIP,F(10));
PUT FILE(F) EDIT(D) (A);

In this example, A is converted under control of E (14,3), and 14 characters are written to the output stream, a new line is begun by SKIP, B is converted under control of F (10), and 10 characters are written to the output stream, C is then converted under control of E (14,3) and written to the output stream. The SKIP is not evaluated a second time because no more values remain to be output from the output list. The second statement converts D to a character string whose length is determined by the normal rules for conversion to character string. For further information on conversions, see the chapter Data Type Conversions. The resulting value is written to the same line as C, unless C happened to just fill a line. In that case, D begins on the next line.

If the original output value is a character string or a pictured value, and the file control block does not have the PRINT attribute, each contained quotation mark is replaced by two quotation marks and the entire string is enclosed by quotation marks.

The possibly modified character string is placed into the output stream followed by a single blank. If the file control block has the PRINT attribute and LINESIZE 20, for example, the value is followed by sufficient blanks to ensure that the next output begins in the next tab stop. At least one blank always separates fields.

If a character string does not fit on a line, a new line is begun and the string is written on that line and subsequent lines, if necessary.

PUT FILE(F) LIST(52,1.07E+5);
PUT FILE(F) LIST('ABCX');

would produce (assuming a line size of 20): boxes

In this example, the value 52 converts to boxes 52 and is output followed by a single blank, 1.07E+5 converts to box 1.07E+05 and is followed by a single blank, and 'ABCX ' converts to ABCX. The resulting value does not fit on a line of size 20, so it is written on the next line followed by a blank. If the file control block had the PRINT attribute, the last value would be output without quotation marks and each value would be followed by sufficient blanks to ensure that the next value would begin at the next tab stop.

If the PRINT attribute does not exist, the output would look like this:

Parent topic: Data-Directed Output
Related information
Format Controlled Conversion
FORMAT Statement
Data Type Conversions


READ

Purpose

Reads a record from an input or update file.

Syntax

READ FILE(f)[INTO(v) [KEY(k)|KEYTO(r)]|
           SET(p)[KEY(k)|KEYTO(r)]
           IGNORE(expr)];

Parameters

f
A reference to the file from which the record is to be read.
v
A reference to the variable to which the record contents are to be assigned.
p
A pointer variable.
expression
Is evaluated and converted to an integer value.
k
An expression that specifies the key to be used to locate the record to be read.
r
The designated variable to which the key of the record being read is to be assigned.

The FILE, INTO, KEYTO, and KEY specifiers may be written in any order. KEYTO must not be specified if KEY is specified. A READ statement without an INTO, SET, or IGNORE option is equivalent to a READ with an IGNORE(1).

Description

The READ statement reads a record from a record file.

The FILE option must contain a reference f that produces a file value. The file identified by f must either have been previously opened with RECORD INPUT or UPDATE, or must be closed. If closed, it is opened by the READ statement and given the INPUT RECORD SEQUENTIAL attributes.

If the file has been opened with the KEYED SEQUENTIAL attributes, the KEY option may be specified. If the file has been opened with the DIRECT attribute, the KEY option must be specified.

The READ statement with INTO option copies the data record into the referenced variable. The SET option specifies a pointer variable that is set to point to the location in a buffer into which data has been moved during the READ operation. The storage for this buffer is handled by the run-time system.

In the following example, the value of the pointer value P is set to the location of F in the buffer of the next sequential record:

READ FILE (F) SET (P) ;

The IGNORE option can be used in a READ statement for any indexed SEQUENTIAL INPUT or SEQUENTIAL UPDATE file.

expression in the IGNORE option is evaluated and converted to an integer value, n. If n is greater than zero, n records are ignored. A subsequent READ statement for the file will access the (n+1)th record. If n is less than 1, the READ statement has no effect.

The IGNORE option cannot be used with non-indexed files.

The following example specifies that the next five records in the file are to be ignored:

READ FILE (IN) IGNORE (5 ) ;

If specified for non-indexed files, the KEY option must be an expression whose value can be converted to a positive integer. Its value must be a key value of a record in the keyed file identified by the file associated with f. An attempt to read the file using a key value that does not identify a record in f results in a signal of the KEY condition. For indexed (VSAM) files, the key value is treated as a Character, and is converted to Character if necessary.

If specified, the KEYTO option must reference a character string variable whose maximum length is implementation-defined. (For details, see your Open PL/I User's Guide.) The file must be a keyed file. The key value of the record is assigned to r.

If a KEY option is given, the file must have been opened previously with the KEYED attribute. The presence of the KEY option does not cause implicit opening to produce the KEYED attribute.

Regardless of how the file was opened, it must have either the INPUT or UPDATE attribute.

If a KEY option is given, the file is positioned to read the record identified by the key value; otherwise, it is positioned to read the current record of a SEQUENTIAL file. After reading the record, the current position is advanced to the next record if the file is SEQUENTIAL. The current position for a DIRECT file is not changed.

Open PL/I allows the use of READ with a stream file, as long as the READ statement specifies a scalar character varying string variable in its INTO option. The READ statement reads the next complete input line and assigns it to the character varying string specified by the INTO option. The string does not include any new-line character.

Example

READ FILE(F) INTO(X);
READ FILE(G) INTO(Y) KEY(N+1);
READ FILE (TOWN_FILE) INTO (TOWN_BUFFER) KEYTO (SAVE_ADDRESS);

In the last example, the READ statement reads the next sequential record in the file TOWN_FILE into the variable TOWN_BUFFER. The key associated with the record that is read is copied into the variable SAVE_ADDRESS.

Restrictions

None.

Parent topic: Statements


%REPLACE

Purpose

Specifies that an identifier is a constant of a given value.

Syntax

%REPLACE name BY constant;

Description

The %REPLACE statement specifies that an identifier is a constant of a given value.

Beginning at the point at which the %REPLACE statement is encountered, each occurrence of name that follows the %REPLACE statement is replaced by the constant until the end of compilation.

The %REPLACE statement is normally used to supply the sizes of tables or to give names to special constants whose meaning would not otherwise be obvious.

Example

%REPLACE TRUE BY '1'B;
%REPLACE TABLE_SIZE BY 400;
%REPLACE MOTOR_POOL BY 5;
%REPLACE X BY -3.0E0;
DECLARE X(TABLE_SIZE) FIXED STATIC;
DO K = 1 TO TABLE_SIZE;
IF DEPARTMENT_NUMBER = MOTOR_POOL
   THEN DO;
      .
      .
      .

Restrictions

The %REPLACE statement operates on the program text without regard to the meaning of the text, which means that a replaced name can accidentally be a keyword such as STOP or READ. in this case, an "unrecognizable statement" error message is issued by the Compiler when it reads a subsequent STOP or READ statement. An error statement is also issued by the Compiler when an attempt is made to replace one name by two different constants.

The %REPLACE statement substitutes all subsequent occurrences of the name without regard to the block structure of the module.

Parent topic: Statements
Related information
Procedure Blocks


RETURN

Purpose

Ends execution of the current procedure and returns control to the calling block.

Syntax

RETURN[(result)];

Parameters

result
Must be an expression whose value can be converted to the data type specified in the RETURNS option of the containing procedure.

Description

The RETURN statement ends execution of the current procedure and returns control to the calling block.

If a result is specified, the containing procedure must have a RETURNS option and must have been called by a function reference. In this case, the result expression is evaluated, converted to the data type specified by the RETURNS option of the PROCEDURE statement, and returned as the function value.

If a result is not specified, the containing procedure must not have a RETURNS option and can be called only by a CALL statement.

A RETURN statement executed in a BEGIN block returns from the activation of the containing procedure block and terminates any BEGIN blocks that contain the RETURN statement.

Example

RETURN;
RETURN(A+B);
RETURN('STRING RESULT');
RETURN('1'B);

Restrictions

A BEGIN block that is an ON-unit must not contain a RETURN statement.

Parent topic: Statements


REVERT

Purpose

Cancels an ON-unit established for a specified condition in the current block.

Syntax

REVERT condition-name;

Parameters

condition-name
The keyword name associated with the condition for which the ON-unit is to be reverted, namely: ANYCONDITION, AREA, ATTENTION, CONDITION(name), CONVERSION, ENDFILE(f), ENDPAGE(f), ERROR, FINISH, FIXEDOVERFLOW, KEY(f), OVERFLOW, RECORD(f), UNDEFINEDFILE, UNDERFLOW, USERCONDITION(expression), USERCONDITION(SS$_UNWIND), VAXCONDITION(expression), or ZERODIVIDE.
Note:

Abbreviation(s):

  • ATTN for ATTENTION
  • COND for CONDITION
  • CONV for CONVERSION
  • OFL for OVERFLOW
  • UFL for UNDERFLOW
  • UNDF for UNDEFINEDFILE
  • ZDIV for ZERODIVIDE

Description

The REVERT statement cancels an ON-unit established for a specified condition in the current block. If no ON-unit for the condition is established in the current block activation, the REVERT statement has no effect.

The reference given in an I/O condition name must produce a file value. The I/O condition is qualified by the file I/O associated with f. This means that in the example below, REVERT ENDPAGE (F) ; and REVERT ENDPAGE (G); revert to different ON-units if F and G designate different files; otherwise, they revert to the same ON-unit.

Example

REVERT ERROR;
REVERT ENDPAGE(F);
REVERT ENDPAGE(G);

Restrictions

None.

Parent topic: Statements


REWRITE

Purpose

Replaces a record in a DIRECT UPDATE, SEQUENTIAL UPDATE, or a KEYED SEQUENTIAL UPDATE file.

Syntax

REWRITE FILE(f)[FROM(v)][KEY(k)];

Parameters

f
A reference to the file containing the record to be replaced.
v
A reference to the variable whose value is to be used to rewrite the specified record.
k
An expression specifying the key to be used to locate the record to be rewritten.

Description

The REWRITE statement replaces a record in an UPDATE file. For SEQUENTIAL UPDATE files, the REWRITE statement specifies that the last record read form the file is to be rewritten. Note that, in this case, a record must be read before it can be rewritten. For DIRECT UPDATE files, and for KEYED SEQUENTIAL UPDATE files associated with indexed (VSAM) files, any record can be rewritten, whether or not it has first been read.

Because the set of file attributes that would be supplied as a result of an implicit file opening caused by a REWRITE statement does not include DIRECT, the FILE specifier must reference a file value whose associated file has been opened with the DIRECT and UPDATE attributes.

The KEY option is required for DIRECT non-indexed files and not allowed for SEQUENTIAL files.

The FROM specifier must contain a variable reference. The storage of that variable is copied as the new record. The FROM specifier must not contain a variable that is an unaligned bit string or a structure that consists entirely of unaligned bit strings or a structure with the UNION attribute.

If the last record read was read by a READ statement with the INTO option, a REWRITE statement without the FROM option has no effect. If the last record read was read by a READ statement with the SET option, a REWRITE without the FROM option causes the data record to be updated with the current contents of the buffer indicated by the pointer variable specified by the SET option of the READ.

The FILE, FROM, and KEY specifiers may be given in any order.

Example

REWRITE FILE(F) FROM(X) KEY(N+1);
REWRITE FILE(F) FROM(Y(K)) KEY('ABC');

Restrictions

None.

Parent topic: Statements


SELECT

Purpose

Heads a SELECT-group, which provides a multi-path conditional branch.

Syntax

SELECT[(select-expression)];
   WHEN(e?1[,e?2[,e?3[…]]]) action_1;
   WHEN(e?4[,e?5[,e?6[…]]]) action_2;
   .
   .
   .
   OTHERWISE action_m;
END;

Abbreviation(s): OTHER for OTHERWISE.

Parameters

select-expression and e?1, e?2... are all valid expressions, and each action is a single or compound statement, a DO-group, a SELECT-group, an ON-unit, or a BEGIN block.

Description

The SELECT statement heads a SELECT-group, which provides a multi-path conditional branch. The SELECT statement tests the expressions in the SELECT-group and performs a particular action if the result of any test is true.

SELECT;
   WHEN (condition B)
      SELECT;
            WHEN (condition B1) statement_1;
            WHEN (condition B2) statement_2;
      END;
   WHEN (condition C)
      SELECT;
            WHEN (condition C1) statement_3;
            WHEN (condition C2) statement_4;
            OTHERWISE statement_5;
      END;
   OTHERWISE statement_6;
END;

statement_1 is executed when both B and B1 are true conditions and statement_2 is executed when both B and B2 are true conditions. If B is true, but B1 and B2 are false, nothing happens. If condition B is false, the C conditions are checked. statement_5 is executed when condition B is false, condition C is true, and conditions C1 and C2 are false. statement_6 is executed when condition B and condition C are both false.

When control reaches a SELECT statement with a select-expression present, the select-expression is evaluated and its value saved. Next, the expressions in the WHEN clauses are evaluated in the order in which they appear, and each value is compared with the value of select-expression. If a value is found that is equal to the value of select-expression, the action following the corresponding WHEN clause is performed, and no further WHEN clause expressions are evaluated. If none of the expressions in the WHEN clauses is equal to the select-expression, the action specified after the OTHERWISE clause, if present, is executed unconditionally. If there is no OTHERWISE clause and there is no matching WHEN value, the ERROR condition is raised.

Note:

OTHERWISE may be abbreviated to OTHER.

After the action has been performed, control passes to the first executable statement following the SELECT-group, unless the normal flow is changed by the specified action.

If the select-expression is omitted, each WHEN clause expression is evaluated and converted, if necessary, to a bit string. The action after the WHEN clause is performed if any bit in the resulting bit string is a '1'B.

If a SELECT-group does not contain any WHEN clauses, the action in the OTHERWISE clause is executed unconditionally. If the OTHERWISE clause is omitted, and execution of the SELECT-group does not result in the selection of a WHEN clause, the ERROR condition is raised.

In nested SELECT statements, conditions are checked from top to bottom. If two conditions are true, only the first course of action is taken.

You must close each group in nested SELECT-groups with an END statement.

Example

SELECT;
   WHEN (9>B, C,D, FOUND) CALL PROC_1;
   WHEN (A=B) CALL PROC_2;
   OTHERWISE CALL PROC_3;
END;

In the previous example, select-expression is omitted, so each WHEN clause expression is evaluated and converted to bit strings. The action after the WHEN clause is performed if any bit in any resulting string is a 1.

DECLARE MONTH CHAR(3),
      YEAR PIC'99',
      NO_DAYS FIXED BINARY;
.
.
.
SELECT(MONTH);
   WHEN ('FEB')
      SELECT (MOD(YEAR,4));
            WHEN (0) NO_DAYS = 29;
            OTHERWISE NO_DAYS = 28;
      END;
   WHEN ('APR','JUN','SEPT','NOV') NO_DAYS = 30;
   OTHERWISE NO_DAYS = 31;
END;

The previous example shows nested SELECT-groups used to set a variable to the number of days in a specified month. Here, the MOD built-in function returns the remainder when YEAR is divided by 4. (The algorithm is incorrect for some century years.)

Restrictions

None.

Parent topic: Statements


SIGNAL

Purpose

Causes a specified condition to be signaled.

Syntax

SIGNAL condition-name;

Parameters

condition-name
ANYCONDITION, AREA, ATTENTION, CONDITION(name), CONVERSION, ENDFILE(f), ENDPAGE(f), ERROR, FINISH, FIXEDOVERFLOW, KEY(f), OVERFLOW, RECORD(f), UNDEFINEDFILE(f), UNDERFLOW, USERCONDITION (expression), USERCONDITION(SS$_UNWIND), VAXCONDITION (expression), or ZERODIVIDE.
Note:

Abbreviations:

  • ATTN for ATTENTION
  • COND for CONDITION
  • CONV for CONVERSION
  • OFL for OVERFLOW
  • UFL for UNDERFLOW
  • UNDF for UNDEFINEDFILE
  • ZDIV for ZERODIVIDE

Description

The SIGNAL statement forces a specified condition to be raised. for detailed information on condition handling, see the section ON Statement.

A signal from a SIGNAL statement or from a condition raised during run-time calls the most recently established ON-unit for the specified condition.

Example

SIGNAL ERROR;
SIGNAL ENDFILE(F);

Restrictions

The ONCODE built-in function returns the value of the expression in the SIGNAL USERCONDITION (expression) or VAXCONDITION (expression) statement that caused the ON-unit to be invoked. For this reason, take care to choose expression values that do not conflict with any of the values used to indicate system or run-time errors or conditions.

In general, you can avoid conflicts with system and run-time-defined codes by using values greater than or equal to 100000 (one hundred thousand) for user-defined conditions. Code values between 0 and 99999 that are currently unused by the system are reserved for future expansions.

Parent topic: Statements
Related information
ON Statement


%SKIP

Purpose

Causes a specified number of lines in the list file to be left blank.

Syntax

%SKIP (n);

Parameters

n
An integer in the range of 1 to 999. If n is omitted, the default value of 1 is supplied.

Description

The %SKIP statement causes n lines following the %SKIP statement in the program listing to be left blank. The %SKIP statement does not appear in the listing.

Restrictions

None.

Parent topic: Statements


STOP

Purpose

Raises the FINISH condition, closes all open files, and ends program execution.

Syntax

STOP;

Description

The STOP statement raises the FINISH condition, closes all open files, and ends program execution.

A RETURN from a main procedure (declared with OPTIONS(MAIN)) has the same effect as STOP.

Example

CLOSE:
   PROCEDURE;

   IF CLOSEDATE(FILE_NO) = 0
      THEN CALL ERROR(7);
      .
      .
      .
   STOP;
END CLOSE;

Restrictions

None.

Parent topic: Statements


WRITE

Purpose

Adds a record to a STREAM OUTPUT, RECORD OUTPUT, or RECORD UPDATE file.

Syntax

WRITE FILE(f)FROM(v)[KEYFROM(k)];

Parameters

f
A reference to the file to which the record will be written.
v
A reference to the variable that contains data for the output record.
k
An expression that specifies a key position.

The FILE, FROM, and KEYFROM specifiers may be written in any order.

Description

The WRITE statement adds a record to a file, either at the end of the file having the SEQUENTIAL and OUTPUT attributes, or into a file having the KEYED and OUTPUT attributes or the KEYED and UPDATE attributes.

The variable that contains data for the output record cannot be an unaligned bit string, a structure consisting entirely of unaligned bit strings, or a structure with the UNION attribute.

If the file associated with f has been opened with the KEYED and SEQUENTIAL attributes, the KEYFROM option may be specified. If the KEYFROM option is specified, the value of the expression k serves as the key value of the new record. If a record with this key value already exists, the KEY condition is signaled.

For non-VSAM files, if the file associated with f has been opened with the KEYED and DIRECT attributes, the KEYFROM option must be specified. The value of the expression k serves as the record number of the new record. If a record with this record number already exists, the KEY condition is signaled.

If a KEYFROM option is given, the file must have been previously opened with the KEYED attribute. The presence of the KEYFROM option does not supply the KEYED attribute in an implicit file opening.

The FILE option must contain a reference f that produces a file value. The file associated with f must either have been previously opened with RECORD OUTPUT, or it must be closed. If closed, it is opened by the WRITE statement and given the OUTPUT RECORD SEQUENTIAL attributes.

Open PL/I allows the use of WRITE with a stream file, as long as the WRITE statement specifies a scalar character varying string variable in its FROM option. The WRITE statement does an implicit SKIP and then writes a line consisting of the current value of the varying string specified by the FROM option followed by a new-line character.

Example

WRITE FILE(F) FROM(CUSTOMER) KEYFROM(N+1);
DECLARE 1 CUSTOMER,
      2 NAME CHAR(20) VARYING,
      2 ADDRESS
            3 NUMBER FIXED BINARY(15),
            3 STREET CHAR(12) VARYING,
            3 CITY CHAR(20) VARYING;
DECLARE F FILE;
   .
   .
   .

Restrictions

For DIRECT and KEYED SEQUENTIAL files the first WRITE that is performed on the file sets the default record size. This means that if a small record is the first record written to a file, subsequent WRITEs of large records could cause errors to occur. For example:

DECLARE F1 FILE,
      RECORD_ONE CHAR(5),
      RECORD_TWO CHAR(6);

OPEN FILE(F1) RECORD DIRECT OUTPUT;
WRITE FILE(F1) FROM(RECORD_ONE) KEYFROM(1);
WRITE FILE(F1) FROM(RECORD_TWO) KEYFROM(2);

In the previous program the first WRITE will cause the default record size to be set to 5. Since the second WRITE is of a value greater than 5, an ERROR will be signaled. This restriction does not apply if the file is opened with the -DAM switch in the TITLE option to specify the record size in the file. For example, the program fragment in the above example would have worked correctly if the OPEN statement had read:

OPEN FILE(F1) TITLE('TESTFILE -DAM 10') RECORD DIRECT OUTPUT;

This would have set the default record size to 10 and the WRITE of both the CHAR (5) and CHAR ( 6 ) would have worked correctly.

Parent topic: Statements


%XINCLUDE

Purpose

Incorporates text from other files into the current source file during compilation but the requested file is included only if it has not been included already.

Syntax

%XINCLUDE filename[,filename]…;

Parameters

filename
One of the following: a character string, an Open PL/I name, or an Open PL/I name enclosed in parentheses.

The specified filename is used to locate a text file whose content is inserted into the program text in place of the %XINCLUDE statement.

Description

%XINCLUDE is very similar to %INCLUDE because it incorporates text from other files into the current source file during compilation but the difference is that the requested file is included only if it has not been included already.

Example

%XINCLUDE 'FILE1','FILE2',(FILE3),(FILE4);

Restrictions

None.

Parent topic: Statements
Related reference
%INCLUDE


Open PL/I Built-ins

  • Introduction
  • ABS Function
  • ACOS Function
  • ADD Function
  • ADDR Function
  • ADDRDATA
  • ALL Function
  • ALLOCATION Function
  • ANY Function
  • ASIN Function
  • ATAN Function
  • ATAND Function
  • ATANH Function
  • BINARY Function
  • BINARYVALUE Function
  • BIT Function
  • BOOL Function
  • BYTE Function
  • CEIL Function
  • CENTERLEFT / CENTRELEFT Function
  • CENTERRIGHT / CENTRERIGHT Function
  • CHARACTER Function
  • COLLATE Function
  • COMPLEX Function
  • CONJG Function
  • COPY Function
  • COS Function
  • COSD Function
  • COSH Function
  • COUNT Function
  • CURRENTSTORAGE Function
  • DATAFIELD Function
  • DATE Function
  • DATETIME Function
  • DECIMAL Function
  • DIMENSION Function
  • DIVIDE Function
  • EMPTY Function
  • ENTRYADDR Function
  • ENTRYADDR pseudovariable Function
  • ERF Function
  • ERFC Function
  • EXP Function
  • FILEDDINT Function
  • FILEDDWORD Function
  • FILEOPEN Function
  • FIXED Function
  • FLOAT Function
  • FLOOR Function
  • FLUSH Subroutine
  • GRAPHIC Function
  • HBOUND Function
  • HEX Function
  • HIGH Function
  • IMAG pseudovariable Function
  • INDEX Function
  • INT Function
  • LBOUND Function
  • LENGTH Function
  • LEFT Function
  • LINENO Function
  • LOG Function
  • LOG10 Function
  • LOG2 Function
  • LOW Function
  • LOWERCASE Function
  • LPIPARAMCOUNT Function
  • MAX Function
  • MAXLENGTH Function
  • MIN Function
  • MOD Function
  • MPSTR Function
  • MULTIPLY Function
  • NULL Function
  • OFFSET Function
  • ONCHAR Function
  • ONCODE Function
  • ONCOUNT Function
  • ONFILE Function
  • ONKEY Function
  • ONLOC Function
  • ONSOURCE Function
  • PACKAGENAME Function
  • PAGENO Function
  • PLIRETC Subroutine
  • PLIRETV Function
  • PLISRTx Subroutines
  • POINTER Function
  • POINTERADD Function
  • POINTERDIFF / PTRDIFF Function
  • POINTERSUBTRACT / PTRSUBTRACT
  • POINTERVALUE Function
  • POLY Function
  • POSINT Function
  • PRECISION Function
  • PROCEDURENAME() Function
  • PROD Function
  • RANK Function
  • REAL Function
  • REPEAT Function
  • RESIGNAL() Subroutine
  • REVERSE Function
  • RIGHT Function
  • ROUND Function
  • SAMEKEY Function
  • SEARCH Function
  • SEARCHR Function
  • SIGN
  • SIN Function
  • SIND Function
  • SINH Function
  • SIZE Function
  • SQRT Function
  • STORAGE Function
  • STRING Function
  • SUBSTR Function
  • SUM Function
  • SYSNULL Function
  • TALLY Function
  • TAN Function
  • TAND Function
  • TANH Function
  • TIME Function
  • TRANSLATE Function
  • TRIM Function
  • TRUNC Function
  • UNSPEC Function
  • UPPERCASE Function
  • VALID Function
  • VERIFY Function
Parent topic: Open PL/I Language Reference Manual


Introduction

Built-in functions and subroutines are procedures provided by the Open PL/I language. They can be used wherever an expression is valid.

The built-in functions and subroutines provided by Open PL/I can be grouped into the following classes:

  • Arithmetic built-in functions, which provide information about the properties of arithmetic values, or that perform ordinary arithmetic calculations. These include:
    ABS | EXP | LOG10 | MOD | SIGN
    ADD | FLOOR | LOG2 | MULTIPLY | SORT
    CEIL | INT | MAX | POSINT | TRUNC
    DIVIDE | LOG | MIN | ROUND
  • Trigonometric built-in functions, which perform standard mathematical calculations in floating-point. These include:
    ACOS | ATAND | COSD | SIND | TAND
    ASIN | ATANH | COSH | SINH | TANH
    ATAN | COS | SIN | TAN
  • String built-in functions, which process character-string and bit-string values. These include:
    BOOL | HIGH | LOW | SUBSTR | VALID
    COLLATE | INDEX | REPEAT | TRANSLATE | VERIFY
    COPY | LENGTH | STRING | TRIM
  • Conversion built-in functions, which convert data from one data type to another. These include:
    BINARY | BYTE | DECIMAL | FLOAT | RANK
    BIT | CHARACTER | FIXED
  • Condition-handling built-in functions, which provide information about interrupts that are caused by signaled conditions. These include:
    ONCHAR ONFILE ONKEY ONLOC ONSOURCE
    ONCODE
  • Array-handling built-in functions, which provide information about arrays and array elements. These include:
    ALL | DIMENSION | LBOUND | PROD | SUM
    ANY | HBOUND
  • Storage-handling built-in functions, which provide information on the storage requirements and location of variables. These include:
    ADDR | CURRENTSTORAGE | OFFSET | SIZE | STORAGE
    ALLOCATION | NULL | POINTER
  • Miscellaneous built-in functions and subroutines. These include:
    DATE | LINENO | PLIRETC | PLISRTx | TIME
    DATETIME | PAGENO | PLIRETV | RESIGNAL | UNSPEC
    FLUSH

This chapter describes each built-in. The built-ins are presented in alphabetical order by name. Each built-in definition consists of the following subsections: syntax, description (the effect of the built-in), examples (one or more examples of the built-in usage and results) and restrictions (any restrictions in the use of the built-in).

Arguments to built-ins are effectively passed by value, that is, no alteration of the arguments is done.

Parent topic: Open PL/I Built-ins


ABS Function

Purpose

Returns the absolute value of an arithmetic value.

Syntax

ABS(x)

Parameters

x is an arithmetic expression.

Description

ABS(x) returns the absolute value of x.

The result has the same data type and precision as x.

Examples

ABS(-132)  /* returns 132 */
ABS(12.5)  /* returns 12.5 */

Restrictions

The ABS function may produce unexpected results when x is fixed binary and has the maximum negative value for its precision. For example, if x is Fixed Binary(15) and has the value -32768, ABS(x) is -32768.

Parent topic: Open PL/I Built-ins


ACOS Function

Purpose

Returns the arc cosine of a floating-point value.

Syntax

ACOS(x)

Parameters

x is a floating-point value such that -1 ? x ? 1, or is an expression that can be converted to such a value.

Description

ACOS(x) returns the arc cosine of x expressed in radians, such that 0 ? ACOS(x) ? ?. The result is a floating-point value.

Examples

ACOS(1.0)   /* returns 0.0 */

Restrictions

An ACOS operation on Float Decimal data is actually performed using its Float Binary equivalent. Thus, the ranges of the operands and the result are limited to the range of Float Binary data.

Parent topic: Open PL/I Built-ins


ADD Function

Purpose

Returns the sum of two arithmetic values.

Syntax

ADD(x,y,p,[q])

Parameters

x and y are arithmetic values, and p and q are integer constants that represent precision and scale factor, respectively.

Description

ADD(x,y,p) returns the arithmetic value x+y with precision and scale (p,0). ADD(x,y,p,q) returns x+y with precision and scale (p,q). The result has the common data type of x and y. If the arguments differ, they are converted as described in the section Arithmetic to Arithmetic Conversion in the chapter Data Type Conversions.

The ADD function can also be used for subtraction. To subtract, precede the operand to be subtracted with a minus sign.

Examples

DECLARE (PRICE, TAX) DECIMAL(5,2);
   .
   .
   .
PUT LIST ('TOTAL COST IS' ||
      ADD (PRICE, TAX, 6,2));

Restrictions

The parameter q must not be specified unless the result type is decimal.

Parent topic: Open PL/I Built-ins
Related information
Arithmetic to Arithmetic Conversion


ADDR Function

Purpose

Returns a pointer to the storage referenced by the specified variable.

Syntax

ADDR(x)

Parameters

x is a specified variable.

Description

The ADDR function returns a pointer to the storage referenced by a specified variable x. If x is an unconnected array cross-section, ADDR returns the address of the first element of the first element of the cross-section.

x must not be a reference to a parameter whose corresponding argument was passed by value.

Examples

DECLARE ELEMENT FIXED BINARY BASED;
DECLARE A(10) FIXED BINARY;
DECLARE P POINTER;
   P = ADDR (A(5));   /* ADDRESS OF 5TH ELEMENT */
   P -> ELEMENT = -1;

Restrictions

On many implementations, x must not be an unaligned bit string or a structure consisting entirely of unaligned bit strings. (For information on this implementation, see your Open PL/I User's Guide.)

Parent topic: Open PL/I Built-ins


ADDRDATA

Purpose

Returns a pointer to the storage referenced by the specified variable.

Syntax

ADDRDATA(x)

Parameters

x is a specified variable.

Description

The ADDRDATA function returns a pointer to the storage referenced by a specified variable x. Its behavior is similar to that of ADDR except when x is a reference to a varying string. In this case ADDRDATA returns the address of the first data byte of the string.

Examples

myprog: proc options (main);

    dcl str char(12) var init ('abcdefgh');
    dcl s   char (4) based;

    dcl i fixed bin (15) init (99);
    dcl fb15 fixed bin (15) based;
    dcl p ptr;

    p = addrdata(str);
    put skip list (addrdata(i)->fb15, addr(str)->fb15, p->s,
                                         ptradd(addrdata(str),4)->s);
end;

Results in:

      99               8       abcd    efgh
Parent topic: Open PL/I Built-ins


ALL Function

Purpose

Returns a bit string that is the logical AND of the elements of a bit string array.

Syntax

ALL(x)

Parameters

x is an array expression. If x is not a bit string array, it is converted to one.

Description

The ALL function returns a bit string whose length is equal to the length of the longest bit string value in the array. Each bit of the result is 1 if and only if the corresponding bit exists and has the value 1 in every element of the array.

Examples

DCL BIT_TEST(3) BIT(5) INITIAL ('10011'B, '10111'B, 10110'B);
DCL BIT_RES BIT(5);
BIT_RES = ALL(BIT_TEST);   /* returns '10010'B */
Parent topic: Open PL/I Built-ins


ALLOCATION Function

Purpose

Returns a fixed-point binary integer that is the number of existing generations of a controlled variable.

Syntax

ALLOCATION (x)

Abbreviation(s): ALLOCN for ALLOCATION.

Parameters

x is a controlled variable.

Description

The ALLOCATION function returns a fixed-point binary integer that is the number of existing generations of a specified controlled variable. If x is not currently allocated, the result is zero.

Examples

DECLARE INPUT CHAR(10) CONTROLLED,
   A CHAR(3) VARYING;
      .
      .
      .
      DO UNTIL (INPUT = 'STOP');
            ALLOCATE INPUT;
            GET LIST (INPUT);
               .
               .
               .
            END;
   A = ALLOCATION(INPUT);
   PUT SKIP LIST('Generations = ', A);

Restrictions

None.

Parent topic: Open PL/I Built-ins


ANY Function

Purpose

Returns a bit string that is the logical OR of the elements of a bit string array.

Syntax

ANY(x)

Parameters

x is an array expression. If x is not a bit string array, it is converted to one.

Description

The ANY function returns a bit string whose length is equal to the length of the longest bit string value in the array. Each bit of the result is 1 if the corresponding bit exists and has the value 1 in any element of the array.

Examples

DECLARE BIT_TEST(3) BIT(5) INITIAL ('10011'B, '10111'B, 10110'B);
DECLARE BIT_RES BIT(5);
BIT_RES = ANY(BIT_TEST);   /* returns '10111'B */

Restrictions

None.

Parent topic: Open PL/I Built-ins


ASIN Function

Purpose

Returns the arc sine of a floating-point value.

Syntax

ASIN(x)

Parameters

x is a floating-point value such that -1 ? x ? 1, or is an expression that can be converted to such a value.

Description

ASIN(x) returns the arc sine of x expressed in radians, such that -?/2 ? ASIN(x) ? ?/2. The result is a floating-point value.

Examples

ASIN(0.0) /* returns 0.0. */

Restrictions

An ASIN operation on Float Decimal data is actually performed using its Float Binary equivalent. Thus, the ranges of the operands and the result are limited to the range of Float Binary data.

Parent topic: Open PL/I Built-ins


ATAN Function

Purpose

Returns the arc tangent of an arithmetic expression.

Syntax

ATAN(x,[y])

Parameters

x and y are floating-point values such that y is not zero, or are expressions that can be converted to such values.

Description

ATAN(x) returns the arc tangent of x. The result is such that -?/2 ? ATAN(x) ? ?/2. The result is expressed in radians and has the same data type as x.

ATAN(x,y) returns the arc tangent of x/y. The result is such that if x/y ? 0, then 0 ? ATAN(x,y) ? ?; and, if x/y < 0, then -? ? ATAN(x,y) ? 0. The result is expressed in radians and has the same data type as x/y, and has the maximum precision of xand y.

Examples

X = 3.14157;
Y = 2.0;
RADIANS = ATAN(X);   /* 1.26 */

or

RADIANS ATAN(X,Y);  /* 1.00 */

Restrictions

An ATAN operation on Float Decimal data is actually performed using its Float Binary equivalent. Thus, the ranges of the operands and the result are limited to the range of Float Binary data.

Parent topic: Open PL/I Built-ins


ATAND Function

Purpose

Returns the arc tangent of an arithmetic expression expressed in degrees.

Syntax

ATAND(x)

or

ATAND(x,y)

Parameters

x is a single floating-point value (syntax 1) or both x and y are floating-point values (syntax 2).

Description

The ATAND function returns a floating-point value that is the arc tangent of a single arithmetic expression x or an arc tangent computed from two arithmetic expressions x and y. If two arguments are supplied, they must not both be zero.

ATAND(x) returns the arctangent of x. The result is expressed in degrees and has the same data type as x such that -90 ? ATAND(x) ? 90.

ATAND(x,y) returns the angle in degrees whose tangent is x/y. The result is the common type and maximum precision of x and y such that if x/y ? 0, then 0 ? ATAND(x,y) ? 180, and if x/y < 0, then -180 ? ATAND(x,y) ? 0.

Examples

ATAND(1.0)   /* returns 45.0. */
ATAND(-1.0,1.0)  /* returns -45.0. */
ATAND(1.0,0.0)   /* returns 45.0. */

X = 3.14157;
Y = 2.0;
DEGREES = ATAND(X);   /* 7.2343E+01 */

or

DEGREES = ATAND(X,Y)   /* 5.7518E+01 */

Restrictions

An ATAND operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


ATANH Function

Purpose

Returns the hyperbolic arc tangent of an arithmetic expression.

Syntax

ATANH(x)

Parameters

x is a floating-point value such that -1 < x < 1.

Description

The ATANH(x) function returns the hyperbolic arc tangent of x. The result has the same data type as x.

Examples

ATANH(0.5)   /* returns 0.54930 */

Restrictions

An ATANH operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


BINARY Function

Purpose

Converts an arithmetic or string value to a binary number with an optionally specified precision.

Syntax

BINARY(x[,p])

Abbreviation(s): BIN for BINARY.

Parameters

x is an arithmetic or string value, and p is an integer constant specifying an optional precision.

Description

The BINARY function converts an arithmetic or string value x to binary radix (Float Binary or Fixed Binary data type), with an optionally specified precision p.

If x is a Fixed Decimal value with a non-zero scale factor, p must be given.

If x is a Float Decimal value, the result is a Float Binary value; otherwise, the result is a Fixed Binary value. A non-zero scale factor is not allowed with a Float Decimal. If p is omitted, the result has a precision that is determined by the rules for data type conversion given in the chapter Data Type Conversions.

Examples

BINARY('2000',31);

In fixed–point context, this example returns the value 2000 as a Fixed Bin(31) integer.

Restrictions

None.

Parent topic: Open PL/I Built-ins
Related information
Data Type Conversions


BINARYVALUE Function

Purpose

Returns a fixed binary integer that is the converted value of a pointer, offset, or ordinal.

Syntax

BINARYVALUE(x)

Abbreviation: BINVALUE for BINARYVALUE.

Parameters

x is an expression.

Restrictions

None.

Parent topic: Open PL/I Built-ins


BIT Function

Purpose

Converts an arithmetic or string value to a bit string.

Syntax

BIT(s)

or

BIT(s,l)

Parameters

s is an arithmetic or string value of an optionally specified length l, and l is a positive integer.

Description

The BIT function converts an arithmetic or string value to a bit string of an optionally specified length.

s is first converted to a bit string whose length is determined by the rules for data type conversion given in the chapter Data Type Conversions. Then, if the length l is specified, the bit string is truncated on the right or padded on the right with zero bits to the specified length.

Examples

DECLARE INTEGER FIXED BINARY(15);
DECLARE BIT_STRING BIT(15);

INTEGER = 20;
BIT_STRING = BIT(INTEGER);
/* BIT_STRING NOW EQUALS '000000000010100'B */

Restrictions

None.

Parent topic: Open PL/I Built-ins
Related information
Data Type Conversions


BOOL Function

Purpose

Performs a Boolean operation on two bit-string arguments.

Syntax

BOOL(x,y,z)

Parameters

x and y are bit-string arguments, and z is a bit string.

Description

The BOOL function performs a Boolean operation on two bit-string arguments, x and y, and returns the result as a bit string with the length of the longer argument.

z should be a bit string 4 bits long. If not, it is converted to Bit (4).

If x and y are null strings, the result is a null string. If x is not the same length as y, the shorter string is extended on the right with zero bits until x and y are the same length. The bit values within z are m1, m2, m3, m4 from left-to-right, respectively.

The Ith bit value of the result is set to one of the values m1, m2, m3, m4 depending on the Ith bit value of x and y according to table below.

X(I) | Y(I) | RESULT(I)
0 | 0 | m1
0 | 1 | m2
1 | 0 | m3
1 | 1 | m4

In other words, bit string z defines the result of some Boolean function. For instance, to define the function OR, the value of bit string z is given as '0111'b. To define the function AND, bit string z is '0001'b. The result is a bit string of the same length as x and y, obtained by applying the function rule described by z to each bit position of string x and string y.

Examples

BOOL('1100110'b,'0101'b,'0110'b)  /*returns '1001110'b */

In this example, the second argument is extended to '0101000'b. For bit 1, x is 1 and y is 0. Therefore, the resulting bit is the value m3or 1. For bit 2, x is 1 and y is 1, therefore the resulting bit is the value of m4 or 0. A comparison of bits 3, 0, and 0 produces the value m1 or 0.

Restrictions

None.

Parent topic: Open PL/I Built-ins


BYTE Function

Purpose

Returns a single character whose ASCII code corresponds to the specified value.

Syntax

BYTE(x)

Parameters

x is a fixed-point binary integer value.

Description

The BYTE function returns a single character whose ASCII code corresponds to the value x. The index into COLLATE() is taken by considering only the rightmost bits of x (one byte). The BYTE function uses a 256-byte collating string.

Examples

CHAR=BYTE(66)   /* returns 'B' for the American English ASCII collating sequence */

Restrictions

None.

Parent topic: Open PL/I Built-ins


CEIL Function

Purpose

Returns the smallest integer greater than or equal to the specified arithmetic expression.

Syntax

CEIL(x)

Parameters

x is an arithmetic expression.

Description

The CEIL function returns the smallest integer greater than or equal to x with precision (p,q). The result has the same data type as x.

If x is a floating-point value, the precision of the result is the precision of x. If x is a fixed-point value, the precision of the result is (MIN(n,MAX(p-q+1,1)),0). n is the maximum precision allowed for a fixed-point value of the result type. (For details, see your Open PL/I User's Guide.)

Examples

CEIL(-3.1)  /* returns -3.0 */
CEIL(3.1)  /* returns 4.0 */
CEIL(0)  /* returns 0 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


CENTERLEFT / CENTRELEFT Function

Purpose

Returns the result of inserting a string in the center or one position to the left of the center of another string with a certain length. It can be padded on the left and on the right with a character.

Syntax

CENTERLEFT(s,l,c)

Parameters

s
A string that is inserted inside another sting. It must have a computational type and a character type. If it does not have a character type, it is converted to character.
l
The length of a string in which s is inserted. It must have a computational type and a character type and is converted to Fixed Binary(31,0).
c
Optional padding character, inserted to the left and to the right of the string. It must have a nonvarying character type.

Examples:

dcl s char (40) var;
    dcl t char (40) var;

    s = 'This string is 33 characters long';
    t = centerleft(s, 40, '+');
    put skip list (t);

will print:

+++This string is 33 characters long++++

Restrictions

None.

Parent topic: Open PL/I Built-ins


CENTERRIGHT / CENTRERIGHT Function

Purpose

Returns the result of inserting a string in the center or one position to the right of the center of another string with a certain length. It can be padded on the left and on the right with a character.

Syntax

CENTERRIGHT(s,l,c)

Parameters

s
A string that is inserted inside another sting. It must have a computational type and a character type. If it does not have a character type, it is converted to character.
l
The length of a string in which s is inserted. It must have a computational type and a character type and is converted to Fixed Binary(31,0).
c
Optional padding character, inserted to the left and to the right of the string. It must have a nonvarying character type.

Examples

dcl s char (40) var;
    dcl t char (40) var;

    s = 'This string is 33 characters long';
    t = centerright(s, 40, '+');
    put skip list (t);

will print:

++++This string is 33 characters long+++

Restriction

None.

Parent topic: Open PL/I Built-ins


CHARACTER Function

Purpose

Converts an arithmetic or string value to a character string.

Syntax

CHARACTER(s)

or

CHARACTER(sl)

Abbreviation(s): CHAR for CHARACTER.

Parameters

s is an arithmetic or string value, and l is a positive integer value.

Description

The CHARACTER function converts an arithmetic or string value s to a character string of an optionally specified length l. s is first converted to a character string whose length is determined by the rules for data type conversion given in the chapter Data Type Conversions. Then, if l is given, s is either truncated on the right or extended on the right with blanks to be l characters long.

Examples

DECLARE X FIXED BINARY (15);
DECLARE Y CHARACTER(14) VARYING;
X = 2;
Y = CHARACTER(X);
PUT LIST ('$'||Y);      /* $    2 */

Restrictions

The CHARACTER function does not support unaligned BIT(n) parameters.

Parent topic: Open PL/I Built-ins
Related information
Data Type Conversions


COLLATE Function

Purpose

Returns a string consisting of the character set of the National Language being used, in ascending order.

Syntax

COLLATE()

or

COLLATE

The second syntax form can be used only when the BUILTIN attribute is specified.

Description

The COLLATE function returns a character string, of a length determined for the National Language support being used (128 characters for American English), that consists of the set of characters in the computer's character set in ascending order.

In Open PL/I, COLLATE returns a string consisting of the number of characters of the character set as determined by the National Language support.

The COLLATE function uses a 256-byte collating string.

Examples

DECLARE X CHARACTER(5);
X = SUBSTR(COLLATE(), 100, 5);   /* returns X = 'cdefg' */

This example assumes American English National Language support.

Restrictions

None.

Parent topic: Open PL/I Built-ins


COMPLEX Function

Purpose

Returns the complex value x + yI.

Syntax

COMPLEX(x,y)

Abbreviation: CPLX for COMPLEX.

Parameters

x and y are real expressions.

Description

If x and y differ in base, the decimal argument is converted to binary.

If x and y differ in scale, the fixed-point argument is converted to floating-point. The result has the common base and scale.

If fixed-point, the precision of the result is given by the following:

(min(N,max(p1-q1,p2-q2)+max(q1,q2)),max(q1,q2))

where (p1,q1) and (p2,q2) are the precisions of x and y, respectively, and N is the maximum number of digits allowed. After any necessary conversions have been performed, if the arguments are floating-point, the result has the precision of the longer argument

Restrictions

None.

Parent topic: Open PL/I Built-ins


CONJG Function

Purpose

Returns the conjugate of the specified expression; that is, the value of the expression with the sign of the imaginary part reversed.

Syntax

CONJG(x)

Parameters

x is an expression.

Description

If x is real, it is converted to complex. The result has the base, scale, mode, and precision of x.

Restrictions

None.

Parent topic: Open PL/I Built-ins


COPY Function

Purpose

Copies a particular string a certain number of times and concatenates the result into a single string.

Syntax

COPY(x,y)

Parameters

x is a character-string, bit-string, or picture value, and y is a positive integer expression. If x is an arithmetic value, it is converted to a bit string if it is binary, or to a character string if it is decimal.

Description

The COPY function copies a particular string, x, a certain number of times, y, and concatenates the result into a single string. COPY effectively returns a string containing y occurrences of the string argument, with length y* length (x).

The result is obtained by concatenating y occurrences of x together.

Examples

DECLARE X CHAR(6);
X = COPY('AB',3)   /* returns X = 'ABABAB' */

Note that the same result could be produced by using a string repetition factor, as illustrated below:

X = (3) 'AB';

Restrictions

None.

Parent topic: Open PL/I Built-ins


COS Function

Purpose

Returns a value that is the cosine of the specified angle expressed in radians.

Syntax

COS(X)

Parameters

x is a floating-point value.

Description

The COS function returns a value that is the cosine of the angle x expressed in radians. The result has the same data type as x such that -1 ? COS(x) ? 1.

Examples

COS(0.0)   /* returns 1.0 */

Restrictions

A COS operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


COSD Function

Purpose

Returns a value that is the cosine of the specified angle expressed in degrees.

Syntax

COSD(x)

Parameters

x is a floating-point value.

Description

The COSD function returns a value that is the cosine of the angle x expressed in degrees. The result has the same value type as x such that -1 ? COSD(x) ? 1.

Examples

COSD(60.0)    /* returns 0.5 */

Restrictions

A COSD operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


COSH Function

Purpose

Returns a value that is the hyperbolic cosine of the specified arithmetic value.

Syntax

COSH(x)

Parameters

x is a floating-point value.

Description

The COSH function returns a value that is the hyperbolic cosine of the angle x expressed in radians.

The result has the same data type as x such that COSH(x) ? 1.

Examples

COSH(0.0)    /* returns 1.0 */

Restrictions

A COSH operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


COUNT Function

Purpose

Returns an unscaled real fixed binary value specifying the number of data items transmitted during the last GET or PUT operation on the specified file-reference.

Syntax

COUNT(x)

Parameters

x is a file-reference. The file must be open and have the STREAM attribute.

Description

The count of transmitted items for a GET or PUT operation on x is initialized to zero before the first data item is transmitted, and is incremented by one after the transmission of each data item in the list. If x is not open in the current program, a value of zero is returned.

If an ON-unit or procedure is entered during a GET or PUT operation, and within that ON-unit or procedure, a GET or PUT operation is executed for x, the value of COUNT is reset for the new operation. It is restored when the original GET or PUT is continued.

Restrictions

None.

Parent topic: Open PL/I Built-ins


CURRENTSTORAGE Function

Purpose

Returns a Fixed Bin(15) value that is the number of bytes of storage used by the current value of the referenced variable.

Syntax

CURRENTSTORAGE(reference)

Abbreviation(s): CSTG for CURRENTSTORAGE.

Parameters

reference is a variable.

Description

For constant-length strings and other fixed-size variables, the CURRENTSTORAGE function returns a Fixed Bin(15) integer that is the number of bytes allocated for the referenced variable.

A variable-length string consists of two parts: the text field and the length field. CURRENTSTORAGE returns the number of bytes of the text field currently in use plus two, since the length field always uses two bytes.

For a scalar area or an element of an array of areas, the CURRENTSTORAGE function returns the sum of the current extent of the area plus the size of the area header. Any bytes at the end of the area that have not been allocated are not included in the area extent value. Note, however, that the extent does include the size of any holes in the area that have developed as a result of ALLOCATE and FREE operations. For an array of areas, the CURRENTSTORAGE function returns the maximum size of the array, including the header bytes for each area element of the array.

Examples

DCL A FIXED BIN(15) INIT (1);   /* CSTG (A) = 2 */
DCL B CHAR(5) INIT ('XY');          /* CSTG (B) = 5 */
DCL C CHAR(5) VARYING INIT ('XY');  /* CSTG ©) = 4 */
DCL D BIT(4) INIT ('1010'B);        /* CSTG (D) = 1 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


DATAFIELD Function

Purpose

In a NAME condition ON-unit (or any of its dynamic descendants), or an ON-unit (or any of its dynamic descendants) for an ERROR or FINISH condition raised as part of the implicit action for the NAME condition, returns a character string whose value is the contents of the field that raised the condition.

Syntax

DATAFIELD[()]

Parameters

None.

Description

If the string that raised the condition contains DBCS identifiers, GRAPHIC data, or mixed character data, DATAFIELD returns a mixed character string. If DATAFIELD is used out of context, a null string is returned.

Restrictions

None.

Parent topic: Open PL/I Built-ins


DATE Function

Purpose

Returns a character string that represents the system date.

Syntax

DATE()

or

DATE

The second form can be used only when the BUILTIN attribute is specified.

Description

The DATE function returns a character string of length 6 that represents the system date in the form yymmdd, where yy, mm, and dd are in the ranges 00–99, 01–12, and 01–31, respectively, and represent year, month, and day, respectively.

You may also define the LPI_YEAR environment variable to return any year value you want (such as 2009).

If you are using Bourne shell, do this:

LPI_YEAR=2009;
export LPI_YEAR

If you are using C-shell, do this:

setenv LPI_YEAR 2009;

Examples

DATE()  /* returned '891017' on October 17, 1989 */
Parent topic: Open PL/I Built-ins


DATETIME Function

Purpose

Returns a character string that represents the system date and time of day.

Syntax

DATETIME()

or

DATETIME

The second form can be used only when DATETIME has been declared with the BUILTIN attribute.

Description

The DATE function returns a character string of length 17 that represents the system date in the form yyyymmddhhmmssttt, where:

String | Range | Represents
yyyy | 0000–9999 | year
mm | 01–12 | month
dd | 01–31 | day
hh | 00–23 | hour
mm | 00–59 | minute
ss | 00–59 | second
ttt | 000–999 | millisecond

You may also define the LPI_YEAR environment variable to return any year value you want (such as 2009).

If you are using Bourne shell, do this:

LPI_YEAR=2009;
export LPI_YEAR

If you are using C-shell, do this:

setenv LPI_YEAR 2009;

Examples

DATETIME()  /* returned '19940526163111585' on May 26,
                   1994 at 11.585 seconds after 4:31 PM */

Restrictions

None.

Parent topic: Open PL/I Built-ins


DECIMAL Function

Purpose

Converts an arithmetic or string value to a DECIMAL number.

Syntax

DECIMAL(x)

or

DECIMAL(x,p)

or

DECIMAL(x,p,q)

Abbreviation(s): DEC for DECIMAL.

Parameters

x is an arithmetic or string value, and p and q are integer constants representing precision and scale factor, respectively.

Description

The DECIMAL function converts an arithmetic or string value x to a DECIMAL number of an optionally specified precision p and scale factor q. p indicates the precision of the result. q indicates the scale of the result. If p alone is given, q is assumed to be zero.

If x is a floating-point value, the result is a float decimal value, and q must be omitted; otherwise, the result is a fixed decimal value, and if q is omitted, the result is an integer of precision p.

If p is omitted, the result has a precision determined by the rules for type conversion given in the chapter Data Type Conversions.

Examples

DECIMAL('3.14')  /* returns 3 */
Parent topic: Open PL/I Built-ins
Related information
Data Type Conversions


DIMENSION Function

Purpose

Returns a fixed binary integer that is the number of elements in the specified dimension of an array.

Syntax

DIMENSION(x[,n])

Abbreviation(s): DIM for DIMENSION.

Parameters

x is an array and n is an integer constant greater than zero that indicates the dimension of the array.

Description

The DIMENSION function returns an integer that is the number of elements in the specified dimension of an array x. This is useful for arrays with * extents.

n is an optional integer constant indicating the nth dimension of x. If n is not specified, the first dimension is assumed. The resulting binary integer gives the number of elements in the nth dimension of x.

The type of the result is Fixed Binary(31). x must have at least n dimensions.

Examples

DECLARE R FIXED BINARY;
DECLARE A(3:5,1:2,10:10,4:7);
   .
   .
   .
R=DIMENSION(A,1);  /*R=3*/
   .
   .
   .

Restrictions

The DIMENSION function is not supported with expression arguments.

Parent topic: Open PL/I Built-ins


DIVIDE Function

Purpose

Divides an arithmetic value by an arithmetic value and returns the quotient with a specified precision and an optionally specified scale factor.

Syntax

DIVIDE(x,y,p)

or

DIVIDE(x,y,p,q)

Parameters

x and y are arithmetic values, and p and q are integer constants that represent precision and scale factor, respectively.

Description

The DIVIDE function divides an arithmetic value, x, by an arithmetic value, y, and returns the quotient with a specified precision p and an optionally specified scale factor q.

The result is xly, having the common data type of x and y.

The precision of the result is (p,q) or (p). In the latter case, q equals zero.

If y equals zero, the program is in error and the ZERODIVIDE condition is raised.

Examples

DECLARE SUM FIXED BINARY(15);
   .
   .
   .
PUT LIST ('HALF PRICE IS'||DIVIDE (SUM, 2, 15));

Restrictions

The parameter q must not occur unless the result type is decimal.

Parent topic: Open PL/I Built-ins


EMPTY Function

Purpose

Returns an area whose extent is zero. This can be used to free all allocations in an area.

Syntax

EMPTY()

or

EMPTY

The second syntax form can be used only if EMPTY has been declared with the BUILTIN attribute.

Description

The value returned by this function is the same as the one used by the Compiler to initialize an area when it is allocated.

Examples

DECLARE  A AREA,
         0 OFFSET(A),
         X FIXED EASED(0);

ALLOCATE X IN(A) SET(0);

A = EMPTY();     /* Frees all allocations in A. */

Restrictions

None.

Parent topic: Open PL/I Built-ins


ENTRYADDR Function

Purpose

Returns a pointer value that is the address of the first executed instruction if the specified entry is invoked.

Syntax

ENTRYADDR(x)

Parameters

x is an entry reference.

Description

x must represent a non-nested procedure. If x is a fetchable entry constant, it must be fetched before ENTRYADDR is executed.

Restrictions

None.

Parent topic: Open PL/I Built-ins


ENTRYADDR pseudovariable Function

Purpose

Initializes an entry variable with the address of the entry to be invoked.

Syntax

ENTRYADDR(x)

Parameters

x is an entry reference.

Description

If the address supplied to the ENTRYADDR variable is the address of an internal procedure, results are unpredictable.

Restrictions

None.

Parent topic: Open PL/I Built-ins


ERF Function

Purpose

Returns a real floating point value that is an approximation of the error function of x.

Syntax

ERF(x)

Parameters

x is a real expression.

Description

The result has the base and precision of x, and a value given by (2/ &sqrt.(&pi.) ) &integral.(x)[0] EXP(-(t(2) ))dt.

Restrictions

None.

Parent topic: Open PL/I Built-ins


ERFC Function

Purpose

Returns a real floating point value that is an approximation of the complement of the error function of x.

Syntax

ERFC(x)

Parameters

x is a real expression.

Description

The result has the base and precision of x, and a value given by: 1 - ERF(x).

Restrictions

None.

Parent topic: Open PL/I Built-ins


EXP Function

Purpose

Returns the base of the natural logarithm raised to the specified power.

Syntax

EXP(x)

Parameters

x is an arithmetic expression.

Description

The EXP function returns the value of the base of the natural logarithm e raised to the power of x or e**x.

The result has the same data type as x.

Examples

EXP(2.0)  /* returns approximately 7.389056 */

Restrictions

An EXP operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


FILEDDINT Function

Purpose

Returns a FIXED BIN(31) value that is the value of attribute c for file x .

Syntax

FILEDDINT(x,c)

Parameters

x
File reference.
c
Character string that holds the attribute to be queried.

Description

FILEDDINT returns a FIXED BIN(31) value that is the value of attribute c for file x. When using FILEDDINT, the following are valid values for c:

  • blksize
  • bufsize
  • delay
  • filesize
  • keylen
  • keyloc
  • recsize
  • retry

These options return the following values:

  • FILEDDINT(x,'BLKSIZE') is valid only for programs executed under Enterprise Server.
  • FILEDDINT(x,'BLKSIZE') will return the blocksize for a CONSECUTIVE file. It will return 0 for a VSAM file.
  • FILEDDINT(x,'FILESIZE') will always return a value of 0.
  • FILEDDINT(x,'KEYLOC') and FILEDDINT(x,'KEYLEN') are valid only for VSAM KSDS files.
  • FILEDDINT(x,'delay') and FILEDDINT(x,'retry') will always return a value of 0.
  • FILEDDINT(x,'KEYLOC') and FILEDDINT(x,'KEYLEN') are valid only for VSAM KSDS files.

Restrictions

The ERROR condition with oncode 1010 is raised when the file is not open or the attribute is invalid for the file being queried.

Parent topic: Open PL/I Built-ins


FILEDDWORD Function

Purpose

Returns a character string that is the value of the attribute c for file x.

Syntax

FILEDDWORD(x,c)

Parameters

x
File reference.
c
Character string that holds the attribute to be queried.

Description

FILEDDWORD returns a character string that is the value of the attribute c for file x. When using FILEDDWORD, the following are valid options for c:

  • access
  • amthd
  • action
  • charset
  • filename
  • organization
  • recfm
  • type

These options return the following values:

  • ACCESS returns SEQUENTIAL or DIRECT.
  • ACTION returns INPUT, OUTPUT, or UPDATE.
  • AMTHD returns VSAM KSDS, VSAM ESDS or VSAM RRDS, FILESYS when run under Enterprise Server and FILESYS when run outside of Enterprise Server.
  • CHARSET returns ASCII or EBCDIC.
  • On the Enterprise Server the FILENAME returns an MVS dataset name. For an MVS dataset that is a member of a PDS or PDSE, the name returned includes the member name. When run outside of Enterprise Server it returns the fully qualified path name of the file.
  • ORGANIZATION returns CONSECUTIVE, RELATIVE, REGIONAL(1) or INDEXED.
  • RECFM returns the appropriate record format setting for the file, and U for VSAM files. This option is only valid on Enterprise Server.
  • TYPE returns RECORD or STREAM.

Restrictions

The ERROR condition with oncode 1010 is raised when the file is not open or the attribute is invalid for the file being queried.

Parent topic: Open PL/I Built-ins


FILEOPEN Function

Purpose

Returns '1'B if the file x is open and '0'B if the file is not open.

Syntax

FILEOPEN (x)

Parameters

x is the file name.

Parent topic: Open PL/I Built-ins


FIXED Function

Purpose

Converts an arithmetic or string value to a fixed-point arithmetic value with a specified precision and, optionally, a scale factor.

Syntax

FIXED(x,p)

or

FIXED(x,p,q)

Parameters

x is an arithmetic or string value, and p and q are integer constants representing precision and scale factor, respectively.

Description

The FIXED function converts an arithmetic or string value x to a fixed-point arithmetic value with a specified precision p and, optionally, a scale factor q. If q is omitted, q equals zero. The resulting fixed-point arithmetic value is converted according to the rules for type conversion given in the chapter Data Type Conversions.

Examples

FIXED(9.8614E+01,15,2)   /* returns 98.61 */

Restrictions

None.

Parent topic: Open PL/I Built-ins
Related information
Data Type Conversions


FLOAT Function

Purpose

Converts a string or arithmetic value to a floating-point arithmetic value, with a specified precision.

Syntax

FLOAT(x,p)

Parameters

x is a string or arithmetic value, and p is an integer representing precision.

Description

The FLOAT function converts a string or arithmetic value x to a floating-point arithmetic value, with a specified precision p. The resulting floating-point arithmetic value is converted according to the rules for type conversion given in the chapter Data Type Conversions.

Examples

FLOAT(98.614,8)   /* returns 9.8614 E+01 */
Parent topic: Open PL/I Built-ins
Related information
Data Type Conversions


FLOOR Function

Purpose

Returns the largest integer that is less than or equal to the specified arithmetic expression.

Syntax

FLOOR(x)

Parameters

x is an arithmetic expression.

Description

The FLOOR function returns the largest integer that is less than or equal to an arithmetic expression x.

If x is a floating-point value, the precision of the result is the precision of x. If x is a fixed-point value, the precision of the result is (MIN(n,MAX(p-q+1,1)),0). n is the maximum precision allowed for fixed-point values of the result type. (For details on maximum precisions, see your Open PL/I User's Guide.)

Examples

FLOOR(3.125)    /* returns 3.000 */
FLOOR(-3.125)   /* returns -4.000 */
FLOOR(0)        /* returns 0 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


FLUSH Subroutine

Purpose

Ensures that all disk I/O on a specified file has been written to disk, as opposed to remaining in I/O buffers.

Syntax

FLUSH(f);

Parameters

f is a filename.

Description

The FLUSH subroutine is used to ensure that all disk I/O on file f has been written to disk. This subroutine might be called in order to ensure some sort of synchronization, such as during critical I/O, or if there is a concern of a system crash or some other serious problem such that you may to want to make sure that the last I/O was in fact written out to disk.

Examples

DECLARE MYFILE FILE;

WRITE FILE(MYFILE) FROM(RECORD);
CALL FLUSH(MYFILE);

Restrictions

None.

Parent topic: Open PL/I Built-ins


GRAPHIC Function

Purpose

Can be use to explicitly convert character (or mixed character) data to GRAPHIC data. All other data first converts to character, and then to the GRAPHIC data type.

Returns the graphic value of x, with a length in graphic symbols specified by y.

Characters convert to graphics. The content of x is checked for validity during conversion, using the same rules as for checking graphic and mixed character constants.

Syntax

GRAPHIC(x[,y])

Parameters

x and y are expressions.

Description

When x is GRAPHIC it is subject to a length change, with appropriate padding or truncation. When x is nongraphic it is converted to character, if necessary. SBCS characters are converted to equivalent DBCS characters.

When necessary, y is converted to a real fixed-point binary value. If y is omitted, the length is determined by the rules for type conversion. y must not be negative.

If y = 0, the result is the null graphic string.

The following rules apply:

  • If y is greater than the length needed to contain the graphic string, the result is padded with graphic blanks.
  • If y is less than the length needed to contain the graphic string, the result is truncated.

Restrictions

None.

Parent topic: Open PL/I Built-ins


HBOUND Function

Purpose

Returns a fixed-point binary integer that is the upper bound of a specified dimension of an array.

Syntax

HBOUND(x[,n])

Parameters

x is an array variable and n is an integer constant indicating the nth dimension of x.

Description

The HBOUND function returns a fixed-point binary integer that is the upper bound of a specified dimension of an array x. This allows you to determine the upper bound of an array with * extents.

n is the specified dimension of the array. If n is not present, 1 is assumed. When present, n must be greater than zero and less than or equal to the number of dimensions declared.

The precision of the result is Fixed Binary(31).

Examples

DECLARE R FIXED BINARY;
DECLARE A(3:5,2,-10:10,4:7);
   .
   .
   .
R = HBOUND(A,1);     /*R = 5*/
   .
   .
   .
R = HBOUND(A,2);     /*R = 2*/
   .
   .
   .

Restrictions

The HBOUND function is now supported with expression arguments.

Parent topic: Open PL/I Built-ins


HEX Function

Purpose

Returns the bytes that contain a variable as a hexidecimal character string.

Syntax

HEX(x,y)

Parameters

x is a variable and y is an expression that must have a nonvarying character type.

Description

HEX returns the hexidecimal representation of the bytes that contain x. Its length is 2 * size(x) when x is the only parameter, i.e. INDEX(x). When there is a second parameter, i.e. INDEX(x,y), it returns a hexidecimal character string that contains x with y inserted between every set of eight characters. Its length is 2 * size(x) + ((size(x) - 1)/4).

Examples

dcl s char (32) varying;

   s = 'The witch cast a terrible spell.';

    put skip list (hex(s));
    put skip list (hex(s,'+'));

On big-endian machines it will print:

002054686520776974636820636173742061207465727269626C65207370656C6C2E
00205468+65207769+74636820+63617374+20612074+65727269+626C6520+7370656C+6C2E

On little-endian machines it will print:

200054686520776974636820636173742061207465727269626C65207370656C6C2E
20005468+65207769+74636820+63617374+20612074+65727269+626C6520+7370656C+6C2E

Restrictions

None.

Parent topic: Open PL/I Built-ins


HIGH Function

Purpose

Returns a character string made up of the highest character in the collating sequence.

Syntax

HIGH(x)

Parameters

x is an expression whose value is a non-negative integer.

Description

The HIGH function returns a character string of length x, in which each character is the highest character in the collating sequence (ASCII = hex 7F).

The HIGH function uses a 256-byte collating string.

The value of x must be non-negative. If x = 0, the result is the null character string.

Examples

HIGH(3)    /* Returns a character string whose length
                  is equal to 3 characters and in which
                  each character is hexadecimal 7F. */

Restrictions

None.

Parent topic: Open PL/I Built-ins


IMAG pseudovariable Function

Purpose

Assigns a real value or the real part of a complex value to the coefficient of the imaginary part of the specified reference.

Syntax

IMAG(x)

Parameters

x is a complex reference.

Restrictions

None.

Parent topic: Open PL/I Built-ins


INDEX Function

Purpose

Searches a string for a specified substring and returns a fixed binary integer value indicating its position.

Syntax

INDEX(s,c,l)

Parameters

s and c are both either character or bit strings, and c may be a substring of s. l is a third optional parameter which specifies the location in s from which to start searching.

Description

The INDEX function searches a string, s, for a specified substring, c, and returns an integer value indicating the position of c within s. l specifies the location in the string from which the search begins.

If either s or c is a null string, the result is zero. If the substring c is not contained within s, the result is zero; otherwise, the result is an integer indicating the position within s of the leftmost character or bit (if s and c are bit strings) of the substring c. The result precision is Fixed Binary(15).

l must have a computational type and is converted to Fixed Binary(31,0). If l is less than 1 or if l is greater than 1 + length(s), the STRINGRANGE condition is raised, and the result is zero.

Examples

Example of INDEX(s,c):

dcl s char (40) ;
    dcl i fixed bin (15);

    s = 'dmf plb cp js acb ltt dsa';
    i = index(s, 'd');
    put skip list (substr(s, i, 3));

will print:

dmf

Example of INDEX(s,c,l):

dcl s char (40) ;
    dcl i fixed bin (15);

    s = 'dmf plb cp js acb ltt dsa';
    i = index(s, 'd', 5);
    put skip list (substr(s, i, 3));

will print:

dsa

Restrictions

None.

Parent topic: Open PL/I Built-ins


INT Function

Purpose

Interprets specified storage as a signed integer and returns the value of that integer.

Syntax

INT(expression[,position[,length]])

Parameters

expression is a scalar expression or reference to connected storage. expression cannot be an array, structure, or named constant. position is a positive integer value specifying the position of the first bit in the field; length is a positive integer value in the range 0–32 specifying the length of the field.

Description

The INT function interprets the storage specified as a signed integer and returns the value of that integer. the INT function does not perform conversion, so that the value returned depends on the data type of the variable contained in the specified storage.

If position is specified, its minimum value is 1 and its maximum value is the length in bits of the storage specified by expression. If position is omitted, the default value is 1.

If length is specified, its minimum value is 0 and its maximum value is the length in bits of the storage specified by expression, less the value of position. If length is omitted, the default value is equal to the number of bits from the bit indicated by position to the end of the storage specified by expression.

If position and length are not specified, the length of the storage referenced by expression cannot exceed 32 bits.

INT returns a value of type Fixed Bin(31). If the field has a length of zero, INT returns zero.

INT and POSINT are identical functions, except that POSINT returns an unsigned integer.

The result of this function is dependent on the native byte ordering of the hardware you are using. For this reason, the use of this function may not be portable across different platforms.

Examples

DCL A BIT(32);

   A = '12345678'B4;
   PUT SKIP LIST(INT(A,5,4));
END TEST;

Restrictions

None.

Parent topic: Open PL/I Built-ins
Related information
POSINT


LBOUND Function

Purpose

Returns a fixed binary integer value giving the lower bound of the specified dimension of an array.

Syntax

LBOUND(x[,n])

Parameters

x is an array variable, and n is an integer constant indicating the dimension of x.

Description

The LBOUND function returns an integer value that gives the lower bound of the nth dimension of x. This is useful for arrays with * extents.

n is the specified dimension of the array. If n is not present, 1 is assumed. When present, n must be greater than zero and less than or equal to the number of dimensions declared.

Examples

DECLARE R FIXED BINARY;
DECLARE A(3:5,2,-10:10,4:7);
   .
   .
   .
R = LBOUND(A,1);     /*R = 3*/
   .
   .
   .
R = LBOUND(A,2);    /*R = 1*/
   .
   .
   .

Restrictions

The LBOUND function is not supported with expression arguments.

Parent topic: Open PL/I Built-ins


LENGTH Function

Purpose

Returns a Fixed Binary integer that gives the number of characters or bits in the specified string.

Syntax

LENGTH(s)

Parameters

s is a Character, Bit String, or Picture value. If s is a binary value, it is converted to a Bit string. If it is a decimal value, it is converted to a character string.

Description

The LENGTH function returns an integer that gives the number of characters or bits in the string s, where s is either a character string or a bit string. For character varying strings, this is the length of the string currently stored in the variable.

The precision of the result is Fixed Binary(15). A null string has length zero.

Examples

    dcl s char (40) varying;
    dcl t char (40) ;

    s = 'The Lawn, 22-30 Old Bath Road';

    put skip list ('length(s) is: ', length(s));   /* char var */
    put skip list ('length(t) is: ', length(t));   /* char       */

will print:

length(s) is:          29
length(t) is:          40

Restrictions

None.

Parent topic: Open PL/I Built-ins


LEFT Function

Purpose

Returns the result of inserting a string to the left of another string with a certain length. It can be padded on the right with a character.

Syntax

LEFT(s,l,c)

Parameters

s
A string that is inserted to the left of another sting. It must have a computational type and a character type. If it does not have a character type, it is converted to character.
l
The length of a string to the left of which s is inserted. It must have a computational type and a character type and is converted to Fixed Binary(31,0).
c
Optional padding character, inserted to the right of the string. It must have a nonvarying character type.

Description

LEFT returns a string which is formed by inserting a string s to the left of another string with length l. An optional padding character c can be attached to the right.

Examples

dcl s char (40) var;
    dcl t char (40) var;

    s = 'This string is 33 characters long';
    t = left(s, 40, '+');
    put skip list (t);

will print:

This string is 33 characters long+++++++

Restrictions

None.

Parent topic: Open PL/I Built-ins


LINENO Function

Purpose

Returns a Fixed Binary integer that gives the line number of an open file control block with the specified PRINT attribute.

Syntax

LINENO(x)

Parameters

x is a file value representing a file control block.

Description

The LINENO function returns an integer that gives the line number of an open file control block identified by x.

The precision of the result is Fixed Binary(15).

x must identify an open file control block with the PRINT attribute.

Examples

DECLARE X FILE;
   .
   .
   .
CURRENT = LINENO(X);  /* GET CORRECT LINE # */

Restrictions

None.

Parent topic: Open PL/I Built-ins


LOG Function

Purpose

Returns the natural logarithm of an arithmetic expression.

Syntax

LOG(x)

Parameters

x is a floating-point value greater than zero.

Description

The LOG function returns the natural logarithm of x. Note that LOG(x) is the inverse of EXP(x), that is, LOG(EXP(x)) = x = EXP(LOG(x)).

The result has the same data type as x.

Examples

LOG(7.389056)    /* returns 2 */

Restrictions

An LOG operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


LOG10 Function

Purpose

Returns the logarithm of an arithmetic expression to the base 10.

Syntax

LOG10(x)

Parameters

x is a floating-point value greater than zero.

Description

The LOG10 function returns the logarithm of x to the base 10. Note that LOG10(x) is the inverse of 10**x, that is, 10**LOG10(x) = x = LOG10(10**x).

The result has the same data type as x.

Examples

LOG10(100.0)   /* returns 2 */

Restrictions

A LOG10 operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


LOG2 Function

Purpose

Returns the logarithm of an arithmetic expression to the base 2.

Syntax

LOG2(x)

Parameters

x is a floating-point value greater than zero.

Description

The LOG2 function returns the logarithm of x to the base 2. Note that LOG2(x) is the inverse of 2**x, that is, 2**LOG2(x) = x = LOG2(2**x).

The result has the same data type as x.

Examples

LOG2(0.5)    /* returns -1 */

Restrictions

An LOG2 operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


LOW Function

Purpose

Returns a character string made up of the lowest character in the collating sequence.

Syntax

LOW(x)

Parameters

x is an expression whose value is a non-negative integer.

Description

The LOW function returns a character string of length x, in which each character is the lowest character in the collating sequence (hex 00).

The LOW function uses a 256-byte collating string.

The value of x must be non-negative. If x = 0, the result is the null character string.

Examples

LOW(3)    /* Returns a character string whose length
                 is equal to 3 characters and in which
                 each character is hexadecimal 00. */

Restrictions

None.

Parent topic: Open PL/I Built-ins


LOWERCASE Function

Purpose

Returns a character string with all the alphabetic characters from A to Z converted to their lowercase equivalent.

Syntax

LOWERCASE(x)

Parameters

x is an expression. It can be converted to character.

Examples

dcl s char (40) varying;

    s = 'Lead is an element with the symbol Pb';
    s = lowercase(s);
    put skip list (s);

will print:

lead is an element with the symbol pb

Restrictions

None.

Parent topic: Open PL/I Built-ins


LPIPARAMCOUNT Function

Purpose

Returns a fixed binary(15) integer that represents the number of parameters passed to a PL/I subroutine.

Syntax

LPIPARAMCOUNT()

or

LPIPARAMCOUNT

Description

The LPIPARAMCOUNT built-in function returns the number of parametes passed to an Open PL/I procedure from another PL/I procedure. To be able to use this function, the calling procedure has to be compiled with the -paramount compile time option, or that procedure has to have an entry name attribute OPTIONS(LPIPARAMCOUNT).

Examples

main: procedure options(main);
declare subr entry;
...
call subr();
...
call subr(x,y,z);
end main;

subr: procedure(p1,p2,p3,p4);
...
declare no_of_args fixed bin(15);
no_of_args = lpiparamcount();
put skip list ('Number of arguments passed to SUBR:  ',
                no_of_args);
end subr;

If the main program is compiled with the -paramcount option, the above example will print:

Number of arguments passed to SUBR: 0
Number of arguments passed to SUBR: 3

Restrictions

None.

Parent topic: Open PL/I Built-ins


MAX Function

Purpose

Returns the greatest of one or more values.

Syntax

MAX(x,…)

Parameters

x and any subsequent values are arithmetic values.

Description

The MAX function returns the largest of a set of arithmetic values. x and any subsequent values are converted to a common arithmetic data type (using the conversion rules for arithmetic infix operators) before the operation is performed. x and any subsequent values cannot be string values. The result is the largest of these converted values and has the common arithmetic data type.

Examples

MAX(5, -118, 1)        /* returns 5 */
MAX(12.3, 13, 9.68)    /* returns 13.0 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


MAXLENGTH Function

Purpose

Returns the maximum length of a string.

Syntax

MAXLENGTH(x)

Parameters

x is an expression that must have a computational type and should have a string type. Otherwise, it is converted to character.

Examples

dcl s char (40) varying;
    dcl t char (40) ;

    s = 'The Lawn, 22-30 Old Bath Road';

    put skip list ('maxlength(s) is: ', maxlength(s));   /* char var */
    put skip list ('maxlength(t) is: ', maxlength(t));   /* char       */

will print:

maxlength(s) is:               40
maxlength(t) is:               40

Restrictions

None.

Parent topic: Open PL/I Built-ins


MIN Function

Purpose

Returns the smallest of one or more values.

Syntax

MIN(x,...)

Parameters

x and any subsequent values are arithmetic values.

Description

The MIN function returns the smallest of a set of arithmetic values. x and any subsequent values are converted to a common arithmetic data type (using the conversion rules for arithmetic infix operators) before the operation is performed. x and any subsequent values cannot be string values. The result is the smallest of these converted values and has the common arithmetic data type.

Examples

MIN(5,-118, 1)         /* returns -118 */
MIN(12.3, 11, 9.68)    /* returns 9.68 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


MOD Function

Purpose

Returns the truncated remainder of x divided by y.

Syntax

MOD(x,y)

Parameters

x and y are arithmetic values.

Description

The MOD function returns the truncated remainder of x divided by y. The result is x-y*FLOOR(x/y) and has the common data type of x and y.

To determine the precision of the result, let (px,qx) and (py,qy) represent the precision of x and y, respectively. If the common type of x and y is fixed point, the precision of the result is:

(MIN(n,py-qy+MAX(qx,qy)),MAX(qx,qy))

Otherwise, the precision of the result is MAX(px,py). n is the maximum precision allowed for the common type of x and y. For details on maximum precisions, see your Open PL/I User's Guide.

Examples

MOD(15,2)    /* returns 1 */

Restrictions

The value of y must not be 0.

An MOD operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


MPSTR Function

Purpose

Truncates a string at a logical boundary and returns a mixed character string. It does not truncate a double-byte character between bytes. The length of the returned string is equal to the length of the expression x, or to the value specified by y.

Syntax

MPSTR(x,r[,y])

Parameters

x, y, and r are expressions.

Description

x yields the character string result. The value of x is converted to character if necessary.

r yields a character result. The expression cannot be GRAPHIC and is converted to character if necessary. r specifies the rules to be used for processing the string.

The characters that can be used in r and the rules for them are as follows:

V or v
Validates the mixed string x and returns a mixed string.
S or s
Removes any null DBCS strings, creates a new string, and returns a mixed string.

If both V and S are specified, V takes precedence over S, regardless of the order in which they were specified. If S is specified without V, the string x is assumed to be a valid string. If the string is not valid, results are undefined.

y, if necessary, is converted to a real fixed point binary value. If y is omitted the length is determined by the rules for type conversion. The value of y cannot be negative.

If y = 0, the result is the null character string. If y is greater than the length needed to contain x, the result is padded with blanks. If y is less than the length needed to contain x, the result is truncated by discarding excess characters from the right (if they are SBCS characters), or by discarding as many DBCS characters (2-byte pairs) as needed.

Restrictions

r is ignored on Intel and AIX.

Parent topic: Open PL/I Built-ins


MULTIPLY Function

Purpose

Multiplies an arithmetic value by an arithmetic value and returns the product with a specified precision and an optionally specified scale factor.

Syntax

MULTIPLY(x,y,p)

or

MULTIPLY(x,y,p,q)

Parameters

x and y are arithmetic values, and p and q are integer constants that represent precision and scale factor, respectively.

Description

The MULTIPLY function multiplies an arithmetic value, x, by an arithmetic value, y, and returns the product with a specified precision p and an optionally specified scale factor q.

The result is x*y, having the common data type of x and y.

The precision of the result is (p,q) or (p). In the latter case, q equals zero.

Examples

DECLARE (LENGTH, WIDTH) FIXED BINARY(15);
   .
   .
   .
PUT LIST ('TOTAL AREA IS'||MULTIPLY (LENGTH, WIDTH, 31));

Restrictions

The parameter q must not occur unless the result type is decimal.

Parent topic: Open PL/I Built-ins


NULL Function

Purpose

Returns a null pointer value.

Syntax

NULL()

or

NULL

The second syntax form can be used only when the BUILTIN attribute is specified.

Description

The NULL function returns a null pointer value. The default NULL value is -1 (all 1 bits). This value is a fictitious address, which is distinct from any valid pointer address.

The -setnull compiler option allows you to designate a particular null pointer value for the NULL function at compile time. For a description of the -setnull compiler option, see your Open PL/I User's Guide.

Examples

IF LAST_POINTER = NULL() THEN CALL FINISH;

In this example, the IF statement determines whether the pointer variable LAST_POINTER is null; if so, the CALL statement executes.

Restrictions

None.

Parent topic: Open PL/I Built-ins


OFFSET Function

Purpose

Returns an offset value relative to an area and derived from a pointer.

Syntax

OFFSET(p,a)

Parameters

p is a pointer reference identifying a based variable; a is the area containing the based variable.

Description

The OFFSET function returns an offset value that is the relative byte offset of a based variable stored within an area variable.

If p is the null pointer value, the OFFSET function returns the null offset value.

Examples

DECLARE (A, B) AREA;
DECLARE (A1, A2) CHAR(20) BASED;
DECLARE (P1, P2) POINTER;
DECLARE (01, 02) OFFSET(A);
DECLARE (03, 04) OFFSET(B);

ALLOCATE A1 IN(A) SET(01);
ALLOCATE A2 IN(A) SET(02);

B = A;                /* assign area */

P1 = ADDR(01->A1);    /* address of A1 in A */
P2 = POINTER(02, B);  /* address of A2 in B */

03 = OFFSET(P1, A);   /* offset value of A1 -
                         same in A and B */
04 = OFFSET(P2, B);   /* offset value of A2 -
                         same in A and B */

Restrictions

None.

Parent topic: Open PL/I Built-ins


ONCHAR Function

Purpose

Returns a character string of length 1, containing the character that caused the CONVERSION condition to be signaled.

Syntax

ONCHAR()

or

ONCHAR

The second syntax form can be used only when ONCHAR has been explicitly declared with the BUILTIN attribute.

Description

The ONCHAR function returns a character string of length 1, containing the character that caused the CONVERSION condition to be signaled.

The ONCHAR function can be used in an ON-unit established for a CONVERSION condition. It can also be used for an ERROR ON-unit that obtains control as the result of unsuccessful error correction in the CONVERSION ON-unit.

Examples

DCL I FIXED BIN(15);
ON CONVERSION BEGIN;
 PUT LIST ('Incorrect character is:',ONCHAR());
END;

I = '34Z9';

In the above example, the program will display the character "Z" that caused the conversion error to occur.

Restrictions

None.

Parent topic: Open PL/I Built-ins


ONCODE Function

Purpose

Returns a fixed-point binary integer that is the status value of the most recent run-time error that signaled the current ON condition.

Syntax

ONCODE()

or

ONCODE

The second syntax form can be used only when the BUILTIN attribute is specified.

Description

The ONCODE function returns a binary integer that is the status value of the most recent run-time error that signaled the current ON condition. The result has an implementation-defined precision. (For details on precisions, see your Open PL/I User's Guide.) The ONCODE function can be used in any ON-unit to ascertain the exact error that caused the condition. Used within any context other than an ON-unit, the ONCODE function returns a zero.

For the values of the run-time errors that signal particular ON conditions, see your Open PL/I User's Guide.

Examples

ON ERROR BEGIN;
   PUT EDIT ('ERROR NUMBER', ONCODE()) (SKIP, A, F(10));
END;

Restrictions

None.

Parent topic: Open PL/I Built-ins


ONCOUNT Function

Purpose

ONCOUNT returns an unscaled real fixed binary value specifying the number of conditions that remain to be handled when an ON-unit is entered.

Syntax

ONCOUNT[()]

Parameters

None.

Description

ONCOUNT can be used in any ON-unit, or any dynamic descendant of an ON-unit. If ONCOUNT is used elsewhere, zero is returned.

Restrictions

None.

Parent topic: Open PL/I Built-ins


ONFILE Function

Purpose

Returns the name of a file constant for which the most recent ENDPAGE, ENDFILE, KEY, or UNDEFINEDFILE condition was signaled.

Syntax

ONFILE()

Description

The ONFILE function returns the name of a file constant for which the most recent ENDPAGE, ENDFILE, KEY, or UNDEFINEDFILE condition was signaled. The ONFILE function can also be used in an ERROR ON-unit that gets control as a consequence of the default Open PL/I action for file-related errors. (The default action for file-related errors is to signal the ERROR condition.)

The returned value is a varying length character string.

On some systems, you may need to specify the -defext compile-time option for ONFILE to return the correct value. For specific information, see your Open PL/I User's Guide.

Restrictions

If referenced outside an ON-unit or within an ON-unit that is executed as a result of a SIGNAL statement, the ONFILE function returns a null string.

If used outside an ON-unit or within an ON-unit that has been invoked as the result of a condition unrelated to any file, the ONFILE function returns a null string.

All other uses of such files must be in other modules compiled without the -defext compile-time option or declared with the GLOBALREF attribute.

Parent topic: Open PL/I Built-ins
Related information
GLOBALREF


ONKEY Function

Purpose

Returns the key value that precipitated the signaling of the condition during an input/output operation to a file that is being accessed.

Syntax

ONKEY()

Description

The ONKEY function returns the key value that precipitated the signaling of the KEY condition during an input/output operation to a file that is being accessed by key.

The ONKEY function can be used in an ON-unit established for the ENDFILE, KEY, RECORD, and UNDEFINEDFILE conditions. It can also be used for an ERROR ON-unit that obtains control as a result of the default Open PL/I action for the KEY condition. (The default action is to signal the ERROR condition.)

The returned value is a varying length character string.

Examples

ON KEY(DFILE) BEGIN;
 PUTEDIT ('DFILE KEY',ONKEY(),'NOT FOUND')(SKIP,3 A);
END;

Restrictions

If the ONKEY function is referenced outside an ON-unit or within an ON-unit executed as a consequence of a condition not related to a file being accessed by key, it will return the null string.

Parent topic: Open PL/I Built-ins


ONLOC Function

Purpose

Returns the name of an entry in which a condition was raised.

Syntax

ONLOC()

Description

When the ONLOC function is called under the control of an ON-unit (that is, from the ON-unit or any procedure called by the ON-unit), it returns a character string whose value is the name of the entry in which the condition was raised that caused the ON-unit to be invoked. If a call to the ONLOC function is made not under the control of an ON-unit, ONLOC() returns the null string.

Examples

SUBPROG: PROCEDURE(X) RETURNS(FLOAT BIN(23));
   DECLARE X FLOAT BIN(23);
   ON ERROR BEGIN;
      PUT LIST('Error at ', ONLOC());
      PUT SKIP;
      GOTO HIGHER_LEVEL_EXIT;
      END;
   X = X / (X-X);
   RETURN(X);
END SUBPROG;

Execution of this subprogram causes the following text to be displayed:

Error at SUBPROG

Restrictions

This feature is currently available only on Sun SPARC Solaris 2.

Parent topic: Open PL/I Built-ins


ONSOURCE Function

Purpose

Returns a character string whose value is the context of the field that was being processed when the CONVERSION condition was signaled.

Syntax

ONSOURCE()

or

ONSOURCE

The second syntax form can be used only when ONSOURCE has been explicitly declared with the BUILTIN attribute.

Description

The ONSOURCE function returns a character string whose value is the context of the field that was being processed when the CONVERSION condition was signaled.

The ONSOURCE function can be used in an ON-unit established for a CONVERSION condition. It can also be used for an ERROR ON-unit that obtains control as the result of unsuccessful error correction in the CONVERSION ON-unit.

The returned value is a varying-length character string.

Examples

DCL BT BIT(4);
ON CONVERSION BEGIN;
PUT LIST ('Incorrect string is:',ONSOURCE());
END;

T = '1021';

In the above example, the program will display the string "1021" that caused the conversion error to occur because only characters 0 and 1 are valid for a bit data type.

Restrictions

None.

Parent topic: Open PL/I Built-ins


PACKAGENAME Function

Purpose

Since packages are not supported, the name of the outermost procedure is returned.

Syntax

PACKAGENAME()

Examples

   /* Since Open PL/I does not support Packages, the name of the outermost  */
   /* procedure is aways returned for the PACKAGENAME() built-in.          */

Micro: proc options(main);

    call Focus();

    Focus: proc;
           put skip list (packagename() || ' ' || procedurename() );
    end;

end;

will print:

MICRO FOCUS
Parent topic: Open PL/I Built-ins


PAGENO Function

Purpose

Returns a fixed binary integer that gives the current page number in the specified file.

Syntax

PAGENO(x)

Parameters

x is a file value that identifies a file control block.

Description

The PAGENO function returns an integer that gives the current page number in the file control block identified by x.

The precision of the result is Fixed Binary(15).

If x does not identify an open file control block with the PRINT attribute, the program is in error. This implementation of PL/I may not diagnose all violations of this restriction.

For a description of the PAGENO function's use as a pseudovariable, see the section Assignment in the chapter Statements.

Examples

DECLARE X FILE;
   .
   .
   .
CURRENT = PAGENO(X);  /* GET CURRENT PAGE # */

Restrictions

None.

Parent topic: Open PL/I Built-ins
Related information
Assignment


PLIRETC Subroutine

Purpose

Sets the Open PL/I return code.

Syntax

CALL PLIRETC(x);

Parameters

x is an arithmetic value.

Description

The PLIRETC built-in subroutine sets a return code that can be examined using the PLIRETV built-in function. When the program ends, the last value used in a call to PLIRETC is returned to the system as the program's exit status.

The argument to PLIRETC is converted to a Fixed Binary (31) value, but the actual precision of the value that is stored and returned to the system may be lower, depending on the implementation. For details on precisions, see your Open PL/I User's Guide.

Examples

ON ERROR CALL PLIRETC (1);

Restrictions

None.

Parent topic: Open PL/I Built-ins
Related information
PLIRETV Function


PLIRETV Function

Purpose

Returns a fixed binary integer that is the Open PL/I return code.

Syntax

PLIRETV()

or

PLIRETV

Description

The PLIRETV function returns the most recent value specified by a CALL PLIRETC statement. Note that the precision of the returned value may be smaller than that of the value passed to PLIRETC, and the precision of the value returned to the system at program termination may be even smaller than that returned by PLIRETV, depending on the implementation. (For more information on this implementation, see your Open PL/I User's Guide.) For example, the PLIRETC and PLIRETV routines may preserve their fixed binary (31) value, but the value may be truncated (using the MOD function) to only the rightmost byte of that value when the program exits.

Examples

CALL READ_LINE (BUFFER);
IF PLIRETV ()
THEN PUT LIST ("ERROR ON INPUT");

Restrictions

None.

Parent topic: Open PL/I Built-ins
Related information
PLIRETC Function


PLISRTx Subroutines

Purpose

These routines enable data to be sorted, with source and destination as indicated by the following table:

 | Input Data From | Output Data To
PLISRTA | Input file | Output file
PLISRTB | Procedure | Output file
PLISRTC | Input file | Procedure
PLISRTD | Procedure | Procedure
RECORD | Input file | ??

Syntax

CALL PLISRTA(fields–spec, records-spec, storage,
             ret-code [,prefix][,msg-level]
             [,algorithm]);
CALL PLISRTB(fields-spec, records-spec, storage,
             ret-code, input-proc[,prefix][msg-level][,algorithm]);
CALL PLISRTC(fields-spec, records-spec, storage,
             ret-code, output-proc [,prefix][,msg-level]
             [,algorithm]);
CALL PLISRTD(fields-spec, records-spec, storage,
             ret-code, input-proc, output-proc [,prefix]
             [,msg-level][,algorithm]);

Parameters

fields-spec is a character-string having the following format:

` box SORT box FIELDS=(pos,len,type,seq,[,posj,lenj,typej,seqj]...) [,options-list] box '

box, in each of the three instances, represents one or more space characters. These are the only spaces that may occur in the string.

  • pos is the start position of a sort key-field with the records. The position is given in bytes, with 1 representing the first byte.
  • len is the length of the key in bytes.
  • type is the key type, as follows:
    CH | character string
    ZD | pictured
    PD | fixed decimal
    Fl | fixed binary
    BI | bit string
    FL | float binary
  • seq must be A or D, indicating whether to sort with ascending or descending values of this key.

    The following items can be specified in the options-list:

    FILSZ=n | Specifies the number of records in the sort. This option is ignored.
    SKIPREC=n | Specifies that n records at the beginning of the input file are to be skipped.
    CKPT or CHKPT | Specifies that checkpoints are to be taken. This option is ignored.
    EQUALS | Specifies a stable sort algorithm (that is, that records with identical key values are to be kept in the same order they have in the input file or were given by the input procedure.
    NOEQUALS | Specifies that a stable sort algorithm will not be used. This is the default.
    DYNALLOC=(d,n) | Specifies the intermediate storage. This option

records–spec is a character-string having the following format:

` box RECORD box TYPE=rectype,LENGTH=(len)[,ftype] box '

box, in each of the three instances, represents one or more space characters. These are the only spaces that may occur in the string.

  • rectypeis F or V, indicating fixed-length records or variable-length ASCII records, respectively.
  • len specifies the length of the records to be sorted.
  • ftype is INDEXED. If ftype is omitted, CONSECUTIVE is assumed.

storage: This argument is ignored.

Description

The input records are sorted as specified by the parameters and written to the output file or passed to the output procedure, as appropriate.

If an input or output procedure is used, it is called repeatedly by the sort subroutine, once for each record involved in the sort. Hence, the procedure must be written so as to process one record at a time. These procedures are ordinary PL/I procedures, and all PL/I language rules apply. Any contained AUTOMATIC variables are reinitialized at each invocation of the procedure and any allocated BASED or CONTROLLED variables are freed when the procedure returns.

An input procedure must have the form:

IN_PROC: PROCEDURE RETURNS(CHAR(len));
   DECLARE S CHAR(len);
   IF LAST_REC THEN DO;
      CALL PLIRETC(8);
/* must tell the sort routine all records have been sent */
      RETURN(S);
      END;
   ELSE DO;
      /* code to produce the record goes here */
      CALL PLIRETC(12);
/* tell the sort routine this is not the last record */
      RETURN(S);
      END;
END IN_PROC;

An output procedure must have the form:

OUT_PROC: PROCEDURE(S);
   DECLARE S CHAR(*);
   /* code to process the sorted record goes here */
   CALL PLIRETC(4);
/* tell the sort routine to continue sending records */
END OUT_PROC;

In the output procedure, use CALL PLI RETC(16); to tell the sort routine to terminate unsuccessfully.

Examples

Example 1

test: proc options(main);

   /* Examples of SORT Bifs */
   /* Uses a data file of name 'SRT1_IN', which must exist.
   /* The contents of 'SRT1_IN' are shown below. */

   dcl  (plisrta, plisrtb, plisrtc, plisrtd) builtin;

   declare ret_code fixed bin(31);
   declare (input_proc,output_proc) entry;
   declare eof bit(1);
   declare x file;
   declare rec char(20);

   put skip list('Calling srta -----------------------------');
   call plisrta(' sort fields=(1,10,ch,a),equals',
             ' record type=F,length=(20) ',
             0 ,              /* strg */
             ret_code,
             'SRT1',         /* data name prefix */
             'AP',           /* msg level */
             'xxxx'          /* sort method */);
   put skip list('result code is ', ret_code);

   /* display output file of above */
   open file(x) record title('SRT1OUT');
   eof = '0'b;
   on endfile(x) eof='1'b;
   read file(x) into(rec);
   do while(eof = '0'b);
      put skip list(rec);
      read file(x) into(rec);
      end;
   close file(x);
   revert endfile(x);

   put skip(2) list('Calling srtb --------------------------------');
   call plisrtb(' sort fields=(1,10,ch,a)',
             ' record type=f,length=(20) ',
             0 ,              /* strg */
             ret_code,
             input_proc,
             ,               /* data name prefix */
             'AP',           /* msg level */
             'xxxx'          /* sort method */);
   put skip list('result code is ',ret_code);
   /* display output file of above */
   open file(x) stream title('SORTOUT');
   eof = '0'b1;
   on endfile(x) eof='1'b1;
   read file(x) into(rec);
   do while(^eof);
      put skip list(rec);
      read file(x) into(rec);
      end;
   close file(x);
   revert endfile(x);

   put skip(2) list('Calling srtc --------------------------------');
   call plisrtc(' sort fields=(1,10,ch,a) ',
             ' record type=f,length=(20) ',
             0 ,              /* strg */
             ret_code,
             output_proc,
             'SRT1',          /* data name prefix */
             'AP',            /* msg level */
             'xxxx'           /* sort method */);
   put skip list('result code is ',ret_code);

   put skip(2) list('Calling srtd --------------------------------');
   call plisrtd(' sort fields=(1,10,ch,a),skiprec=3 ',
             ' record type=f,length=(20) ',
             0 ,              /* strg */
             ret_code,
             input_proc,
             output_proc,
             ,                /* data name prefix */
             'AP',            /* msg level */
             'xxxx'          /* sort method */);
   put skip list('result code is ',ret_code);

end test;

input_proc: procedure returns(char(20));
   dcl x char(20);
   dcl cnt fixed bin(31) static internal initial(0);
   dcl rec(1:5) char(20) static internal initial (
        'abc2', 'abc4', 'abc1', 'abc6', 'abc3');

   cnt = cnt + 1;
   if cnt <= 5 then do;
      x=rec(cnt);
      call pliretc(12);
      end;
   else do;
      x = '';
      call pliretc(8);   /* no more */
      cnt = 0;
      end;
   return(x);
end input_proc;

output_proc: procedure(x);
   dcl x char(*);

   put skip list(x);
   call pliretc(4);    /* ready for more */
end output_proc;

Example 2

test: proc options(main);

   /* Test of SORT Bif using a indexed file as input.
   /* The input file is 1st created by this program prior to the sort. */

/*
/* How to compile/link
/*
/* mfplx srt2.pl1 -defext -cisam
*/

/* Output of this program:
/*
/* Creating a indexed file with following records:
/*
/* Calling plisrtc ---------------------------------------
/* Sorting on 2nd column ASCENDING, 1st column DECENDING
/*    Boston                             abc
/*    Albany                             ccc
/*    Westboro                           xyz
/*    Milford                            xyz
/*    Acton                              xyz
/*
/**/

   dcl   plisrtd builtin;
   declare ret_code fixed bin(31);
   declare (input_proc,output_proc) entry;

   dcl SORTIN direct env(vsam keylength(8) keyloc (5) recsize(50));
   dcl rec char(50);

   %replace KEY2 by 40;       /* be sure to change other references */
   %replace KEY2_LEN by 3;    /* be sure to change other references */

   put skip list('Creating a indexed file with following records:');
   open file(SORTIN) output;

   rec = ' ';
   substr(rec,KEY2,KEY2_LEN) = 'ccc';
   write file(SORTIN) from(rec) keyfrom('Albany');

   rec = ' ';
   substr(rec,KEY2,KEY2_LEN) = 'xyz';
   write file(SORTIN) from(rec) keyfrom('Acton');

   rec = ' ';
   substr(rec,KEY2,KEY2_LEN) = 'abc';
   write file(SORTIN) from(rec) keyfrom('Boston');

   rec = ' ';
   substr(rec,KEY2,KEY2_LEN) = 'xyz';
   write file(SORTIN) from(rec) keyfrom('Westboro');

   rec = ' ';
   substr(rec,KEY2,KEY2_LEN) = 'xyz';
   write file(SORTIN) from(rec) keyfrom('Milford');
   close file(SORTIN);
   put skip;

   put skip list('Calling plisrtc ---------------------------------------');
   put skip list('Sorting on 2nd column ASCENDING, 1st column DECENDING');
   call plisrtc(' sort fields=(40,3,ch,a,5,8,ch,d) ',
             ' record type=f,length(50),indexed ',
             0 ,            /* strg */
             ret_code,      /* result status */
             output_proc,
             ,              /* data name prefix */
             'AP',          /* msg level */
             'xxxx'         /* sort method */);
   put skip list('result code is ',ret_code);

end test;

output_proc: procedure(x);
   dcl x char(*);

   put skip list(x);
   call pliretc(4);    /* ready for more */
end output_proc;

Restrictions

Open PLI supports up to 64 sort keys. All sort control keys must fit into 1024 bytes.

Parent topic: Open PL/I Built-ins
Related information
Using Open PL/I with Other Software Products


POINTER Function

Purpose

Returns a pointer value specifying the generation of a based variable in an area.

Syntax

POINTER(o,a)

Abbreviation(s): PTR for POINTER.

Parameters

o is an offset reference that specifies the generation of a based variable in the area identified by a.

Description

If o is the null offset value, the POINTER function returns the null pointer value; otherwise, the value of o must be the offset of some based variable's allocation in an area, but not necessarily in a.

The result returned by the POINTER function is the sum of the offset value, o, plus the address of the beginning of the area, a.

Examples

DECLARE (A, B) AREA;
DECLARE (A1, A2) CHAR(20) BASED;
DECLARE (P1, P2) POINTER;
DECLARE (01, 02) OFFSET;

ALLOCATE A1 IN(A) SET(01);
ALLOCATE A2 IN(A) SET(02);

B = A;                  /* assign area */

P1 = POINTER(01, B);    /* address of A1 in B */
P2 = POINTER(02, B);    /* address of A2 in B */

Restrictions

None.

Parent topic: Open PL/I Built-ins


POINTERADD Function

Purpose

Increments (or decrements) a pointer value by an integer value.

Syntax

POINTERADD(x,y)

Abbreviation(s): PTRADD for POINTERADD.

Parameters

x is a pointer expression. y is a fixed binary(31) value or a value that can be converted to a fixed binary(31) value.

Description

The POINTERADD function returns a pointer value that is the pointer value x incremented by y bytes (or decremented by y bytes if y is negative).

Examples

DECLARE A CHAR(10) BASED INIT('0123456789');
DECLARE B CHAR(3);
DECLARE P POINTER;
ALLOCATE A SET(P);
B = POINTERADD(P,3)->A;   /* This yields B = '345'. */

Restrictions

None.

Parent topic: Open PL/I Built-ins


POINTERDIFF / PTRDIFF Function

Purpose

Returns the difference between two pointers, which is FIXED BINARY(31,0).

Syntax

POINTERDIFF(x,y)

Parameters

x and y are expressions declared as POINTER.

Description

POINTERDIFF returns the difference between two pointers, which is FIXED BINARY(31,0). It can be abbreviated as PTRDIFF.

Restrictions

None.

Parent topic: Open PL/I Built-ins


POINTERSUBTRACT / PTRSUBTRACT

Purpose

Equivalent to POINTERADD(x,-y).

Syntax

POINTERSUBTRACT(x,y)

Parameters

x
A pointer expression.
y
Expression that has a computational type and is converted to FIXED BINARY(31,0).

Description

POINTERSUBTRACT is equivalent to POINTERADD(x,-y). It can be abbreviated as PTRSUBTRACT.

Restrictions

None.

Parent topic: Open PL/I Built-ins


POINTERVALUE Function

Purpose

Returns a pointer value that is the converted value of the specified expression.

Syntax

POINTERVALUE(x)

Abbreviation: PTRVALUE for POINTERVALUE.

Parameters

x is an expression. It must have either the HANDLE attribute, or have a computational type. If x has a computational type, it is converted to fixed binary.

Description

You can use POINTERVALUE(x) to initialize static pointer variables if x is a constant.

Restrictions

None.

Parent topic: Open PL/I Built-ins


POLY Function

Purpose

Returns a floating point value that is an approximation of a polynomial formed from the specified one-dimensional array expression. The returned value has the same attributes as the first argument.

Syntax

POLY(x,y)

Parameters

x is an array expression, and y is an element expression.

Description

x must be real float and y is converted to the attributes of x, if necessary.

If x has lower bound 0 and upper bound n, the result is a classic polynomial of degree n in y with coefficients given by x: x(0) + x(1)*y + x(2)*y**2 + ... + x(n)*y**n.

In the general case, where x has lower bound m and upper bound n, the result is the polynomial x(m) + x(m+1)*y + x(m+2)*y**2 + ... + x(n)*y**(n-m)

Parent topic: Open PL/I Built-ins


POSINT Function

Purpose

Interprets specified storage as an unsigned integer and returns the value of that integer.

Syntax

POSINT(expression[,position[,length]])

Parameters

expression is a scalar expression or reference to connected storage. expression cannot be an array, structure, or named constant. position is a positive integer value specifying the position of the first bit in the field; length is a positive integer value in the range 0 – 32 specifying the length of the field.

Description

The POSINT function interprets the storage specified as an unsigned integer and returns the value of that integer. The POSINT function does not perform conversion, so that the value returned depends on the data type of the variable contained in the specified storage.

If position is specified, its minimum value is 1 and its maximum value is the length in bits of the storage specified by expression. If position is omitted, the default value is 1.

If length is specified, its minimum value is 0 and its maximum value is the length in bits of the storage specified by expression, less the value of position. If length is omitted, the default value is equal to the number of bits from the bit indicated by position to the end of the storage specified by expression.

If position and length are not specified, the length of the storage referenced by expression cannot exceed 32 bits.

POSINT returns a value of type Fixed Bin(31). If the field has a length of zero, POSINT returns zero. Because POSINT returns an unsigned integer, it is possible for the value returned to be too large for assignment to Fixed Bin(31). The result of such an operation is undefined.

POSINT and INT are identical functions, except that INT returns a signed integer.

The result of this function is dependent on the native byte ordering of the hardware you are using. For this reason, the use of this function may not be portable across different platforms.

Examples

DCL A BIT(32);

   A = '12345678'B4;
   PUT SKIP LIST(POSINT(A,5,4));

END TEST;

Restrictions

None.

Parent topic: Open PL/I Built-ins
Related information
INT


PRECISION Function

Purpose

Returns the value of the specified expression using specified precsion.

Syntax

PRECISION(x,p[,q])

Abbreviation: PREC for PRECISION.

Parameters

x is an expression, and p and q are restricted expressions.

Description

p specifies the number of digits that the value of the expression x is to have after conversion.

q specifies the scaling factor of the result. For a fixed-point result, if q is omitted a scaling factor of zero is assumed. For a floating-point result, q must be omitted.

The base, mode, and scale of the returned value are the same as that of x.

Restrictions

None.

Parent topic: Open PL/I Built-ins


PROCEDURENAME() Function

Purpose

Returns the name of the most closely nested procedure as a character-string. PROCNAME() can be used equivalently.

Syntax

PROCEDURENAME();
or
PROCNAME();

Examples

Example 1:

myprog: proc options(main);

    dcl procedurename builtin;

    call sub1(procedurename());

   sub1: proc( caller);

    dcl caller char (*);

    put skip list('The calling procedure is: ' || caller);

    /* Note: procname() is equiv. of procedurename() */
    put skip list('The current procedure is: ' || procname());

   end;
end;

This program prints:

The calling procedure is: MYPROG
The current procedure is: SUB1

Example 2:

   /* Since Open PL/I does not support Packages, the name of the outermost  */
   /* procedure is aways returned for the PACKAGENAME() built-in.          */

Micro: proc options(main);

    call Focus();

    Focus: proc;
           put skip list (packagename() || ' ' || procedurename() );
    end;

end;

will print:

MICRO FOCUS
Parent topic: Open PL/I Built-ins


PROD Function

Purpose

Returns the product of all the elements of an array.

Syntax

PROD(x)

Parameters

x is an array expression.

Description

The PROD function returns the product of all the elements of the array.

If the elements of x are strings, they are converted to fixed-point values. If they are neither fixed-point values nor strings, they are converted to floating-point values. In the latter case, the result is a floating-point value; otherwise, it is a fixed-point value.

Examples

DECLARE (A(4), I) FIXED BIN (15);

DO I = 1 to 4;
   A(I) = I;
END

I = PROD(A);       /* returns 24 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


RANK Function

Purpose

Returns a fixed binary integer that is the position of the character x within the collating sequence.

Syntax

RANK(x)

Parameters

x is a character string of length one.

Description

The RANK function returns a fixed binary integer that is the position of the character x within the collating sequence.

The result is defined as RANK(x) = INDEX(COLLATE(),x)-1 and has an implementation-defined precision. For details on precisions, see your Open PL/I User's Guide.

The RANK function uses a 256-byte collating string.

Examples

DECLARE X FIXED BINARY(15);
X = RANK('2');   /* X IS SET TO 50 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


REAL Function

Purpose

Returns the real part of the specified expression.

Syntax

REAL(x)

Parameters

x is an expression. If it is real it is converted to complex.

Description

The result has the base, scale, and precision of x.

Restrictions

None.

Parent topic: Open PL/I Built-ins


REPEAT Function

Purpose

Returns a string consisting of the source string concatenated to itself the number of times specified by the second argument.

Syntax

REPEAT(x,y)

Parameters

xis a character-string, bit-string, or picture value, and y is a positive integer expression. If x is an arithmetic value, it is converted to a bit string if it is binary, or to a character string if it is decimal.

Description

The REPEAT function copies a particular string, x, a certain number of times, y, and concatenates the result to the original string x. REPEAT effectively returns a string containing (y+1) occurrences of the string argument with length (y+1) * length (x).

Examples

DECLARE X CHAR(8);

X = REPEAT('AB',3);       /* returns X = 'ABABABAB' *

Note that the same result could be produced by using a string repetition factor, as illustrated below:

X = (4) 'AB';

Here is an example of using the REPEAT function for bit–strings:

DECLARE B_STRING BIT(4) STATIC INIT('1110'B);
DECLARE B_RESULT BIT(8);

B_RESULT = REPEAT(B_STRING,1);

The above example will produce B_RESULT equal to '11101110'B.

Restrictions

None.

Parent topic: Open PL/I Built-ins


RESIGNAL() Subroutine

Purpose

Continues to search for another ON-unit to handle a condition.

Syntax

CALL RESIGNAL();

Description

In Open PL/I, an ON-unit can determine that it does not want to handle a condition and can subsequently request that, instead of returning control to the point of interruption, Open PL/I continue to search for another ON-unit to handle the condition. The RESIGNAL built-in subroutine is available for this purpose.

CALL RESIGNAL() is used in an ON-unit to pass the signaled condition back to the run-time system so that it can look for another ON-unit to handle the condition. The condition is passed at the end of the current ON-unit, that is, execution of the RESIGNAL does not immediately cause a return to the run-time system, but merely sets up the conditions so that when the ON-unit completes its execution and returns, the run-time system will continue searching for another ON-unit that matches the signaled condition.

Examples

ON ERROR BEGIN;
 PUT SKIP LIST('AN UNIDENTIFIED ERROR OCCURRED IN GETREC');
 CALL RESIGNAL();
END;

Restrictions

None.

Parent topic: Open PL/I Built-ins


REVERSE Function

Purpose

Returns a nonvarying string that contains the elements of an expression in reverse order.

Syntax

REVERSE(x)

Parameters

x is an expression.

Description

REVERSE returns a nonvaying string that contains the elements of an expression x in reverse order. x must have a computational type and a string type. If it does not have a string type, it is converted to string (that is, from numeric to bit or character), according to the rules for concatenation.

Examples

dcl s char (40) varying;

    s = 'NeverOddOrEven';
    s = reverse(s);
    put skip list (s);

will print:

nevErOddOreveN

Restrictions

None.

Parent topic: Open PL/I Built-ins


RIGHT Function

Purpose

Returns the result of inserting a string at the right of another string with a certain length. It can be padded on the left with a character. If no padding character is inserted, a blank is used as a padding.

Syntax

RIGHT(s,l,c)

Parameters

s
A string that is inserted to the right of another sting. It must have a computational type and a character type. If it does not have a character type, it is converted to character.
l
The length of a string to the rigth of which s is inserted. It must have a computational type and is converted to Fixed Binary(31,0).
c
Optional padding character, inserted to the left of the string. It must have a nonvarying character type.

Description

RIGHT returns a string which is formed by inserting a string s to the right of another string with length l. An optional padding character c can be attached to the left. If not, a blank is used as a padding.

Examples

dcl s char (40) var;
    dcl t char (40) var;

    s = 'This string is 33 characters long';
    t = right(s, 40, '+');
    put skip list (t);

will print:

+++++++This string is 33 characters long

Restrictions

None.

Parent topic: Open PL/I Built-ins


ROUND Function

Purpose

Rounds a given value at a specified digit and pads spare digit positions with zeros.

Syntax

ROUND(x,k)

Parameters

x is a fixed-point arithmetic or decimal picture value to be rounded, and k is an integer constant that specifies the digit at which the value x is to be rounded.

Description

The ROUND function rounds a given value x at a specified digit and pads positions k+1 to q (q is the scale factor) with zeros. The result is the value of x rounded such that the kth position of x is expressed to its nearest integer. For example, if the argument is 8.77 and it is desired to round to the first fractional digit, the result would be 8.80.

The first argument, x, may be an element expression or array name representing the value (or values, in the case of an array). If the value to be rounded is negative, its absolute value is rounded, but its sign remains unchanged.

The second argument, k, may be unsigned or signed. If k is positive, rounding occurs at the kth digit to the right of the decimal (or binary) point in the first argument; if k is zero, rounding occurs at the first digit to the left of the decimal (or binary) point in the first argument; if k is negative, rounding occurs at the (1 - k) digit to the left of the decimal (or binary) point in the first argument.

Examples

DCL (X,K) DECIMAL FIXED (7,4);
X = 123.7261;
K = ROUND(X,3);       /* K IS NOW 123.7260 */
K = ROUND(X,2);       /* K IS NOW 123.7300 */
K = ROUND(X,1);       /* K IS NOW 123.7000 */
K = ROUND(X,0);       /* K IS NOW 124.0000 */
X = -123.7261;
K = ROUND(X,2);       /* K IS NOW -123.7300 */
K = ROUND(X,0);       /* K IS NOW -124.0000 */
K = ROUND(X,-1);      /* KIS NOW -120.0000 */
X = 9.9999;
K = ROUND(X,0);       /* K IS NOW 10.0000 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


SAMEKEY Function

Purpose

Returns a bit string of length 1 indicating whether a record that has been accessed is followed by another with the same key.

Syntax

SAMEKEY(x)

Parameters

x is a file reference. The file must have the RECORD attribute.

Description

Upon successful completion of an input/output operation on file x, or immediately before the RECORD condition is raised, the value accessed by SAMEKEY is set to '1'B if the record processed is followed by another record with the same key, and set to '0'B if it is not.

The value accessed by SAMEKEY is also set to '0'B if:

  • An input/output operation that raises a condition other than RECORD also causes file positioning to be changed or lost.
  • The file is not open.
  • No current cursor position exists in the file.

Restrictions

None.

Parent topic: Open PL/I Built-ins


SEARCH Function

Purpose

Returns the first position in a string where a character or bit of another string appears. You can also specify the location from which to start searching.

Syntax

SEARCH(x,y,z)

Parameters

x
An expression which pecifies the string in which to search for a character or bit that appears in another string.
y
An expression where a character or bit appears.
z
An optional expression which specifies the location in the string x from which to start searching. It must have a computational type and is converted to Fixed Binary(31,0).

Description

SEARCH returns the first position in the string x where a character or bit of the string y appears. The result is an unscaled real fixed binary value.If any of these two expressions is a null string, the result is zero. If y doesn't appear in x, the result is zero.

You can also specify the location from which to start searching with the expression z.

The SEARCH function can be used to find delimiters in a string of numbers.

Examples

dcl s char (16);
    dcl i fixed bin (15);

    s = 'Newbury, England';
    i = search (s, 'ry');            /* i = 6, ‘r’ found starting from the left */

Restrictions

None.

Parent topic: Open PL/I Built-ins


SEARCHR Function

Purpose

Similar to the SEARCH function with a few differences.

Syntax

SEARCHR(x,y,z)

Parameters

x
An expression which pecifies the string in which to search for a character or bit that appears in another string.
y
An expression where a character or bit appears.
z
An optional expression which specifies the location in the string x from which to start searching. It must have a computational type and is converted to Fixed Binary(31,0).

Description

SEARCHR does the same same as SEARCH, i.e. it returns the first position in a string where a character or bit of another string appears. However, there are a few differences between them. With SEARCHR search is done from right to left and the default value for z is LENGTH(x).

Examples

dcl s char (16);
    dcl i fixed bin (15);

    s = 'Newbury, England';
    i = search (s, 'ry');            /* i = 7, ‘y’ found starting from the right */

Restrictions

None.

Parent topic: Open PL/I Built-ins


SIGN

Purpose

Returns a 1, -1, or 0, indicating whether the specified value is positive, negative, or zero, respectively.

Syntax

SIGN(x)

Parameters

x is an arithmetic expression.

Description

The SIGN function returns a 1, -1, or 0, indicating whether x is positive, negative, or zero, respectively. The precision of the result is Fixed Binary(15).

Examples

IF SIGN(X) = 1 THEN
   PUT LIST ('SIGN OF X IS POSITIVE');

Restrictions

None.

Parent topic: Open PL/I Built-ins


SIN Function

Purpose

Returns a floating-point value that is the sine of an arithmetic expression.

Syntax

SIN(x)

Parameters

x is an arithmetic expression.

Description

The SIN function returns a floating-point value that is the sine of an arithmetic expression x, where x is an angle in radians such that -1 ? SIN(x) ? 1.

The sine is computed in floating-point, and the result has the same data type as x.

Examples

SIN(0.0)    /* returns 0.0 */

Restrictions

An SIN operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


SIND Function

Purpose

Returns a floating-point value that is the sine of the specified angle expressed in degrees.

Syntax

SIND(x)

Parameters

x is a floating-point value representing the sine of an angle.

Description

The SIND function returns the sine of the angle x expressed in degrees. The result has the same data type as x such that -1 ? SIND(x) ? 1.

Examples

SIND(30.0)      /* returns 0.5 */

Restrictions

An SIND operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


SINH Function

Purpose

Returns a floating-point value that is the hyperbolic sine of the arithmetic value x.

Syntax

SINH(x)

Parameters

x is a floating-point value representing the sine of an angle.

Description

The SINH function returns the hyperbolic sine of the angle x expressed in radians. The result has the same data type as x.

Examples

SINH(0.0)   /* returns 0.0 */

Restrictions

An SINH operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


SIZE Function

Purpose

Returns a Fixed Bin(31) value that is the number of bytes allocated for the referenced variable.

Syntax

SIZE(reference)

Parameters

reference is a variable of any data type and storage class.

Description

This function is identical to the STORAGE function and is provided for compatibility with earlier versions of Open PL/I (formerly called LPI-PL/I).

The SIZE function returns a Fixed Bin(31) integer that is the number of bytes allocated for the referenced variable. The variable can be a scalar, an array, an array element, a structure, or a member of a structure. The reference cannot be made to a constant or an expression.

When a reference is made to an individual array element, the value returned is the size of the element of the array and not the size of the entire array. The SIZE function can be used with an unconnected array argument.

If the variable is a bit string that does not fill an integral number of bytes, the value returned is rounded up to the next byte. If the variable is of the type character varying, the value returned is the declared length of the string plus two, where the extra two bytes are the bytes needed to store the current length of the string.

Examples

In the following example, the returned values are shown in the comment.

Note: The sizes in the example are accurate for Open PL/I, but may not be correct for different implementations of PL/I that have different precision, alignment, boundaries, or datatype representations. For information on this implementation, see your Open PL/I User's Guide.
DECLARE
   S FIXED BIN(31),
   A FIXED BIN(15),
   B FIXED BIN(31),
   C FLOAT BIN(23),
   D CHAR(5),
   E CHAR(5) VARYING,
   F BIT(11),
   G POINTER;

S = SIZE(A);   /* S = 2 */
S = SIZE(B);   /* S = 4 */
S = SIZE©);   /* S = 4 */
S = SIZE(D);   /* S = 5 */
S = SIZE(E);   /* S = 7 */
S = SIZE(F);   /* S = 2 */
S = SIZE(G);   /* S = 4 */

DECLARE
   S FIXED BIN(31),
   1 A_STRUCT
      2 A FIXED BIN(31),
      2 B CHAR (2),
   C(20) FIXED BIN(15);

S = SIZE(A_STRUCT);    /* S = 6 */
S = SIZE(A STRUCT.A);  /* S = 4 */
S = SIZE(A_STRUCT.B);  /* S = 2 */
S = SIZE©);           /* S = 40 */
S = SIZE©(13));       /* S = 2 */

DECLARE
   S FIXED BIN(31),
   1 STRUC1,
      2 A BIT(1),
      2 B BIT(3);
DECLARE
   1 STRUC2,
      2 C BIT(1) ALIGNED,
      2 D BIT(3) ALIGNED;

S = SIZE(STRUC1);   /* S = 1 */
S = SIZE(STRUC2);   /* S = 2 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


SQRT Function

Purpose

Returns the positive square root of the specified value.

Syntax

SQRT(x)

Parameters

x is a positive or zero floating-point value.

Description

The SORT function returns the positive square root of x. The result has the same data type as x.

Examples

SQRT(4.0)    /* returns 2.0 */

Restrictions

An SQRT operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


STORAGE Function

Purpose

Returns a Fixed Bin(31) value that is the number of bytes allocated for the referenced variable.

Syntax

STORAGE(reference)

Abbreviation(s): STG for STORAGE.

Parameters

reference is a variable.

Description

The STORAGE function returns a Fixed Bin(31) integer that is the number of bytes allocated for the referenced variable. The variable can be a scalar, an array, an array element, a structure, or a member of a structure.

When a reference is made to an individual array element, the value returned is the size of the element of the array and not the size of the entire array. If the variable is a bit string that does not fill an integral number of bytes, the value returned is rounded up to the next byte.

If the variable is of the type character varying it consists of two parts: the text field and the length field. STORAGE returns the declared length of the text field plus two, since the length field always uses two bytes.

If the variable is an area, STORAGE returns the maximum size of the area plus the size of the area header.

For more information on data storage, see your Open PL/I User's Guide.

Examples

DCL A FIXED BIN(15);
      DCL 1 FOO,
            2 AB FIXED BIN(15),
            2 F001,
               5 A0 CHAR(12),
               5 A2 FIXED BIN(31),
               5 A1 CHAR(5) VARYING,
            2 ABC CHAR(4);

          PUT SKIP LIST('Should see 2 ->',SIZE (A));
          PUT SKIP LIST('Should see 2 ->',STG (A));
          PUT SKIP LIST('Should see 23 ->',STG (F001));
          PUT SKIP;

Restrictions

None.

Parent topic: Open PL/I Built-ins


STRING Function

Purpose

Concatenates the elements of an array or a structure and returns the results.

Syntax

STRING(s)

Parameters

s is an arithmetic value, string value, picture value, or an array or structure containing all nonvarying string or picture values.

Description

The STRING function concatenates the elements of an array s or a structure s and returns the results. If s is scalar, it is converted to a string.

If s is an array or structure, it must be suitable for storage sharing, as defined in the section Storage Sharing in the chapter Storage Classes. s must be a reference to a variable whose storage is connected. The STRING function can be used with an unconnected array argument.

The result is converted to a string according to the rules for data type conversion given in the chapter Data Type Conversions.

For a description of the STRING function's use as a pseudovariable, see the section Assignment in the chapter Statements.

Examples

DECLARE S(4) CHAR(1);
S(1) = 'A';
S(2) = 'B';
S(3) = 'C';
S(4) = 'D';

STR = STRING(S);   /* 'ABCD' */

Restrictions

None.

Parent topic: Open PL/I Built-ins
Related information
Storage Sharing
Data Type Conversions
Assignment


SUBSTR Function

Purpose

Returns a string that is a copy of a specified part of the specified string.

Syntax

SUBSTR(s,i,j)

or

SUBSTR(s,i)

Parameters

s is a bit string, character string, or picture value. If s is not a string, it is converted to a bit string if it is binary or to a character string if it is decimal. I is an integer value indicating the first bit (if s is a bit string) or character of a substring within s; and j is an integer value indicating the length of the substring within s.

Description

The SUBSTR function returns a string that is a copy of a part of the string s starting at the Ith character for a length j. If j is not given, j = LENGTH(s)-I+1, that is, the remainder of the string s.

The program is in error if I < 1 or (I + j -1) > LENGTH(s) or j < 0. If the program is compiled with subscript checking enabled, these errors result in the ERROR condition; otherwise, these errors produce unpredictable results.

For a description of the SUBSTR function's use as a pseudovariable, and for the description of the ASSIGNMENT statement, see the section Assignment in the chapter Statements.

Examples

SUBSTR('ABCDE',2,2)   /* returns 'BC' */
SUBSTR('ABCDE',2)         /* returns 'BCDE' */

Restrictions

None.

Parent topic: Open PL/I Built-ins
Related information
Assignment


SUM Function

Purpose

Returns the sum of all the elements in an array.

Syntax

SUM(x)

Parameters

x is an array expression.

Description

The SUM function returns the sum of all the elements in the array.

If the elements of the array are strings, they are converted to fixed-point values. If they are neither fixed-point values nor strings, they are converted to floating-point values. In the latter case, the result is a floating-point value; otherwise, it is a fixed-point value.

Examples

DECLARE (A(4), I) FIXED BIN (15);

DO I = 1 to 4;
   A(I) = 4;
END

I = SUM(A);     /* returns 10 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


SYSNULL Function

Purpose

Returns the system null pointer value.

Syntax

SYSNULL()

or

SYSNULL

The second syntax form can be used only when the BUILTIN attribute is specified.

Parameters

None.

Description

The SYSNULL function returns a null pointer value. The SYSNULL value is 0.

This value cannot be changed by the -setnull compiler option, which applies only to the NULL built-in. For a description of the -setnull compiler option, see your Open PL/I User's Guide.

Examples

IF LAST_POINTER = SYSNULL() THEN CALL FINISH;

In this example, the IF statement determines whether the pointer variable LAST_POINTER is system null; if so, the CALL statement executes.

Restrictions

None.

Parent topic: Open PL/I Built-ins


TALLY Function

Purpose

Returns the number of times a string appears in another string.

Syntax

TALLY(x,y)

Parameters

x and y are string expressions that must have computational type and should be character or bit.

Description

TALLY returns the number of times the string x appears in the string y. The result is a Fixed Binary (31,0) value. If y does not appear in x, the result is zero. If any of these two expressions is a null string, the result is zero.

Examples

dcl s char (40);
   dcl n fixed bin (15);

   s = 'peter piper picked a peck of pickled peppers.';

   n = tally(s, 'p');
   put skip list ("'p'  appears " || trim(n) || ' times.');

   n = tally(s, 'pe');
   put skip list ("'pe' appears " || trim(n) || ' times.');

   n = tally(s, 'pi');
   put skip list ("'pi' appears " || trim(n) || ' times.');

   n = tally(s, 'ck');
   put skip list ("'ck' appears " || trim(n) || ' times.');

will print:

'p'  appears 8 times.
'pe' appears 4 times.
'pi' appears 3 times.
'ck' appears 3 times.

Restrictions

None.

Parent topic: Open PL/I Built-ins


TAN Function

Purpose

Returns the tangent of the specified angle expressed in radians.

Syntax

TAN(x)

Parameters

x is a floating-point value representing an angle and cannot be an odd multiple of ?/2.

Description

The TAN function returns the tangent of the angle x expressed in radians. The result has the same data type as x.

Examples

TAN(0.0)    /* returns 0.0 */

Restrictions

A TAN operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


TAND Function

Purpose

Returns the tangent of the specified angle expressed in degrees.

Syntax

TAND(x)

Parameters

x is a floating-point value representing an angle and cannot be an odd multiple of 90.

Description

The TAND function returns the tangent of the angle x expressed in degrees. The result has the same data type as x.

Examples

TAND(45.0)    /* returns 1.0 */

Restrictions

A TAND operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


TANH Function

Purpose

Returns the hyperbolic tangent of the specified arithmetic value.

Syntax

TANH(x)

Parameters

x is a floating-point value representing an angle.

Description

The TANH function returns the hyperbolic tangent of the angle x expressed in radians such that -1 ? TANH(x) ? 1.

The result has the same data type as x.

Examples

TANH(0.0)       /* returns 0.0 */

Restrictions

A TANH operation on floating-point decimal data is actually performed using the floating-point binary operation. Thus, the range of the operands and the result of the operation are limited to the ranges for floating-point binary numbers.

Parent topic: Open PL/I Built-ins


TIME Function

Purpose

Returns a character string that represents the time of day.

Syntax

TIME()

or

TIME

The second syntax form can be used only if the BUILTIN attribute was specified.

Description

The TIME function returns a character string of the form hhmmssttt that represents the time of day, where hh, mm, and ss are in the ranges 00 – 23, 00 – 59, and 00 – 59, respectively, and represent hours, minutes, and seconds, respectively. ttt represents thousandths of a second. If your system is not capable of supplying ttt, zeros are returned in these positions. (Releases of Open PL/I prior to release 5.0 returned only two fractional digits, that is, hundredths, instead of three. To retain that behavior, compile with the -pl1g option. (See your Open PL/I User's Guide.)

Examples

The value of TIME at 6 seconds after 11:15 P.M. is '231506000 '.

Restrictions

None.

Parent topic: Open PL/I Built-ins


TRANSLATE Function

Purpose

Replaces occurrences of a character in a string with a corresponding translation character and returns the resulting string.

Syntax

TRANSLATE(s,t)

or

TRANSLATE(s,t,x)

Parameters

s, t, and x are all character strings.

Description

Given a character string argument, the TRANSLATE function replaces occurrences of a character with a corresponding translation character and returns the resulting string. If x is not given, it is assumed to be COLLATE(). (The TRANSLATE function uses a 256-byte collating string.) If x is the null string, s is returned without translation.

If t is shorter than x, t is padded on the right with blanks until the length of t is equal to the length of x. If t is longer than x, the rightmost extra characters of t are ignored.

The occurrence of an element of x in the string s is replaced by the corresponding element in the string t.

If s is the null string, the result is the null string. If s is not the null string, for each character of s, s(k), the value I is calculated to be equal to INDEX(x,s(k)). If the value of I is 0, the corresponding character of the result is s(k); otherwise, the corresponding character of the result is t(I).

Examples

TRANSLATE('TEXT','abcdefghijklmnopqrstuvwxyz',
        'ABCDEFGHIJKLMNOPQRSTUVWXYZ')    /*returns 'text'*/

Restrictions

None.

Parent topic: Open PL/I Built-ins


TRIM Function

Purpose

Strips blanks or specified characters from the beginning and end of a character string value and returns the resulting string.

Syntax

TRIM(string[,a,b])

Parameters

string is a character string value (variable or constant). a, if present, is a string consisting of the set of characters to be trimmed from the beginning of string. b, if present, is a string consisting of the set of characters to be trimmed from the end of string.

Description

The TRIM built-in function strips the characters specified in a from the beginning of string and the characters specified in b from the end of string and returns the resulting string.

If the second and third arguments are not present, blanks are trimmed from the beginning and end of the first argument.

Examples

The following example returns the values shown in the comment.

DECLARE
   S CHAR(25)VARYING,
   A CHAR(5);
A = 'ABC';
S = TRIM(A);            /* S = 'ABC' */
S = TRIM(' HELLO');     /* S = 'HELLO' */
S = TRIM(' GOODBYE ');  /* S = 'GOODBYE' */
S = TRIM('');           /* S = '' null string */
S = TRIM('abcdefghi','cba', 'high');    /* S = 'def' */
S = TRIM('abc','abc','abc')   /* S = '' null string */

Restrictions

None.

Parent topic: Open PL/I Built-ins


TRUNC Function

Purpose

Returns the integer part of a specified value.

Syntax

TRUNC(x)

Parameters

x is an arithmetic expression.

Description

The TRUNC function returns the integer part of x. If x is floating-point, the precision of the result is the precision of x.

If x is fixed-point, the precision of the result is (MIN(n,MAX(p-q+1,1)),0). n is the maximum precision allowed for values of the result type. For details on maximum precisions, see your Open PL/I User's Guide.

For x < 0, the result is CEIL(x). For x ? 0, the result is FLOOR(x).

Examples

TRUNC(3.125)    /* returns 3 */
TRUNC(-3.125)   /* returns -3 */

Restrictions

None.

Parent topic: Open PL/I Built-ins


UNSPEC Function

Purpose

Returns a bit string containing the internal representation of the specified value.

Syntax

UNSPEC(x)

or

UNSPEC(SUBSTR(char_string,i,j))

Parameters

x is a reference to a scalar variable.

?

Description

The UNSPEC function returns a bit string containing the internal representation of x.

The length and content of the result value depend on the data type and value of x and are implementation-defined. For details, see your Open PL/I User's Guide.

Examples

DECLARE CH CHAR(1);
DECLARE MINUS_ONE FIXED BIN;
MINUS_ONE = -1;
UNSPEC(CH) = UNSPEC(MINUS_ONE);
BIT(8) = UNSPEC(CH);   /* '11111111'B */
Parent topic: Open PL/I Built-ins
Related information
Assignment


UPPERCASE Function

Purpose

Returns a character string with all the alphabetic characters from a to z converted to their uppercase equivalent.

Syntax

UPPERCASE(x)

Parameters

x is an expression. It can be converted to character.

Examples

    dcl s char (40) varying;

    s = 'Lead is an element with the symbol Pb';
    s = uppercase(s);
    put skip list (s);

will print:

LEAD IS AN ELEMENT WITH THE SYMBOL PB

Restrictions

None.

Parent topic: Open PL/I Built-ins


VALID Function

Purpose

Determines whether a reference to a scalar pictured value has a value that is valid with respect to its picture specification.

Syntax

VALID(x)

Parameters

x is a reference to a scalar pictured value.

Description

The VALID function determines whether x, a reference to a scalar pictured value, has a value that is valid with respect to its picture specification. The result is a bit string of length one that indicates if the character-string value of x can be edited into the picture declared for x.

If the character-string value of x can be edited into the picture declared for x, the result value is '1' B; otherwise, the result is '0' B.

The VALID function can be used when a pictured data item or a pictured item that is a member of a structure is read using the READ statement. Record input done with READ does not perform the validation that is normally done when a value is assigned to a pictured data item.

Examples

VALIDATE_FILE: PROCEDURE (BALANCES, REC_COUNT);
   DECLARE BALANCES FILE RECORD;
   DECLARE REC_COUNT FIXED BIN(31);
   DECLARE TOTAL PICTURE '999V.99';

DO I = 1 TO REC_COUNT;
   READ FILE(BALANCES) INTO (TOTAL);
   IF ^VALID(TOTAL) THEN
      DO;
      PUT LIST('Invalid total value:', TOTAL);
      PUT SKIP;
      END;
   END;
END VALIDATE_FILE;

Restrictions

None.

Parent topic: Open PL/I Built-ins


VERIFY Function

Purpose

Compares a string with a test string and verifies that all characters appearing in the string also appear in the test string.

Syntax

VERIFY(s,c)

Parameters

s and c are both either character-string or picture values.

Description

The VERIFY function compares a string s with a test string c and verifies that all characters appearing in the string also appear in the test string. If each of the characters in s occurs in c, the result is 0. If all of the characters in s do not occur in c, the result is a fixed-point binary integer that indicates the leftmost character in s that is not found in c. If only s is null, a 0 is returned. If only c is null, a 1 is returned. If both s and c are null, a 0 is returned.

Examples

VERIFY('2a56b','0123456789')
/* returns the value 2 to indicate the first */
/* non-numeric character in the string '2a56b' */

Restrictions

None.

Parent topic: Open PL/I Built-ins


Open PL/I Macro Preprocessor

This appendix describes the Open PL/I Macro Preprocessor and defines the statements, procedures, and built-ins available for use with the preprocessor. For information on invoking the Open PL/I Macro Preprocessor refer to the chapter Using Open PL/I in your Open PL/I User's Guide.

  • Overview
  • Preprocessor Scan
  • Preprocessor Variables and Data Elements
  • Preprocessor References and Expressions
  • Scope of Preprocessor Names
  • Preprocessor Statements
  • Preprocessor Procedures
Parent topic: Open PL/I Language Reference Manual
Related information
Using Open PL/I


Overview

The Open PL/I Macro Preprocessor enables the PL/I programmer to have control of the source program during compile time. It is executed prior to the compilation, and its output is passed to the Open PL/I Compiler.

  • Preprocessor I/O
Parent topic: Open PL/I Macro Preprocessor


Preprocessor I/O

The preprocessor input is a file containing an Open PL/I source module, possibly including Open PL/I Macro Preprocessor statements. The preprocessor output is an Open PL/I source module containing no further preprocessor statements, but with the source code modified according to the semantics of the preprocessor statements that were encountered in the input file.

  • Preprocessor Statements
  • Listing Control Statements
Parent topic: Overview


Preprocessor Statements

Preprocessor statements, with the exception of preprocessor procedures, are executed as they are encountered. Preprocessor procedures must be invoked in order to be executed. Preprocessor statements, except those in preprocessor procedures, begin with a percent symbol (%). Blanks, tabs, and returns may separate the percent symbol from the rest of the statement, except where indicated.

The preprocessor executes preprocessor statements and alters the input text accordingly. Preprocessor statements can cause parts of the input text to be altered in any of the following ways:

  • Any identifier (and optional argument list) appearing in the input text can be changed to become an arbitrary string of text.
  • If a conditional compilation is desired, the programmer can indicate which sections of the program are to be compiled and which discarded.
  • Strings of text residing in different files can be incorporated into the source program.
Parent topic: Preprocessor I/O


Listing Control Statements

Listing control statements are not copied to the preprocessor output. A warning message is given when these are found. These statements are:

  • %CONTROL (ignored by the preprocessor)
  • %NOPRINT
  • %PAGE
  • %PRINT
  • %SKIP
Parent topic: Preprocessor I/O


Preprocessor Scan

The preprocessor starts its scan at the beginning of its input and proceeds sequentially. When preprocessor statements are found they are executed immediately (except for preprocessor procedures, which are executed only when referenced).

An identifier that matches the name of an active preprocessor variable is replaced in the preprocessor output by the value of the variable. When an identifier matches the name of an active preprocessor function (either programmer-written or built-in) the function is invoked and the invocation is replaced by the returned value. For a discussion about activation, replacement, and rescanning, see the %ACTIVATE statement.

Parent topic: Open PL/I Macro Preprocessor
Related information
%ACTIVATE statement


Preprocessor Variables and Data Elements

Preprocessor local variables function like static storage, rather than automatic storage, so values are maintained across invocations of a preprocessor procedure.

Preprocessor names are formed according to the rules for other Open PL/I names.

A preprocessor variable is specified in a %DECLARE statement with the FIXED, CHARACTER, or BIT attribute. No other attributes can be declared for a preprocessor variable.

A preprocessor variable declared with the FIXED attribute is given the PL/I attribute DECIMAL and precision (5,0). Fixed decimal constants in preprocessor expressions must be integers.

A preprocessor variable declared with the CHARACTER attribute is given the PL/I VARYING attribute with certain restrictions on its length, as described elsewhere in this manual. String repetition factors are not allowed for character constants in preprocessor expressions.

There are no preprocessor bit variables. However, bit constants are allowed. They are converted to their corresponding decimal value and treated as fixed constants. Only the rightmost 17 digits are used. A conversion result greater than 99999 is given that value. String repetition factors are not allowed for bit constants in preprocessor expressions.

Parent topic: Open PL/I Macro Preprocessor


Preprocessor References and Expressions

Preprocessor references and expressions are written and evaluated the same way as PL/I references and expressions are, with the following restrictions:

  • Operands of a preprocessor expression can consist only of preprocessor variables, references to preprocessor procedures, fixed decimal constants, bit constants, character constants, and references to preprocessor built-in functions. Strings or character constants are limited in size to 1023 characters.
  • The exponent symbol (**) cannot be used. When found, it is converted to a plus symbol (+) and a warning message is issued.
  • For arithmetic operations, only decimal arithmetic of precision (5.0) is performed; that is, each operand is converted to a decimal fixed-point integer value of precision (5,0) before the operation is performed, and the decimal fixed-point result is converted to precision (5,0). When the value of an operand or a result of an operation exceeds 99999 (the limit of precision (5,0)) that value is set to zero.
  • The concatenation of strings is limited to 2047 characters.
Parent topic: Open PL/I Macro Preprocessor


Scope of Preprocessor Names

The scope of a preprocessor name is determined by where it is declared:

  • The scope of a name declared within a preprocessor procedure is that procedure.
  • The scope of a name declared within an included string is that included string and all input text scanned after that string is included (except any preprocessor procedure in which the name is also declared).
  • The scope of any other name is the entire preprocessor input (except any preprocessor procedure in which the name is also declared).
Parent topic: Open PL/I Macro Preprocessor


Preprocessor Statements

This section lists alphabetically, the preprocessor statements and discusses each. The characters /* introduce a comment, which terminates with the characters */. Comments do not nest and can appear within a preprocessor statement wherever blanks can appear. Comments within preprocessor statements are not inserted into the preprocessor output text.

  • %ACTIVATE
  • %ASSIGNMENT
  • %DEACTIVATE
  • %DECLARE
  • %DO
  • %END
  • %GOTO
  • %IF
  • %INCLUDE
  • %NOTE
  • %NULL
  • %REPLACE
Parent topic: Open PL/I Macro Preprocessor


%ACTIVATE

Purpose

Renders identifiers active and eligible for replacement.

Syntax

%[label:]...ACTIVATE ident[RESCAN|NORESCAN][,ident[RESCAN|NORESCAN]]...;

Abbreviation(s): %ACT for %ACTIVATE.

Parameters

Each identifier must be a preprocessor variable, a preprocessor procedure name, or a preprocessor built-in function name.

Description

When a preprocessor variable is declared, it is automatically activated. It can be deactivated by use of the %DEACTIVATE statement and reactivated by use of the %ACTIVATE statement.

If neither RESCAN nor NORESCAN is specified, RESCAN is assumed. RESCAN implies that, after a text replacement has been made, this text will be rescanned to see if any further substitutions apply. NORESCAN implies the opposite.

The appearance of an identifier in a %ACTIVATE statement makes it active and eligible for replacement; that is, any subsequent encounter of that identifier in a nonprocessor statement, while the identifier is active, will initiate replacement activity, except when the identifier appears within a comment or within single quotes.

Example

Example 1.

%DECLARE A FIXED, B CHARACTER;
%DEACTIVATE B;
%A = 24;
%B = 'VAR_NAME';
NUM = B + A;
%ACTIVATE B;
%DEACTIVATE A;
NUM = B + A;

The text generated by this example would be as follows:

NUM = B + 24;
NUM = VAR_NAME + A;

Example 2.

%DECLARE (C,D) CHARACTER;
%C = D**2;
%D = 'NUM';
NUM = C;
%ACTIVATE C NORESCAN;
NUM = C;

The text generated by this example would be as follows:

NUM = NUM**2;
NUM = D**2;

Restrictions

A %ACTIVATE statement cannot appear within a preprocessor procedure. The replacement in a rescan operation is limited to 1023 characters.

References to preprocessor procedures will not be recognized when rescanning an identifier for replacement.

Parent topic: Preprocessor Statements


%ASSIGNMENT

Purpose

Assigns a value to a specified preprocessor variable.

Syntax

%[label:]... preprocessor-variable = preprocessor-expression;

Parameters

preprocessor-variable is a preprocessor variable reference, and preprocessor-expression is any valid expression.

Description

The %ASSIGNMENT statement is used to evaluate preprocessor expressions and to assign the result to a preprocessor variable.

Example

Example 1.

%DECLARE A FIXED (B,C) CHARACTER;
%A = 1024;
%B = 'BALANCE(CUST(I,J),DATE())';
%C = 'ALLOCATE STRUC SET(STRUC_PTR);';
C
STRUC.BAL(A) = B;

The text generated by this example would be as follows:

ALLOCATE STRUC SET(STRUC_PTR);
STRUC.BAL(1024) = BALANCE(CUST(I,J),DATE());

Example 2.

%DECLARE (D,E) CHAR;
%D = 'TEST_CASE';
%E = D || '_0';
F = E;

The text generated by this example would be as follows:

F = TEST_CASE_0;
Parent topic: Preprocessor Statements


%DEACTIVATE

Purpose

Renders identifiers inactive and ineligible for replacement.

Syntax

%[label:]... DEACTIVATE ident[,ident]...;

Abbreviation(s): %DEACT for %DEACTIVATE.

Parameters

Each identifier must be a preprocessor variable, a preprocessor procedure name, or a preprocessor built-in function name.

Description

The appearance of an identifier in a %DEACTIVATE statement makes it inactive and ineligible for replacement; that is, any subsequent encounter of that identifier in a nonpreprocessor statement will not initiate any replacement activity (unless, of course, the identifier is later reactivated by use of the %ACTIVATE statement).

Parent topic: Preprocessor Statements


%DECLARE

Purpose

Specifies that an identifier is a preprocessor variable or a preprocessor procedure name.

Syntax

%[label]... DECLARE(ident[,ident]...);

Abbreviation(s): %DCL for %DECLARE.

Parameters

ident is a PL/I name.

Description

The %DECLARE statement establishes an identifier as a preprocessor variable or a preprocessor procedure name and also serves to activate that identifier with the RESCAN option.

When declaring parameters in a preprocessor procedure, they should all be declared together in the first statement.

CHARACTER (abbreviation, CHAR) specifies that the identifier represents a varying length character string of up to 4096 characters. FIXED specifies that the variable is also given the PL/I attributes DECIMAL (5,0). BIT specifies that the identifier represents a bit string of maximum length 16.

An ENTRY declaration can be specified for each preprocessor entry name in the source program. The declaration activates the entry name. The declaration of a preprocessor procedure entry name can be performed explicitly by its appearance as the label of a %PROCEDURE statement. This explicit declaration, however, does not activate the preprocessor procedure name. Preprocessor built-in function names must not be used to name preprocessor procedures.

BUILTIN specifies that the identifier is the preprocessor built-in function of the same name.

Factoring of attributes is allowed. Attributes common to several names can be factored to eliminate repeated specification of the same attribute. Factoring is achieved by enclosing names in parentheses, and following this by a set of attributes that apply to all of the names. Declarations within the parenthesized list are separated by commas.

Example

%DECLARE A FIXED, (B,C) CHARACTER;
%DECLARE SUBSTR BUILTIN;

/* Note that preprocessor variables B and C are declared using factored declaration. */
Parent topic: Preprocessor Statements


%DO

Purpose

Begins a sequence of preprocessor statements to be executed in a group.

Syntax

%[labe1:]... DO[index = start[TO finish[BY increment]] |
                                  [BY increment [TO finish]]];

Parameters

Where index is a preprocessor variable; start, finish, and increment are preprocessor expressions.

Description

The %DO statement and its corresponding %END statement delimit a preprocessor DO group and can also specify repetitive execution of the DO group.

Preprocessor DO groups can be nested. Both preprocessor statements and text other than preprocessor statements can appear within a preprocessor DO group. However, only the preprocessor statements are executed. Nonpreprocessor statements are scanned but only for possible replacement activity. Non-iterative preprocessor DO groups are useful as THEN or ELSE clauses of %IF statements.

If increment is ? 0 or start > finish, the body of the loop is not executed.

Example

%DECLARE IX FIXED;
%DO IX = 1 TO 4;
A(IX) = IX;
%END

The text generated by this example would be as follows:

A(1) = 1;
A(2) = 2;
A(3) = 3;
A(4) = 4;
Parent topic: Preprocessor Statements


%END

Purpose

Terminates a block or group headed by the most recent %DO or %PROCEDURE statement.

Syntax

%[label:]... END [label];

Parameters

Description

The %END statement is used in conjunction with %DO or %PROCEDURE statements to delimit preprocessor DO groups or preprocessor procedures.

The label following the END can be a label of a %PROCEDURE or %DO statement. No checking is done.

Restrictions

Multiple closure, that is, using one %END to close multiple groups and/or blocks, is not permitted.

Parent topic: Preprocessor Statements


%GOTO

Purpose

Transfers control to a labeled preprocessor statement.

Syntax

%[label:]... GOTO statement-label;

Alternate form: %GO TO for %GOTO.

Parameters

statement-label is a reference to a preprocessor statement.

Description

The %GOTO statement causes the preprocessor to continue its scan at the specified label.

The label following the GOTO specifies the point to which the scan will be transferred. It must be a label of a preprocessor statement.

A preprocessor GOTO statement appearing within a preprocessor procedure cannot transfer control to a point outside of that procedure.

A GOTO statement can transfer control to a label in another included file at an inner level of nesting.

Example

%DECLARE A CHARACTER;
%A = 'NAME';
%GOTO PREP_LABEL;
C = A;
%PREP_LABEL:;           /* Null statement */
D = A;

The text generated by this example would be as follows:

D = NAME;

Restrictions

The label following the GOTO cannot be the label of a preprocessor procedure.

Parent topic: Preprocessor Statements


%IF

Purpose

Conditionally executes code based on a test expression.

Syntax

%[label:]... IF expr %THEN clause-1 [%ELSE clause-2]

Parameters

expr is any expression that results in a scalar bit string value of length ? 1. The test-expression is considered true if any bit in the string is one; the expression is considered false only when all bits are zero. clause-n is any single preprocessor statement (other than %DECLARE, %PROCEDURE, %END or %DO), or a preprocessor DO group. Otherwise, the description is the same as that of Open PL/I IF statements.

Description

The %IF statement can control the flow of the scan according to the value of a preprocessor expression.

The preprocessor expression is evaluated. If the result of the evaluation is 1 or greater than 1, clause-1 is executed and clause-2 is ignored, if present. If the result of the evaluation is 0, clause-1 is ignored and clause-2, if present, is executed. In either case, the scan resumes immediately following the IF statement, unless, of course, a %GOTO in any of the clauses causes the scan to resume elsewhere. %IF statements can be nested according to the rules for nesting Open PL/I IF statements.

Example

%DECLARE (A,B) CHARACTER;
%A ='CONTROL_1';
%B = 'NAME';
%IF A = 'CONTROL_1'
%THEN %DO;
   RES = B + F(X);
%END;
%ELSE %DO;
   RES = B - F(X) + SQRT(X);
   LST = F(X) + 1;
%END;

The text generated by this example would be as follows:

RES = NAME + F(X);
Parent topic: Preprocessor Statements


%INCLUDE

Purpose

Incorporates external text into the program being scanned.

Syntax

%[label:] . . . INCLUDE pathname [,pathname] . . . ;

Parameters

pathname can be any legal UNIX pathname.

Description

The %INCLUDE statement is used to include or incorporate strings of external text into the source program being scanned.

Included text can contain nonpreprocessor and/or preprocessor statements. The scan continues with the first character in the included text. The included text is scanned in the same manner as the source program.

%INCLUDE statements can be nested to a limit of eight levels.

Parent topic: Preprocessor Statements


%NOTE

Purpose

Generates a preprocessor diagnostic message.

Syntax

%[label:]... NOTE (message [, code]);

Parameters

message is a character string expression whose value is the required diagnostic message. code is a fixed expression whose value (in a range of 0 to 16) indicates the severity of the diagnostic. If code is omitted, 0 is assumed.

Description

The %NOTE statement enables the user to generate a preprocessor diagnostic message of specified text and severity.

A code of 16 (the maximum) causes immediate termination of the preprocessing.

Parent topic: Preprocessor Statements


%NULL

Purpose

Placeholder statement.

Syntax

%[label:]... ;

Parameters

Description

The %NULL statement does nothing and does not modify sequential statement execution. It can be used to provide transfer targets for %GOTO statements. It is also useful for balancing ELSE clauses in nested %IF statements.

Parent topic: Preprocessor Statements


%REPLACE

Purpose

Specifies that an identifier is a constant of a given value.

Syntax

%REPLACE name BY constant;

Description

The %REPLACE statement specifies that an identifier is a constant of a given value.

Beginning at the point at which the %REPLACE statement is encountered, each occurrence of name that follows the %REPLACE statement, as interpreted by the macro preprocessor, is replaced by the constant until the end of compilation or until another %REPLACE statement that specifies the same name is encountered.

The %REPLACE statement is normally used to supply the sizes of tables or to give names to special constants whose meaning would not otherwise be obvious.

Example

%REPLACE MSG BY 'login';
PUT SKIP LIST(MSG);
...
%REPLACE MSG BY 'logout';
PUT SKIP LIST(MSG);
Parent topic: Preprocessor Statements


Preprocessor Procedures

Preprocessor procedures are function procedures. A preprocessor procedure is delimited by %PROCEDURE and %END statements and contains at least one RETURN statement. Preprocessor statements in a preprocessor procedure do not begin with a percent symbol.

  • Invocation of Preprocessor Procedures
  • Preprocessor Built-In Functions
Parent topic: Open PL/I Macro Preprocessor


Invocation of Preprocessor Procedures

A preprocessor procedure is invoked by the appearance of its entry name, together with an optional list of arguments. The procedure must have been previously activated by use of the %ACTIVATE statement or by its inclusion in a %DECLARE statement.

The argument list must be a parenthesized list of positional arguments following the entry name. Trailing arguments can be omitted; their absence is detected by use of the PARMSET built-in.

  • %PROCEDURE
  • RETURN
Parent topic: Preprocessor Procedures


%PROCEDURE

Purpose

Defines a procedure entry and specifies the parameters of the procedure, if any.

Syntax

%label:[label:]... PROCEDURE[(ident[,ident]...)]
[STATEMENT]RETURNS(CHARACTER|FIXED|BIT);

Abbreviation(s): %PROC for %PROCEDURE.

Parameters

ident is a PL/I name.

Description

The %PROCEDURE statement is used in conjunction with a %END statement to delimit a preprocessor procedure. Such a preprocessor procedure is an internal function procedure that can be executed only by the preprocessor.

The STATEMENT option is ignored in this version of Open PL/I. One of the attributes, CHARACTER, FIXED, or BIT, must be specified in the RETURNS attribute list to indicate the type of value returned by the function procedure. There can be no default.

The preprocessor statements ASSIGNMENT, DECLARE, DO, GOTO, IF, NULL, RETURN, and NOTE can be used within a preprocessor procedure. Inside the preprocessor procedure the % symbols are omitted.

Example

%DECLARE (A,B,C) CHARACTER;
%ACTIVATE CAT;
%A = 'AAA';
%B = 'BBB';
%C = 'CCC';
RES_STRING_3 = CAT(A,B,C);
RES_STRING_2 = CAT (A,B);
RES_STRING_1 = CAT(A);
%CAT: PROCEDURE(X,Y,Z) RETURNS(CHAR);
DECLARE (X,Y,Z) CHAR;
DECLARE S CHAR;
IF PARMSET(Z) THEN S = ''''||X||Y||Z||'''';
ELSE IF PARMSET(Y) THEN S = ''''||X||Y||'''';
ELSE S = ''''||X||'''';
RETURN(S);
%END CAT;

The text generated by this example would be as follows:

RES_STRING_3 = 'AAABBBCCC';
RES_STRING_2 = 'AAABBB';
RES_STRING_1 = 'AAA';

This example also shows how to generate a character string constant using the preprocessor. To do so, use four successive apostrophes, followed by the concatenation symbol, followed by the expression for the desired character string constant, followed by another concatenation symbol, followed by four more apostrophes.

Parent topic: Invocation of Preprocessor Procedures


RETURN

Purpose

Returns control and a value back to the point of invocation.

Syntax

[label:]...RETURN(expr);

Parameters

expr is any valid preprocessor expression.

Description

The preprocessor RETURN statement can be used only in a preprocessor procedure and can have no leading percent symbol. It returns a value as well as control back to the point from which the preprocessor procedure was invoked.

Parent topic: Invocation of Preprocessor Procedures


Preprocessor Built-In Functions

A reference to a preprocessor built-in function in input text is executed by the preprocessor only if the built-in function name is active. The functions are explained in the following table:

Function Name | Use
COMPILETIME | Returns a character string containing the current date and time in the following format: DD MMM YY HH.MM.SS
COUNTER | Returns a character string containing a decimal number. The returned number is 00001 for the first invocation and is incremented by one on each successive invocation.
INDEX(x,y) | Returns a FIXED value indicating the starting position within the character expression x of a substring identical to character expression y.
LENGTH(x) | Returns a FIXED value specifying the current length of a given character expression x.
PARMSET(x) | Used to determine whether a specified parameter has been set on the invocation of a procedure.
SUBSTR(x,y[,z]) | Returns a substring of the character expression x, starting at position y with length z.
TRANSLATE(s,t,x) | Replaces occurrences in the character string s of a character in the specified string x with the corresponding translation character in translation string t and returns the resulting string.
VARIANT | Returns a character string specified on the command line.

Examples

Example 1.

%ACTIVATE COMPILETIME;
%DECLARE TOC CHAR;
%TOC = ''''||COMPILETIME||'''';
PUT LIST ('COMPILED AT' ||TOC);
PUT SKIP;

The text generated by this example would be as follows:

PUT LIST('COMPILED AT '||' 14 NOV 93 15.53.12');
PUT SKIP;

Example 2.

%DECLARE XXX CHAR, COUNTER BUILTIN, I FIXED;
%DO I = 1 TO 4;
%XXX = 'DECLARE NAME_'|| COUNTER || 'FIXED BIN(31);';
XXX
%END;

The text generated by this example would be as follows:

DECLARE NAME_00001 FIXED BIN(31);
DECLARE NAME_00002 FIXED BIN(31)
DECLARE NAME_00003 FIXED BIN(31)
DECLARE NAME_00004 FIXED BIN(31)
Parent topic: Preprocessor Procedures


Features Unsupported by Open PL/I

  • Built-in Subroutines
  • Attributes
  • Options
  • Conditions
  • Statements
  • Constants
  • Items
  • Operations
  • Arrays
  • Others
Parent topic: Open PL/I Language Reference Manual


Built-in Subroutines

The following lists the unsupported built-in subroutines:

  • $ subroutine
  • ASMTDLI subroutine
  • ONCOUNT subroutine
  • PLICANC subroutine
  • PLICKPT subroutine
  • PLIDUMP subroutine
  • PLIREST subroutine
  • PLITDLI subroutine
  • PLITEST subroutine
Parent topic: Features Unsupported by Open PL/I


Attributes

The following lists the unsupported attributes:

  • BACKWARDS
  • COMPLEX
  • EVENT
  • EXCLUSIVE
  • GENERIC
  • GRAPHIC
  • TASK
  • TRANSIENT
Parent topic: Features Unsupported by Open PL/I


Options

The following lists the unsupported options:

  • BACKWARDS
  • COPY
  • DATA
  • ENVIRONMENT options:
    • CTL360
    • GRAPHIC
    • NCP
    • PASSWORD
    • REGIONAL
    • TP
  • EVENT
  • EXCLUSIVE
  • NOLOCK
  • PRIORITY
  • REPLY
  • SNAP
  • TASK
  • TRANSIENT
Parent topic: Features Unsupported by Open PL/I


Conditions

The following lists the unsupported conditions:

  • (NO)CHECK condition prefix
  • (NO)CONVERSION condition prefix
  • (NO)FIXEDOVERFLOW condition prefix
  • (NO)OVERFLOW condition prefix
  • (NO)SIZE condition prefix
  • (NO)STRINGRANGE condition prefix
  • (NO)STRINGSIZE condition prefix
  • (NO)SUBSCRIPTRANGE condition prefix
  • (NO)UNDERFLOW condition prefix
  • (NO)ZERODIVIDE condition prefix
  • CHECK
  • NAME
  • PENDING
  • STRINGRANGE
  • STRINGSIZE
  • SUBSCRIPTRANGE
  • TRANSMIT
Parent topic: Features Unsupported by Open PL/I


Statements

The following lists the unsupported statements:

  • DISPLAY
  • LOCATE
  • UNLOCK
  • WAIT
Parent topic: Features Unsupported by Open PL/I


Constants

  • G(Graphic)
  • GX(Graphic Hex)
  • Imaginary
  • M(Mixed)
Parent topic: Features Unsupported by Open PL/I


Items

  • C-FORMAT
  • E-FORMAT item with significant digits specifier
  • F-FORMAT item with scaling factor specifier
  • G-FORMAT
Parent topic: Features Unsupported by Open PL/I


Operations

The '/' divide operator applied to FIXED BINARY values.

Parent topic: Features Unsupported by Open PL/I


Arrays

  • Array cross-sections
  • Bit(*) arrays are not supported for ANY and ALL array builtins
Parent topic: Features Unsupported by Open PL/I


Others

  • ALLOCATE for controlled variables with attribute
  • iSUB defining
  • PICTURE symbols (A, E, F, K, or X)
  • Structure expressions
  • VARYING bit strings
Parent topic: Features Unsupported by Open PL/I


Glossary

A

application program

A program used to perform a particular data processing task such as inventory control or payroll.

argument

A value passed to an invoked function, procedure, or program.

arithmetic operation

An operation such as addition, subtraction, multiplication, or division that is performed only on numeric fields.

array

An ordered set of values, all having the same data type.

array element

A data item in an array.

array index

The actual number of an element in an array, or the field containing the number or relative position of an element in an array.

attribute

Characteristics the compiler uses to interpret and store the data in a program.

B

based variable

A variable that does not have a block of storage of its own, or an address. Serves as a description of the storage, but a pointer value must be used to supply the address of the storage.

binary

Relating to, being, or belonging to a numbering system with a base of 2. Valid digits are 0 and 1.

binary format

Representation of a decimal value in which each field must be 2 or 4 bytes long. The sign (4. or –) is the leftmost bit of the field and the integer value is in the remaining bits of the field. Positive numbers have a zero in the sign bit and are in two's complement form.

bit string

A sequence of bits.

branching

The technique of bypassing specific instructions or operations to alter the sequential execution of instructions in a program.

by reference

An invoked procedure for a parameter uses the same memory location as the invoking procedure for the corresponding argument.

byte

A group of eight adjacent binary digits that represents one ASCII character.

by value

An argument is copied to a temporary block of storage in the calling routine's stack frame. The parameter is a description of the temporary storage.

C

called program

A program whose execution is requested by another program, a calling program.

calling program

A program that controls the execution of another program, a called program.

comment

Words or statements in a program, command, or file that serve as documentation instead of as instructions.

compilation

Translation of a source program into an executable program.

compiler

A program that translates a source program into an executable program.

compound statement

A statement that includes another statement.

constant

Data that has an unchanging, predefined value to be used in processing. A constant does not change during the execution of a program.

controlled variable

A variable whose storage is dynamically allocated and freed in generations. Controlled variables are allocated oniy when specified in an ALLOCATE statement.

D

data format

Controls the transmission and conversion of a value to or from a stream file.

data set

A collection of data external to a program.

data structure

An area in storage that is composed of one or more subfields. A data structure can be either program described or externally described.

declared name

A name used to denote an object operated upon by the program such as a variable, file, or label.

dynamic

Occurring at execution time.

E

execution

The carrying out of the instructions of a computer program by a processing unit.

expression

Consists of operands and operators.

extent

The range indicated by the bounds of an array dimension (the upper bound minus the lower bound plus 1) and the declared length of a string variable.

external procedure

A procedure not contained within another procedure.

F

factored declarations

Declare statements that contain parenthesized lists of names.

field

An area that is reserved and used for a particular item of information.

file

A named representation of a data set.

file constant

A pointer to, or designator of, a file control block.

file control block

A block of static storage in which information about the current status of a file is retained while the file is opened.

file value

Designates a file control block.

file variable

A variable that can be assigned file values.

format list

A list of format items that controls the transmission of data to or from a stream I/O file.

H

hexadecimal

Pertaining to a numbering system with a base of 16. Valid numbers are the digits 0 through 9 and the characters A through F, where A represents 10 and F represents 15.

I

internal procedure

A procedure nested within another procedure.

K

key

A value which is used to identify a record during an I/O operation.

keyword

A name used to denote part of a statement, such as a verb, option, or clause.

L

label

A symbolic name that represents a specific location in a program. A label can serve as the destination point for one or more branching operations.

M

major structure

A structure that is not a substructure.

members

Immediate components of a structure.

N

name

A single letter, or a sequence of letters, digits, and the underscore character. Also referred to as an identifier.

null pointer value

Unique value that does not address any variable. Indicates a pointer variable and does not address anything.

null string

A string of zero length.

O

ON-unit

A block of statements that are executed if a specifiedcondition occurs.

operand

A constant, a variable reference, a built-in function reference, or an expression.

operation

A defined action performed on one or more data items, such as adding, multiplying, comparing, or moving information.

P

parameter

A name that an invoked function, procedure, or program uses to refer to an argument.

picture

A string of symbols that defines the character occupying the corresponding space.

pictured value

Character-string values that represent fixed-point decimal numbers.

pointer value

The address of a variable's storage.

precision

The number of digits in an arithmetic value.

procedure

A sequence of statements, beginning with a PROCEDURE statement and ending with an END statement. Also referred to as a block.

program

A set of instructions that directs the computer to perform a series of tasks in a specified order. Consists of one or more external procedures.

R

record

A copy of a scalar, structure, or array variable.

record file

A sequence of discrete records that are either accessible sequentially or by character-string valued keys.

reference

A name together with any subscripts, pointer qualifier, or structure names necessary to indicate the purpose of the reference.

S

scalar variable

A variable that can have only a single value.

scope

The distinct region of the program text in which a name can be referenced.

self-defining structure

A BASED structure that contains information about its own fields. The value of one member is used to determine the amount of storage space allocated for another member of the same structure.

separator

A character or series of characters used to separate names, constants, numbers, and character strings.

sequential file

A file into which records are entered one after the other. If the file is keyed, the records are processed in the sequence of the access path.

simple reference

A name without any subscripts, pointer qualifier, or structure names.

stack frame

A block of storage allocated on a stack.

statement

A sequence of tokens ending with a semicolon. Except for assignment statements, all statements start with a keyword.

statement label

A name followed by a colon (:) that prefixes a statement.

stream file

A sequence of characters organized into lines and pages.

structure

A hierarchically ordered set of values that may be of different data types.

structure qualified reference

A sequence of names written left-to-right in order of increasing level numbers.

subscript

An integer valued expression used to reference an element of an array.

subscripted reference

A name that has been declared as an array, followed by a parenthesized list of subscript expressions.

substructure

A structure that is itself a member of another structure.

T

token

A name, constant, punctuation symbol, comment, or compile-time text modification statement.

V

variable

A name to which a value can be assigned during the execution of a program. A variable can only take on values of the type specified in its variable declaration.

Parent topic: Open PL/I Language Reference Manual


Open PL/I User's Guide

This book shows you how to operate Micro Focus's Open PL/I application.

  • Using Open PL/I
    This chapter explains how to install the Open PL/I Compiler and how to enter, compile, link, and run Open PL/I programs.
  • Language Concepts
    This chapter describes the Open PL/I language implementation for your system. For detailed information on the Open PL/I programming language, see your Open PL/I Language Reference Manual.
  • Open PL/I SQL Options
    This Chapter describes the SQL Options available with Open PL/I. These include the DB2 SQL Option that provides support for IBM's DB2 on UNIX and the Pro*PL/I Option that provides support for Oracle versions 10 and 11 on UNIX.
  • Open PL/I Source Checker
    This chapter introduces you to the Open PL/I Source Checker.
  • Open PL/I Compiler Diagnostic Messages
    This appendix describes the format of Open PL/I compiler diagnostic messages and their levels.
  • Open PL/I Run-time Error Messages
    This appendix contains information on Open PL/I run-time errors, UNIX system error codes, and Open File Manager (OFM) error codes. Run-time errors are detected by the Open PL/I run-time system, or by the operating system.
  • Value Table for ONCODE Built-in Function
    You may use the ONCODE built-in function in any unit to determine the nature of the error condition that caused invocation of that ON-unit. This appendix lists the values returned by the ONCODE built-in function and the errors or conditions corresponding to each value.
  • Character Sets
    This appendix provides you with the ASCII equivalents of EBCDIC characters.
  • Migration to Micro Focus File Formats
Parent topic: Open PL/I 8.1 for UNIX


Using Open PL/I

  • Compiling a Program
  • Linking a Program
  • Running a Program
  • Using Open PL/I with Other Software Products
Parent topic: Open PL/I User's Guide


Compiling a Program

Open PL/I consists of the following executable programs:

  • The Open PL/I Macro Preprocessor, named mfpp
  • A CICS preprocessor
  • A DB2 Preprocessor
  • The Compiler itself, named mfpli
  • A command-line driver that allows compiling and linking in one step, named mfplx
  • An interactive menu-oriented program for managing indexed (VSAM) files, named mfvsam

Note that in the names mfpli and mfplx the fourth character is the lowercase letter "L".

mfpp is executed prior to the compilation, and its output is passed to the Open PL/I Compiler.

You can run mfpp directly, but the recommended way to run it is by use of the -macro option with mfplx when you are compiling your program. This allows the mfpp output to be automatically directed to the Compiler.

mfpli allows only one filename, accepts only Open PL/I Compiler options, and requires a separate ldpli step. The suffix of the filename to be compiled by mfpli is not restricted.

mfplx allows multiple filenames and accepts mfpli options as well as many standard UNIX or Windows system compiler and linker options, such as -c and -o. The -c option specifies compilation without linking. When -c is used, the -o option is passed to the compiler; when -c is not used, -o is passed to ldpli. Note that some file name suffixes are restricted to .pl1 or .pli when using mfplx.

mfvsam allows the creation of an indexed file, the addition or deletion of an index to an indexed file, and the display of information about an indexed file.

The CICS preprocessor converts EXEC statements into native PL/I code that is then possibly further macro processed and then finally compiled and linked.

The DB2 preprocessor processes SQL statements before the compilation.

See the following sections for descriptions of the syntax to invoke mfpp, mfpli, mfplx, or mfvsam.

  • mfpp Syntax
  • mfpli Syntax
  • mfplx Syntax
  • mfvsam Syntax
  • Preprocessor Order of Execution
  • mfplx Options
  • Macro Preprocessor Options
  • CICS Preprocessor Options
  • DB2 Preprocessor Options
  • Compiler Options
  • Compiler Listings
  • Open PL/I Compiler Implementation Limits
  • Compilation Statistics
  • Temporary Files
  • Optimization
Parent topic: Using Open PL/I


mfpp Syntax

The valid format for the mfpp command is:

mfpp [–ipath dir][-{isuffix|x} suffix] [–pp outfile]infile

where dir is a directory name, suffix defines a string to be appended to any unquoted filename in a %INCLUDE statement, infile specifies a source filename, and outfile specifies an output filename. At least one input file must be specified.

The preprocessor input is a file containing an Open PL/I source module, possibly including Open PL/I Macro Preprocessor statements. The preprocessor output is an Open PL/I source module containing no further preprocessor statements, but with the source code modified according to the semantics of the preprocessor statements that were encountered in the input file.

mfpp is usually run by use of the -macro option with mfplx.

Parent topic: Compiling a Program
Related information
Macro Preprocessor Options


mfpli Syntax

The valid format for the mfpli command is:

mfpli [option] ... file [option]...

where option represents a Compiler option and file represents any single specified source file. There is no restriction on the suffix of the filename. option arguments can go either before or after file. (An error may result if the -I or -o option appears before file without specifying a list filename or object filename.)

Parent topic: Compiling a Program


mfplx Syntax

The valid format for the mfplx command is:

 mfplx {option | source_file | object_file} ...

where option represents an Open PL/I Compiler option or a system Compiler or linker option.

source_file represents any specified source file. Files with a .pl1 or .pli suffix are passed to mfpli. On UNIX systems, files with an .s suffix are passed to the system assembler. On Windows systems, files with an .asm suffix are passed to the system assembler.

mfplx supports wildcard characters and indirect files (@files).

object_file represents any specified object file (with an .o suffix for UNIX systems or a .obj suffix for Windows systems) or any specified library (with an .a suffix for UNIX systems or an .lib suffix for Windows systems). Files with an .o (or .obj) or an .a (or .lib) suffix are passed to mfpli, as are specified files with unknown or absent suffixes. The command line that mfpli constructs for each of these invocations is limited to 4096 characters. The .o files can be linked (possibly with other object files and/or libraries) using ldpli or mfplx -o.

mfplx processes options in one of the following ways:

  • Passes the option to the preprocessor (mfpp).
  • Passes the option to the compiler (mfpli).
  • Passes the option to the linker (ldpli).
  • Executes the option (for example, -c) in a fashion similar to cc.
  • Ignores the option.

Program execution begins at the main entry point.

Parent topic: Compiling a Program
Related information
Compiler Options
Compiling a Program
Linking a Program
Main Procedure


mfvsam Syntax

The mfvsam utility is invoked by the command mfvsam. This utility offers the following options when invoked:

  1. Display information about a VSAM file.
  2. Create a VSAM file.
  3. Add an index to a VSAM file.
  4. Delete an index from a VSAM file.
  5. Exit.
Note:

The mfvsam utility currently produces indexed data files using the C-ISAM format only.

Parent topic: Compiling a Program


Preprocessor Order of Execution

The Open PL/I preprocessors are run by mfplx in the following order:

  1. Open PL/I Macro Preprocessor
  2. CICS Preprocessor
  3. Open PL/I Macro Preprocessor
  4. Oracle Pro*PL/I Preprocessor or DB2 Preprocessor

The ordering of the Compiler switches you use has no impact.

You may change the order, if necessary, by separately invoking the preprocessor you choose.

It is recommended that you run the preprocessors in this order via mfplx, but if you want to run the preprocessors separately, run mfplx with the preprocessor arguments you want and the -# flag to see what command lines are generated.

The running of the preprocessor is controlled by the following flags:

  • -macro [-pp [output_file]]
  • -cics [-ppcics [output_file]]
  • -db2 [-ppdb2 [output_file]]

-macro, -cics and -db2 cause respective preprocessors to run. -pp, -ppcics, -ppdb2 cause the preprocessor's output to be kept and the optional output_file says to give the output file a particular name.

  • Examples
Parent topic: Compiling a Program


Examples

Example 1: Equivalent to an ordinary compilation with -macro.

The command line

mfplx -macro sample.pl1 -#

produces:

mfpp sample.pl1 -pp sample.pp
mfpli sample.pp -o sample.o
rm -f sample.pp
ldpli sample.o

Example 2: Equivalent to an ordinary compilation with -macro and two preprocessors.

The command line

mfplx -db2 -macro sample.pl1 -cics -#

produces:

mfpp sample-pl1 -pp sample.pp
mfcics -i sample.pp -o sample.pp1
mfpp sample.pp1 –pp sample.pp2
mfdb2 -i sample.pp2 -o sample.pp3
mfpli sample.pp3 -o sample.o
rm -f sample.pp sample.pp1 sample.pp2 sample.pp3
ldpli sample.o

Example 3: Run macro preprocessor and CICS preprocessor only, preserving the intermediate output files.

The command line

mfplx -E sample.pl1 -macro -cics -#

produces:

mfpp sample.pl1 -pp sample.pp
mfcics -i sample.pp -o sample.pp1
mfpp sample.pp1 –pp sample.pp2

Example 4: Ordinary compile, preserving CICS preprocessor output.

The command line

mfplx -cics -ppcics cicsout.out sample.pl1 -#

produces:

kixplt -i sample.pl1 -o cicsout.pl1
mfpli cicsout.pl1 -o sample.o
ldpli sample.o

Example 5: Multiple compilations.

The command line

mfplx -db2 -cics sample.pl1 sample2.pl1 -#

produces:

sample.pl1:
mfpp sample.pl1 -pp sample.pp
mfcics -i sample.pp -o sample.pp1
mfpp sample.pp1 -pp sample.pp2
mfdb2 -i sample.pp2 -o sample.pp3
mfpli sample.pp3 -o sample.obj
del sample.pp sample.pp1 sample.pp2 sample.pp3
sample2.pl1:
mfpp sample2.pl1 -pp sample2.pp
mfcics -i sample2.pp -o sample2.pp1
mfpp sample2.pp1 -pp sample.pp2
mfdb2 -i sample.pp2 -o sample2.pp3
mfpli sample2.pp3 -o sample2.obj
del sample2.pp sample2.pp1 sample.pp2 sample2.pp3
ldpli -db2 sample.obj sample2.obj
Parent topic: Preprocessor Order of Execution


mfplx Options

mfplx allows multiple filenames and accepts mfpli options as well as many standard UNIX or Windows system compiler and linker options, such as -c and -o. The -c option specifies compilation without linking. When -c is used, the -o option is passed to the compiler; when -c is not used, -o is passed to ldpli. Some of the options available for use with the mfplx command are explained in the following table.

Option | Explanation
-cics | Invokes the CICS preprocessor.
-vtrace | Micro Focus Tracing Option
-ptrace | Micro Focus Tracing Option
-ctrace | Micro Focus Tracing Option
-littleendian | Default to LITTLEENDIAN integers.
-bigendian | Default to BIGENDIAN integers.
-deb | Generates debug code for CodeWatch.
-not_symbol | Selects alternate NOT symbol
-or_symbol | Selects alternate OR symbol
Parent topic: Compiling a Program


Macro Preprocessor Options

The options available for use with the mfpp command are explained in the following table. The -ipath and -suffix options obey the rules that apply when they are invoked as compiler options.

Option | Explanation
-currency_symbol | Provides a currency symbol for picture specification. It can take the character, decimal number, or hex constant of the form 0xDD, for example, -currency_symbol £, -currency_symbol 163, -currency_symbol 0xa3.
-define name[=value] | Causes value to be used in place of name wherever the identifier name appears.
-includes | Tells the preprocessor to process %INCLUDE statements.
-ipath dir | The -ipath and -suffix options obey the rules that apply when they are invoked as Compiler options.
-isuffix suffix (or -x suffix) | The -ipath and -suffix options obey the rules that apply when they are invoked as compiler options.
-margins I,r Sets the margins within which characters of the source file are interpreted as source code and outside which all characters are ignored by the Compiler. l is the column number of the leftmost character and r is the column number of the rightmost character to be interpreted as source code. Note that, if tabs are used, each tab is counted as a single character.

The -margins option on a *PROCESS card is ignored if the macro pre-processor is in use (either by executing mfpp or mfplx with the -macro option); in this case, if the source margins are not 1,256, the actual margins must be specified with the -margins option.

-nodebuginfo | Specifies that the preprocessor will not generate the normal debug information that it passes to the Compiler. This is useful if you wish to debug using the post-preprocessing PL/I source file rather than the original source file.
-noincludes | Tells the preprocessor not to handle %INCLUDE statements.
-[no]namesstring1 [string2] Provides extended character support. For example,
-names 'string1' ['string2']
where string1 are extralingual characters to add to identifiers, and string2 are optional corresponding uppercase characters. Hex constants of the form 0xDD are accepted in place of the strings. The default is -names.
-not_symbol | Provides a not symbol. It can take the character, decimal number, or hex constant of the form 0xDD.
-or_symbol | Provides an or symbol. It can take the character, decimal number, or hex constant of the form 0xDD.
-pp outfile (or -o outfile) | Names the output file the name you specify with outfile. If -pp is not specified, the default name of the file is xxx.pp, where xxxis the input filename up to, but not including, the last "." (if any) in the name. For example, if the input filename is prog.pl1, the default output filename is prog.pp.
-T | Causes the preprocessor to examine a %INCLUDE file name for the characters @, #, and $, and to replace @ with A, # with N, and $ with D.
-undefine name | Removes a definition for name, if name was created by a -define option, and leaves the identifier name in the source as name. It does not preclude a %REPLACE statement or %name=expr from changing the value of name.
-variant string | Supplies a string to be used in place of the VARIANT built-in function.
Parent topic: Compiling a Program


CICS Preprocessor Options

The CICS Preprocessor Options are explained in the following table.
Option | Explanation
-# | Displays the mfexecpp command line.
-i | Specifies input file.
-o | Specifies ouput file.
-margins | Specifies the margins (-margins left,right)
-or_symbol | Selects alternate OR symbol
-not_symbol | Selects alternate NOT symbol
-deb | Allows debugging.
-vtrace | Micro Focus Tracing Option
-ptrace | Micro Focus Tracing Option
-ctrace | Micro Focus Tracing Option
-bigendian | Default to BIGENDIAN integers. Note: It is applied by default.
-nonnative | Default to BIGENDIAN integers.
-native | Default to LITTLEENDIAN integers.
Parent topic: Compiling a Program


DB2 Preprocessor Options

The DB2 Preprocessor options are listed in the table below:

-action | Refer to the IBM DB2 documentation.
-bind | Specifies that a bind file should be created.
-bindname | Specifies name of bindfile to create.
-block | Specifies type (unambig, all or no) of row blocking.
-catalog | Refer to the IBM DB2 documentation.
-charsub | Refer to the IBM DB2 documentation.
-connect | Specifies if the CONNECT statement should be of type 1 or 2.
-collection | Specifies the collection shema name.
-datetime | Specifies date/time format (def, usa, eur, iso, jis, loc).
-dbname | Specifies name of database to precompile against.
-dec | Refer to the IBM DB2 documentation.
-decdel | Refer to the IBM DB2 documentation.
-degree | Refer to the IBM DB2 documentation.
-disconnect | Refers to disconnections (explicit, automatic or conditional).
-dynamicrules | Refer to the IBM DB2 documentation.
-explain | Refer to the IBM DB2 documentation.
-explsnap | Stores Explain snapshot (no, all or yes)
-funcpath | Specifies func path for types and functions in static SQL.
-insert | Refers to data buffering (def or buf).
-isolation | Specifies isolation level (ss, rr, ur).
-level | Refer to the IBM DB2 documentation.
-nobind | Specifies that no .bnd file is created.
-nooptimize | Specifies that no SQLDA initialization optimizations are done.
-package | Causes package creation.
-packagename | Specifies name of package. Implies -package.
-optimize | Specifies that SQLDA initialization optimizations are done.
-optlevel | Same as -optimize. Impacts initializations of SQLDAs.
-owner | Refer to the IBM DB2 documentation.
-queryopt | Optimization of static SQL. The default level is 5.
-qualifier | Refer to the IBM DB2 documentation.
-release | Refer to the IBM DB2 documentation.
-replver | Refer to the IBM DB2 documentation.
-retain | Refer to the IBM DB2 documentation.
-schema | Refer to the IBM DB2 documentation.
-sqlerror | Specifies action following error(s).
-sqlflag | Reports on deviationson SQL syntax.
-sqlrules | Refers to connects (std or db2).
-sqltwop | Performs two passes because variable usage proceeds declarations.
-sqlwarns | Refers to dynamic SQL.
-stds | Refer to the IBM DB2 documentation.
-syncpoint | Refers to commits or rollbacks (onephase, none, twophase)
-syntax | Suppresses package or binding. Validity checking.
-text | Refer to the IBM DB2 documentation.
-validate | Refer to the IBM DB2 documentation.
-version | Refer to the IBM DB2 documentation.
Parent topic: Compiling a Program


Compiler Options

The list below describes each of the Compiler options and its default setting, when applicable.

-#
Provides information on how the Compiler and linker would be invoked without actually invoking them. This option also shows which UNIX options are translated to Micro Focus options; for example, when the standard UNIX -O option is given on the driver command line, it is translated on the Compiler invocation line as -opt.
--agginit
Performs initialzation of aggregates (arrays and structures) compatible with 7.x versions of Open PL/I.

Example:

dcl myarr(4) fixed bin(31) static init (1);
put skip list (myarr);

results in:
             1               1               1               1

By default, without -agginit, only the first element is initialized.

-bigendian
Specifies that all fixed binary items are implicitly declared with the BIGENDIAN data attribute, unless the NATIVE attribute is explicitly applied to a data item.
-c
Suppresses linking and produces a relocatable object file. This option applies to mfplx only.
-check
This option, which can be used only with mfplx, causes the Open PL/I Source Checker to be run instead of the Open PL/I Compiler.
-cicsdebug
Allows use of CodeWatch to debug the PL/I code generated by the CICS precompiler for EXEC CICS statements, rather than debugging with the original source code. Also, causes Compiler diagnostics to use line numbers referencing the CICS precompiler output file. The -cicsdebug command applies to mfplx and kixplt only.
-currency_symbol
Allows an alternate currency symbol for picture specification. It can take a character, decimal number, or hex constant of the form 0xDD, for example, -currency_symbol £, -currency_symbol 163, -currency_symbol 0xa3.
-db2
Invokes the DB2 precompiler, mfdb2. The default DB2 precompiler output file name is xxx.pp2, where xxx is the name of the source file. If the -ppdb2 option is not specified, the file xxx.pp2 is deleted after the compilation phase is completed. The -db2 option applies to mfplx only.
-deb
Produces debugging information for CodeWatch, Micro Focus's source-level debugger. You must specify this option if you intend to use CodeWatch to debug this source. When using -deb, you may specify only optimization levels 1 or 2.
-default_binary
Causes the BINARY attribute to be assumed if the FIXED attribute is specified without BINARY or DECIMAL.
-default_decimal
Causes the DECIMAL attribute to be assumed if the FIXED attribute is specified without BINARY or DECIMAL. This option is the Compiler default.
-defext
Causes external variables to be defined in the .data section. You must use this option for programs using external files.

The -defext option causes the initialized values of STATIC EXTERNAL variables and external file constants to be defined. Each STATIC EXTERNAL variable that has an INITIAL value must be declared in one and only one module that has been compiled with -defext. Failure to do so causes the INITIAL value to have no effect. The default is -nodefext.

Also, each file constant must be declared in one and only one module that has been compiled with -defext. When -defext is used, file attributes specified in the file declaration will be merged with attributes specified when the file is opened. This is critical when doing VSAM/INDEXED I/O.

-E
Causes any specified precompilers or preprocessor (-macro, -unikix, -db2, -oracle) to be run on the source file, and saves their output, but stops without running the Compiler.
-exp
Produces an expanded listing of the generated code in the form of assembly language statements in the listing file.
-fdasfb
Causes Float Decimal data to be internally coded as Float Binary. This option produces much faster code but loses precision in the least significant digits of arithmetic results. -fdasfb is the default. See also the -nofdasfb option.
-flag
Specifies the minimum diagnostic level of messages listed in the compiler listing.
-flag minimum diagnostic level
The minimum diagnostic level can be:
I
Emits diagnostic messages beginning at the Informational level (Lists all messages. This is the default).
W
Emits diagnostic messages beginning at the Warning level.
E
Emits diagnostic messages beginning at the Error level.
S
Emits diagnostic messages beginning at the Severe level.
A
Abort.
-fmaxp
Causes extended floating-point precision to be used for the trigonometric built-ins and for the following arithmetic built-ins: EXP, LOG, LOG10, LOG2, SQRT. -fmaxp is the default.
-highbif
This compile-time switch allows changing the value returned by the HIGH() built-in function. For example, -highbif 127 (the default value is 255; the value 127 maybe used for compatibility with earlier versions of Open PL/I).
-ipath dirlist
Directs the Compiler to search specified directories for files to be included in the source program text by use of the %INCLUDE statement. dirlist is an ordered list of directories of the form
dirname[:dirname] ...

-ipath instructs the Compiler to use these directories in the specified order in its search for files to satisfy %INCLUDE statements (except in cases where an absolute directory path is specified in the %INCLUDE statement).

For example, suppose the source program contains:

%INCLUDE partlist;

and the Compiler invocation command is:

mfplx source_file -ipath .:/u/libr1:/u/libr2

In this case, the Compiler will first search for "PARTLIST" in the current working directory, then /u/ libr1, and finally /u/ libr2. If that fails, it will search for "partlist" (lowercase) in the same directories.

In a Windows environment, the equivalent Compiler invocation is:

mfplx source_file -ipath .;drive:\libr1;drive:\libr2
-isuffix string
Causes string to be appended to the filename specified in %INCLUDE statements, except those in which the quoted filename form of the %INCLUDE statement is used.

For example, suppose the source program contains:

%INCLUDE partlist;

and the Compiler invocation command is:

mfplx source_file -isuffix .INC

In this case, the Compiler will search for a file named "PARTLIST.INC".

-l [ file]
Produces a Compiler listing where file is the name of the file to which the listing is output. If you do not supply a filename, you must place this option after the source filename on the command line; otherwise, an error message appears. The default name of the file containing the listing is xxx.list, where xxx is the source filename (excluding the pathname) up to, but not including, the last "." (if any) in the name. For example, if the source filename is prog.pl1, the default listing is prog.list (prog.lst for Windows systems). A Compiler listing is produced by default whenever -exp, -map, or -xref is specified.
-longint
Changes the default precision of Fixed Binary variables from (15) to (31).
-lowercase
Converts all uppercase names of internal and external variables and constants to lowercase.
-macro
Invokes the Open PL/I Macro Preprocessor, mfpp. The default preprocessor output file name is xxx.pp, where xxx is the name of the source file. If the -pp option is not specified, the xxx.pp file is deleted after the compilation phase is completed. The -macro option applies to mfplx only.
-map
Produces a storage allocation map at the end of the listing file.
-margins 1,r
Sets the margins within which characters of the source file are interpreted as source code and outside which all characters are ignored by the Compiler. 1 is the column number of the leftmost character, and r is the column number of the rightmost character to be interpreted as source code. Note that if tabs are used, each tab is counted as a single character. The -margins option can be overridden by a *PROCESS statement in the source.
Note: There must be no spaces around the comma separating the left and right margin.
-nest
Indicates the nesting level on the listing of DO ... END, PROC ... END, and so on.
-nocicsdebug
Allows use of CodeWatch to debug the original source file, rather than the intermediate file generated by the CICS precompiler. Also, causes Compiler diagnostics to use line numbers referencing the original source file. This is the default. The -nocicsdebug command applies to mfplx and kixplt only.
-nofdasfb
Causes Float Decimal data to be internally coded as Binary Coded Decimal. The default setting is -fdasfb.
-nofmaxp
Causes standard PL/I conversion rules to be used to determine the precision of trigonometric and certain arithmetic built-ins. The default is -fmaxp.
-noincludes
Directs the Compiler not to include the contents of %INCLUDE files in the listing file. The default is to include file contents in the listing file.
-nomacro
Suppresses the invocation of the Open PL/I Macro Preprocessor. The default is -nomacro.
-[no]namesstring1 [string2]
Provides extended character support. For example,
-names 'string1' ['string2']
where string1 are extralingual characters to add to identifiers, and string2 are optional corresponding uppercase characters. Hex constants of the form 0xDD are accepted in place of the strings. The default is -names.
-noobj
Compiles for syntax and semantic checking only. Does not produce an object file.
-noopt
Compiles without optimization. This is the default.
-norange
Suppresses generation of code to check the validity of subscript references. This option should be used after your program has been debugged to improve execution time performance. The default is -norange.
-not_symbol
Allows an additional NOT symbol. It can take a character, decimal number, or hex constant of the form 0xDD. See also %PROCESS in the Language Reference Manual.
-nounixdebug
Avoids generating the additional object file data needed to report source file and line number when a fatal run-time error occurs, or for use by the ONLOC built-in function.
-nounrefexternals
Prevents external entry symbols that are not referenced in the program from being generated in the object file. This is the default.
-nowarn
Suppresses all WARNING level diagnostics.
-O
Invokes the optimization phase of the Compiler. This option applies to mfplx only and is equivalent to the -opt option.
-o file
Names the object file the name you specify with file. If -o is not specified, the default name of the file is xxx.o, where xxx is the source filename up to, but not including, the last "." (if any) in the name. For example, if the source filename is prog.pl1, the default object filename is prog.o (prog.obj for Windows).

If -c is specified, the -o option is passed to the compiler; if -c is not specified, -o is passed to ldpli.

-oldalign
Causes the Compiler to allocate Character Varying items and align structure members compatible with releases prior to Open PL/I 6.0.
-opt [level]
Specifies the level of optimization by the Open PL/I Compiler, where level stands for the level (1 – 3) of optimization. The default setting is -noopt. If level is not included, the program is optimized at level 3. If -deb is specified, -opt 2 is the maximum level allowed. Note, -opt -deb is equivalent to -opt 2 -deb.
-or_symbol
Allows an additional OR symbol. It can take a character, decimal number, or hex constant of the form 0xDD. See also %PROCESS in the Language Reference Manual.
-pic
Generates position-independent code, suitable for linking into a shared library. This option is only available on Solaris, SUSE Linux and Red Hat Linux.
-pl1g
Causes Open PL/I to retain the behavior of releases prior to Open PL/I 5.0 for certain operations that have been changed in such a way as to become incompatible with that former behavior. For example, TIME() returns a value including three fractional digits (thousandths), but -pl1g causes it to return only two fractional digits (hundredths).
-pp [file]
Specifies the file name for the output file of the Open PL/I Macro Preprocessor. An output file created with the -pp option is preserved after the compilation phase is completed. This option applies to mfplx and mfpp only.
-ppcics [file]
Specifies the file name for the output of the CICS precompiler. An output file created with the -ppcics option is preserved after the compilation phase is completed. This option applies to mfplx only.
-ppdb2 [file]
Specifies the file name for the output of the DB2 precompiler. An output file created with the -ppdb2 option is preserved after the compilation phase is completed. This option applies to mfplx only.
-proto
Provides more extensive prototype checking on arguments vs. parameters in entry declarations (also assumed by default when using -vax).

Example:

declare myproc external entry(
      fixed binary(31),
      fixed binary(15),
      fixed binary(15));

   myproc: procedure(a,b,c);        /* mismatch diagnosed, -proto and -vax */
      declare a fixed binary(15);
      declare b fixed binary(15);
      declare c fixed binary(15);

   end t660;
-range
Generates code to check the validity of all subscript references. (Note that checking code slows down execution time performance.) We recommend that this option be used to debug programming errors relating to subscripting, and that the -norange option be used for debugged code. The default is -norange.
-report [file]
Specifies the file name for the output of the Open PL/I Source Checker. If this option is not used, the output of the checker will be directed to the standard error file. This option applies to mfplx only.
-setnull n
Designates a null pointer value n to be returned by the NULL built-in function, where n is a decimal value. If this option is not specified, the value of the NULL built-in function is an address with all bits set to 1.
-stardesc
Tells the Compiler to produce argument descriptors for calls only when array bounds or string lengths in the parameter declaration are represented by the asterisk (*) symbol. (This was compiler behavior in releases prior to release 7.0.) When this option is not used, the Compiler produces descriptors for array, structure, and string arguments, which can be a problem for very large structures.
-stat
Prints Compiler statistics to the standard output as each Compiler phase completes.
-unaligned
This compile-time switch has been added for use on RISC architectures. This switch causes byte instructions to be generated for all based references, which might point anywhere in memory.
-unikix
Invokes the CICS precompiler, kixplt. The default CICS precompiler output file name is xxx.pp1, where xxx is the name of the source file. If the -ppcics option is not specified, the file xxx.pp1 is deleted after the compilation phase is completed. The -unikix option applies to mfplx only.
-unrefexternals
Causes external entry symbols to be generated in the object file, even if they are not referenced in the program.
-v
Prints information to stdout relating to the compilation and link-step phases. This option applies to mfplx only.
-variant string
Passes the variant string string to the Open PL/I Macro Preprocessor. This option applies to mfplx only.
-vax
Makes the following adaptations for programs originally written with Digital Equipment Corporations's PL/I Compiler for the VAX platform:
  • Enables the Fixed Binary(p ? 7) data type as a one-byte signed binary integer.
  • Enables Float Binary(24) as equivalent to Float Binary(23).
  • Enables Float Binary(53) as equivalent to Float Binary(52).
  • Causes the BINARY attribute to be assumed if the FIXED attribute is specified without BINARY or DECIMAL.
-warn
Does not suppress level 1 (WARNING) messages. This is the default.
-xref
Produces cross-reference information in the listing file.
-zp1
Causes all structures to be mapped as if the UNALIGNED attribute is specified at the level 1 structure level. This option is for compatibility with versions of DEC VAX PL/I.
  • Intel-Specific Options
Parent topic: Compiling a Program
Related reference
%PROCESS
Related information
Open PL/I Source Checker
Optimization
The -exp Option
The -l Option
The -map Option
External Names
Open PL/I Compiler Diagnostic Messages
Compilation Statistics


Intel-Specific Options

The Intel-specific options and their default settings are listed below. Use the default settings of the Compiler options to generate the most efficient code for your system.

-codealign argument
Controls alignment of the generated code where argument is a concatenation of one or more of the following suboptions. Note that each suboption must be followed by a number that is one of 4, 8, or 16; this subargument is referred to as align in the descriptions.
j | Align each label that follows an unconditional jump or a return to be at an address such that mod(address, align)=0. The NOPs that are inserted are never executed.
e | Align each entry point such that mod(address, align)=0.
I | Align loop tops such that mod(address, align)=0.
h | Use heuristics to attempt to align labels that do not follow jumps such that mod(address, align)=0, but without inserting any NOP instructions. If align is followed by ".1", alignment will be such that mod(address, align)=0 or 1. The suboptions tell the Compiler where to insert NOP instructions to force the address of critical instructions in generated code to be aligned on boundaries that improve the performance of jumps and calls to those instructions.
-f287
Generates Intel287 floating-point coprocessor instructions where possible. This is the default if an Intel387 coprocessor is not present.
-f387
Generates Intel387 floating-point coprocessor instructions where possible. This is the default if an Intel 80387 coprocessor is present. If an Intel387 coprocessor is not present, the default generates Intel287 floating-point instructions.
-i386
Produces code for the Intel386 processor avoiding optimizations designed for the Intel486 processor. Programs compiled with the -i386 option run correctly on the Intel486, but may perform better when they are compiled with the -i486 option. -i386 is the default when the Compiler is run on an Intel386 processor.
-i486
Produces code for the Intel486 processor, using optimizations designed for the Intel486. Programs compiled with the -i486 option may not run on an Intel386 processor. -i486 is the default when the Compiler is run on an Intel486 processor.
-ix86
Produces code that will run well on both the Intel486 and the Pentium CPUs.
-Pentium
Produces code for the Pentium processor. This is the default when the Compiler is run on a Pentium processor.
Parent topic: Compiler Options


Compiler Listings

The Compiler listing options are:

  • -l (list)
  • -map (storage allocation map)
  • -xref (cross-reference)
  • -exp (expanded code)

All listing information is directed to the listing file. When any of the listing options are specified, the -l option is invoked by default.

  • The -l Option
  • The -map Option
  • The -xref Option
  • The -exp Option
Parent topic: Compiling a Program


The -l Option

The -l option produces a listing file, which is named by default with the source program name (up to but not including the last ".") and the suffix .list. You can choose another name for the listing file by specifying a name after the -l option, in the following format:

-l file

The listing file contains a program listing, which consists of a copy of the source program with line numbers beginning at 1 in a column to the left of the source line.

Parent topic: Compiler Listings


The -map Option

The -map option produces a storage allocation map, which displays the location and allocation size of each program entity. The map categorizes this information by name, class, size, location, and attributes.

This information is presented in five columns:

Column | Description
NAME | Indicates the name of each entity in the program.
CLASS | Indicates the storage class of each program entity; for example, AUTOMATIC, CONSTANT, STATIC, PARAMETER, CONTROLLED, or BASED.
SIZE | Indicates the size of the entity, usually in bytes. If the size is measured in bits, the size number is followed by a B. If the size of the entity is not constant, a -V- is displayed in the location listing. Entities of class ENTRY or BUILTIN have no size or location listing.
LOCATION Gives the offset location of the entity in hexadecimal notation.
  • For automatic variables, the location column gives the memory offset from the frame pointer
  • For static variables, it gives the memory offset from the beginning of static data
  • For controlled and based variables, it displays the value -V-
ATTRIBUTES Displays the data type of the entity, for example, FIXED DEC, FLOAT BIN, CHAR, CHAR VAR, BIT ALIGNED, and ENTRY.

Displays BUILTIN for an entity of BUILTIN class. Displays the precision and scale of the entity, where applicable, in parentheses: for example, FIXED BIN(15,0).

Program entities are listed in the order in which they appear in the procedure.

The map first lists external entry points to the program: external constants, subroutines, or programs, including the source program itself. These entry points are listed with name, class, and attributes.

The map then lists program procedures and entities by line number.

Parent topic: Compiler Listings


The -xref Option

The -xref option provides cross-reference information for each program entity, displaying the line number on which it was declared and the line numbers of all references to it.

The -xref listing for a program is added to the map listing; when you specify the -xref option, you receive a data storage allocation map by default. The cross-reference information appears on the map in the ATTRIBUTES column for each entity, after the line of map attributes information.

References to each entity are listed in the following format:

 DEF line_number REF line_number[...]

A sample map listing with the -xref option follows.

Figure 1-1 Sample Output from the -xref Option

EXTERNAL ENTRY POINTS
NAME         CLASS           SIZE  LOCATION  ATTRIBUTES
SYSPRINT     CONSTANT                        FILE EXTERNAL
                                             DEF 41 REF 41 48 49
PRIMES       CONSTANT                        ENTRY(MAIN)EXTERNAL
PROCEDURE PRIMES ON LINE 10
NAME         CLASS           SIZE  LOCATION  ATTRIBUTES
STORE_CLASS  CONSTANT                        ENTRY
                                             DEF 90 REF 45
ARITH_STR    CONSTANT                        ENTRY
                                             DEF 56 REF 43
PROCEDURE ARITH_STR ON LINE 56
NAME         CLASS           SIZE  LOCATION  ATTRIBUTES
DECIMAL      BUILTIN                   BUILTIN
ESC          AUTOMATIC 6     FFFFFFD8  PICTURED
FLT_BIN      AUTOMATIC 4     FFFFFFE4  FLOAT BIN(15)
                                       DEF 63 REF 71
FIX_DEC      AUTOMATIC 3     FFFFFFEC  FIXED DEC(4,2)
                                       DEF 62 REF 70
CHR_STR      AUTOMATIC 4     FFFFFFEO  CHAR(4)
                                       DEF 61 REF 69
BIT_STR      AUTOMATIC 4B    FFFFFFD4  BIT(4)
                                       DEF 60 REF 68
PROCEDURE STORE_CLASS ON LINE 90
NAME         CLASS     SIZE  LOCATION  ATTRIBUTES
NUMBER       AUTOMATIC 16B   FFFFFFE8  UNION
 FIXED_N     MEMBER    2     00000000  FIXED BIN(15,0)
 FIXED_N_BIT MEMBER    16B   00000000  BIT(16)
STAT_A_EX    STATIC    3     External  FIXED DEC(5,0)EXTERNAL
Y            BASED     4     -V-       FLOAT BIN(23)
Parent topic: Compiler Listings


The -exp Option

The -exp option produces an expanded code listing at the end of the listing file, providing the location and low-level language translation for each instruction and label in the program. The following information is displayed for each statement, in five columns:

Column | Displays
First | The source statement line number.
Second | The offset location of each instruction in the statement.
Third | The hexadecimal representation of each instruction.
Fourth | The instruction in a pseudo-assembly code dialect.
Fifth | Information about the operands used by each instruction.
Parent topic: Compiler Listings


Open PL/I Compiler Implementation Limits

The Compiler generates messages if your source program exceeds certain Open PL/I Compiler implementation limits. The following table lists these implementation limits.

Message | Limit
Depth of nesting of a structure | 16
Length of a string constant | 2541
Maximum length of a string constant with repeat specifier | 1018
Maximum length of a character string | 32767
Maximum length of source line | 320
Maximum length of an identifier | 100
Maximum size of storage for AREA data | 32767
Array dimensions | 8
Nesting level of INCLUDE statements | 7
Nesting of DO, PROCEDURE, BEGIN, SELECT, and simple ON-unit statements | 642
Number of arguments in a subroutine or function call | 239
Number of errors | 100
Maximum VSAM key size | 120 bytes
Scale factor of variables | 0 ? scale factor ? 128
Scale factor of a constant | 0 ? scale factor ? 127
Scale factor of a conversion built-in function | 0 ? scale factor ? 127
Value of a format's repeat, w, or d field | 254
Precision for a fixed binary number | 31
Precision for a fixed decimal number | 18
Precision for a float binary number | 52
Precision for a float decimal number | 16
Internal Limits |
Number of tokens in a statement | 20,000
Maximum number of 'Severe' diagnostics before termination 3 | 200
Parent topic: Compiling a Program
1

The actual spelling of the constant is limited to 256 characters, where the spelling includes the surrounding quotation marks, the extra quotation mark when two single quotation marks represent a single quotation mark inside the string, and the possible trailing X in a hexadecimal string constant or the possibly trailing B and optional digit used to terminate bit-string constants.

2

64 including the top level procedure.

3 For other diagnostic levels (Info, Warnifng, Error and Abort) there is no limitation in the number.


Compilation Statistics

The -stat compiler option provides a listing of statistics for each phase of the compilation. The statistics are displayed at the terminal by default or can be redirected to a file. The following figure is a sample terminal display from a UNIX system.

Figure 1-2 Sample Output from the -stat Option (UNIX)

PHASE            USER     SYSTEM    CPU  REAL  13:43:26
Parser Pass 1    0.05       0.02   0.07     0  13:43:26
Declare          0.00       0.00   0.00     0  13:43:26
Parser Pass 2    0.08       0.03   0.11     0  13:43:26
Allocator        0.01       0.00   0.01     0  13:43:27
Code Generator   0.71       0.05   0.76     1  13:43:27
Total            0.85       0.10   0.95     1  13:43:27

Total source lines:                  38
Lines per minute (CPU):           2,400
Lines per minute (real):          2,280

Text size:                 2,574 bytes
Data size:                   914 bytes
Bss Size:                      0 bytes

The following names and describes each of the columns displayed in the printout.

Column | Description
PHASE | Defines the various phases of the compilation. Each phase and its corresponding statistics displays upon completion.
USER | Indicates the CPU time spent on this phase of compilation, excluding CPU time spent by the operating system on behalf of the Compiler.
SYSTEM | Indicates the CPU time used by the operating system while executing the corresponding phase.
CPU | Indicates the CPU time used by the Compiler while executing the corresponding phase. This is simply the sum of USER and SYSTEM.
REAL | Indicates the number of seconds elapsed during the corresponding phase.
The final column | Displays the current time of day in 24-hour notation (on Intel systems only).
Parent topic: Compiling a Program


Temporary Files

Compiler-generated temporary files are normally placed in the /tmp directory. If you wish to put them in your current working directory, use the command appropriate to your shell program.

Bourne/Korn shell users: | TMPDIR=. ; export TMPDIR
C shell users: | setenv TMPDIR .

To store Compiler-generated temporary files elsewhere, specify a pathname by using the command appropriate to your shell program.

Bourne/Korn shell users: | TMPDIR=pathname; export TMPDIR
C shell users: | setenv TMPDIR pathname
Windows users: | set TMPDIR=pathname
Parent topic: Compiling a Program


Optimization

By default, programs are not optimized during compilation. You can specify optimization at level 1, 2, or 3, using the following syntax:

-opt level

For example, "-opt 2". If you specify -opt with no level, level 3 optimizations are performed by default. (Remember that if you use the -deb option, only level 1 or 2 is allowed. If you use -deb and specify -opt with no level, level 2 optimizations are performed.) A brief description of the optimizations performed at each level follows.

Level | Description
1 | Operator pattern replacement and Boolean conditional expression optimizations.
2 | Common subexpression elimination; all level 1 optimizations.
3 All level 1 and level 2 optimizations plus the following:
  • branch chaining
  • dead code elimination
  • strength reduction
  • loop induction
  • loop invariant code motion
  • removal of redundant register saves and loads
  • removal of mathematical identities
Parent topic: Compiling a Program


Linking a Program

You can use either static or dynamic linking of Open PL/I applications. The Open PL/I run-time library is built as a static library (.lib). The ldpli link-step uses the static version of the Open PL/I run-time library by default. To link, use

ldpli -dll [options…]
You also need to add to the command one of the options below:
  • -mvs - for programs executed under the control of JCL.
  • -ims - for programs exacuted under the control of IMS.
  • -cics - for programs exacuted under teh control of CICS.

To link an Open PL/I program, use either mfplx or ldpli.

  • mfplx compiles and links in one step, automatically invoking ldpli if the -c option is not used. For the use of mfplx, see the section mfplx Syntax .
  • ldpli references the components that were installed with this version of Open PL/I and is the recommended link command when using mfpli.
  • Link Options
  • Using ldpli
Parent topic: Using Open PL/I
Related information
mfplx Syntax


Link Options

The table below lists link options that permit the use of Open PL/I with other software products. For more information, see the section Using Open PL/I with Other Software Products.

Option | Explanation
-tisam | Enables the TISAM package from Transarc for VSAM/indexed files, using Transarc's SFS format.
-mvs | Allows linking of programs running under the control of JCL.
-ims | Allows linking of programs running under the control of IMS.
-cics | Allows linking of programs running under the control of CICS.
Parent topic: Linking a Program
Related information
Using Open PL/I with Other Software Products


Using ldpli

ldpli references the components, such as libraries, that were installed with Open PL/I. ldpli generates executable files from relocatable object files.

Note:

The first and fourth characters of the ldpli command are lowercase letter "L".

The ldpli command-line syntax is as follows:

ldpli [option] ... object_file [object_file] ... [optional_library] ...

where

ldpli | The command that invokes the linker.
option | Represents all valid linker options. Any of the valid UNIX or Windows system linker command options are accepted. See your operating system reference manual for a listing and description of all valid system linker options.
object_file | Specifies object files that are to be linked.
optional_library | Represents library specifications for libraries that are required for your special application. These are needed only if you explicitly CALL library routines from your program. The standard system libraries, such as libc.a on a UNIX system, are always included in the link.
Parent topic: Linking a Program


Running a Program

To run an Open PL/I program, invoke the executable object file produced by the link utility.

The name of the executable object file produced by the linker defaults to a.out. However, if you include the -o filename option on the link command line, the executable object file has the filename that you specified.

For example, "-o sample" on the mfplx command line produces an executable object file named "sample".

  • Run-time Errors
  • Accessing Command-Line Arguments in Open PL/I Programs
  • Associating a Logical Open PL/I File with a Physical Disk Data File
  • Using CodeWatch
  • Creating a Sharable Library
Parent topic: Using Open PL/I


Run-time Errors

If an error occurs at run time, a message appears on the terminal.

You can use Open PL/I's ON statement to develop handlers for the conditions that can occur in your program. The ON ERROR statement can be used for arbitrary errors. The ONLOC built-in function can be used in an ON-unit to report the name of an entry in which a condition was raised, and the ONCODE built-in function can be used to report the status value of a run-time error.

Note:

If an error is not caught by an ON-unit, Open PL/I displays the source file and line number where the error occurred. For these features to work, however, you must have compiled the source file with the default option -unixdebug.

This feature is currently available only in the Sun Solaris 2 and IBM AIX versions of Open PL/I.

When a fatal error condition occurs at run time, a message is displayed naming the condition that has been raised; the program address where this occurred; and the source file, entry, and line number at which the condition was raised, as well as the lines in each procedure above it in the call stack. For example:

*** Condition ERROR raised
***Unhandled condition ZERODIVIDE at PC=00010233
CALCDIV line 26 in /dirl/dir2/calcs.pl1
SUBR3 line 444 in /dirl/dir2/subprog.pl1
MYPROG line 871 in /dirl/dir2/mainprog.pl1

In this example,

CALCDIV | Is the entry in which the "ZERODIVIDE" condition was raised.
SUBR3 | Is the entry that called "CALCDIV" (at line 444).
MYPROG | Is the program that called SUBR3.

If you have compiled your program using the -nounixdebug option, only the program address where the condition was raised will be displayed:

*** Condition ERROR raised
*** Unhandled condition ZERODIVIDE at PC=00010233
Parent topic: Running a Program
Related information
Open PL/I Run-time Error Messages


Accessing Command-Line Arguments in Open PL/I Programs

It is sometimes useful to be able to execute a program specifying one or more arguments on the command line in order to cause a variation in the program's behavior. For example, to run a departmental expense report program, you might issue the command deptexp summary to indicate that you wish to see only category totals rather than all the line items.

Command-line arguments can be accessed in a PL/I main program using the following technique:

/* PL/I main program accessing command line args. */

PMAIN: PROCEDURE OPTIONS(MAIN);

   DECLARE ARGC_     FIXED BIN(31) EXTERNAL STATIC;
   DECLARE ARGV_     POINTER EXTERNAL STATIC;
   DECLARE ARG(10)   POINTER BASED;
   DECLARE ARGS      CHAR(50) BASED;
   DECLARE ARGSV     CHAR(50) VARYING;
   DECLARE I         FIXED BIN(31);

   PUT SKIP EDIT(ARGC_)(f(2));
   DO I = 1 TO ARGC_;
      ARGSV = SUBSTR(ARGV_->ARG(I)->ARGS,1,
            INDEX(ARGV_->ARG(I)->ARGS,BYTE(0))-1);
      PUT SKIP EDIT('"',argsv,'"')(a,a,a);
      END;
   PUT SKIP;

   END PMAIN;

If your PL/I program is controlled by a C main program, you can pass the command-line arguments through to the PL/I program in the following manner:

/* C main program calling PL/I subroutine */

main(argc,argv)
   int argc;
   char **argv;
{
   PSUBR(argc,argv);
}

/* PL/I subroutine receiving command line args
   from C main program */

PSUBR: PROCEDURE(ARGC,ARGV);

   DECLARE ARGC      FIXED BIN(31) VALUE;
   DECLARE ARGV      POINTER VALUE;
   DECLARE ARG(10)   POINTER BASED;
   DECLARE ARGS      CHAR(50) BASED;
   DECLARE ARGSV     CHAR(50) VARYING;
   DECLARE I         FIXED BIN(31);

   PUT SKIP EDIT(ARGC)(f(2));
   DO I = 1 TO ARGC;
      ARGSV = SUBSTR(ARGV->ARG(I)->ARGS,1,
            INDEX(ARGV->ARG(I)->ARGS,BYTE(0)));
      PUT SKIP EDIT('"',ARGSV,'"')(a,a,a);
      END;
   PUT SKIP;

END PSUBR;
Parent topic: Running a Program


Associating a Logical Open PL/I File with a Physical Disk Data File

Open PL/I supports a number of ways to associate your physical disk data files with the logical file names used in Open PL/I sources.

  • Method 1 (Default)
  • Method 2
  • Method 3
Parent topic: Running a Program


Method 1 (Default)

The run-time environment will use the name of the file variable (or constant) used in the source, shifted to all uppercase.

Example

dcl Payroll file input;
open file(Payroll);

A file named PAYROLL will be used for all I/O operations using file Payroll.

Parent topic: Associating a Logical Open PL/I File with a Physical Disk Data File


Method 2

Using the TITLE option on the OPEN statement allows one to specify an explicit disk file name with an optional directory prefix. The use of the TITLE option takes precedence over method 1.

Example

dcl Payroll file input;
open file(Payroll) title ('/global/acct/sep-95.days')

A file named /global/acct/sep-95.days will be used for all I/O operations using file Payroll.

dcl Payroll file input;
dcl filename character(100) varying;
<assignment into filename>
open file(Payroll) title (filename);
                                   /* Using a variable name */

The value of filename determines the file that will be used for all I/O operations using file Payroll.

Note:

Once the file has been opened, changing the value of filename will have no impact. The association is made only once, at the time of the open.

Parent topic: Associating a Logical Open PL/I File with a Physical Disk Data File


Method 3

The physical disk file name can be specified with the use of UNIX shell environment variables. This method takes precedence over methods 1 and 2. This method allows you to easily alter the physical disk file used for different invocations of the same application.

The environment variable name is the value of the derived name from either of the above methods with MF_ or DD_ prefixed.

Example

dcl file data2 update;
dcl file specs output;

open file (data2);
open file (specs) title('report');

By setting the following environment variables:

  • setenv MF_DATA2 /common/data
  • setenv MF_REPORT /common/report

I/O operations for file data2 will access /common/data and I/O for file specs will access /common/report.

Note that to override the name for file variable "specs", the name MF_REPORT was used, because of the title option on its OPEN statement.

In the above example, environment variables of the names DD_DATA2 and DD_report would also be allowed.

Note:

To assign a physical file to the following special file declarations you will need to use the corresponding environment variables:

SYSIN | use DD_STDIN
SYSPRINT | use DD_STDOUT
SYSOUT | use DD_STDOUT
Parent topic: Associating a Logical Open PL/I File with a Physical Disk Data File


Using CodeWatch

CodeWatch is a powerful software development tool that can help you locate bugs in your Open PL/I programs. There are two versions of CodeWatch available with Open PL/I:

  • a command-line interface
  • a Windows interface

The command-line version offers a traditional line-oriented interface allowing you to interactively enter commands from the keyboard. The Windows interface offers at least two main windows: one that allows you to enter commands and one that allows you to view your source code. You access CodeWatch commands through pulldown menus and dialogs. The Windows interface runs on a graphical workstation running X-Windows.

CodeWatch enables you to control program execution to set breakpoints, monitor what is happening, examine static type data, and evaluate results. CodeWatch keeps track of variables, subroutines, and data types in terms of the symbols used in the source language. You can reference these items without having to consider the underlying machine language or architecture. You can use CodeWatch to access the source text of the program, to identify and reference program entities, and to detect errors in the program's algorithms and logic.

Note: Your programs must be compiled using the -deb option before they can be run under the control of the debugger. (Every module need not be compiled in -deb mode, but at least one must be; CodeWatch debugs only the modules compiled in -deb mode.) When executed with the -deb option, the Compiler generates a separate symbol table file, filename.stb, in the current directory. filename.stb contains symbolic information that the debugger uses to reference and manipulate source program symbols and entities; set breakpoints, tracepoints, and watchpoints; and control program execution.

For detailed information on CodeWatch, see your CodeWatch Reference Manual.

Parent topic: Running a Program


Creating a Sharable Library

Open PL/I can be used to create sharable libraries on any of the following operating systems:

  • Solaris 2
  • AIX
  • UNIX SVR4
  • SUSE Linux
  • Red Hat Linux

To produce code that can be included in a sharable library, other than on AIX, you must ask Open PL/I to produce position-independent code by using the -pic option. The -pic option is not required for AIX, because all Open PL/I code on AIX is position-independent. Once you have object files generated as position-independent code, you link them into a sharable library using the commands listed below. You also need to link in dllmain.o.

Note: If you intend to use your shared object as an executable program under Enterprise Server it is important to note that your PLI "MAIN" proc needs to have the same name as the shared object or Enterprise Server will not load the .so.

On Solaris 2 or UNIX SVR4:

ld -G -o NEWSHARE.so newshare.o x1.o x2.o x3.o  $MFPLI_PRODUCT_DIR/lib/dllmain.o $MFPLI_PRODUCT_DIR/lib/noofm.o $MFPLI_PRODUCT_DIR/lib/nojw.o -lmf -L$MFPLI_PRODUCT_DIR/lib

On AIX:

ld -o NEWSHARE.so newshare.o x1.o x2.o x3.o -bE:newshare.exp -bM:SRE -brtl $MFPLI_PRODUCT_DIR/lib/dllmain.o $MFPLI_PRODUCT_DIR/lib/noofm.o $MFPLI_PRODUCT_DIR/lib/nojw.o -lmfnso -L$MFPLI_PRODUCT_DIR/lib

You need to add MFOPENPLIINIT and MFOPENPLITERM to the export file

On Red Hat and SUSE Linux:

ld -shared -o NEWSHARE.so newshare.o x1.o x2.o x3.o $MFPLI_PRODUCT_DIR/lib/dllmain.o $MFPLI_PRODUCT_DIR/lib/noofm.o $MFPLI_PRODUCT_DIR/lib/nojw.o -melf_i386 -lmf -L$MFPLI_PRODUCT_DIR/lib
Note: You need the -melf_i386 command only if building on a 64-bit Red Hat or SUSE Linux.
Parent topic: Running a Program


Using Open PL/I with Other Software Products

Because Open PL/I supports a wide range of data types and because it supports standard calling sequences, Open PL/I can be used with many other software products. These include other Micro Focus products as well as products from other companies. This section lists some of the products that Open PL/I is known to work with and gives some hints about using them with Open PL/I.

  • UniKix
  • Oracle
  • DB2
  • C++/Views
  • SyncSort
  • Open PL/I and Informix
  • Open PL/I and Micro Focus
  • Open PL/I and Encina
Parent topic: Using Open PL/I


UniKix

UniKix is UniKix Technologies' CICS system for open systems. Open PL/I supports and is supported by UniKix to enable you to develop On-Line Transaction Processing applications in PL/I.

To create UniKix screens, use UniKix's BMS screen generator utility. Within your screen definition place the command:

LANGUAGE = PLI

Open PL/I provides a CICS precompiler, kixplt, that you can use to process embedded EXEC CICS statements within your PL/I programs. For more information about using Open PL/I's CICS precompiler, see the section Precompiler and Preprocessor Order of Execution .

Note:

While the CICS precompiler can be invoked directly with kixplt, we recommend that you invoke it with the -unikix option to the mfplx command.

The following restrictions apply to Open PL/I programs being used as UniKix applications:

  • Ordinary PL/I input/output statements must not be used. There are EXEC CICS commands for accessing data files.
  • Open PL/I sort routines, PLISRTx, must not be used.
  • STATIC storage must be read-only. The INITIAL attribute can be used to assign values to variables in STATIC storage.
  • The following PL/I statements must not be used: DELAY, STOP.
  • Variables or structures must not be defined with variable names that are the same as variable names generated by the CICS precompiler. These names begin with "DFH."

If OPTIONS(MAIN) is specified in an application program, that program can be the first program of a transaction, or control can be passed to it by means of an EXEC CICS LINK or XCTL command.

The definition of the External Interface Block (EIB) is generated in each program based upon the pointer variable DFHEIPTR. In programs compiled with OPTIONS(MAIN), the DFHEIPTR variable is set by UniKix to address the EIB on entry; therefore, the CICS precompiler will insert DFHEIPTR and DFHCOMMAREA (pointer to the communications area) as parameters of the MAIN program. For example, the following source line

TEST: PROCEDURE OPTIONS(MAIN);

will be translated to

TEST: PROCEDURE(DFHEIPTR, DFHCOMMAREA) OPTIONS(CICSMAIN);

In programs other than those declared with OPTIONS(MAIN), addressability to the EIB is the user's responsibility. This can be achieved by using the CICS command

EXEC CICS ADDRESS EIB(DFHEIPTR);

or by passing the EIB address or the values of particular EIB fields as parameters.

To perform proper initialization and cleanup, all procedures declared with OPTIONS(MAIN) that contain EXEC CICS statements, or that are calling other procedures containing EXEC CICS statements, must be run through the CICS precompiler.

Open PL/I's UniKix support is license managed. You must obtain a special license from Micro Focus to use it. Of course, you must also have the UniKix product.

Parent topic: Using Open PL/I with Other Software Products
Related information
Precompiler and Preprocessor Order of Execution


Oracle

Open PL/I can be used with the Oracle database system. Oracle's Pro*PL/I SQL precompiler is supplied with Open PL/I.

Note: While the Pro*PL/I precompiler can be invoked directly with propli, we recommend that you invoke it with the -oracle option to the mfplx command.

Open PL/I's Oracle support is license managed. You must obtain a special license from Micro Focus to use it. Of course, you must also have the Oracle product.

Parent topic: Using Open PL/I with Other Software Products
Related information
Precompiler and Preprocessor Order of Execution
Open PL/I SQL Options


DB2

Open PL/I can be used with the IBM's DB2 database system. Open PL/I has a precompiler for embedded EXEC SQL statements in your PL/I programs.

Note:

While the DB2 precompiler can be invoked directly with mfdb2, we recommend that you invoke it with the -db2 option to the mfplx command.

Open PL/I's DB2 support is license managed. You must obtain a special license from Micro Focus to use it. Of course, you must also have IBM's DB2 product.

Parent topic: Using Open PL/I with Other Software Products
Related information
Precompiler and Preprocessor Order of Execution
Open PL/I SQL Options


C++/Views

C++/Views is Intersolv's object-oriented graphical user interface (GUI) program framework. C++/Views includes an interactive graphical designer, as well as an extensive C++ class library. Using C++/Views, you can create the framework for an application with an attractive and efficient graphical user interface. Your C++ framework can then call procedures written with Open PL/I to do your ordinary data processing work.

A C++/Views example, PhoneList, is included in the product set. The example consists of a number of C++ source modules and one PL/I module, a readme file, and a makefile.

C++/Views is not yet available on the following platform supported by Open PL/I:

  • Intel-based computers running UNIX SVR4 or Windows
Parent topic: Using Open PL/I with Other Software Products


SyncSort

You may use sort routines supplied by SyncSort with Open PL/I. To do so:

  1. Add the pathname of the SyncSort library to your LD_LIBRARY_PATH environment variable.
  2. Set the SYNCSORT_INSERT environment variable to the pathname of your SyncSort definition file.

    SyncSort will append SyncSort definition options to options that you explicitly specify to Open PL/I.

  3. Specify -syncsort on the ldpli link command.

While developing an application, it is best to turn on debug output fromSyncSort. You can do this by using the /debug option in the sort definition or by setting the environment variable SYNCSORT_DEBUG to 33. For example:

SYNCSORT_DEBUG 33
export SYNCSORT_DEBUG

The use of the environment variable is recommended, because it activates debug output from the start of the SyncSort definition.

By default, SyncSort uses null(s) to pad short keys, whereas Open PL/I rules say that spaces are to be padded to the shorter string during a character string comparison. You must use the SycnSort /padkey X"20" option to have SyncSort match Open PL/I string comparison rules if you expect to have short keys.

The following notes pertain to using SyncSort via the Open PL/I PLISRTx built-ins. (See the section PLISRTx Subroutines in the chapter Open PL/I Built-Ins in your Language Reference Manual for more information.) In all cases, the syntax must be valid.

PL/I PLISRTx built-in arguments:

fields-spec
The 'sort fields=(...)' argument is ignored.
The options-list:
SKIPREC=n For PLISRTA and PLISRTC, Open PL/I automatically adds "/skiprecord n" to the SyncSort definition.

For PLISRTB and PLISRTD, Open PL/I skips n records returned from the input procedure.

EQUALS "/stable" will be added to the SyncSort definition.
records-spec
The record type (V or F) and length are used in the invocation of input or output routines. For PLISRTA, this argument is ignored.
input-proc
This must conform to an E15 Sort Input Handling routine. When the record type is F, it should return a char(n), where n is the record length.

When the record type is V, it should return a char(n) varying, where n is the record length.

output-proc
This must conform to an E35 Sort Output Handling routine. It should always declare its parameter as char(*), never char(*) varying.

Open PL/I handles the invocation of both input and output procedures. Open PL/I adds the applicable /inprocedure and /outprocedure options to the SyncSort definition, using the record length specified in the records-spec. You may not add these options to your SyncSort definition explicitly.

Note:

When comparing the output from SyncSort and Open PL/I, you should note that records that matched on their keys may be in a different order. This prevents the use of the UNIX diff utility to compare the two files. You can avoid this problem, however, by using the EQUALS option in the fields-spec (in your source program). When EQUALS is present, both SyncSort and Open PL/I use a stable sort. Having records that do not fully contain the keys can also cause different results. You must use /padkey x"20" in your SyncSort definition to overcome this. If you use EQUALS in your PL/I source and the /padkey x"20" option in your SyncSort definition, the output files should be identical.

Parent topic: Using Open PL/I with Other Software Products
Related information
PLISRTx Subroutines


Open PL/I and Informix

Open PL/I follows the native C compiler's naming conventions. This allows you to mix subroutines and functions compiled with Open PL/I with any other language or third-party library that supports a C language interface. However, you must link the Open PL/I run-time libraries into the final stand-alone program. The -cisam link option enables the C-ISAM package from Informix for VSAM/indexed files.

Informix fully documents their Application Programming Interface for the C language. In general, you should follow the Informix directions for mixing Informix and C, simply treating the modules compiled with Open PL/I as C modules.

The following examples illustrate the command used to link an Open PL/I program that uses the Informix libraries. For the purposes of this illustration the Open PL/I Compiler and Informix modules are running on a Sun Solaris system. The Open PL/I modules are called "testobj1.o" and "testobj 2.o", the Open PL/I Compiler has been installed in /opt /pl1, and the environment variable $MFPLI_PRODUCT_DIR has been set to that directory.

ldpli testobj1.o testobj2.o -o testprogram
/opt/informix/lib/esql/libsql.a
/opt/informix/lib/esql/libgen.a
/opt/informix/lib/esql/libos.a
/usr/ucblib/libucb.a
/opt/SUNWspro/SC3.0/lib/cg92/_fstd.o

Note that the names and locations of the Open PL/I and Informix libraries are specific to your installation of Informix and Open PL/I. This illustrates a typical installation.

Parent topic: Using Open PL/I with Other Software Products
Related information
Language Concepts


Open PL/I and Micro Focus

Open PL/I follows the native C compiler's naming conventions. This allows you to mix subroutines and functions compiled with Open PL/I with any other language or third party library that supports a C language interface. You must link the Open PL/I run-time libraries into the final stand-alone program. Micro Focus fully documents inter-language calling between COBOL/2 and C. In general, you should follow the Micro Focus directions for mixing COBOL and C, simply treating the modules compiled with Open PL/I as C modules. The following test program illustrates a COBOL program that calls a PL/I function, passing a string as an argument.

The COBOL source code module:

WORKING-STORAGE SECTION. 01 STR PIC X(20).
*
PROCEDURE DIVISION.
CALL-PL1 SECTION.
DISPLAY "Calling the PL/I program".
CALL "PL1PROC" USING STR.
DISPLAY "Return from PL/I program".
DISPLAY STR.
STOP RUN.

The PL/I source code module:

PL1PROC: PROCEDURE ( CHARSTR );
DECLARE CHARSTR CHARACTER(20);

CHARSTR = 'This is a real test!';

END PL1PROC;

The commands to compile and link:

mfplx mfpll.pl1 -stat -c

cob mfcob.cbl mfpl1.o -o mf -v -V -x \
    /pl1dir/lib/dflock.o071030 \
    /pl1dir/lib/noofm.o071030\
    /pl1dir/lib/lpi.a071030

Note that the names and locations of the Open PL/I libraries are specific to your version of Open PL/I. This illustrates a typical installation.

Parent topic: Using Open PL/I with Other Software Products


Open PL/I and Encina

Encina is Transarc Corporation's online transaction processing system. Encina can be accessed from Open PL/I using Encina's open application program interface (API). All Encina functions can be accessed. The -tisam link option enables the TISAM package from Transarc for VSAM/indexed files. This allows for sharing datafiles in the SFS format. You can use Open PL/I to develop transaction processing client server applications with one caveat concerning multi-threaded programming.

The I/O subroutines in Open PL/I's run-time library are not thread-safe. Code that contains PL/I I/O can be made thread-safe by using the global lock to serialize PL/I I/O, as in the following example:

DECLARE

  PTHREAD_LOCK_GLOBAL_NP
      EXTRY() EXTERNAL('pthread_lock_global_np'),
  PTHREAD_UNLOCK_GLOBAL_NP
      ENTRY() EXTERNAL('pthread_unlock_global_np');

  CALL PTHREAD_LOCK_GLOBAL_NP();

  /* PL/I I/O ... */

  CALL PTHREAD_UNLOCK_GLOBAL_NP();

For information on programming with threads, see the OSF DCE Application Development Guide.

A complete example of using Encina with Open PL/I can be found in the directory $MFPLI_PRODUCT_DIR/examples/OpenPLI/encina.

Parent topic: Using Open PL/I with Other Software Products


Language Concepts

  • Line Boundaries
  • Main Procedure
  • Data Types
  • Arithmetic Precision
  • External Procedures
  • Maximum Number of Arguments for a Function or Subroutine Call
  • Open PL/I Calling Conventions
Parent topic: Open PL/I User's Guide
Related information
Open PLI Language Reference Manual


Line Boundaries

A line boundary consists of a new-line character (CRLF on a Windows system), and the line boundary in a quoted string constant is considered part of the string constant.

Parent topic: Language Concepts


Main Procedure

Exactly one of the external procedures that is linked into an executable file must specify the main entry point to the program by including the OPTIONS(MAIN) clause on the PROCEDURE statement. This designates that procedure as the main entry point at which execution should begin, after some run-time initialization has been completed. This option must appear even if the entire program is a single procedure contained in a single source file. Failure to specify a main program, or specifying more than one main program, will cause errors to occur during program linkage.

The main procedure is not required to be a PL/I procedure; that is, it can be written in another language.

Parent topic: Language Concepts


Data Types

The Open PL/I data types include the following:

  • Fixed Binary
  • Float Binary
  • Fixed Decimal
  • Float Decimal
  • Character
  • Character Varying
  • Bit
  • Bit Aligned
  • Pointer
  • Picture
  • Label
  • Entry
  • File
  • Structure
  • Area
  • Offset

The table below lists the data types, along with the alignment and size of their machine representations.

Alignment is the same for HP PA-RISC, Intel, RS/6000, and Sun SPARC, unless otherwise specified.

Data Type | Size | Alignment: aligned data | Alignment: unaligned data
Fixed Binary ( p ? 7) 1 | 1 byte | 1 byte | byte
Fixed Binary (8 ? p ? 15) | 2 bytes | 2 bytes | byte
Fixed Binary (p > 15) | 4 bytes | 4 bytes | byte
Fixed Decimal (p,q) | [(p+2)/2] bytes | byte | byte
Float Binary (p ? 23) | 4 bytes | 4 bytes | byte
Float Binary (p > 23) | 8 bytes | 4 bytes (Intel), 8 bytes (non-Intel) | byte
Float Decimal (p) | 12 bytes | 4 bytes | byte
Character (n) | n bytes | byte | byte
Character (n) Varying | n+2 bytes | 2 bytes | byte
Bit (n) | n bits | bit | bit
Bit (n) Aligned | [(n+7)/8] bytes | byte | –
Pointer | 4 bytes | 4 bytes | byte
Picture | n bytes | byte | byte
Label | 8 bytes | 4 bytes | byte
Entry Variable | 8 bytes | 4 bytes | byte
File Variable | 4 bytes | 4 bytes | byte
Structure | sum of members + gaps for alignment | max of members |
Area (n) | (((n+7)/8)*8)+8 bytes | 8 bytes | –
Offset | 4 bytes | 4 bytes | byte

Subsequent sections provide additional information about the size, alignment, internal representation including byte ordering, and range, where applicable.

The byte ordering on the HP PA-RISC, IBM RS/6000, and Sun SPARC platforms is Big Endian, while the Intel-based platforms have Little Endian byte ordering.

Note:

In the descriptions of data types that follow, the alignment specified is the default, which is ALIGNED for all data types except Bit. For the alignment of each data type with the UNALIGNED attribute, refer to the table above.

  • Fixed Binary (p ? 7)
  • Fixed Binary (8 ? p ? 15)
  • Fixed Binary (15 ? p ? 31)
  • Fixed Decimal (p,q)
  • Float Binary (p ? 23)
  • Float Binary (23 < p ? 52)
  • Float Decimal (p)
  • Character (n)
  • Character (n) Varying
  • Bit (n)
  • Bit (n) Aligned
  • Pointer
  • Label
  • Picture
  • Entry
  • File Variable
  • Structure
  • Area (n)
  • Offset
Parent topic: Language Concepts
1

*Fixed Binary (p ? 7) is handled as a one-byte signed binary integer only if the -vax Compiler option is in effect. Otherwise, it is handled as Fixed Binary(15).


Fixed Binary (p ? 7)

Fixed Binary (p 7) is an 8-bit, signed, 2's complement binary integer. The low order 7 bits contain the integer, the high order bit contains the sign. The sign bit (S) is 1 if the value is negative, 0 if the value is positive or zero. This data type is available only when you use the -vax Compiler option.

Size | Alignment | Range
1 byte | 1 byte | -128 to 127
Parent topic: Data Types


Fixed Binary (8 ? p ? 15)

Fixed Binary (8 ? p ? 15) is a 16-bit, signed, 2's complement binary integer. The low order 15 bits contain the integer, the high order bit contains the sign. The sign bit (S) is 1 if the value is negative, 0 if the value is positive or zero.

Size | Alignment | Range
2 bytes | 2 bytes | -32768 to 32767
Parent topic: Data Types


Fixed Binary (15 ? p ? 31)

Fixed Binary (15 ? p ? 31) is a 32-bit, signed, 2's complement binary integer. The low order 31 bits contain the integer, the high order bit contains the sign. The sign bit (S) is 1 if the value represented is negative.

Size | Alignment | Range
4 bytes | 4 bytes | -2,147,483,648 to 2,147,483,647
Parent topic: Data Types


Fixed Decimal (p,q)

Fixed Decimal (p,q) is a fixed-point number that contains p digits, where q of those digits are fraction digits. Fixed decimal values are typically used only when fraction digits are required. Fixed-point decimal values are always stored as an accurate representation of decimal fractions. The most significant digits are stored at the lowest memory address, and the byte containing the least significant digit and the sign (hexadecimal C for positive or D for negative) is stored at the highest memory address.

Size | Alignment | Range
[(p+2)/2] bytes | byte | -(10p-q - 10-q) to +(10p-q -10-q
Parent topic: Data Types


Float Binary (p ? 23)

Float Binary (p ? 23) is a single-precision, basic format, binary floating-point number (ASCII/IEEE 754-1985 compliant). It contains a 1-bit sign, 8-bit biased exponent (bias = 127), and 23+(1)-bit binary fraction (hidden bit).

An exponent of 255 represents +/- infinity or not-a-number. +/- infinity is represented by an exponent of 255 and zero as the fraction part; the sign bit denotes the + or - infinity. Not-a-number is represented by an exponent of 255 and any non-zero value in the fraction part; the sign bit of not-a-number is not significant. An exponent of 0 denotes a denormalized small value of reduced precision. Both +0 and -0 are possible. Note that the range is approximate and indicates representable values, which include zero and both negative and positive numbers.

Size | Alignment | Approximate Absolute Value of Range
4 bytes | 4 bytes | 1.40E-45 to 3.40E+38
Parent topic: Data Types


Float Binary (23 < p ? 52)

Float Binary (23 < p ? 52) is a double-precision, basic format, binary floating-point number (ANSI/IEEE 754-1985 compliant). It consists of a 1-bit sign, 11-bit biased exponent (bias = 1023), and 52+(1)-bit binary fraction (hidden bit).

An exponent of 2047 represents +/- infinity or not-a-number. +/- infinity is represented by an exponent of 2047 and zero as the fraction part; the sign bit (S) denotes the + or - infinity. Not-a-number is represented by an exponent of 2047 and any non-zero value in the fraction part; the sign bit of not-a-number is not significant. An exponent of 0 denotes a denormalized value of reduced precision. Both +0 and -0 are possible. Note that the range is approximate and indicates representable values, which include zero and both negative and positive numbers.

Size | Alignment | Approximate Absolute Value of Range
Size | Alignment | Approximate Absolute Value of Range
Size | Alignment | Approximate Absolute Value of Range
8 bytes | 4 bytes (Little Endian) 8 bytes (Big Endian) | 4.9E-324 to 1.8E+308
8 bytes | 4 bytes (Little Endian) 8 bytes (Big Endian) | 4.9E-324 to 1.8E+308
8 bytes | 4 bytes (Little Endian) 8 bytes (Big Endian) | 4.9E-324 to 1.8E+308
Parent topic: Data Types


Float Decimal (p)

For compatibility with IBM PL/I, data declared as float decimal is stored and processed by default as 4-byte or 8-byte float binary. (If the specified precision is ? 6, 4-byte float binary is used.)

Alternatively, float decimal data can be stored and processed as 12-byte Binary Coded Decimal BCD float decimal data by using the -nofdasfb ("no float dec as float bin") compiler option. In this case, Float Decimal (p) is a decimal floating-point number, stored in packed decimal format. It consists of a sign, an exponent sign, two bits used for infinity, not-a-number (usually 0), a 3-digit (base 10) exponent and a 17-digit (base 10) fraction. Both the exponent and fraction have a separate sign bit. All digits are packed Binary Coded Decimal (BCD), such that the entire string fits in 96 bits (12 bytes). The fraction contains at least p decimal digits.

Size | Alignment | Approximate Absolute Value of Range
12 bytes | 4 bytes | 9.9999999999999999x10 -999 to 9.9999999999999999x10 999
Parent topic: Data Types


Character (n)

Character (n) is a character-string variable where n is an integer that specifies the length of the string value held by the variable. Character (n) is a sequence of 8-bit ASCll characters stored as 1 character per byte. In Open PL/I, the maximum length of a string variable is 32767 characters.

Size | Alignment
n bytes | byte
Parent topic: Data Types


Character (n) Varying

Character (n) Varying is a character-string variable. The VARYING attribute causes the string variable to hold values of varying length. The representation of a varying string variable in storage is such that any string up to n characters may be held by the variable, and the length of the current string is retained as part of the value. Character (n) Varying is stored as follows: the first two bytes contain the length of the string (represented by a Fixed Binary (15) number) followed by a sequence of 8-bit ASCII characters stored as 1 character per byte. In Open PL/I, the maximum length of a string value is 32767 characters.

Note that the character string is not terminated with a null (ASCII 0) character.

Size | Alignment
n+2 bytes | 2 bytes
Parent topic: Data Types


Bit (n)

Bit (n) is a bit-string variable where n is an integer valued expression that specifies the length of the string value held by the variable. Bit (n) is a sequence of binary digits (bits) that always occupies exactly n bits of storage.

If the last bit of the bit-string does not occur on a byte boundary, the remaining bits in the last byte might be part of another bit-string variable. Within each byte, the bits of the string are stored from the high-order to the low-order position. For example, Bit (23) would be stored as follows:

Size | Alignment
n bits | bit (none)
Parent topic: Data Types


Bit (n) Aligned

Bit (n) Aligned is a bit-string variable. The ALIGNED attribute causes the bit-string variable for which it is declared to be byte-aligned, resulting in more efficient access. This attribute may also cause the variable to occupy more than n bits, but it does not increase the length of the value that can be stored in the variable. The ALIGNED attribute has no effect on operations performed on the variable, but is considered part of the data type for purposes of argument/parameter matching and storage sharing.

Bit (n) Aligned size is in bytes. If the length, n, is not a multiple of eight (for example, Bit (27) Aligned) then the remaining bits in the last byte are unused. Within each byte, the bits of the string are stored from the high-order to the low-order position. For example, Bit (27) Aligned would be stored as follows:

Size | Alignment
[(n+7)/8] bytes | byte
Parent topic: Data Types


Pointer

Pointer is a 4-byte, 32-bit word variable capable of holding the address of any variable except unaligned bit variables. Pointers are normally used to locate the storage of dynamically allocated BASED variables rather than as a mechanism for accessing another variable's storage. A pointer is used with a template to access the storage to which it points. A pointer value cannot be represented by a constant. Pointer values can be assigned, compared for equality or inequality, passed as arguments, and returned from functions. No calculations or conversions can be performed on them, and they cannot be transmitted in stream I/O.

Size | Alignment
4 bytes | 4 bytes
Parent topic: Data Types


Label

Label is an 8-byte, 32-bit word pair variable consisting of a 4-byte text address and a 4-byte frame pointer value. The text address identifies the first instruction of a labeled statement in the containing procedure. The frame pointer value identifies the address of the stack frame of the block containing the statement. Label values can be assigned, compared for equality or inequality, passed as arguments, and returned from functions. No calculations or conversions can be performed on them, and they cannot be transmitted in stream I/O.

Size | Alignment
8 bytes | 4 bytes
Parent topic: Data Types


Picture

Picture is a fixed-point decimal value stored internally as a character string. The string contains the characters that represent the numeric value, and may be formatted with special embedded symbols such as a period (.) or a comma (,). Picture data is best used to manipulate a quantity arithmetically and then print or display its value.

Size | Alignment
n bytes | byte
Parent topic: Data Types


Entry

Entry is an 8-byte, 32-bit word pair variable consisting of a 4-byte descriptor pointer and a 4-byte frame pointer value. The descriptor pointer points to a data area that specifies the text address of the procedure entry and the table of contents pointer for the procedure. The frame pointer (relevant only with internal procedures) designates the stack frame of the containing procedure, if any. For external procedures, the frame pointer value is zero (0).

Size | Alignment
8 bytes | 4 bytes
Parent topic: Data Types


File Variable

File Variable is represented internally as a 4-byte, 32-bit word containing the address of a file control block. When evaluated, the value of the file variable is the address of the file control block for the file with which the variable is associated. A file variable can be assigned any file value; it is declared using both the FILE and VARIABLE attributes.

Size | Alignment
4 bytes | 4 bytes
Parent topic: Data Types


Structure

Structure is a hierarchically ordered set of values that may be of different data types. The immediate components of a structure are called "members" of the structure. An entire structure can be transmitted in stream or record I/O, passed as an argument, or assigned to another structure of identical size and shape and having members of corresponding identical data types. No conversions or calculations can be performed on entire structures.

Size | Alignment
Sum of members + gaps for alignment | Most stringent of members' alignment requirements
Parent topic: Data Types


Area (n)

Area (n) is a variable describing a region of storage whose size in bytes is defined by the integer n. An area variable is a region of storage in which based variables can be allocated and freed. An area can be passed as an argument or it can be assigned to another area. It can also be transmitted in its entirety in a record I/O operation. No other operations, calculations, or conversions can be performed on area variables.

Size | Alignment
n bytes rounded to 8 byte boundary, plus 8 byte header [ (((n+7)/8)*8)+8] bytes | 8 bytes

Related Topics

Offset

Parent topic: Data Types
Related information
Offset


Offset

An offset variable is a locator used only in conjunction with an area variable. The value of an offset variable specifies the location of a based variable within an area, relative to the beginning of the area.

Offset variables can be assigned, compared for equality and inequality, passed as arguments, and returned as function results. No calculations or conversions can be performed on them, except in the context of explicit conversion to a Pointer, using Open PL/I's POINTER built-in function.

Size | Alignment
4 bytes | 4 bytes
Parent topic: Data Types
Related information
Area n


Arithmetic Precision

Each arithmetic data type has a default precision and a maximum precision as specified in Table 2-2. The range of the scale factor of fixed-point decimal data is 0 through 18 (0 ? q ? 18).

Data Type | Maximum Precision | Default Precision
Fixed Binary | 31 | 15*
Fixed Decimal | 18 | 5
Float Binary | 52 | 23
Float Decimal | 16 | 6

* The -Iongint Compiler option changes the default precision of fixed binary from 15 to 31.

Parent topic: Language Concepts


External Procedures

Open PL/I adheres to the calling conventions of the native architecture. Programs compiled by Open PL/I can be linked with object modules produced by other language products, and the resulting object program will run if the following conditions are met:

  • The calling conventions used by other language product(s) also adhere to the calling conventions of the native architecture. Note that the system C compiler on UNIX and the Windows Visual C/C++ compiler meet this requirement.
  • Declarations for formal and actual parameters in the calling and called programs must be written in their respective languages, so that the data representations assumed in the declarations agree with each other.
  • External Names
Parent topic: Language Concepts


External Names

Certain rules apply with regard to name length and the use of lowercase letters when specifying an identifier name:

  1. Name length: Open PL/I allows names up to 256 characters long.
  2. Lowercase names: By default, Open PL/I treats all names, including external names, as if all lowercase letters were upper case. When interfacing with non-PL/I external procedures, it may be necessary to work around this. For example, the C language preserves the case of all external names.

    If Open PL/I is calling a C function or vice-versa, one of the following options is available.

    • Spell with uppercase letters the external names in the C function where needed.
    • Use the EXTERNAL('name') option on the PLI ENTRY declaration to specify the exact name of the external C entry point.
    • Use the Open PL/I -lowercase Compiler option, which maps all external names to lower case instead of upper case. Note that all external names produced are lower case, not just the entry point to a procedure.
Parent topic: External Procedures


Maximum Number of Arguments for a Function or Subroutine Call

The maximum number of arguments that may be passed in an Open PL/I program is given by the following formula, which holds generally for any function or subroutine call argument list:

N + M= 241

where:

N | Is the actual number of arguments specified.
M | Is the position of the last *-extent argument, or zero if none exists.

Example:

DECLARE (S, T, U, V) CHAR (32),
   (I, J, K, L) BINARY (15),
   MYSUB ENTRY (BINARY(15), BINARY (15), CHAR(*),
         CHAR(*), BINARY(15), BINARY(15));
.
.
.
   CALL MYSUB(I,J,K,S,T,L);

where:

N | = 6 (the number or arguments specified)
M | = 5 (the position of "T" in the argument list)

which gives:

N+ M = 11 (6 actual arguments; 3 dummy descriptors for I, J, and K; and 2 actual descriptors for S and T).
Parent topic: Language Concepts


Open PL/I Calling Conventions

The following sections describe the calling conventions for HP, Intel, RS/6000, and Sun Sparc systems. All LPI-series languages compilers use the following calling conventions and are compatible with Open PL/I.

  • Calling Other Languages
  • Argument Passing Conventions
  • Register Save Conventions
  • Function Result Conventions
  • Open PL/I Equivalent Data Types
Parent topic: Language Concepts


Calling Other Languages

If you are calling a function written in another language, the result type must be able to be mapped to a PL/I data type.

C often expects character strings to be null terminated, that is, the string is delimited by an '\0' byte immediately following the last character of interest. When constructing a character value in PL/I that is passed to a C function expecting a null terminator, the PL/I procedure must supply an explicit null character in the appropriate position. The BYTE built-in function can be used for this purpose, as shown in the following example.

call CFUNC('abcde' || BYTE(0))

or without the BYTE built-in using z-character constants,

call CFUNC('abcde'Z)
  • C Calling Conventions
Parent topic: Open PL/I Calling Conventions


C Calling Conventions

The following program illustrates how to declare and call two standard C library functions, "atoi" and "strtol":

int atoi(const char *str)

long strtol(const char *str, char **endptr, int base)

Please note the following points:

  1. Since C is case-sensitive and PL/I is not, use EXTERNAL('name') to map the PL/I name to the function's real name.
  2. Since C arguments are passed by immediate value, specify the VALUE attribute for FIXED BINARY parameters.
  3. Because PL/I arguments are normally passed by reference, the VALUE attribute is not necessary for char * arguments declared CHARACTER(n). However, when a char * argument is declared POINTER, as in the ATOI_2 declaration, the VALUE attribute is required.
  4. By convention, C strings are terminated with a NULL byte.
  5. In this example, although char * is declared CHARACTER(80), any length long enough to hold the string and a terminating null byte would be all right. Of course, if the C function expected a pointer to a character string of a certain length, the PL/I and C declarations should agree.
  6. Note the use of the z-character constants for compatibility with C-style null-terminated strings, and the use of the SYSNULL() built-in, which returns 0, as opposed to the NULL() built-in, which returns -1 by default.
    CALLC: PROCEDURE OPTIONS(MAIN);

DECLARE

ATOI   ENTRY(CHARACTER(80))
       RETURNS(FIXED BINARY(31))
       EXTERNAL('atoi'),

ATOI_2 ENTRY(POINTER VALUE)
       RETURNS(FIXED BINARY(31))
       EXTERNAL('atoi'),

STRTOL ENTRY(CHARACTER(80),
             POINTER VALUE,
             FIXED BINARY(31) VALUE)
       RETURNS(FIXED BINARY(31))
       EXTERNAL('strtol'),

BASE   FIXED BINARY(31),
ENDPTR POINTER,
INT    FIXED BINARY(31),
LONG   FIXED BINARY(31),
STR    CHARACTER(80),
STRPTR POINTER;

STR    = '2147483647'z;
INT    = ATOI(STR);

PUT SKIP LIST(INT);

STRPTR = ADDR(STR);
INT    = ATOI_2(STRPTR);

PUT SKIP LIST(INT);

STR    = '0x7fffffff'z;
ENDPTR = SYSNULL();
BASE   = 16;
LONG   = STRTOL(STR, ENDPTR, BASE);

PUT SKIP LIST(LONG);

PUT SKIP LIST(STRTOL('0x7fffffff'z, SYSNULL(), 16));

END CALLC;
Parent topic: Calling Other Languages


Argument Passing Conventions

The following sections detail the argument passing conventions for HP, Intel, RS/6000, and Sun Sparc platforms.

  • HP Argument Passing Conventions (32-bit)
  • Intel Argument Passing Conventions (32-bit)
  • RS/6000 Argument Passing Conventions (32-bit)
  • Sun Sparc Argument Passing Conventions (32-bit)
Parent topic: Open PL/I Calling Conventions


HP Argument Passing Conventions (32-bit)

Arguments are passed in General Purpose Registers (GR) 26–23, Single-Precision Floating-Point Registers (FR) 4–7, Double-Precision Floating-Point Registers (FR) 5 and 7, and in the parameter area of the stack, according to the Open PL/I standard calling conventions.

  • If the function returns a value in a temporary storage area, a pointer to that area is passed in GR28.
  • The argument list contains addresses of the actual arguments in order or their appearance. If any arguments have the VALUE attribute, the actual argument is passed.
  • If OPTIONS(VARIABLE) is used, any missing arguments are replaced by null pointers.
  • If any of the function's parameters have variable extents, for example, asterisks(*), the addresses of dope vectors describing the arguments are appended to the explicit argument list.
Parent topic: Argument Passing Conventions


Intel Argument Passing Conventions (32-bit)

  • The calling procedure pushes the addresses of the actual arguments (pointers) onto the stack in the reverse order of their appearance in an argument list. In other words, the address of the last argument is pushed first and the address of the first argument is pushed last.
  • A call to a function returning one of the data types that requires a return temporary must push a pointer to the area for the result value onto the stack.

The external procedure is called by executing a CALL instruction.

Parent topic: Argument Passing Conventions


RS/6000 Argument Passing Conventions (32-bit)

Arguments are passed in General Purpose Registers (GPR) 3–10, Floating-point Registers (FPR) 1–13, and in the parameter area of the stack according to the Open PL/I standard calling conventions.

  • If the function returns a value in a temporary storage area, a pointer to that area is passed in GPR3 and all other arguments are displaced by one.
  • The argument list contains addresses of the actual arguments in order of their appearance. If any arguments have the VALUE attribute, the actual argument is passed.
  • If OPTIONS(VARIABLE) is used, any missing arguments are replaced by null pointers.
  • If any of the function's parameters have variable extents, for example asterisks (*), the addresses of dope vectors describing the arguments are appended to the explicit argument list.
Parent topic: Argument Passing Conventions


Sun Sparc Argument Passing Conventions (32-bit)

External procedures are called using the CALL instruction and are returned using the RET and RESTORE sequence.

  • The first six parameters are passed in the output registers; that is, the first parameter is passed in register o0, the second in register o1 and the sixth one in register o5. Parameters beyond the sixth are passed on the stack.
  • If OPTIONS(VARIABLE) is used, any missing arguments in the call to the procedure are replaced by null pointers.
  • The external procedure is called by executing a CALL instruction.
Parent topic: Argument Passing Conventions


Register Save Conventions

The following sections detail the register save conventions for HP, Intel, and Sun Sparc systems.

  • HP Register Save Conventions (32-bit)
  • Intel Register Save Conventions (32-bit)
  • RS/6000 Register Save Conventions (32-bit)
  • Sun Sparc Register Save Conventions (32-bit)
Parent topic: Open PL/I Calling Conventions


HP Register Save Conventions (32-bit)

The called procedure is expected to save and restore values in registers GR3–GR18 and FR12–FR21. The calling procedure can assume that those registers are preserved across the call. The function result is in GR28, FR4, or the result temporary provided by the caller, depending on the result data type. For more information, see the section HP Function Result Conventions.

Parent topic: Register Save Conventions
Related information
HP Function Result Conventions


Intel Register Save Conventions (32-bit)

The contents of ebx, esi, and edi must be preserved across a subroutine call. If a subroutine uses one of these registers, it must save the original value and restore it before returning to the caller.

Registers eax, ecx, and edx are scratch registers. A subroutine can change the value in a scratch register without saving its previous value.

When the Intel floating-point coprocessor is used, the floating-point stack registers must be empty before entry and upon exit from a subroutine. However, if the subroutine returns a floating-point value, the value is returned on top of the stack in register fp0 and the remainder of the stack is empty.

A called procedure is responsible for establishing a new stack frame for itself and saving and restoring all preserved registers. The procedure establishes the stack frame with the following sequence:

pushl ebp
movl esp, ebp
subl #framesize, esp
pushl ebx         //only if used within function
pushl esi         //only if used within function
pushl edi         //only if used within function

Note that the code sequence may be abbreviated if -opt is specified.

A return must store any function result value, restore any preserved registers it used, pop its stack frame, and return to the caller.

A procedure that returns one of the data types that requires a return temporary must remove the extra pointer(s) from the stack entry; callers to such routines push these hidden arguments. The called routine must load register eax with the pointer to the return area that its caller passed before returning. Such a routine will start with the following code before establishing a frame:

popl edx
xchgl edx, 0 (esp)

Then it saves the return pointer in a local variable in its stack frame.

Parent topic: Register Save Conventions


RS/6000 Register Save Conventions (32-bit)

The called procedure is expected to save and restore values in registers GPR13 through GPR31 and FPR14 through FPR31. The calling procedure can assume that those registers are preserved across the call. The function result is in GPR3, FPR1, or the result temporary provided by the caller, depending on the result data type.

Parent topic: Register Save Conventions


Sun Sparc Register Save Conventions (32-bit)

The called procedure is expected to save and restore all local and input registers (10 through 17 and i0 through i7). The calling procedure can assume that only these registers are preserved across the call. The function result is general ally in o0, f0, or both f0 and f1, or the result temporary provided by the caller, depending on the result data type. For more information, see the section Sun Sparc Function Result Conventions.

A called procedure is responsible for establishing a new stack frame for itself and saving and restoring all local and input registers. This is accomplished by a SAVE instruction. Before returning, the called procedure must store any function result value, restore all local and input registers, and adjust the stack frame. This is accomplished by a load of i0, f0, or both f0 and f1, or a store to a result temporary and a RESTORE instruction.

Parent topic: Register Save Conventions
Related information
Sun Sparc Function Result Conventions


Function Result Conventions

A function returns its result to the caller in one of four ways. The following sections detail the function result conventions on HP, Intel, RS/6000, and Sun Sparc systems.

  • HP Function Result Conventions (32-bit)
  • Intel Function Result Conventions (32-bit)
  • RS/6000 Function Result Conventions (32-bit)
  • Sun Sparc Function Result Conventions (32-bit)
  • Return of Data Types
Parent topic: Open PL/I Calling Conventions


HP Function Result Conventions (32-bit)

A function procedure returns its result value to the calling procedure in one of three ways, depending upon the data type: in register GR28, in register FR4, or in a temporary storage area provided by the caller.

If the result is returned in a temporary storage area, the calling procedure provides the temporary area and passes its address in GR28.

Parent topic: Function Result Conventions


Intel Function Result Conventions (32-bit)

On Intel x86 systems, the result of a function is returned in one of the following three ways, depending upon the result's data type and if the floating-point coprocessor is used:

  • In register eax
  • In a temporary storage area provided by the caller
  • On top of the Intel floating-point coprocessor's stack in register fp0
Parent topic: Function Result Conventions


RS/6000 Function Result Conventions (32-bit)

A function procedure returns its result value to the calling procedure in one of three ways, depending upon the data type:

  1. In register GPR3
  2. In register FPR1
  3. In a temporary storage area provided by the caller

If the result is returned in a temporary storage area, the calling procedure provides the temporary area and passes its address as the first (hidden) parameter in the call.

Parent topic: Function Result Conventions


Sun Sparc Function Result Conventions (32-bit)

On the Sun Sparc, the result of a function is returned in one of the following four ways, depending upon the result's data type:

  1. In register o0
  2. In a temporary storage area
  3. In register f0
  4. In registers f0 and f1

On Sun Sparc systems, the calling procedure provides the temporary area and stores the address to the temporary area in the one-word hidden parameter of the user frame at %sp+0x40 prior to the call.

Parent topic: Function Result Conventions


Return of Data Types

The table below lists the Open PL/I data types and the registers to which they are returned on each platform.

Open PL/I Data Type | Register Returned in
 | HP | Intel | RS/6000 | Sun Sparc
Fixed Binary Character(1), not * or Varying Bit(1), not * Pointer Offset File | GR28 | eax | GPR3 | o0
Float Binary | FR4 | on top of the floating-point coprocessor stack | FPR1 | f0/f1
Fixed Decimal Float Decimal Character( n), n > 1 or n = * Character( n) Varying Bit( n), n > 1 or n = * Picture Label Entry | Returned in Temporary Storage Area
Parent topic: Function Result Conventions


Open PL/I Equivalent Data Types

Table 2-4 lists compatible data types for determining equivalent argument type correspondence. Some data types (for example, char in C) are used more than once in the table to show the correspondence of equivalent types in more than two languages. The subscripts used in the table have the following meanings:

PL/I
 | COBOL | C | C++ | FORTRAN | BASIC | PASCAL
Fixed Bin, P <= 7 | COMP PIC S9 (1) – S9 (2) | char | char | INTEGER*1 | – | –
Fixed Bin, 8 <= P <= 15 | COMP PIC S 9 (3) – S 9 (4) | short | short | INTEGER*2 | INTEGER (%) | Integer
Fixed Bin, P >15 | COMP PIC S 9 (5) – S 9 (9) | int or long | int or long | INTEGER*4 | – | Integer
– | – | char | char | INTEGER*1 | – | Packed Array[1...5]
Character (n) | DISPLAY A(n) or PIC X(n) | char [n] | char[n] | CHARACTER*n | – | –
Character (N) Varying | DISPLAY PIC X OCCURS num1 to num2 DEPENDING on N | struct {short s; char c[n];} | struct {short s; char c[n];} | – | – | Char
Character (1) | DISPLAY PIC X | char | char | CHARACTER*1 | – | –
Character (*) | – | char[ ] | char[ ] | – | – | –
Fixed Decimal | COMP–3 PIC S9 (n) | – | – | – | – | –
 | DISPLAY PIC S9(n) SIGN TRAILING | – | – | – | – | –
– | DISPLAY PIC S9(n) SIGN LEADING SEPARATE | – | – | – | – | –
– | DISPLAY PIC S9(n) SIGN TRAILING SEPARATE | – | – | – | – | –
Bit(1) | – | – | – | – | – | –
Bit(1) Aligned | – | char | char | – | – | Boolean
Bit(N) Aligned | COMP–5 PIC [S] 9 (n), n<5 | – | – | – | – | Set
– | – | int or long | int or long | LOGICAL*4 | – | –
– | – | short | short | LOGICAL*2 | – | –
– | – | char | char | LOGICAL*1 /BYTE | – | –
Float Bin, p > 23 | COMP–2 | double | double | REAL*8 | REAL (#) (MBASIC) | –
Float Bin, p <= 22 | COMP–1 | float | float | REAL*4 | REAL (1) (MBASIC) | Real
– | – | struct {float real, imaginary;} | struct {float real, imaginary;} | COMPLEX*8 | – | –
– | – | struct {double real; double imaginary} | #include <complex.h> class complex | COMPLEX*16 | – | –
Pointer | – | Pointer | Pointer | – | – | Pointer
Label | – | – | – | alternate return | – | –
Entry | DISPLAY PIC X(32) | – | – | Dummy procedure | – | –
Float Decimal | – | – | – | – | REAL (CBASIC) | –
– | – | – | – | – | STRING ($) | –
Area | – | – | – | – | – | –
Offset | COMP PIC S 9 (5) – S 9 (9) | int or long | int or long | INTEGER*4 | – | integer
Parent topic: Open PL/I Calling Conventions


Open PL/I SQL Options

  • Oracle SQL Support
  • DB2 SQL Support
Parent topic: Open PL/I User's Guide


Oracle SQL Support

Open PL/I enables you to develop PL/I applications that make use of Oracle databases. Open PL/I's Pro*PLI precompiler allows you to compile and link PL/I applications containing embedded Oracle SQL statements to access these databases. This chapter gives the special instructions needed to compile and link such Open PL/I applications. For more information on Pro*PL/I, refer to the following documents:

  • Programmer's Guide to the Oracle Precompilers
  • Pro*PL/I Precompiler Supplement

Support for Pro*PL/I is included in the standard Open PL/I product set, but you must obtain from Micro Focus a Pro*PL/I license before it can be used. Also, before you can take advantage of EXEC SQL support, you must have installed Oracle version 10 on your system (the Oracle version 10 is also able to communicate with Oracle 11 database).

  • Running Pro*PL/I
Parent topic: Open PL/I SQL Options


Running Pro*PL/I

The Oracle precompiler can be run using the Open PL/I driver (mfplx), or it can be invoked directly using the Pro*PL/I executable file. To invoke Pro*PL/I using mfplx, add the -oracle Compiler option to the command line:

mfplx filename.pl1 –oracle
  • Pro*PL/I Precompiler Options for mfplx
Parent topic: Oracle SQL Support


Pro*PL/I Precompiler Options for mfplx

The following precompiler options are used with the Open PL/I command driver, mfplx. If you want to invoke Pro*PL/I directly, see the Pro*PL/I Precompiler Supplement for the available options.

The Pro*PL/I precompiler options can be entered on the command line or from a configuration file. We recommend the use of a configuration file.

Option
 | Explanation
-config fileName | Indicates that precompiler options should be taken from the named configuration file.
-ireclen recordLength | Specifies the record length of the input file.
-Imargin columnNo | Specifies the value of the left margin of the input source file.
-Iname fileName | Specifies the name of the listing file.
-Ireclen recordLength | Specifies the record length of the listing file.
-Itype listingType | Specifies the listing type.
-maxliteral stringLength | Specifies the maximum length of string literals generated by the Pro*PL/I.
-maxopencursors numberOfCursors | Specifies the maximum number of concurrently open cursors.
-mode modeValue | Specifies one of the valid Pro*PL/I modes: ANSI, ISO, ANSI14, IS014, ANSI13, IS013, or ORACLE.
-ora_include directory | Specifies a directory path for EXEC SQL INCLUDE files. Note that unlike the -ipath switch, only one directory can be specified at a time. However, it is allowed to use this switch as many times as required.
-oreclen recordLength | Specifies the record length of the output file.
-pagelen number | Specifies the number of lines per physical page of the listing file.
-pporacle fileName | Specifies Pro*PL/I output file name.
-release_cursor YES | NO | Specifies how the cursors for SQL statements are handled in the cursor cache.
-rmargin columnNo | Specifies the value of the right margin of the input source file.
-select_error YES | NO | Specifies whether your program should generate an error in case a single–row SELECT statement returns more than one row or more rows than a host array can accommodate.
-sqlcheck SEMANTICS | FULL | SYNTAX | LI MITED | NONE | Specifies the type and extent of syntactic and semantic checking.
Parent topic: Running Pro*PL/I


DB2 SQL Support

Open PL/I enables you to develop PL/I applications that make use of databases maintained by IBM DB2. Open PL/I's DB2 SQL precompiler allows you to compile and link PL/I applications containing embedded DB2 SQL statements to access these databases. This document gives the special instructions needed to code, compile, and link such Open PL/I applications.

Support for DB2 SQL is included in the standard Open PL/I product set, but you must obtain from Micro Focus a DB2 SQL license before it can be used. Also, before you can take advantage of EXEC SQL support, you must have installed and started IBM's DB2 product on your system.

You can code DB2 EXEC SQL statements in Open PL/I applications using the language defined in the IBM document DATABASE 2 Client/Server SOL Reference. Specific requirements for your SQL code are described in the sections that follow.

  • DB2 SQL Precompiler Options
  • Coding DB2 SQL Statements in Open PL/I Applications
  • Sample Programs
Parent topic: Open PL/I SQL Options


DB2 SQL Precompiler Options

The following DB2 SQL precompiler options are supported by the Open PL/I driver program, mfplx:

-bind or -nobind
Determines whether or not a bind file is created. The bind file's name is specified by the -bindname option, if that option is used. Otherwise, the name defaults to the name of the input source file with the suffix .bnd.
-bindname b
Specifies the bind file name, b, if one is created.
-block t
Specifies the type of record blocking, t, to be used and how ambiguous cursors are to be treated. The valid types are:
unambig | Blocking occurs for read-only cursors, those that are not specified as FOR UPDATE OF, have no static DELETE WHERE CURRENT OF statements, and have no dynamic statements. Ambiguous cursors can be updated.
all | Blocking occurs for read-only cursors, those that are not specified as FOR UPDATE OF, and for which no static DELETE WHERE CURRENT OF statements are executed. Ambiguous and dynamic cursors are treated as read-only.
no | No blocking is done on any cursors in the package. Ambiguous cursors can be updated.
-datetime d
Determines the date and time format used when date and time fields are assigned to string representations in host variables. The possible formats are:
def | Use the date/time format associated with the country code of the database. This is also the default if -datetime is not specified.
usa IBM standard for United States form:

mm/ddlyyyy hh:mm xM (AM or PM).

eur IBM standard for European form:

dd.mm.yyyy hh.mm.ss.

iso International Standards Organization form:

yyyy–mm–dd hh.mm.ss.

jis Japanese Industrial Standards form:

yyyy–mm–dd hh:mm:ss.

loc | Local form, not necessarily equal to def.
-db2
Specifies that the DB2 version of SQL is to be used.
-dbname d
Specifies the original or alias name of a database. This option directs the precompiler to process SQL statements against the specified database, d. If you omit this option, the precompiler uses the default database. The default database is specified by the environment variable DB2DBDFT.
-E
Allows you to run the DB2 SQL precompiler without running the Open PL/I compiler. The precompiler output is saved using the file specified by the -ppdb2 option, if that option is used. Otherwise, the name defaults to the name of the input source file with the suffix .pp2. This option is useful for a faster syntax and semantic checking of your SQL statements.
-isolation I
Specifies the isolation level at which your program runs. The values of Iare:
cs | Cursor stability
rr | Repeatable read
ur | Uncommitted read
-optimize or -nooptimize
If you specify -optimize, SQLDA initialization is optimized for SQL statements that use host variables. Do not specify this option when using AUTOMATIC host variables or in other situations when the address of a host variable might change during execution of the program. -nooptimize is the default.
-plan or -noplan
Determines whether or not an access plan is created.
-ppdb2 [f]
Specifies the DB2 SQL precompiler output file. This is useful when using the -E option.
-sqltwop
It is good programming practice to declare all SQL host variables before using them in SQL statements. However, if you are not able to do this, -sqltwop provides support for declarations of host variables subsequent to their use. This is done by making a preliminary pass over the source to detect all declarations, followed by a second pass to process the remaining SQL statements. In general, you should not need to use this option and incur the extra overhead it entails.
Parent topic: DB2 SQL Support


Coding DB2 SQL Statements in Open PL/I Applications

Specific requirements for your embedded SQL code are described in the sections that follow.

  • Defining the DB2 SQL Communications Area
  • Defining SQL Descriptor Areas
  • Embedding SQL Statements
  • Using Host Variables
  • Determining Equivalent SQL and PL/I Data Types
  • Determining Compatibility of SQL and PL/I Data Types
  • Using Host Structures
  • Using Indicator Variables
  • CONNECT TO Statement
  • COMPOUND Statement
  • Handling SQL Error Return Codes
Parent topic: DB2 SQL Support


Defining the DB2 SQL Communications Area

An Open PL/I program that contains SQL statements must include an SQL communications area (SQLCA). As shown in the example below, SQLCA includes an SQLCODE variable and an SQLSTATE variable.

The SQLCODE value is set by the Database Manager after each SQL statement is executed. An application can check the SQLCODE value to determine whether the last SQL statement was successful.

The SQLSTATE variable can be used as an alternative to the SQLCODE variable when analyzing the result of an SQL statement. Like the SQLCODE variable, the SQLSTATE variable is set by the Database Manager after each SQL statement is executed.

The SQLCA should be included by using the SQL INCLUDE statement:

exec sql include sqlca;

The SQLCA must not be defined within an SQL declare section. The scope of the SQLCODE and SQLSTATE declarations must include the scope of all SQL statements in the program.

/*--------------------------------------------------------------- */
/* DB2 SQL Communications Area                                    */
/* This should be included by the                                 */
/* 'EXEC SQL INCLUDE SQLCA;' statement.                           */
/* Do not place this within a SQL declare statement.              */
/*--------------------------------------------------------------- */
declare 1 sqlca,
  2 sqlcaid char(8),                 /* Eyecatcher = 'SQLA '      */
  2 sqlcabc fixed bin(31),           /* SQLCA size in bytes = 136 */
       2 sqlcode fixed bin(31),      /* SQL return code           */
       2 sqlerrm char(70) varying,   /* Error message tokens      */
       2 sqlerrp char (8),           /* Diagnostic information    */
       2 sqlerrd(1:6) fixed bin(31), /* Diagnostic information    */
       2 sqlwarn,                    /* Warning flags             */
         3 sqlwarn0 char(1),
         3 sqlwarnl char(1),
         3 sqlwarn2 char(1),
         3 sqlwarn3 char(1),
         3 sqlwarn5 char(1),
         3 sqlwarn6 char(1),
         3 sqlwarn7 char(1),
       2 sqltext,
         3 sqlwarn8 char(1),
         3 sqlwarn9 char(1),
         3 sqlwarna char(1),
         3 sqlstate char(5); /* State corresponding to SQLCODE */

/*    End of SQL Communications Area declaration */
Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


Defining SQL Descriptor Areas

The following statements require an SQLDA:

  • PREPARE statement-name INTO descriptor-name FROM host-variable
  • EXECUTE ... USING DESCRIPTOR descriptor-name
  • FETCH ... USING DESCRIPTOR descnptor-name
  • OPEN ... USING DESCRIPTOR descriptor-name
  • DESCRIBE statement-name INTO descriptor-name

Unlike the SQLCA, there can be more than one SQLDA in a program, and an SQLDA can have any valid name. An SQLDA should be included by using the SQL INCLUDE statement:

exec sql include sqlda;

The SQLDA must not be defined within an SQL declare section.

The Open PL/I SQLDA template includes %REPLACE statements for the SQL data types.

/*-------------------------------------------------------------------------------- */
/* DB2 SQL Descriptor Template                                                         */
/* This should be included by the 'EXEC SQL INCLUDE SQLDA;' statement.                 */
/* Do not place this within an SQL declare statement.                                  */
/*------------------------------------------------------------------------------------ */
declare 1 sqlda based(sqldaptr),                                                       */
   2 sqldaid        char(8),                     /* Eye catcher 'SQLDA   '             */
   2 sqldabc fixed bin(31),                      /* SQLDA size in bytes 16 + 44 * SQLN */
   2 sqln           fixed bin(15),               /* Number of SQLVAR elements          */
   2 sqld           fixed bin(15),               /* Number of used SQLVAR elements     */
   2 sqlvar(1:sqlsize refer(sqln)),              /* Variable descriptor                */
     3 sqltype      fixed bin(15),               /* Variable data type                 */
     3 sqllen       fixed bin(15),               /* Variable length                    */
     3 sqldata      pointer,                     /* Pointer to variable data value     */
     3 sqlind       pointer,                     /* Pointer to null indicator          */
     3 sqlname      char(30) var;                /* Variable name                      */
declare sqlsize fixed bin(15);                   /* Number of sqlvars (sqln)           */
declare sqldaptr pointer;
/* End of SQL Descriptor Template declaration */

/* replaces for SQL type codes                                                         */
/* replaces of the SQL_TYP_Nxxnnn means with Null indicator                            */
%replace SQL_TYP_DATE      by 384; /* DATE */
%replace SQL_TYP_NDATE     by 385;
%replace SQL_TYP_TIME      by 388; /* TIME */
%replace SQL_TYP_NTIME     by 389;
%replace SQL_TYP_STAMP     by 392; /* TIMESTAMP */
%replace SQL_TYP_NSTAMP    by 393;
%replace SQL_TYP_VARCHAR   by 448; /* VARCHAR(I) varying length string I<=4000*/41)
%replace SQL_TYP_NVARCHAR  by 449;
%replace SQL_TYP_CHAR      by 452; /* CHAR(I) - fixed length string */
%replace SQL_TYP_NCHAR     by 453;
%replace SQL_TYP_LONG      by 456; /* LONG VARCHAR - varying length I > 4000 */
%replace SQL_TYP_NLONG     by 457;
%replace SQL_TYP_CSTR      by 460; /* varying length string for C */
%replace SQL_TYPNCSTR      by 461;
%replace SQL_TYP_VARGRAPH  by 464; /* VARGRAPHIC(I) - varying length */
%replace SQL_TYP_NVARGRAPH by 465;
%replace SQL_TYP_GRAPHIC   by 468; /* GRAPHIC(I) - fixed length graphic */
%replace SQL_TYP_NGRAPHIC  by 469;
%replace SQL_TYP_LONGRAPH  by 472; /* LONG VARGRAPHIC(I) - varying length */

%replace SQL_TYP_NLONGRAPH by 473;
%replace SQL_TYP_LSTR      by 476; /* varying length string for Pascal */
%replace SQL_TYP_NLSTR     by 477;
%replace SQL_TYP_FLOAT     by 480; /* FLOAT - 8-byte floating point */
%replace SQL_TYP_NFLOAT    by 481;
%replace SQL_TYP_DECIMAL   by 484; /* DECIMAL (p,q), sqllen q + (256 * p) */
%replace SQL_TYP NDECIMAL  by 485;
%replace SQL_TYP_ZONED     by 488; /* Zoned Decimal -> DECIMAL (m,n) */
%replace SQL_TYP_NZONED    by 489;
%replace SQL_TYP_INTEGER   by 496; /* INTEGER - 4-byte signed integer */
%replace SQL_TYP_NINTEGER  by 497;
%replace SQL_TYP_SMALL     by 500; /* SMALLINT - 2-byte signed integer*/
%replace SQL_TYP NSMALL    by 501;
%replace SQL_TYP_NUMERIC   by 504; /* NUMERIC -> DECIMAL (m,n) */
%replace SQL_TYP_NNUMERIC  by 505;

/* End of EXEC SQL INCLUDE SQLDA  -------------------------------------------------*/
Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


Embedding SQL Statements

You can add SQL statements to your program wherever executable statements can appear. Each SQL statement must begin with EXEC (or EXECUTE) SQL and end with a semicolon (;).

For example, an UPDATE statement might be coded as follows:

exec sql update Department
   set Mgrno    = :Mgr_Num
   where Deptno = :Int_Dept;

Comments

PL/I comments can be included in embedded SQL statements wherever a blank is allowed.

Continuation

The line continuation rules for embedded SQL statements are the same as for other PL/I statements.

Including Code

SQL statements or PL/I host variable declaration statements can be included by placing the following SQL statement at the point in the source code where the statements are to be embedded:

exec sql include {filename | 'filename'};

filename can be enclosed in single quote characters ('). Quotes are required if filename contains any non-alphanumeric characters, as for example,

'inventory.db001'.

Names

Any valid PL/I variable name can be used for a host variable, subject to the following restriction: Do not use host variable names or external entry names that begin with "SQL". These names are reserved for the database manager or Open PL/I. The length of a host variable name must not exceed 30 characters.

Statement Labels

With the exception of the END DECLARE SECTION statement and the INCLUDE text-filename statement, executable SQL statements, like PL/I statements, can have a label prefix.

WHENEVER Statement

The target for a GOTO clause in an SQL WHENEVER statement must be a label in the PL/I source code and must be within the scope of any SQL statements affected by the WHENEVER statement.

Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


Using Host Variables

All host variables used in SQL statements must be explicitly declared. A host variable used in an SQL statement must be declared prior to the first use of the host variable in an SQL statement, except when the -sqltwop precompiler option is used. In addition:

  • All host variables within an SQL statement must be preceded by a colon (:).
  • The names of host variables must be unique within a program, even if the host variables are in different blocks or procedures.
  • An SQL statement that uses a host variable must be within the scope of the statement in which the variable is declared.
  • A host variable cannot be declared as an array.
  • Declaring Host Variables
  • Numeric Host Variables
  • Character Host Variables
Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


Declaring Host Variables

Host variable declarations can be made at the same places as ordinary PL/I variable declarations.

Not all PL/I data types are acceptable for host variables. The precompiler does not use the data attribute defaults specified in the PL/I DEFAULT statement. If the declaration for a variable is not recognized, any statement that references the variable may result in the message "The host variable token ID is not valid".

The SQL precompiler uses only the names and data attributes of host variable declarations; the alignment, scope, and storage class attributes are ignored.

Parent topic: Using Host Variables


Numeric Host Variables

The syntax for numeric host variable declarations is as follows:

DECLARE var-name-spec {BINARY | DECIMAL} scale-spec align-scope-storage ;

where:

var-name-spec | is {variable-name | (variable-name, ...) }
scale-spec | is {FIXED [(precision [,scale])] | FLOAT [(precision)]}
align-scope-storage | is any set of PL/I alignment, scope, or storage class attributes
Note:
  • BINARY | DECIMAL and FIXED | FLOAT can be specified in either order.
  • The precision and scale attributes can follow BINARY | DECIMAL instead of FIXED | FLOAT.
  • A value for scale can be specified only for DECIMAL FIXED.
  • DCL, BIN, and DEC are accepted as abbreviations for DECLARE, BINARY, and DECIMAL, respectively.

Parent topic: Using Host Variables


Character Host Variables

The syntax for character host variable declarations is as follows:

DECLARE var-name-spec CHARACTER [(length)] [VARYING] align-scope-storage ;

where:

var-name-spec | is {variable-name | (variable-name, ...) }
align-scope-storage | is any set of PL/I alignment, scope, or storage class attributes

Note:
  • For non-varying character host variables, length must be a constant no greater than the maximum length for SQL CHAR data.
  • For varying-length character host variables, length must be a constant greater than the maximum length for SQL LONG VARCHAR data.
  • DCL, CHAR, and VAR are accepted as abbreviations for DECLARE, CHARACTER, and VARYING, respectively.
Parent topic: Using Host Variables


Determining Equivalent SQL and PL/I Data Types

The base SQLTYPE and SQLLEN of host variables are determined according to the following table. If a host variable appears with an indicator variable, the SQLTYPE is the base SQLTYPE plus one.

PL/1 Data Type | SQLTYPE of Host Variable | SQLLEN of Host Variable | SQL Data Type
BIN FIXED(n), n < 16 | 500 | 2 | SMALLINT
BIN FIXED(n), 16 ? n ? 31 | 496 | 4 | INTEGER
DEC FIXED(p,s) | 484 | p (byte 1) s (byte 2) | DECIMAL(p,s)
BIN FLOAT(p), 24 ? n ? 52 | 480 | 8 | FLOAT
CHAR(n), 1 ? n ? 254 | 452 | n | CHAR(n)
CHAR(n) VARYING, 1 ? n ? 4000 | 448 | n | VARCHAR(n)
CHAR(n) VARYING, n > 4000 | 456 | n | LONG VARCHAR
  • For FLOAT data, only double-word BIN FLOAT is supported.
  • Precisions, where appropriate, must be specified with integer constants. Default values are not provided.
  • The SQLDA include file has %REPLACE statements for the SQL data types.

The following table can be used to determine the PL/I data type that is equivalent to a given SQL data type.

SQL Data Type | PL/I Equivalent | Notes
SMALLINT | BIN FIXED(15) |
INTEGER | BIN FIXED(31) |
DECIMAL(p,s) | DEC FIXED(p) or DEC FIXED(p,s) | 1 ? p ? 31 and 0 ? s ? p
FLOAT | BIN FLOAT(p) | 24 ? p ? 52
CHAR(n) | CHAR(n) | 1 ? n ? 254
VARCHAR(n) | CHAR(n) VAR | 1 ? n ? 4000
LONG VARCHAR | CHAR(n) VAR | 4000 < n
DATE | CHAR(n) | 10 ? n
TIME | CHAR(n) | 8 ? n
TIMESTAMP | CHAR(n) | 26 ? n
Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


Determining Compatibility of SQL and PL/I Data Types

PL/I host variables in SQL statements must be type compatible with the columns that use them:

  • Numeric data types are compatible with each other. A SMALLINT, INTEGER, DECIMAL, or FLOAT column is compatible with a PL/I host variable of BIN FIXED(15), BIN FIXED(31), DECIMAL(p,s), or BIN FLOAT(n), where 24 ? n ? 53.
  • Character data types are compatible with each other. A CHAR or VARCHAR column is compatible with a fixed-length or varying-length PL/I character host variable. When necessary, the Database Manager automatically converts a fixed-length character string to a varying-length string or a varying-length string to a fixed-length string.
  • Datetime data types are compatible with character host variables. A DATE, TIME, or TIMESTAMP column is compatible with a fixed-length or varying-length PL/I character host variable.
Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


Using Host Structures

A PL/I host structure name can be a structure name. For example:

dcl 1 A,
      2  B,
        3  C1 char(...),
        3  C2 char(...);

In this example, B is the name of a host structure consisting of the scalar members C1 and C2.

However, structures (whether level 1 structures or substructures) may not be referenced in SQL statements. Only scalar members may be so referenced.

A fully qualified member name must be no more than 30 characters in length.

Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


Using Indicator Variables

An indicator variable is a two-byte integer (BIN FIXED(15)). On retrieval, an indicator variable is used to show whether its associated host variable has been assigned a null value. On assignment to a column, a negative indicator value is used to indicate that a null value should be assigned.

Indicator variables are declared in the same way as host variables and the declarations of the two can be mixed in any way that seems appropriate.

Given the statement:

exec sql fetch Cls_Cursor into  :Cls_Cd,
                                :Day  :Day_Ind,
                                :Bgn  :Bgn_Ind,
                                :End  :End_Ind;

the variables could be declared as follows:

exec sql begin declare section;
dcl Cls_Cd     char(7);
dcl Day        bin fixed(15);
dcl Bgn        char(8);
dcl End        char(8);
dcl (Day_Ind, Bgn_Ind, End_Ind) bin fixed(15);
Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


CONNECT TO Statement

You can use a host variable to represent the database name you want your application to connect to. For example:

exec sql connect to :dbase;

If a host variable is specified:

  • It must be a character or character varying variable.
  • It must be preceded by a colon and must not be followed by an indicator variable.
  • The server-name that is contained within the host variable must be left-justified.
  • If the length of the server-name is less than the length of the fixed-length character host variable, it must be padded on the right with blanks.
    dcl dbase char(10);
dbase = 'SAMPLE';    /*four blanks are */
                     /* automatically appended */
exec sql connect to :dbase;
Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


COMPOUND Statement

Open PL/I requires a trailing semicolon after the start of an SQL compound statement. For example:

exec sql begin compound atomic static;
      select count(*) into :tmp3 from department;
      select count(*) into :tmp4 from project;
end compound;
Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


Handling SQL Error Return Codes

Your DB2 product includes a routine that translates SQLCODE error values into readable text messages. When you process your program source with Open PL/I's DB2 SQL precompiler, an %INCLUDE statement is inserted into your program, and the include file this incorporates into your program contains a declaration of this SQLCODE translator routine as an entry, as follows:

declare sqldb2err entry(fixed bin(15) value,
                                    /* Buffer Size   */
               fixed bin(15) value, /* Line Width    */
               any,                 /* SQLCA         */
               any)                 /* Buffer        */
      returns(fixed bin(15))
      external('sqlgintp');

The return code values are:

  • >0 Length of message
  • -1 Internal DB2 error
  • -2 No error, SQLCODE = 0
  • -3 Invalid SQLCODE, no such error
  • -4 Line width is 0
  • -5 Invalid SQLCA, bad buffer address or bad buffer size

Example:

declare errmsg character(200);

exec sql connect to MYDB;
if sqlca.sqlcode < 0 then do;
   put skip list('Connect failed');
   /* Now print out reason for failure for most */
   /* recent SQL statement (i.e., the connect) */
   msg_len = sqldb2err(size(errmsg),0,sqlca,errmsg);
   put skip list(substr(errmsg,1,msg_len));
   return;
   end;

You do not need to declare sqldb2err. This is done for you automatically, as described above.

For more information about this routine, see SQLGINTP (Get Error Message) in your IBM platform-specific DATABASE 2 Programming Reference manual.

Parent topic: Coding DB2 SQL Statements in Open PL/I Applications


Sample Programs

  • Open PL/I DB2 SQL Sample 1 Program
  • Compilation, Linking, and Execution
  • Open PL/I DB2 SQL Sample 2 Program
Parent topic: DB2 SQL Support


Open PL/I DB2 SQL Sample 1 Program

filename: sample1.sqp

sample1: proc options(main);

/*                                                  */
/* This program shows the usage of host-variables,  */
/* indicators, and some common SQL statements       */

/* The database this program uses is the IBMSAMPL   */
/* database that your DB2 product uses. You must be */
/* able to run the IBM DB2 demo sample program in   */
/* order to be able to run this program.            */
/*                                                  */

dcl idx fixed bin(15);
dcl errmsg character(200);
dcl msg_len fixed bin(15);

exec sql include sqlca;

exec sql begin declare section;
   dcl cnt fixed bin(15);
   dcl projno char(6);
   dcl projname char(24) varying;
   dcl deptno char(6);
   dcl respemp char(6);

   dcl prstaff float bin(24);
   dcl prstaff_ind fixed bin(15);

   dcl prstdate char(10);
   dcl prstdate_ind fixed bin(15);

   dcl prendate char(10);
   dcl prendate_ind fixed bin(15);

   dcl majproj char(6);
   dcl majproj_ind fixed bin(15);
exec sql end declare section;

/* Set up error label for all SQL statements. */
exec sql whenever sqlerror goto err_label;

/* Connect to the IBM DB2 sample demo data base */
exec sql connect to IBMSAMPL;

/* Determine how many rows are in table project. */
exec SQL SELECT COUNT(*) INTO :cnt from project;

put skip edit('Number of rows in table project:', cnt) (a(40),x,f(3,0));
put skip list('Ail the rows for project are:');
put skip;

/* Declare and use a cursor to fetch each row. */
exec sql declare cl cursor for
  select projno, projname, deptno, respemp, prstaff,
         prstdate, prendate, majproj
  from project;

exec sql open cl;
do idx = 1 to cnt;
   prstaff 0;         /* re-init */
   prstdate = ' ';    /* re-init */
   prendate = ' ';    /* re-init */
   majproj = ' ';     /* re-init */
   exec sql fetch cl into :projno,
                          :projname,
                          :deptno,
                          :respemp,
                          :prstaff  :prstaff_ind,
                          :prstdate :prstdate_ind,
                          :prendate :prendate_ind,
                          :majproj  :majproj_ind;
   put edit (projno, projname, deptno, respemp, prstaff, prstdate,
             prendate, majproj)
            (a(6),x,a(24),x,a(3),x,a(6),x,f(5,2),x,a(10),x,a(10),x,a(6));
   put skip;
   end;

 return;

err_label:
   msg_len = sqldb2err(200,0,sqlca,errmsg);
   put skip list(substr(errmsg,l,msg_len));

end sample1;
Parent topic: Sample Programs


Compilation, Linking, and Execution

mfplx -db2 sample1.sqp -o sample1.out

sample1.out
Number of rows in table project:         20
All the rows for project are:
AD3100 ADMIN SERVICES        DO1 000010  6.50 01/01/1982 02/01/1983
AD3110 GENERAL ADMIN SYSTEMS D21 000070  6.00 01/01/1982 02/01/1983 AD3100
AD3111 PAYROLL PROGRAMMING   D21 000230  2.00 01/01/1982 02/01/1983 AD3110
AD3112 PERSONNEL PROGRAMMING D21 000250  1.00 01/01/1982 02/01/1983 AD3110
AD3113 ACCOUNT PROGRAMMING   D21 000270  2.00 01/01/1982 02/01/1983 AD3110
IF1000 QUERY SERVICES        CO1 000030  2.00 01/01/1982 02/01/1983
IF2000 USER EDUCATION        CO1 000030  1.00 01/01/1982 02/01/1983
MA2100 WELD LINE AUTOMATION  DO1 000010 12.00 01/01/1982 02/01/1983
MA2110 W L PROGRAMMING       Dl1 000060  9.00 01/01/1982 02/01/1983 MA2100
MA2111 W L PROGRAM DESIGN    Dl1 000220  2.00 01/01/1982 12/01/1982 MA2110
MA2112 W L ROBOT DESIGN      Dl1 000150  3.00 01/01/1982 12/01/1982 MA2110
MA2113 W L PROD CONT PROGS   D11 000160  3.00 02/15/1982 12/01/1982 MA2110
OP1000 OPERATION SUPPORT     E01 000050  6.00 01/01/1982 02/01/1983
0P1010 OPERATION             E11 000090  5.00 01/01/1982 02/01/1983 OP1000
0P2000 GEN SYSTEMS SERVICES  E01 000050  5.00 01/01/1982 02/01/1983
OP2010 SYSTEMS SUPPORT       E21 000100  4.00 01/01/1982 02/01/1983 OP2000
OP2011 SCP SYSTEMS SUPPORT   E21 000320  1.00 01/01/1982 02/01/1983 0P2010
OP2012 APPLICATIONS SUPPORT  E21 000330  1.00 01/01/1982 02/01/1983 0P2010
092013 DB/DC SUPPORT         E21 000340  1.00 01/01/1982 02/01/1983 0P2010
PL2100 WELD LINE PLANNING    B01 000020  1.00 01/01/1982 09/15/1982 MA2100
Parent topic: Sample Programs


Open PL/I DB2 SQL Sample 2 Program

filename: sample2.sqp

sample2: proc options(main);

   /* Sample program 2                                              */
   /* Example of using a user defined SQLDA                         */

   /* The database this program uses is the IBMSAMPL database that  */
   /* your DB2 product uses. You must be able to run the IBM DB2    */
   /* demo sample program in order to be able to run this program   */

   /* Uses a table of the form:                                     */
   /*    create table project                                       */
   /*       (projno char(6) not null,                               */
   /*       projname varchar(24) not null,                          */
   /*       deptno char(3) not null,                                */
   /*       respemp char(6) not null,                               */
   /*       prstaff dec(5,2),                                       */
   /*       prstdate date)                                          */

dcl k fixed bin(15);

exec sql include sqlca;
exec sql include sqlda;

exec sql begin declare section;
   dcl cnt fixed bin(15);
exec sql end declare section;

sqlsize 6;                     /* Lets only look at the 1st 6 columns */
allocate sqlda set(sqldapntr); /* sets sqln */
sqldaptr->sqld = 6;

dcl projno char(6) based;
sqldaptr->sqlda.sqlvar(1).sqltype = SQL_TYP_CHAR;
allocate projno set(sqldaptr->sqlda.sqlvar(1).sqldata);
sqldaptr->sqlda.sqlvar(1).sqllen = 6;

dcl projname char(24) var based;
saldaptr->sqlda.sqlvar(2).sqltype = SQL_TYP VARCHAR;
allocate projname set(sqldaptr->sqlda.sqlvar(2).sqldata);
sqldaptr->sqlda.sqlvar(2).sqllen = 24;

dcl deptno char(3) based;
sqldaptr->sqlda.sqlvar(3).sqltype = SQL_TYP_CHAR;
allocate deptno set(sqldaptr->sqlda.sqlvar(3).sqldata);
sqldaptr->sqlda.sqlvar(3).sqllen = 3;

dcl respemp char(6) based;
sqldaptr->sqlda.sqlvar(4).sqltype = SQL_TYP_CHAR;
allocate respemp set(sqldaptr->sqlda.sqlvar(4).sqldata);
sqldaptr->sqlda.sqlvar(4).sqllen = 6;

dcl prstaff float(24) binary based;
sqldaptr->sqlda.sqlvar(5).sqltype = SQL_TYP_FLOAT;
allocate prstaff set(sqldaptr->sqlda.salvar(5).sqldata);
sqldaptr->sqlda.sqlvar(5).sqllen = 8;

dcl prstdate char(10) based;
sqldaptr->sqlda.sqlvar(6).sqltype = SQL_TYP_CHAR;
allocate prstdate set(sqldaptr->sqlda.sqlvar(6).sqldata);
sqldaptr->sqlda.sqlvar(6).sqllen = 10;

exec sql connect to IBMSAMPL;
if SQLCA.SQLCODE < 0 THEN do;
   put skip list('Connect failed');
   return;
   end;
  else put skip list('Connect OK');
  put skip;
  exec sql whenever sqlerror goto err_label;
  put skip list('Projno Projname                 Dpt Respemp Prst Prstdate');
  put skip;

  exec sql declare cl cursor for select * from project;
  exec sql open cl;
  exec sql whenever not found go to done;
  do while ('1'b1);  /* do till fetch raises not found error */
     exec sql fetch c1 using descriptor :sqldaptr;
     put edit (sqldaptr->sqlda.sqlvar(1).sqldata->projno,
               sqldaptr->sqlda.sqlvar(2).sqldata->projname,
               sqldaptr->sqlda.sqlvar(3).sqldata->deptno,
               sqldaptr->sqlda.sqlvar(4).sqldata->respemp,
               sqldaptr->sqlda.sqlvar(5).sqldata->prstaff,
               sqldaptr->sqlda.sqlvar(6).sqldata->prstdate)
              (a(6),x,a(24),x,a(3),x,a(6),x,f(5,2),x,a(10));
     put skip;
     end;
done:
   exec sql whenever not found continue;   /* turn off */

   put skip;
   return;
err_label:
   put skip list('Branched to err_label');
   put skip list('sqlcode =', sqlcode);
   put skip list('sqlerrm =' , sqlerrm);
   put skip list('sqlstate =', sqlstate);
   return;

end sample2;

Output

Connect OK

Projno Projname              Opt Respemp  Prst Prstdate
AD3100 ADMIN SERVICES        D01 000010   6.50 01/01/1982
AD3110 GENERAL ADMIN SYSTEMS D21 000070   6.00 01/01/1982
AD3111 PAYROLL PROGRAMMING   D21 000230   2.00 01/01/1982
AD3112 PERSONNEL PROGRAMMING D21 000250   1.00 01/01/1982
AD3113 ACCOUNT PROGRAMMING   D21 000270   2.00 01/01/1982
1F1000 QUERY SERVICES        CO1 000030   2.00 01/01/1982
1F2000 USER EDUCATION        CO1 000030   1.00 01/01/1982
MA2100 WELD LINE AUTOMATION  DO1 000010  12.00 01/01/1982
MA2110 W L PROGRAMMING       D11 000060   9.00 01/01/1982
MA2111 W L PROGRAM DESIGN    D11 000220   2.00 01/01/1982
MA2112 W L ROBOT DESIGN      D11 000150   3.00 01/01/1982
MA2113 W L PROD CONT PROGS   D11 000160   3.00 02/15/1982
OP1000 OPERATION SUPPORT     E01 000050   6.00 01/01/1982
OP1010 OPERATION             E11 000090   5.00 01/01/1982
OP2000 GEN SYSTEMS SERVICES  E01 000050   5.00 01/01/1982
OP2010 SYSTEMS SUPPORT       E21 000100   4.00 01/01/1982
OP2011 SCP SYSTEMS SUPPORT   E21 000320   1.00 01/01/1982
0P2012 APPLICATIONS SUPPORT  E21 000330   1.00 01/01/1982
0P2013 DB/DC SUPPORT         E21 000340   1.00 01/01/1982
PL2100 WELD LINE PLANNING    B01 000020   1.00 01/01/1982
Parent topic: Sample Programs


Open PL/I Source Checker

  • Introduction to the Open PL/I Source Checker
Parent topic: Open PL/I User's Guide


Introduction to the Open PL/I Source Checker

The Open PL/I Source Checker, plicheck, is a utility that enables you to scan sets of PL/I source code identifying all features that are not yet supported by the Open PL/I compiler. The results are reported in tabular form.

The source checker is run by use of the mfplx command with the -check option. This command allows you to use the Open PL/I Macro Preprocessor, to run the source checker on multiple source files producing a single report for all of your PL/I source code, to specify the directories containing your include files, and to employ other Open PL/I options that may be needed to describe your source code.

The command syntax is as follows:

mfplx file-list -check [-report report-filename][other mfplx options]

If the -report option is not used, the output of the source checker will be directed to standard error.

Example

mfplx appl* app2.pl1 subdir/app3* -check -report app.rep

If your source code contains macro preprocessor statements (which therefore require the Open PL/I Macro Preprocessor), you must specify the -macro option, and you may also specify any of the other Preprocessor options described in the chapter Using Open PL/I.

All include files needed by your source code must also be accessible for the source checking operation. You may specify include-file search paths by use of the -ipath and -isuffix options that are described in the chapter Using Open PL/I. if these options are not used, your include files must be in the current working directory.

Other options described in the chapter Using Open PL/I, such as -longint and -margins, may also be needed.

Two environment variables can be used to control the source checker: LPI_PLI_CHECKER and TMPDIR.

You can set the environment variable LPI_PLI_CHECKER to point to the directory where the source checker resides. If LPI_PLI_CHECKER is not set, mfplx will try to invoke the source checker from the normal Open PL/I installation directory, MFPLI_PRODUCT_DIR.

The TMPDIR environment variable tells the source checker where to create temporary scratch files. If TMPDIR is not set, scratch files are created in your current working directory. Scratch files are deleted after use.

Note:

The Open PL/I Source Checker does not report a complete syntax and semantic analysis of your source code. It serves only to report PL/I features used in your source code that are not supported by the current release of Open PL/I. It does not report errors in your code.

To gain full advantage of the Open PL/I Source Checker, the source code presented to it must be complete, including all include files that are needed, and must be capable of compilation without error. Errors in your code will cause the source checker to skip over portions of your code, and may even cause the source checker to abort its check of some source files.

Parent topic: Open PL/I Source Checker
Related information
Using Open PL/I


Open PL/I Compiler Diagnostic Messages

  • Interpreting Diagnostic Messages
Parent topic: Open PL/I User's Guide


Interpreting Diagnostic Messages

The format for Open PL/I compilation diagnostic messages is as follows:

filename (line, col)  :  diagnostic level  MFPLI + diagnostic number + first letter of the diagnostic level :  diagnostic message
filename
The name of the file that caused the diagnostic message.
(line, col)
Line number and column number. If the column number is 0, the column is not available.
diagnostic level
There are five diagnostic levels: Info, Warning, Error, Severe and Abort.
MFPLI + diagnostic number + first letter of the diagnostic level
This consists of "MFPLI", the diagnostic number and the first letter of the diagnostic level (Info - "I", Warning - "W", Error - "E", Severe - "S" and Abort - "A").
diagnostic message
A brief statement of the diagnostic.

Example

hex2.pl1 (10,0) : Severe MFPLI01253S : The first argument of the HEX built-in function must be a variable reference.
Note: An object file is not generated if an error at the Severe or Abort level is encountered.
Parent topic: Open PL/I Compiler Diagnostic Messages
Related information
Compiler Options


Open PL/I Run-time Error Messages

  • Run-time Errors
  • LPI Run-time Error Codes
Parent topic: Open PL/I User's Guide


Run-time Errors

A run-time error is a program exception that occurs during execution. Some examples of program exceptions are:

  • Overflow on a floating-point computation
  • An invalid I/O operation on a file
  • A UNIX signal
  • An address violation trap
  • An invalid operand to a math routine.

When such errors occur, the LPI run-time system responds by raising an appropriate condition. If the program has established a handler for the particular condition, the handler is invoked; otherwise, the LPI run-time system performs a default action. A program establishes handlers for various conditions by means that differ from language to language: PL/I procedures can establish handlers by using ON-units, FORTRAN procedures can establish handlers for certain kinds of exceptions by using the ERR= and END= specifiers on I/O statements, and other languages provide no means of handling exceptions.

In the absence of a handler, the default action performed by the LPI run-time system for most conditions except the ENDPAGE (f), FINISH, UNDERFLOW, and ERROR conditions is simply to raise the ERROR condition.

  • As the default action for the UNDERFLOW condition, the Open PL/I run-time system substitutes a true zero for the result and continues the computation.
  • As the default action for the ENDPAGE condition, the Open PL/I run-time system does a PUT(f)PAGE.
  • As the default action for the ERROR condition, the LPI run-time system writes a message line to the standard output file (usually the terminal), closes all opened files, and terminates execution of the program.
  • As the default action for the FINISH condition, the Open PL/I run-time system continues execution.

The message line has the following form:

*** Condition ERROR raised

If the ERROR condition was raised as the default action for another condition, the above line is followed by another line:

*** Unhandled condition cccccc[for 000000 on file ffffff] at PC=xxxxxxxx

where

cccccc | Is the name of a condition and indicates the nature of the program exception as described in the remainder of this section.
000000 | Describes the I/O operation.
ffffff | Is the name of the file.
xxxxxxxx | Is the hexadecimal value of the PC at the time the error was detected (usually the address of an instruction in a routine from an LPI run-time library).

If the error is related to an I/O operation on a file, the optional part of the message appears.

I/O errors are program exceptions related to operations on files. End-of-file on sequential input may raise the ENDFILE condition, and errors opening a file usually raise the UNDEFINEDFILE condition. The condition name used by the LPI run-time system for other I/O errors has the form

I0_ERROR_nnn

where nnn is the error code for the particular error: either an LPI run-time system error code or a UNIX system error code.

The AREA condition is raised in two situations: (1) if an attempt is made to allocate a based variable within an area that has insufficient free storage for the allocation, or (2) if an attempt is made to assign one area to another where the maximum size of the source area exceeds that of the target area.

Floating point exceptions raise conditions OVERFLOW, UNDERFLOW, ZERODIVIDE, CONVERSION, INVALID_OPERAND, or INVALID_mmmm, where mmmm is the name of a floating-point function or operation.

OVERFLOW | Indicates that the magnitude of a computational result is too large to represent.
UNDERFLOW | Indicates that the magnitude of a computational result is too close to zero to represent.
ZERODIVIDE | Indicates an attempt to divide by zero (note that the special case of zero divided by zero raises SIGFPE, however). Note: This condition is not recognized in cases where integer division is performed. In this case, the ONCODE for a general computational error (99200) is returned.
CONVERSION | Is raised when a floating-point value cannot be correctly converted to an integer, to or from another floating-point value of a different size, or to or from a character string representation.
INVALID_OPERAND | Results when an operand to a floating-point function (such as SIN, COS, TAN, EXP, and LOG) is out of the range capable of being handled accurately by the system.
INVALID_mmmm | Usually denotes an invalid operand to the indicated floating-point function or operation: the operand is Not-a-Number, +/- infinity, or is outside the mathematical domain of the function or operation.

RTS errors are program exceptions detected by the LPI run-time system not related to I/O. The condition name raised for these errors has the form

 RTS_ERROR_nnn

where nnn is one of the error codes listed in Table B-1. An RTS error related to the conversion of a value from one data type to another is sometimes reported as the CONVERSION condition.

Finally, UNIX signals are errors detected by the system and reported to the program by the system's signaling mechanism. Signaled condition names have the form

SIGxxxx

where xxxx depends on the signal value. The various UNIX signal values are described in your UNIX documentation. On some UNIX systems, floating-point exceptions appear as SIGFPE.

Parent topic: Open PL/I Run-time Error Messages


LPI Run-time Error Codes

The table below lists the LPI run-time system error codes (100 –170). The UNIX system error codes (001 – 099) correspond exactly to the UNIX system error codes and are listed in your UNIX documentation.

Code | Meaning
100 | Duplicate record
101 | File not open
102 | Illegal argument
103 | Illegal key descriptor
104 | Too many files open
105 | Bad isam file format
106 | Non-exclusive access
107 | Record locked
108 | Key already exists
109 | Is primary key
110 | End of file reached
111 | No record found
112 | No current record
113 | File locked
114 | File name too long
115 | Can't create lock file
116 | Duplicate record (warning)
117 | Current record pointer undefined
118 | Can't allocate memory
119 | Bad custom collating
120 | Invalid operation
121 | Boundary violation on write
122 | Boundary violation on sequential file
123 | Not available, file locking or closed w/ lock
124 | Inconsistent attributes
125 | Open -APPEND on KEYED file
126 | Open -DAM on non-IDIRECT file
127 | Open -SAM on KEYED file
128 | File not open or is open for output only
129 | File not open or is open for input only
130 | Open on file not yet closed
131 | KEY specified on sequential file
132 | KEY specified on stream file
133 | No KEY specified on KEYED file
134 | Not a PRINT file
135 | Not a STREAM file
136 | CALL dataname name not found
137 | B-format error (35)
138 | BI format error (36)
139 | C format error (32)
140 | E format error (34)
141 | I/O stack overflow
142 | Conversion error
143 | LIST input item too long
144 | Implicit open failed
145 | EOF found while parsing edited input
146 | End of string on GET/PUT string
147 | Invalid format item for GET/PUT string
148 | Invalid format for GET
149 | Cannot initialize RPG screens
150 | File not open for input
151 | REWRITE on input file
152 | File not open on non-optional "sequential"
153 | File open on optional
154 | Sequential error on REW or DELE COBOL85
155 | Sequential error no next record COBOL85
156 | Bad record size on current record
157 | Cannot read log record
158 | Bad log record
159 | Cannot open log file
160 | Cannot write log file
161 | No transaction
162 | No shared memory
163 | No begin work yet
164 | Can't use nfs
165 | Audit trail exists
166 | F format error
167 | Record number too big for data item
168 | Open of wrong file type within transaction
169 | CLOSE REEL on non reel file
170 | No READ or WRITE before DELETE of record
171 | Return from subroutine specified a value
172 | Return from function did not specify a value
173 | Bad definition for creating a VSAM file
174 | No -defext used
175 | SET requires INDEXED or VSAM files
176 | Missing FROM on REWRITE and not VSAM
Parent topic: Open PL/I Run-time Error Messages


Value Table for ONCODE Built-in Function

  • Introduction
  • Table of Values Returned by ONCODE
Parent topic: Open PL/I User's Guide


Introduction

For more information on ON conditions, see the section ON in the chapter Statements and the section ONCODE Function in the chapter Open PL/I Built-Ins, both in your Open PL/I Language Reference Manual.

Note that the value returned by ONCODE for some conditions is implementation-dependent; in fact, some conditions that occur on one implementation may not be raised at all on another implementation, even by an identical source program run on both implementations. Further, subsequent releases of Open PL/I may change these ONCODE values. Therefore, to make programs more portable, avoid writing Open PL/I programs that depend on specific ONCODE return values to function properly; failing that, use replace constants to represent needed values so that implementation-specific values can be changed easily.

Parent topic: Value Table for ONCODE Built-in Function
Related information
ON
ONCODE Function
%REPLACE


Table of Values Returned by ONCODE

The table below lists the values (codes) in ascending order, in sections marked by error category.

Code | Meaning
0 | ONCODE has been used outside of an active ON-unit
System-Defined Condition Codes
001 – 099 | A UNIX system error has occurred; the value returned corresponds exactly to the UNIX system error codes as listed in your system documentation.
100 – 89999 | An LPI run-time error has occurred; the value returned corresponds exactly to the Open PL/I run-time error codes, as documented in Appendix C. (Note that 89999 is the highest possible error number and that not all error numbers are currently being used.)
UNIX Signal Condition Codes
90000 | Shell exit for any reason other than UNIX signals, including EOF.
90nnn | UNIX signal number nnn has been caught by the LPI run-time system. The value nnn corresponds exactly with the signal number as defined in your system documentation, except for the following signals: SIGINT – Treated as PL/I ATTENTION condition. SIGFPE – Treated as computational error condition.
99001 | ERROR condition raised by SIGNAL ERROR statement.
99011 | FINISH condition
99012 | STOP condition
99020 | ATTENTION condition
99110 | ENDFILE condition
99120 | ENDPAGE condition
99130 | KEY condition
99140 | UNDEFINEDFILE condition
99150 | RECORD condition
99200 | Computational error; some operating systems indicate the precise cause of the error, in which case ONCODE will return the number corresponding to the more specific error description.
99201 | OVERFLOW condition
99202 | UNDERFLOW condition
99203 | ZERODIVIDE condition
99204 | SUBSCRIPTRANGE condition
99205 | CONVERSION condition
99206 | CONDITION condition
99207 | AREA condition
99210 | INVALID OPERAND condition
99211 | INVALID_ADD_SUBTRACT condition
99212 | INVALID_MULTIPLY condition
99213 | INVALID_DIVIDE condition
99214 | INVALID_MOD condition
99215 | INVALID_COMPARISON condition
99251 | INVALID_SQRT condition
99252 | INVALID_ASIN_ACOS condition
99253 | INVALID_ATAN2 condition
99254 | INVALID_LOG condition
99255 | INVALID_POWER condition
99256 | INVALID_ATANH condition
99257 | INVALID_COMPLEX_OPERAND condition
99301 | Stack unwind condition raised during non-local GOTO. This corresponds to the SS$_UNWIND value.
Parent topic: Value Table for ONCODE Built-in Function


Character Sets

  • EBCDIC/ASCII Equivalents
Parent topic: Open PL/I User's Guide


EBCDIC/ASCII Equivalents

Index | EBCDIC (Hex) | Character | ASCII (Hex) | Notes
000 | 00 | NUL | 00 | null
001 | 01 | SOH | 01 |
002 | 02 | STX | 02 |
003 | 03 | ETX | 03 |
004 | 04 | PF | EC |
005 | 05 | HT | 09 | horizontal tab
006 | 06 | LC | CA |
007 | 07 | DEL | 7F | delete
008 | 08 |  | E2 |
009 | 09 |  | D2 |
010 | OA | SMM | D3 |
011 | OB | VT | OB | vertical tab
012 | OC | FF | OC | form feed
013 | OD | CR | OD | carriage return
014 | OE | SO | OE |
015 | OF | SI | A9 |
016 | 10 | DLE | 10 |
017 | 11 | DC1 | 11 |
018 | 12 | DC2 | 12 |
019 | 13 | TM | 13 |
020 | 14 | RES | EF |
021 | 15 | NL | C5 |
022 | 16 | BS | 08 |
023 | 17 | IL | CB |
024 | 18 | CAN | 18 |
025 | 19 | EM | 19 |
026 | 1A | CC | DC |
027 | 1B | CU1 | D8 |
028 | 1C | IFS | 1C |
029 | 1D | IGS | 1D |
030 | 1E | IRS | 1E |
031 | 1F | IUS | 1F |
032 | 20 | DS | B7 |
033 | 21 | SOS | B8 |
034 | 22 | FS | B9 |
035 | 23 |  | BB |
036 | 24 | BYP | C4 |
037 | 25 | LF | OA | line feed (new line)
038 | 26 | ETB | 17 |
039 | 27 | ESC | 1B |
040 | 28 |  | CC |
041 | 29 |  | CD |
042 | 2A | SM | CF |
043 | 2B | CU2 | DO |
044 | 2C |  | D1 |
045 | 2D | ENQ | 05 |
046 | 2E | ACK | 06 |
047 | 2F | BEL | 07 | bell
048 | 30 |  | D9 |
049 | 31 |  | DA |
050 | 32 | SYN | 16 |
051 | 33 |  | DD |
052 | 34 | PN | DE |
053 | 35 | RS | DF |
054 | 36 | UC | E0 |
055 | 37 | EOT | 04 | end transmission
056 | 38 |  | E3 |
057 | 39 |  | E5 |
058 | 3A |  | E9 |
059 | 3B | CU3 | EB |
060 | 3C | DC4 | B0 |
061 | 3D | NAK | B1 |
062 | 3E |  | 9E |
063 | 3F | SUB | 1A |
064 | 40 | SP | 20 | space
065 | 41 |  | C9 |
066 | 42 |  | 83 |
067 | 43 |  | 84 |
068 | 44 |  | 85 |
069 | 45 |  | A0 |
070 | 46 |  | F2 |
071 | 47 |  | 86 |
072 | 48 |  | 87 |
073 | 49 |  | A4 |
074 | 4A | ¢ | D5 |
075 | 4B | . | 2E | period
076 | 4C | < | 3C |
077 | 4D | ( | 28 |
078 | 4E | + | 2B |
079 | 4F | I | 7C |
080 | 50 | & | 26 |
081 | 51 |  | 82
082 | 52 |  | 88 |
083 | 53 |  | 89 |
084 | 54 |  | 8A |
085 | 55 |  | A1 |
086 | 56 |  | 8C |
087 | 57 |  | 8B |
088 | 58 |  | 8D |
089 | 59 |  | E1
090 | 5A | ! | 21 |
091 | 5B | $ | 24 |
092 | 5C | * | 2A |
093 | 5D | ) | 29 |
094 | 5E | ; | 3B | semicolon
095 | 5F | ¬ | 7E | ASCII tilde (~)
096 | 60 | - | 2D | hyphen
097 | 61 | / | 2F |
098 | 62 |  | B2 |
099 | 63 |  | 8E |
100 | 64 |  | B4 |
101 | 65 |  | B5 |
102 | 66 |  | B6 |
103 | 67 |  | 8F |
104 | 68 |  | 80 |
105 | 69 |  | A5 |
106 | 6A |  | B3 |
107 | 6B | , | 2C | comma
108 | 6C | % | 25 |
109 | 6D | _ | 5F | underscore
110 | 6E | > | 3E |
111 | 6F | ? | 3F |
112 | 70 |  | BA
113 | 71 |  | 90 |
114 | 72 |  | BC |
115 | 73 |  | BD |
116 | 74 |  | BE |
117 | 75 |  | F3 |
118 | 76 |  | C0 |
119 | 77 |  | C1 |
120 | 78 |  | C2 |
121 | 79 | ´ | 60 | accent grave
122 | 7A | : | 3A | colon
123 | 7B | # | 23 |
124 | 7C | @ | 40 |
125 | 7D | ' | 27 | apostrophe (accent acute)
126 | 7E | = | 3D |
127 | 7F | " | 22 | quotation mark
128 | 80 |  | C3 |
129 | 81 | a | 61 |
130 | 82 | b | 62 |
131 | 83 | c | 63 |
132 | 84 | d | 64 |
133 | 85 | e | 65 |
134 | 86 | f | 66 |
135 | 87 | g | 67 |
136 | 88 | h | 68 |
137 | 89 | I | 69 |
138 | 8A |  | AE |
139 | 8B |  | AF |
140 | 8C |  | C6 |
141 | 8D |  | C7 |
142 | 8E |  | C8 |
143 | 8F |  | F1 |
144 | 90 |  | F8 |
145 | 91 | j | 6A |
146 | 92 | k | 6B |
147 | 93 | l | 6C |
148 | 94 | m | 6D |
149 | 95 | n | 6E |
150 | 96 | o | 6F |
151 | 97 | p | 70 |
152 | 98 | q | 71 |
153 | 99 | r | 72 |
154 | 9A |  | 5E | ASCII caret ( ^ )
155 | 9B |  | A7 |
156 | 9C |  | 91 |
157 | 9D |  | CE |
158 | 9E |  | 92 |
159 | 9F |  | 0F |
160 | A0 |  | E6 |
161 | A1 |  | A6 |
162 | A2 | s | 73 |
163 | A3 | t | 74 |
164 | A4 | u | 75 |
165 | A5 | v | 76 |
166 | A6 | w | 77 |
167 | A7 | x | 78 |
168 | A8 | y | 79 |
169 | A9 | z | 7A |
170 | AA |  | AD |
171 | AB |  | A8 |
172 | AC |  | D4 |
173 | AD |  | 5B | ASCII left bracket ( [ )
174 | AE |  | D6 |
175 | AF |  | D7 |
176 | B0 |  | 9B |
177 | B1 |  | 9C |
178 | B2 |  | 9D |
179 | B3 |  | FA |
180 | B4 |  | 9F |
181 | B5 |  | 15 |
182 | B6 |  | 14 |
183 | B7 |  | AC |
184 | B8 |  | AB |
185 | B9 |  | FC |
186 | BA |  | AA |
187 | BB |  | FE |
188 | BC |  | E4 |
189 | BD |  | 5D | ASCII right bracket (])
190 | BE |  | BF |
191 | BF |  | E7 |
192 | C0 |  | 7B | ASCII left brace ( { )
193 | C1 | A | 41 |
194 | C2 | B | 42 |
195 | C3 | C | 43 |
196 | C4 | D | 44 |
197 | C5 | E | 45 |
198 | C6 | F | 46 |
199 | C7 | G | 47 |
200 | C8 | H | 48 |
201 | C9 | I | 49 |
202 | CA |  | E8 |
203 | CB |  | 93 |
204 | CC |  | 94 |
205 | CD |  | 95 |
206 | CE |  | A2 |
207 | CF |  | ED |
208 | D0 |  | 7D | ASCII right brace ( } )
209 | D1 | J | 4A |
210 | D2 | K | 4B |
211 | D3 | L | 4C |
212 | D4 | M | 4D |
213 | D5 | N | 4E |
214 | D6 | O | 4F |
215 | D7 | P | 50 |
216 | D8 | Q | 51 |
217 | D9 | R | 52 |
218 | DA |  | EE |
219 | DB |  | 96 |
220 | DC |  | 81 |
221 | DD |  | 97 |
222 | DE |  | A3 |
223 | DF |  | 98 |
224 | E0 |  | 5C | ASCII backslash ( \ )
225 | E1 |  | F0 |
226 | E2 | S | 53 |
227 | E3 | T | 54 |
228 | E4 | U | 55 |
229 | E5 | V | 56 |
230 | E6 | W | 57 |
231 | E7 | X | 58 |
232 | E8 | Y | 59 |
233 | E9 | Z | 5A |
234 | EA |  | FD |
235 | EB |  | F5 |
236 | EC |  | 99 |
237 | ED |  | F7 |
238 | EE |  | F6 |
239 | EF |  | F9 |
240 | F0 | 0 | 30 |
241 | F1 | 1 | 31 |
242 | F2 | 2 | 32 |
243 | F3 | 3 | 33 |
244 | F4 | 4 | 34 |
245 | F5 | 5 | 35 |
246 | F6 | 6 | 36 |
247 | F7 | 7 | 37 |
248 | F8 | 8 | 38 |
249 | F9 | 9 | 39 |
250 | FA |  | DB |
251 | FB |  | FB |
252 | FC |  | 9A |
253 | FD |  | F4 |
254 | FE |  | EA |
255 | FF |  | FF |
Parent topic: Character Sets


Migration to Micro Focus File Formats

  • Overview
  • Reasons for Migrating to Micro Focus File Formats
  • Determine What File Formats You Are Using
  • Liant Indexed (aka) IBM/Informix CISAM
  • Liant Indexed (aka) IBM/Informix CISAM Conversion Process
  • Liant Variable Length Sequential Conversion Process
  • Liant Relative Record Conversion Process
  • Appendix - Unload Program
  • Appendix - Load Program
  • Appendix - Sample Shell Script to Build/Run
  • Appendix - Sample extfh.cfg
Parent topic: Open PL/I User's Guide


Overview

This guide shows you how to migrate your data to Micro Focus file formats so that it can be processed and manipulated using standard processes.

Parent topic: Migration to Micro Focus File Formats


Reasons for Migrating to Micro Focus File Formats

Micro Focus has its own file handler called Micro Focus ISAM that it has developed and enhanced for over two decades to provide file processing support for all Micro Focus COBOL based applications. Within version 8.1 of Open PL/I we have therefore switched to using this core technology from Micro Focus rather than relying on the 3 rd party file handler for Indexed files that was utilised originally within Open PL/I.

This will enable all Micro Focus to provide ongoing support for all file processing requirements of our Open PL/I customers from a single technology shared with all Micro Focus COBOL customers but it does require data to be unloaded from original files formats and loaded into new Micro Focus file formats. The following document gives guidance about how to go about this transition process.

Parent topic: Migration to Micro Focus File Formats


Determine What File Formats You Are Using

These are the available file formats:

  • Line Sequential - no conversion necessary
  • Liant Sequential Fixed Length - no conversion necessary
  • Liant Indexed (aka) - IBM/Informix CISAM - conversion necessary *
  • Liant Relative Record - conversion optional **
  • Liant Sequential (Variable Length) - conversion optional **
Parent topic: Migration to Micro Focus File Formats
* Conversion is necessary if utilizing PLI IO Verbs.
** Conversion is only necessary if you intend to utilize the data within Micro Focus Enterprise Server and/or share the files with Micro Focus COBOL Programs.


Liant Indexed (aka) IBM/Informix CISAM

If you are using native PL/I I/O Verbs, you must convert data to Micro Focus Indexed Format.

If you are using IBM/Informix "IsXXXXX" APIs, you have two options:
  • Convert API calls to native PL/I I/O Verbs (and convert data)
  • Purchase a copy of CISAM from IBM and continue to use your existing datasets and "IsXXXXX" APIs.
    ( isaddindex () isbuild () isclose () isdelcurr () isdelete () iserase () isindexinfo () isopen () isread () isrelease () isrewcurr () isrewrite () ISRELOCK () isstart () isdef () iswrite () )
Parent topic: Migration to Micro Focus File Formats


Liant Indexed (aka) IBM/Informix CISAM Conversion Process

Unload is a very simple generic program needing only maximum record length and file names.

Load is a very simple generic program needing only maximum record length, file names, and key offset and length. Sample code is provided in Appendix A.

Load requires use of extfh.cfg to prevent null bytes from being stripped from output.

Note: SCALARV in the diagram above stands for SCALARVARYING.

The source programs in Appendix A are small and very simple. If you find that you have a large number of files that need to be converted, then one approach would be to use a shell script to generate the unload and load programs.

The easiest way to automate the process and generate the conversion programs via scripts would be to place all of the %REPLACE statements and the VSAM File Declarations in a PLI %INCLUDE. You should then be able to compile up the programs and be off and running.

In our testing of this process we had both the Open PL/I 7.4 Compiler and Open PL/I 8.1 Compiler and RTS Environments running side by side with no problems.

Parent topic: Migration to Micro Focus File Formats


Liant Variable Length Sequential Conversion Process

Load and Unload programs are very simple generic programs needing only maximum record length and file names to be provided. Sample code provided in Appendix A can be easily modified.

Load requires use of extfh.cfg to prevent null bytes from being stripped from output.

Note: SCALARV in the diagram above stands for SCALARVARYING.
Parent topic: Migration to Micro Focus File Formats


Liant Relative Record Conversion Process

Load and Unload programs are very simple generic programs needing only maximum record length and file names to be provided. Sample code provided in Appendix A can be easily modified.

Load requires use of extfh.cfg to prevent null bytes from being stripped from output.

Note: SCALARV in the diagram above stands for SCALARVARYING.
Parent topic: Migration to Micro Focus File Formats


Appendix - Unload Program

unload_liant_files: proc() options(main);
%replace MAX_REC_LEN               by 100;
%replace MAX_REC_LEN_SV            by 102;
%replace INPUT_TITLE               by 'liantCISAM';
%replace OUTPUT_TITLE              by 'fixed_cisam.dat';
 dcl inputfile    file record         env(vsam  recsize( MAX_REC_LEN ) );
 dcl outputfile    file record output env(f recsize( MAX_REC_LEN_SV ));

 dcl record_buff char(MAX_REC_LEN ) varying;
 dcl fixed_buf   char( MAX_REC_LEN_SV ) based(addr(record_buff));
 dcl vsam_buff   char( MAX_REC_LEN );

 on endfile(inputfile) goto doneinputfile;

 open file(inputfile) title(INPUT_TITLE) keyed sequential input;
 open file(outputfile) title(OUTPUT_TITLE);

 substr(fixed_buf, 2, length(fixed_buf) - 2) = '';
 read file(inputfile) into(record_buff);
 do while(1);
    write file(outputfile) from (fixed_buf);
    substr(fixed_buf, 2, length(fixed_buf) - 2) = '';
    read file(inputfile) into(record_buff);
 end;

doneinputfile:
 close file(inputfile);
 close file(outputfile);
end;
Parent topic: Migration to Micro Focus File Formats


Appendix - Load Program

load_microfocus_files: proc() options(main);

%replace MAX_REC_LEN               by 100;
%replace MAX_REC_LEN_SV            by 102;
%replace INPUT_TITLE               by 'fixed_cisam.dat';
%replace OUTPUT_TITLE              by 'microfocusIndexed.dat';
%include ‘vsamrec.in’;

 dcl inputfile    file record input env(f recsize( MAX_REC_LEN_SV ));
 dcl outputfile    file record
     env(vsam  recsize( MAX_REC_LEN ) keyloc(11) keylength(10));
 dcl 1 fixed_buf based(addr(in_rec)),
       5 fixed_buf_len  fixed bin(15),
       5 fixed_buf_data char( MAX_REC_LEN );
 dcl in_rec    char( MAX_REC_LEN ) varying;
 on endfile(inputfile) goto done;
 open file(inputfile) title(INPUT_TITLE);
 open file(outputfile) title(OUTPUT_TITLE) keyed sequential output;
 read file(inputfile) into(fixed_buf);
 do while(1);
    string(vsam_rec) = in_rec;
    write file(outputfile) from (vsam_rec) keyfrom(last_name);
    read file(inputfile) into(fixed_buf);
 end;
done:
 close file(inputfile);
 close file(outputfile);
end;
Parent topic: Migration to Micro Focus File Formats


Appendix - Sample Shell Script to Build/Run

echo ‘Solaris Sparc Shell Script’
rm liant*
rm microfocus*
rm fixed_*

lpiplx -deb -defext -cisam create_liant_files.pli -o create_liant_files
lpiplx -deb -defext -cisam test_liant_files.pli   -o test_liant_files
lpiplx -deb -defext -cisam unload_liant_files.pli -o unload_liant_files

mfplx  -deb -defext load_microfocus_files.pli -o load_microfocus_files
mfplx  -deb -defext test_microfocus_files.pli -o test_microfocus_files

echo 'Running create_liant_files'
./create_liant_files
echo 'Running test_liant_files'
./test_liant_files
echo 'Running unload_liant_files'
./unload_liant_files
echo 'Running load_microfocus_files'
./load_microfocus_files
echo 'Running test_microfocus_files'
./test_microfocus_files
Parent topic: Migration to Micro Focus File Formats


Appendix - Sample extfh.cfg

[XFH-DEFAULT]
IDXFORMAT=8
INSERTNULL=OFF
Parent topic: Migration to Micro Focus File Formats
Related information
Configuration File


Copyright and Trademarks

Copyright © 1984-2010 Micro Focus (IP) Ltd. All rights reserved.

Micro Focus (IP) Ltd. has made every effort to ensure that this book is correct and accurate, but reserves the right to make changes without notice at its sole discretion at any time. The software described in this document is supplied under a license and may be used or copied only in accordance with the terms of such license, and in particular any warranty of fitness of Micro Focus software products for any particular purpose is expressly excluded and in no event will Micro Focus be liable for any consequential loss.

Micro Focus, the Micro Focus Logo, Micro Focus Server, Micro Focus Studio, Net Express, Net Express Academic Edition, Net Express Personal Edition, Server Enterprise Edition, Server Express, Mainframe Express, Animator, Application Server, AppMaster Builder, APS, Data Express, Enterprise Server, Enterprise View, EnterpriseLink, Object COBOL Developer Suite, Revolve, Revolve Enterprise Edition, SOA Express, Visual COBOL, Unlocking the Value of Legacy, and XDB are trademarks or registered trademarks of Micro Focus (IP) Limited in the United Kingdom, the United States and other countries.

IBM®, z/OS®, CICS® and RACF® are registered trademarks, and IMS™ is a trademark, of International Business Machines Corporation.

License management is based on SentinelRMS © 1989-2006 SafeNet, Inc. All rights reserved. Sentinel is a registered trademark of SafeNet, Inc.

Copyrights for third party software used in the product:

  • Apache
  • Eclipse

All other trademarks are the property of their respective owners.

Reference to third party companies, products and web sites is for information purposes only and constitutes neither an endorsement nor a recommendation. Micro Focus provides this information only as a convenience to users. Micro Focus makes no representation whatsoever regarding the content of any other web site or the use of any such third party products. Micro Focus shall not be liable in respect of your use or access to such third party products/web sites.

No part of this publication, with the exception of the software product user documentation contained on a CD-ROM, may be copied, photocopied, reproduced, transmitted, transcribed, or reduced to any electronic medium or machine-readable form without prior written consent of Micro Focus (IP) Ltd.

Licensees may duplicate the software product user documentation contained on a CD-ROM, but only to the extent necessary to support the users authorized access to the software under the license agreement. Any reproduction of the documentation, regardless of whether the documentation is reproduced in whole or in part, must be accompanied by this copyright statement in its entirety, without modification.

U.S. GOVERNMENT RESTRICTED RIGHTS. It is acknowledged that the Software and the Documentation were developed at private expense, that no part is in the public domain, and that the Software and Documentation are Commercial Computer Software provided with RESTRICTED RIGHTS under Federal Acquisition Regulations and agency supplements to them. Use, duplication or disclosure by the U.S. Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer Software clause at DFAR 252.227-7013 et. seq. or subparagraphs (c)(1) and (2) of the Commercial Computer Software Restricted Rights at FAR 52.227-19, as applicable. Contractor is Micro Focus (IP) Ltd, 9420 Key West Avenue, Rockville, Maryland 20850. Rights are reserved under copyright laws of the United States with respect to unpublished portions of the Software.

Parent topic: Open PL/I 8.1 for UNIX


Notations and Conventions

  • Enter refers to the carriage return or Enter key. Where commands to be typed are shown, the Enter key is not explicitly shown; it is treated as implicit that Enter must be pressed at the end of the line.
  • Hexadecimal numbers are enclosed in quotation marks and preceded by a lower-case "x" or "h"; for example, x"9D", h"03FF". The "x" is used when the hexadecimal number represents a character string; the "h" when it represents a numerical value.
  • PIC X is used rather than PIC 99 with the COMP-X and COMP-5 data types. Unlike PIC 99, PIC X shows the length of the data item and so demonstrates more clearly the use of COMP-X, which is to define a binary item of the specified number of bytes.
  • Keytops and menu choices are emboldened within the text.
  • In some environments, you might notice that what appears on your screen differs in minor ways (for example, version numbers) from that illustrated in this Help. This does not affect the operation of your software.
  • F1=Help appears on every menu in character-mode Micro Focus software. It invokes a help screen describing the current menu.

The notation used to describe the format of command lines is as follows:

  • Words printed in italics are generic terms representing names to be devised by you.
  • Words printed in nonitalic characters are the actual words you must enter. You must type them in upper or lower case as shown.
  • Material enclosed in square brackets [ ] is optional.
  • When material is enclosed in braces { }, you must choose from the options within them. If there is only one option in the braces, the braces indicate repetition.
  • The ellipsis (. . .) follows { } or [ ] and means you can repeat the material in the { } or [ ]. The number of repetitions allowed is unlimited unless otherwise stated. If the ellipsis is used with [ ] the material can be omitted altogether.
  • If a command line does not fit across the page, it is continued on the next line; the continuation line is indented.
  • The Help may refer you to the readme for details specific to a particular UNIX platform.
  • All command line formats and examples are for the standard UNIX shell, the Bourne shell. If you are using another shell, see your UNIX documentation for the appropriate formats.
  • Where examples showing environment variables do not specifically show them being exported to the shell, it is treated as implicit that they are exported.
  • Some keystrokes using function keys or the Alt or Ctrl keys are not available on all UNIX platforms.The UNIX Key Usage Chart shows how the keystrokes shown in the Help map onto actual keystrokes.
Parent topic: Open PL/I 8.1 for UNIX


Scenario - Disconnecting your computer from the license server network

You need to disconnect your computer from the network that gives you access to the license server to work, for example, from home or a customer site. You need a license to continue to use your product.

You can obtain a license temporarily from the license server. This is known as a commuter license.

  1. Start the Micro Focus License System Administration tool.
  2. Obtain a commuter license.
  3. Disconnect your computer from the network.
Related tasks
To start the Licensing System Administration tool
To obtain a commuter license
To return a commuter license


To return a commuter license

  1. Start the Micro Focus License System Administration tool.
  2. Select the Commuter tab.
  3. Select the appropriate product and press Return.
Related tasks
To start the Licensing System Administration tool
To authorize your product using a local license server
To authorize your product manually
To set up a central license server and load licenses
To authorize your product using a central license server
To view installed licenses
To revoke licenses
To revoke licenses manually
To obtain a commuter license
To start the Licensing System Administration tool
To authorize your product
To view installed licenses
To configure licenses
To install licenses from a license file
To revoke licenses


To revoke licenses during product uninstall

When you uninstall a product, the Micro Focus License Manager software perfoms a check to see if any licenses for that product exist on your computer. If so, you will be prompted to revoke them. If you do revoke them, they will be removed and you will be given you a new authorization code. You use this new code to generate a license when you install the product on another machine.

If you are going to re-install your product on the same machine, you do not need to revoke the license. In this case, select Keep when you are prompted to revoke the license.

  1. Uninstall your product.

    A prompt will display to reallocate your licenses.

  2. Select Revoke if you want to revoke the licenses.

    The Micro Focus License System Administration tool is displayed at the Revoke tab.

  3. Select the product license you want to revoke.
  4. Click Revoke.

    After a check has been made to ensure no licensed products are running, the Revoke Product Licenses dialog box is displayed.

  5. Input or select the number of licenses you want to revoke.
  6. Click Revoke.

    A new authorization code for each revoked license will be generated and saved to file on your computer. The file location and the new codes will be displayed on the screen.

    Ensure that you keep the new authorization codes in a safe place. You will need them when you re-authorize your product(s) .

Note: If there is a problem accessing the Micro Focus License Authorization Server and the revoke fails, the Revoke Product Licenses dialog box will enable options to allow manual revocation. At this point your licences are revoked and cannot be used. To obtain an authorization code you must send the License Revocation Tickets (LRTs) to Micro Focus, either by pasting them into the revoke web page or by sending the indicated file to your SupportLine representative.


To obtain a commuter license

Not all licenses are commutable. You must have commuter licenses on your license server.
  1. Start the Micro Focus License System Administration tool.
  2. Select the Commuter tab. A list of commutable products is displayed.
  3. Select the product you want to commute and click Commute. A dialog is displayed allowing you to select the number of days you want to commute the license for.
Commuted licenses will appear in the Commuted here column with the number of days remaining in the commute period.

Related tasks
To start the Licensing System Administration tool
To authorize your product using a local license server
To authorize your product manually
To set up a central license server and load licenses
To authorize your product using a central license server
To view installed licenses
To revoke licenses
To revoke licenses manually
To return a commuter license
To start the Licensing System Administration tool
To authorize your product
To view installed licenses
To configure licenses
To install licenses from a license file
To revoke licenses


Scenario - Licensing using a local license server

You need to:

  1. Start the Micro Focus License System Administration tool.
  2. Authorize your product using your authorization code.
Related tasks
To start the Licensing System Administration tool
To authorize your product using a local license server


Scenario - Licensing using a central license server

You need to:

  1. Start the Micro Focus License System Administration tool.
  2. Authorize the product on your workstation by configuring it to obtain a license from your site's central license server.
Related tasks
To start the Licensing System Administration tool
To authorize your product using a central license server


Scenario - Moving your product to a different computer

You need to:

  1. Start the Micro Focus License System Administration tool.
  2. Revoke the license, making note of the new authorization code that will be required when you re-authorize your product.
  3. Uninstall the product.
  4. Install the product on the new computer.
  5. Start the Micro Focus License System Administration tool.
  6. Authorize your product with the new authorization code.
Note: You can proceed with the product uninstall without taking steps to revoke the license first. In this case, you will be guided through the revoke process as part of the uninstall.
Related tasks
To start the Licensing System Administration tool
To revoke licenses during product uninstall
To authorize your product using a local license server
To authorize your product using a central license server


To authorize your product using a local license server

The task steps below describe how to authorize your product if you are using the license server that is set up on you local machine. (The license server is automatically set up when you first install your product).

  1. Start the Licensing System Administration tool if it is not already enabled.
  2. Click the Authorize tab.
  3. Enter your authorization code.
  4. Click Authorize.
Note: If authorization fails, the user interface will allow you to attempt manual authorization.
Related tasks
To start the Licensing System Administration tool
To authorize your product manually
To set up a central license server and load licenses
To authorize your product using a central license server
To view installed licenses
To revoke licenses
To revoke licenses manually
To obtain a commuter license
To return a commuter license


To authorize your product manually

Manual authorization is necessary if your machine does not have Internet connectivity or if normal (automatic) authorization has failed. Where normal authorization has failed the user interface for Manual authorization is displayed automatically. You can start the interface manually by taking the Manual Activation option from the Options menu.

  1. Start the Licensing System Administration tool if it is not already enabled.
  2. From the Options menu, select Manual Authorization.

Take the following steps for both methods of Manual Authorization:

  1. Either:

    Click the http link on the Manual Authorization Interface

    or

    Paste the http link into an Internet browser.

    The link will take you to the Micro Focus Safenet activation webpage.

  2. Enter your authorization code in Enter Authorization Code .
    Your authorization code is a 16-character alphanumeric string. Depending on how you obtained your product the code will be either:
    • printed on a colored card marked Authorization Code that is provided with your product packaging or,
    • provided in an accompanying email if your product was obtained by electronic download.
  3. Enter your Machine ID. The Machine ID string is displayed on the Manual Authorization interface.
  4. Click Generate.
  5. Copy the generated license string and paste it into License String on the Manual Authorization interface.
  6. Click Install Licenses.
Related tasks
To start the Licensing System Administration tool
To authorize your product using a local license server
To set up a central license server and load licenses
To authorize your product using a central license server
To view installed licenses
To revoke licenses
To revoke licenses manually
To obtain a commuter license
To return a commuter license


To view installed licenses

  1. Start the Micro Focus License System Administration tool.
  2. Select the Licenses tab.
Related tasks
To start the Licensing System Administration tool
To authorize your product using a local license server
To authorize your product manually
To set up a central license server and load licenses
To authorize your product using a central license server
To revoke licenses
To revoke licenses manually
To obtain a commuter license
To return a commuter license


To start the Licensing System Administration tool

From the Windows Taskbar click Start > All Programs > Micro Focus Open PLI x.x > License System Administration .

Related tasks
To authorize your product using a local license server
To authorize your product manually
To set up a central license server and load licenses
To authorize your product using a central license server
To view installed licenses
To revoke licenses
To revoke licenses manually
To obtain a commuter license
To return a commuter license


To revoke licenses

Revoke licenses if you want, for example, to move your product to a different machine or if you no longer use your product and want to reallocate the license.

  1. Start the Micro Focus License System Administration tool.
  2. Select the Revoke tab.
  3. Select the product license you want to revoke.
  4. Click Revoke

    After a check has been made to ensure no licensed products are running, the Revoke Product Licenses dialog box is displayed.

  5. Input or select the number of licenses you want to revoke.
  6. Click Revoke.

    A new authorization code for each revoked license will be generated and saved to file on your computer. The file location and the new codes will be displayed on the screen.

    Ensure that you keep the new authorization codes in a safe place. You will need them when you re-authorize your product(s) .

    Note: If there is a problem accessing the Micro Focus License Authorization Server and the revoke fails, the Revoke Product Licenses dialog box will enable options to allow manual revocation. At this point your licences are revoked and cannot be used. To obtain an authorization code you must send the License Revocation Tickets (LRTs) to Micro Focus, either by pasting them into the revoke web page or by sending the indicated file to your SupportLine representative.
Related tasks
To start the Licensing System Administration tool
To authorize your product using a local license server
To authorize your product manually
To set up a central license server and load licenses
To authorize your product using a central license server
To view installed licenses
To revoke licenses manually
To obtain a commuter license
To return a commuter license


To authorize your product using a central license server

The task steps below describe how to authorize your workstation product if you want to obtain a license from a central license server.

You need the IP address or server name for the central license server you want to access. You should be able to get this from your License System Administrator.

  1. Start the Micro Focus License System Administration tool.
  2. Select Options -> Advanced Configuration
  3. Click Change against the License Server row.
  4. Enter the IP address or server name for the license server.
  5. Click Save.
  6. Click Close.
Note: We recommend that other options on Advanced Configuration are modified only under guidance from Micro Focus SupportLine.
Related tasks
To start the Licensing System Administration tool
To authorize your product using a local license server
To authorize your product manually
To set up a central license server and load licenses
To view installed licenses
To revoke licenses
To revoke licenses manually
To obtain a commuter license
To return a commuter license


To set up a central license server and load licenses

Note: Internet connectivity is required to authorize your product and obtain licenses

After you have installed your product:

  1. Start the Micro Focus License System Administration tool.
  2. Click the Authorize tab.
  3. Enter your authorization code.
    Your authorization code is a 16-character alphanumeric string. Depending on how you obtained your product the code will be either:
    • printed on a colored card marked Authorization Code that is provided with your product packaging or,
    • provided in an accompanying email if your product was obtained by electronic download.
  4. Click Authorize.
Related tasks
To start the Licensing System Administration tool
To authorize your product using a local license server
To authorize your product manually
To authorize your product using a central license server
To view installed licenses
To revoke licenses
To revoke licenses manually
To obtain a commuter license
To return a commuter license


To revoke licenses manually

The manual revoke process should be followed when automatic revoke has failed. If automatic revocation fails, the Revoke Product Licenses dialog box will display options for manual revocation.

Either:

  1. Copy all of the character string displayed in the text box at the bottom of the Revoke Product Licenses dialog box.

    This string contains the Sentinel RMS License Revoke Tickets that are required to issue a new authorization code.

  2. Click the http link.

    The link will take you to the Micro Focus SafeNet License Revocation webpage.

  3. Paste the copied string into the text box and click Generate.

    The new Authorization code will be displayed.

Or

Copy all of the character string displayed in the text box at the bottom of the Revoke Product Licenses dialog box and send in an email to you SupportLine representative.

Note: Ensure that you keep the new authorization codes in a safe place. You will need them when you re-authorize your product .
Related tasks
To start the Licensing System Administration tool
To authorize your product using a local license server
To authorize your product manually
To set up a central license server and load licenses
To authorize your product using a central license server
To view installed licenses
To revoke licenses
To obtain a commuter license
To return a commuter license