INDEX
*  SPIRES Formats
A  Introduction
A.1  Introduction to this Manual
A.2  Notation Conventions
A.3  An Overview of Formats
A.3.1  An Introduction to Formats
A.3.2  The Format Creation Procedure and Some Sample Formats
A.3.3  Basic Concepts of Formats
A.3.4  The Outline of the Manual
B  Output Formats
B.1  Introduction to Output Formats
B.1.1  Do You Need a Custom-Designed Output Format?
B.1.2  Output Formats in General
B.1.3  Format Definitions as Records in the FORMATS Subfile
B.2  The Identification Section
B.2.1  The ID Statement
B.2.2  The COMMENTS (COM) Statement
B.2.3  The AUTHOR Statement
B.2.4  The DEFDATE, MODDATE and MODTIME Statements
B.2.5  The FILE Statement
B.2.6  The RECORD-NAME (REC) Statement
B.2.7  A Sample Identification Section
B.3  Instructions for Formatting: the Frame Definitions Section
B.3.1  The FRAME-ID Statement
B.3.1.1  The COMMENTS (COM) Statement
B.3.2  The DIRECTION (DIR) Statement
B.3.3  The FRAME-DIM Statement
B.3.3.1  (*) The SET NROWS and SET NCOLS Uprocs
B.3.4  The USAGE Statement
B.3.5  The Rest of the Frame Definition
B.4  Label Groups: The Basic Building Blocks of Formats
B.4.1  The LABEL Statement
B.4.2  The GETELEM Statement
B.4.2.1  (*) Other Forms of the GETELEM Value
B.4.3  The VALUE (VAL) Statement
B.4.3.1  (*) Special Characters in the VALUE Statement
B.4.4  The PUTDATA Statement
B.4.5  Label Group Statements that Control the Value
B.4.5.1  The DEFAULT Statement
B.4.5.2  The OUTPROC (OUT) and INPROC (IN) Statements
B.4.5.3  The INSERT (INS) Statement
B.4.5.4  The SET CVAL Uproc
B.4.5.5  The UPROC (P) Statement
B.4.5.6  The ENTRY-UPROC Statement
B.4.5.7  The SET BUILD Entry-Uprocs
B.4.6  Label Group Statements that Control the Placement of the Value
B.4.6.1  The START Statement
B.4.6.2  The SET STARTROW and SET STARTCOL Uprocs
B.4.6.3  The MARGINS (MAR) Statement
B.4.6.4  The BREAK (TRUNC) Statement
B.4.6.5  The LENGTH (LEN) Statement
B.4.6.6  The MAXROWS (ROWS) Statement
B.4.6.7  The SET PADCHAR Uproc and the PADCHAR Statement
B.4.6.8  The SET ADJUST Uproc
B.4.6.9  The SET REPEAT Uproc
B.4.6.10  The SET SKIPROW Uproc
B.4.7  Element Headings: the TITLE and TSTART Statements
B.4.8  Statements that Control Frame Execution; Procedural Statements
B.4.8.1  Condition Tests: The IF... THEN, THEN and ELSE Uprocs
B.4.8.1a  The Block-Construct Uprocs
B.4.8.2  The JUMP and GOTO Uprocs
B.4.8.3  The CASE Uproc
B.4.8.4  The LOOP Statement
B.4.8.5  The SET STARTOCC and SET LOOP BACKWARDS Entry-Uprocs
B.4.8.5a  The SET FILTER and CLEAR FILTER Uprocs
B.4.8.6  Subroutines within Frames: The XEQ PROC and RETURN Uprocs
B.4.8.7  Subroutines that are Frames: the IND-FRAME Statement
B.4.8.8  Leaving a Frame: the RETURN, ABORT, STOPRUN and BACKOUT Uprocs
B.4.8.9  Passing Commands to WYLBUR from a Format
B.4.8.10  Variable Manipulation: The LET and SET Uprocs
B.4.8.11  Terminal Input: The ASK Uproc
B.4.8.12  Terminal Output: The * (Star) Uproc
B.4.8.13  (*) Terminal Input/Output and Buffer Processing
B.4.8.14  Comments as Uprocs: the "-" (Hyphen) Uproc
B.4.8.15  (*) The SITE Statement
B.4.9  The COMMENTS (COM) Statement in Label Groups
B.5  The Format Declaration Section of the Format Definition
B.5.1  Naming the Format: The FORMAT-NAME Statement
B.5.2  Identifying the Frames: the FRAME-NAME and FRAME-TYPE Statements
B.5.3  Limiting Account Access: The ACCOUNTS (ACCT) Statement
B.6  Compiling Your Format Definition
B.6.1  The FORMATS Subfile
B.6.2  Compiling the Format
B.6.3  Recompiling a Format: the RECOMPILE Command
B.6.4  Destroying a Format: the ZAP FORMAT (ZAP FOR) Command
B.7  Using Your Format
B.7.1  Setting a Format: the SET FORMAT (SET FOR) Command
B.7.2  Debugging a Format
B.7.2.1  The SET FTRACE (SET FTR) Command
B.7.2.2  SET FTRACE JUMP
B.7.2.3  SET FTRACE SNAPSHOT
B.7.2.4  SET FTRACE VARIABLES
B.7.2.5  SET FTRACE FRAMES
B.7.2.6  SET FTRACE BRIEF
B.7.2.7  Directing Tracing Output to a Trace Log
B.7.2.8  Using the $FTRACE Variable
B.7.3  A Troubleshooter's Checklist for Format Debugging
B.8  Handling Structures in Output Formats
B.8.1  The PUTDATA Statement and Frame Dimensions for the Indirect Frame
B.8.2  Statements for the Indirect Frame: the SUBTREE Statement
B.8.3  Statements in the Calling Label Group: the IND-STRUCTURE Statement
B.9  User and System Variables in Output Formats
B.9.1  Using Variables in Formats
B.9.2  System Variables that are Useful in Output Formats
B.9.3  User Variables in Formats: Vgroups
B.9.3.1  The Vgroups Section of the Format Definition
B.9.3.2  The ALLOCATE Statement
B.9.3.3  Resetting Variables and Vgroups; the EVAL Uproc
B.10  Report Formats
B.10.1  The Fundamentals of Report Formats
B.10.1.1  Execution Order of Frames in a Report Format
B.10.2  Enabling Report Mode Processing (SET REPORT and WITH REPORT)
B.10.3  Controlling Page Layout for Reports
B.10.3.1  Header Frames
B.10.3.2  Footer Frames
B.10.3.3  Carriage Control in Report Formats
B.10.3.4  The SET NOBREAK Uproc
B.10.3.5  The EJECT PAGE, SET NEWPAGE and SET FRONTPAGE Uprocs
B.10.3.6  The FLUSH Uproc
B.10.3.7  The HOLD Uproc
B.10.3.7a  (*) The SET NOPUTFLAG Uproc and The $PUTFLAG Variable
B.10.3.8  Multiple Column Output
B.10.4  Using the Initial Frame to Provide Prefatory Material
B.10.5  Using the Initial Frame to Initialize System Variables
B.10.6  The Ending Frame
B.10.7  The Break Frame-Types: Group-Start and Group-End Frames
B.10.7.1  The BREAK-ELEM (BRK) and BREAK-LEVEL (LVL) Statements
B.10.7.2  The Group-Start and Group-End Frame Definitions
B.10.7.3  Sorting Records for Report Processing
B.10.7.4  The SET MAXLEVELS Uproc
B.10.8  Sorting Values in Formats
B.10.9  Using Multiple Character Set Fonts in Report Formats
B.10.10  System Variables that are Useful in Report Formats
B.10.11  A Sample Report Format Definition
B.10.12  Sample Output from the Sample Report Format
B.11  Invoking Formats from within Formats: Load Formats
B.11.1  The Load Format Itself
B.11.2  The LOAD-FORMAT (LOAD) and USING-FRAME (USING) Statements
B.11.3  The LOAD-OPTIONS Statement
B.12  Accessing Data in Other Record Types from Output Formats
B.12.1  Phantom Structures
B.12.2  Same-File Subgoal Processing
B.12.2.1  The Indirect Frame for the Subgoal: the SUBTREE Statement
B.12.2.2  The Label Group that Invokes Subgoal Processing
B.12.3  Subfile Subgoal Processing in Output Formats
B.12.4  Accessing Subtrees Within a Subgoal
B.12.5  SUBFILE versus TREE Accessing of Subgoal Records
B.12.6  A Complete Example of a Format Using Subgoal Processing
B.12.7  (*) Subgoal Processing Without Data
B.12.8  Subgoal Access to Transaction Records
B.13  Full Screen Output Formats
B.14  General File Formats for Output
B.15  Output Formats for Partial Processing
B.16  Output Formats with Device Services
B.16.1  Directing Output Frames to Multiple Areas: The IN-AREA Statement
B.16.2  The IN-AREA Statement with Report Formats
B.16.3  Creating Reports During SPIBILD Input
B.16.4  Directing Output Data to Another Subfile as Input
C  Input Formats
C.1  Introduction to Input Formats
C.1.1  Do You Need a Custom-Designed Input Format?
C.1.2  General Differences Between Input and Output Formats
C.1.3  The Input Format Definition
C.2  The Frame Definitions Section of an Input Format Definition
C.2.1  The FRAME-ID Statement
C.2.2  The DIRECTION (DIR) Statement
C.2.3  The FRAME-DIM Statement
C.2.4  The USAGE Statement
C.3  Label Groups for Input Formats
C.3.1  The GETDATA Statement
C.3.2  The VALUE (VAL) Statement
C.3.3  The PUTELEM Statement
C.3.3.1  The SET PUTOCC Uproc
C.3.3.1a  The SET STARTOCC Entry-Uproc
C.3.3.2  The SET SKIPEL Uproc
C.3.4  Changing or Testing the Label Group's Value
C.3.4.1  The INPROC (IN) Statement
C.3.4.2  The SET CVAL Uproc
C.3.4.3  The SET UVAL and DOPROC Uprocs
C.3.4.4  The BUILD RECORD Uproc
C.3.5  Statements that Control the Retrieval Location of the Value
C.3.5.1  The START and XSTART Statements
C.3.5.2  The LENGTH (LEN) Statement
C.3.5.3  The MAXROWS (ROWS) Statement
C.3.5.4  The MARGINS (MAR) Statement
C.3.5.5  The SCAN Statement
C.3.5.6  The SET SCANROW Uprocs
C.3.6  Error Handling in Input Formats
C.3.6.1  The Error Flags: $PROCERR, $APROCERR, $WPROCERR and $GPROCERR
C.3.6.2  The SET TESTFAIL Uproc or Entry-Uproc
C.3.6.3  The SET ERROR Uproc
C.3.6.4  The SET MESSAGES Uprocs
C.3.6.5  The ATTN/BREAK Key and the $ATTN Flag
C.3.7  Execution Statements Used in Input Formats
C.3.8  System Variables used with Input Formats
C.3.9  Designing and Coding Input Frames
C.3.9.1  Multiply-Occurring Elements
C.3.9.2  Structures
C.3.9.3  Guidelines for Data Retrieval with the GETDATA Statement
C.3.9.4  Using the Position Variables
C.3.9.5  The Order of Element Processing in an Input Format
C.3.9.6  (*) Record Keys
C.3.9.7  Formats for the ADDUPDATE and ADDMERGE Commands
C.3.10  A Sample Input Format Definition
C.4  Prompting Input Formats
C.4.1  The Frame Identification Statements
C.4.2  Label Groups for Prompting Input Formats
C.4.2.1  Error Handling
C.4.2.2  Null and Attention Responses
C.4.2.3  Providing Help to the User
C.4.3  A Sample Prompting Input Format Definition
C.5  Merge Formats
C.5.1  Merge Frames
C.5.1.1  The USAGE Statement
C.5.1.2  Handling Elements in Merge Frames: PUTELEM and REMELEM Statements
C.5.1.3  Occurrence Numbers in Merge Frames
C.5.1.4  The SET REMOVEL Uproc
C.5.1.5  (*) Formats Used with the ADDMERGE Command
C.5.1.6  Filtering Merge Input
C.5.2  Referenced Record Processing
C.5.3  (*) The SET PUTSTRUC Uproc
C.6  The Format Declaration Section
C.7  Compiling and Testing Your Format Definition
C.8  Retrieving Data in Other Record-Types from Input Formats
C.8.1  Subgoal Processing for Input Frames
C.9  Multiple-Record Input Formats for SPIRES and SPIBILD
C.9.1  General Rules about Batch Input Formats
C.9.2  Multiple-Record Input Formats for Adding Records
C.9.3  Multiple-Record Merge Formats Outside of Global FOR
C.9.4  SPIBILD Merge Formats Under Global FOR Processing
C.10  General File Formats for Input
C.11  Input Formats for Partial Record Processing
C.12  Input Formats for Full-Screen Applications
C.13  Special Format Techniques for Updating Records
C.13.1  Updating the Same Record Being Displayed
C.13.2  Updating Other Records from an Output Format
C.13.3  Updating Other Records During Record Input
D  Assorted Topics of Formats
D.1  Combining Frames into Formats: Multiple-Purpose Format Definitions
D.1.1  Input and Output Frames in a Single Format
D.1.1.1  The "USING frame" Command Prefix
D.1.1.2  The SHOW FRAMES Command
D.1.1.3  Formats for TRANSFER/UPDATE Processing
D.1.2  Sharing Subroutines Between Input and Output Frames
D.1.3  Multiple Formats in a Single Format Definition
D.2  XEQ Frames
D.2.1  The XEQ FRAME Command
D.2.2  XEQ Frame Definitions
D.2.2.1  XEQ Frames for Output
D.2.2.2  XEQ Frames for Input
D.2.3  The SHOW FORMAT INFORMATION (SHO FOR INF) Command
D.2.4  The SHOW FORMAT INPUT (SHO FOR INP) Command
D.2.5  Global Formats
D.3  Startup Frames
D.4  Generating Formats Code from System Formats
D.4.1  The GENERATE FORMAT Command
D.4.2  Customizing a Generated Format Further
E  Appendices
E.1  Annotated List of Elements (Statements) in a Format Definition Record
E.2  SPIRES System Variables Specific to Formats
E.2.1  Flag Variables
E.2.1.1  $NEWPAGE and $FRONTPAGE
E.2.1.2  $NOBREAK
E.2.1.3  $FREC
E.2.1.4  $GPROCERR and $WPROCERR
E.2.1.4a  $GCHANGED and $GNCHANGED
E.2.1.5  $LRGNXT, $LRGLCTR and the SET LARGE Uproc
E.2.1.6  $SORTKEND
E.2.1.7  $SORTDEND
E.2.1.8  $NEWCOL
E.2.1.9  $REPORT and $NOREPORT
E.2.1.10  $ENDATA
E.2.1.11  $ABORT
E.2.1.12  $REPROMPT
E.2.1.13  $PROTECT
E.2.1.14  $TESTFAIL
E.2.1.15  $ATTN
E.2.1.16  $SKIPF
E.2.1.17  $SUPPRESS
E.2.1.18  $FLUSH
E.2.1.19  $PROCERR
E.2.1.20  $DEFAULT
E.2.1.21  $SKIPEL
E.2.1.22  $APROCERR
E.2.1.23  $OVERFLOW
E.2.1.24  $CHANGED
E.2.1.25  $TESTREF and $REFERENCED
E.2.1.26  $LREC
E.2.1.27  $NODATA
E.2.1.28  $FTRACE
E.2.1.29  $PUTFLAG
E.2.1.29a  $NOACCESS
E.2.2  Integer Variables
E.2.2.1  $RECNO ($RECNUM)
E.2.2.2  $PAGECTL
E.2.2.3  $LLEFT
E.2.2.4  $LINEPP
E.2.2.5  $HDRLEN
E.2.2.6  $FTRLEN
E.2.2.7  $MARGIN
E.2.2.8  $PAGENO ($PAGENUM)
E.2.2.9  $COLUMNS
E.2.2.10  $COLWDTH
E.2.2.11  $CURCOL
E.2.2.12  $ULEN
E.2.2.13  $CLEN or $VLEN
E.2.2.14  $CROW
E.2.2.15  $CCOL
E.2.2.16  $LOOPCT
E.2.2.17  $NROWS
E.2.2.18  $NCOLS
E.2.2.19  $SROW
E.2.2.20  $SCOL
E.2.2.21  $LROW
E.2.2.22  $LCOL
E.2.2.23  $EROW
E.2.2.24  $ECOL
E.2.2.25  $FLINES
E.2.2.26  $ELOCC and $LASTOCC
E.2.2.27  $CURROCC and $TRUEOCC
E.2.3  Variables of other Types
E.2.3.1  $UVAL
E.2.3.2  $CVAL
E.2.3.3  $PVAL
E.2.3.4  $SORTKEY
E.2.3.5  $SORTDATA
E.2.3.6  $STARTCHAR
E.2.3.7  $ENDCHAR
E.2.3.8  $LABEL
E.2.3.9  $PARM
E.2.3.10  $ELEMID
E.2.3.11  $FORMAT, $SETFORMAT, and $GLOFORMAT
E.2.3.12  $FORMATID and $GLOFORMATID
E.2.3.13  $FRAME
:
:29  SPIRES Documentation

