MAINSAIL Structure Blaster User's Guide, Chapter 3

previous   next   top   complete contents   complete index   framed top   this page unframed


3. Text Forms

Text forms serve four main purposes:

  1. A data image may be translated to a text form and shipped to another operating system (although if this is the only purpose of the text form, a PDF image should be used instead).

  2. The values in a structure may be examined by a human reader (noncompressed text forms only).

  3. A data image may be translated to a text form and converted to be acceptable to another version of the Structure Blaster (a PDF image is also satisfactory for this purpose).

  4. A data structure may be created or edited by hand; the text form serves as a language for specifying MAINSAIL data structures (noncompressed text forms only).

Except as noted below, descriptions of the contents of a text form apply only to noncompressed text forms. Compressed text forms, although portable among operating systems, are not intended for human readers, and their format is subject to change.

A detailed understanding of text forms is necessary only if they are to be edited by a human user or parsed by a program; otherwise, the contents of a text form should be self-explanatory.

Except within STRING constants, the case of alphabetic characters in a text form is irrelevant. The hash mark (#) may be used as in MAINSAIL source text to indicate that the remainder of a line in a text form is to be ignored.

A text form consists of a sequence of “attributes” followed by a sequence of “units”.

3.1. Constants

Constants are written in text forms as if they appeared in MAINSAIL source, except:

3.2. Attributes

An attribute is a line in a text form that describes the contents of the text form. Attributes may be separated from one another and from the first unit by one or more blank lines.

There is currently just one valid attribute. It has the form:

systemWrittenOn operatingSystemNameAbbreviation

A list of possible operating system name abbreviations may be found in Appendix B of the MAINSAIL Language Manual. The systemWrittenOn attribute identifies the operating system on which the text form was written, which is used when a text form written on one system is read on another (e.g., to translate escape sequences in STRING constants). If this attribute is not present, it is assumed that the text form was written on the current host system.

3.3. Units

A unit is a series of lines in a text form representing an object stored in the text form. A unit is either a “CLASS unit” or a “chunk unit”. A CLASS unit declares a CLASS, and a chunk unit gives the values for a dynamic object. The chunk unit for a dynamic record is a “record unit”, for a dynamic ARRAY an “ARRAY unit”, and for a data section a “dataSec unit”. Units are separated by blank lines, and hence may not themselves contain blank lines. A text form is terminated either by a page mark or by end-of-file. If several text forms are to be stored in the same file, it is the user's responsibility to write the separating page marks into the file (e.g., by means of write(f,eop)). The first chunk unit in the text form is assumed to be the root of the data structure.

Each unit starts with a “header line” that “declares” the unit, followed by a “dash line”, which is a row of hyphens to underline the header line. Typically the dash line is the same length as the header line, but this is not necessary. The dash line must be present.

Each header line starts with an “internal name” for the unit, followed by a colon and a space. Internal names consist of a valid MAINSAIL identifier or INTEGER constant preceded by the character < and followed by the character >. For example, <123> and <foo> are valid internal names. Internal names give a unique name to each unit so that units may be referenced unambiguously within the text form.

3.3.1. CLASS Units

All CLASS units must occur before any chunk units. The general form of a CLASS unit is:

<internalName>: CLASS className
-------------------------------
... field declarations...

className is the name of the CLASS. The field declarations are specified one per line. Each has the form:

dataType fieldName

where dataType is a data type name, e.g., BOOLEAN or LONG INTEGER, and fieldName is the name of the field. ADDRESS and POINTER fields cannot be classified. An ARRAY field is declared as a POINTER.

An example of a CLASS unit is shown in Example 3–2.

Example 3–2. A Sample CLASS Unit
A CLASS unit corresponding to a CLASS declared as:

CLASS strListCls (
    
STRING val,key;
    
POINTER(strListClsnext;
);

would look like:

<51>: CLASS strlistcls
----------------------
STRING val
STRING key
POINTER next

3.3.2. Record Units

A record unit specifies the values for the fields of a record, and has the form:

<recordInternalName>: record of CLASS <classInternalName>
---------------------------------------------------------
... field specifications...

<classInternalName> is the internal name of the CLASS that describes the record fields. Field specifications are specified one per line, except that STRING constants may occupy more than one line. Each specification has the form:

fieldName = constantValue

constantValue must be of the same data type as declared for fieldName. An example of a record unit is shown in Example 3–3.

Example 3–3. A Sample Record Unit
A record of the CLASS shown in Example 3–2 with field values "This is a string" for val, "THIS" for key, and NULLPOINTER for next would look like:

<52>: record of CLASS <51> # strlistcls
---------------------------------------
val = "This is a string"
key = "THIS"
next = NULLPOINTER

3.3.3. ARRAY Units

An ARRAY unit specifies the values for the elements of an ARRAY, and has the format:

<internalName>: typeName {LONGARRAY(<bounds>) {aryName}
---------------------------------------------------------
... element specifications...

LONG is optional and is ignored. The bounds are a series of (LONG) INTEGER pairs, separated by the word TO, as in MAINSAIL source text. aryName is the name of the ARRAY; it may be omitted since it is possible for an ARRAY name to be the empty STRING. The element specifications are written one per line, except that STRING constants may use more than one line. Each specification has the form:

elementSpecifier {FOR n} = value

where the FOR n part is optional. elementSpecifier is the bracketed subscript part of a MAINSAIL subscripted variable, i.e., [i], [i,j], or [i,j,k] for a one-, two-, or three-dimensional ARRAY, respectively, where i, j, and k are (LONG) INTEGER constants. The elementSpecifiers need not be in any particular order. If FOR n is present, then n elements are initialized to the value, starting at the one specified; otherwise, just one element is initialized. The elementSpecifiers are read and corresponding initializations performed from the first elementSpecifier to the last, so that an element receives the last specified value if initialized more than once. Uninitialized elements have Zero values.

An example of an ARRAY unit is shown in Example 3–4.

Example 3–4. A Sample ARRAY Unit
An ARRAY unit for an ARRAY declared as:

CHARADR ARRAY(*) cAry;

and allocated with:

new(cAry,-2,40);

with elements 3 through 6 given non-Zero values might look like:

<88>: CHARADR ARRAY(-2 TO 40) cary
----------------------------------
[-2] 
FOR 5 = NULLCHARADR
[3] = '
HC4120
[4] 
FOR 2 = 'HD48C0 + 1 character
[6] = '
HACC48 + 1 character
[7] 
FOR 34 = NULLCHARADR

3.3.4. Vector Units (Obsolete)

A vector was a data structure used internally by MAINSAIL before Version 16. They do not exist in Version 16 and later.

A vector unit had the form:

<internalName>: typeName VECTOR(0 TO n)
---------------------------------------
... element specifications...

You should not ordinarily find vector units in your text forms, since the effect of performing a $structureWrite on the sorts of runtime system objects that could contain vectors has undefined effects.

3.3.5. DataSec Units

A dataSec unit specifies the values in a data section, and has the form:

<iName>: dataSection for MODULE modName {of CLASS <cName>}
----------------------------------------------------------
... specifications for interface data fields...
... OWN data specifications...

of CLASS <cName> must be present if the module has any interface data fields, in which case <cName> is the internal name for the CLASS that declares the fields.

A data section consists of the interface data fields followed by the OWN POINTERs, the OWN STRINGs and then any other OWN variables. OWN variables are the “outer” variables for the module (those declared outside of any PROCEDURE, but local to the module), variables declared local to a PROCEDURE but qualified with OWN, and some implicit, undeclared variables maintained by the MAINSAIL runtime system.

The specifications for the interface data fields have the form of the field specifications for a record.

The OWN data specifications have the form:

typeName {variableName} {FOR n} = value

variableName is not currently written out by the Structure Blaster since MAINSAIL does not know at runtime the names of the OWN variables. FOR n gives a repetition factor just as in an ARRAY unit (the repetition factor cannot be used if variableName is present). The OWN specifications must appear in the same order in which they occur in the data section; the user should not edit them.

An example of a dataSec unit is shown in Example 3–5.

Example 3–5. A Sample DataSec Unit
A module WINMOD with an interface declaration like:

MODULE winMod (
    
INTEGER curCharNum,charNumBefore;
    
INTEGER windowNumLines,windowNumChars;
    
INTEGER windowFirstCharNum;
    
LONG INTEGER curLineNum,lineNumBefore,
        
windowFirstLineNum;
    
LONG BITS attributes;
    
STRING bufferName,fileName;
    
POINTER(lineManagerClslineMgr;
    
POINTER(bufferManagerClsnextBfrMgr,
        
bfrMgrForWindowAbove,bfrMgrForWindowBelow;
);

might generate a dataSec unit like:

<94>: dataSection for MODULE winmod of CLASS <93>
-------------------------------------------------
curcharnum = 1
charnumbefore = 0
windownumlines = 29
windownumchars = 72
windowfirstcharnum = 1
curlinenum = 12L
linenumbefore = 0L
windowfirstlinenum = 1L
attributes = 'H0L
buffername = "BUFFER ONE"
filename = ""
linemgr = <45>
nextbfrmgr = <66>
bfrmgrforwindowabove = NULLPOINTER
bfrmgrforwindowbelow = <66>
POINTER FOR 19 = NULLPOINTER
POINTER = <70>
POINTER = <92>
POINTER FOR 2 = NULLPOINTER
STRING = "Type <eolto continueA to abortN for next,"
         " ? 
for help"
BOOLEAN = FALSE
INTEGER = 4
INTEGER FOR 2 = 0
INTEGER = 4
LONG INTEGER = 0L
LONG INTEGER FOR 2 = 1L
INTEGER = -1

WINMOD has 23 OWN POINTERs, one OWN STRING, and 9 other OWN variables. The names of the OWN variables are not provided; some of these variables may be implicit variables that have no names.

3.4. Inplace Records and ARRAYs in Text Forms

As a field or element of another object in a text form, an inplace record looks much like a record unit, and an inplace ARRAY looks much like an ARRAY unit, except that the value of each is surrounded by curly brackets ({ and }). For example, the following program:

BEGIN "foo"

CLASS c (
    
INTEGER i;
);

CLASS d (
    
$RECORD(crec;
    
STRING $INPLACEARRAY(0 to 10) ary;
);

INITIAL PROCEDURE;
BEGIN
$structureWrite(logFile,new(d));
END;

END "foo"

produces the following output:

SYSTEMWRITTENON ...

<352>: 
CLASS c
--------------
INTEGER i

<224>: 
CLASS d
--------------
$RECORD(<352>) rec
STRING $INPLACEARRAY(0 TO 10) ary

<120>: 
RECORD OF CLASS <224> # d
--------------------------------
rec = {
    
i = 0
    }
ary = {
    [0] 
FOR 11 = ""
    }

3.5. Editing a Text Form

A text form can be created or edited, and then read into memory, as long as it is syntactically and semantically correct. Values can be changed, fields and elements can be added or deleted, and records, ARRAYs, and data sections can be added or deleted. A text form can be created “from scratch”, and then read into memory as a structure or translated into a data image.

Two kinds of discrepancies are permitted to facilitate editing and subsequent reading of existing text forms:

  1. If a field name is used in a record or dataSec unit but is not declared in the corresponding CLASS unit, it is assumed that the user has deleted the declaration for the field in the CLASS unit, and hence the field specification is ignored (since the field does not exist in the record being initialized).

  2. If a field name is declared in a CLASS, but is not initialized in a referencing record or dataSec unit, it is assumed that the user has inserted the declaration for the field into the CLASS unit. Such fields are initialized to Zero.

Thus, the user can add or delete CLASS fields without having to update every referencing record or dataSec unit, thereby facilitating the editing of text forms.

The fields of a record unit need not appear in the same order as the fields of the corresponding CLASS unit. When the record is assembled in memory, the order of the memory fields is the order of the fields in the corresponding CLASS unit (this is subject to change if the way fields of a record are laid out in memory changes).

If the warning bit is set in the ctrlBits argument of $structureTextToData or the textFile form of $structureRead, a warning message is given whenever the first kind of discrepancy occurs.

3.6. Compressed Text Forms

The PROCEDUREs $structureWrite and $structureDataToText accept the ctrlBits bit $compressed, which indicates that a compressed text form is to be read or written. The use of the $compressed bit results in a text form that is more compact (and is processed faster) than a noncompressed text form, but is not human-readable. Compressed text forms are useful for structure files that must be transferred among different systems or MAINSAIL versions, but are not examined by human readers.

Compressed text forms are detected automatically on input.


previous   next   top   complete contents   complete index   framed top   this page unframed

MAINSAIL Structure Blaster User's Guide, Chapter 3