®

cobolscript

Developer’s Guide


 

cobolscript® Developer’s Guide

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Copyright © 1996-2017 Matt Dean.    All Rights Reserved.


 

 

 

 

 

 

Copyright © 1996-2017 Matt Dean.  All Rights Reserved.

 

This manual and its entire contents are copyrighted material.  No part of this manual may be reproduced in any form or by any means, either electronic or mechanical, including photocopying and recording, for any purpose without the express written permission of Matt Dean.  Information contained herein is subject to change without prior notice.  All names and data in this manual are fictitious except where otherwise noted.  The software described in this manual is furnished under a license agreement.  The software may be used or copied only in accordance with the terms of the agreement.

 

The term “cobolscript” is a registered trademark of Matt Dean.  All other product names, including but not limited to the terms “VACE” , “VACE Maintenance Workbench” are trademarks or registered trademarks of Matt Dean.

 

Microsoft Windows and MS-DOS are registered trademarks of Microsoft Corporation.

Linux is a registered trademark of Linus Torvalds.

FreeBSD is a registered trademark of FreeBSD Inc. and Walnut Creek CDROM.

SunOS, Solaris, and Sun are registered trademarks of Sun Microsystems, Inc.

SQL*Loader and Oracle are registered trademarks of Oracle Corporation.

 

 

All other brand and product names mentioned herein are trademarks or registered trademarks of their respective holders.

 

 

 

 

 

 

 

Matt Dean

PO Box 6066

Chattanooga, TN 37401

 

 

 

 

Phone:

423-888-7475

World Wide Web:

www.cobolscripting.cloud

 

 

 

 

 

Enjoy your programming.

 

 


Table of Contents

 

Chapter 1                  Introduction to CobolScript® / Installation Instructions…………….      1

                                    CobolScript Features…………….…………….…………….………….         2

                                    About this Manual……………….…………….…………….………….         3

                                    Installing CobolScript…………….……………….…………….………         4

Chapter 2                  Getting Started with CobolScript®.…..……….…………….…………       9

                                    Creating and Editing CobolScript Programs………………………...…...        9

                                    Running CobolScript from the Command Line..………….….………….       10

                                    Running CobolScript in Interactive Mode..……….……….…….………        14

                                    Running CobolScript from a Web Server and Browser.………….………       17

Chapter 3                  CobolScript® Language Constructs……..…………………..……….         21

                                    Literals and Literal Keywords..…….………….…………….….……….         21

                                    Variables………………………...…………….…………….….……….         24

                                    Data and Copybook Files………………………………………….……         31

                                    Expressions and Conditions….….…………….…………….….……….        34

                                    Commands……………...…...…..…………….…………….….……….         39

                                    CobolScript Reserved Words….………………………………………...        42

                                    Statements…………………….….…………….…………….………….        43

                                    Sentences………………………....…………….…………….………….        44

                                    Comments……………….....……..….…………….…………….………       45

Chapter 4                  File Processing and I/O……………………………………………...         47

                                    Describing Files and Defining Data Records…………………………...          48

                                    Opening Files……...…………….…………….…………….………….         48

                                    Closing Files……...…………….…………….…………….…………...         48

                                    Reading Records From Files..…………………………………………..          49

                                    Overwriting a File……………………………………………………...          50

                                    Appending Records to an Existing File…………………………………         50

                                    Writing to a File by Updating Existing Records ……………………….          52   

                                    Relative and Absolute File Positioning…………………………………          53

                                    Relational Database Interaction with CobolScript Standard Edition……        55

Chapter 5                  Building Web Based Systems………………………………………...         63

                                    Interacting with a Web Server and Web Browser…………….………….        64

                                    Creating Virtual HTML…………………………………………………        65

                                    Creating an HTML Form……………………………………………….         66

                                    Capturing Input Data from a Web Page…………………………………        66

                                    DISPLAY and DISPLAYLF……………………………………………        68

                                    Retrieving Web Pages....…………….…………….…………….………         69

Chapter 6                  Network and Internet Programming Using CobolScript®….…….…      71

                                    Transferring Files using FTP…...………………………………………..        71

                                    Using Email Commands……………………………..…………………..       73

                                    Using TCP/IP Commands………………………………………………       75

 

Chapter 7                  Advanced Internet Programming Techniques Using CobolScript®..       83

                                    Environment Variables..……….…………….…………….……………         84

                                    CGI Form Components……………..………………………………….         86

                                    Using Hidden Fields……………………………………………………..       90

                                    Sending Email from CobolScript Using CGI Form Input...……………..       92

                                    Using CobolScript to Transmit Files……..……………………………....        93

                                    Embedding JavaScript in CobolScript Programs….…………….……….        95

Chapter 8                  Programming Techniques and Advanced CobolScript® Features….       99

                                    Designing a Modular Program..….…………….…………….………….         99

                                    Manipulating CobolScript Variables…………………………………….         101

                                    Advanced CobolScript Features...…...…………….…………….………         102

Chapter 9                  CS Professional CodeBrowser™, AppMaker™, and Control Panel...      109

                                    Feature Requirements..….…………………….…………….………….          109

                                    Using CodeBrowser…………………………………………………….         109

                                    Building Executables with AppMaker.…………….…………….………        112

                                    Using the CobolScript Control Panel..…………….…………….………         113

Appendixes

 

Appendix A              Language Reference…………….…………….…………….…………     117

Appendix B              Function Reference…………….…………….…………….…………..      159

Appendix C              CobolScript® Constraints…………….…..……….…………….……...    175

Appendix D             Sample CobolScript® Programs………………...……….…………….       177

Appendix E              CobolScript® Picture Clauses…….….….…………….…………….…       181

Appendix F              CobolScript® Basic Program Structure……………….……………...         187

Appendix G             Setting Up ODBC and ODBC Data Sources for LinkMaker™……..       195

Appendix H             Using LinkMaker™ Embedded SQL in CobolScript® Professional..       223

Appendix I               CobolScript® Error Messages..………….…………….…………….…       231

 

Glossary………….…………….…………….…………….…………….…………….……...     259 

Index…………….…………….…………….…………….…………….…………….………     265

 


Chapter

1


Introduction to CobolScript® / Installation Instructions

C

icon key

Ü  Important point

obolScript® is a powerful, easy to use, platform independent, internet-friendly programming language.  With it, you will be able to quickly develop and test web-based systems, interface programs, and compact business applications.  The natural syntax of CobolScript  will help you to start programming productively in a short amount of time, provided you’ve had at least some exposure to other programming languages.  This natural syntax, coupled with a variety of network and internet-specific commands, makes CobolScript a great alternative to more cryptic or complicated network programming languages.  If you’re an experienced internet developer, we think you’ll find that certain web programming tasks that used to be difficult with your old language will be simple with CobolScript, and as a side benefit, your code will be more manageable and easier to maintain.  If you’ve avoided web programming in the past because of its apparent complexity, CobolScript can open the door to a whole new style of application development for you, and can do it with a relatively small effort.

CobolScript is available for Microsoft Windows®, SunOS®, FreeBSD®, and Linux®.  Any program developed and tested on one platform can be almost seamlessly ported to another supported platform.  And like all web systems, CobolScript web apps can be executed from any machine that has a compatible browser and can access the web that is running CobolScript.  For this reason, a well coded, web-based CobolScript system will not require modification if client machines are changed or upgraded, so long as the clients still have compatible browsers installed – a welcome change for anyone who has had to modify applications with client front-ends specific to their operating system.

Alternatively, a single web client can run different CobolScript applications that reside on separate servers.  By linking small applications that are located on distinct servers to one another, you can create a complete web system,  and the processing for this single, larger system will be spread across the servers.  Figure 1.1 illustrates one possible architecture for such a system.

 

 

 

 

 

       Figure 1.1 – A multi-server CobolScript application


CobolScript Features

In addition to the standard language commands and the internet processing commands available in  CobolScript, other features provide the means to quickly and easily create programs with a wide range of functionality:

·         Internetworking commands such as FTPPUT, FTPGET, SENDMAIL, and GETMAIL for transferring files and emails from within a CobolScript program.

·         File processing commands for reading and parsing both fixed-format and delimited data files.

·         Flexible naming syntax that allows underscores ( _ ) and dashes ( - ) to be used interchangeably in variable names, to support both modern variable naming as well as COBOL-style variable naming.

·         Advanced expression evaluator that does not require explicit spaces between expression components, even for subtraction operations, for programmers who are used to coding mathematical expressions in C or similar languages.

·         Financial functions for calculating annuities and depreciation.

·         Scientific, stochastic, and other higher math functions.

·         Metric to English and English to metric system unit conversion functions.

·         TCP/IP socket programming commands such as SENDSOCKET and RECEIVESOCKET, for creating client-server communications programs without web server software or FTP configuration.

·         DNS commands such as GETHOSTNAME for incorporating internet information retrieval into programs.

·         PIC X(n) picture clause that automatically calculates variable size based on VALUE clause, eliminating the need for time-consuming computations with FILLER variables, and an implied version of PIC X(n) that allows the FILLER keyword and picture clause to be eliminated entirely.

·         REPLICA variable declaration syntax that permits the same elementary data item to be used in multiple group items.

·         EXECUTE command for dynamic statement creation and execution.

·         Intelligent error messaging that displays browser-based error messages when running programs from a browser, and text-based error messages when running programs from the command line, thereby speeding the debugging process.

Using these CobolScript features, you can develop programs to get and save web pages to text files, transfer files via FTP, send simple emails, retrieve emails, accept data from web page forms, create virtual HTML documents, and perform various file input and output operations.

CobolScript Professional Edition also contains a number of enhancements that enable professional development with CobolScript:

·         CobolScript AppMaker, which makes it possible to create executables from CobolScript programs.

·         CobolScript CodeBrowser, a browser-based utility to examine your code in colorized form.

·         CobolScript LinkMaker, a tool that enables you to directly embed SQL calls in your CobolScript program to access any data source for which you have an ODBC driver.  On Unix platforms, LinkMaker is used in conjunction with UnixODBC, a freeware product.

·         The CobolScript Control Panel, a graphical administration tool accessible from your web server machine (so long as both CobolScript and web server software are installed), for accessing other CS Professional features, and for administering your CS Professional system.

·         Multidimensional array support.

About this Manual

This developer’s guide should serve as both a guide for learning to program with CobolScript, and as a reference for your day-to-day programming.  It should provide sufficient instruction for most experienced programmers to learn to develop CobolScript applications; however, in certain instances you may wish to find additional information:

·         If you are completely new to the art of programming, you should probably familiarize yourself with introductory programming principles as well.  Understanding the basics of programming will reduce the time it takes you to learn CobolScript.

·         If you choose to program web applications using CobolScript, you should be familiar with HTML.  HTML is relatively easy to learn, and many good web sites and books exist on the topic, so it would be redundant to include an HTML reference in this guide.  A number of ‘WYSIWYG’ (What You See Is What You Get) software tools are also freely available and can assist you in prototyping your system and creating the HTML that will be displayed by your programs.  Check www.download.com for the latest freeware and shareware WYSIWYG tools.

·         Although web programming is addressed in this guide, you may also choose to seek more in-depth coverage of the subject, if, for instance, you want background information about CGI or about concepts not in this manual, such as cookie creation using CGI scripting. 

·         If you are interested in providing more real-time user feedback than is possible with just CGI scripting, or you want to distribute some of your web served application’s processing to client machines, consider learning more about an appropriate embedded language like JavaScript.  These languages’ scripts can be embedded in the HTML that is displayed by your CobolScript programs, so you can provide real-time, client-based processing while still using CobolScript.  Our preferred client-side scripting language is JavaScript, since it loads and executes relatively quickly, and will run on both Netscape Navigator® and Internet Explorer®.

If you are looking for books on any of the above topics, we’ve found the Peachpit Press Visual Quickstart Guide series to be affordable, concise, readable for beginners but not overly simplified, and filled with good examples.  Peachpit Press is on the Web at www.peachpit.com.

Installing CobolScript

System Requirements

A Pentium®-compatible machine (166 MHz and higher preferred) is required for the Windows®, Linux®, and FreeBSD® versions of CobolScript, a RISC-processor machine for the SunOS® version.  32MB of RAM is recommended for CobolScript Standard, more for programs of substantial size.  64MB of RAM is recommended for CobolScript Professional Edition.

Installing CobolScript on a Windows®-compatible machine

Step 1.  Download CobolScript.

Create a directory such as C:\DESKWARE or C:\COBOLSCRIPT where you will keep  CobolScript and your CobolScript programs.  Download the file(s) to that directory from the Deskware Registered User Web Site.  If you have downloaded a zip file (with the extension .zip), unzip it using WinZip or a similar product.  The cobolscript.exe file is the CobolScript interpreter, and the .cbl files are the sample CobolScript programs.  As you have already discovered because you are reading this, this manual is the file cbmanual.pdf, and requires that you have a free copy of Adobe Acrobat Reader®, version 4.0 or higher, installed on your computer to read and print it.

Step 2.  Install CobolScript.

No special configuration is required for CobolScript to run.  However, we recommend that you modify your PATH environment variable in your AUTOEXEC.BAT file to point to the location of the CobolScript engine.  To do this, first save a copy of your old C:\AUTOEXEC.BAT file to a backup file such as C:\AUTOEXEC.BAK, then open AUTOEXEC.BAT in a text editor such as notepad, and modify the SET PATH= line.  For example, if a line in your AUTOEXEC.BAT file reads:

SET PATH=C:\MOUSE;%PATH%;C:\PP\BIN\WIN32

you would change it to:

SET PATH=C:\MOUSE;%PATH%;C:\PP\BIN\WIN32;C:\DESKWARE

if you have saved the CobolScript engine to the C:\DESKWARE directory.

Step 3.  Run CobolScript.

CobolScript can be run from the command line.  Start an MS-DOS prompt, and type:

cobolscript.exe

to run CobolScript and see the command line options.  To run a specific program from the command line, type:

cobolscript.exe <program-name>

where <program-name> is the name of the program you wish to run, along with a path if the program is not in the current directory.  For example:

cobolscript.exe test.cbl

cobolscript.exe ..\testdir\test.cbl

Ü

For more information on running CobolScript from the command line, turn to the next chapter, Getting Started with CobolScript.

If you plan to do Web and CGI development, you will probably want to put CobolScript in your web server’s CGI directory.  Usually this directory has “cgi” or “cgi-bin” in the name, as in c:\httpd\cgi-bin for the OmniHTTPd web server.  Just place the cobolscript.exe file in this directory.  See the section titled Running CobolScript from a Web Server and Browser in Chapter 2, Getting Started with CobolScript.

If you don’t already have a web server, OmniHTTPd is a freeware development-quality web server for Windows 95/98/NT®.  Search the web for “OmniHTTPd” to find a copy.

Step 4.  Configure ODBC on your computer.

If you have CobolScript Professional Edition and you want to access a database using LinkMaker, you will need to set up an ODBC data source on your computer.  Refer to Appendix H for complete instructions on how to do this. 

Installing CobolScript on a Linux®, SunOS®/Solaris®, or FreeBSD® machine

Step 1.  Download CobolScript.

Create a directory such as /deskware or /cobolscript where you will keep CobolScript and your CobolScript programs.  Download the file(s) to that directory from the Deskware Registered User Web Site.  If you have downloaded the complete file, un-tar it with the appropriate command (depending on your OS).  Below are some un-tarring examples:

tar -xvf linuxcob.tar

tar -xvf suncob.tar

tar -xvf bsdcob.tar