*  SPIRES Formats

******************************************************************
*                                                                *
*                     Stanford Data Center                       *
*                     Stanford University                        *
*                     Stanford, Ca.   94305                      *
*                                                                *
*       (c)Copyright 1994 by the Board of Trustees of the        *
*               Leland Stanford Junior University                *
*                      All rights reserved                       *
*            Printed in the United States of America             *
*                                                                *
******************************************************************

        SPIRES (TM) is a trademark of Stanford University.

A  Introduction

A.1  Introduction to this Manual

How data is arranged is an integral part of any computer application. The input data must be presented to the computer in a form it can interpret; similarly, the data output by the computer must be arranged so that it can be read and understood by the user.

In the SPIRES data base management system, input and output data is frequently processed through "formats", programs that may gather and arrange the data for the computer to place in the SPIRES file or for the computer to display to the user. SPIRES system formats, such as the standard format and the prompting input format called $PROMPT, are available for use with any SPIRES data base. However, many users want or need to create custom formats designed especially for the records in a particular subfile.

As a SPIRES user, you may want to develop custom formats for many different reasons, but each reason can probably be generalized to one of the following:

 - your requirements cannot be handled by one of the system formats;
 - a custom format is probably cheaper to use than a generalized system format that can do the
 same tasks; or
 - you want to learn how to write SPIRES formats.

This manual is designed to teach you how to create your own custom SPIRES formats. Before reading it, however, you should be familiar with the material in the SPIRES primer "A Guide to Data Base Development" or in the reference manual "SPIRES Searching and Updating". Although reading the SPIRES primer "A Guide to Output Formats" is also highly recommended as a good background to this manual, it is not essential. That document introduces the SPIRES formats language and teaches you how to design output formats with the most popular features, following one example step-by-step through the format design process.

Though this manual will also teach you how to create formats, it also serves as the primary reference source on formats -- material from it is displayed when you issue the SPIRES command EXPLAIN to find out more information online about formats topics. If you are just learning formats, the size of this manual might be overwhelming (another reason why the primer serves as a better introduction to the topic). Note that sections whose titles are preceded by "(*)" usually consist of specialized material describing how to handle rare and unusual formatting problems. The (*) prefix indicates that reading the section is not necessary for most users.

Acknowledgments

The SPIRES Data Base Management System is developed and maintained by the Data Base Management Division of the Center for Information Technology, Stanford University. The formats language and processor were designed by Bill Kiefer. This manual was written by John Klemm, who thanks Becky Morton, Dick Guertin, Jack Hamilton, June Genis and especially Bill Kiefer, John Sack, Lynn McRae and Sandy Laws for their help in its preparation.

A.2  Notation Conventions

In this manual, examples of sessions are shown with prompts and messages from SPIRES as they appear on the terminal, often in uppercase; commands you type are shown in lowercase. (You may use upper- or lowercase interchangeably when you are actually using SPIRES). For example:

Here SPIRES types "-OK TO CLEAR?" and you type "ok".

In formal command syntax descriptions, uppercase letters denote command verbs or other command elements to be entered exactly as shown; a value for lowercase terms and characters must be supplied by you. For example:

To use this particular command, you type the command verb "SELECT" with the name of the desired subfile, for instance, "Restaurant":

where "->" is the prompt from SPIRES.

