DocumentationEndless PL/I for OpenVMSUser Manual  ·  ESS-PFVUM-001

Appendix C

Optional Programming Productivity Tools

This appendix provides an overview of optional programming productivity tools. As these tools are not included with the PL/I software, they must be purchased separately. Using these tools can increase your productivity as a PL/I programmer. For information on how to purchase these tools, contact your VSI sales representative.

C.1. Using LSE with PL/I

The DEC Language-Sensitive Editor (LSE) is a powerful and flexible text editor designed for software development. LSE's features help you to produce syntactically correct code in PL/I.

To invoke LSE, specify the LSEDIT command followed by a file name with a PLI file type at the DCL prompt. For example:

$ LSEDIT USER.PLI

The following sections describe some of the key features of LSE. Section C.1.1, “Entering Source Code Using Tokens and Placeholders” discusses how to enter source code using LSE, and Section C.1.2, “Compiling Source Code” describes LSE's compiler interface features. Section C.1.3, “Examples” gives examples of how to generate PL/I source code with LSE. Section C.2, “Using SCA (Endless PL/I V3.9 for OpenVMS VAX only)” describes the Source Code Analyzer, which you can use only with Endless PL/I V3.9 for OpenVMS VAX.

For more information on LSE and the Source Code Analyzer (SCA), see the Guide to Language-Sensitive Editor for VMS Systems and the Guide to Source Code Analyzer for VMS Systems.

C.1.1. Entering Source Code Using Tokens and Placeholders

LSE's language-sensitive features simplify the tasks of developing and maintaining software systems. These features include language-specific placeholders and tokens, aliases, comment and indentation control, and templates for subroutine libraries. The following sections describe these features in detail.

LSE can be used as a traditional text editor. In addition, you can have the power of using LSE's tokens and placeholders to step through each program construct and supply text for those constructs needing it.

Placeholders are markers in the source code that indicate locations where you can provide program text. These placeholders help you to supply the appropriate syntax in a given context. Generally, you do not need to enter placeholders; rather, they are inserted for you by LSE. Placeholders are surrounded by brackets or braces.

The types of LSE placeholders are as follows:

TypeDescription
Terminal placeholdersProvide text strings that describe valid replacements for the placeholder
Nonterminal placeholdersExpand into additional language constructs
Menu placeholdersProvide a list of options corresponding to the placeholder

Placeholders are either optional or required. Required placeholders, indicated by braces, represent places in the source code where you must provide program text. Optional placeholders, indicated by brackets, represent places in the source code where you can either provide additional constructs or erase the placeholder.

You can move forward or backward from placeholder to placeholder. In addition, you can delete or expand placeholders as needed.

Tokens typically represent keywords in PL/I. Tokens are provided for all PL/I statements, built-in functions, and built-in subroutines. When expanded, tokens provide additional language constructs. You can enter tokens directly into the buffer.

Generally, you use tokens in situations, such as modifying an existing program, where you want to add additional language constructs and there are no placeholders. For example, typing IF and issuing the EXPAND command causes a template for an IF construct to appear on your screen.

You can use tokens to insert text when editing an existing file by typing the name for a function or keyword and issuing the EXPAND command. You can also use tokens to bypass long menus in situations where expanding a placeholder, such as [statement], would result in a lengthy menu.

LSE provides commands that allow you to manipulate tokens and placeholders. These commands and their default key bindings are as follows:

CommandKey BindingFunction
EXPANDCtrl/eExpands a placeholder
UNEXPANDPF1-Ctrl/eReverses the effect of the most recent placeholder expansion
GOTO PLACEHOLDER/FORWARDCtrl/nMoves the cursor forward to the next placeholder
GOTO PLACEHOLDER/REVERSECtrl/pMoves the cursor backward to the previous placeholder
ERASE PLACEHOLDER/FORWARDCtrl/kErases a placeholder
UNERASE PLACEHOLDERPF1-Ctrl/kRestores the most recently erased placeholder
NoneDown arrowMoves the indicator through a screen menu toward the bottom
NoneUp arrowMoves the indicator through a screen menu toward the top
None
{ ENTER  }
{ RETURN }
Selects a menu option