Similar steps should be followed with other tar files; just use the same syntax as above and substitute the appropriate filename.  The cobolscript.exe file is the CobolScript interpreter, and the .cbl files are the sample CobolScript programs.  As you have already discovered because you are reading this, this manual is the file cbmanual.pdf, and requires that you have a free copy of Adobe Acrobat Reader® 4.0 or higher installed on your computer to read and print it.  Because there is not a version of Adobe Acrobat Reader® available for FreeBSD, if you have purchased this version of CobolScript you will have to print the manual from an Acrobat®-compatible OS (Windows®, Linux®, IRIX®, HP-UX®, AIX®, Solaris®, Macintosh®, etc.).

Step 2.  Install CobolScript.

No special configuration is required for CobolScript to run.  However, we recommend that you modify your PATH environment variable to point to the location of the CobolScript engine.  To do this permanently (preferred), you can modify the appropriate line of your .profile file in your home directory.  For example, if a line in your .profile file reads:

PATH=/bin:/sbin

you should change it to:

PATH=/bin:/sbin:/deskware

in the case where CobolScript is in the /deskware directory.  If you are going to run CobolScript from your current directory only, make certain that "./" is also a component of the PATH variable.

To modify your PATH environment variable for the current session only, first type:

echo $PATH

at the command prompt to see the current value of your PATH environment variable.  Next, on Linux® or Sun® machines, at the command prompt type:

PATH=$PATH:/deskware

where /deskware is the path to the CobolScript interpreter.  In FreeBSD, you should instead type:

setenv PATH oldpath:/deskware

or alternatively:

set path=oldpath:/deskware

where oldpath is the original value of the PATH variable, and /deskware is the path to the  CobolScript interpreter.  Your path will be changed for the current session.

Step 3.  Run CobolScript.

CobolScript can be run from the command line.  Bring up an xterm or command prompt, and type:

cobolscript.exe

 to run CobolScript and see the command line options.  To run a specific program from the command line, type:

cobolscript.exe <program-name>

where <program-name> is the name of the program you wish to run, along with a path if the program is not in the current directory.  For example::

cobolscript.exe test.cbl

cobolscript.exe ../testdir/test.cbl

Ü

For more information on running CobolScript from the command line, turn to the next chapter, Getting Started with CobolScript.

If you plan to do Web and CGI development using CobolScript, you will probably want to put CobolScript  in your web server’s CGI directory.  Usually this directory has “cgi” or “cgi-bin” in the name, as in /home/httpd/cgi-bin on Apache.   Just place the cobolscript.exe file in this directory.

If you are doing CGI development and intend to read and write to files in your cgi-bin directory, make certain that the permissions on these files (and on the cgi-bin directory, and its parent directories) are correctly set.  Use the chmod command at the command prompt to properly set file permissions.  If this is not done, you will encounter difficulties when running scripts from a web browser, since these scripts generally run as user 'nobody', who does not have the same authority as you do when you are logged in at a command prompt, creating these files.

Step 4.  Set up ODBC on your computer.

If you have CobolScript Professional Edition and you want to access a database using LinkMaker, you will need to set up an ODBC data source on your computer.  Refer to Appendix H for instructions on how to set up UnixODBC (a freeware product from UnixODBC.org) so that you can connect directly to your data source. 


 

 

 

 

Chapter

2


Getting Started with CobolScript®

B

icon key

Ü  Important point

efore you dive headfirst into CobolScript programming, you will need to learn the basics, like how to edit your CobolScript programs, how to run them, and how to debug them.  This chapter aims to answer the basic logistical questions of CobolScript coding that you may have, as well as providing a background on CobolScript interactive mode, which contains some useful debugging tools.  With the information here, you’ll be ready to learn the CobolScript language.

Just as a note, all of the screens shown in this chapter, with the exceptions of the Windows®-specific information in Figures 2.1 and 2.2, are representative of any CobolScript platform; don’t worry about whether the figure shows an MS-DOS screen or a Unix screen, because the syntax and output of the illustration would be the same no matter what the platform.

Creating and Editing CobolScript Programs

 

Figure 2.1 – Saving a CobolScript program in the Microsoft® Wordpad Save As dialog box.


Use a standard text editor to create and edit your CobolScript programs. In Windows®, editors such as Notepad or Wordpad work well.  If you use Wordpad, make certain you save your files as text documents, and specify the extension when naming your program, as in Figure 2.1, or Wordpad will save the file with a default extension of .txt.  Also, in Wordpad you’ll find it easiest if you choose a fixed-width font for your editing such as Courier New.  This will allow you to later open your programs in Notepad, MS-DOS EDIT, or in Unix without a loss of formatting.  You will probably find yourself using the aforementioned MS-DOS EDIT text editor (accessible by typing the word edit at the DOS prompt) when debugging, because despite its old-fashioned appearance, it tracks the current column and row positions of the cursor, which can allow you to quickly locate a program line number.  Figure 2.2 shows an EDIT screen, with the cursor positioned down and to the right of center; the resulting Line and Column position values appear in the lower right corner of the screen.

 

Figure 2.2 – The MS-DOS EDIT text editor, showing the current cursor position (Line and Column) in the

                    lower right corner.


If you choose to edit your programs in Unix, any editor that saves documents as plain ASCII text will suffice.  Like MS-DOS EDIT, vi is a useful editor because it provides the means to quickly navigate to a particular line number.  Teaching vi is beyond the scope of this manual, however, so refer to a Unix or vi-specific reference for more information.

If you are using CobolScript Professional Edition, you will probably find CobolScript CodeBrowser to be a useful tool for printing and examining your programs; CodeBrowser is discussed in detail in chapter 9.

Running CobolScript from the Command Line

The simplest way to use CobolScript is by running a CobolScript program in command line mode.  To do this, type:

cobolscript.exe <program-name>

at the command prompt, where <program-name> is the name of the program you wish to run (don’t literally enclose the program name in < >; we use this syntax to indicate that program-name is an argument to the CobolScript executable, cobolscript.exe).  This command assumes that you have already included your CobolScript directory in your PATH environment variable, or alternatively, that you are executing the command from within the CobolScript directory.  If you need instructions on how to include your CobolScript directory in your PATH variable, refer to the Installing CobolScript section of Chapter 1, Introduction to CobolScript / Installation Instructions.

If you’re using the Windows® version of CobolScript (rather than a Unix version), running from command line mode means that you are running your CobolScript programs in an MS-DOS session.  However, it is important to note that although your CobolScript applications can be run from the DOS prompt, CobolScript is not a DOS application; it is a native 32-bit application that excludes Windows-specific graphical components in order to minimize the CobolScript engine’s footprint and to provide cross-platform capability.  Graphical development with CobolScript is achieved through the use of a web server and browser-based applications, discussed in more detail in Chapters 6 and 8.  See the section titled Running CobolScript from a Web Server and Browser later in the chapter for more information on getting started in a web-based environment.

Running CobolScript from Windows® command-line mode, you can drop the extensions if you like, and just type:

cobolscript <program-name>

 

 

 Figure 2.3 – Executing CobolScript programs from the command line prompt.


Command line program execution will direct all output to the current command line window, and therefore all output will be plain text.  Several of the example programs contained with CobolScript are designed to run in command line mode; figure 2.3 shows the output of the ARITHMETIC.CBL example program in an MS-DOS prompt window.

CobolScript also comes with a number of command line options.  If you aren’t already familiar with the term, a command line option is a switch that you set at the time that you call an executable program, which in this case is the CobolScript executable.  These switches allow you to change some specifics in the way that CobolScript runs, at the time you run it.  If you type cobolscript.exe at the command line prompt, without any program arguments specified, you will see a list of the CobolScript command line options.

 

  Figure 2.4 – CobolScript Professional command line options.


Figure 2.4 illustrates this in an MS-DOS window (on other platforms, you would need to specify the .exe extension to the CobolScript executable).  The syntax of the CobolScript Standard Edition command line options is as follows:

cobolscript.exe  [-i|-l] <program-name> [-t|-dd|-ds]

·         The -i option runs the interpreter in interactive mode; see below for more information on running in interactive mode.  When the -i option is used, if a program-name is not specified, interactive mode will be entered with nothing in the program buffer.  If program-name is specified, interactive mode will be entered, and program-name will be loaded into the program buffer.

·         The -l option runs <program-name> and creates a listing of the program execution as a separate log file with the name program-name.log.  For example, if your program name is test.cbl, and you type the following at the command prompt:

      cobolscript.exe –l test.cbl

then a log file named test.log  will be created in the working directory.

·         The -t, -dd, and -ds options are options that come after the program name: 

Ţ     The -t option causes CobolScript to truncate (and ignore) all characters beyond the 72nd column position when parsing the program; this mimics the way mainframe COBOL works.  Your program file is not affected, just the execution of the program.  The default (no –t specified) is for all characters in the program to be treated as code.

Ţ     The -dd option causes CobolScript to recognize the double quote character ( “ ) as the string delimiter instead of the default, the accent symbol ( ` ).  To display a literal double quote when using this option, your program must use the keyword DOUBLEQUOTE.  The -dd and -ds options are mutually exclusive.

Ţ     The -ds option causes CobolScript to recognize the single quote character ( ‘ ) as the string delimiter instead of the default, the accent symbol ( ` ).  To display a literal single quote when using this option, your program must use the keyword SINGLEQUOTE.  The -dd and -ds options are mutually exclusive.

CobolScript Professional Edition also provides a utility to build executables from the command line, CobolScript AppMaker.  The syntax for creating an executable using AppMaker is:

cobolscript.exe -b <program-name>

If your program successfully loads, an executable will be created from it and placed in the working directory.  For example, typing the following will create an executable named test.exe in the working directory:

cobolscript.exe -b test.cbl

CobolScript Error Messages in Command Line Mode

It will be normal for you to encounter bugs in your code while you are testing your CobolScript programs.  In command line mode, error messages display directly to the screen in a text-based format.  The error messages are quite specific, and will usually help you pinpoint the source of the problem with your code. 

Multiple error messages are displayed when a single line of code causes multiple errors in the CobolScript engine; in these cases, one of these multiple errors should be obviously more specific than the others, and will better assist you in determining the problem than the more general messages.  Multiple error messages, however, never indicate that there are unrelated errors on different lines of the program.  This is because CobolScript is an interpreted language, and program execution is halted as soon as a single error is encountered.  For this reason, you must re-run your program after correcting each error to determine if there are other errors in your code.

 

 

Figure 2.5 – CobolScript command line error message.


All error messages have an associated CobolScript Error Number, which displays along with the error message when the error is encountered; all error messages are explained in detail in Appendix F, CobolScript Error Messages, in order of this CobolScript Error Number.

After the last error message is displayed for a particular error, the text of the line that caused the error is displayed, along with some line number information.  The Source Line Number is the actual number of the line in the program text file that caused the error.  Use this line number to navigate to the line of faulty code in your program with a text editor like MS-DOS EDIT or vi.  The Internal Line Number indicates the number assigned to the Instruction Pointer (IP) at the time of the error.  This number can be used when a program is run in interactive mode to determine the problem line, in conjunction with the list and ip interactive mode commands.  Finally, the Source Line is the text of the line that caused the error.  Figure 2.5 shows an example of a command line error and the resulting error messages.

Running CobolScript in Interactive Mode

From CobolScript interactive mode, you can load a program, execute it, step through and animate its execution, and examine the contents of your program’s variables as they are populated.  These features make interactive mode a great debugging tool.  Interactive mode can be accessed by using the -i command line option when running CobolScript from the command prompt.  Refer to the explanation of the CobolScript command line options above for the appropriate command line syntax.  Figure 2.6 shows the start of a CobolScript interactive mode session on SunOS; interactive mode on other supported platforms is essentially the same.

Once you’ve started an interactive mode session, you’ll see the CobolScript interactive mode prompt that looks like this:

cobolscript>

 

 

Figure 2.6 - Interactive Mode in SunOS®


From this prompt, you can use all of the interactive mode commands, although some commands will not work properly until a program has been loaded, and others will not work correctly until a program has been run.  To see a help screen-style list of these commands, type a question mark (?) at the command prompt.  Figure 2.7 shows a representation of this list of commands.

+---------------------------------------------------------+

| CobolScript 2.01 Copyright (c) 1996-2000 Deskware, Inc. |

+---------------------------------------------------------+

| COMMANDS:                                               |

|                                                         |

| ?                    dump modules      positions        |

| ! <system command>   dump positions    q                |

| animate <speed>      dump variables    run              |

| break <linenumber>   files             save <filename>  |

| clear                help <command>    stack            |

| count                ip                stepoff          |

| deskware             list              stepon           |

| display <variable>   load <filename>   variables        |

| dump listing         modules           ver              |

|                                                         |

|                                                         |

+---------------------------------------------------------+

 

   Figure 2.7 – Interactive Mode Help Screen example


Interactive Mode Commands

The following list defines the interactive mode commands.  Online command-specific help is also available in interactive mode by typing help <command>.

Interactive Mode Command

                                                                                                    Description

?

Displays all of the commands available in interactive mode.

! `system command`

Runs a system command on your machine.  The system command must be an operating system command in the appropriate syntax for your operating system.  Examples:

! dir

! `dir | more`

! `ls –al`

! `chmod 777 test.cbl`

animate <speed>

Executes the code that is in the program buffer line by line, and displays each line of code as it is executed.  The speed parameter controls the speed of the code interpreting and displaying process:  the higher the number, the slower the lines of code will be displayed.

break <linenumber>

Sets a break point to halt program execution. 

The break command has the following forms:

·         break  with no argument specified lists all current break points;

·         break <linenumber>  sets a break point in a program’s execution at linenumber;

·         break clear <linenumber>  clears the existing break point at linenumber;

·         break clear all  removes all existing break points.

clear

Removes the contents of the current program buffer.  After the clear command is used, another program can be loaded into the buffer.

count

Displays the number of lines of code in the program currently loaded in the program buffer.

deskware

Displays Deskware, Inc. contact information.

display <variable>

Displays the contents of the specified variable.  The display command can be used after run, animate <speed>, or stepon has been used to execute a loaded program.

dump variables

dump modules

dump positions

dump listing

Creates a text file dump of all variable contents, a module list, a program listing, or a variable position listing, depending on the argument.  Below are the names of the files that are created by each command:

·         dump variables    - dump.var

·         dump modules    - dump.mod

·         dump positions   - dump.pos

·         dump listing         - dump.lst

files

Displays all of the files that a program used as it was executed.  The files command can be used after run, animate <speed>, or stepon has been used to execute a loaded program.

help <command>

Displays command-specific help.

ip

 

Displays the current value of the CobolScript internal instruction pointer.  This value is equivalent to the internal line number of the line that was just processed.

list

Displays the contents of the program buffer to the screen.  The program buffer contains the lines of program code that were loaded with the  load <filename> command.

load <filename> 

Loads the contents of the specified program file filename into the program buffer.  Once loaded, a program file can be executed by using the run or animate <speed> command.

modules

Displays all of the modules defined in the code that has been loaded into the program buffer.

positions

Displays all variables’ byte offsets.  The positions command can be used after a program has been executed using run or animate <speed>.

q

Quits interactive mode.

run

Executes code that has been loaded into the program buffer.

save <filename>

Saves the current contents of the program buffer to a text file filename.

stack

Displays the code lines that are currently on the CobolScript internal stack.

stepoff

Turns off step mode that was set using the stepon command.  After step mode has been turned off, the run command will run programs normally, without stepping.

stepon

Places CobolScript in step mode.  Once in step mode, the run command will begin interactive execution of the loaded program.  Interactive execution means that the program is executed, one line at a time, by pressing the ENTER key.  As the program is interactively executed, commands such as variables, files, ip, and stack can be used to display current information.