Brackets ([]) denote optional parts of a command's syntax. Braces ({ }) indicate that you must specify one (and only one) of the alternatives within the braces. Within the braces or brackets, a vertical line (|) separates possible choices. Neither brackets nor braces are to be typed as part of the command. For example:

could be entered as

depending on whether you want one of the options.

Sections and subsections of this manual whose titles are preceded by an asterisk in parentheses -- (*) -- may be considered optional reading at that point. Usually the material provides details that most users will not need about how to handle uncommon situations, or technical information about how SPIRES internally handles some particular piece of formats code.

A.3  An Overview of Formats

This chapter, in a general way, describes formats conceptually and technically. A couple of simple examples of formats and their "format definitions" will also be examined, to show some of the capabilities of SPIRES formats. This chapter will also describe the structure of the rest of the manual.

A.3.1  An Introduction to Formats

Conceptually, a format is a design for the arrangement of data. The primary purpose of the design is to facilitate the interpretation of the data, whether it is a person or a computer doing the interpreting. For example, the SPIRES standard format, in which goal record data is presented in the form

tells you (on output) or SPIRES (on input) the name of each piece of data, where the data begins, where it ends, and thus, what it is. The format is a template for mapping data, specifying what data elements go where and suggesting relationships between the elements. You cannot make sense out of any data presented to you unless you understand how it is "formatted", i.e., how it is arranged.

Technically, in SPIRES a format is a program that processes data, usually as the data is placed inside the data base ("input formats") or is displayed from the data base ("output formats"). In its most basic form, the program tells SPIRES the source of the data and its destination. However, many other capabilities are based on that foundation. The program may, for example, modify or test the data, if desired. In addition, it may take advantage of standard programming facilities, such as looping, branching or subroutines.

The SPIRES formats language has a very rich and eclectic vocabulary, including pieces from file definition (e.g., processing rules), protocols (e.g., labels, variable groups and procedural statements) and other parts of SPIRES, such as system variables and functions.

A format program, written in the formats language, is called a "format definition". Just as a SPIRES file definition is a goal record in the public subfile FILEDEF, a format definition is a goal record in the subfile FORMATS, entered in the standard SPIRES format. Because of this, the format program structure is guided by the structure of FORMATS goal records; and at the detail level, much of the program statement syntax is affected by the rules for data entry via the standard SPIRES format.

In the next sections, examples of input and output formats will be briefly discussed in order to demonstrate some of these points.

A.3.2  The Format Creation Procedure and Some Sample Formats

Before stating the specific capabilities of formats, let's examine the procedure for creating two simple formats (one input, one output) for a subfile whose goal records consist of names and addresses. This procedure will introduce some concepts and terminology that will simplify the discussions of formatting capabilities later. [See B.1.1, C.1.1.]

The steps involved in creating a SPIRES format are:

     1) design the format (both the layout and the program);
     2) write the format definition;
     3) add the definition to the FORMATS subfile;
     4) compile the format definition; and
     5) test, modify and use the format.

Each of those steps is discussed below as we create an output format for the subfile.

1) Design the Format

The first step is the conceptual one. Generally, the first question to ask is, what is the purpose of the format? In this particular case, the purpose of the format is to put the names and addresses into our active file so that a LABELER program can read the data, converting it into mailing labels. Often a specific need, such as mailing labels, creates the purpose, but a more general goal, such as the desire to display the data more attractively or to make data entry easier, can certainly be a reasonable purpose.

The LABELER program we want to use has certain requirements about the data input to it:

 - Each record should be preceded by an exclamation point,  which  serves  as  a  delimiter.
 - On the next line should be the NAME element; on the next lines should be the  occurrences
 of the ADDRESS.LINE element.
 - No record may use more than five lines, including the exclamation point.
 - No line may exceed 36 characters in length.

So a record to be displayed in this LABELER format would look like this:

Our SPIRES file was designed partially around these requirements -- for example, each line of the address as it is to appear on a mailing label is a separate occurrence of the ADDRESS.LINE element. The NAME element is only allowed to have one occurrence, while the ADDRESS.LINE element may have up to three. Also, both elements are limited to 36 characters in length per occurrence. These goal record characteristics, specified in the file definition, suggest that file designers often create files with specific formats in mind from the beginning -- format design requirements may affect some aspects of the file design.

At this point, it is a good idea to look at the format as a template laid out on a grid, such as a piece of graph paper. The grid will represent one goal record displayed via the format. The size of the grid is determined here by the LABELER program: 5 rows by 36 columns is the maximum size of a record. Below is a representation of that grid, each "." representing one position in the grid:

In formats terminology, this 5x36 grid is called a "frame". (Later, the term "frame" will also mean the part of the program that moves the data to and from the grid.) Within the frame, we can position element values and textual strings as we like: they can be centered or left- or right-adjusted within the frame, or they can be restricted to certain columns, or they can wrap around from one row to the next, and so forth. (The "and so forth" will be discussed later.) We will position the exclamation point and the elements in a very simple manner, all left-adjusted within the frame:

The strings in parentheses indicate the elements, whose values would appear there instead.

External specifications guided the design of this particular format; for another format, you might have more creative freedom. Whatever the situation, however, it is recommended that you lay out your format design in a grid such as the one above, especially when you are just beginning to write format definitions. Some more specific guidelines for designing formats will be presented later.

2) Write the Format Definition

The next step is to use the format definition language to write a format definition. The format definition is both a program and a goal record, and the format language reflects this dual role. When we treat it as a program, we say it consists of instructions, or "statements"; when we treat it as a goal record, it consists of "elements", which must follow the standard rules for record input. (In general, we will refer to the elements in a format definition as "statements", to avoid confusion with the elements in records of your subfile to be handled by the format.) Below is the format definition for the LABELER format, as collected in the active file:

     1.    ID = GQ.JNK.ADDRESS.LABELS;
     2.    FILE = GQ.JNK.ADDRESS.BOOK;
     3.    RECORD-NAME = REC01;
     4.    FRAME-ID = LABEL.OUT;
     5.      DIRECTION = OUTPUT;
     6.      FRAME-DIM = 5,36;
     7.      USAGE = DISPLAY;
     8.      LABEL = DELIMITER;
     9.        VALUE = '!';
    10.        PUTDATA;
    11.      LABEL = NAME;
    12.        GETELEM;
    13.        PUTDATA;
    14.      LABEL = ADDRESS.LINE;
    15.        GETELEM;
    16.        PUTDATA;
    17.        LOOP;
    18.    FORMAT-NAME = LABELER;
    19.      FRAME-NAME = LABEL.OUT;
    20.        FRAME-TYPE = DATA;

We can break that format definition into three main sections:

1) Identification Section (lines 1-3)

These statements provide information about the format definition itself and the file to which it applies. The ID element serves as the key of the format definition goal record when it is placed in the FORMATS subfile. The FILE and RECORD-NAME statements name the file and the particular record-type within the file for which the format is being created.

2) Frame Definitions Section (lines 4-17)

This section is usually the largest section in the format definition; most, if not all, of the instructions on how the goal record is to be processed are stated here. Although a format may have multiple frames, often one will suffice. Here, the single "frame definition" begins with some statements about the frame itself, including its name and dimensions. Then the remainder of the frame definition consists of "label groups", which specify the work to be done.

Each label group begins with a LABEL statement (which, by the way, has nothing to do with the fact that this format will be used to create mailing labels) and handles one value or one element. For example, the label group in lines 11 through 13 GETs the ELEMent named by the LABEL statement (NAME) and PUTs that DATA into the grid into a default location (the first column of the next row). Format execution within a frame begins with the first label group and proceeds from one to the next, executing the statements within each.

Label groups are often more complex, using more statements than are shown in this example. For instance, they may test the accessed element value and choose not to put it into the frame, or they may be used entirely to control the execution flow of the frame without accessing data elements or values at all.

3) Format Declaration Section (lines 18-20)

In this section, the frames, which are the building blocks of the format, are put together and given a name used in the SET FORMAT command (the name specified in the FORMAT-NAME statement). When that command is issued, SPIRES fetches the frames under that FORMAT-NAME; SPIRES will execute them later when a command that uses this format is issued. (Remember that more than one frame definition may be specified in the format definition.)

Though only three sections were shown in this definition, many formats contain a fourth section, called "Vgroups", that defines user variables to be used during frame processing. Statements in the Frame Definitions and Format Declaration sections may assign, test, change and display variable values; these capabilities are used frequently in more complicated format applications.

Granted, the above presentation does not teach you how to write a format definition, that is, it does not teach you specifically how to convert a design on a grid into a format definition, but it does introduce some of the statements allowed and show you that some format definitions can be rather simple. The rest of the manual will teach you what formats statements to specify for a given design feature of your formats.

3) Add the Format Definition to the FORMATS Subfile

To compile a format definition, you must first place it in the FORMATS subfile. If the format definition shown above is in your active file, the procedure is simple:

SPIRES examines the format definition in your active file, and if it follows the rules for goal records in the FORMATS subfile (e.g., it has a value for the key element ID, and it has the proper elements in the Frame Definitions section), then the record is added to the subfile.

4) Compile the Format Definition

Once SPIRES has accepted your format's blueprint (that is, once you have successfully added the format definition to the FORMATS subfile), you may compile it:

The COMPILE command names the format definition in the FORMATS subfile that is to be compiled. SPIRES in effect "builds" the format from the definition, checking the syntax of the statements and creating the compiled code to be used by SPIRES when the format is invoked. If a syntax error is found by the compiler, an error message is issued, and you must correct the format definition record in the FORMATS subfile, and then try compiling again. When the format definition is compiled, the format may be used.

5) Test, Modify and Use the Format

You may now select the appropriate subfile, and set the format:

One of the record output commands, probably DISPLAY or TYPE, may now be used to display records through the format. If the format is not satisfactory, adjustments can be made to the format definition, which you then "recompile".

The procedure for format creation consists of the same steps regardless of the type of format. Next we will create an input format for the ADDRESS BOOK subfile.

We want to make data entry into the subfile very easy. Only two elements are collected: the single occurrence of NAME and the multiple (up to 3) occurrences of ADDRESS. An input format may prompt the user for the appropriate data (as the system format $PROMPT does) or may read the data from a data set such as your active file (as the standard SPIRES format does). For our simple input format, let's assume we will collect the data for each record in our active file, in a manner similar to the way the data is displayed by our output format above -- that is, the name will be on the first line, and the address lines will be found on the next one to three lines.