To display a list of all the defined tokens provided by PL/I, enter the SHOW TOKEN command as follows:

LSE> SHOW TOKEN

To display a list of all the defined placeholders provided by PL/I, enter the SHOW PLACEHOLDER command as follows:

LSE> SHOW PLACEHOLDER

You must have a PLI file in your current buffer in order to use the SHOW TOKEN or SHOW PLACEHOLDER command. To put a copy of either list into a separate file, first enter the appropriate SHOW command to put the list into the $SHOW buffer. Then enter the following commands:

LSE> GOTO BUFFER $SHOW
LSE> WRITE filename

To obtain a hard copy of the list, use the PRINT command at the DCL level to print the file you created.

To obtain information about a particular token or placeholder, you can also specify a token name or placeholder name after the SHOW TOKEN or SHOW PLACEHOLDER command.

C.1.2. Compiling Source Code

To compile your code and to review compilation errors without leaving the editing session, you can use the LSE commands COMPILE and REVIEW. The COMPILE command issues a DCL command in a subprocess to invoke the PL/I compiler. The compiler then generates a file of compile-time diagnostic information that LSE can use to review compilation errors. The diagnostic information is generated with the /DIAGNOSTICS qualifier that LSE appends onto the compilation command.

For example, if you issue the COMPILE command while in the buffer USER.PLI, the resulting DCL command is as follows:

$ PLI USER.PLI/DIAGNOSTICS=USER.DIA

LSE supports all of the PL/I compiler's command qualifiers as well as user-supplied command procedures. You can specify DCL qualifiers, such as the /LIBRARY qualifier, when invoking the compiler from LSE. For example, to generate Source Code Analyzer (SCA) data (with Endless PL/I V3.9 for OpenVMS VAX only), you can use the following command:

LSE> COMPILE $/ANALYSIS_DATA

The REVIEW command displays any diagnostic messages that result from a compilation. LSE displays the compilation errors in one window and the corresponding source code in a second window. This multiwindow capability allows you to review your errors while examining the associated source code. This capability eliminates tedious steps in the error correction process, and helps ensure that all the errors are fixed before you compile your program again.

LSE provides several commands to help you review errors and examine your source code. The following table lists these commands and their default key bindings where applicable.

CommandKey BindingFunction
COMPILENoneCompiles the contents of the source buffer
COMPILE/REVIEWNoneCompiles the contents of the source buffer, puts LSE into REVIEW mode, and displays any errors resulting from the compilation
REVIEWNonePerforms the same function as the /REVIEW qualifier on the COMPILE command: puts LSE into REVIEW mode, and displays any errors resulting from the last compilation
END REVIEWNoneRemoves the buffer $REVIEW from the screen; returns the cursor to a single window containing the source buffer
GOTO SOURCECtrl/gMoves the cursor to the source buffer that contains the error
NEXT STEPCtrl/fMoves the cursor to the next error in the buffer $REVIEW
PREVIOUS STEPCtrl/bMoves the cursor to the previous error in the buffer $REVIEW
None
{ Down arrow }
{ Up arrow   }
Moves the cursor within a buffer

C.1.3. Examples

This section describes the special features of PL/I available through LSE and provides examples of PL/I code written with LSE.

The following examples show expansions of the more frequently used PL/I tokens and placeholders. The examples are expanded to show the formats and guidelines LSE provides; however, not all of the examples are fully expanded.

The examples show expansions of the following PL/I features:

  • DO Statement

  • IF Statement

  • Assignment Statement

  • DECLARE Statement

  • SUBSTR Expression

  • %PROCEDURE Statement

Instructions and explanations precede each example, and an arrow (->) indicates the line in the code where an action has occurred.

To reproduce the examples, invoke LSE and the PL/I language by using the following syntax:

LSEDIT [/qualifier...] filename.PLI

