[Access to Wang masthead]

The TRANSPRT Procedure, Part II

Creating print file headers

From "VS Procedure",  Access 87, September 1987
  [ Prior Article ]     [ Return to the Catalog of articles ]     [ Next Article ]  

This month we'll conclude our discussion of the TRANSPRT procedure with by adding code to create an additional print file header for files to be transferred with the PRINT option. We will also review the structure of Wang print files and use CREATE to write printer control information for each line.

Identifying transferred print files

As I mentioned last month, anyone who has used the SPOOL option of TRANSFER to move their files to a remote printer has discovered how difficult it is to identify the listing. This is because TRANSFER creates a new print file on the remote system, applying a four-character prefix (typically WNETxxxx) and releasing the file under fixed initials. (Both of these default values are assigned by the system administrator during network configuration.) In other words, the original file name and user's initials are lost in the transfer.

TRANSFER is certainly not the only application that doesn't give adequate means of identification, nor are transferred print files the only ones that need further identification. Many installations have need to add routing, department billing, or other data to EXISTING PRINT FILES whether they are printed locally or at a remote site. The process described here rewrites an existing print file with a new first page containing additional information. It is generic enough that it could be used for a variety of purposes. Before going into the design elements, however, let's review the methods of passing data between programs, procedures, or the user.

Passing data to programs

In order to be usable in a generic sense, a utility should have the capability to accept data and modify its operation based on that data. For example, Wang's DISPLAY utility accepts the file name and other parameters, verifies the existence of the file, and finally reads the file and displays it on the workstation. Because DISPLAY uses a GETPARM approach to get its information, the parameters may be entered through a variety of means: manually; through the ENTER or DISPLAY statements in a procedure; or via the PUTPARM subroutine within a program.

What is a GETPARM, then? The GETPARM term stands for GET PARAMETERS. GETPARM screens are special calls to the operating system that create a special kind of interface. This interface can present a screen on the user's workstation, take system default parameters, or get it's information from a controlling program or procedure. I chose the word INTERFACE rather than SCREEN because the generation of a screen image is incidental to the process and optional; experienced users will attest to the hidden GETPARMs in many programs that often allow many new features.

But how does the use of GETPARMS relate to the other methods of getting data into a procedure? As we discussed in the February article on subprocedures, two means are typically used to accept data: as a GLOBAL variable, or as ARGUMENTS passed from the calling program or procedure. Though not discussed in that column, data can also be entered through direct screen entry (the PROMPT function). GETPARMs are much more flexible than any of the above methods because they can accept data from all sources. The following table should explain these capabilities:

Access Method Program Procedure Direct Entry Example
Passed arguments Yes Yes No PROCEDURE PRINTID USING &INFIL, &INLIB, &INVOL
GLOBAL variables No Yes No DECLARE &INLIB STRING (08) GLOBAL
Direct entry
(PROMPT)
No No Yes PROMPT CENTER "Enter INLIB", UPPER &INLIB
Input GETPARM Yes Yes Yes RUN GETPARM IN USERAIDS etc.
(see below)

As you can see, the GETPARM approach offers the most flexibility, accepting data from all three sources. A utility that uses the GETPARM approach can be run manually or automated easily, and thus be generically applied.

Now the bad news: in spite of the existence of two approaches to GETPARM creation (a USERAID and a USERSUB version), there appears to be no way to generate GETPARM screens from a procedure. GETPARMs can be generated from any high-level language (BASIC, COBOL, RPGII, etc.) by calling the GETPARM USERSUB, or within Assembly language or PL/I directly.

(Thus said, I solicit response from the readership on the use of the GETPARM USERAID, which would appear to exist for this purpose. Please write with your experiences.)

Print headers in TRANSPRT

Let's return to the problem of identifying print files. Our specifications for print file headers might include the following items:

1. Create a working print file, adding a page to document the user, time, and source system.

2. Advance to the top of the next page, then accept the text data from the original print file.

3. Send the resulting work print file to the destination system via the TRANSFER utility.

From these specifications, our procedure might contain the following steps:

1. Appropriate Procedure variables would be declared to accept the user name, ID, and date. Two working print lines would also be defined.

2. Before sending the print file to TRANSFER, a routine would be invoked to add the new header page and create a new print file.

3. The EXTRACT Usersub would be called to get the user's full name from the system security file. The DATE USERSUB would be called to get the formatted date and time.

4. The CREATE utility would be run to merge the source print file with the generated header. Each line would include the characters needed for printer control, including line and page feeds. The original print file would be read as data.

5. The resulting print file would be transferred to the destination system as before.