Again, we lay out a grid, representing a frame. This time, since we will not need the exclamation point delimiter required by the LABELER program, we can eliminate one row, leaving the grid as 4 rows by 36 columns:

Below is the appropriate input format definition. You will notice several new statements, but basically this format definition is similar to the output format definition above:

     1.    ID = GQ.JNK.ADDRESS.INPUT;
     2.    FILE = GQ.JNK.ADDRESS.BOOK;
     3.    RECORD-NAME = REC01;
     4.    FRAME-ID = INPUT.DATA;
     5.      DIRECTION = INPUT;
     6.      FRAME-DIM = 4,36;
     7.      USAGE = FULL;
     8.      LABEL = NAME;
     9.        GETDATA;
    10.        PUTELEM;
    11.      LABEL = ADDRESS.LINE;
    12.        GETDATA;
    13.        UPROC = IF $ENDATA THEN RETURN;
    14.        PUTELEM;
    15.        LOOP;
    16.    FORMAT-NAME = INPUT;
    17.      FRAME-NAME = INPUT.DATA;
    18.        FRAME-TYPE = DATA;

This format definition has the same three sections; the major differences are in the statements within the Frame Definition section:

 - the DIRECTION has changed from OUTPUT to INPUT.
 - the GETELEMs and PUTDATAs have been switched  around,  becoming  GETDATAs  and  PUTELEMs,
 reflecting the switch from output to input.
 - the value of the USAGE statement has changed from DISPLAY to FULL.
 - a new statement, the UPROC (for User  PROCessing),  controls  the  handling  of  multiple
 occurrences  of  ADDRESS.LINE:  If  the  end  of  the data has been reached, then no more
 processing is to be done in that label group.

The format definition would be added to the FORMATS subfile and compiled, just as shown earlier for the output format. Then you would probably test the format like this:

With this basic outline of the process for creating SPIRES formats, we are now better equipped to consider the capabilities of particular types of formats.

A.3.3  Basic Concepts of Formats

Let's examine the process of how formats work and how they are used in more detail.

All formats are created to process data. In almost all cases, a format maps data from a record-type within a SPIRES file to a character array or vice versa. (A special type of format called a "global format" [See D.2.5.] is not associated specifically with any data base.)

No format can be used until a SET FORMAT command (or an equivalent, such as automatic format selection when a subfile is selected) has been issued. When SPIRES receives a SET FORMAT command, it looks for the record containing the compiled characteristics of the named format in a subfile called FORCHAR (for FORmat CHARacteristics). FORCHAR records are created by SPIRES when a format definition is compiled; users, including format definers, rarely need to access this subfile themselves. The compiled code is then in user memory for use by subsequent commands.

Also at this time, SPIRES initializes any user-defined variable groups ("vgroups") that can be used by frames that will be executed. Any user variables used during format execution (e.g., to hold element values for testing later in the format) must be defined either in the Vgroups section of the format definition, or in a separate record for the VGROUPS subfile. [See B.9.3.] When the compiled format is set, room in user memory is reserved for these variables, and initial values, if any, are assigned to them.

Sometimes a format may have a special type of frame called a "startup frame", which is executed as soon as SPIRES "loads" the format (i.e., when the SET FORMAT command is issued). The startup frame is typically used to send information to the terminal about how the format is used or to set certain variables or make certain tests, just like "select-commands" may be used when a subfile is selected. [See D.3.]

All of the commands listed below may cause format execution if a format is set:

When any of the above commands is issued and a format is set, SPIRES checks to see whether execution of any frames within that format is appropriate. This decision is based on the values of several statements within the format definition, specifically DIRECTION and USAGE in the Frame Definitions section and FRAME-NAME and FRAME-TYPE within the Format Declaration section. [See B.3.2, B.3.4, B.5.2.]

A single format may have frames to be used when the ADD command is executed and different frames to be used when the DISPLAY command is executed. Similarly, a single format may have two different "sets" of output frames, one set of which is invoked by a DISPLAY or TYPE command, and the other which is invoked by a TRANSFER command, or even by a TYPE or DISPLAY command that is preceded by the "USING frame" prefix. [See D.1.1.1.] The ability to have several contrasting uses for a format can make applications simple -- you may not have to keep switching formats back and forth to alternately add and display records, for instance. On the other hand, it creates a minor terminology problem, because a format used for adding records, which we are tempted to call an "input format", may be defined so that it can also be used to display records, in which case it also qualifies as an "output format".

That description of the terminology problem also suggests its solution. A given format may be both an input and an output format, so calling one an "input format" will not rule out the possibility that it may also be defined for use as an output format as well. The term "input format" simply implies that the format definition contains frames that can be executed when data is being mapped into the data base. Similarly, "output format" implies that the format definition contains frames that can be executed when data is being mapped from the data base. A format then may be either or both. [See D.2 to see how it can be neither.]

For example, the two formats defined in the previous section can be combined into a single format:

Identification section

      1.     ID = GQ.JNK.ADDRESS.FORMATS;
      2.     FILE = GQ.JNK.ADDRESS.BOOK;
      3.     RECORD-NAME = REC01;

Frame Definitions section

      4.     FRAME-ID = LABEL.OUT;
      5.       DIRECTION = OUTPUT;
      6.       FRAME-DIM = 5,36;
      7.       USAGE = DISPLAY;
      8.       LABEL = DELIMITER;
      9.         VALUE = '!';
     10.         PUTDATA;
     11.       LABEL = NAME;
     12.         GETELEM;
     13.         PUTDATA;
     14.       LABEL = ADDRESS.LINE;
     15.         GETELEM;
     16.         PUTDATA;
     17.         LOOP;
     18.     FRAME-ID = INPUT.DATA;
     19.       DIRECTION = INPUT;
     20.       FRAME-DIM = 4,36;
     21.       USAGE = FULL;
     22.       LABEL = NAME;
     23.         GETDATA;
     24.         PUTELEM;
     25.       LABEL = ADDRESS.LINE;
     26.         GETDATA;
     27.         UPROC = IF $ENDATA THEN RETURN;
     28.         PUTELEM;
     29.         LOOP;

Format Declaration Section

     30.     FORMAT-NAME = INPUT.AND.LABELS;
     31.       FRAME-NAME = LABEL.OUT;
     32.         FRAME-TYPE = DATA;
     33.       FRAME-NAME = INPUT.DATA;
     34.         FRAME-TYPE = DATA;

Though only the single format INPUT.AND.LABELS is set, different frames, each with a different purpose, would be executed when different commands are issued. When a TYPE or DISPLAY command is issued, for instance, the output frame LABEL.OUT would be executed; when an ADD command is issued, however, the input frame INPUT.DATA would be executed. Hence, a single format serves as both an input and an output format.

Suppose now that a command is issued that will cause one or more frames of the set format to be executed. Again, for example, suppose that the set format has frames that will be executed when a TYPE command is issued. SPIRES will then begin executing the appropriate data frames, following the instructions in the label groups for each frame, beginning at the first label group and continuing straight through (unless some branching instruction is encountered) for each record. Data frames are executed once per record. Certain types of frames, available in "report mode", are executed once per "group" of records or at the end of all records when multiple records are output.

If we return to the conceptual notion of a frame being a grid in which data is positioned, we can think of a format being a collection of such grids. Many formats may have only one grid, but a format may consist of multiple grids; the grids may appear one after the other, or they may be grids superimposed upon grids. The latter capability is particularly important when data elements within structures are being processed. Thus, just the way you can position a data element within a frame, you can construct a frame and position it within another frame.

As a program then, a format can proceed from frame to frame, or a frame may invoke another frame, like a subroutine, that gets control, executes and then returns control back to the "calling" frame. Such a frame is called an "indirect frame" because it is invoked not directly by a user command but instead by another frame.

When SPIRES begins executing a frame, it first establishes a "buffer" in user memory -- the buffer can be considered the internal equivalent to a grid. For output, the data is positioned individually in the buffer according to the directions given in the label-groups. For input, input data is placed in the buffer until it is full and then individual pieces are read from the buffer, according to the label-groups. (The exception to this is the prompting input format, in which the data being input is not read from a data set but is retrieved by prompting the user for data values at the terminal.)

A.3.4  The Outline of the Manual

This manual will show you how to write formats, based on the concepts shown in this section. In Part B, we will concentrate on output formats. In a task-related approach, we will begin constructing simple output formats, adding to our capabilities and skills as we need them. Our format creation procedure a few sections back will be covered in detail; from that point of view, Part B is worth studying even if you just want to write input formats, since the procedure, as you saw, is very similar for both types of formats.

In Part C, we will examine input formats. Input formats for adding and modifying (either via the UPDATE or MERGE command) records will be covered, including discussions on the major methods of providing the input data -- reading input data sets, prompting the user, and providing the data in the format itself (normally done in merge processing). Though the direction of data flow has changed, the basic format definition concepts do not, and the chapters of Part C build on the statements and techniques introduced in Part B.

In Part D, some miscellaneous topics will be covered, including formats used for both input and output and formats used for neither. Also discussed there will be single format definitions that define multiple formats.

The concluding section, Part E, provides several appendices to the manual, including descriptions of all SPIRES system variables associated with formats (they are used from time to time throughout the manual) and explanations for error messages that you might receive when you compile a format definition.

B  Output Formats

B.1  Introduction to Output Formats

Output formats can be designed to display data from a SPIRES data base. The format may be designed for displaying individual records or for reporting on groups of records (providing subtotals and totals across records, for example).

The first few chapters of this part of the manual will lead you step-by-step through the procedure of creating output formats. Later in this part, special features and capabilities of output formats will be discussed, such as the ability to call other formats from within a format, the ability to access records in other data bases from within a format, and even the ability to update records while displaying them.

It is important to realize, especially if you will be writing input formats, that most of the topics discussed in this part concerning output formats also relate to input formats. Statements discussed here in regard to output often are identical to, or have their opposite counterpart in, statements in input formats. Please be aware that the details of such topics covered in this part may not be repeated in the part on input formats -- cross references to this part will be provided there instead.

One final reminder before beginning this chapter: Remember that the term "output formats" is misleading in that a single format can be used for many different purposes (input and output) by many different commands. The term is used to identify formats that can be used for output, but not necessarily exclusively for output.

B.1.1  Do You Need a Custom-Designed Output Format?