See Section C.1.1, “Entering Source Code Using Tokens and Placeholders” for the commands that manipulate tokens and placeholders.

When you use LSE to create a new PL/I program, the initial string appears at the top of the screen as follows:

        [program]

Expand the placeholder [program] to produce the following:

        /*
        [module_header_comments]
        **/
        [preprocessor_statement]...
        [declare_statement]...
        {procedure}...

Erase the first five lines of this expansion and expand the placeholder {procedure}.

        /*
        [procedure_header_comments]
        **/

->     {entry_name}: procedure [parameters] [options] [returns] [recursive];
        [declare_statement]...
        [statement]...
        end {entry_name};
        [procedure]...

Erase the first three lines. Enter test over the placeholder {entry_name}. (Once the cursor is moved from that text, LSE automatically fills in the next occurrence of {entry_name}.) Erase the placeholder [parameters].

->     test: procedure [options] [returns] [recursive];
        [declare_statement]...
        [statement]...
        end test;
        [procedure]...

Expand the placeholder [options].

->     test: procedure options({option}...) [returns] [recursive];
        [declare_statement]...
        [statement]...
        end test;
        [procedure]...

Expand the list placeholder {option} to produce a menu and select the option MAIN.

->     test: procedure options(main, [option]...) [returns] [recursive];
        [declare_statement]...
        [statement]...
        end test;
        [procedure]...

Erase the duplicated placeholder [option], and the placeholders [returns], [recursive], and [declare_statement].

        test: procedure options(main);
        [statement]...
        end test;
        [procedure]...

Each of the following examples starts from this expansion.

C.1.4. DO Statement

Begin at the following expansion developed in Section C.1.3, “Examples”.

        test: procedure options(main);
        [statement]...
        end test;
        [procedure]...

Expand the list placeholder [statement] to display a menu and select the option DO.

        test: procedure options(main);

->     do [do_specification];
            [statement]...
            end;
        [statement]...
        end test;
        [procedure]...

Expand the placeholder [do_specification] to display a menu and select the option while ({boolean_expression}).

        test: procedure options(main);

->     do while({boolean_expression});
            [statement]...
            end;
        [statement]...
        end test;
        [procedure]...

Enter '1'b over the placeholder {boolean_expression}.

        test: procedure options(main);

->     do while('1'b);
            [statement]...
            end;
        [statement]...
        end test;
        [procedure]...

C.1.5. IF Statement

Begin at the following expansion developed in Section C.1.3, “Examples”.

        test: procedure options(main);
        [statement]...
        end test;
        [procedure]...

Expand the list placeholder [statement] to display a menu and select the option IF.

        test: procedure options(main);

->     if {boolean_expression}
        then
            [if_action]
        [else_clause]
        [statement]...
        end test;
        [procedure]...

Enter not_control over the placeholder {boolean_expression}.

        test: procedure options(main);

->     if not_control
        then
            [if_action]
        [else_clause]
        [statement]...
        end test;
        [procedure]...

Enter string='missile'; over the placeholder [if_action].

        test: procedure options(main);
        if not_control
        then

->         string='missile';
        [else_clause]
        [statement]...
        end test;
        [procedure]...

Expand the placeholder [else_clause].

        test: procedure options(main);
        if not_control
        then
            string='missile';

->     else
            {if_action}
        [statement]...
        end test;
        [procedure]...

Enter string='control'; over the placeholder {if_action}.

        test: procedure options(main);
        if not_control
        then
            string='missile';
        else

->         string='control';
        [statement]...
        end test;
        [procedure]...

C.1.6. Assignment Statement

Begin at the following expansion developed in Section C.1.3, “Examples”.

        test: procedure options(main);
        [statement]...
        end test;
        [procedure]...

Expand the list placeholder [statement] to display a menu and select the option ASSIGNMENT.

        test: procedure options(main);

->     {target_variable}... ={expression};
        [statement]...
        end test;
        [procedure]...

Expand the placeholder {target_variable} to display a menu and select the option {SCALAR_VARIABLE}.

        test: procedure options(main);

