Language Constructs

CobolScript® Language Constructs

In CobolScript, there are several categories of constructs which form the foundation of the language. This chapter defines these constructs and their specific CobolScript syntax. Since CobolScript language constructs are not so different from the elementary components that comprise most other computer languages, you may opt to focus your attention only on those sections in this chapter that deal with material unfamiliar to you. Each CobolScript construct is unique in at least a minor fashion, however, so refer back to the appropriate section here if you are having difficulties with a particular construct.

With the exception of delimited string literals, all CobolScript alphanumeric syntax is case insensitive, meaning uppercase letters, lowercase letters, and any combination of these will work for any particular command, variable, or reserved word. This flexibility requires that you be cautious, however, when defining your variables; see the Variables section for more information.

The CobolScript language constructs are divided into the following categories:

· Literals and Literal Keywords

· Variables

· Data and Copybook Files

· Expressions and Conditions

· Commands

· Reserved Words

· Statements

· Sentences

· Comments

We explain each of these categories individually in the following sections.

Literals and Literal Keywords

Literals are any numbers or character strings which are meant to be taken literally by your program. Literals are perhaps best defined by what they aren’t: A literal is not a variable, which has values substituted in for the variable name at the time the program is run, nor is a literal necessarily an expression, which is mathematically evaluated to arrive at a resulting value (although literals can comprise expressions). As you will see from the examples below, literals can only appear in places within statements or variable definitions where they are used as a source for information, and never as a target, since a literal cannot change its value.

Numeric Literals

If a literal is numeric, and you want that numeric literal to be treated as a number by your program, it should not be enclosed in any offsetting quotes or string delimiters. Also, a numeric literal should not include any special formatting characters like commas or dollar signs; the only special characters allowed within a numeric literal are the negative sign ( - ) and the decimal point, indicated with a standard period ( . ). To use a numeric literal in your program, just insert the number, including any negative sign and decimal point, into your statement or VALUE clause in the appropriate position.

If you use a numeric literal in a VALUE clause, the variable being defined must also be numeric. Here are some examples of numeric literals in VALUE clauses in variable definitions:

1 variable_1 PIC $9,999.99 VALUE 2323.41.

1 variable_2 PIC S99,999.999 VALUE –32000.

If you have questions about the PIC clauses in the above variable definitions, picture clauses are explained completely in Appendix E, CobolScript Picture Clauses.

Here are some examples of numeric literals in code statements:

MOVE 5 TO variable_1.

SUBTRACT 6.23 FROM number_var_1.

MULTIPLY 2 BY –6 GIVING result_var.

COMPUTE result_var = -2.25.

Alphanumeric Literals

Alphanumeric literals, also known as strings, are any delimited character or string of characters which is to be taken literally by your program. Any character other than the string delimiting character, which is normally the accent symbol, can appear within a delimited string. See the subsection below for more information on string delimiters.

If you use an alphanumeric literal in a VALUE clause, the variable being defined must be of alphanumeric (PIC X) type. Here are some examples of alphanumeric literals in VALUE clauses in variable definitions:

1 variable_2 PIC XXX VALUE `123`.

1 FILLER PIC X(n) VALUE `<BODY><HR><BR>”#1” Web Page</BODY>`.

If you want further explanation of the types of PIC clauses used in the above variable definitions, refer to Appendix E, CobolScript Picture Clauses.

Here are some examples of alphanumeric literals used in procedure statements:

MOVE `Y` TO variable_1.

IF condition_val = `E1qwT`

CONTINUE

END-IF.

DISPLAY `Hello, ‘Ray’. `.

The CobolScript String Delimiter

The string delimiter in any language is the character that is used to signal the beginning and the end of alphanumeric literals. In most computer languages, the string delimiter is either the single or double quote, so strings enclosed in their delimiters are commonly referred to as being quoted. In CobolScript, however, the default string delimiter is the Gravè accent, or just plain accent ( ` ). Since CobolScript also has command line options to permit the use of the single or double quote as the string delimiter (see the section titled Running CobolScript from the Command Line in Chapter 2, Getting Started with CobolScript for more details), we usually refer to alphanumeric literals simply as being delimited to avoid confusion.

The accent key is the key located in the upper left corner of North American keyboards, below the Esc key. Normally, both the tilde ( ~ ) and the accent ( ` ) are on the same key. We selected the accent as the default string delimiter for CobolScript because HTML, which must be displayed from CobolScript web applications, requires the frequent use of double and single quotes; using a different character for the CobolScript string delimiter simplifies the creation of these strings. The alphanumeric literal in the following MOVE statement is standard HTML and illustrates this point well:

MOVE `<A HREF=“/test.htm”>Test Page</A>` TO url_var.

If you still prefer to use quotes, however, you can. Just create your program using either single or double quotes as the string delimiters, and run the program using the appropriate command line option. See the previously mentioned section in Chapter 2 for syntax information.

If you’re an experienced C programmer, you may be curious about whether the backslash ( \ ) has special meaning inside a CobolScript string. It doesn’t. This is primarily because CobolScript strings must contain any client-side scripts that you choose to embed in your CobolScript-generated HTML. These scripting languages each may attribute special meaning to certain characters inside a string, and these special characters should not interfere with the original CobolScript string. Simply put, there is no ‘escape’ character, backslash or other, in CobolScript that will cause the character following it to be interpreted literally. Because of this, there is no direct way to display the current delimiter symbol from within a delimited string – a special keyword, not enclosed in delimiters, must be used instead.

To display a literal of the accent symbol from within a CobolScript program that uses the accent as the string delimiter, you must use the ACCENT keyword, as in:

DISPLAY ACCENT.

DISPLAY `The accent symbol: ( ` & ACCENT & ` ).`

The same rule applies if you are using double or single quotes as the string delimiter. When the double quote is your string delimiter, use the DOUBLEQUOTE keyword to display the symbol, as in:

DISPLAY DOUBLEQUOTE.

and when using the single quote as the string delimiter, use the SINGLEQUOTE keyword, as in:

DISPLAY SINGLEQUOTE.

Literal Keywords

Below is the complete list of literal keywords. Like ACCENT, DOUBLEQUOTE, and SINGLEQUOTE, each of these keywords represents a specific ASCII character constant.

Keyword

Symbol represented by keyword

ACCENT

`

CARRIGERETURN

{equivalent of ASCII character number 13}

CRLF

{equivalent of ASCII character number 13 + ASCII character 10; uses two bytes}

DOUBLEQUOTE

"

LINEFEED

{equivalent of ASCII character number 10}

SINGLEQUOTE

'

SPACE

{all blanks}

SPACES

{all blanks}

TAB

{equivalent of ASCII character number 9}

ZERO

0

ZEROS

0

Variables

Variables are information holders. In CobolScript, variables come in five basic forms, each of which has its own characteristics and utility. These five forms are:

· Elementary data items, which can be either numeric or alphanumeric;

· Group-level data items;

· FILLER variables, which are really a special category of elementary data item;

· REPLICA variables;

· OCCURS clause variables.

No matter what the form, a variable must first be defined in a program, and then, as the term variable implies, the variable’s contents can be assigned and reassigned throughout the body of a program. In CobolScript, these value assignments are done with VALUE clauses and assignment statements. VALUE clauses are optional components of elementary data item variable definitions that establish an initial value for a variable; assignment statements are any procedure statements that modify a variable’s contents.

A variable definition must follow certain rules of syntax, which are described below for each of the variable forms. A variable definition may be placed anywhere within a CobolScript program, meaning that variable definitions are not restricted to the Data Division as they are in COBOL. However, you should not define the same variable more than once within a program.

In CobolScript, variable names are not case sensitive, so WS-VAR, ws-var, and Ws-Var will all be treated internally as the same variable. For this reason, only one of these names should be defined in a program. Similarly, two variables that have the same alphanumeric name and differ only by underscore and dash separators within the variable name, such as WS-VAR and WS_VAR, will be treated interchangeably by certain CobolScript commands and should not both be defined in a single program.

The Elementary Data Item

An elementary data item (also referred to as a ‘subvariable’ or just ‘elementary item’) is any basic numeric or alphanumeric variable. An elementary data item cannot have subvariable components. The syntax of a normal elementary data item variable definition is:

<level-number> <variable-name> PIC <picture-clause> [VALUE <value-literal>].

The level-number is a one- or two-digit number from 1 to 99. Think of the level number as representing the outline position of a variable; the lower the level number, the higher the variable’s rank in the outline, with 1 being the highest level. So long as you have defined at least one variable with a level of 1 in your program, the variables with level numbers greater than 1 will all be subvariables. This is best illustrated with an example:

1 text_input PIC X(40).

1 group_variable.

2 components.

3 component_1 PIC X(12).

3 component_2 PIC $,999.99.

2 val_1 PIC 99.

1 input_1 PIC X(25).

In the variable definitions above, text_input is both an elementary data item, because it doesn’t have any subvariables beneath it, and is a level 1 variable. The variable group-variable is a group-level data item (explained in the subsequent section), which has two subvariables, components and val_1. The variable components is a group item itself, and has two subvariables, each of which are elementary items. The variable val_1 is an elementary data item, as is input_1.

The variable-name of an elementary data item is the name that will be used throughout the program to reference this particular variable.

The elementary data item variable’s type, format, and length are all determined by the value of the picture-clause that immediately follows the PIC keyword. In CobolScript, all elementary item variables are assigned a fixed number of bytes according to the size specified in the picture clause, so you must allocate sufficient space for your variables when you create their picture clauses; otherwise, the variable values will be truncated and information will be lost. A picture clause can be of two basic types: numeric (PIC 9 format) or alphanumeric (PIC X format). The various picture clause formats, and their meaning, are explained fully in Appendix E, CobolScript Picture Clauses.

If you want to initialize the elementary data item variable to a value at the time you define it, you can include the VALUE keyword and follow it with a value-literal to assign to the variable. The value literal must be of a type that matches the picture type of the variable; in other words, a variable with a numeric picture clause must be assigned a numeric value literal, and a variable with an alphanumeric picture clause must be assigned an alphanumeric literal. See the preceding section of this chapter for more information on literals.

These are some example elementary item variable definitions:

1 string_variable PIC X(10) VALUE `abcdefghij`.

1 input_var PIC XX.

1 num_variable PIC $,999.99 VALUE 679.

The Group-Level Data Item

A group-level data item (also referred to as a ‘gldi’ or just ‘group item’) is a hierarchical parent variable that is made up of other variables known as subvariables or component variables. Group items are similar to record variables or data structures in other programming languages; they’re useful because they enable you to reference and transfer whole groups of variables by citing a single, succinct variable name. In CobolScript, group items are also used to define file records. See the Data and Copybook Files section of this chapter for more information on file records.

The syntax of a group-level data item variable definition is:

<level-number> <variable-name>.

<subvariable-definition>.

.

.

.

As in elementary items, the level-number of a gldi indicates the variable’s position in the hierarchy; see the definition of level number for elementary data items for more information.

The variable-name of a group item is the name assigned to the variable, just as in elementary data items.

In group items, no PIC or VALUE clauses are allowed. This is because a gldi’s structure is defined solely by its subvariable-definitions. A group-level data item’s subvariables can be group items themselves, making possible multiple levels of grouping, or the subvariables can be elementary data item variables.

Below is a standard group-level data item variable definition. In this example, group_variable is the group item, and is composed of two elementary items:

1 group_variable.

5 component_1 PIC XXX VALUE `mS1`.

5 component_2 PIC $,999.99.

The FILLER Variable

The FILLER variable is a special type of elementary data item; it should only be used as a subvariable to a group item, because it is always given the name FILLER, and cannot be directly referenced. The syntax of a FILLER variable definition is:

<level-number> FILLER PIC <picture-clause> VALUE <value-literal>.

The level-number and picture-clause are the same as those for a normal elementary data item, except FILLER variables should never be level 1 variables (because they must be subvariables).

A VALUE clause should almost always be specified for a FILLER variable, since FILLERs generally act as constants in a program. In cases where the FILLER variable is just acting as a placeholder, a VALUE clause may not be necessary.

Once defined, FILLER variables can only be referenced and modified indirectly, through references to their parent variable. They should be used in cases where there is no need for a direct reference, such as when a component of a group item remains static throughout the program. In the example below, a FILLER variable is one of three subvariables that comprise the group item variable group_variable:

1 group_variable.

5 component_1 PIC XXX VALUE `mS1`.

5 FILLER PIC X(n) VALUE ` has a dollar value of `.

5 component_2 PIC $,999.99.

Using PIC X(n) with FILLER variables

The special picture clause PIC X(n) can (and generally should) be used with any alphanumeric FILLER variable for which you specify a VALUE clause. PIC X(n) automatically assigns a length to the FILLER variable based on the length of the VALUE clause, so that you don’t have to calculate the variable length yourself when creating the picture clause. For example, in group_variable above, the FILLER variable is automatically assigned a length of 23 characters because the value clause is 23 characters long.

For more information on PIC X(n), see Appendix E, CobolScript Picture Clauses.

Implied PIC X(n) FILLER variables

FILLER variables using PIC X(n) can also be defined with a shorthand notation that eliminates the FILLER keyword, picture clause, and VALUE keyword. This is best illustrated with an example:

1 group_variable.

5 `Enter your name here: `.

In group_variable above, there is a single FILLER variable, with a value of `Enter your name here: `. The above gldi is the exact equivalent of the following:

1 group_variable.

5 FILLER PIC X(n) VALUE `Enter your name here: `.

This shorthand may only be used when the FILLER variable’s value is an alphanumeric that is set off by delimiters.

REPLICA Variables

A REPLICA variable is a special type of elementary item variable that has the same name and level number as a previously defined elementary item variable, and refers to the same physical variable in memory as the originally defined variable. REPLICA variables are useful when defining multiple group item variables that all require the same elementary item component; using a replica in these cases avoids the task of moving values back and forth between these elementary items.

REPLICA variables are defined with a level number, variable name, and the REPLICA keyword. PIC and VALUE clauses are not permitted in a REPLICA variable because they are not meaningful; this information is defined by the original variable (also called the replica parent), whose definition always precedes the REPLICA variable definition. Similarly, no VALUE clauses are permitted in replicas, and both the replica and the replica parent must be elementary item variables with the same level number. Here’s the basic REPLICA variable syntax:

<level-number> variable_name REPLICA.

And here’s a simple example of REPLICA usage:

1 group_variable_1.

5 component_1 PIC XXX VALUE `mS1`.

5 ` has a dollar value of `.

5 component_2 PIC $,999.99 value 125.99.

1 group_variable_2.

5 `The value in the component_1 replica variable is: `.

5 component_1 REPLICA.

DISPLAY group_variable_1.

DISPLAY group_variable_2.

MOVE `q72` TO component_1.

DISPLAY group_variable_1.

DISPLAY group_variable_2.

In the above example, the normal, full definition of component_1 occurs in the group_variable_1 group item definition; the second component_1, defined in group_variable_2, is a replica of the original component_1. Thus, component_1 inside group_variable_1 is the replica parent, and component_1 inside group_variable_2 is the replica. The output of the code above is:

mS1 has a dollar value of $125.99

The value in the component_1 replica variable is: mS1

q72 has a dollar value of $125.99

The value in the component_1 replica variable is: q72

The OCCURS Clause Variable

In CobolScript, the OCCURS clause variable is a special type of variable, either elementary or group item, that defines arrays of each of its subvariables. The OCCURS clause syntax excels over other types of array definition syntax when defining record arrays; this is because arrays of records fit naturally within the syntax of an OCCURS clause group item definition.

The syntax of an OCCURS clause group item variable definition is:

<level-number> <variable-name> OCCURS <n> TIMES.

<elementary-item-definition> or <group-item-definition>.

.

.

.

The syntax of an OCCURS clause elementary item variable definition is:

<level-number> <variable-name> OCCURS <n> TIMES PIC <picture-clause>

VALUE <value-literal>.

An OCCURS clause variable is defined the same way as its underlying form (elementary or group item), except for the OCCURS clause. This clause is initiated by the OCCURS keyword; in the case of the OCCURS group item, it indicates that the subvariables that comprise this group are recurring. In the case of the OCCURS elementary item, it indicates that this particular variable is recurring. In either case, the number of times the OCCURS variable(s) recur is indicated by a positive (strictly greater than zero) integer value n, which can either be a numeric literal or a numeric variable.

When referencing an OCCURS variable, you must use an index to indicate which of the recurring variables you mean. The index must be an integer with a value from 1 to n. So, if the OCCURS variable is defined using either of these forms:

1 occurs_variable OCCURS 10 TIMES.

5 component_1 PIC 99.

5 component_2.

10 component_2_1 PIC XX.

10 component_2_2 PIC 99.

or,

1 component_1 OCCURS 10 TIMES PIC 99.

Then, component_1 is a recurring variable (along with component_2 and its subvariables in the group item example), and its index can be any number or variable with an integer value from 1 to 10, inclusive. So, to reference the third OCCURS variable of component_1 in a statement, we would use the syntax:

component_1(3)

or, alternatively:

component_1(integer_variable)

where integer_variable is an integer numeric variable that is equal to 3 at the time it is referenced. We can also use the syntax:

component_1(expression)

where expression is any valid mathematical expression that evaluates to a positive integer, such as the following expression, which again assumes a value of 3 for integer_variable:

component_1(((2^2)+integer_variable)%3)

The group item component_2 and its two subvariables, component_2_1 and component_2_2, can be referenced the same way as component_1; thus, all of the following forms are permissible:

component_2(3)

component_2_1(3)

component_2_1(integer_variable)

component_2_2( ((2^2)+integer_variable)%3 )

Specifying a VALUE clause for an elementary item that recurs initializes all OCCURS elements to the value-literal. For example, in the gldi below, component_1(1) through component_1(5) will have initial values of 05, and component_2_1(1) through component_2_1(5) will have initial values of `me`. Specifying a value clause for an OCCURS elementary data item has the same net effect, as in the second OCCURS clause definition below:

1 occurs_variable OCCURS 10 TIMES.

5 component_1 PIC 99 VALUE 5.

5 component_2.

10 component_2_1 PIC XX VALUE `me`.

10 component_2_2 PIC 99.

or,

1 component_1 OCCURS 10 TIMES PIC 99 VALUE 5.

Þ Ü

Note that CobolScript Standard Edition only permits single-level OCCURS clauses. In other words, two-dimensional and higher arrays are not supported by the Standard Edition. This means that an OCCURS clause gldi that has any OCCURS clause subvariables is not permitted in the Standard Edition. See below for an explanation of multidimensional array usage in CobolScript Professional Edition.

Multidimensional Arrays Using CobolScript Professional

If you are programming with CobolScript Professional Edition, you can define OCCURS clause variables that contain other OCCURS clause subvariables. This type of variable is also known as a multidimensional array because its individual elements comprise an array that has more than one index argument, or dimension. Let’s take a look at a basic multidimensional array definition using CobolScript Professional:

1 day_of_week OCCURS 7 TIMES.

5 hour_of_day OCCURS 24 TIMES.

10 fahr_temp PIC ---9 VALUE –300.

10 barom_pressure PIC 99.99 VALUE 0.

In the definition above, 168 total instances of the fahr_temp and barom_pressure variables are created and initialized. Each elemental variable corresponds to a temperature and barometric pressure reading for a specific hour of the day on a specific day of the week. The value in a specific element is referenced using a two-argument array reference with the dimensions separated by commas, as in the following statement:

DISPLAY fahr_temp(1, 13).

This statement corresponds to displaying the temperature value for 1:00 PM on Sunday, assuming Sunday is treated as the first day of the week.

The same range of argument syntax is permissible in multidimensional arrays as in one-dimensional arrays, so that the following are all valid references, assuming var_idx1 and var_idx2 are both properly defined:

fahr_temp(7, var_idx2)

hour_of_day(6+1, var_idx2)

barom_pressure(var_idx1, var_idx2)

fahr_temp(var_idx1+1, var_idx2-1)

Additional array dimensions are declared using additional nested OCCURS clauses:

1 a OCCURS occurs_num TIMES.

5 b PIC X VALUE `b`.

5 c.

10 d PIC 9 VALUE 1.

10 e PIC XX VALUE `ee`.

5 f OCCURS 2 TIMES PIC XX VALUE `ff`.

5 g OCCURS 3 TIMES.

10 h PIC XX VALUE `hh`.

10 i OCCURS 4 TIMES.

20 j PIC X VALUE `j`.

20 k PIC X VALUE `k`.

20 l OCCURS 2 TIMES PIC XX VALUE `ll`.

20 m OCCURS 2 TIMES.

30 n PIC X VALUE `n`.

Referencing syntax for variables with more than two dimensions is just an extension of the two dimension case, with additional commas separating the additional array dimensions:

MOVE `p` TO n(1,2,3,1).

DISPLAY `n(1,2,3,1) after move = ` & n(1, 1+1, occurs_num-1, 1).

There is no technical limit to the number of array dimensions that can be used in CobolScript Professional; however, the limit on the number of variables that may be declared in a single program creates a practical upper bound on the number of array dimensions. At any rate, careful programming will rarely warrant the use of more than three dimensions. Although exceptions may apply in certain mathematical programming cases, and in cases involving intentional denormalizing of data constructs, very large dimension arrays should generally be avoided in order to keep your programs comprehensible.

Data and Copybook Files

Like variables, data and copybook files hold information that can be used in a CobolScript program. Of course, files are external entities, and as such are independent of the program and are stored separately on disk. Files also have a total capacity that is generally only limited by your disk space, rather than being controlled by program limitations (although there are limits on individual record sizes in data files).

Data Files

A CobolScript data file is just a special type of ASCII text file that contains data records. Records are a long string of data values, or fields. Each record is terminated with a linefeed.

Records have a specific layout, so that each record has the same number of fields, and each specific field within a record shares formatting characteristics with the field in the same position in the other records in the data file. For example, if the fifth field in a record is a numeric with the value 000311, then the fifth fields in the other records in the file will also be six byte numerics. An example delimited data file with a delimiter of ‘|’ and several records in it might look like this:

12051999|al@bbnb.net|Reynolds|Al|10 Meisenheimer Drive|Womack|MI|49332|

12051999|smith@ffdfff.com|Smith|Roy|511 Critical Pass|Boca Raton|FL|33983|

07061999|misterm@wyyyee.edu|M|Mr|302489|Rejkyavik||54663-211|

Data files can be either token-delimited or fixed format. In a delimited file, a single byte delimiter character of your choice is used to separate individual fields from one another, while in a fixed format file, a fixed number of bytes is assigned to each field, so there is no need for a delimiter.

To enable a particular data file to be processed by a program, you must first describe the file. This is done with the FD (File Description) statement. The FD statement has the following syntax:

FD <filename> RECORD IS <length> BYTES.

The filename argument is the alphanumeric literal or variable that indicates the name and path of the data file. It’s best to keep your data files in the same directory as the CobolScript engine if you frequently move your code between machines with Windows file systems and ones with Unix file systems. This is because the directory symbol is different for these file systems ( ‘\’ versus ‘/’ ) and your code will then require that you change this symbol every time you switch between the two platforms.

It’s important that you specify the correct length argument, since this tells CobolScript where to end the record. A record is terminated with a carriage return-linefeed combination for Windows machines, and just a linefeed for Unix platforms; these terminating characters, however, are not included in the length argument, so that the same file can be described by the same FD statement, regardless of platform.

The length argument can be either a numeric variable or a numeric literal. In either case, it should have a positive (strictly greater than zero) integer value.

The length of a fixed width record is always equal to the sum of the lengths of the fields that comprise it; calculating the length of a delimited record is a bit more involved, but not difficult. The minimum length that you must use for a CobolScript delimited record, provided your delimiter requires one byte of storage, is always equal to the formula:

Sum of lengths of individual record fields + (number of fields in record)

In delimited files, CobolScript right-pads the records with spaces, so that each record is still the exact number of bytes specified in the length argument. This fact is relevant if you process a delimited data file created with another application: Although reading and appending to that file will work fine in CobolScript, updating existing records will not, since each record has a different size. For more on this topic, see Chapter 4, File Processing and I/O.

Once you’ve described a file, you must define a record variable with subvariables that represent each component field in the record. In CobolScript, you define record variables like any other group-level data item. You can define file record variables anywhere within a program, so long as the record definition appears prior to any file processing statements that make use of the record such as READ and WRITE. It’s important to not leave any fields out of your record definition, and to define them with the proper format and length, especially if they are fixed-length format. An incorrect or incomplete record definition will cause your record subvariables to be populated with the wrong fields, and your data will be messed up, to say the least.

A FD statement for a fixed-width record, followed by the record definition for the file, might look like this:

1 filename_var PIC X(n) VALUE `file.dat`.

1 bytes_var PIC 999 VALUE 100.

FD filename_var RECORD IS bytes_var BYTES.

1 record_var.

5 rv_field_1 PIC X(50).

5 rv_field_2 PIC X(10).

5 rv_field_3 PIC X(40).

Data file manipulation is discussed in detail in Chapter 4, File Processing and I/O.

Copybook Files

Copybook files are external code files that can be loaded into a CobolScript program via a single statement. The contents of the copybook file are then treated as if they were part of the program. Copybooks are most commonly used to store variable definitions, especially record variable definitions, since the same data file is often used by multiple programs. Using a copybook to store a record variable definition reduces programming effort and eliminates the possibility of discrepancies in the definition across programs. Copybooks also work well for storing group-level data items that contain HTML that you want to replicate across your CobolScript CGI programs.

Copybook files are included in a program with the COPY or INCLUDE statement. These statements are special in that they can be located anywhere within a program. This allows the code in a copybook to be substituted into the program at any location, wherever the COPY or INCLUDE statement is placed.

In the following example, an INCLUDE statement is inserted into a program to include the file testvars.cpy, which is located in the parent directory of the CobolScript engine’s directory, on a Windows machine:

FD test.dat RECORD IS 17 BYTES.

INCLUDE `..\testvars.cpy`.

Although it’s possible to include a path in the INCLUDE statement like this example does, it’s inadvisable if you frequently move your code between machines with Windows file systems and ones with Unix file systems. The directory symbol is different for these file systems ( ‘\’ versus ‘/’ ) and your code will then require that you change this symbol every time you switch between the two platforms.

When we examine the contents of testvars.cpy, we see that this file contains a few simple variable definitions that can then be referenced by the calling program:

1 content_length PIC 9(5).

1 eof PIC 9.

1 occurs_var OCCURS 5 TIMES.

5 occurs_var_1 PIC 999.

Assuming that it follows the INCLUDE statement in our original program, the following MOVE is legitimate because the definition for eof is now included in the program’s variables:

MOVE 1 TO eof.

For more information on the COPY and INCLUDE statements, see their respective entries in Appendix A, Language Reference.

Expressions and Conditions

Expressions and conditions can appear in multiple locations in a CobolScript program. Positional string reference and array arguments can be expressions; CobolScript COMPUTE statements, which assign a value to a single variable, permit the use of mathematical expressions in the assigning value; the CobolScript DISPLAY and DISPLAYLF statements allow expressions as arguments, and the expressions are then evaluated before the result is displayed; and the IF statement and all variations of the PERFORM .. UNTIL statements evaluate conditions. Below are the CobolScript rules of syntax and evaluation for expressions and conditions. See Appendix A, Language Reference, for the exact syntax of COMPUTE, DISPLAY, IF, and PERFORM.

Expressions

In CobolScript, an expression is any mathematical formula that has a single-value solution. An expression can consist of any other expressions, numeric literals, variables, functions, or assignment statements using mathematical operators. All variables used in an expression must be properly defined with a numeric picture clause prior to the expression’s statement, because the variables’ values will be substituted in prior to evaluating the expression. Functions, which are mathematical operations such as sine, cosine, present values, and the natural log, are described fully in Appendix B, Function Reference.

CobolScript permitted operators

Symbol

Meaning

Example

Example result

+

Add

5 + 2

7

-

Unary negative sign

-4

-4

-

Subtract

5 - 2

3

*

Multiply

2 * 2

4

/

Divide

7 / 7

1

^

Raise to a power

2^4

16

\

Express in scientific notation

2\2

2 * 10^2 = 200

%

Modulus, or mod

10%4

2

=

Equals

1 = 3

0

Symbol

Meaning

Example

Example result

NOT =

Not equal to

1 NOT = 3

1

>

Greater than sign

18 > 1

1

1 > 18

0

1 > 1

0

<

Less than sign

18 < 1

0

1 < 18

1

1 < 1

0

>=

Greater than or equal to

18 >= 1

1

1 >= 18

0

1 >= 1

1

<=

Less than or equal to

18 <= 1

0

1 <= 18

1

1 <= 1

1

AND

Logical AND

2 AND 0

0

5 AND 3

1

0 AND 0

0

OR

Logical OR

1 OR 0

1

0 OR 0

0

3 OR 7

1

XOR

Logical exclusive OR

1 XOR 0

1

0 XOR 0

0

3 XOR 7

0

NOT

Logical NOT

NOT 1

0

NOT 0

1

NOT 9

0

Order of operations

Operations are not necessarily performed from left to right in an expression; instead, they are evaluated in an order that depends on the relative rank of the operation, so long as no parentheses are used. The order in which operations are performed in an expression, from first performed to last performed, is:

Order

Operation(s)

1

- (unary negative sign)

2

^ (power)

3

\ (scientific notation)

4

% (mod)

5

/, * (divide, multiply)

6

+, - (add, subtract)

7

>, <, >=, <= (greater than, less than, greater than or equals,

less than or equals)

8

=, NOT = (equals, not equals)

9

NOT (logical not)

10

AND (logical and)

11

XOR (logical exclusive or)

12

OR (logical or)

Rather than memorizing the order of operations, we recommend that you always use parentheses in your expressions. This will ensure that operations are performed in the order that you wish, and will avoid confusion for anyone else who reads or maintains your code.

Example expressions

Expression

Meaning

5

The number 5.

X

The value of the variable X.

X + Y

or

X+Y

The value of the variable X plus

the value of the variable Y.

X+Y + Z

The value of the variable X plus

the value of the variable Y plus

the value of the variable Z.

(((X+Y)/Z)%3) ^1.86 - SQRT(X)

The variable X plus the variable Y,

all divided by Z,

all mod’ed by 3,

all raised to the power of 1.86,

all minus the square root of the variable X (SQRT is a function).

3\2

3 multiplied by 10 to the power of 2,

equivalent to 3 * (10^2).

ROUNDED(X*Y*Z-Q/5/4^0.34)

The variable X multiplied by the variable Y multiplied by the variable Z,

all minus the value of:

The variable Q divided by 5 divided by the value

of:

4 to the power of 0.34.

The result is passed as an argument to the ROUNDED function, and is rounded to the nearest integer.

X + SIN(PI(0)/2)

The variable X plus the sine of p/2 radians (SIN and PI are both mathematical functions).

Expression construction rules

· Any level of nesting using parentheses is permitted.

· There is a finite length of expression permitted; generally speaking, keep your expressions small enough to be easily understandable and you will avoid this limit. If you do encounter the limit, divide your expression up into multiple assignment statements.

· There is a finite length of individual token (argument not separated by spaces) permitted. Insert spaces between expression components if you encounter this limit.

· Spaces are not required between expression components if a symbol (non-word) mathematical operator is separating the components; however, you should generally use spaces when performing subtraction operations on variables with dashes or underscores in their names. To illustrate, the expression “VAR-1 minus six” can be written two different ways, but the first method is preferred:

Þ (VAR-1 - 6)

Þ (VAR-1-6)

This is because if both VAR-1 and VAR-1-6 are defined variables, the meaning of the second example becomes unclear to anyone reading the code. In CobolScript, longer variable names are always substituted prior to shorter names, so that the second case above would always evaluate to the variable VAR-1-6. Even if both variables were defined, the first example would still evaluate to the quantity (VAR-1) minus 6, which is the desired result in this case.

· Alphanumeric variables or literals in expressions that are within COMPUTE statements are not allowed, even if the argument is in the context of a truth test. Thus, the statement:

COMPUTE total = (alnum_var = `Y`).

is illegal because it contains an alphanumeric variable (alnum_var) and an alphanumeric literal (`Y`), even though the expression would evaluate to a numeric result. To set values based on a test of alphanumerics, embed the assignment within an IF condition.

Conditions

Conditions are expression-like logic tests in IF and PERFORM .. UNTIL statements that evaluate to a numeric result. In CobolScript, conditions are less restrictive than expressions are, because conditions allow alphanumeric variables or literals to be included in tests. Like regular expressions, though, conditions must still evaluate to a single-value result. This numeric result determines whether the condition has evaluated to TRUE or FALSE; a result of exactly zero (0) is FALSE, while any other result is considered to be TRUE. Thus, the conditional statement below will evaluate to TRUE because the value of the condition is -40:

IF (4 + 6) *(-4) THEN

General condition rules

There are some general rules that govern conditions , no matter what form they take:

· As mentioned above, a condition will evaluate to FALSE only if its value is zero. Any other numeric result is TRUE.

· A condition must evaluate to a numeric result. Alphanumeric results are invalid.

· Any level of compound condition nesting using parentheses is permitted.

· There is a finite length of condition; generally speaking, keep your condition’s component expressions small enough to be easily understandable and you will avoid this limit. If you do encounter the limit, assign the value of one or some of your expressions to a variable prior to evaluating the condition. Then, your condition can include the variable in place of the lengthy expression. If you cannot do this because you are evaluating alphanumerics, break your condition up into multiple conditions instead, and nest your IF statements.

· There is a finite length of individual token (component of condition which is not separated by spaces) permitted. Insert spaces between condition components if you encounter this limit.

· There is no support for implied subjects or implied operators in CobolScript conditions. You must completely write out your conditions. (If you’re not familiar with these terms, don’t worry. They are COBOL constructs that don’t really have an equivalent in other computer languages.)

Condition syntax

CobolScript conditions come in two types: General logic tests, or Type I conditions, and tests of the type of value contained in an alphanumeric variable or literal, which are Type II conditions. This is the allowed syntax for both types of conditions, and rules specific to each condition type:

Type I conditions:

<Expression>

NOT <Expression>

<Expression> AND <Expression>

<Expression> OR <Expression>

<Expression> XOR <Expression>

<Expression> [IS] [NOT] = <Expression>

<Expression> [IS] [NOT] EQUAL [TO] <Expression>

<Expression> [IS] [NOT] > <Expression>

<Expression> [IS] [NOT] GREATER [THAN] <Expression>

<Expression> [IS] [NOT] < <Expression>

<Expression> [IS] [NOT] LESS [THAN] <Expression>

<Expression> [IS] [NOT] >= <Expression>

<Expression> [IS] [NOT] <= <Expression>

Rules specific to Type I conditions:

· All Type I conditions may have numeric literals, numeric variables, alphanumeric variables, or string literals in their component expressions.

· Alphanumeric comparisons of letters assigns a greater value to letters that come later in the English alphabet. Therefore:

`Z` > `A` evaluates to TRUE;

`A` = ` ` evaluates to FALSE.

· Comparison of alphanumeric values to numeric values is permitted, but will default to an alphanumeric to alphanumeric comparison. Thus, the following condition and others like it will evaluate to TRUE:

`9` = 9

Type II conditions:

<Alphanumeric-val> [IS] [NOT] NUMERIC

<Alphanumeric-val> [IS] [NOT] ALPHABETIC

Rules specific to Type II conditions:

· Type II conditions are tests to determine whether the characters contained within an alphanumeric variable or literal are NUMERIC or ALPHABETIC.

· A NUMERIC value is any valid number, including any negative sign and decimal point. NUMERIC values may not include spaces; a value such as `5 ` will not be considered numeric.

· An ALPHABETIC value is any value that falls within the ranges A-Z and a-z, or is a space.

· All Type II conditions may operate only on alphanumeric variables or string literals.

Commands

A command is the reserved word or words that form the foundation of a single procedural statement. In this section, we divide the commands into categories that can help give you a basic idea of what CobolScript commands can be used for. Refer to Appendix A, Language Reference, for detailed syntax rules governing each command as it is used in a complete statement.

General Program Control Commands


This group of commands is used to direct program flow, populate variables, and include code modules from external files in a program. Check the Language Reference for a command to determine its CobolScript syntax and its full capability.

ACCEPT

DISPLAY

INCLUDE

PERFORM..VARYING

ADD

DISPLAYLF

INITIALIZE

STOP RUN

COMPUTE

DIVIDE

MOVE

SUBTRACT

CONTINUE

GOBACK

MULTIPLY

COPY

IF

PERFORM

File Processing Commands


These commands execute file input and output operations on normal text files. Files in fixed width and delimited formats can be read into normal group-level data items, and normal group-level data items can be populated and then written to delimited or fixed-width files. Note that these commands will only operate on ASCII files; no proprietary data formats are supported in CobolScript.

CLOSE

POSITION

REWRITE

OPEN

READ

WRITE


LinkMakerTM Database Interactivity Commands

This group of CobolScript Professional Edition commands can be used to establish a connection with an external database, and directly embed SQL (Structured Query Language) in your programs to interact with that database. See Appendix H, CobolScript Professional Edition Embedded SQL, for more information on interacting with a database in your programs and on the general syntax of embedded SQL.

CLOSEDB

EXEC SQL

OPENDB

Web Processing Commands


This group of commands can be used to simplify CGI programming and interaction with a web server. The ACCEPT DATA FROM WEBPAGE command gets CGI data that has been passed to it via the POST method from HTML forms; DISPLAYFILE enables binary files to be sent to the web visitor, while DISPLAYASCIIFILE sends ASCII text files; GETENV gets information about the web server; and GETWEBPAGE gets the content of a web page at a specified address.

ACCEPT DATA FROM WEBPAGE

DISPLAYASCIIFILE

DISPLAYFILE

GETENV

GETWEBPAGE


Basic Email Commands

Simple emails may be sent and received using these commands. You must have an email (POP) account in order to use GETMAIL and GETMAILCOUNT. You must have access and permission to use an SMTP server to utilize SENDMAIL. A specific set of error-trapping variables is mandatory when using these commands; these variables can be used to redirect program flow when errors are encountered in the mail transfer process.

GETMAIL

GETMAILCOUNT

SENDMAIL


FTP Commands

CobolScript provides standard FTP commands, so that you don’t have to access the command shell in order to invoke and conduct file transfers. You can use these commands to send and receive files from within your CobolScript applications. A specific set of error-trapping variables is mandatory when using these commands; these variables can be used to redirect program flow when errors are encountered in the file transfer process.

FTPASCII

FTPCD

FTPCONNECT

FTPPUT

FTPBINARY

FTPCLOSE

FTPGET


TCP/IP Commands

This group of commands provides the means to do TCP/IP socket programming using CobolScript. Socket programming is useful for building data interfaces over a network, and for other types of network communication tasks. A specific set of error-trapping variables is mandatory when using these commands; these variables can be used to redirect program flow when errors are encountered with a particular command.

ACCEPTFROMSOCKET

CONNECTTOSOCKET

GETHOSTNAME

RECEIVESOCKET

BINDSOCKET

CREATESOCKET

GETTIMEFROMSERVER

SENDSOCKET

CLOSESOCKET

GETHOSTBYNAME

LISTENTOSOCKET

SHUTDOWNSOCKET


Unix Shell-style Commands

These commands either mimic a Unix shell command (BANNER and CALENDAR), provide a unique twist on a shell command (GETBANNER and GETCALENDAR), or allow interaction with the host environment (CALL).

BANNER

CALL

GETCALENDAR

CALENDAR

GETBANNER


Dynamic Processing Command

This command enables dynamic execution of CobolScript statements that are held within variables. This allows statements to be created ‘on the fly’ and is a basic construct of AI programming.

EXECUTE


CobolScript Reserved Words

This is a list of the reserved words in CobolScript, which includes commands, keywords, special division and section words, and words reserved for future use in later releases of the CobolScript engine. Not all words listed here necessarily have meaning to the current version of the CobolScript engine, but you should not use any of these exact words as variable or module names. This list does not include CobolScript function names, but you should also avoid naming any variables with the same name as any function. The complete list of functions is in Appendix B, Function Reference.

ACCENT

ELSE

IF

SENDSOCKET

ACCEPT

ELSIF

INTO

SENTENCE

ACCEPTFROMSOCKET

END

IS

SET

ADD

ENDIF

INCLUDE

SHUTDOWNSOCKET

ALPHABETIC

END-EXEC

INITIALIZE

SINGLEQUOTE

AND

END-IF

LENGTH

SLEEP

AT

END-PERFORM

LESS

SOURCE

AUTHOR

ENVIRONMENT

LINEFEED

SPACE

BANNER

EQUAL

LISTENTOSOCKET

SPACES

BINDSOCKET

EQUALS

MOVE

SQL

BY

EVALUATE

MULTIPLY

STOP

BYTES

EXEC

NEXT

SUBTRACT

CALENDAR

EXECUTE

NOT

TAB

CALL

FD

NUMERIC

THAN

CARRIAGERETURN

FILE

OBJECT

THEN

CLOSE

FILLER

OCCURS

TIME

CLOSEDB

FROM

OFFSET

TO

CLOSESOCKET

FTPASCII

OPEN

STOP

COMPUTE

FTPBINARY

OPENDB

SUBTRACT

COMPUTER

FTPCD

OR

TAB

CONFIGURATION

FTPCLOSE

PERFORM

THAN

CONNECTTOSOCKET

FTPCONNECT

PIC

THEN

CONTINUE

FTPGET

POSITION

TIME

COPY

FTPPUT

PROCEDURE

TO

CREATESOCKET

GETBANNER

PROGRAM-ID

UNTIL

CRLF

GETCALENDAR

READ

UPDATING

DATA

GETENV

READING

USING

DATE

GETHOSTBYNAME

RECEIVESOCKET

VALUE

DAY

GETHOSTNAME

RECORD

VARYING

DAY-OF-WEEK

GETMAIL

RELATIVE

WEBPAGE

DELIMITED

GETMAILOUNT

REMAINDER

WITH

DISPLAY

GETTIMEFROMSERVER

REPLICA

WORKING-STORAGE

DISPLAYASCIIFILE

GETWEBPAGE

REWRITE

WRITE

DISPLAYFILE

GIVING

ROUNDED

WRITING

DISPLAYLF

GOBACK

RUN

XOR

DIVIDE

GREATER

SECTION

ZERO

DIVISION

IDENTIFICATION

SENDMAIL

ZEROS

DOUBLEQUOTE

Statements

A statement joins a CobolScript command with arguments and other keywords to form a single, distinct operation. You can also think of a statement as being a ‘step’ in a program, since the CobolScript engine executes code in a statement-by-statement manner. Sometimes a statement is just a single-word command without arguments, as in the following two cases:

FTPASCII

CONTINUE

Normally, however, statements are composed of commands, arguments, and any additional keywords that are required to complete the statement, as in:

MOVE source_var TO target_var

COMPUTE target_var = Y + 1

DIVIDE 10 BY 3 GIVING div_result REMAINDER remain_result

GETENV USING `CONTENT-LENGTH` content_variable

All statements, like sentences, must begin after column 7 (the seventh character counting from the left-hand side of your text program file), meaning that the leftmost character in a statement should be in column 8 or higher.

You should indent statements that are nested within conditionals with a consistent offset for each successive level of nesting to make your code more legible. Appropriate indentation looks like this:

MOVE 20 to x.

PERFORM UNTIL (x < 2)

COMPUTE target_var = SQRT(x)

IF target_var < SQRT(2) THEN

DISPLAY `x is less than 2`

ELSE

IF target_var > (SQRT(4)+1) THEN

DISPLAY `x is greater than 9`

END-IF

END-IF

MOVE target_var TO x

END-PERFORM.

A statement can be spread across multiple lines of your program if you wish, so long as all individual arguments and keywords within the statement remain intact. A statement should not, however, begin on the same line as a previous statement. The following lines, for example, are valid CobolScript code:


IF truth_test_var

COMPUTE

target-var = SQRT (x)

+ 1

IF target-var

< SQRT (2)

DISPLAY `X is less than 2`

ELSE

DISPLAY `X > 2`

END-IF

END-IF.

The following is not valid CobolScript code, since more than one statement is on a single line:

IF truth_test_var COMPUTE target_var = (6 + 2) END-IF.

You should be able to see by now that statements are really just a combination of the program elements previously discussed in this chapter, like commands, variables, expressions, conditions, and literals, in a way that makes sense to the CobolScript engine. For the exact syntax of each command’s respective statement, see Appendix A, Language Reference.

Sentences

A program sentence is any phrase, statement, or group of statements in a program that is terminated with a period.

All sentences must begin after column 7 (the seventh character counting from the left-hand side of your text program file), meaning that the leftmost character in a statement should be in column 8 or higher.

In CobolScript, each of the following items constitutes a discrete and complete sentence, and therefore requires a period to terminate it:

· All Division and Section titles, as in ‘PROCEDURE DIVISION.’ and ‘WORKING-STORAGE SECTION.’; see Appendix F, CobolScript Basic Program Structure, for more information on Divisions and Sections;

· The ‘PROGRAM-ID.’ and ‘AUTHOR.’ keywords in the Identification Division are each complete sentences on their own. Also, the argument to each of these keywords is a complete sentence;

· The ‘SOURCE COMPUTER.’ and ‘OBJECT COMPUTER.’ phrases in the Environment Division are each complete sentences on their own. The argument to each of these phrases is a complete sentence as well;

· All complete FD (File Description) entries;

· All variable definitions, whether group-level data item or elementary data item;

· Module (code paragraph) names;

· All complete statements that are not between PERFORM..END-PERFORM (an in-line perform) or IF..END-IF.

· If a statement is nested within an in-line perform or conditional, periods must not be used. The sentence in these cases terminates with the ‘END-PERFORM.’ or the ‘END-IF.’ keywords. If there are multiple levels of nesting, only the outermost level should be terminated with a period, as in the example that we used previously to demonstrate proper indentation:

MOVE 20 to x.

PERFORM UNTIL (x < 2)

COMPUTE target_var = SQRT(x)

IF target_var < SQRT(2)

DISPLAY `x is less than 2`

ELSE

IF target_var > (SQRT(4)+1)

DISPLAY `x is greater than 9`

END-IF

END-IF

MOVE target_var TO x

END-PERFORM.

Comments

Comments are text that has no effect on your program’s execution. Comments must begin with an asterisk (*) in column 7 (the seventh character counting from the left-hand side of your program file). Therefore, any line in a program that has an asterisk in column 7 will be ignored by the CobolScript engine, no matter what other text is on that line.

Well-placed, meaningful comments are critical to the readability and overall worth of your program. Explaining difficult-to-understand or non-intuitive code with a good comment will ultimately save you and anyone who edits your code a large amount of time.