Before you decide to create an output format (and go to the trouble of learning how if you have never done so before), you should seriously consider whether a custom-designed format is necessary. SPIRES allows you to display record data in various ways without forcing you to learn the formats language. If you are not acquainted with these "system formats" (general-purpose formats that can often be used by any data base) and features, which are individually discussed below, you are encouraged to read about them in the references cited.

The data in records to be displayed may be controlled in two ways: 1) you may control the specific elements to be shown; or 2) you may control specific element values to be shown, based on their values. In the first case, the control is handled by element lists; in the second, it is handled by element filters. An example of element filters will be shown later in this section.

The Standard SPIRES Format

The most commonly seen system format is the standard SPIRES format, whose general form is:

Here are some notes on the standard SPIRES format:

 - It may be used by any record-type of any file.
 - It is the default format for any record-type unless another format is so named in the  file
 definition.
 - It is in effect after the CLEAR FORMAT command is issued.
 - It is used to display parts of records when a SET ELEMENTS command is in effect or when the
 "element list" option is added to a TYPE command.
 - By indenting elements within structures, it shows you the data  hierarchy  of  the  record.
 - It is no more expensive and usually less expensive to use than  a  custom-designed  format.
 - With the capitalization of element names, the trailing semicolons, and the quotation  marks
 when special characters (like semicolons and quotation marks) appear in the value, the data
 may  look  unattractive  and, at worst, be difficult to read, especially for large records.

The $PROMPT Format

This format also displays element names and values, but in a different form from the standard format. The element names are shown on the left; their values appear several blanks later on the right. Structures are labeled, and the format makes it clear which elements are in them. In general, it is more expensive to use than similar, custom-designed output formats, though you can generate a custom format from $PROMPT. Not only is one of these generated formats as cheap to use as a custom-designed one, it is also simple to create, saving you from writing a complex format definition. [See D.4.1.]

If you are not familiar with the format, select a subfile, issue the SET FORMAT $PROMPT command, and display some records with it. The format is also useful for input, as its name suggests. It is described fully in the SPIRES manual "Searching and Updating", section D.3.

The $REPORT Format

This format displays records in a tabular form. The elements are arranged horizontally in columns across the page. (Because the $REPORT format is a "report" format [See B.10.] it is designed primarily to produce output for printed reports, though by no means is it limited to that.) The documentation for it can be found in part C of "Searching and Updating".

Here are some additional notes on the $REPORT format:

 - Only the elements specified in the SET FORMAT $REPORT command are displayed.
 - It includes features especially for multiple record displays -- totals, averages, maximums,
 minimums, and the like, computed across all the records or across groups of records, may be
 requested.
 - Titles, page numbers, and "headers" and "footers" for each page may  be
 requested.

Filtered Record Processing

This feature allows you to restrict elements displayed to particular occurrences or to occurrences with particular values. Filters affect the output regardless of what format is set. Although formats can restrict the occurrences displayed of a particular element, filters provide a more general facility.

Here is an example of a SET FILTER command:

This command tells SPIRES that later record-display commands should process only the occurrences of the CHILDREN structure that have an AGE element value of less than ten for any given record. Any records displayed after the command has been issued will be affected -- no occurrences of the structure that have an AGE value greater than or equal to ten will be displayed, no matter what format is used.

A command such as "SET FILTER FOR CHILDREN (1/3) WHERE AGE < 10" will limit displays to only the first three occurrences of the structure that represent children less than ten years old. Another form of the command, such as "SET FILTER FOR CHILDREN IN 2/4", identifies the specific occurrences (the second through fourth) that should be processed.

Filters are a very powerful feature that can be used instead of output formats or in conjunction with them, depending on the application. They have no effect on output formats used for the TRANSFER command [See B.3.4.] nor do they generally affect input formats. If your application involves both formats and protocols, you may find it easier to limit the displayed values with SET FILTER commands in the protocol than with specific code in the format definition. Complete documentation for filters is in chapter 21 of "SPIRES Technical Notes". [See B.4.8.5a for information about how filters may be set within an output format.]

Dynamic Elements

Dynamic elements can be used to show element values in different forms than the way in which they would be output by the standard format. For a very simple example, suppose an element were displayed like this:

You might issue a DEFINE ELEMENT command to create the dynamic element RPM:

The RPM element is based on the value of the SPEED element for any given record. If you issue the command "TYPE SPEED, RPM", you might get the following result:

Dynamic elements may be defined by anyone with access to the selected subfile; they only last for that user as long as he or she has the subfile selected. They may concatenate or perform computations with several element values. They may use SPIRES functions and system variables. They may use either the internal (i.e., pre-OUTPROC) or external (post-OUTPROC) form of the elements.

Dynamic elements are a very helpful tool; like filters, they may be used instead of or in conjunction with output formats, though if you intend to use them in a format, they must be represented by variables in GETELEM statements. [See B.4.2.1.] For more information about them, see "SPIRES Technical Notes", section 20.

Why You Might Need a Custom-Designed Format

Despite the power of all of these system formats and features, considered separately or in combinations, they do not handle all the situations that custom formats do. Moreover, a customized format has certain advantages over them.

In regard to the system formats described above, a customized format does exactly what you want -- you do not have to compromise your needs with generalized capabilities. In regard to the features such as dynamic elements, a customized format has the advantage of being compiled, and compiled code is more efficient to execute than uncompiled equivalents.

Generally, the individual capabilities described above for both the formats and features can be coded in output formats as well. But specifically, here are a few other capabilities of customized formats that may not be as easy to handle by other methods:

 - conditionally displaying elements depending on the values of other elements;
 - displaying structural data in  a  way  that  clearly  and  attractively  shows  the  data's
 structural hierarchy;
 - retrieving data from other records in other record-types ("subgoal  processing");
 - calling other formats ("load formats").

B.1.2  Output Formats in General

Output format record-processing can be considered a two-step operation. First, the data is retrieved from the record according to the instructions given in the format definition (specifically, in the definition of the frame being executed) and placed, after any specified alterations, in the "buffer". The buffer, an area in main memory, is associated with the frame currently executing.

Second, when execution of the frame is complete, the buffer is "flushed" (sent) to the output device, usually the terminal screen or active file. If the format contains multiple frames to be executed, SPIRES will go on to the next one, starting this process over again. Similarly, if multiple records are being processed and the last frame has been executed for a given record, SPIRES will go on to the next record, starting the process over again.

The concept of the buffer as an intermediate storage place for data is important to keep in mind, especially for output formats. For example, if an instruction within a frame tells SPIRES to immediately display a message at the terminal using the star ("*") "Uproc" [See B.4.8.13.] you might be surprised at first to see the message on your screen ahead of the data already processed by the format. But again, the formatted data is being held in the buffer until the frame executes completely, whereas the message from the star Uproc is sent to the terminal immediately. [See B.3.3.]

Output formats can be designed to display individual records or to produce reports processing multiple records. However, regardless of whether the format is designed for single record displays or multiple-record reports, only one record is processed per execution of the format -- that is, the frames that process records are written to process individual records. Commands that cause multiple records to be displayed (e.g., DISPLAY ALL) cause the format to be executed one time per record.

Many output formats are written with a single frame to process the data. The "data frame" can handle all record-level elements in the records, but elements within structures must usually be handled by separate frames that are invoked from the data frame. Within a frame, each element is usually "processed" (i.e., retrieved from the record, modified if desired and placed in the buffer) by a group of statements called a "label group"; although several label groups may be used and are sometimes necessary to handle an element, the norm is one label group per element.

B.1.3  Format Definitions as Records in the FORMATS Subfile

All format definitions must be placed in the public subfile FORMATS before they can be compiled and used. Hence they have a dual role: a format definition is a collection of instructions in a particular language, and it is a goal record in a subfile. The rest of this manual discusses the format definition language, but this section will discuss the format definition as a goal record.

Generally, FORMATS records are entered in the standard SPIRES format. Almost all format definitions are entered into the FORMATS subfiles as records in the standard SPIRES format, so the syntax of statements in a format definition will be shown as they would be entered in that format. For example, the ID statement's syntax is:

Thus, in the FORMATS subfile, the value for the element ID must have the form "gg.uuu.anyname". If you enter the format definition in the standard format, you must begin the statement with the element name and end it with the semicolon. The equals sign, though not shown as such in the syntax statements, is always optional.

The maximum length for any single element value in a FORMATS goal record is 3072 bytes. That means, for example, that no single occurrence of the COMMENTS statement may be longer than 3072 characters (about 40 72-character lines). However, COMMENTS statements are allowed to occur multiple times wherever they appear in a format definition, so very long comments could be split into multiple occurrences. [See B.2.2.]

The rules for data entry using the standard SPIRES format are discussed in detail in the SPIRES manual "Searching and Updating", section D.1.2. The most important ones to remember are the following:

The last rules are important to stress. Many of the statements in a format definition are elements within structures. For example, a frame definition is an occurrence of a structure; each label group in a frame is an occurrence of a structure within the frame structure.

All structures in a FORMATS goal record have key elements, such as VARIABLE in the VARIABLES structure shown above. Because a statement introducing or ending a structure may thus look like any other statement, you can easily lose your bearings in the format definition hierarchy.

Also important to remember is that SPIRES allows you to enter the elements in a structure (or the record-level elements, for that matter) in almost any order. However, they will be rearranged into the order shown by the SHOW ELEMENTS command for the FORMATS subfile. Thus the order in which you enter the statements may not be the order in which they are stored and compiled and executed. That is occasionally a problem for people learning to write label groups. [See B.4.]

An appendix in the back of this manual shows the proper order of statements in a format definition record. [See E.1.] In addition, the examples throughout will show you the order in which to code the statements.

A format definition has four major parts: the Identification section, the Vgroups section, the Frame Definitions section and the Format Declaration section. The first section represents most of the record-level elements in a format definition record; the others represent multiply-occurring structures. For example, there may be more than one frame definition, each one representing one occurrence of the FRAME-DEF structure.

Each of the sections of the definition are covered in separate chapters of Part B. [See B.2, B.3, B.5.] In addition, one chapter covers label groups, the multiply-occurring structure within the FRAME-DEF structure. [See B.4.] Other chapters in Part B will discuss how to compile the created format definition, how to use it, and how to handle other special situations in output formats.

B.2  The Identification Section