->     {SCALAR_VARIABLE},[target_variable]... ={expression};
        [statement]...
        end test;
        [procedure]...

Enter general over the placeholder {SCALAR_VARIABLE} and erase the placeholder [target_variable]. Enter 'Lee' over the placeholder {expression}.

        test: procedure options(main);

->     general='Lee';
        [statement]...
        end test;
        [procedure]...

C.1.7. DECLARE Statement

Begin at the following expansion developed in Section C.1.3, “Examples”.

        test: procedure options(main);
        [statement]...
        end test;
        [procedure]...

Expand the placeholder [statement] to display a menu and select the option DECLARE.

        test: procedure options(main);

->     declare
            {declaration}...;
        [statement]...
        end test;
        [procedure]...

Expand the list placeholder {declaration} to display a menu and select the option {NON_STRUCTURE_DECLARATION}.

        test: procedure options(main);
        declare

->         {NON_STRUCTURE_DECLARATION}...,
            [declaration]...;
        [statement]...
        end test;
        [procedure]...

Expand the placeholder {NON_STRUCTURE_DECLARATION} to display a menu and select the option {SIMPLE_DECLARATION}.

        test: procedure options(main);
        declare

->         {identifier}[array_bounds] [datatype] [storage_class],
            [declaration]...;
        [statement]...
        end test;
        [procedure]...

Enter what_if over the placeholder {identifier} and erase the placeholder [array_bounds].

        test: procedure options(main);
        declare

->         what_if [datatype] [storage_class],
            [declaration]...;
        [statement]...
        end test;
        [procedure]...

Expand the placeholder [datatype] to display a menu and select the option [BIT_DATATYPE].

        test: procedure options(main);
        declare

->        what_if bit[string_length_opt] [aligned] [storage_class],
           [declaration]...;
        [statement]...
        end test;
        [procedure]...

Erase the placeholder [string_length_opt] and expand the placeholder [aligned].

        test: procedure options(main);
        declare

->        what_if bit aligned [storage_class],
           [declaration]...;
        [statement]...
        end test;
        [procedure]...

Expand the placeholder [storage_class] to display a menu and select the option [CONTROLLED].

        test: procedure options(main);
        declare

->        what_if bit aligned controlled [external],
           [declaration]...;
        [statement]...
        end test;
        [procedure]...

Erase the placeholders [external] and [declaration].

        test: procedure options(main);
        declare

->         what_if bit aligned controlled;
        [statement]...
        end test;
        [procedure]...

C.1.8. SUBSTR Expression

Begin at the following expansion developed in Section C.1.3, “Examples”.

        test: procedure options(main);
        [statement]...
        end test;
        [procedure]...

Expand the placeholder [statement] to produce a menu and select the option ASSIGNMENT.

        test: procedure options(main);

->     {target_variable}... ={expression};
        [statement]...
        end test;
        [procedure]...

Expand the placeholder {target_variable} to display a menu and select the option {SCALAR_VARIABLE}.

        test: procedure options(main);

->     {SCALAR_VARIABLE},[target_variable]... ={expression};
        [statement]...
        end test;
        [procedure]...

Enter vhf over the placeholder {SCALAR_VARIABLE}. Erase the placeholder [target_variable]. Enter substr over the placeholder {expression} and expand substr.

        test: procedure options(main);

->     vhf=substr({string_expression},{position}[length_option]);
        [statement]...
        end test;
        [procedure]...

Enter 'where''s dixie' over the placeholder {string_expression}.

        test: procedure options(main);

->     vhf=substr('where''s dixie',{position}[length_option]);
        [statement]...
        end test;
        [procedure]...

Enter the value 9 over the placeholder {position}. Expand the placeholder [length_option], and enter the value 5 over the placeholder {integer_expression}.

        test: procedure options(main);

->     vhf=substr('where''s dixie',9,5);
        [statement]...
        end test;
        [procedure]...

C.1.9. %PROCEDURE Statement

Begin at the following expansion developed in Section C.1.3, “Examples”.

        test: procedure options(main);
        [statement]...
        end test;
        [procedure]...