variables

Displays all of the variables used by a program, and the contents of those variables. The variables command can be used after run, animate <speed>, or stepon has been used to execute all or a portion of a loaded program.

ver

Displays version information for your CobolScript installation.

 

Running CobolScript from a Web Server and Browser

With proper installation and web server configuration, CobolScript programs residing in the appropriate web server directory can be initiated by (and the output displayed in) a web browser.  By placing your CobolScript programs on a server and accessing them with a browser, you can create graphical, efficient applications accessible from any computer with browser software installed on it, so long as the browsing computer has visibility to the web server computer, either across a network or the internet.

For your CobolScript web applications to run correctly, you should perform the following steps:

1.       Place your programs, any text files used by your programs, and the CobolScript executable in your web server’s cgi-bin directory.  Consult your web server documentation if you do not know where the cgi-bin directory is, or you want to modify its location.

2.       On Unix servers, use the chmod command to change the permissions on the files that you placed in the cgi-bin directory, as necessary.  Since CGI scripts usually run as user ‘nobody’, the permissions on these files generally must be set to allow any user to have the appropriate access to all files used by your programs.  As an example, suppose a CobolScript web program reads from and writes data to a file named DATA.TXT.  The file DATA.TXT must then permit both reading and writing by any user, in order for the program to run successfully.  In this case, typing

chmod 666 DATA.TXT

at the Unix command prompt will change DATA.TXT appropriately.

3.       Make certain CGI scripting is turned on and permitted by your web server software; this is necessary for CobolScript applications to run correctly.  Consult your web server documentation for information on how to enable CGI scripting if it is not already enabled.

4.      

 

 

Figure 2.8 – CobolScript Web Application (Timesheet Program) Example


After you have placed CobolScript and your CobolScript programs in your cgi-bin directory, you can execute the programs on the server with your browser by placing a “?” between the cobolscript.exe and the program’s filename in the browser URL.  Figure 2.8 illustrates the execution of a sample timesheet program initiated from a Netscape® browser, but running on a FreeBSD® server with Apache web server software; note the address in the Location: (URL) box, that runs the program uts.cbl in the cgi-bin directory with the syntax “cobolscript.exe?uts.cbl”.

To generalize, any CobolScript program that has been placed, along with the CobolScript executable, in the appropriate directory on your web server’s computer can be executed by using a URL of the following form:

http://<your ip address>/cgi-bin/cobolscript.exe?<program name>

You can see several more example of this on the Deskware samples web site at http://www.cobolscript.com/cgi-bin/cobolscript.exe?samples.cbl.

CobolScript Error Messages in Web Browser Mode

 

 

 Figure 2.9 – Browser-based error message


Besides the standard command line error messaging system explained in the Running CobolScript from the Command Line section in this chapter, CobolScript provides an integrated web-based error messaging system.  This messaging system is unique in that CobolScript determines whether you are running a program from a web browser or the command line, and controls the display of the error message accordingly.  If you run a CobolScript program from you web browser and encounter an error, you will see the CobolScript Error Number and error message displayed in a consistent HTML-based format; if you run the same program from the command line and encounter the same error, the number and messages will display in a text-based format.

The web based error message in figure 2.9 illustrates this HTML-based error messaging system.  In this particular example, a variable was misspelled in the GETENV statement, and was therefore undefined and caused an error. 

Ü

In certain cases when running CobolScript programs from a browser, you will see a completely blank browser window, or an incomplete display of your HTML without a CobolScript error on the page.  These cases can indicate errors in your HTML code as well as a CobolScript error.  Check the page source from your browser to find any CobolScript error messages that are embedded in the HTML but did not successfully display.  Correct the CobolScript error(s) first; if the page still fails to display properly, but there are no longer any CobolScript error messages in the page source, check your HTML syntax.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Chapter

3


CobolScript® Language Constructs

I

icon key

Ü  Important point

n 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

UPPER

COPY

IF

PERFORM

LOWER

TRIM

LTRIM

RTRIM

TOK

GETCMDLINE

CREATESHMPOOL

PUTSHMPOOL

GETSHMPOOL

DETACHSHMPOOL

 

 

 

 

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

READBLOCK

WRITEBLOCK

 

 

 

 

 


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

GETMAILSIZE

DELETEMAIL

 


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

TRIM

LTRIM

RTRIM

TOK

GETCMDLINE

CREATESHMPOOL

PUTSHMPOOL

GETSHMPOOL

DETACHSHMPOOL

UPPER

LOWER

 

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.

 


 

 

 

 

 

 

Chapter

4


File Processing and I/O

A

ccessing and manipulating disk-resident data are tasks that must be performed by any application that has long-term information storage requirements.  Almost all business applications utilize or manipulate external information in some form, and many scientific programs also have data input and output, so any good programming language must incorporate commands to enable the processing of data that is external to the program.

icon key

Ü  Important point

All native CobolScript data processing is done with ASCII text files, commonly referred to as flat files; this flat file processing is the primary focus of this chapter.  CobolScript will correctly process data files that are either fixed field width or single-character delimited.  If the data in the file is delimited, the parsing of the fields is handled internally by CobolScript. 

The data records in CobolScript data files are stored sequentially, meaning one after another.  Sequential organization is the most straightforward approach to organizing records within a file; the operations that can be performed on such a file are necessarily basic, and in CobolScript, input and output commands are restricted to entire-file operations (OPEN and CLOSE), entire-record operations (READ, WRITE, REWRITE), and an operation that moves the file pointer (POSITION).  Nevertheless, if you have previously only dealt with relational database access methods to retrieve or modify data, you should pay special attention to this chapter, since data access methods such as direct SQL calls are strictly a CobolScript Professional Edition feature and are not available from within CobolScript Standard Edition.

It is, however, possible for CobolScript Standard Edition to interact with a relational database, if the RDBMS (relational database management system) supports stored procedures, these procedures can be called from the system prompt, and the RDBMS is able to direct the output from stored procedure calls to flat files.  Our interaction technique, which uses a combination of stored procedure calls and intermediate flat files, is described in the last section of this chapter.  Since your actual technique will vary depending on the relational database that you use and any firewall that may exist on your network, the information in this section is presented at a more conceptual level than the other sections in the chapter.

If you are programming with CobolScript Professional Edition, and you want to directly interact with a relational database using CobolScript LinkMaker’s embedded SQL capability, refer to Appendixes G and H for instructions on configuring and using LinkMaker.

Describing Files and Defining Data Records

Before any processing can be done on a data file, you must first describe it using an FD statement, and you must create a record variable that defines the individual fields within each data record.  See the Data and Copybook Files section of Chapter 3 for more details on describing a file and defining a data record.

Opening Files

Before you can begin reading data from a file or writing data to a file, you must first open the file.  Opening a file lets the operating system know that you intend to perform an input or output operation on that file, and prepares the file for subsequent operations. You can open a file in CobolScript for reading, writing, updating, or appending.

If you open a file for writing and the file already exists, its contents will be destroyed and a new file created in its place.  Opening a file for reading, updating, or appending, however, will not destroy the file’s contents.

The DELIMITED WITH clause can be added to an OPEN statement to indicate that a data file is delimited, meaning that fields are separated with a single-character delimiter that is specified after the WITH keyword.  The absence of the DELIMITED WITH phrase indicates that the data file has fixed width fields, which will be separated based on the individual field sizes in the record definition.

Below are some examples of each variation of the OPEN statement, with and without the DELIMITED WITH clause:

OPEN test_file FOR READING.

OPEN `test.dat` FOR READING DELIMITED WITH `|`.

OPEN `test_file FOR WRITING.

OPEN test_file FOR WRITING DELIMITED WITH `,`.

OPEN `test.dat` FOR APPENDING.

Ü

OPEN test_file FOR APPENDING DELIMITED WITH `,`.

If you’re working in a Unix environment, you must have the appropriate permissions set for your data files; specifically, read as well as write permissions must be set on all data files for all file processing options.  Even files that are only opened for reading must have Unix write permissions set, because early versions of CobolScript used OPEN FOR READING to update records as well as to read them; to be backward compatible, current versions of CobolScript still support this format.

Closing Files

After you have finished working with a file, you must close it.  Closing a file releases the file descriptor to the operating system; failing to close a file will cause the file to be locked and appear unavailable to other applications. Here is an example of the CLOSE statement:

CLOSE `test.dat`.

In the following CobolScript program, we simply open and close a file.  Since it is opened for writing, the file will be created if it does not already exist, or overwritten if it does already exist.

1 io_file PIC X(n) value `IO.DAT`.

FD io_file RECORD IS 100 BYTES. 

 

OPEN io_file FOR WRITING.

CLOSE io_file.

Reading Records From Files

The READ statement reads one data record from the data file and loads it into the target record variable.  A single READ will read data until it reaches a line terminator, at which point it stops.   The line terminator is the ASCII character or character combination that is used by your operating system to indicate the end of a line, usually either the carriage return or carriage return and linefeed characters in combination.  The line terminator is not included in the record data.

The AT END clause of the READ statement is an error-trapping routine that recognizes when the end-of-file marker has been reached, and executes a specific statement when this condition is met.  We have chosen to use a MOVE statement in this example; any simple one-line statement, such as DISPLAY or COMPUTE, could be substituted for the MOVE.  The clause should be used in most cases; if the AT END clause is not specified, reaching the end of a data file will cause a CobolScript error.

Once a data record has been read and the target record variable populated, the component fields of the record variable can be used like any other variable.  Below is some example code that utilizes the READ statement:

1 test_file PIC X(n) VALUE `TEST.DAT`.

FD test_file RECORD IS 100 BYTES.

1 input_record.

  5 ir_component_1 PIC X(50).

  5 ir_component_2 PIC X(50).

1 eof PIC 9 VALUE 0.

 

OPEN test_file FOR READING.

 

PERFORM UNTIL EOF

   READ test_file INTO input_record

     AT END MOVE 1 TO eof

   DISPLAY `Record component 1 is: ` & ir_component_1

END-PERFORM.

CLOSE test_file.

 

Overwriting a File

To overwrite a file, just open it for writing and write the new output to the file using the WRITE statement.  Writing will put data from a source literal or variable into a single record in the file.  In this example, the fields comprising RECORD-VARIABLE are assumed to have already been populated:

OPEN test_file FOR WRITING DELIMITED WITH `|`.

WRITE record_variable TO test_file.

CLOSE test_file.

Appending New Records to an Existing File

To append records to the end of an existing file, open the file for appending and write each record to the file using the WRITE statement.  Each WRITE statement will add the source record to the file as the last sequential data record.  Here’s the code for several appends to a delimited data file:

1 test_file PIC X(n) VALUE `test.dat`.

1 bytes_num PIC 99 VALUE 10.

FD test_file record is bytes_num bytes.

OPEN test_file FOR APPENDING DELIMITED WITH `,`.

WRITE `12345` TO test_file.

WRITE `1234`  TO test_file.

WRITE `123`   TO test_file.

CLOSE test_file.

The following output (highlighted in gray) will be written to the file test.dat:

12345,   `

1234,    `

123,     `

Each of the three records above is made up of three components:  the source literal from the WRITE statement that created that record, followed by the comma delimiter, and then followed by enough spaces to make the total length of the record equal to ten characters.  Note that even when files are opened as delimited files, CobolScript still right-pads the record with spaces until it is the total length declared in the FD statement (in this case, ten bytes).  This padding is an intentional feature of CobolScript, because it simplifies the task of individually updating delimited data records.  This also has relevance if you intend to update delimited data records created outside of CobolScript; see the next section on updating records for more information.

If the DELIMITED WITH option is absent from our code block, as in the following:

OPEN test_file FOR APPENDING.

Then, assuming that the FD statement and everything else in our original block of code does not change, the following output will be written to test.dat:

 

12345    `

1234     `

123      `

Now let’s look at a slightly more complex case with a record variable that is made up of two fields.  First, we’ll describe the file and define the record variable:

1 test_file PIC X(n) VALUE `test.dat`.

1 bytes_num PIC 99 VALUE 9.

FD test_file record is bytes_num bytes.

1  record_var.

  5  field_1  PIC X(4).

  5  field_2  PIC X(5).

 

Next, we’ll open the file and write some records.  Note that this is a fixed width file, because there is no DELIMITED WITH clause in our OPEN statement:

OPEN `test.dat` FOR APPENDING.

MOVE `1` TO field_1.

MOVE `test` TO field_2.

WRITE record_var TO test_file.

MOVE `test` TO field_1.

MOVE `1` TO field_2.

WRITE record_var TO test_file.

CLOSE test_file.

The code above would produce the following output in the file test.dat:

1   test`

test1   `

Note that each field inside a fixed width file has, not surprisingly, a fixed width.  Therefore, the second field in the above example always begins in the fifth character of the record, regardless of the size of the first field.

Now let’s take a look at what happens if we append delimited records instead of fixed width ones.  We’ll first modify the original OPEN statement to handle comma-delimited data:

OPEN test_file FOR APPENDING DELIMITED WITH `,`.

Our record should be two bytes larger than the fixed width record to account for the two comma delimiters that will be in each record, so we must also modify the VALUE clause in our bytes_num variable declaration: 

1 bytes_num PIC 99 VALUE 11.

We could also have changed our bytes_num value with a MOVE statement, so long as it preceded our FD.  Either way, with the two above modifications, our code would write the following to test.dat:

 

1,test,   `

test,1,   `

You can see that, unlike the fixed width file, the starting position of each individual field within a delimited record varies. 

Writing to a File by Updating Existing Records

In certain situations, you will probably want to update a record that already exists in a data file without appending an additional record to the file.  To update a record in a data file, you should first open the file for update using the UPDATING keyword, as in:

OPEN test_file FOR UPDATING.

Next, you should perform reads until you have read the record that you wish to update.  Then, using the REWRITE statement, you can overwrite the old record, as in the following:

REWRITE record_variable TO test_file.

Here’s some code that demonstrates this technique more completely:

1 eof          PIC 9 VALUE 0.

1 rec_found    PIC 9 VALUE 0.

1 rec_position PIC 999999.

 

1 test_file PIC X(n) VALUE `TEST.DAT`.

FD test_file record is 9 bytes.

1  record_var.

  5  field_1  PIC X(4).

  5  field_2  PIC X(5).

 

1 customer_of_interest PIC X(n) VALUE `Dave`.

1 new_field_2_val PIC X(n) VALUE `Davie`.

 

OPEN test_file FOR UPDATING.

PERFORM VARYING rec_position FROM 1 BY 1 UNTIL eof OR rec_found

   READ test_file INTO record_var

     AT END MOVE 1 TO eof

   IF field_1 = customer_of_interest

      MOVE 1 TO rec_found

      MOVE new_field_2_val TO field_2

      REWRITE record_var TO test_file

   END-IF

END-PERFORM.

CLOSE test_file.

 

IF eof

   DISPLAY `Customer record of interest was not found.`

END-IF.

Because CobolScript right-pads delimited records with spaces, each record is the exact number of bytes specified in the length argument to the initial FD statement.  This allows any CobolScript data record, whether fixed format or delimited, to be updated in a simple and efficient manner with a simple record overlay, and without requiring any complex file reorganization for each update.  However, if you process a delimited data file created with another application such as a Microsoft ExcelŇ CSV (comma-separated values) file, CobolScript updates to this file will usually not work properly, since each record in the file will have a different byte length (reads and appends to the unmodified file will work correctly, however).  The data must be copied to a different file via a CobolScript program before records can be individually updated.  Here’s an example of a program that does this (available in the sample program RECCOPY.CBL):

 1 input_file PIC X(n) value `INPUT.CSV`.

 FD input_file RECORD IS 100 BYTES.

 1  input_record.

  5  ir_input_1  PIC X(33).

  5  ir_input_2  PIC X(32).

  5  ir_input_3  PIC X(30).

  5  ir_input_4  PIC X.

 

 1 output_file PIC X(n) value `OUTPUT.CSV`.

 FD output_file RECORD IS 100 BYTES.

 1  eof   PIC 9 VALUE 0.

 

 OPEN input_file  FOR READING DELIMITED WITH `,`.

 OPEN output_file FOR WRITING DELIMITED WITH `,`.

 

 PERFORM UNTIL eof

    READ input_file INTO input_record AT END MOVE 1 TO eof

    WRITE input_record TO output_file

 END-PERFORM.

 

 CLOSE input_file.

 CLOSE output_file.

 GOBACK.

Relative and Absolute File Positioning

If you regularly process a large number of records in flat files, you’re probably aware of the time-consuming nature of sequential searches.  As your file sizes increase, sequential search times increase by a proportional amount; if file sizes grow unchecked, search times will eventually become unacceptably long.  In fact, this is perhaps the most critical limitation of flat file databases, and it is what prompts many organizations to opt instead for relational databases, more so than data granularity, manageability, or other considerations.

In CobolScript, flat file search times can be reduced by using the POSITION statement.  This statement positions the file pointer at the beginning of a particular record within a text data file in a single step. If a data file uses a sequential numeric value as the record key value, a record within the file can be randomly (directly) accessed given that key value.

For COBOL developers, the POSITION statement functionality is similar to relative file processing.

POSITION works with standard text data files. The POSITION statement has two forms:

POSITION data_file AT RECORD record_number.

POSITION data_file RELATIVE OFFSET number_of_records.

The record_number value in the AT RECORD clause must be a positive integer in the range:

(1 <= record_number <= total number of records in file)

The record_number value (and hence the number of records in your data file) cannot exceed 2,147,483,647.

The number_of_records value used with the RELATIVE OFFSET clause must be an integer. This value indicates the number of records, counting from the current record, that the file pointer should be moved. Thus, a value of 1 will shift the file pointer one record forward in the data file; a value of –1 will shift the file pointer one record back. The number_of_records value must fall within the absolute range:

        (-2,147,483,647 <= number_of_records <= 2,147,483,647)

Furthermore, a number_of_records value that causes the file pointer to be positioned before the beginning of the data file or after the end of the data file will cause a CobolScript error.

When using the POSITION statement, the number of bytes specified in the BYTES clause of the FD statement for your file must exactly match the number of bytes in the data file record; this value is used to reposition the file pointer, and a BYTES value that is larger or smaller than the actual data record size will cause the file pointer to be incorrectly positioned.

The following POSITION example uses the AT RECORD clause to access a particular record based on a sequential key value. The record is then read and displayed. After this, the file pointer is repositioned to the record prior to the record first read by using the RELATIVE OFFSET clause of POSITION:

1   filename_var  PIC X(n) VALUE `datafile.txt`.

1   bytes_num     PIC 99 VALUE 50.

FD  filename_var  RECORD IS bytes_num BYTES.

 

1   record_variable.

 5  order_nbr     PIC 99999.

 5  data_var      PIC X(45).

 

1   key_val       PIC 99999 VALUE 24331.

 

OPEN filename_var FOR READING.

 

POSITION filename_var AT RECORD key_val.

READ filename_var INTO record_variable.

 

 

 

 

IF order_nbr = key_val

   DISPLAY `For order number ` & order_nbr & `, data = ` & data_var

ELSE

   DISPLAY `Problem with order_nbr values in data file; check file.`

END-IF.

 

POSITION filename_var RELATIVE OFFSET –2.

READ filename_var INTO record_variable.

IF order_nbr = (key_val-1)

   DISPLAY `For order number ` & order_nbr & `, data = ` & data_var

ELSE

   DISPLAY `Problem with order_nbr values in data file; check file.`

END-IF.

CLOSE filename_var.

STOP RUN.

Relational Database Interaction with CobolScript Standard Edition

CobolScript Standard Edition can interact with a relational database if the database supports batch interaction from the system prompt, and if the database is able to direct the output from these batch interactions to ASCII text files.  Ideally, the database will also support stored procedures.  For table inserts, a batch row-loading utility such as Oracle’s SQLLoaderŇ will simplify the job.

We’ve devised a technique for database interaction with CobolScript Standard which we describe further below, but it may not work with your system since every database product is different.

Instead, we recommend you use the LinkMaker feature of CobolScript Professional Edition to embed SQL calls directly into your CobolScript code.  If you have CobolScript Professional, read Appendixes G and H for further information on configuring LinkMaker and embedding SQL directly in your programs.

Note that network security configurations and firewalls may restrict your access to your database across your network.  Even if you have complete access to your database, if you are using your CobolScript engine as a server-side language to complement your web server, you should be careful about which pieces of your database are made visible to the internet through SQL or stored procedure calls, especially if your database has sensitive data in it.

Regarding database security and information protection, in general, these are complicated topics beyond the scope of this manual.  In larger organizations, network and database administration staff should normally be sought out and included in the decision-making process whenever there is the risk, however slight, of revealing sensitive information to the outside world.  Most network administrators will appreciate it if you approach them prior to attempting to implement your idea.

We’ll look at the three main SQL table interactions here (select, insert, and update). We exclude delete because in most production database cases, deletes are best handled by first updating a table row as ‘to be deleted’, and then deleting all such rows later in a batch stored procedure.  Our explanations assume that you are already familiar with SQL and your particular relational database software.  You should also have an understanding of how to write shell scripts for your operating system.

The Unix shell scripts that are included in this section are meant only as conceptual guidelines for your development; the database login portions of these scripts won’t directly work with any one relational database product without at least minor modification.

Selects (Queries)

Select statements come in two forms, from a CobolScript perspective:  Those that have static SQL, and those that require input from a CobolScript program.

Static Selects

Static selects are table queries that don’t require any external parameters.  It is just the SQL statement that remains static in a static query; the query results can change, even if the database remains unchanged between queries.  This is because time constraints can be included in a static query, as in the following SQL statement:

SELECT customer_name

FROM   customer_table

WHERE  last_updated_datetime > (NOW – 1)

Assuming that the database is capable of converting the expression ‘NOW – 1’ into the datetime equivalent of 24 hours prior to now, there is no need for this query to incorporate external inputs.  A Unix shell script that directs the output of this static query to a text file would look something like the script below:

#!/bin/ksh

sqllogin ‘userid/passwd’ <<EOF >queryresult.dat

   SET HEADING OFF

   SET ECHO OFF

   SET BREAK OFF

   WHENEVER SQLERROR pkg_output.screen_write(‘Database error’|SQLERROR)

 

   SELECT customer_name

   FROM   customer_table

   WHERE  last_updated_datetime > (NOW – 1)

   EOF

Two different approaches can be used to gather the result set from a static query inside a CobolScript program:

·         The first approach is to run the query script in batch mode (on a daily basis, for instance) outside of the CobolScript program.  Then, the CobolScript program only needs to open the data file and process the data.  This approach puts the least strain on the database and on your system, and returns a query result in the quickest time.  The drawback to this method is that the data is not current at the time the CobolScript program is executed.

·         Alternatively, you can call the shell script from within a CobolScript program using the CALL statement, and then open and read the resulting data from the shell script’s output file using normal file processing methods.  Here’s some code that does this, along with a minor bit of code that takes advantage of the error trapping included in the above shell script.  Assume the shell script above is named query.sh, and is in the same directory as our CobolScript engine:

CALL `query.sh >error.txt`.

 

OPEN `error.txt` FOR READING.

READ `error.txt` INTO ERROR-REC AT END MOVE `Y` TO WS-EOF.

CLOSE `error.txt`.

MOVE `N` TO WS-EOF.

 

IF ERROR-REC(1:14) = `Database error` THEN

   DISPLAY ERROR-REC

ELSE

   OPEN `queryresult.dat` FOR READING

   PERFORM UNTIL WS-EOF = `Y`

      READ `queryresult.dat` INTO QUERY-REC AT END MOVE `Y` TO WS-EOF

      DISPLAY QUERY-REC

   END-PERFORM

   CLOSE `queryresult.dat`

END-IF.

STOP RUN.

The results returned by this approach are essentially real-time.  The drawback to this type of query is that it accesses the database every time this program is run.

Dynamic Selects

Dynamic selects are table queries that require external parameters, as in the following SQL statement:

SELECT customer_name

FROM   order_table

WHERE  customer_id = $customer_id_var

AND    order_number > $order_number_var

Here, the fields $customer_id_var (the value assigned to the shell script variable customer_id_var) and $order_number_var are passed in to the query from an external source (in this case, the shell script).

Here’s our new shell script to handle the above query:

#!/bin/ksh

customer_id_var=$1

order_number_var=$2

sqllogin ‘userid/passwd’ <<EOF >queryresult.dat

   SET HEADING OFF

   SET ECHO OFF

   SET BREAK OFF

   WHENEVER SQLERROR pkg_output.screen_write(‘Database error’|SQLERROR)

 

 

   SELECT customer_name

   FROM   order_table

   WHERE  customer_id = $customer_id_var

   AND    order_number > $order_number_var

   EOF

This script is dependent on two input parameters ($1 and $2), which are then assigned to our two variables.  The variable values are inserted into the WHERE clause, thereby changing our query condition and result based on external values.

Unlike static queries, dynamic selects must always be performed at the time the calling program is run, since their result set depends directly on parameters passed in from the calling program.  Here’s a portion of the CobolScript code to call the above shell script:

 MOVE `‘101101’`  TO cust_id.

 MOVE `22345`   TO order_nbr.

 

* We build our CALL argument below.  All of the following target

* variables are assumed to be components of the group item

* input_group.

 MOVE `query.sh `   TO input_arg_1.

 MOVE cust_id       TO input_arg_2.

 MOVE ` `           TO input_arg_3.

 MOVE order_nbr     TO input_arg_4.

 MOVE ` >error.txt` TO input_arg_5.

 

* At this point, input_group has a literal value of

* `query.sh ‘101101’ 22345 >error.txt`.  The two literals that follow

* query.sh are our two shell script parameters that will be used

* inside the WHERE clause of the query.

 CALL input_group.

 

 OPEN `error.txt` FOR READING.

 READ `error.txt` INTO error_rec AT END MOVE 1 TO eof.

 CLOSE `error.txt`.

 MOVE 0 TO eof.

 

 IF error_rec(1:14) = `Database error` THEN

    DISPLAY error_rec

 ELSE

    OPEN `queryresult.dat` FOR READING

    PERFORM UNTIL eof

       READ `queryresult.dat` INTO query_rec AT END MOVE 1 TO eof

       DISPLAY query_rec

    END-PERFORM

    CLOSE `queryresult.dat`

 END-IF.

 STOP RUN.

By building the CALL argument in this manner, you can easily pass the values in CobolScript variables as parameters to shell scripts.  These parameters can then be used in select statement conditions that are inside the shell script.

Inserts

We’ll be doing database inserts a bit differently than we handled queries, since inserts tend to be involve much more text input than dynamic select statements do.

A batch ASCII file loading utility will simplify the task of inserting database rows from CobolScript input.  The insert example that we give below assumes that such a utility is available for you to use.

Here’s the important CobolScript code for our insert:

 FD `order.dat` RECORD IS 57 BYTES.

 1  order_rec

  5  rec_cust_id           PIC X(10).

  5  rec_order_nbr         PIC 9(6).

  5  rec_order_val         PIC 99999.99.

  5  rec_tax_val           PIC 99999.99.

  5  rec_salesperson_nbr   PIC 9(5).

  5  rec_date_and_time_val PIC X(14).

 

 1  order_info.

  5  cust_id           PIC X(10).

  5  order_nbr         PIC 999999.

  5  order_val         PIC 99999.99.

  5  tax_val           PIC 99999.99.

  5  salesperson_nbr   PIC 99999.

  5  date_and_time_val.

    10  date_val        PIC X(8).

    10  time_val        PIC X(6).

 

* First we assign our values to be inserted.  This is a simplification;

* It’s likely that you would first collect at least some of this data

* from the user on a web page form or from keyboard input.

 MOVE `‘101101’`  TO cust_id.

 MOVE `22345`     TO order_nbr.

 MOVE 199.95      TO order_val. 

 MOVE 12.90       TO tax_val.

 MOVE 1226        TO salesperson_nbr.

 ACCEPT date_val  FROM DATE.

 ACCEPT time_val  FROM TIME.

 

 MOVE order_info TO order_rec.

 

 OPEN `order.dat` FOR WRITING DELIMITED WITH `,`.

 WRITE order_rec TO `order.dat`.

 CLOSE `order.dat`.

 

 CALL `sqlins configfile.txt order.dat >loadinfo.txt`.

 DISPLAYASCIIFILE `loadinfo.txt`.

 STOP RUN.

Most batch loading utilities take a configuration file input and produce one or several file outputs.  Normally, the configuration file names all the other files involved, such as the input data file, the output information file, and an output ‘bad’ record file that contains all data records that were not successfully inserted in the.  In the CALL statement above, however, we include the order.dat and loadinfo.txt files to enhance your understanding of this operation, since we don’t provide a configuration file example.

Consult your load utility’s documentation for information on how to construct the load configuration file.

Updates

Database updates are perhaps the most code-intensive operations to perform using CobolScript.  The technique we employ to do updates uses portions of both our dynamic select and our insert operation techniques.

We’ll use the following update statement as our starting point:

UPDATE order_table

SET  customer_name    = $customer_name_var

    ,order_val        = $order_val_var

    ,salesperson_nbr  = $salesperson_nbr_var

    ,update_timestamp = TO_DATE(‘DDMMYYYYhh24miss’, $date_and_time_val)

WHERE  customer_id   = $customer_id_var

AND    order_number  = $order_number_var

As was the case in our dynamic select example, the fields that are preceded by a $ sign are passed in to the update statement as shell script variable values.  This time, however, we’ll use an interim file to transfer these variables from the CobolScript program to the shell script, rather than pass all of these variables as parameters to the shell script.

The new shell script will extract all of our relevant variables from a data file that we generated in CobolScript.  Since we’re looking at the shell script before we examine our CobolScript program, assume for now that the data file update.dat is a comma-delimited file that contains our field data in a single record, and in the following order:

customer_name_var,order_val_var,salesperson_nbr_var,date_and_time_val,customer_id_var,order_number_var

 

The shell script is below.  Note that we’ve chosen to use the Unix cut command to extract our CobolScript variable values from update.dat.  Consult your man pages for an explanation of this command:

#!/bin/ksh

customer_name_var=`cut –f 1 –d ‘,’ update.dat`

order_val_var=`cut –f 2 –d ‘,’ update.dat`

salesperson_nbr_var=`cut –f 3 –d ‘,’ update.dat`

date_and_time_val=`cut –f 4 –d ‘,’ update.dat`

customer_id_var=`cut –f 5 –d ‘,’ update.dat`

order_number_var=`cut –f 6 –d ‘,’ update.dat`

 

sqllogin ‘userid/passwd’ <<EOF >updateresult.dat

   SET HEADING OFF

   SET ECHO OFF

   SET BREAK OFF

   WHENEVER SQLERROR pkg_output.screen_write(‘Database error’|SQLERROR)

 

   UPDATE order_table

   SET  customer_name    = $customer_name_var

       ,order_val        = $order_val_var

       ,salesperson_nbr  = $salesperson_nbr_var

       ,update_timestamp = TO_DATE(‘DDMMYYYYhh24miss’,

                                    $date_and_time_val)

   WHERE  customer_id   = $customer_id_var

   AND    order_number  = $order_number_var

   EOF

And here’s our CobolScript code to call the above shell script.  Assume that the shell script is named update.sh and is located in the working directory of the CobolScript program:

 FD `update.dat` RECORD IS 59 BYTES.

 1  order_rec.

  5   customer_name_var     PIC X(10).

  5   order_val_var         PIC 99999.99.

  5   salesperson_nbr_var   PIC 9(5).

  5   date_and_time_val     PIC X(14).

  5   customer_id_var       PIC X(10).

  5   order_number_var      PIC 9(6).

 1  order_info.

  5   customer_name_var     PIC X(10).

  5   order_val_var         PIC 99999.99.

  5   salesperson_nbr_var   PIC 9(5).

  5   date_and_time_val.

   10  date_val        PIC X(8).

   10  time_val        PIC X(6).

  5   customer_id_var       PIC X(10).

  5   order_number_var      PIC 9(6).

 

* First we assign our values to be updated.  This is a simplification;

* It’s likely that you would first collect at least some of this data

* from the user on a web page form or from keyboard input.

 MOVE `Larry Melman` TO customer_name_var.

 MOVE 199.95         TO order_val_var. 

 MOVE 1226           TO salesperson_nbr_var.

 ACCEPT date_val     FROM DATE.

 ACCEPT time_val     FROM TIME.

 MOVE `‘101101’`     TO customer_id_var.

 MOVE `22345`        TO order_number_var.

 

 MOVE order_info TO order_rec

 OPEN `update.dat` FOR WRITING DELIMITED WITH `,`.

 WRITE order_rec TO `update.dat`.

 CLOSE `update.dat`.

 

* Since all of our variables were written to a file to be used by the

* shell script, we don’t pass any parameters to the shell script when

* we call it.

 CALL `update.sh>error.txt`.

 

 OPEN `error.txt` FOR READING.

 READ `error.txt` INTO error_rec AT END MOVE 1 TO eof.

 CLOSE `error.txt`.

 MOVE 0 TO eof.

 IF error_rec(1:14) = `Database error` THEN

   DISPLAY error_rec

 ELSE

   DISPLAYASCIIFILE `updateresult.dat`.

 END-IF.

 STOP RUN.

Although the code for the update technique is a bit more involved than the code for our select and insert techniques (primarily because we use a data file interface with the shell script in the update, rather than passing parameters to the script), it’s still relatively straightforward.  Of course, if you don’t exceed the shell script parameter limit, an update script can still be called using parameters, just like the dynamic select example.

 

Chapter

5


Building Web-Based Systems

T

icon key

his chapter will describe techniques that can be used for building web-based systems with CobolScript.  Since CobolScript is an interpreted language, it lends itself well to the debugging and tweaking that are often necessary when outputting HTML documents.  You’ll find that it’s very easy to write small pieces of CobolScript code and then run and re-run the code in your web browser to see if you get the desired results.  CobolScript also has syntax specifically designed to simplify and quicken the development of web systems, such as the ACCEPT DATA FROM WEBPAGE statement, the GETENV command, and the GETWEBPAGE command, all of which are described in this chapter.

Ü  Important point

If you’re still confused about why you need a language other than HTML to create web pages, the answer is that you don’t, if all that you’re interested in doing is displaying static web pages.  However, if you want your site visitors to interact with your web pages in any way; if you want to display or not display certain HTML based on conditions; or if you want to build a web-based system, then a programming language like CobolScript, not just a markup language like HTML, is required.  Furthermore, as you become more familiar with web programming., you will discover that using a web server and standard browsers to run CobolScript web-based systems that are internal to your organization (intranets) can be an efficient and economical alternative to systems that have a client-side component that must be individually installed and managed on each user’s machine.

CobolScript normally communicates with a web server through CGI (the Common Gateway Interface).  The Common Gateway Interface is a type of protocol; it defines a  method of interaction between the web server and external programs, which are normally run by the web server in only two situations:

·         When a form on an active web page is submitted;

·         When a URL that calls a program (as opposed to a URL that calls a static web page) is typed into the Location: text box, or its equivalent, in a browser.

When data from a web page is sent to a CobolScript program, the data is encoded in accordance with the CGI protocol.  The CobolScript engine can automatically decode this data stream when it has been submitted via the Post method and place each field of data in a corresponding CobolScript variable.  This makes CobolScript a very easy programming language to use for web and internet development.  Instead of building interfaces to web servers, you can focus your programming efforts on the business logic that belongs in your code.

To run the program examples in this chapter, or to run any CobolScript web programs, for that matter, you must have access to a web server.  You must also have installed the CobolScript engine on the same machine as your web server software, ideally in the web server’s cgi-bin directory.  If you have installed the CobolScript engine on your PC, you can install web server software on your PC as well, which will allow you to test your web development code without uploading it to a different machine.  By using a web server on your own PC, you won’t even need an internet or network connection to run your code.  The Apache web server and derivatives work well for Unix platforms, and OmniHTTPd is a good web server for WindowsŇ.  Both are free.  For further information on how to install CobolScript for use with a web server, see the Installing CobolScript section of Chapter 1, Introduction to CobolScript/Installation Instructions.  Refer to the section Running CobolScript from a Web Server and Browser in Chapter 2, Getting Started with CobolScript, for general information on steps you must take for your programs to be capable of being run from a browser.

Interacting with a Web Server and Web Browser

Figure 5.1 provides a (simplified) representation of the normal methods by which CobolScript interacts with a web server and browsers.  The browser sends data to the server when a CGI form is submitted or a free-text URL calling a program is completed, and this information is then passed directly from the server to CobolScript.  The CobolScript engine interprets the inputs and makes them available to your CobolScript program.  Your program then creates custom web page content, either based on the browser inputs or other information, and delivers this content back to the browser (actually, this delivery is done via the web server, but this interaction is excluded from the diagram for the sake of clarity) in the form of virtual HTML.  Virtual HTML differs from static

Figure 5.1 – A representation of CobolScript program interactions with a web browser and web server.

HTML in that virtual HTML is HTML code that has been output by a program, while static HTML resides in an independent HTML file.  There is no syntactical difference between the two.

Creating Virtual HTML

Creating a virtual HTML document is simply a matter of displaying valid HTML to standard output.  The example program below, which we’ll call hello1.cbl, is very simple CobolScript code that will do just this, without any conditions or input processing.

To run the example, first place it in your web server’s cgi-bin directory.  Then, if you are running your browser and your web server on the same machine, and 127.0.0.1 is your web server’s loopback address (the IP address that a machine typically uses to refer to itself), execute the program by typing http://127.0.0.1/cgi-bin/cobolscript.exe?hello1.cbl  in your browser’s URL window.  If your web server is on a different machine than your browser but you know your server IP address, just substitute that address for 127.0.0.1.

You can also run this program from a command line by simply typing the following at the command prompt:

cobolscript.exe hello1.cbl

This will display the raw HTML output to your command line screen.

Here’s the hello1.cbl code:

DISPLAY `Content-type: text/html `.

DISPLAY LINEFEED.

DISPLAY `<HTML><BODY>`.

DISPLAY `<CENTER>Hello World</CENTER>`.

DISPLAY `</BODY></HTML>`.

GOBACK.

You can see that the first text we display is the MIME header, which is this exact literal:

`Content-type: text/html`

Ü

This is followed immediately by the display of a LINEFEED character.  Displaying a MIME header, followed by a linefeed, indicates to the web server that the program output that will follow the header will be a certain MIME type of input.  In this case (and in the vast majority of your CGI programming), the MIME type is text/html, which means that we intend to output HTML content.  The web server will recognize this MIME type and pass the remainder of our output on to the browser as HTML.

It’s very important to remember to display the correct MIME header, followed by a line with only a linefeed, in the beginning of your CobolScript CGI programs.  Failing to do this may prevent anything at all from displaying in your browser when you attempt to run your programs; depending on how your web server is configured, you may or may not get an appropriate error message in your browser window.

After the program has displayed all of the HTML (which is then transferred by the web server to the browser), it executes the GOBACK command to terminate processing, and your browser window will have the phrase “Hello World” in it. 

Creating an HTML Form

If you want to create a web page that will allow your users to enter data, the simplest way to do this is by using an HTML form.  Forms allow you to create text boxes, text areas, list boxes, check boxes, and radio buttons to collect data, reset buttons to clear data entries, and submit buttons to submit the data to a receiving program.  See Chapter 7 for a detailed discussion on how to use each of the form components in programs.

The FORM tag, along with its end tag, are used to demarcate the form, which is essentially a data input area inside an HTML document.  Every form has an associated action; this action is specified in the ACTION component of the FORM tag.  The ACTION argument is an URL that names a CGI program that will be executed when the browser user submits the form.  In the case of the program below, which we’ll name hello2.cbl, the action is /cgi-bin/cobolscript.exe?hello2.cbl.  In this example, when you submit the form on your web browser, it will run the hello2.cbl program again.  Of course, since incoming data is not processed by this program, the data typed in the text box is lost after the form is submitted.

Here’s the code for hello2.cbl:

DISPLAY `Content-type: text/html`.

DISPLAY LINEFEED.

 

DISPLAY `<HTML><BODY>`.

DISPLAY `<CENTER>Hello World</CENTER>`.

DISPLAY `<FORM ACTION=”/cgi-bin/cobolscript.exe?hello2.cbl” `

        & `METHOD=POST>`.

DISPLAY `<INPUT TYPE=TEXT NAME=”my_variable”>`.

DISPLAY `<INPUT TYPE=SUBMIT VALUE=”Click here to Submit”>`.

DISPLAY `</FORM>`.

DISPLAY `</BODY></HTML>`.

 

GOBACK.

The program above uses a simple text box (created by INPUT TYPE=TEXT) to collect information.  You’ll notice that the text box has a NAME argument associated with it, and that the name is my_variable; this is the CGI field name.  The CGI field name is the name of a CGI variable that will hold the contents of the text box when the form is submitted from the web page.

Capturing Input Data from a Web Page

At this point, you’re probably wondering how the data from the CGI variable gets into a variable in a CobolScript program.  In CobolScript, when your program needs to get form data from a web page, you just use a special form of the ACCEPT statement called ACCEPT DATA FROM WEBPAGE.  Here’s an example: 

ACCEPT DATA FROM WEBPAGE.

This command will get the CGI data that was submitted, parse it, decode it, and place the contents in CobolScript variables that have the same names as the incoming CGI variables.

To accept data from a CGI form into a CobolScript program, you must define variables to capture the contents of the incoming CGI variables.  The CobolScript variables must have the same names as the CGI variables.  The program in this section, which we’ll call hello3.cbl, accepts a CGI variable called “my_variable” into a like-named CobolScript 40 byte alphanumeric variable that we’ll define here:

1 my_variable     PIC X(40).

1 content_length  PIC 9(05).

If you look at our hello3.cbl code segment below, you’ll notice that we use the GETENV command before we accept the CGI data from the web page.  This command gets the value of the web server environment variable that is specified as the GETENV argument and places its contents into a CobolScript variable.  The environmental variable CONTENT_LENGTH holds the CGI query string’s actual length.  The query string is the raw data stream that the POST method uses to send data to a target program, so if this the length of this string is greater than zero, we know that there is data to accept.  It’s good practice to get the value of CONTENT_LENGTH at the beginning of your CobolScript program, because by doing this, you know whether or not there is CGI data waiting for you to process.  If the value of CONTENT_LENGTH is zero, then you know that the user is simply running your web based application for the first time and has not submitted a form on it.  If CONTENT_LENGTH is greater than zero, then you know that the user has submitted a form from your application.

The ACCEPT DATA FROM WEBPAGE command handles all of the parsing of the POST method-submitted data internally, so you don’t have to worry about decoding the CGI data passed to the web server.

Here’s the rest of the code for hello3.cbl: 

GETENV USING `CONTENT_LENGTH` content_length.

IF content_length > 0

   ACCEPT DATA FROM WEBPAGE

END-IF.

 

DISPLAY `Content-type: text/html`.

DISPLAY LINEFEED.

DISPLAY `<HTML><BODY>`.

DISPLAY `<CENTER>Hello World</CENTER>`.

DISPLAY `my_variable: ` & my_variable.

 

DISPLAYLF `<FORM ACTION=”/cgi-bin/cobolscript.exe?hello3.cbl” `

         & `METHOD=”POST”>`

DISPLAY `<INPUT TYPE=”TEXT” NAME=”my_variable” VALUE=”`

        & my_variable & `”>`.

DISPLAYLF `<INPUT TYPE=”SUBMIT” VALUE=”Click here to Submit”>`

DISPLAYLF `</FORM>`.

DISPLAY `</BODY></HTML>`.

Again, if CONTENT-LENGTH is greater than zero, there is CGI data waiting to be accepted, and therefore the ACCEPT DATA FROM WEBPAGE statement should be executed.  This statement will look at the CGI data stream being sent from the web server, decode it, and match the CGI form variable names with CobolScript variable names.  That is why both the CobolScript variable and the form field are named my_variable.  Because these two names correspond, the data associated with the form field my_variable will be moved to the contents of the CobolScript variable my_variable.  All decoding and parsing of the CGI data stream is performed automatically. 

Ü

Important note: The maximum elementary variable size in CobolScript is 2,000 bytes.  If you happen to have an individual CGI field that has contents greater than 2,000 bytes, only the first 2,000 bytes of data will be stored in any target CobolScript variable that is an elementary data item.  The rest will be truncated.

DISPLAY and DISPLAYLF

The DISPLAY and DISPLAYLF commands differ most significantly in the way they handle group items.  This has special relevance in the context of CGI development, since you may or may not want your HTML output to have line breaks in it that makes it more readable.  The differences in the two are:

·         The DISPLAY command will print a literal or the contents of any variable to standard output.  After all of the arguments to DISPLAY have been displayed, a linefeed character displays, terminating the output.  In the case of a group-level data item DISPLAY, all individual components of the group item will print on the same line.

·         The DISPLAYLF command will print a literal or the contents of a variable to standard output, followed by an ASCII line feed character between each individual component of a group-level data item, or each individual argument, if multiple arguments are specified.  After all of the arguments have been displayed, another linefeed character is displayed to complete the output.

Let’s take a look at how DISPLAY and DISPLAYLF each display the following group-level data item.  Note the use of the Implied PIC X(n) FILLER variables (explained in the Variables section of Chapter 3):

1 form_var.

 5 `<FORM ACTION=cobolscript.exe?test.cbl METHOD=POST>`.

 5 `<INPUT TYPE=TEXT NAME=field1>`.

 5 `<INPUT TYPE=SUBMIT VALUE=Submit>`.

 5 `</FORM>`.

The statement DISPLAY form_var will produce the following output (all on a single line):

<FORM ACTION=cobolscript.exe?test.cbl METHOD=POST><INPUT TYPE=TEXT NAME=field1><INPUT TYPE=SUBMIT VALUE=Submit></FORM>

 

 

 

The statement DISPLAYLF form_var will produce the following output:

<FORM ACTION=cobolscript.exe?test.cbl METHOD=POST>

<INPUT TYPE=TEXT NAME=field1>

<INPUT TYPE=SUBMIT VALUE=Submit>

</FORM>

Retrieving Web Pages

If you ever need to build an application that retrieves web pages, you can use the GETWEBPAGE command.  It connects to a web server, retrieves a given web page, and saves it to a user-specified file.

The program below called WEB.CBL demonstrates the usage of the GETWEBPAGE command.  It utilizes a standard data structure called TCPIP-RETURN-CODES.  This group level data item will be populated with information from the specific web server you are accessing.  TCPIP-RETURN-CODE is a number, while TCPIP-RETURN-MESSAGE is a string.  Typically a successful return code for this operation will be zero, and the return message will contain a string describing the number of bytes received for a particular web document.

Here’s a portion of the code for WEB.CBL:

1 TCPIP-RETURN-CODES.

 5 TCPIP-RETURN-CODE     PIC 9(07).

 5 TCPIP-RETURN-MESSAGE  PIC X(255).

MOVE `www.deskware.com` TO host_name.

MOVE `/cobol/cobol.htm` TO web_page_name.

MOVE `web.txt` TO file_name.

DISPLAY `<` host_name `>`.

DISPLAY `<` web_page_name `>`.

DISPLAY `<` file_name `>`.

GETWEBPAGE USING host_name web_page_name file_name.

DISPLAY `TCPIP-RETURN-CODES: ` TCPIP-RETURN-CODES.

GOBACK.

The host name in this example is a fully qualified domain name – www.deskware.com.  It is also acceptable to specify a raw IP address as the host name argument.  The file name argument is used to create a file with the HTML that you are retrieving.  The named file is overwritten each time the GETWEBPAGE command is executed.


 

 

 

 

Chapter

6


Network and Internet Programming Using CobolScript®

W

icon key

Ü  Important point

hile a combination of static HTML pages and basic CGI programs written in nearly any programming language can address the on-line requirements of internet information systems, few languages can satisfactorily address the interface and networking requirements of internet systems, at least not without compromising platform independence.  With CobolScript, however, you can transfer files, receive and deliver email messages, and conduct point-to-point communications with other computers, all by using standard CobolScript commands.  Because these commands all use the TCP/IP protocol or extensions such as FTP, SMTP, and HTTP, cross-platform communication is handled the same way as same-platform communication.

This chapter provides some basic examples of how to transfer files, send and receive emails, and program TCP/IP sockets.  By learning and expanding on these examples, you will be able to create, in CobolScript code, the interfaces that your system requires.

Transferring Files using FTP

Sharing files is one of the fundamental motivations for networking computers.  FTP (File Transfer Protocol) is a protocol for transferring files over a TCP/IP network.  FTP is an effective way to share data between heterogeneous network hosts.  CobolScript has commands that allow you to program FTP clients to transfer files to and from FTP servers.

Most computers on the Internet support FTP access.  Before you can build a program that will access files on these FTP servers, however, you will need the following:

·         The name of the system on the network that has the files you want to obtain, or on which you want to place files.  In other words, you need to know the fully qualified domain name or IP address of the host that you want to transfer files from and to.

·         A valid user name and password to use on the remote computer.  Many remote computers will allow anonymous ftp, which allows you restricted FTP access by using the user name anonymous and your email address as the password. 

FTP is extremely useful for transmitting data rapidly between sites that need to share information system data.  Using FTP eliminates many usual considerations when transferring files.  By using FTP:

·         You won’t need to worry about requiring both hosts to use the same types of disks or tapes to transfer files;

·         You won’t have to break up a file into several smaller files because the larger file won’t fit on a single disk or as an email attachment. 

CobolScript programs that transfer files using FTP commands can be scheduled to run at regular time intervals.  This is allows you to have unattended file transfers between hosts.  

When you try to connect to a remote computer using FTP, you will need to supply a valid user name and password.  The CobolScript command FTPCONNECT is the command you should use to login to an FTP server.  Here’s an example:

MOVE `deskware.com` TO host_name.

MOVE `anonymous` TO user.

MOVE `interpreter@deskware.com` TO password.

 

FTPCONNECT USING host_name user password.

After you have connected to an FTP server, you should set the transfer type.  This is done with the FTPASCII or FTPBINARY commands.  If you will be transferring plain ASCII text files, you should use FTPASCII.  By doing this, the server knows to convert the files to an ASCII format that your client computer can read.  This is important because ASCII files on Windows machines are line terminated with carriage return and line feed ASCII characters, and on Unix-based machines, ASCII files are line terminated with only line feed characters.  If you are connecting to a mainframe, text files are stored in EBCDIC format.  Using the FTPASCII command before you transfer text files will ensure that you receive them in the ASCII format that is native to your client machine.  Using the FTPASCII command is as simple as the following statement:

FTPASCII.

If you need to transfer binary data such as word processing documents or spreadsheet files, you should use the FTPBINARY command before transmitting files.  This ensures that no ASCII translation is performed on your file during the transfer. 

Another useful command is FTPCD.  It allows you to change the directory on the FTP server that you are connecting to.  Here’s an example:

 

FTPCD USING `\ftp\data\interfaces`.

You should make sure that you use the correct directory naming structure for the FTP host that you are connecting to.  The above example is a directory name on a Unix based host.  If it were a Windows based server, you might use something like `C:\datafiles\output`, or on a mainframe you might use `’idy2v.data.acct’`.

The FTPGET and FTPPUT commands actually perform the file transfer operations.  You should use FTPGET to get a file from an FTP server, and FTPPUT to send a file to an FTP server.  Here are examples of these commands in complete statements:

 

FTPGET USING `order.dat`.          

DISPLAY `FTPGET TCPIP-RETURN-CODES: ` & TCPIP-RETURN-CODES.

FTPPUT USING `order.dat`.          

DISPLAY `FTPPUT TCPIP-RETURN-CODES: ` & TCPIP-RETURN-CODES.

Using Email Commands

Although you may never have thought of email as a system interfacing tool, this is in fact what it is, because email allows users to send and receive messages from a local machine to recipients on destination hosts, regardless of platform.  Even if the email message is only textual, and is only meant to be read by the recipient and not cause any direct system action, the delivery and receipt of the email constitute a system interface.

A standard email message without attachments is simply a text file, made up of header lines that tell an email server how to deliver the message, and of the message content. 

SMTP is an acronym for Simple Mail Transfer Protocol and POP3 for Post Office Protocol 3; they are the standard TCP/IP protocols for sending email and receiving email, respectively.  CobolScript uses these protocols in its email commands, which enable the sending and receiving of simple email messages.

To use CobolScript to build programs that send email messages, you will need access to an SMTP server.  Once you have this, you can use the CobolScript SENDMAIL command to send email.  Here’s an example:

COPY `tcpip.cpy`.

1 to_addresses.

 5  `<nobody1@ttttt.com>`.

 5  `Nobody <nobody2@ttttt.com>`.

 5  `nobody3@ttttt.com`.

 

1 from_address PIC X(n) VALUE `youremail@yourhost.com`.

1 subject PIC X(n) VALUE `mail.cbl test`.

 

1 message.

 5 `This is a test message from mail.cbl.`.

 5 FILLER PIC X VALUE LINEFEED.

 5 `Sent from me to you.`.

 

1 smtp_server PIC X(n) VALUE `yoursmptserver.com`.

 

SENDMAIL USING to_addresses

               from_address

               subject

               message

               smtp_server.

DISPLAY `TCPIP-RETURN-CODES: ` & TCPIP-RETURN-CODES.

Of course, you would substitute your addresses and message for the above addresses and message.

With CobolScript there are two commands for retrieving email messages, GETMAILCOUNT and GETMAIL.  The GETMAILCOUNT command connects to your mail server and determines the number of messages in your inbox.  The GETMAIL command retrieves a copy of a specific email message and saves its contents to a text file.  GETMAIL does not remove the email message from the server.  Here is an example of how to use these commands:

MOVE `youremail@yourhost.com` TO email_address.

MOVE `yourpassword` TO email_password.

MOVE 0 TO email_count.

 

GETMAILCOUNT USING email_address

                   email_password

                   email_count

                   smtp_server.

DISPLAY `Email count: ` & email_count.

DISPLAY `TCPIP-RETURN-CODES: ` & TCPIP-RETURN-CODES.

           

MOVE `youremail@yourhost.com` TO email_address.

MOVE `yourpassword` TO email_password.

MOVE 1 TO email_number.

MOVE `mymail.txt` TO email_file_name.

GETMAIL USING email_address

              email_password

              email_number

              email_file_name

              smtp_server.

DISPLAY`TCPIP-RETURN-CODES: ` & TCPIP-RETURN-CODES.

Ü

When the GETMAIL command retrieves an email message from a server, it appends the message to the specified text file.  This means that if you want to retrieve a copy of all of your email messages, you should use GETMAILCOUNT to find out how many messages there are, and then perform a loop that retrieve each message.  If you want each message to be in a separate text file, you should use a new text file name each time you call GETMAIL.


Important Note: When you are sending emails it is important to use a valid SMTP server.  Generally it works best if your applications send all emails through your SMTP server, and then your SMTP server delivers the email to the user.

 

 

 

 

 

Using TCP/IP Commands

Several TCP/IP commands are available in CobolScript.  They can be used for socket programming and obtaining DNS information about a host.  They are:

·         GETHOSTNAME

·         GETHOSTBYNAME

·         CREATESOCKET

·         BINDSOCKET

·         LISTENTOSOCKET

·         CONNECTTOSOCKET

·         ACCEPTFROMSOCKET

·         RECEIVESOCKET

·         SENDSOCKET

·         SHUTDOWNSOCKET

·         CLOSESOCKET

DNS Commands

The program below (which is the DNS.CBL sample program) demonstrates how to use the GETHOSTBYNAME command.  You can run this program from your web browser by typing in the URL http://127.0.0.1/cgi-bin/cobolscript.exe?dns.cbl if you are running CobolScript and a web server on your local machine.

Both GETHOSTNAME and GETHOSTBYNAME require two special group level data items – TCPIP-HOSTENT and TCPIP-RETURN-CODES. These data structures are placeholders for return values that are populated when these commands are executed.  The structures must be in your program in order for it to run properly when you use these commands. 

GETHOSTNAME gets the TCP/IP hostname from your local machine and place the name in a CobolScript variable.  The GETHOSTBYNAME  is a much more advanced command.  It contacts your DNS (Domain Name Server) and retrieves detailed information about a specified host name.  It retrieves information such as aliases and host addresses associated with a particular domain name.  Try running this example with some domain names like lycos.com or yahoo.com.

Here are the variable definitions for DNS.CBL.  Note the two standardized TCP/IP structures that we mentioned earlier.  These would normally just be placed in a copybook by themselves, such as tcpip.cpy, but we include them here to show their detail:

 

 

 

 

**************************************

*             TCP/IP                 *

*          DATA STRUCTURES           *

**************************************

* GETHOSTBYNAME REQUIRES THE DATA    *

* STRUCTURE BELOW.  DO NOT CHANGE IT.*

**************************************

 01 TCPIP-HOSTENT.

  05 TCPIP-HOSTENT-HOSTNAME                   PIC X(255).

  05 TCPIP-HOSTENT-NUM-ALIASES                PIC X.

  05 TCPIP-HOSTENT-ALIASES OCCURS 8 TIMES.

   10 TCPIP-HOSTENT-ALIAS                     PIC X(255).

  05 TCPIP-HOSTENT-ADDRESS-TYPE               PIC 9(7).

  05 TCPIP-HOSTENT-ADDRESS-LENGTH             PIC 9(7).

  05 TCPIP-HOSTENT-NUM-ADDRESSES              PIC X.

  05 TCPIP-HOSTENT-ADDRESSES OCCURS 8 TIMES.

   10 TCPIP-HOSTENT-ADDRESS                   PIC X(255).

**************************************

* TCP/IP RETURN CODES DATA STRUCTURE *

* DO NOT CHANGE.                     *

**************************************

 01 TCPIP-RETURN-CODES.

  05 TCPIP-RETURN-CODE                        PIC 9(7).

  05 TCPIP-RETURN-MESSAGE                     PIC X(255).

 

* Program-specific variables

**************************************

 1 content_length   PIC 9(05).

 

 1 web_header_html.

  5 `Content-type: text/html`.

  5 ` `.

  5 `<HTML><BODY>`.

  5 `<BR>`.

  5 `<B>Sample CobolScript DNS Application</B>`.

  5 `<BR><BR>`.

  5 `Enter a Fully Qualified Domain Name or an IP address and then`

  5 ` click on the Resolve button.`.

  5 `<FORM ACTION="/cgi-bin/cobolscript.exe?dns.cbl" METHOD="POST">`.

  5 `<INPUT TYPE="TEXT" NAME="host_name" SIZE=60 VALUE="`.

  5 host_name  PIC X(80) VALUE `www.cornell.edu`.

  5 `">`.

  5 `<INPUT TYPE="SUBMIT" VALUE="Resolve">`.

  5 `</FORM>`.

  5 `<HR>`.