This chapter describes the format definition statements that relate to the format definition as a whole. The key of the format definition record is the first statement, ID. Other statements, FILE and RECORD-NAME, identify the file and the record-type within the file to which the formats defined in this record will apply. Other statements (such as AUTHOR and DEFDATE) may contain other information about the record that will be useful to you.

In terms of the FORMATS goal record, these statements are record-level elements. Following the RECORD-NAME statement come the VGROUPS, FRAME-DEF and FORMAT-DEC structures, discussed in later chapters. Several other record-level elements, such as GEN-FILE, follow these structures, but they are discussed in later chapters. [See B.4.5.2, C.10.]

B.2.1  The ID Statement

The ID statement specifies the key element value of the format definition for the FORMATS subfile -- no other format definition in the FORMATS subfile may have the same value.

The form of the ID statement is:

where "gg.uuu" is your account number and "anyname" is a character string containing any characters other than blanks.

Usually, to make identification easier, a format definition's ID references the file to which it applies. For example, if a file is named XR.RMN.TAPES, a format definition for one of its record-types might be specified as:

The ID value is not the value used in the SET FORMAT command; that value is specified in the FORMAT-NAME statement in the format declaration section. [See B.5.1.] The ID value is used when you want to update the record in the FORMATS subfile and when you compile the format definition, so it is usually advisable to keep it relatively short and easy to type. A reasonable limit to suggest here is that the entire value be no longer than 30 characters, but the absolute limit is over 100.

You may replace the "gg.uuu:" portion of the value with a period or an asterisk:

Both are equivalent to the first form shown above for account number XR.RMN.

B.2.2  The COMMENTS (COM) Statement

This free-form, multiply occurring statement is the first of several COMMENTS statements allowed throughout the definition, appearing in most every section. The COMMENTS statement here is often used to describe the purpose of the format(s) being defined, though of course you may use it for anything you want.

For example,

Be aware that, if this were collected in your active file, the extra blanks on the second line of the COMMENTS value (preceding "of the RECORDS subfile") would be retained in the value. It is shown this way here, and in similar examples throughout the document, to make long values easier to read than the way you probably should enter them:

     ID = GQ.JNK.RECORDS.LISTING;
     COMMENTS = This format definition is for the LISTING format
of the RECORDS subfile.;
     AUTHOR = John Klemm, DBMG, 497-4420.;

That style of presentation, though more accurate, can make examples more difficult to read.

Here is an example demonstrating "block comments", which are often easier to read because you enter them the way you want to see them:

Certainly the asterisk border draws your attention to the comments inside.

Some users maintain their format definitions in WYLBUR or ORVYL data sets. Rather than transferring the definition from the FORMATS subfile, making changes, and then updating it, they make changes to their own copy of the definition and then update the copy in the FORMATS subfile. This procedure lets them take advantage of the "-" element, sometimes called the "dash element" or the "throwaway element". If you add a record that includes throwaway element values, those values are indeed thrown away, and not included in the stored record; the throwaway element is available for all SPIRES subfiles. People who maintain their own copies of a format definition can use the throwaway element to place comments anywhere they please within the definition, since SPIRES will ignore them.

Yet another type of comment is allowed in UPROC statements. [See B.4.8.14.]

B.2.3  The AUTHOR Statement

Like the COMMENTS statement, this is an optional, multiply occurring, free-form statement, meant to include your name, as the definition's author, along with a phone number in case the SPIRES system programmers need to get in touch with you. Such a need seldom arises, of course, but when it does, the appearance of this statement is very helpful.

Here is an example of an AUTHOR statement:

B.2.4  The DEFDATE, MODDATE and MODTIME Statements

These three statements, automatically supplied when you add or update your format definition in the FORMATS subfile, provide the date the record was first added to the subfile (DEFDATE), as well as the date (MODDATE) and time (MODTIME) that it was last updated. They are provided for your convenience.

B.2.5  The FILE Statement

This singly occurring statement contains the full name (including the account number prefix) of the file to which the format definition applies.

For example,

If the file belongs to your account, you may replace the "gg.uuu." portion of the file name with either a period or an asterisk:

SPIRES will replace those characters with your account number for record storage.

You can write a format definition for a record-type within any file; however, to use the format, you must be able to access the record-type, usually by selecting the subfile for which it is the goal record-type.

If you are not the file owner, you may not know the file name. That information may be obtained by selecting the appropriate subfile and issuing the SHOW SUBFILE INFORMATION command.

This statement and the RECORD-NAME statement [See B.2.6.] may be omitted if you are writing a general file format or a global format. [See B.14, D.2.5.]

B.2.6  The RECORD-NAME (REC) Statement

This singly occurring statement identifies the record-type in the previously named file to which the format definition applies. If you do not know the name of the record-type, it may be discovered by selecting the subfile for which the format is being written and issuing the SHOW SUBFILE INFORMATION command.

Here is an example of the RECORD-NAME statement:

The record name will never be longer than six characters.

A format definition and all the formats it defines can be used with only one record-type of one file (unless it is a general file format, described later in this manual). Usually a format is written for the goal record-type of a subfile, but not always -- the format definition is tied to a specific record-type of a file, not to a subfile, via the FILE and RECORD-NAME statements. It is possible to access other record-types from a format, however, through subgoal processing. [See B.12, B.14.]

B.2.7  A Sample Identification Section

Below is a sample identification section, combining the statements described in this chapter:

Remember that this definition is a goal record in the standard SPIRES format. Hence, in the second COMMENTS statement, the inclusion of quotation marks around the title "SPIRES Formats" means that the entire element value must be enclosed in quotation marks, and the internal quotation marks must be doubled. Similarly, if a semicolon (;) appears within a value, the value must be enclosed in quotation marks. Within the value, using apostrophes (') instead of quotation marks (") and avoiding semicolons are alternatives to consider as well. [See B.1.3.]

The next section of the format definition, Vgroups, will be discussed later. For the time being, just remember that we will be able to use variables declared in the Vgroups section later in the frames that we write. The next two chapters will discuss the Frame Definitions section.

B.3  Instructions for Formatting: the Frame Definitions Section

The Frame Definitions section, which contains sets of formatting instructions, does most and often all of the work for a format. The section is comprised of one or more "frame definitions". Most frame definitions consist of two parts: frame identification statements, that provide the name of the frame and put limits on how the frame may be used (for example, for input or for output), and label groups, the individual subroutines that specify the processing to occur.

Though many formats have only one frame to be executed, formats commonly have multiple ones. There are several reasons why this is so. The most common reason is that the goal record-type for which you are writing the output format has structures in it. In most such cases, the processing of the elements within the structure must be specified in a separate frame definition. How to handle structures is the subject of a later chapter. [See B.8.] Other reasons for using multiple frames, such as the ability to share the same code between multiple formats, will be discussed in later chapters of Part B.

The remainder of this chapter will focus on the basic statements of frame identification. Some others, such as SUBTREE and LOAD-FORMAT, are involved with the above-mentioned reasons for having multiple frames, and thus will be covered in later chapters. Discussion of the label groups in a frame definition will appear in the next chapter.

B.3.1  The FRAME-ID Statement

The FRAME-ID statement signals the beginning of a frame definition. It provides a name for the defined frame that will be necessary in various situations later. In particular, this name is used in the format declaration section to tell SPIRES which frames can be used when a format is executed. [See B.5.2.]

The frame name may be from one to sixteen characters long. No blanks are allowed in the name. Few special characters (i.e., not alphabetic or numeric) are allowed in the name either, though the useful exceptions are periods, hyphens and underscores, which are commonly used as substitutes for blanks.

For example,

B.3.1.1  The COMMENTS (COM) Statement

Just after the FRAME-ID statement, you can add another COMMENTS statements in the same form as the one described earlier. [See B.2.2.] The COMMENTS statement here will most likely describe how the frame will be used, or, if it is an indirect frame, which other frame or frames called it. [See B.4.8.7.]

B.3.2  The DIRECTION (DIR) Statement

This statement specifies the direction of the data mapping. A frame used for data output will have the value OUTPUT for this statement.

For example,

Frames for input will have the value INPUT. A third value, INOUT, is used primarily in formats used in full-screen applications [See D.1.2.] though it may also be specified for frames containing code that is shared between input and output formats. [See D.1.]

In other words, the output commands DISPLAY, TYPE, SCAN and TRANSFER may cause execution of frames of DIRECTION = OUTPUT. The input commands ADD, UPDATE, MERGE and BATCH (in SPIBILD) cannot cause execution of such frames; instead, they may cause execution of frames of DIRECTION = INPUT. Neither of these statements is meant to imply that such frames will necessarily be executed when one of those commands is executed; that depends on other factors as well. [See B.3.4, B.5.2.]

By default, if no value is coded for the DIRECTION statement (i.e., the statement is omitted from the frame definition), it is given the value of OUTPUT. Getting into the habit of explicitly coding it is recommended, however, since forgetting to code it properly on an input frame would cause a compilation error.

Generally speaking, an indirect frame has the same direction as the frame that calls it, but that is not always the case. [See B.4.8.7, B.16.3, C.13.3, D.1.2.]

B.3.3  The FRAME-DIM Statement

The FRAME-DIM statement defines the size of the two-dimensional array (also known as the format "buffer") into which the data for an output frame is placed. In other words, the values given are the dimensions of the frame being defined. This statement also specifies whether SPIRES will process the frame "line by line" or as a "fixed frame" (see below). This statement is very important -- it may only be omitted when the frame being defined is not placing data in or reading data from the buffer. [See B.4.8.7.]

The syntax of the FRAME-DIM statement is:

where "nrows" and "ncols" are integers representing the number of rows down and the number of columns across the frame respectively. The only restriction on the size of these two values is that their product (nrows times ncols) must be less that 65,536 (64K). (For purposes of comparison, a standard terminal screen, 24 rows by 80 columns, would have a product of 1,920, and a printer page of 60 rows by 150 columns would have a product of 9,000.)

If the value of "nrows" is given as "0" (zero) or omitted, as in the last form shown above, then "line by line processing" goes into effect (see below). If the value of "ncols" is 0, then the width of the destination area (such as the active file) will be used; in other words, the width is dynamically set, based on the final destination of the data. For the active file and the terminal, both in SPIRES and batch SPIRES, the value used for "ncols" is the value of the system variable $LENGTH, which is 72 by default. If the format is used to display records in other device services areas, the width of the area will be used for "ncols". [See the note below about SET HCLIP, and see the SPIRES manual "Device Services" for more details.]

When the frame is executed, SPIRES will construct a buffer in memory having the dimensions given. Subsequent instructions within label groups may reference any position within the frame by citing its row and column numbers. References to positions outside the frame dimensions (too high a row or column number, for instance) may cause an S808 error when the frame is executing -- they will not cause a compilation error. [See B.6.2.] When the frame finishes executing, the buffer is "flushed" (that is, released from main memory and sent to the specified output device, such as your terminal).

(*) The SET HCLIP Uproc in Device Services Formats

The SET HCLIP Uproc allows you to display records in a device services area when the right margin of your format's FRAME-DIM would otherwise be too wide for the area. HCLIP stands for "horizontal clipping", and the effect is that when records are displayed in a device services area, the right portion of the data output by the format will simply not be displayed, rather than giving you S808 or S825 errors. You will see only what will fit in the dimensions of the device services area.

A primary use of this Uproc is in report formats coded for use in Prism. A report might be too wide to fit on Prism's screen, so one option is simply to forbid users to display the report online (i.e. they must print the report in order to see it). Alternatively, if the SET HCLIP Uproc is used in the format, you can allow the application users to display the portion of the report that will fit on the Prism screen. (The entire wider report would still be generated for printing.)

Code SET HCLIP in an initial frame, so that the setting can be established before frame dimensions are set. The HCLIP setting is reinitialized each time a multi-record output command is issued; there is also a SET NOHCLIP Uproc to turn it off.

Choosing Frame Dimensions: Fixed Frame vs. Line-by-Line

The following principles should be considered when setting frame dimensions:

These guidelines seem to suggest that you should get the dimensions exactly right -- "too large" means inefficiency, "too small" means an error if the record being formatted is larger than anticipated. Ideally that is true, but it is somewhat impractical when you are dealing with records whose sizes vary. Given only these principles on "fixed frame dimensions", you should probably risk erring on the side of "too large".

However, there are other possibilities to consider. A neat alternative is to take advantage of "flush processing". You set "nrows" to a low, reasonable number and then specify the SET FLUSH Uproc. [See B.4.8.10, E.2.1.18.] Then, if a label-group tries to place data in a row beyond the last row of the frame, the partially completed buffer is flushed, as described above, and format processing continues, constructing and releasing rows of formatted data one by one. Once "flush processing" begins, each row is sent to the output device as soon as some value is positioned in the next row.

For example, if a data record that would require 35 rows is placed in a buffer of 30 rows that allows flush processing, as soon as SPIRES tries to place data in row 31, the first 30 rows would be flushed to, say, the active file. Then, when SPIRES tries to place data in row 32, row 31 is flushed, and so on. This process can continue indefinitely; the record may require just a few extra rows beyond the fixed frame dimensions, or hundreds. The SET FLUSH Uproc, which is specified in the format declaration section [See B.5.] grants you this flexibility.

One significant limitation of "flush processing" should be kept in mind: Once a frame or a row has been flushed, you cannot put any more data into it. Compare the two "frames" shown below. The string AAAAAAA represents an occurrence of the element A, the string BBBBBBBB represents an occurrence of the element B, and the strings made up of periods represent blanks. Both frames have fixed dimensions, but Frame 2 also has SET FLUSH. For both frames, you want to do the same thing: place all the occurrences of element A on the left, and all the occurrences of element B on the right, both sets of occurrences beginning on the first line. Note that all occurrences of A will be processed before any occurrences of B:

Presumably you want both to look like Frame 1. However, because the first row of Frame 2 is flushed when the second occurrence of element A is positioned, the first occurrence of element B cannot be positioned there; the row is already gone. The best that can be done at that point is to begin the occurrences of element B on the same row as the last occurrence of element A, as shown. Summarizing this example, we can say that multiply occurring elements to be positioned side by side with other multiply occurring elements should not usually be done within flush processing.

Line-by-line processing takes flush processing to the extreme. Each row of the frame is constructed and then is flushed when SPIRES tries to put data in the next row. Because SPIRES is working with a smaller frame (a single row at a time), line-by-line processing is slightly more efficient than fixed-frame processing. If you use a format extensively, line-by-line processing could represent a significant savings over time. On the other hand, line-by-line processing shares the same minor restriction as flush processing -- once you have written data into row 2, you cannot put any in row 1.

There may be ways around this restriction (such as another way to design the format or specify the instructions) but it is generally preferable to use fixed frame dimensions and code straightforwardly than to use line-by-line processing with a few kluges. The extra coding you do or the extra processing SPIRES must do in the latter case may far outweigh any efficiency advantages gained by using line-by-line processing. Formats that put out row after row of data down the page are natural candidates for line-by-line processing, though.

As mentioned earlier, line-by-line processing is requested by coding "0" for "nrows" in the FRAME-DIM statement:

Other aspects of frame dimensions are discussed elsewhere as appropriate.

B.3.3.1  (*) The SET NROWS and SET NCOLS Uprocs

You can change the frame dimensions set for a frame by using the SET NROWS and SET NCOLS "Uprocs". (A Uproc is a statement requesting a particular procedure to be executed at that point in the format.) [See B.4.5.5.] Their syntaxes are:

where "nrows" and "ncols" are non-negative integers, integer variables, or expressions whose results can be converted to integers. If SET NROWS or SET NCOLS appears in a label group within the frame, the value of "nrows" or "ncols" must be less than the corresponding FRAME-DIM value. The frame dimensions of the buffer will change immediately. Further changes to the frame dimensions may be made in the frame, as long as they have successively smaller values. (In general, you should not set "nrows" to zero within a frame in an attempt to switch to line-by-line processing. However, you can do it if you have not already put any data into the buffer and if the SET FLUSH Uproc is in effect.)

These UPROCs can thus be used, for example, to change the number of rows for fixed-dimension frames such as initial or header frames once you know how many rows of data they have used. [See B.10.3.1.]

The SET NROWS and SET NCOLS Uprocs can also change the frame dimensions of a frame before it is entered, if they are coded as UPROCs in the frame declaration of the Format Declaration section. (They would be coded after the FRAME-NAME statement for the frame they are to be applied to.) [See B.5.2.] Then they would be executed before the frame itself was executed. Here the value of "nrows" or "ncols" may be larger than the corresponding FRAME-DIM value, but whatever it is, it will override that FRAME-DIM value when the frame is subsequently entered. Setting the value of "nrows" to zero will set line-by-line processing for the frame when it is entered.

B.3.4  The USAGE Statement

The USAGE statement, in combination with the DIRECTION statement, determines which commands can cause execution of the frame being defined. For output frames, the most common usage is DISPLAY, indicating that DISPLAY, TYPE and SCAN commands can cause their execution.

The syntax of the USAGE statement is:

where "value" is one of the usage values shown below, and NAMED is an additional option, which is described below.

For an output frame, four values are allowed:

By default for DIRECTION=OUTPUT frames, the USAGE is DISPLAY. That is, if no USAGE statement is coded, or if USAGE = NAMED is coded by itself, the primary usage value is DISPLAY.

For most simple output formats, USAGE = DISPLAY is coded. Later we will see how the other values, including NAMED, are commonly used. [See D.1.1.1.]

B.3.5  The Rest of the Frame Definition

Next in the frame definition usually come the label groups, which will specify the processing that should be done: which elements should be accessed, where their values should be placed, etc. Alternatively, other statements may appear next, shifting execution control to other formats. [See B.11.]

Label groups are more common, however, and they are the subject of the next chapter. Before that, however, here is the start of a sample frame definition, preceded by the Identification section, using the statements described in this chapter:

Note that there is another statement that may appear between the DIRECTION and FRAME-DIM statements, the SUBTREE statement. SUBTREE is specified for indirect frames that are used to access element structures, and will be discussed later, along with indirect frames. [See B.8.2.]

B.4  Label Groups: The Basic Building Blocks of Formats

The second part of a frame definition is a collection of program instructions arranged in "label groups". Most frames have multiple label groups, at least one for each element being processed -- a single label group generally retrieves only one element.

Label groups basically have two purposes: to handle a single data value, and to control format execution. A single label group may do either or both. Specifically, label group statements have five functions:

 - 1) to access the value;
 - 2) to place the value;
 - 3) to control (test and/or change) the value;
 - 4) to control (test and/or change) the placement of the value;
 - 5) to control the execution of the label groups.

More than twenty different statements are available within a label group for an output frame, each one serving at least one of the above functions. The wide variety of possibilities is just barely suggested by their names, shown below:

Several other label group statements are available for input and "inout" frames. [See C.3.]

When SPIRES executes a frame, it begins with the first label group, executes the instructions described therein, and then proceeds to the next one. In general, the statements within a label group are executed independently, but some of them will have an effect on others -- as an extreme example of this, a UPROC = JUMP statement could possibly "undo" all the rest of the statements that preceded it in the label group. So there are two ways to look at a label group: first, as a collection of individual instructions, executed one by one; and second, as a single "super-instruction" that executes all at once, in most cases handling one data element.

The latter view is preferable for several reasons. First, whenever execution branching occurs (e.g., skipping some instructions, or looping back to earlier instructions), execution always resumes at the start of a label group. You cannot jump into the middle of a label group.

Second, a single execution of a label group handles a single value. Each label group has a value (actually in two forms, represented by the system variables $CVAL and $UVAL) and many label groups deal exclusively with their value -- retrieving it from the data base record, testing and adjusting it, and placing it in the buffer. Although these individual activities can be split into multiple label groups, the SPIRES formats language is designed to handle all a value's processing, in most cases, in one label group of statements.

Third, because the statements in a label group are actually elements in the LABEL-GROUP structure of a format definition record, they will be compiled and executed in the order in which they are stored in the FORMATS subfile, which may be different from the order in which you coded them. [See B.1.3, E.1.] In other words, you may code the three label group statements GETELEM, PUTDATA, and UPROC = JUMP in that order, but when the record is added to the FORMATS subfile, the order will be changed to GETELEM, UPROC = JUMP, and PUTDATA, and the statements would be executed in the changed order. (The PUTDATA statement would never execute, because the JUMP Uproc tells SPIRES to jump to the next label group.) Hence, treating a label group as a single, large instruction whose component statements work together in a standard order is more reliable than treating it as just a collection of instructions that will be executed. This subject will come up again in examples later in this chapter and the next.

Below is a list of the statements most commonly found in output format label groups, showing the order in which they are stored in the FORMATS record and are executed.