Erase the list placeholder [statement]. Enter %proc and expand it.

        test: procedure options(main);

->     %{identifier}: procedure [parameters] [statement_option]
                returns({prep_attribute});
            [prep_proc_statements]...
            return({prep_expression});
            %end;
        end test;
        [procedure]...

Enter f over the placeholder {identifier}.

        test: procedure options(main);

->     %f: procedure [parameters] [statement_option]
                returns({prep_attribute});
            [prep_proc_statements]...
            return({prep_expression});
            %end;
        end test;
        [procedure]...

Erase the placeholders [parameters] and [statement_option].

        test: procedure options(main);

->     %f: procedure returns({prep_attribute});
            [prep_proc_statements]...
            return({prep_expression});
            %end;
        end test;
        [procedure]...

Enter char over the placeholder {prep_attribute} and erase the placeholder [prep_proc_statements].

        test: procedure options(main);

->     %f: procedure returns(char);
            return({prep_expression});
            %end;
        end test;
        [procedure]...

Enter time() over the placeholder {prep_expression}.

        test: procedure options(main);
        %f: procedure returns(char);

->         return(time());
            %end;
        end test;
        [procedure]...

C.2. Using SCA (Endless PL/I V3.9 for OpenVMS VAX only)

The DEC Source Code Analyzer (SCA) is an interactive source code cross-reference and static analysis tool that works with most OpenVMS programming languages. SCA helps developers keep track of the details of complex, large-scale software systems by displaying source information in response to user queries. SCA uses data generated by the PL/I compiler to supply the requested source information. That information is stored in a unique location, the SCA library. The data in an SCA library consists of the names of, and information about, all the symbols, modules, and files encountered during a specific compilation of the source.

SCA has both cross-reference and static analysis query features. Cross-referencing supplies information about program symbols and source files. Cross-referencing features include the following:

  • Locating names, and occurrences (uses) of these names

  • Querying a specified set of names or partial names (with wildcards allowed)

  • Limiting a query to specific characteristics (such as routine names, variable names, or source files)

  • Limiting a query to specific occurrences (such as the primary declaration of a symbol, read or write occurrences of a symbol, or occurrences of a file)

The static analysis query features of SCA provide structural information on the interrelation of routines, symbols and files. Static analysis features include the following:

  • Displaying routine calls to and from a specified routine

  • Analyzing routine calls for consistency as to the numbers and data types of arguments passed, and the types of values returned

SCA is fully integrated with LSE to provide extended features. By using SCA with LSE, you can view any portion of an entire system and edit related source files.

C.2.1. Multimodular Development

The cross-referencing and static analysis features of SCA can become useful during the implementation and maintenance phases of a project that involves many programming modules. For example, Figure C.1, “Use of SCA for Multimodular Development” shows a project team work area that contains a set of source modules. To keep track of these modules in their various development stages, the team can use a code management tool, such as Code Management System (CMS), which is represented in the figure by the CMS Library.

Figure C.1. Use of SCA for Multimodular Development
Use of SCA for Multimodular Development

When the team compiles the source code, a /ANALYSIS_DATA qualifier to the COMPILE command instructs the PL/I compiler to generate SCA-required source information (.ANA data files) from the sources. The team then instructs SCA to load the .ANA files into a previously established SCA Library.

When a team member wants to do additional development work on specific modules, that member sets up an individual work area. Such individual work areas might consist of the following:

  • Copies of source and object modules from the project libraries.

  • Local SCA libraries that contain copies of the module information required to complete assigned tasks.

To make available the module-viewing capabilities of SCA/LSE integration, the project team member must inform LSE of the locations of latest sources, and the related source information. The team member provides pointers to these locations by supplying a search list for LSE. The search list first points to source modules in individual team members' default directories, and then points to the remaining modules in the project source directory. With such an arrangement, each member can effectively see through the local work area to the project-wide area. If an individual work area contains only new modules, and all of the work can be done with local resources, the team member need not specify the pointers to the project-wide area.

The following sections provide a general overview of SCA and discuss some of the commands that are available to you while using SCA within LSE. For detailed information on SCA and its use with various programming languages, refer to the manual Using DECset for VMS Systems.

C.2.2. Setting Up an SCA Environment

To set up an SCA environment, you must take the following steps:

  1. Create an SCA library in a subdirectory.

  2. Use the PL/I compiler to generate the data analysis (.ANA) files for each source module in your system.

  3. Load these data analysis files into your local SCA library.

You are then ready to use SCA to conduct source information queries.

C.2.2.1. Creating an SCA Library

To use SCA, you must have an SCA library to store the detailed source analysis data that the PL/I compiler collects. Source analysis data is information about all of the symbols, files and modules contained in the source.

To create an SCA library you first create a subdirectory at the DCL level. For example:

$ CREATE/DIRECTORY PROJ:[USER.LIB1]

This command creates a subdirectory LIB1 for a local SCA library.

To initialize a new SCA library you specify the CREATE LIBRARY command. This command has the following form:

CREATE LIBRARY [/qualifier...] directory-spec[,...]

For example:

$ SCA CREATE LIBRARY [.LIB1]

This command initializes and activates library LIB1.

C.2.2.2. Generating the Data Analysis Files

SCA uses detailed source data that is generated by the PL/I compiler. When you specify the /ANALYSIS_DATA qualifier on the PLI command, the generated data is output to a file with the default type .ANA. For example:

$ PLI/LIST/DIAGNOSTICS/ANALYSIS_DATA PG1,PG2,PG3

This command line compiles the input files PG1.PLI, PG2.PLI, and PG3.PLI, and generates four corresponding output files for each input file with the file types OBJ, LIS, DIA, and ANA. SCA puts these files in your current default directory unless you specify otherwise.

C.2.2.3. Loading Data Analysis Files into a Local Library

Before you can examine the information in the compiler-generated source analysis (.ANA) files, you must load the files into an SCA library using the LOAD command. The LOAD command has the following form:

LOAD [/qualifier...] file-spec[,...]

For example:

LSE> LOAD PG1,PG2,PG3

This command loads your library with the modules contained in the data analysis files PG1, PG2, and PG3.

C.2.2.4. Selecting an SCA Library

To select an existing SCA library to use with your current SCA session, use the SET LIBRARY command. The command has the following form:

SET LIBRARY [/qualifier...] directory-spec[,...]

A message appears in the message buffer at the bottom of your screen, indicating whether your SCA library selection succeeded.

C.2.3. Using SCA for Cross-Referencing

Once you have set up your SCA environment, you can ask for symbol or file information by using the SCA command FIND. The FIND command has the following form:

FIND [/qualifier...] [name-expression[,...]]
nohead
name-expression

The name-expression can be explicit (for example, ABC) or can contain wildcards (for example, ABC* or AB%).

For example:

LSE> FIND ABC,XY%

You can query an SCA library for the following:

NameA series of characters that uniquely identifies a symbol or a file.
ItemAn appearance of a symbol (such as a variable, constant, label, or procedure) or a file.
OccurrenceThe use of a symbol or a file.

To limit the information resulting from a query, you can use qualifiers on the FIND command, such as the /DECLARATIONS and /REFERENCE qualifiers. For example:

LSE> FIND/REFERENCES=CALL BUILD_TABLE

This command causes SCA to report only references in the source code where the routine BUILD_TABLE is called.

When you first issue a FIND command within LSE, you initiate a query session. Within this context, the integration of LSE and SCA provides the following commands that can be used only within LSE:

{ NEXT     }
{ PREVIOUS }
{ NAME       }
{ ITEM       }
{ OCCURRENCE }
{ QUERY      }
{ STEP       }
Closely associated commands that let you step through one or more query buffer displays within LSE.
GOTO SOURCEDisplays the source corresponding to the current query item.
GOTO DECLARATIONPositions the cursor on a symbol declaration in one window, and displays the source code that contains the symbol declaration in another window.