1 web_footer_html.

  5 `</BODY></HTML>`.

Here’s our main paragraph of code for DNS.CBL.  Since we’re running this program from a browser, we first use the GETENV statement to determine whether we have input or not (see Chapter 5) and the output that we display is HTML:

 MAIN.

    GETENV USING `CONTENT_LENGTH` content_length.

 

    IF content_length > 0

       ACCEPT DATA FROM WEBPAGE

    END-IF.

 

    IF host_name = SPACES

       MOVE `www.cornell.edu` TO host_name

    END-IF.

 

* Populate TCP/IP structure that is defined in included copybook.

    GETHOSTBYNAME USING host_name.

 

    DISPLAYLF web_header_html.

    PERFORM DISPLAY-TCPIP-INFO.

    DISPLAYLF web_footer_html.

 

    GOBACK.

The code module below displays each of the TCP/IP variables that are populated by the call to GETHOSTBYNAME, in an HTML table format.  We’re excluding most of this module’s code from here because of its repetitive nature, but the entire code is in the DNS.CBL sample program:

 DISPLAY-TCPIP-INFO.

 

   1 counter PIC Z9.

 

   DISPLAY `<TABLE BORDER=1 BGCOLOR="CCCCCC">`.

 

   DISPLAY `<TR BGCOLOR="lightgreen">`.

   DISPLAY `<TD><B>host_name:</B></TD>`.

   DISPLAY `<TD><B>` & host_name & `</B></TD>`.

   DISPLAY `</TR>`.

   .

   .

   .

   DISPLAY `</TABLE>`.

TCP/IP Socket Commands

CobolScript has commands for several TCP/IP socket operations.  Socket programming is very similar to file I/O, except socket programming reads from and writes to sockets instead of files.  A socket is an endpoint of communication, created in software, and equivalent to a computer’s network interface. 

We have provided two sample programs that, when combined, demonstrate the use of socket operations – the first program is a socket server, and the second is its client.  The server program should first be run from one command prompt window, and then the client program run from another .  After they have both started, you can type a string in the client window that will be sent via TCP/IP to the server.  This example can easily be modified to communicate with clients and servers on different platforms simply by changing the IP address (host name) parameters.

The server program (the sample program SERV.CBL) requires the same set of TCP/IP data structures that we defined in the previously discussed DNS.CBL program, as well the following user-defined variables:

1 host_name            PIC X(80).

1 socket_num           PIC 9(2).

1 connected_socket_num PIC 9(2).

1 port_num             PIC 9(5).

1 backlog_num          PIC 9(2).

1 string_var           PIC X(10).

1 receive_string       PIC X(20).

1  send_string         PIC X(20).

Here’s the main code.  Note the order of the socket server commands (CREATESOCKET, BINDSOCKET, LISTENTOSOCKET), which is necessary set-up for the socket before a connection can be accepted using ACCEPTFROMSOCKET:

******************************************************

* This program requires that you have TCP/IP running

* on your machine.

******************************************************

 MAIN.

   GETHOSTNAME USING host_name.

   DISPLAY `Starting Deskware Server on ` & host_name.

 

   MOVE 1 TO socket_num.

   MOVE 2 TO connected_socket_num.

   CREATESOCKET USING socket_num.

   DISPLAY `CREATESOCKET return code = <` & TCPIP-RETURN-CODE & `>`.

           

   MOVE 2500 TO port_num.

   BINDSOCKET USING socket_num port_num.

   DISPLAY `BINDSOCKET return code = <` & TCPIP-RETURN-CODE & `>`.

 

   MOVE 1 TO backlog_num.

   LISTENTOSOCKET USING socket_num backlog_num.

   DISPLAY `LISTENTOSOCKET return code = <` & TCPIP-RETURN-CODE & `>`.

 

   DISPLAY `Waiting to accept socket connection on port ` & port_num

          & `...`.

   ACCEPTFROMSOCKET USING socket_num connected_socket_num.

   DISPLAY `ACCEPTFROMSOCKET return code = <` & TCPIP-RETURN-CODE

          & `>`.

 

   MOVE SPACES TO receive_string.

   PERFORM ACCEPT-TCPIP-CONNECTIONS UNTIL receive_string(1:4) = `STOP`.

 

   DISPLAY `Shutting down Deskware Server`.

 

   SHUTDOWNSOCKET USING connected_socket_num 1.

   CLOSESOCKET USING connected_socket_num.

 

   SHUTDOWNSOCKET USING socket_num 1.

   CLOSESOCKET USING socket_num.

   GOBACK.

 

 ACCEPT-TCPIP-CONNECTIONS.

   MOVE SPACES TO receive_string.

   RECEIVESOCKET USING connected_socket_num receive_string.

   DISPLAY `TCP/IP return code = <` & TCPIP-RETURN-CODE & `>`.

   DISPLAY `TCP/IP return message = <` & TCPIP-RETURN-MESSAGE & `>`.

 

   DISPLAY `This was received: ` & receive_string.

 

   MOVE `GOT IT` TO send_string.

   SENDSOCKET USING connected_socket_num send_string.

   DISPLAY `TCP/IP return code = <` & TCPIP-RETURN-CODE & `>`.

   DISPLAY `TCP/IP return message = <` & TCPIP-RETURN-MESSAGE & `>`.

   DISPLAY `This was sent: ` & send_string.

 

Figure 6.1 – Command prompt with server program running.


The client program (the sample program CLIENT.CBL) requires the same set of TCP/IP data structures as defined in DNS.CBL, and also the following user-defined variables:

 

1 host_name            PIC X(80).

1 socket_num           PIC 9(2).

1 connected_socket_num PIC 9(2).

1 port_num             PIC Z9999.

1 backlog_num          PIC 9(2).

1 string               PIC X(10).

1 receive_string       PIC X(20).

1 send_string          PIC X(20).

1 stop_var             PIC 9.

The client code in this example assumes that the client and server programs are running on the same machine (hence the move of the loopback address to host_name).

Note the interaction points between the previous server program and this client program; the server uses ACCEPTFROMSOCKET to accept a connection initiated by the client’s CONNECTTOSOCKET statement.  Once the connection is established, the server uses RECEIVESOCKET to receive the data transmitted from the client using SENDSOCKET.  Once the transmission is complete, they reverse, and the server sends the string `GOT IT` back to the client as a way to confirm the data transmission.  Here’s our client code:

 DISPLAY `Starting Deskware Client (type STOP to exit).`.

 MOVE 1 TO socket_num .

 CREATESOCKET USING socket_num.

 DISPLAY `CREATESOCKET return code = <` & TCPIP-RETURN-CODE & `>`.

            

 MOVE 2500 TO port_num.

* We are using the loop back IP in this example;

* uncomment the line below and comment out the move

* to actually get the host name

* GETHOSTNAME USING host_name

 MOVE `127.0.0.1` TO host_name.

 

 DISPLAY `Your hostname is: ` & host_name.

 CONNECTTOSOCKET USING socket_num host_name port_num.

 DISPLAY `CONNECTTOSOCKET return code = <` & TCPIP-RETURN-CODE & `>`.

 DISPLAY TCPIP-RETURN-MESSAGE.

 

 PERFORM SEND-DATA-TO-SERVER UNTIL stop_var.

 

 SHUTDOWNSOCKET USING socket_num 1.

 CLOSESOCKET USING socket_num.

 GOBACK.

 

 SEND-DATA-TO-SERVER.

   ACCEPT send_string FROM KEYBOARD

          PROMPT `Data to send to port 2500: `.

 

   SENDSOCKET USING socket_num send_string.

   DISPLAY `SENDSOCKET return code = <` & TCPIP-RETURN-CODE & `>`.

   DISPLAY TCPIP-RETURN-MESSAGE.

     

   MOVE SPACES TO receive_string.

   RECEIVESOCKET USING socket_num receive_string.

   DISPLAY `RECEIVESOCKET return code = <` &  TCPIP-RETURN-CODE & `>`.

   DISPLAY `This was received: <` & receive_string & `>`.

   DISPLAY `RECEIVESOCKET return code = <` & TCPIP-RETURN-CODE & `>`.

   DISPLAY TCPIP-RETURN-MESSAGE.

 

   IF send_string(1:4) = `STOP` THEN

      MOVE 1 to stop_var

   END-IF.

 

 

Figure 6.2 – Command prompt with client programming.


 


 

Chapter

7


 

Advanced Internet Programming Techniques Using CobolScript®

T

his chapter discusses advanced techniques for processing internet data retrieval using CobolScript.  We also briefly discuss the use of embedded JavaScript in your CobolScript programs, for handling tasks suited for client-side processing.

Our discussion of CGI data retrieval and processing assumes that the incoming CGI data is always submitted using the POST method.  With the POST method, URL-encoded data is delivered to the CobolScript program through standard input. The CobolScript engine reads all of this data, decodes it, and places it in corresponding CobolScript variables.

Also, all code examples assume that you’ve set your file permissions correctly.  As mentioned in earlier chapters, if you’re working in a Unix environment, always make certain that the file permissions on your CobolScript internet programs allow the CGI user (usually user ‘nobody’) to execute them.

All of our web and internet code examples also assume that you have not modified your web server software to make CobolScript your default CGI interpreter.  However, making CobolScript the default CGI interpreter is usually relatively easy, depending on your web server.  Doing so will simplify the URLs you use to call CobolScript programs; instead of calling a program with a URL such as the following:

http://www.cobolscript.com/cgi-bin/cobolscript.exe?samples.cbl

You would instead use a URL such as:

http://www.cobolscript.com/cgi-bin/samples.cgi

Or, if your web server is flexible enough to allow modification to the CGI program extension, even this:

http://www.cobolscript.com/cgi-bin/samples.cbl

However, by modifying your web server’s configuration in this manner, you will disable any interpreted programs already existing on the server that relied on the previous configuration, and that were written in a different language such as Perl (these programs will be treated as CobolScript programs and will fail to run because they are not valid CobolScript code).  Use your own discretion in making this type of modification; a web system built from scratch, using only CobolScript code, is an ideal candidate for this kind of configuration change; a web system with existing interpreted code written in other languages is not.  Consult your web server’s documentation for more information on how to configure the default interpreter path and the default CGI extension.

Environment Variables

Environment variables are system variables that exist within a particular computer user’s environment.  With regard to a web server, the full set of environment variables is recreated each time a CGI process is executed.  You can think of these variables as placeholders that a web server uses to pass data about an HTTP request from the server to the CGI-processing application, i.e., your CobolScript program. 

With CobolScript, environment variables are accessed with the GETENV command:

GETENV USING <environment variable> <cobolscript variable>.

The names for environment variables are system-specific.  Fortunately, most web servers have adopted many of the same names.  Here are a few of the standard ones; experiment with these variables in the GETENV statement to determine the formats of the contents of each of these variables:

Environment Variable

Description

CONTENT_LENGTH

Size of the attached incoming CGI data in bytes (characters).

CONTENT_TYPE

The MIME type of the incoming CGI data

PATH_INFO

Path to be interpreted by the CGI application.

PATH_TRANSLATED

The virtual-to-physical mapping of the file on the system.

QUERY_STRING

The URL-encoded string that was submitted to the web server

REMOTE_ADDR

The IP address of the agent making the CGI request.

REMOTE_HOST

The fully qualified domain name of the requesting agent.

REMOTE_IDENT

Data reported about the agents’ connection to the server.

REMOTE_USER

The User ID sent by the client agent.

REQUEST_METHOD

The request method used by the client.  For CobolScript applications, this should be “POST”.

SCRIPT_NAME

The path identifying the CGI application requested.

SERVER_NAME

The server name of the requested URL.  This will either be the IP address of the server or the fully qualified domain name.

SERVER_PORT

The port where the client request was received by the server.

SERVER_PROTOCOL

The name and revision of the request protocol.

 

Environment Variable

Description

SERVER_SOFTWARE

The name and version of the server software.  For example: “OmniHTTPd/1.01 (Win32; I386)”

 

Some web servers do not support all of these environment variables.  You should consult your web server documentation to find out what environment variables are supported by your specific web server.

All normal web servers support the CONTENT_LENGTH environment variable.  Because of this, we recommend getting this variable when your CobolScript application is first invoked via a web server, like this:

GETENV USING `CONTENT_LENGTH` content_length.

IF content_length > 0

   ACCEPT DATA FROM WEBPAGE

END-IF.

By doing this, you will know if a form was submitted to your application or not.  If your application was called directly from a typed URL, outside of a form submission, the value of CONTENT_LENGTH would be 0 and you would not need to accept CGI data from the web server.  Normally, when the ACCEPT DATA FROM WEBPAGE statement is executed, CobolScript will begin reading data from the CGI stream and place the contents in the appropriate CobolScript variables.  Of course, it’s not necessary to do this if no CGI data has been sent to the web server.

Sometimes, web servers are configured to not populate certain environment variables such as REMOTE_HOST.  This is often done because there is a time cost in resolving the IP addresses of each client as it makes a request.  However, you can still resolve these IP addresses by using the GETHOSTBYNAME command.  Simply get the REMOTE_ADDR environment variable that contains the IP address of the client, and use this as the argument to GETHOSTBYNAME:

GETENV USING `REMOTE_ADDR` download_ip.

GETHOSTBYNAME USING download_ip.

MOVE TCPIP-HOSTENT-HOSTNAME TO download_host.

The GETHOSTBYNAME command will resolve the IP address to its fully qualified domain name, and the result will be placed in the TCPIP-HOSTENT-HOSTNAME variable.  If the DNS server cannot resolve the IP address, the TCPIP-HOSTENT-HOSTNAME will be spaces.  Also, for completeness, the TCP/IP return code values should always be examined after executing GETHOSTBYNAME to determine whether the command executed successfully or not.

 

 

 

 

CGI Form Components

 

Figure 7.1 – Input.cbl sample program, as seen from Netscape browser.


As we saw in Chapter 5, the ACCEPT DATA FROM WEBPAGE statement can capture HTML form data.  This data capture can be done from all of the possible submitting form components – text boxes, multi-line text boxes, list boxes, drop down list boxes, radio buttons, check boxes, and submit buttons.  In this section, we describe how to process input from each of these components.  The example program input.cbl illustrates the data capture for each of these components (except submit buttons).  This sample program can be found in the sample programs included with CobolScript.  The first screen of this sample program is shown in Figure 7.1.

All of the HTML form control tags that we discuss in this section have a common attribute called NAME.  This attribute is of the form:

NAME=variable_name

Or, alternatively (quotes can be included or excluded from tag attribute values; they must be included, however, when spaces exist in the attribute’s value):

NAME=“variable_name”

where variable_name is the name of the CGI variable that will be passed to the receiving program when the form is submitted.  The receiving CobolScript program, specified in the ACTION attribute of the FORM tag, must define a variable for each submitted form control with a NAME attribute in order for the ACCEPT DATA FROM WEBPAGE statement to work correctly.

Text Box Input

Text boxes are created with the <INPUT TYPE=TEXT… > tag.  For instance, if our source CGI form submits a text input named field1, defined here: 

<FORM ACTION=”/cgi-bin/cobolscript.exe?receive.cbl”>

<INPUT TYPE=TEXT NAME=field1><BR><BR>

<INPUT TYPE=SUBMIT>

</FORM>

Then, our receiving CobolScript program (which will be named receive.cbl, according to the ACTION attribute of the FORM tag above) must define a variable named field1: 

1 field1  PIC X(20).

In the example program input.cbl, a text box named field1 is displayed to a web browser when the program is run.  When the form is submitted from the web browser, the CobolScript program will get any data in the text box and place it in a CobolScript variable named field1.

Text boxes can also have preassigned values through the use of the VALUE attribute.  In a more complex example than the one above, a CobolScript program we’ll call recurse.cbl, that both displays a form and calls itself after accepting submitted input from the form, could have some code like the following:

DISPLAY `<INPUT TYPE=TEXT NAME=field1 VALUE=”`.

IF field1 NOT = SPACES

   DISPLAY field1

END-IF.

DISPLAY `”>`.

DISPLAY `<BR><BR>`.

DISPLAY `<INPUT TYPE=SUBMIT>`.

DISPLAY `</FORM>`.

In this case, the text box’s VALUE will be assigned “” (a null value) if field1 is blank (all spaces); otherwise it will be assigned the value of the CobolScript variable field1.

Text Area Input

Text area controls are created with the <TEXTAREA … > tag:

<TEXTAREA NAME=”field2” COLS=20 ROWS=2>

</TEXTAREA><BR><BR>

Our receiving CobolScript program must, in this case, define a variable named field2: 

1 field2  PIC X(40).

In the example program input.cbl, a text area with the name field2 is displayed to the web browser when the program is run.  When the form is submitted from the web browser, the CobolScript program will get any data in the text area and place it in a CobolScript variable named field2.  Special characters like carriage returns and line feeds will be translated into HTML special characters such as &#013; and &#010;  This is useful when you need to save the contents of a TEXTAREA to a file and later redisplay them in a web browser.  The breaks and tabs will be preserved when you redisplay the HTML.

Because text areas can be large, and CobolScript variables are fixed width, you may find that you want a way to display only the initial populated portion of the text area input.  HTML tends to ignore extra spaces, so it’s not usually necessary to eliminate trailing spaces, but you may find it useful when working inside dynamically-sized HTML tables, since trailing spaces are taken into account when table elements are sized.  The routine below accomplishes this with a PERFORM..VARYING loop and the use of positional string referencing:

PERFORM VARYING space_location FROM 40 BY –1

   UNTIL FIELD2(space_location:1) NOT = SPACE

END-PERFORM.

 

DISPLAY FIELD2(1:space_location)

List and Dropdown List Boxes

List and dropdown list boxes are displayed with the <SELECT … > tag inside an HTML form, like this: 

<SELECT NAME=”field3” SIZE=3>

<OPTION SELECTED>Item1

<OPTION>Item2

<OPTION>Item3

<OPTION>Item4

<OPTION>Item5

<OPTION>Item6

</SELECT><BR><BR>

 

<B>field4:</B>

<SELECT NAME=”field4”>

<OPTION SELECTED VALUE=Item11>Item 11

<OPTION VALUE=Item22>Item 22

<OPTION VALUE=Item33>Item 33

<OPTION VALUE=Item44>Item 44

<OPTION VALUE=Item55>Item 55

<OPTION VALUE=Item66>Item 66

</SELECT><BR><BR>

To retrieve these CGI fields, our receiving program defines two variables, one for each of the SELECT tags’ names:

5 field3  PIC X(20).

5 field4  PIC X(20).

The SELECT tag is relatively straightforward:  The value of each option is the text that immediately follows each OPTION tag, unless a VALUE attribute is specified in the OPTION tag.  When an option is selected and the controlling form submitted, the SELECT variable is assigned the value of the option that was selected.  By using a list box, you can limit the possible inputs that can be submitted, and therefore more readily direct processing based on these inputs.  For instance, we could control processing based on the value assigned to field4 like this:

IF field4(1:6) = `Item33`

   DISPLAY `Item33 is currently out of stock`

ELSE

   DISPLAY field4 & ` has been ordered for you`

END-IF.

Radio Buttons

Radio buttons are created with the <INPUT TYPE=RADIO … > tag.  They allow the selection of a single option from multiple options; when created properly, only one radio item may be selected from all radio buttons that have the same NAME value within a particular form.  The VALUE tag is useful because you can put a compressed or numeric value in it and display a different text label in your web page, like this:

<INPUT TYPE=RADIO NAME=field5 VALUE=111>Item 111<BR>

<INPUT TYPE=RADIO NAME=field5 VALUE=222>Item 222<BR>

<INPUT TYPE=RADIO NAME=field5 VALUE=333>Item 333<BR>

<INPUT TYPE=RADIO NAME=field5 VALUE=444>Item 444<BR>

<INPUT TYPE=RADIO NAME=field5 VALUE=555>Item 555<BR><BR>

After the form is submitted, ACCEPT DATA FROM WEBPAGE will copy the VALUE of the radio button to the CobolScript variable with the same name as the buttons, so in this case, the following CobolScript field definition is required:

5 field5  PIC X(3).

Checkboxes

Checkboxes are created with the <INPUT TYPE=CHECKBOX … > tag.  They allow multiple options to be selected or deselected from a group of options.  When the form is submitted, those items that were checked will have their corresponding CobolScript variables populated with the VALUE specified for that check box item.  Here is some example HTML for checkbox controls:

<B>FIELD6:</B> <INPUT TYPE=CHECKBOX NAME=”field6”  VALUE=”Item1111”>Item1111<BR>

<B>FIELD7:</B> <INPUT TYPE=CHECKBOX NAME=”field7”  VALUE=”Item2222”>Item2222<BR>

<B>FIELD8:</B> <INPUT TYPE=CHECKBOX NAME=”field8”  VALUE=”Item3333”>Item3333<BR>

<B>FIELD9:</B> <INPUT TYPE=CHECKBOX NAME=”field9”  VALUE=”Item4444”>Item4444<BR>

<B>FIELD10:</B><INPUT TYPE=CHECKBOX NAME=”field10” VALUE=”Item5555”>Item5555<BR>

<B>FIELD11:</B><INPUT TYPE=CHECKBOX NAME=”field11” VALUE=”Item6666”>Item6666<BR><BR>

  Each checkbox field must have its own corresponding CobolScript variable, like this:

5 field6   PIC X(20).

5 field7   PIC X(20).

5 field8   PIC X(20).

5 field9   PIC X(20).

5 field10  PIC X(20).

5 field11  PIC X(20).

Using Hidden Fields

 

 

Figure 7.2 – Web page with hidden fields in the underlying HTML.


Hidden fields are actually just another type of CGI input, but they are special enough to warrant a section all their own.  They are HTML form fields that are not visible in the browser window, but are still part of the underlying HTML form.  They are useful for storing and passing information to the recipient program, and they can be used to maintain program continuity through a series of CobolScript-created pages without directly displaying all data to the browser window, and without writing to a temporary file.  The sample problem tracking system uses hidden fields in the HTML forms it displays; figure 7.2 is a capture of the Update screen.

 

Figure 7.3 – HTML form with hidden fields, as seen from Netscape’s source window.

 


Figure 7.3 shows the HTML source to the screen in 7.2, complete with hidden HTML form fields.  You can see the fields update-record and record-key have a TYPE=“hidden”.

When this form is submitted, the field update-record will pass a value of “T” to the CobolScript variable update-record.  The form field record-key will pass a value of 00000007 to the CobolScript variable record-key.  These fields are hidden on this form because we do not want them to be edited by the user.  The record-key is used to determine which record needs to be updated after the form is submitted.  This program is the Problem Tracking System example application (PRB.CBL) that comes with the sample programs included with CobolScript. 

When you look at the source of the HTML form in Figure 7.3, you will notice that the hidden field record-key appears on three lines, like this:

 

<INPUT TYPE=”hidden” NAME=”record-key” VALUE=”

00000007

“>

The HTML is formatted in this way because we used DISPLAYLF to display the group level data item that contained the HTML.  Had we used DISPLAY instead of DISPLAYLF, the entire text would have appeared on a single line.  More on this below.

Here’s a snippet of the CobolScript group item that contains the hidden field record-key.  Here we spread the tag definition across three variables (two of these are implied FILLER variables, but variables nonetheless).  This is a useful technique because it allows you to populate the CobolScript variable record-key with a value before displaying the group item:

5  `<INPUT TYPE=”hidden” NAME=”record-key” VALUE=”`.

5  record-key    PIC 9(08).

5  `”>`.

Sometimes when interfacing with other systems, particularly those written in Perl, the INPUT fields must be on a single line.  In these cases, use DISPLAY than DISPLAYLF to print the relevant group item so that it prints on one line.  At any rate, CobolScript is intelligent enough to process HTML forms that contain INPUT tags on single or multiple lines, so you won’t encounter this issue unless you submit CGI data to non-CobolScript programs. 

Sending Email from CobolScript Using CGI Form Input

As we discussed in Chapter 6, CobolScript has the capability to send simple emails, and this can easily be linked with data that has been submitted from a form, in order to create an auto-responder.  The sample program email.cbl is an example of how to do this.  The program is in the sample programs included with CobolScript.  Figure 7.4 shows the application screen. 

In email.cbl, email is sent using the SENDMAIL statement after fields corresponding to the to-address, from-address, subject, and message have been accepted from CGI input:

MOVE `yourservername.com` TO smtp_server.

SENDMAIL USING to_address

               from_address

               subject

               message server.

When sending an email with this command, you must be sure to supply a valid SMTP server name, which is the name of your sending mail server.  CobolScript will then use this server to forward the email to the recipient.

 

 

 

 

 

 

Figure 7.4 – The email.cbl sample application as seen in Netscape.

 


Using CobolScript to Transmit Files

Within HTML, you can provide links to files that can be downloaded by using the anchor tag (<A HREF= … >), but if you do this your users will be able to see the location of the file on your server when they view your HTML source.  If you want to hide the location of your files and regulate who downloads files from your site, you can build a CobolScript program to directly send the file to the user’s web browser.

 

Figure 7.5 – The Save As… dialog box.


CobolScript can be used to send a file to a client web browser.  This is accomplished by sending the appropriate MIME header and then using either the DISPLAYFILE or DISPLAYASCIIFILE commands, depending on whether the file is binary or ASCII text.  The user will be presented with a “Save As…” dialog box like the one in Figure 7.5, and will be allowed to save the file. 

To use DISPLAYFILE or DISPLAYASCIIFILE, you should first build a program that displays a form that a user will submit when he wants to download a file.  Within this form, specify the CobolScript program that will use the appropriate command to transmit the file.  Typically this form will contain a submit button, and possibly some additional fields that you will use to validate the user, as in the following:

<FORM ACTION=”/cgi-bin/cobolscript.exe?down.cbl” METHOD=”POST”>

<INPUT TYPE=”hidden” NAME=”user_id”   VALUE=”md837653    “>

<INPUT TYPE=”hidden” NAME=”password_id” VALUE=”83fFrR      “>

<INPUT TYPE=”hidden” NAME=”file”     VALUE=”budgetfile  “>

<INPUT TYPE=”Submit” VALUE=”Download”>

</FORM>

When this form is submitted, it will run the program you specify in the ACTION attribute of the FORM tag (down.cbl in this example).  Your program can then accept authentication information and decide whether to transmit the file to that particular user based on this information.  If you choose to not send the file, you can simply display an error page instead. 

After you have validated the authentication information, you can begin transmitting the file to the user.  There are two steps to this process.  First, you will need to display a special MIME header.  This mime header is what prompts the user’s web browser to show the “Save As” dialog box.  The file name that you use in your MIME header will be the default file name in the “Save As” dialog box.  It is very important that the file size in your MIME header matches the exact file size of the file you wish to transmit; in bytes.  If it doesn’t, your file will not be transmitted correctly to the user. 

After you have displayed the appropriate MIME header, you can use the DISPLAYFILE or DISPLAYASCIIFILE statement.  This will transmit the contents of the file to the client’s web browser after he selects the “Save” button from the “Save As…” dialog. 

Here’s a CobolScript code example with the appropriate MIME header and the DISPLAYFILE statement (DISPLAYASCIIFILE could be substituted for DISPLAYFILE below if the file to be transferred is a text file):

MOVE `budget.xls` to xfer_filename

MOVE `octet-stream` to xfer_method

MOVE 420000 TO xfer_filesize

DISPLAY `Content-type: application/` & xfer_method.

DISPLAY `Content-Disposition: inline; filename=`  & xfer_filename.

DISPLAY `Content-Description: ` & xfer_filename.

DISPLAY `Content-Length: ` & xfer_filesize.

DISPLAYLF.

DISPLAYFILE download_filename.

By using this technique, you can regulate downloads, and audit which users download your files.  You can also build custom text files that will be sent to your users by displaying a MIME header and then displaying individual lines, one line at a time.  If you do this, make certain that the amount of data you send matches the Content-Length specified in your MIME header.

Embedding JavaScript in CobolScript Programs

In some cases, you may want to have a portion of your application’s processing take place on the client machine (the browser’s computer).  Client-side processing is useful for tasks like edit validations, because user feedback can be more real-time, and can be provided to a user prior to his submitting a form and reconnecting with the web server.

If you want to use client-side processing with CobolScript, we recommend you do it by embedding JavaScript in the HTML displayed by your CobolScript programs.  JavaScript is relatively independent of browser manufacturer (it works with current versions of both Netscape® and IE®), runs on the client’s web browser, and is very useful for basic data validation and checking.  By embedding JavaScript-enriched HTML in your CobolScript applications, you can also reduce network traffic because checks can be performed on the data before it is submitted to the web for processing.  If you’re interested in using JavaScript, a pretty good (and reasonably priced) book for beginners is JavaScript for the World Wide Web, available from Peachpit Press.

 

Figure 7.6 – JavaScript message box.


Some situations where you might want to take advantage of JavaScript are those that require form fields to be populated or data validation of numeric and alphabetic fields.  Figure 7.6 provides an example of a message box generated by JavaScript upon a failed data validation.

The JavaScript function that displays this message box is listed below.  It is a small function and can be easily embedded into a CobolScript program that displays HTML to a web browser.

function check_fields(form) {

  if

   (form.first_name.value==””||escape(form.first_name.value).match(“%”)

    != null){

      alert(“You must enter an alphabetic first name.”);

      form.first_name.focus();

      form.first_name.select();

      return false;

    }

}

CobolScript lends itself very well to displaying web pages, primarily because the nature of group-level data items allows entire HTML code segments to be isolated in your program (or in copybooks) in simple variable definitions.  Because of this, you can create group items comprised of FILLER variables that contain your JavaScript code, and then just display the group level data item.  By doing this, you can preserve the visual layout of your JavaScript code, and it will be relatively easy to debug from within your CobolScript program.

Following is an example of a group item named web_page_header that contains our JavaScript code from above:

1 web_page_header.

 5 `Content-type: text/html`.

 5 FILLER  PIC X    VALUE LINEFEED.

 5 `<HTML><HEAD><TITLE>Validate</TITLE>`.

 5 FILLER  PIC X    VALUE LINEFEED.

 5 `<SCRIPT LANGUAGE=”JavaScript”>`.

 5 `<!—Hide script from old browsers`.

 5 `  function check_fields(form) {`.

 5 `  if (form.first_name.value == “”`.

 5 `    || escape(form.first_name.value).match(“%”) !=null){`.

 5 `        alert(“You must enter an alphabetic first name.”);`.

 5 `        form.first_name.focus();`.

 5 `        form.first_name.select();`.

 5 `        return false;`.

 5 `        }`.

 5 `  }`.

 5 `  // End script hiding -->`.

 5 `</SCRIPT>`.

Let’s assume that we saved this variable definition, by itself, as a text file with the name HEADER.CPY.  Then, this header and JavaScript are freely available to any CobolScript program, and including this file in any CobolScript program’s variable definition is just a matter of using the COPY or INCLUDE statement to reference the copybook in your program code, like this:

COPY `HEADER.CPY`.

 

1  other_stuff   PIC 99.

.

.

.

Now, the header data can be displayed with this small piece of code:

DISPLAYLF web_page_header.

When this statement executes, all of the variables that comprise web_page_header above will be printed to standard output, which in this case means they’ll be sent to the requesting client’s browser window.

Breaking a web page document into separate group-level data items in this manner can make it very easy to maintain, and using copybooks to store these items can be a real timesaver when modifications to the group items have to be made.


 

 

 

 

 

 

 

 

Chapter

8


Programming Techniques and Advanced CobolScript® Features

I

n this chapter, we discuss the technique of modular program design, provide some detailed information on manipulating CobolScript variables using the MOVE statement, and discuss some advanced features that make CobolScript a truly unique programming language.

icon key

Ü  Important point

Designing a Modular Program

Modular programming is a way of organizing your program code to make the program easier to develop, understand, and maintain.  A modular program is organized into paragraphs of code called modules.  Modules are broken down into lines of code that perform one function or several closely related functions. 

Modules are defined by paragraph names in the body of your CobolScript program.  The names of your modules must start in column 8 and must be less than 80 characters in length.  Your module names should also be descriptive, meaning, a module name should describe that module’s function.  It is also helpful to put a comment block right immediately before the module name.  This should be a short description that a programmer can easily read in order to understand what the module does, and how it does it.

A program should be designed in a hierarchical fashion. Splitting a program up into modules facilitates the partitioning of logic into individual components that are easy to code and maintain.  A program module should be as short as possible to perform a specific function in an independent manner.  A good guideline is that a module should not be longer than one page of code. 

To demonstrate the concept of modular programming we will create a program that displays a web page.  The requirements of our programs are as follows:

·         Print a header for our  web page

·         Print the body of our web page

·         Print a footer for our web page

 

Figure 8.1 – Top-down design.

 

The requirements of our program can be easily broken down into a hierarchy.  The hierarchy for our program is illustrated in Figure 9.1.  This hierarchy can then be transformed into modules. We have named our modules relative to their function.  They are as follows:

·         MAIN

·         PRINT-HEADER

·         PRINT-BODY

·         PRINT-FOOTER

MAIN is the main program module.  It will call each of the three modules in sequence in order to display a simple web page with a horizontal rule at the top, the word “Deskware, Inc” formatted and centered in the page, and a horizontal rule at the bottom of the page. 

The PERFORM statement controls the flow of the program.  We PERFORM each of the three modules and then terminate program flow with the GOBACK statement.  Below is a partial listing of our program (the sample program PAGE.CBL):

 MAIN.

    PERFORM PRINT-HEADER.

    PERFORM PRINT-BODY.

    PERFORM PRINT-FOOTER.

    GOBACK.

 

******************************************************

* MODULE: PRINT-HEADER                                                                        

* Prints header info for the html document. 

*******************************************************