The necessary changes to TRANSPRT are shown in Figure 1, Figure 2, and Figure 3. Figure 1 defines new variables, extracts system information, and builds the print lines - including printer control data. (I'll cover more on printer control characters below.) These lines should be placed at the top of TRANSPRT near other DECLARE statements.

Figure 2 shows the added call to the PCONVERT subroutine and changes to the name of the print file to be transferred. These statements replace similar code in the original TRANSPRT procedure.

Figure 3 shows the PCONVERT subroutine to be added to TRANSPRT. This should be added at the end of the procedure. The PCONVERT subroutine extracts the record count and file size of the original print file, then uses the CREATE utility to write a new print file. For those unfamiliar with CREATE, this section will look ponderous; actually, it is a relatively straightforward (if tedious) rewriting of the source print file with several new records added in the front. Note that each line begins by using PAD to clear the next record line, and that the record length is the one extracted from the original print file with the READFDR USERSUB.

Printer control characters

The first two characters of Wang print files control the line feed, page feed, and certain character parameters of the printer. Since no one but programmers comes into contact with these characters, I thought it might be interesting to explain them here.

The two characters control line spacing before or after printing, page feeding, and use of an expanded print font (if available). These items consist of hexidecimal characters that are not available on a keyboard; thus, you must create them through other means. In Procedure, this is easiest with the &BYTE function.

To understand this, examine the definition of &TOPFORM in Figure 1. This two-character string consists of a character with a decimal value of 128 (in hexidecimal, '80) along with a character with a decimal value of one. The result is a page feed, one time. Similarly, a value of '00 in the first character indicates a line feed before printing and '40 line feeds after printing, with the second character indicating the count. Here is a condensed summary of practical print control characters:

Function HEX value Procedure Usage
Space 1 line
BEFORE printing
'0000

&BYTE(000) !! &BYTE(001)

Space 1 line
AFTER printing
'4001

&BYTE(064) !! &BYTE(001)

Advance 1 page'8001&BYTE(128) !! &BYTE(001)

This is a simplified table, but it should be of some use to the procedure writer. Be sure to remember that the &BYTE function can only create one character at a time, and that the resulting characters must from the first two positions of the file. Note, too, that print files comprise a discrete type of file organization, and they must be created with the type specified as PRINTER.

So what's new?

Starting next month, I will no longer be writing on Procedure language specifically. Instead, I will attempt to cover a broader slice of the VS world. There are many other items of interest to you gentle readers and I wish to present more of them. You can help me by forwarding your questions and criticisms to the address below. Please be patient; I do try to answer all letters.


Figure 1: Changes to DECLARE Statements in TRANSPRT



**********************************************************************
**   These variables are added to accept system data and create     **
**   standard print file headers.                                   **
**********************************************************************

* Variables for print ID header
     DECLARE &RECCOUNT   INTEGER
     DECLARE &RECLEN     INTEGER

     DECLARE &ID         STRING (03)
     DECLARE &NAME       STRING (24)
     DECLARE &RPTDATE    STRING (45)
     DECLARE &SYSID      STRING (08)

     EXTRACT             &ID        = USERID,   &NAME     = USERNAME,
                         &PRTLIB    = SPOOLIB,  &PRTVOL   = SPOOLVOL,
                         &SYSID     = SYSID

**********************************************************************
**   TOP-OF-PAGE INDICATOR                                          **
**                                                                  **
**   If HEX(80) (decimal 128) is the first byte of a print file,    **
**   the printer will advance to the top of the page the number     **
**   of lines stated in the second byte BEFORE printing the line.   **
**   Thus, HEX(8001) will advance the paper one page.               **
**********************************************************************

     DECLARE &TOPFORM    STRING (02) INITIAL
                         &BYTE (128) !!            [ TOF indicator   ]
                         &BYTE (001)               [ Advance 1 page  ]

**********************************************************************
**  LINE-FEED INDICATOR                                             **
**                                                                  **
**  If the first byte of a print file is HEX(00), the second        **
**  byte is the number of lines to advance before printing the      **
**  text.  The following will advance the printer 45 lines          **
**  before printing the line.                                       **
**********************************************************************

     DECLARE &45LINES    STRING (02) INITIAL
                         &BYTE (000) !!          [ Line advance ind. ]
                         &BYTE (045)             [ Advance 45 lines  ]

**********************************************************************
**  Standard user and system identification lines follow            **
**********************************************************************

     DECLARE &PRTLINE1   STRING (134) INITIAL
                         &BYTE (000) !!
                         &BYTE (001) !!
                         "This document sent from " !!
                         &SYSID(1,*) !!
                         " by user " !!
                         &ID(1,*)    !!
                         " - "       !!
                         &NAME(1,*)

     DECLARE &PRTLINE2   STRING (134) INITIAL
                         &BYTE (000) !!
                         &BYTE (002)               [ Advance 2 lines ]

Figure 2: Changes to the SPOOL Option of the TRANSFER Procedure


**********************************************************************
**  The following modifications add a call to the PCONVERT          **
**  subroutine to add the print file headers.  Note that the        **
**  output file created by PCONVERT is named dynamically, so the    **
**  file, library, and volume assignments in the PRINT option of    **
**  TRANSFER must reference the output label.                       **
**********************************************************************

* Transfer files - PRINT option **************************************

* Add print headers
     CALL PCONVERT

STP: RUN TRANSFER [ in library on volume ]
     CANCEL EXIT IS CANCEL  ERROR EXIT IS E03

     ENTER FUNCTION      01
     ENTER OPTIONS       LOCATION  = &REMSYS
     ENTER INPUT         FILE      = (O1.FILE),       [ <- Note! ]
                         LIBRARY   = (O1.LIBRARY),
                         VOLUME    = (O1.VOLUME),
                         DISP      = P,
                         SCRATCH   = YES
     ENTER OUTPUT        PRTCLASS  = &PRTCLASS,
                         FORM#     = &PRTFORM
     ENTER FUNCTION      16

     GOTO E03

Figure 3: The PCONVERT Subroutine


**********************************************************************
**  This routine checks the record count and record size of the     **
**  input print file, formats the standard header information,      **
**  and then writes a new print file from the input print file.     **
**********************************************************************

* Add page identifer to front of print file **************************

PCONVERT:

     EXTRACT &RECCOUNT   = RECORDS USED BY &PRTFIL IN &PRTLIB ON &PRTVOL

     ASSIGN  &RECCOUNT   = &RECCOUNT + 1

* Extract record length of input print file **************************

     RUN READFDR IN USERSUBS       USING &PRTFIL, &PRTLIB, &PRTVOL,
                                         0, "RL", &RECLEN, &RC

     RUN DATE IN USERSUBS          USING "HL", &RPTDATE

     ASSIGN &PRTLINE2 (3,45)       = &RPTDATE

STP: RUN CREATE IN USERAIDS

O1:  ENTER OUTPUT        FILE      = ##TRANS,  TYPE     = P,
                         RECSIZE   = &RECLEN,  RECORDS  = &RECCOUNT

     ENTER INPUT         02
     ENTER PAD           POSITION  = 1,        LENGTH   = &RECLEN
     ENTER INPUT         01
     ENTER LITERAL       STRING    = &TOPFORM, LENGTH   = 2,
                         POSITION  = 1
     ENTER INPUT         16
     ENTER COUNT         RECORDS   = 1

     ENTER INPUT         02
     ENTER PAD           POSITION  = 1,        LENGTH   = &RECLEN
     ENTER INPUT         01
     ENTER LITERAL       STRING    = &45LINES, LENGTH   = 2,
                         POSITION  = 1
     ENTER INPUT         16
     ENTER COUNT         RECORDS   = 1

     ENTER INPUT         02
     ENTER PAD           POSITION  = 1,        LENGTH   = &RECLEN
     ENTER INPUT         01
     ENTER LITERAL       STRING    = &PRTLINE1,
                         LENGTH   = 64,        POSITION  = 1
     ENTER INPUT         16
     ENTER COUNT         RECORDS   = 1

     ENTER INPUT         02
     ENTER PAD           POSITION  = 1,        LENGTH   = &RECLEN
     ENTER INPUT         01
     ENTER LITERAL       STRING    = &PRTLINE2,
                         LENGTH   = 64,        POSITION  = 1
     ENTER INPUT         16
     ENTER COUNT         RECORDS   = 1

     ENTER INPUT         02
     ENTER PAD           POSITION  = 1,        LENGTH   = &RECLEN
     ENTER INPUT         01
     ENTER LITERAL       STRING    = &TOPFORM, LENGTH   = 64,
                         POSITION  = 1,        LENGTH   = 2
I1:  ENTER INPUT         FILE      = &PRTFIL,  LIBRARY  = &PRTLIB,
                         VOLUME    = &PRTVOL
     ENTER FILE          INPOS     = 3,        OUTPOS   = 3,
                         START     = 1,        END      = 1,
                         LENGTH    = &RECLEN - 2
     ENTER INPUT         16

     ENTER INPUT         02
     ENTER PAD           POSITION  = 1,        LENGTH   = &RECLEN
     ENTER INPUT         (I1)
     ENTER FILE          START     = 2,        END      = LAST,
                         LENGTH    = &RECLEN - 2
     ENTER INPUT         16
     ENTER INPUT         16
     ENTER EOJ           16

     IF STP = 0          END

     ASSIGN &RC = STP

     PROMPT              ALARM     = YES
     CENTER BRIGHT LINE  "Print File Transfer";;
     CENTER BLINK        "E R R O R ! !";;
     CENTER              "CREATE has returned error code", &RC;;

     GOTO @16

  [ Prior Article ]     [ Return to the Catalog of articles ]     [ Next Article ]  


Copyright © 1987 Dennis S. Barnes
Reprints of this article are permitted without notification if the source of the information is clearly identified