This chapter covers most of the label group statements listed above; a couple of them used primarily with structures, report formats or full-screen applications are discussed later. [See B.8.3, B.10.8, B.13.] The first few sections cover the most basic statements: LABEL, GETELEM, VALUE and PUTDATA. The remaining statements are then discussed in more or less the order of the categories shown above.

B.4.1  The LABEL Statement

The LABEL statement is the first and only required statement in a label group. It identifies the beginning of the label group and, if given a value, identifies the label group itself.

The syntax of the LABEL statement is:

where "label.name" is a string of one to sixteen characters. Like the FRAME-ID statement, the LABEL value should contain only alphanumeric characters and not special characters, with the common exceptions of periods, hyphens or underscores. [See B.2.1.] No blanks are allowed in the label name either.

If no label name is given (i.e., the LABEL statement is given a null value), the syntax is:

Label names are specified for several different reasons. Assigning a name lets you "jump" to that particular label group explicitly, using the XEQ PROC and JUMP Uprocs. The name will also be used as the default value for a subsequent GETELEM, PUTELEM or REMELEM statement in the label group. [See B.4.2, C.3.3, C.5.1.2.] The name will also be used by SPIRES to identify the label group in error messages if an error within the label group is detected during compilation. (If no label name is given, the label group is identified by a count from the last named label group.) And if you compile your format with the LABELS option, your label names will be used in SET FTRACE output. (SET FTRACE is a formats tracing and debugging command.) [See B.6.2, B.7.2.1.]

Here are some examples of LABEL statements:

B.4.2  The GETELEM Statement

The GETELEM statement tells SPIRES to retrieve an occurrence of the named element from the record being processed for handling by the current label group. In general, other statements within the label group will then position the element value in the frame, though that is not required -- the GETELEM statement simply retrieves the occurrence, and the rest of the label group determines what is done to it.

The most explicit form of the GETELEM statement is:

where "element.name" is the name of the element to be retrieved. Another form takes advantage of the label name supplied in the LABEL statement:

Here the name given in the previous LABEL statement is presumed to be the name of the element to be retrieved by GETELEM. [See B.4.1.]

For example, the two sets of LABEL and GETELEM statements below are equivalent:

Either set could be the beginning of a label group that is to retrieve the PHONE.NUMBER data element. If both the LABEL and the GETELEM statements are given values, the value given in the GETELEM statement is the element that will be retrieved.

When the element has multiple occurrences and you want to retrieve all of them, one by one, you must use the LOOP statement. [See B.4.8.4.] However, if you only want to retrieve one of the occurrences, you may request it explicitly:

where "n" represents an integer, either 0 (zero) or positive. (Beware: the first element occurrence is numbered 0, the second is 1, the third 2, etc.) Another form, "GETELEM = element.name::n", is now considered obsolete, though it may still be used; it was replaced by the form shown above, because the obsolete form is confusing in regard to variables, whose subscripts are indicated similarly. [See B.4.2.1 for information on using variables for the element name or the occurrence number.]

If no occurrence number is given, then the next occurrence (usually the first occurrence, number 0) is retrieved by GETELEM. Note, however, that the two statements below:

are not exactly equivalent. If you use the LOOP statement to retrieve multiple occurrences of the element, code the first statement rather than the second, for the second tells SPIRES to always retrieve the first occurrence. With the first statement, a LOOP statement will cause SPIRES to always retrieve the "next" occurrence. [See B.4.8.4.] Alternatively, in some situations you can use the SET STARTOCC Entry-Uproc to cause a loop to begin with a specified occurrence. [See B.4.8.5.]

Several other, less common forms for specifying the element to be retrieved are discussed later. [See B.4.2.1.]

The GETELEM statement is not usually coded for elements that are structures, though it can be. A structure is most often processed with an indirect frame. [See B.8.]

When a GETELEM statement fails to retrieve a value (that is, no occurrences or, in the case of a loop, no more occurrences of that element exist), the rest of the label group is skipped, and execution resumes with the next label group. The DEFAULT statement can be used to force SPIRES to continue executing the current label group in such cases. [See B.4.5.1.] Do not confuse "no occurrence" with a "null occurrence" where the element occurs but has no value. A null occurrence will not cause the rest of the label group to be skipped; however, the retrieved value is null.

When a GETELEM statement is executed, values for several important system variables are established. The most important are $UVAL ("Unconverted VALue") and $CVAL ("Converted VALue"). These two variables represent two forms of the element value retrieved, and they may be used to test or alter the value. [See B.4.5.4.] In fact, it is $CVAL that will be placed in the output buffer by the PUTDATA statement. [See B.4.4.]

B.4.2.1  (*) Other Forms of the GETELEM Value

Some other forms of the value for the GETELEM statement, though not commonly used, are discussed in this "optional" section. The forms are:

Each of these forms is discussed below. In addition, a use of the GETELEM statement with structures is discussed.

1) The first form may be used when the name of the element to be retrieved is stored in the given string variable. Alternatively, if it is a four-byte value of type HEX, then it represents the "element ID" ($ELEMID) of a particular element. [See E.2.3.10.] In either case, SPIRES uses the variable to determine the element whose values are to be retrieved.

Although a LOOP statement may cause the label group to be executed repeatedly, SPIRES will only do the variable substitution the first time through. In other words, changing the value of the variable within the label group will not cause the label group to retrieve a different element if the re-execution of the label group is caused by the LOOP statement. [See B.4.8.4.] However, if you leave the label group and return to it later, the current value of the variable will be used.

2) When "@n" (where "n" is an integer) is given as the value of GETELEM, SPIRES uses that integer as the absolute element number within the record (or within the structure, if the frame is an indirect frame processing a structure). Elements are numbered from 0 (zero) both at record-level and within a structure; the slot number key of a slot record-type is always number 0. This form may not be specified using variables.

3) The "@element.name" form is related to the "@n" form discussed above. It may be coded in an indirect frame that processes structures if the frame definition contains multiple SUBTREE statements. [See B.8.2.] This form tells SPIRES to convert the element name to the absolute element number, as in "@n". Then, this indirect frame can be called to process other structures, as listed in the SUBTREE statements, even though the element names in the GETELEM statements do not match the element names in the structure being processed. SPIRES will change the element names to the element numbers for the first structure listed in the SUBTREE statement and then use those element numbers when retrieving elements in the other structures.

As mentioned earlier, the GETELEM statement is seldom used to retrieve an entire structure. [See B.4.2.] In most cases, an indirect frame is coded to process the elements within the structure individually. However, a structure may be retrieved all at once with a GETELEM statement, usually if the structure is defined with the $STRUC or $STRUC.OUT system proc (A33) for an OUTPROC. [See B.8, C.5.3.]

You may also use GETELEM with a structure to find out how many occurrences of the structure exist:

The user variable NUM.ADDRESSES is set to the value of the system variable $ELOCC, which contains the number of occurrences of the data element processed by the GETELEM statement. [See B.9.3, E.2.2.26.]

(*) Specifying Element and Variable Occurrences

Because an element occurrence can be specified in the same way as on occurrence of a variable in an array, using the symbol '::', confusion can arise. For instance, examine the following statement:

Does this statement refer to the "Nth" occurrence of the element represented by #ELEMENT or to the "Nth" value of the variable array represented by #ELEMENT? SPIRES assumes the latter case -- #N represents the occurrence number of the variable, not of the element.

To specifically request the occurrence of the element rather than the variable:

Thus, these forms are equivalent:

In both cases, #N represents the occurrence number of the element ELEM. However, when the element name is in a variable, these two forms are not equivalent:

To specify both variable and element occurrence:

You can also specify the element occurrence number with an indexed variable:

The letter "I" as an occurrence number for the variable indicates that the definition of the variable included the INDEXED-BY statement, pointing to another variable whose value is to be used as the occurrence number for the first variable. [See the discussion of the INDEXED-BY statement in the manual "SPIRES Protocols" for further information.]

B.4.3  The VALUE (VAL) Statement

Sometimes in an output frame you have other values that are not elements that you want to be placed in the frame. The VALUE statement can be used to give the label group a value to process, just as it processes an element value accessed by the GETELEM statement. In fact, the GETELEM and VALUE statements are mutually exclusive: you may not code both of them in a single label group.

Specifically, the VALUE statement can be used:

 - when you want to place a string value (e.g., some text) in the frame when the value is  not
 directly tied to an element being positioned (cf. the TITLE statement).
 - when you want to place the result of an expression (perhaps the value of a system  or  user
 variable) in the frame.
 - when you want a value to be processed by an action  or  system  proc  whose  processing  is
 unavailable    or    difficult   to   simulate   through   system   functions.    [See   B.4.5.2.]

The syntax of the VALUE statement is:

where "expression" is an expression following the same rules as expressions in a LET command or LET Uproc. [See B.4.8.10.] The type of the value (e.g., string, integer) depends on the result of the evaluation of the expression; it is not by default converted to a string value (see below).

Each individual part of the expression must not exceed 256 characters in length. The VALUE statement follows the LABEL statement in a label group definition.

For example, here is a VALUE statement specifying a string value to be placed in the frame:

This value might appear at the top of a personnel record, identifying the data that will follow. Note that string values should usually be enclosed in apostrophes. [See B.4.3.1.]

Values and Types

Values that are expressions or whose type is not string may require extra care in handling:

During format execution, SPIRES will evaluate the expression. By default, arithmetic is done using packed decimal values, so the pieces of this particular expression, "3" and "4", are converted to packed numbers, and the result, "7", is also a packed decimal. However, before the value is output, i.e., placed in the format, it needs to be converted to a string value. The easiest way to accomplish this is to apply the $STRING function to the expression:

Another alternative would be to code an OUTPROC, such as $PACK.OUT, that would convert the value to a string. [See B.4.5.2.] But regardless of your method, it is important to know the type of the evaluated expression and, if it is not a string and you are going to position the value in an output frame, to convert it to a string. [See B.4.5.4 for a further discussion of type conversions in this regard.]

The value of the evaluated expression is assigned to the system variable $UVAL. When SPIRES executes the VALUE statement (just like the GETELEM statement), the values of several important system variables are established, in particular $UVAL and $CVAL. [See B.4.5.]

B.4.3.1  (*) Special Characters in the VALUE Statement

Although it is not absolutely required, character strings in the VALUE statement should be enclosed in apostrophes: