Binary Device Files
From Open Watcom
Contents |
Introduction
The binary device file format is used for two distinct purposes:
- To encode :DEVICE, :DRIVER, and :FONT blocks.
- To provide a directory file.
The directory file is used to allow device names of up to 78 characters to be used, even on file systems which restrict file name length (i.e., FAT). The 78-character limit is documented in theWGML Reference.
The attributes that are used to build the entries in the directory file are discussed in Common Attributes.
Preliminary Notes
Psuedo-Code Format
The decoded structures in the binary device files are expressed in a "sort-of C struct" form which should make the structure found clear to anyone reading this Wiki. They may or may not be valid "C" code.
These are not the structs that are used in the code. The binary device files contain many count bytes and designators which simply are not needed by wgml after the binary device file has been parsed. Indeed, in many instances, their only role in parsing the binary device file is to be read and checked to be certain that they have the correct value.
Fields are referred to in these ways:
- If the field is part of the struct under discussion, the field name is used by itself.
- If the field is part of another struct, then the struct name is prepended with . as a separator.
- If the field is part of an instance of another struct (that is, of a field in yet another struct) then the parent field's name is prepended with . as a separator.
The last two cases are distinguishable: struct names start with capital letters, field names start with lower case.
Source Format
Many of the discussions of the specifics of the binary device file format include notes on the actual form of the source code accepted by gendev 3.33 and gendev 4.1. This section is intended to summarize common rules discovered governing that form, so that they need not be repeated in each section and sub-section.
All of the statements made here were confirmed by actual test. Many of them match statements made in the WGML Reference or the README file produceable from the WGML 3.33 Update and should be taken as confirming the documentation, not as new discoveries. Those which contradict the documentation or which provide information not included in the documentation are new discoveries.
Block Structure
These statements apply unless otherwise noted in the discussion of a particular block:
- Although the documentation and all available source files show each entry on its own line, this is not required and multiple elements can be placed on the same line.
- The attributes which are present can appear in any order.
- For blocks that include both attributes and sub-blocks, all of the attributes which are present must appear before any sub-block or this error message is seen:
AT--001: Required attribute not found.
- Blocks which produce CodeBlocks (:VALUE, etc) must not be empty or this error message appears:
SN--034: Expecting text before termination tag.
Orthography
These statements apply unless otherwise noted in the discussion of a particular block:
- Except for character and string values, each character may be upper or lower case individually. This applies to tags, attribute names, and predefined attribute values. NOTE: it is yet to be determined if character and string values match regardless of case.
- Characters can be entered as such but must be delimited when used as an attribute value; if not delimited then either this message:
SN--001: Number is too large or contains invalid characters
or this message:
AT--002: Missing attribute value
appears, apparently depending on whether or not the character entered can be interpreted by gendev as a "number". NOTE: if the character happens to be a decimal digit, then it will be indistinguishable from and so taken as a decimal number.
- Characters used in :INTRANS, :OUTTRANS, and :WIDTH blocks are neither attributes nor attribute values, and should be entered without delimiters.
- Characters can be entered as decimal numbers, with no delimiters or prefixes.
- Characters can be entered as hexadecimal numbers, with no delimiters but with a $ prefix.
- Decimal or hexadecimal numbers (used to represent characters) which are delimited are treated as one or more characters.
- If more than one character is entered, then this error message appears:
AT--007: The attribute value cannot have more than one character
- Character strings can always use delimiters.
- Character strings with no embedded spaces do not need to be delimited in most contexts; the known exception is that the value of attribute font of the :BOX or :UNDERSCORE block must be delimited if a character string is used, presumably to distinguish them from a font number, or this error message results:
SN--001: Number is too large or contains invalid characters
- Undelimited character strings with embedded spaces produce this error message:
AT--001: Required attribute not found
Since more than one attribute can be placed on the same line, the first word after the space cannot be distinguished from the next attribute name.
These statements apply to both character and string delimiters:
- Either single or double quotes may be used.
- The quote on each end must be the same type (single or double), or this error message appears:
AT--005: Missing or invalid closing quote on attribute
Further experimentation with one attribute, font_out_name1, showed that
$B5$C4'fred'$C3
was encoded by gendev as
$B5$C4fred$C3
just as if the entire string were delimited or, since it does not have spaces, no delimiters were used at all. More intriguingly,
'testfon_outname1'$C5
was encoded by gendev as
testfon_outname1
suggesting that gendev treats a closing delimiter as the end of the string. These details will have to be further explored when gendev is being recreated.
Differences Between Versions
There are some differences between version 3.33 and version 4.1. This section provides a summary. For more information, see the sections discussing the details of the binary device file format.
- The file headers are different.
- The directory files are slightly different.
- These numeric attributes are encoded as two-byte unsigned integers in version 3.33 and as four-byte unsigned integers in version 4.1:
For :DEVICE blocks: 3.33 upper limit 4.1 upper limit
page_width $CCCF $7FFFFFFF
page_depth $CCCF $7FFFFFFF
horizontal_base_units $CCCF $7FFFFFFF
vertical_base_units $CCCF $7FFFFFFF
For :PAGESTART blocks:
x_start $CCCF $7FFFFFFF
y_start $CCCF $7FFFFFFF
For :PAGEOFFSET blocks:
x_start $CCCF $7FFFFFFF
y_start $CCCF $7FFFFFFF
For :FONT blocks:
line_height $CCCF $7FFFFFFF
line_space $CCCF $7FFFFFFF
scale_basis $7FFFFFFF $7FFFFFFF
scale_min $7FFFFFFF $7FFFFFFF
scale_max $7FFFFFFF $7FFFFFFF
char_width $CCCF $7FFFFFFF
For :DBOX, :HLINE, and :VLINE blocks:
thickness (not determined)
- The :WIDTH block comes in two sizes, and the larger size is different in version 3.33 than it is in version 4.1.
Invariant Order
The order in which items appear in a binary device file does not depend on the order in which the various components of the encoded block appear in the source file. It does not matter if the order in the source file is fixed or if it can vary.
The order shown for all fields of all structs shown is the only order in which those fields appear. All of these fields are required in the sense that, if they are not present, the file contains a clear indicator that they are not present, which is to say that all fields are present, if only vistigially. This is the reason that a file error or premature end-of-file while reading a binary device file is the same as an error in the format: the format requires that all fields be present, if only vistigially, so their complete absence is a formatting error.
Common Semantic Elements
Parsing a binary device file involves reducing it to semantically meaningful units, and the bulk of this page (and associated pages) deals with those units in detail. These units are composed of semantic elements, which can be classified into three groups:
- Character data, which can hold any byte value.
- String data, which cannot include null bytes.
- 8-bit, 16-bit, and 32-bit unsigned integers.
Unless otherwise noted in the detailed discussions, character data has these properties:
- Each character has its own unique significance, even when multiple characters appear in sets.
Unless otherwise noted in the detailed discussions, string data has these properties:
- The significance of a string lies in the entire string taken as a unit, not in the individual characters.
- Most strings are preceeded by a count byte; any "terminating null" in this case is part of the next semantic element.
- Some strings are instead terminated by a null byte, which is part of the string considered as a semantic element in the binary device file.
Unless otherwise noted in the detailed discussions, integers have these properties:
- The values are unsigned.
- 8-bit values are used to count the number of following bytes, which may be character or numeric data as well as strings or even sementic units containing several semantic elements.
- Internal data, such as counts of repeated semantic units, are encoded by 16-bit values.
- Attributes which are encoded as 16-bit values in version 3.33 are encoded as 32-bit values in version 4.1.
Analysis Technique
The basic tool in analyzing the binary device file format was a small set of test source files. These files changed so rapidly that no attempt was made to preserve their various versions.
Attributes with character or string values were located in the binary device file by providing them with a known value in the source file and looking for it in the binary device file, and then changing it in the source file to confirm that the value found in the binary device file also changed.
Attributes with numeric values were located using the decimal equivalents of such values as "0x1111", "0x2222" and so on for 16-bit integers and "0x11111111", "0x22222222" and so on for 32-bit integers (note that each attribute was given a distinct value) and then looking for those values in the binary file. Once the location were found, since I am using a x86 processor which stores integers in "little-endian" format, values such as "0x1122" or "0x11223344" were used to confirm that they are, in fact, stored as integers and not just as arrays of bytes.
The remaining unsigned integers are produced by gendev all on its own, so it is not possible to be certain that they are, in fact, unsigned integers. It is, perhaps, a personal bias that I identify these as integers rather than as arrays of bytes. Unless a big-endian version of one or more binary device files appears, it will never be possible to be certain that these identifications are correct.
As each major type of binary device file was analyzed, the corresponding test file was reworked to form a set of test files which could be used with wgml to determine which CodeBlocks are invoked at what points in creating the output file. This was used to determine, for those :INIT blocks which produce multiple CodeBlocks, the order in which the CodeBlocks are invoked. This led to the interesting discovery that they are invoked by wgml 4.0 in the order given in the source, and that the CodeBlocks encoding :FONTVALUE blocks are invoked multiple times, which, insofar as the struct used for parsing is concerned, meant that each CodeBlock had to be identified as encoding a :VALUE block or a :FONTVALUE block as well as having their order preserved. I expect this sort of investigation to be very helpful when the time comes to produce the output side of wgml.
Device Library File Formats
The Header
Here is what wdump -b produces when applied to the wgmlst.cop file in ow\docs\doc\whelp:
0000: 02 0C 00 0B 56 34 2E 31 20 50 43 2F 44 4F 53 04 V4.1 PC/DOS 0010: 02 00 00 00 01 02 08 77 68 65 6C 70 64 72 76 08 whelpdrv 0020: 57 48 45 4C 50 44 52 56 01 01 05 77 68 65 6C 70 WHELPDRV whelp 0030: 05 57 48 45 4C 50 00 00 00 00 00 00 00 00 00 00 WHELP 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Examining other binary device files shows that every binary device file has a header with this structure:
COPHeader {
uint8_t count = { 0x02 };
uint16_t version;
uint8_t text_version_length;
char text_version[ text_version_length ];
uint8_t type;
};
The field count gives the number of bytes in the field version. It can, however, also be used as a "magic value", since any file starting with a different byte cannot be a binary device file.
The the field version differs between version 3.33 and version 4.1:
- version 3.33: 0x000a
- version 4.1: 0x000c
and so is taken to encode the file version. Testing shows that gendev and wgml from one version will not work with binary device files produced by gendev from the other version.
The field length contains the length of the field text_version.
The field text_version differs between version 3.33 and version 4.1:
- version 3.33: V3.33 PC/DOS
- version 4.1: V4.1 PC/DOS
and clearly contains human-readable text giving the version number.
The field type is also a count field, but the values it can contain can also be used to indicate the type of the file:
- version 3.33: 0x02: directory file
- either version: 0x03: device/driver/font file
- version 4.1: 0x04: directory file
while the true significance of the value is:
- 0x02: a two-byte count of directory entries
- 0x03: a three-byte discriminator ("DEV", "DRV" or "FON")
- 0x04: a four-byte count of directory entries
Ending the header with what is, in fact, the count byte for the next field may appear strange. This does make sense when parsing the file is considered: if the function parsing the header simply indicated that it was working on a valid binary device file, each calling function (and there are four of them) would then have to determine for itself whether or not that file was a directory file. It is simpler and more efficient to make this determination in the function parsing the header.
The research program cfcheck.exe has verified that all available binary device files have either 0x02, 0x03, or 0x04 as the value of the count field type. Research programs cfparse.exe and copparse.exe have thoroughly exercised the header parsing code.
The Directory File
Take another look at the contents of the wgmlst.cop file in ow\docs\doc\whelp:
0000: 02 0C 00 0B 56 34 2E 31 20 50 43 2F 44 4F 53 04 V4.1 PC/DOS 0010: 02 00 00 00 01 02 08 77 68 65 6C 70 64 72 76 08 whelpdrv 0020: 57 48 45 4C 50 44 52 56 01 01 05 77 68 65 6C 70 WHELPDRV whelp 0030: 05 57 48 45 4C 50 00 00 00 00 00 00 00 00 00 00 WHELP 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
At first glance, the file (after the header) is as simple as this:
DirFile {
uint32_t count;
DirEntry entries[count];
};
The file illustrated is a version 4.1 directory file. Comparison with a version 3.33 directory file gives this structure for the version 3.33 directory file:
DirFile {
uint16_t count;
DirEntry entries[count];
};
At this point, the page Directory File Format might be worth examining. It explains the actual format currently found in the directory file ow\docs\gml\syslib\wgmlst.cop.
The value of the field count is the number of entries, at least, that is what it clearly contained in the directory files I produced with either version of gendev (the directory file discussed in Directory File Format is, as in so much else, an exception to this).
The compact directory file entries are the defined name/member name pairs which it is the entire purpose of a directory file to provide. They have this structure:
CompactDirEntry {
uint16_t type = < 0x0101 | 0x201 | 0x401 >;
uint8_t defined_name_length;
char defined_name[defined_name_length];
uint8_t member_name_length;
char member_name[member_name_length];
};
The extended directory file entries have this structure:
ExtendedDirEntry {
uint16_t metatype = 0x0001;
uint16_t type = < 0x0101 | 0x201 | 0x401 >;
uint8_t defined_name_length;
char defined_name[defined_name_length];
uint16_t marker = 0x0001;
uint8_t member_name_length;
char member_name[member_name_length];
uint16_t preview = < 0x0101 | 0x201 | 0x401 >;
};
These fields are common to the two structures:
uint16_t type = < 0x0101 | 0x201 | 0x401 >;
uint8_t defined_name_length;
char defined_name[defined_name_length];
uint8_t member_name_length;
char member_name[member_name_length];
The values of the field type have these values:
- 0x101 for a binary device file encoding a :DEVICE block.
- 0x201 for a binary device file encoding a :DRIVER block.
- 0x401 for a binary device file encoding a :FONT block.
The program cfparse.exe has confirmed that, in each case where the binary device file exists, the type and the Discriminator are consistent with the interpretations given above.
The fields defined_name_length and member_name_length provide the number of characters in the associated string.
The field defined_name encodes the value of the attribute defined_name and field member_name encodes the value of the attribute member_name. These attributes are discussed in the section Common Attributes.
These fields are unique to the extended structure:
uint16_t metatype = 0x0001;
uint16_t marker = 0x0001;
uint16_t preview = < 0x0101 | 0x201 | 0x401 >;
- The field metatype indicates that this is an extended rather than a compact DirEntry structure.
- The field marker always has the same value, but it is not clear why it is needed.
- The values of the field preview have the same meaning as the values of the field type but match the value of the field type field of the following DirEntry.
The page Directory File Format should be consulted if more information on the extended structure is needed.
Device Library Member Files
The entire point of a device library is to provide files encoding information used by wgml to format a document for a particular device. The term used for all such files up to this section has been "binary device file". However, now that the directory file has been examined, the term "binary member file" will be used to refer to any of the three remaining types of binary device file. Thus, up to this point, the terms "directory file" and "binary member file" refer to the two main varieties of binary device files.
The three types of binary member files, each corresponding to a particular source code block, are:
- A device file describes the device.
- A driver file provides code which, when executed, will produce the proper commands to control the device.
- A font file describes a particular font, usually for use with a specific device or set of devices.
When these terms are used by themselves, they should be understood to refer to the concepts rather than any specific file. When source or binary is prepended, then they should be understood to refer to the source format or to the binary format (respectively). When file is appended, then the they should be understood to refer to an actual file containing either the source or the binary data, unless "source" or "binary" is prepended to indicate that the reference is specific. Thus, in this section, a "binary device file" is a binary member file which encodes a :DEVICE block describing the device.
Since both version 3.33 and version 4.1 headers use the same type byte (0x03) for these files, and the directory files use the same types (0x101, 0x201 and 0x401) to identify them, it should come as no surprise that there are very few differences between the two versions. A summary of those differences can be found here.
Discriminator
The first item in each binary member file is a three-byte discriminator:
char discriminator[3] = <'D','E','V' for a device, 'D','R','V' for a driver, or 'F','O','N' for a font>
gendev does check to see that a source file whose defined name already exists in the directory file has the same member name as found for that defined name in the directory file, but whether it checks that the value in the field DirEntry.type is consistent with whether the member source file being processed is a device, driver, or font file is not known at this time -- and, even if it did, checking the descriminator of the existing file would appear to be pointless, since that file will be overwritten by a new one based on the block being processed.
wgml always knows what type of binary member file it is searching for: the only defined name that can correspond to a :DEVICE block is the defined name entered with the DEVICE command line option; the only defined name that can correspond to a :DRIVER block is the one given as the value of the attribute driver_name (which is an attribute found only in a :DEVICE block); and the only defined names that can correspond to :FONT blocks are those given as the values of the various attributes font or fontname (which attributes are found only in a :DEVICE block).
The discriminator, then, can be treated as a final sanity check: if it is the value expected, the file is to be processed; if not, an error is to be reported.
Device File Format
The Source Format
The :DEVICE block was changed from the description in WGML Reference by the README file produceable from the WGML 3.33 Update. The result of this is rather disjointed, so I will be exploring the source file format as well as the binary file format.
All of the statements made describing the requirements imposed on the :DEVICE block by gendev were confirmed by actual test. Many of them match statements made in the documentation or the README and should be taken as confirming the documentation, not as new discoveries.
Due to the size and complexity of the device formats, a separate page, Device File Blocks, will be used to explore the blocks included in the :DEVICE block.
Except as noted, the version 4.1 and version 3.33 source and binary formats for the device file are identical. And, as will be seen, the differences can be detected without having to know the version of the binary file being parsed.
This is the :DEVICE block:
:DEVICE Attributes :PAUSE Block :DEVICEFONT Block :DEFAULTFONT Block :FONTPAUSE Block :BOX Block :UNDERSCORE Block :PAGESTART Block :PAGEOFFSET Block :INTRANS Block :OUTTRANS Block :eDEVICE.
Device File Blocks uses the tags (or "Attributes") to identify the blocks.
The README documents the removal of the :RULE block, which used the tags :RULE and :eRULE and which is no longer allowed, and the changes to the :BOX block (using the tag :DBOX instead of :BOX, which is confusing since :DBOX is a valid tag used in :DRIVER blocks), but the presence of the :PAGEOFFSET block, :INTRANS block, and :OUTTRANS block is not documented in either the WGML Reference or in the wgml 3.33 README as possible blocks inside a :DEVICE block; instead, they were discovered by examining existing source files containing :DEVICE blocks. The structure of the :INTRANS block and of the :OUTTRANS block are documented as part of the :FONT block. The :PAGEOFFSET block is not documented at all (except for an error message for a missing :ePAGEOFFSET tag).
These included blocks are required (the error triggered by each if absent is also shown):
- The Attributes:
AT--001: Required attribute not found.
- The :BOX block:
SN-054: Expecting :box tag.
- The :DEFAULTFONT block:
SN--021: Must have a :defaultfont with font=0.
- The :DEVICEFONT block is required because the font names which are used by the :DEFAULTFONT block (at least one of which must be present) and which may be used by the :BOX block must also be used in a :DEVICEFONT block:
SN-019: Fontname not specified in :devicefont.
- The :FONTPAUSE block is required for every :DEVICEFONT block which provides a name for the attribute fontpause (the same value must appear in the attribute type of the :FONTPAUSE block). Note that an empty string can be used for the attribute fontpause of the :DEVICEFONT block, in which case no :FONTPAUSE block is required.
SN--022: The fontpause in :devicefont has no match in :fontpause.
These included blocks are completely optional:
- The :INTRANS block
- The :OUTTRANS block
- The :PAGEOFFSET block
- The :PAGESTART block
- The :PAUSE block
- The :UNDERSCORE block
These included blocks can have multiple instances:
- The :DEFAULTFONT block
- The :DEVICEFONT block
- The :FONTPAUSE block
- The :INTRANS block
- The :OUTTRANS block
- The :PAUSE block
Extensive tests of block ordering revealed this fact:
All blocks present must be in the order shown.
The details (potentially useful in creating gendev) are:
- If the :PAUSE block follows the :DEVICEFONT block, this error message is produced:
SN-054: Expecting :box tag.
and, if it follows the :BOX block, this error message results:
SN--043: Expecting :edevice tag
- If the :DEVICEFONT block whose value for the attribute fontname matches the value for the attribute fontname used by a :DEFAULTFONT block follows that :DEFAULTFONT block, or if the :DEVICEFONT block whose value for the attribute fontname matches the value for the attribute font used by the :BOX block follows the :BOX block, then this error message results:
SN-019: Fontname not specified in :devicefont.
- If a :DEVICEFONT block whose fontname is not used by a :DEFAULTFONT block is placed after all of the :DEFAULTFONT blocks but before the :BOX block, this error message is produced:
SN-054: Expecting :box tag.
- A :DEVICEFONT block whose fontname is not used anywhere else which is placed after the :BOX block produces this error message:
SN--043: Expecting :edevice tag
- A :DEFAULTFONT block which is placed after the :BOX block produces this error message:
SN--043: Expecting :edevice tag
- A :FONTPAUSE block which is placed before all :DEVICEFONT blocks produces this error message:
SN-054: Expecting :box tag.
- A :FONTPAUSE block which is placed after the :BOX block produces this error message:
SN--043: Expecting :edevice tag
- A :RULE block placed before the :BOX block produces this error message:
SN-054: Expecting :box tag.
when placed after the :BOX block it produces this error message:
SN--043: Expecting :edevice tag
this shows that a :RULE block is no longer allowed in a :DEVICE block.
- If the :BOX block is placed in front of any :PAUSE block or the :DEVICEFONT block whose value for the attribute fontname matches the value for the attribute font value in the :BOX block, then this error message results:
SN-019: Fontname not specified in :devicefont.
- If the :BOX block is placed after all :PAUSE block and after the :DEVICEFONT Block whose value for the attribute fontname matches the value for the attribute font value in the :BOX block, but before the required :DEFAULTFONT block,
this error message results on the :DEFAULTFONT line of the first :DEFAULTFONT block:
SN--043: Expecting :edevice tag
- If the :BOX block is placed after all :PAUSE blocks and after all :DEVICEFONT blocks and after all :DEFAULTFONT blocks, then this error message results on the :FONTPAUSE line of the first :FONTPAUSE block:
SN--043: Expecting :edevice tag
- If the :BOX block is placed after the :UNDERSCORE block, the :PAGESTART block, the :PAGEOFFSET block, an :INTRANS block, or an :OUTTRANS block, then this error message appears:
SN-054: Expecting :box tag.
- If the :UNDERSCORE block, the :PAGESTART block, the :PAGEOFFSET block, an :INTRANS block, or an :OUTTRANS block is placed anywhere before the :BOX block, then this error message appears:
SN-054: Expecting :box tag.
- If the :UNDERSCORE block is placed after the :PAGESTART block, the :PAGEOFFSET block, an :INTRANS block, or an :OUTTRANS block then this error message appears:
SN--043: Expecting :edevice tag
- If the :PAGESTART block is placed after the :PAGEOFFSET block, an :INTRANS block, or an :OUTTRANS block then this error message appears:
SN--043: Expecting :edevice tag
- If the :PAGEOFFSET block is placed after an :INTRANS block or an :OUTTRANS Block, then error message appears:
SN--043: Expecting :edevice tag
- If an :INTRANS Block is placed after an :OUTTRANS Block, then this error message appears.
SN--043: Expecting :edevice tag
Testing produced these additional results:
- This error message:
SN--043: Expecting :edevice tag
appears if more than one instance of the Attributes, the :BOX block, the :UNDERSCORE block, the :PAGESTART block, or the :PAGEOFFSET block is placed in the source file.
The Binary Format
Now we come to the binary format used to encode the above structure. Device File Blocks contains the format of the blocks in the resulting binary device file, usually as part of the description of the corresponding source block. The exceptions are:
- The FunctionsBlock, which is a Variant A FunctionsBlock as discussed in Device Functions, encodes the :VALUE blocks of both the :PAUSE blocks and the :FONTPAUSE blocks.
- The PageGeometryBlock, as discussed in Device File Blocks, encodes both the :PAGESTART block and the :PAGEOFFSET block.
- The TranslationBlock, as discussed in Device File Blocks, encodes both the :INTRANS blocks and the :OUTTRANS blocks.
- The attributes defined_name and member_name and the :INTRANS block and the :OUTRANS block are discussed in Common File Blocks.
Here is the overall format of the binary device file, starting with the first byte after the discriminator:
DeviceFile {
Attributes attributes;
uint16_t next_codeblock;
PagegeometryBlock pagegeometry;
BoxBlock box;
UnderscoreBlock underscore;
TranslationBlock translation;
DefaultfontBlock defaultfonts;
FunctionsBlock functions;
PauseBlock pauses;
DevicefontBlock devicefonts;
}
The field next_codeblock requires some explanation. This is the same sort of value found in the fields pauses.start_pause, pauses.document_pause, pauses.docpage_pause, pauses.devpage_pause, and devicefont.devicefonts[].font_pause: it is the sum of the values of all fields functions.codeblocks[].count.
Now that it is known that the compiled code in field CodeBlock.function is, on its highest level, a linked list with a termination indicator, so that the length of the field is not needed to interpret it, a possible use for the field next_codeblock appears: perhaps wgml is using it to allocate a block of memory, copying the CodeBlock.function fields into it in order, and then using the values in the fields pauses.start_pause, pauses.document_pause, pauses.docpage_pause, pauses.devpage_pause, and devicefont.devicefonts[].font_pause as offsets into this block.
This structure has these properties:
- It is correct for both version 3.33 and version 4.1.
- Every field is always present, whether the corresponding sub-block was present in the source file or not.
- Every field is always present in the order shown.
Sizing Data
This table shows the number of bytes allocated for the cop_device object, the number of bytes actually used, and the size of each binary device file in the Open Watcom repository development branch:
Device File: Allocated Used File Size HELP 2048 530 560 PS 4096 3324 2480 TASA 2048 530 560 TERM 2048 686 720 WHELP 2048 531 560
This table shows the number of bytes allocated for the cop_device object, the number of bytes actually used, and the size of each binary device file produced by gendev 4.1 from the source files provided in the WGML 3.33 Update:
Device File: Allocated Used File Size ASA 2048 529 560 DIA630 2048 579 640 ELQ850DR 2048 829 880 ELQ805LQ 2048 808 800 HPFAXSYS 2048 1798 1600 HPLASER 11264 10333 8160 HPLASRII 13312 12424 9760 HPLASRPL 11264 10568 8320 HPLPLEGL 11264 10566 8320 MLT 2048 559 640 MLTEXP 2048 576 640 PCGRAPH 2048 609 640 PCMATRIX 2048 571 640 PROX24E 2048 732 800 PS 4096 3268 2480 QUME 2048 634 640 TASA 2048 530 560 TERM 2048 686 720 TTY 2048 529 560 X2700 2048 853 880
The code currently begins by allocating 2048 bytes and then increases the block, if necessary, by multiples of 1024. The above suggests that an initial value of 1024 and an increase of 3072 (for PS) would work as well (or better, since PS would then require only one reallocation) for the devices actually in use. However, it appears that realloc() could be used to shrink each the cop_device instance to the actual size needed, freeing the additional space, in which case starting at 4096 would be fastest for the devices used by Open Watcom since, for those devices, no expansion would be needed.
Driver File Format
The Source Format
The :DRIVER block was changed from the description in WGML Reference by the README file produceable from the WGML 3.33 Update. The result of this is rather disjointed, so I will be exploring the source file format as well as the binary file format.
All of the statements made describing the requirements imposed on the :DRIVER block by gendev were confirmed by actual test. Many of them match statements made in the documentation or the README and should be taken as confirming the documentation, not as new discoveries.
Due to the size and complexity of the driver formats, a separate page, Driver File Blocks, will be used to explore the blocks included in the :DRIVER block.
Except as noted, the version 4.1 and version 3.33 source and binary formats for the driver file are identical. And, as will be seen, the differences can be detected without having to know the version of the binary file being parsed.
This is the :DRIVER block:
:DRIVER Attributes :INIT Block :FINISH Block :NEWLINE Block :NEWPAGE Block :HTAB Block :FONTSTYLE Block :FONTSWITCH Block :PAGEADDRESS Block :ABSOLUTEADDRSS Block :HLINE Block :VLINE Block :DBOX Block :eDRIVER
Driver File Blocks uses the tags (or "Attributes") to identify the blocks.
The README documents the removal of the :BOLDSTART, :BOLDEND, :UNDERSTART, and :UNDEREND blocks, their replacement with the :FONTSTYLE block, and that a :NEWLINE block is no longer required "if :ABSOLUTE is specified". The :FONTSTYLE Block is not documented at all (except for two error messages: SN-084 and SN-088).
These included blocks are required (the error triggered by each if absent is also shown):
- The Attributes:
AT--001: Required attribute not found
- The :NEWPAGE block:
SN--033: Expecting :newpage tag
- Either an :ABSOLUTEADDRESS block or a :NEWLINE block with an attribute advance value of "1" is required. If there is no :ABSOLUTEADDRESS block and no :NEWLINE block, then this error message results:
DF--011: Need a newline with an advance of 1
These included blocks are completely optional:
- The :DBOX block
- The :FINISH block
- The :FONTSTYLE block
- The :FONTSWITCH block
- The :HLINE block
- The :HTAB block
- The :INIT block
- The :PAGEADDRESS block
- The :VLINE block
These included blocks can have multiple instances:
- The :FINISH block
- The :FONTSTYLE block
- The :FONTSWITCH block
- The :INIT block
- The :NEWLINE block
The :FINISH block and the :INIT block can have at most two instances; the others which can have multiple instances can have as many as needed.
Extensive tests of block ordering show these results:
- Although the WGML Reference states that "[w]hen [the blocks] are specified, they must be in the order shown in [the figure showing the structure]", exhaustive (and exhausting) testing shows that the blocks can, in fact, occur in any order whatsoever, so long as they are all placed after the Attributes.
The phrase "any order whatsoever" means exactly what it says:
- If two :INIT blocks are present, it does not matter whether the block with the value START for the attribute place comes before or after the block with the value DOCUMENT for the attribute place.
- If two :FINISH blocks are present, it does not matter whether the block with the value END for the attribute place comes before or after the block with the value DOCUMENT for the attribute place.
- If more than one :NEWLINE block is present, they can be in any order by the value of the attribute advance.
- Whenever more than one instance of the same included block is present, the instances do not have to be grouped in any fashion: each instance can be placed anywhere in the file, before or after any instance of any included block, provided only that the Attributes come first.
Testing produced these additional results:
- Including any of the :BOLDSTART, :BOLDEND, :UNDERSTART, or :UNDEREND blocks produces this error message at the start of the first which is encountered:
SN--036: Expecting :edriver tag
this shows that these blocks are no longer allowed in a :DRIVER block.
- Using a value other than START or DOCUMENT for the attribute place in an :INIT block produces this error:
AT--003: Invalid attribute value
- A second :INIT block with the value START or DOCUMENT for the attribute place produces this statement:
Place value was already used.
and this error message:
AT--004: Attribute already found
- Using a value other than END or DOCUMENT for the attribute place in a :FINISH block produces this error:
AT--003: Invalid attribute value
- A second :FINISH block with the value END or DOCUMENT for the attribute place produces this statement:
Place value was already used.
and this error:
AT--004: Attribute already found
- The values for the attribute advance of the :NEWLINE block, when more than one block is present, need not be contiguous.
- Multiple :FONTSWITCH blocks may be placed in the source file; however, if more than one :FONTSWITCH block has the same value for the attribute type, this error message results:
SN--030: Duplicate :fontswitch type
- Multiple :FONTSTYLE blocks may be placed in the source file; however, if more than one :FONTSTYLE block has the same value for the attribute type, this error message results:
SN--084: Duplicate :fontstyle type
- There can be at most one :PAGEADDRESS block; if a second :PAGEADDRESS block is encountered, this error results:
SN--066: More than one :pageaddress specified
- There can be at most one :ABSOLUTEADDRESS block; if a second :ABSOLUTEADDRESS block is found, this error message appears:
SN--067: More than one :absoluteaddress specified
- There can be at most one :HLINE block; if a second :HLINE block is found, this error message appears:
SN--075: More than one :hline specified
- There can be at most one :VLINE block; if a second :HLINE block is found, this error message appears:
SN--076: More than one :vline specified
- There can be at most one :DBOX block; if a second :DBOX block is found, this error message appears:
SN--077: More than one :dbox specified
The Binary Format
Now we come to the binary format used to encode the above structure. Driver File Blocks contains the format of the blocks in the resulting binary driver file, usually as part of the description of the corresponding source block. The exceptions are:
- The various FunctionsBlock variants, and the CodeBlock structure, are discussed in Device Functions.
- The attributes defined_name and member_name are discussed in the section Common Attributes.
Here is the overall format of the binary driver file, starting with the first byte after the discriminator:
DriverFile {
Attributes attributes;
PageAddressBlock pageaddress;
InitFuncs inits;
FinishFuncs finishes;
NewlineFuncs newlines;
FunctionsBlock unknown;
FunctionsBlock newpage;
FunctionsBlock htab;
FontswitchFuncs fontswitches;
FontstyleGroup fontstyles;
FunctionsBlock absoluteaddress;
HlineBlock hline;
VlineBlock vline;
DboxBlock dbox;
};
Fields of type FunctionsBlock are all Variant A FunctionsBlocks.
The field unknown is a blank P-buffer. While other possibilities doubtless exist, I suspect one of these is the correct explanation:
- There may be an unknown block that can occur in a :DRIVER but for which we have neither documentation nor example.
- This may have been where the :BOLDSTART, :BOLDEND, :UNDERSTART, and :UNDEREND blocks were encoded, when they were allowed in a :DRIVER block, if they were encoded in a single FunctionsBlock of some sort.
This structure has these properties:
- It is correct for both version 3.33 and version 4.1.
- Every field is always present, whether the corresponding sub-block was present in the source file or not.
- Every field is always present in the order shown.
Sizing Data
This table shows the number of bytes allocated for the cop_driver object, the number of bytes actually used, and the size of each binary driver file in the Open Watcom repository development branch:
Device File: Allocated Used File Size HELPDRV 2048 710 1520 PSDRV 8192 8074 9120 TASADRV 2048 874 1920 TERMDRV 2048 325 1600 WHELPDRV 3072 2586 3920
This table shows the number of bytes allocated for the cop_driver object, the number of bytes actually used, and the size of each binary driver file produced by gendev 4.1 from the source files provided in the WGML 3.33 Update:
Device File: Allocated Used File Size ASADRV 2048 856 1840 D630DRV 2048 1352 2560 DR850DRV 2048 1556 2560 HPLDRV 2048 1377 2240 HPLPDRV 3072 2976 4000 HPLPLDRV 3072 2976 4000 LQ850DRV 2048 1881 3120 MLTDRV 2048 1535 2400 MLTEDRV 2048 1942 2800 PCMADRV 2048 1083 2000 PSDRV 8192 7368 8320 QUMEDRV 2048 1633 2800 TASADRV 2048 874 1920 TERMDRV 2048 313 1520 TTYDRV 2048 844 1920 X24EDRV 2048 1478 2560 X2700DRV 2048 1963 2640
The code currently begins by allocating 2048 bytes and then increases the block, if necessary, by multiples of 1024. The above suggests that an initial value of 3072 (for WHLPDRV) and an increase of 5120 (for PS) would work well for the drivers actually in use. However, it appears that realloc() could be used to shrink each the cop_driver instance to the actual size needed, freeing the additional space, in which case starting at 8192 would be fastest for all of the drivers listed above, whether used by Open Watcom or not, since no expansion would be needed.
Font File Format
The Source Format
The :FONT block was changed from the description in WGML Reference by the README file produceable from the WGML 3.33 Update. Although the :FONT block is so simple that the result of this can not really be called "disjointed", I will still be exploring the source file format as well as the binary file format.
All of the statements made describing the requirements imposed on the :FONT block by gendev were confirmed by actual test. Many of them match statements made in the documentation or the README and should be taken as confirming the documentation, not as new discoveries.
Although the :FONT block is not nearly as complicated as either the :DEVICE or the :DRIVER block, a separate page, Font File Blocks, will nevertheless be used to explore the blocks included in the :FONT block.
Except as noted, the version 4.1 and version 3.33 source and binary formats for the font file are identical. And, as will be seen, the differences can be detected without having to know the version of the binary file being parsed.
This is the :FONT block:
:FONT Attributes :WIDTH Block :INTRANS Block :OUTTRANS Block :eFONT.
Font File Blocks uses the tags (or "Attributes") to identify the blocks.
The README documents the removal of the attribute mono_space_width from the Attributes.
The manual gives this info (in reference to the :WIDTH, :INTRANS and :OUTTRANS Blocks):
Each of the character definition blocks are optional, and may be specified more tha[n] once and in any order. If specified, they must follow the font attributes.
Which aptly describes the situation, when emended as shown.
The Binary Format
Now we come to the binary format used to encode the above structure. Font File Blocks contains the format of the blocks in the resulting binary device file, usually as part of the description of the corresponding source block. The exceptions are:
- The CharacterDescriptionBlock, as discussed in Font File Blocks, encodes the :INTRANS blocks, the :OUTTRANS blocks, and the :WIDTH blocks.
- The attributes defined_name and member_name and the :INTRANS block and the :OUTRANS block are discussed in Common File Blocks.
Here is the overall format of the binary font file, starting with the first byte after the discriminator:
FontBlock {
Attributes attributes;
CharacterDescriptionBlock characterBlock;
}
At this level of abstraction, this format is not very complicated at all. The CharacterDescriptionBlock, as discussed in Font File Blocks, compensates for this by being rather intricate.
Sizing Data
This table shows the number of bytes allocated for the cop_font object, the number of bytes actually used, and the size of each binary font file in the Open Watcom repository development branch:
Font File: Allocated Used File Size MONO01 2048 52 80 PSAB 2048 1092 1120 PSABO 2048 1099 1120 PSAD 2048 1092 1120 PSADO 2048 1099 1120 PSBD 2048 1089 1120 PSBDI 2048 1095 1120 PSBL 2048 1090 1120 PSBLI 2048 1096 1120 PSCB 2048 65 80 PSCO 2048 60 80 PSCOB 2048 68 80 PSCOBO 2048 72 80 PSHN 2048 1093 1120 PSHNB 2048 1098 1120 PSHNBO 2048 1105 1120 PSHNO 2048 1101 1120 PSHV 2048 1086 1120 PSHVB 2048 1091 1120 PSHVBO 2048 1098 1120 PSHVO 2048 1094 1120 PSNB 2048 1098 1120 PSNBI 2048 1104 1120 PSNI 2048 1100 1120 PSNR 2048 1099 1120 PSPB 2048 1090 1120 PSPBI 2048 1096 1120 PSPI 2048 1092 1120 PSPR 2048 1091 1120 PSSHADE 2048 52 80 PSSYM 3072 2519 2000 PSTR 2048 1088 1120 PSTRB 2048 1087 1120 PSTRBI 2048 1093 1120 PSTRI 2048 1089 1120 PSZAP 2048 1089 1120
This table shows the number of bytes allocated for the cop_font object, the number of bytes actually used, and the size of each binary font file produced by gendev 4.1 from the source files provided in the WGML 3.33 Update:
Font File: Allocated Used File Size DIAPROP 2048 1076 320 HP1C10B8 2048 73 80 HP1C10BC 2048 74 80 HP1C10BE 2048 73 80 HP1C10BN 2048 74 80 HP1C10I8 2048 73 80 HP1C10IC 2048 74 80 HP1C10IE 2048 73 80 HP1C10IN 2048 74 80 HP1C10M8 2048 73 80 HP1C10MC 2048 74 80 HP1C10ME 2048 73 80 HP1C10MN 2048 74 80 HP1C12I8 2048 73 80 HP1C12IC 2048 74 80 HP1C12IE 2048 73 80 HP1C12IN 2048 74 80 HP2H14B8 2048 1097 400 HP2H14BC 2048 1098 400 HP2H14BE 2048 1097 400 HP2H14BN 2048 1098 400 HP2T08M8 2048 1095 400 HP2T08MC 2048 1096 400 HP2T08ME 2048 1095 400 HP2T08MN 2048 1096 400 HP2T12B8 2048 1097 400 HP2T12BC 2048 1098 400 HP2T12BE 2048 1097 400 HP2T12BN 2048 1098 400 HP2T12I8 2048 1097 400 HP2T12IC 2048 1098 400 HP2T12IE 2048 1097 400 HP2T12IN 2048 1098 400 HP2T12M8 2048 1097 400 HP2T12MC 2048 1098 400 HP2T12ME 2048 1097 400 HP2T12MN 2048 1098 400 HPAC12B8 2048 73 80 HPAC12I8 2048 73 80 HPBH14BA 2048 1101 400 HPBT08MA 2048 1095 400 HPBT10BA 2048 1097 400 HPBT10IA 2048 1097 400 HPBT10MA 2048 1097 400 HPCC12B8 2048 73 80 HPCC12BA 2048 73 80 HPCC12BF 2048 73 80 HPCC12BG 2048 73 80 HPCC12BH 2048 73 80 HPCC12BI 2048 73 80 HPCC12BK 2048 73 80 HPCC12BS 2048 73 80 HPCC12BW 2048 73 80 HPCC12I8 2048 73 80 HPCC12IA 2048 73 80 HPCC12IF 2048 73 80 HPCC12IG 2048 73 80 HPCC12IH 2048 73 80 HPCC12II 2048 73 80 HPCC12IK 2048 73 80 HPCC12IS 2048 73 80 HPCC12IW 2048 73 80 HPCC12M8 2048 73 80 HPCC12MA 2048 73 80 HPCC12MF 2048 73 80 HPCC12MG 2048 73 80 HPCC12MH 2048 73 80 HPCC12MI 2048 73 80 HPCC12MK 2048 73 80 HPCC12MS 2048 73 80 HPCC12MW 2048 73 80 HPCN09M8 2048 77 80 HPCN09MA 2048 77 80 HPCN09MF 2048 77 80 HPCN09MG 2048 77 80 HPCN09MH 2048 77 80 HPCN09MI 2048 77 80 HPCN09MK 2048 77 80 HPCN09MS 2048 77 80 HPCN09MW 2048 77 80 HPDP10B8 2048 73 80 HPDP10BA 2048 73 80 HPDP10I8 2048 73 80 HPDP10IA 2048 73 80 HPDP10M8 2048 73 80 HPDP10MA 2048 73 80 HPEG12B8 2048 73 80 HPEG12BA 2048 73 80 HPEG12I8 2048 73 80 HPEG12IA 2048 73 80 HPEG12M8 2048 73 80 HPEG12MA 2048 73 80 HPFH14B8 2048 1101 400 HPFH14BA 2048 1101 400 HPFN09M8 2048 77 80 HPFN09MA 2048 77 80 HPFT08M8 2048 1095 400 HPFT08MA 2048 1095 400 HPFT10B8 2048 1097 400 HPFT10BA 2048 1097 400 HPFT10I8 2048 1097 400 HPFT10IA 2048 1097 400 HPFT10M8 2048 1097 400 HPFT10MA 2048 1097 400 HPFXC12B 2048 88 160 HPFXC12M 2048 88 160 HPFXH08M 2048 1096 400 HPFXH10B 2048 1096 400 HPFXH10I 2048 1096 400 HPFXH10M 2048 1096 400 HPFXH12B 2048 1096 400 HPFXH12I 2048 1096 400 HPFXH12M 2048 1096 400 HPFXH14B 2048 1096 400 HPFXH14I 2048 1096 400 HPFXH14M 2048 1096 400 HPFXH18B 2048 1096 400 HPFXH24B 2048 1096 400 HPFXT08M 2048 1096 400 HPFXT10B 2048 1096 400 HPFXT10I 2048 1096 400 HPFXT10M 2048 1096 400 HPFXT12B 2048 1096 400 HPFXT12I 2048 1096 400 HPFXT12M 2048 1096 400 HPFXT14B 2048 1096 400 HPFXT14I 2048 1096 400 HPFXT14M 2048 1096 400 HPFXT18M 2048 1096 400 HPFXT24M 2048 1096 400 HPGL12MD 2048 73 80 HPGP07MA 2048 75 80 HPGP07ML 2048 75 80 HPGP10BA 2048 73 80 HPGP10BL 2048 73 80 HPGP10IA 2048 73 80 HPGP10IL 2048 73 80 HPGP10MA 2048 73 80 HPGP10ML 2048 73 80 HPHC12BA 2048 73 80 HPHC12BL 2048 73 80 HPHC12IA 2048 73 80 HPHC12IL 2048 73 80 HPHC12MA 2048 73 80 HPHC12ML 2048 73 80 HPHL12MD 2048 73 80 HPHP07MA 2048 75 80 HPHP07ML 2048 75 80 HPIC12B8 2048 73 80 HPIC12BC 2048 74 80 HPIC12BE 2048 73 80 HPIC12BN 2048 74 80 HPIC12M8 2048 73 80 HPIC12MA 2048 73 80 HPIC12MC 2048 74 80 HPIC12ME 2048 73 80 HPIC12MN 2048 74 80 HPIC12MX 2048 73 80 HPIN09M8 2048 77 80 HPIN09MA 2048 77 80 HPIN09MC 2048 78 80 HPIN09ME 2048 77 80 HPIN09MN 2048 78 80 HPIN09MX 2048 77 80 HPJP07M8 2048 75 80 HPJP07MA 2048 75 80 HPJP07MM 2048 75 80 HPJP10B8 2048 73 80 HPJP10BA 2048 73 80 HPJP10I8 2048 73 80 HPJP10IA 2048 73 80 HPJP10M7 2048 73 80 HPJP10M8 2048 73 80 HPJP10MA 2048 73 80 HPJP10MM 2048 73 80 HPJP10MO 2048 74 80 HPKT08M8 2048 1095 400 HPKT08MA 2048 1095 400 HPKT08MM 2048 1095 400 HPKT10B8 2048 1097 400 HPKT10BA 2048 1097 400 HPKT10I8 2048 1097 400 HPKT10IA 2048 1097 400 HPKT10M7 2048 1097 400 HPKT10M8 2048 1097 400 HPKT10MA 2048 1097 400 HPKT10MM 2048 1097 400 HPKT10MO 2048 1098 400 HPLC12B8 2048 73 80 HPLC12I8 2048 73 80 HPLN09M8 2048 77 80 HPMP10B8 2048 73 80 HPMP10I8 2048 73 80 HPMP10M8 2048 73 80 HPNG12B8 2048 73 80 HPNG12I8 2048 73 80 HPNG12M8 2048 73 80 HPPT10B8 2048 1097 400 HPPT10I8 2048 1097 400 HPPT10M8 2048 1097 400 HPQC12B8 2048 73 80 HPQC12I8 2048 73 80 HPQG12B8 2048 73 80 HPQG12M8 2048 73 80 HPRG14MA 2048 73 80 HPRG14ML 2048 73 80 HPRL14MD 2048 73 80 HPRR14BA 2048 74 80 HPRR14BL 2048 74 80 HPRR16BA 2048 75 80 HPRR16BL 2048 75 80 HPRR18BA 2048 75 80 HPRR18BL 2048 75 80 HPTH06MA 2048 1095 400 HPTH08BA 2048 1095 400 HPTH08MA 2048 1095 400 HPTH10BA 2048 1097 400 HPTH12BA 2048 1097 400 HPTH14BA 2048 1097 400 HPUG10M8 2048 77 80 HPUH06M8 2048 1095 400 HPUH08M8 2048 1095 400 HPUH10B8 2048 1097 400 HPUH12B8 2048 1097 400 HPUH14B8 2048 1097 400 HPUL12MD 2048 73 80 HPVG10M8 2048 77 80 HPVH06M8 2048 1095 400 HPVH08M8 2048 1095 400 HPVH10B8 2048 1097 400 HPVH12B8 2048 1097 400 HPVH14B8 2048 1097 400 HPVL12MD 2048 73 80 HPW346M8 2048 74 80 HPW381M8 2048 74 80 HPWG10M8 2048 77 80 HPWG10MA 2048 77 80 HPWG14M8 2048 73 80 HPWG14MA 2048 73 80 HPWL12MD 2048 73 80 HPWO12MR 2048 73 80 HPXB12MB 2048 73 80 HPXG10M8 2048 77 80 HPXG10MA 2048 77 80 HPXG14M8 2048 73 80 HPXG14MA 2048 73 80 HPXL12MD 2048 73 80 HPYC12B8 2048 73 80 HPYC12I8 2048 73 80 HPYC12M8 2048 73 80 HPYN09M8 2048 77 80 HPZH08M8 2048 1095 400 HPZH08MA 2048 1095 400 HPZH08ME 2048 1095 400 HPZH10B8 2048 1097 400 HPZH10BA 2048 1097 400 HPZH10BE 2048 1097 400 HPZH10I8 2048 1097 400 HPZH10IA 2048 1097 400 HPZH10IE 2048 1097 400 HPZH10M8 2048 1097 400 HPZH10MA 2048 1097 400 HPZH10ME 2048 1097 400 HPZH12B8 2048 1097 400 HPZH12BA 2048 1097 400 HPZH12BE 2048 1097 400 HPZH12I8 2048 1097 400 HPZH12IA 2048 1097 400 HPZH12IE 2048 1097 400 HPZH12M8 2048 1097 400 HPZH12MA 2048 1097 400 HPZH12ME 2048 1097 400 HPZH14B8 2048 1097 400 HPZH14BA 2048 1097 400 HPZH14BE 2048 1097 400 HPZN09M8 2048 77 80 HPZN09MA 2048 77 80 HPZN09ME 2048 77 80 HPZT08M8 2048 1095 400 HPZT08MA 2048 1095 400 HPZT08ME 2048 1095 400 HPZT10B8 2048 1097 400 HPZT10BA 2048 1097 400 HPZT10BE 2048 1097 400 HPZT10I8 2048 1097 400 HPZT10IA 2048 1097 400 HPZT10IE 2048 1097 400 HPZT10M8 2048 1097 400 HPZT10MA 2048 1097 400 HPZT10ME 2048 1097 400 HPZT12B8 2048 1097 400 HPZT12BA 2048 1097 400 HPZT12BE 2048 1097 400 HPZT12I8 2048 1097 400 HPZT12IA 2048 1097 400 HPZT12IE 2048 1097 400 HPZT12M8 2048 1097 400 HPZT12MA 2048 1097 400 HPZT12ME 2048 1097 400 HPZT14B8 2048 1097 400 HPZT14BA 2048 1097 400 HPZT14BE 2048 1097 400 LQ850C17 2048 52 80 LQ850D10 2048 54 80 LQ850D12 2048 54 80 LQ850D15 2048 54 80 LQ850D17 2048 52 80 LQ850D20 2048 52 80 LQ850E12 2048 54 80 LQ850E20 2048 52 80 LQ850M15 2048 54 80 LQ850P10 2048 54 80 LQ850PRO 2048 1076 320 MLTRES 2048 52 80 MONO01 2048 52 80 MONO07 2048 52 80 MONO12 2048 52 80 MONO12H8 2048 52 80 MONO24 2048 52 80 PSAB 2048 1092 1120 PSABO 2048 1099 1120 PSAD 2048 1092 1120 PSADO 2048 1099 1120 PSBD 2048 1089 1120 PSBDI 2048 1095 1120 PSBL 2048 1090 1120 PSBLI 2048 1096 1120 PSCB 2048 65 80 PSCO 2048 60 80 PSCOB 2048 68 80 PSCOBO 2048 72 80 PSHN 2048 1093 1120 PSHNB 2048 1098 1120 PSHNBO 2048 1105 1120 PSHNO 2048 1101 1120 PSHV 2048 1096 1120 PSHVB 2048 1091 1120 PSHVBO 2048 1098 1120 PSHVO 2048 1094 1120 PSNB 2048 1098 1120 PSNBI 2048 1104 1120 PSNI 2048 1100 1120 PSNR 2048 1099 1120 PSPB 2048 1090 1120 PSPBI 2048 1096 1120 PSPI 2048 1092 1120 PSPR 2048 1091 1120 PSSYM 3072 2519 2000 PSTR 2048 1088 1120 PSTRB 2048 1087 1120 PSTRBI 2048 1093 1120 PSTRI 2048 1089 1120 PSZAP 2048 1089 1120 QUME10 2048 52 80 QUME12 2048 52 80 QUMEPROP 2048 1076 320 X24EC10 2048 52 80 X24EC17 2048 52 80 X24EE12 2048 52 80 X24EPRO 2048 1076 320 XBOPS 2048 1094 400 XBOPSBIO 3072 2150 640 XBOPSBO 3072 2149 640 XBOPSIO 3072 2149 640 XBOPSO 3072 2148 640 XCP125O 2048 1125 400 XCP14 2048 1093 400 XEL12 2048 1095 400 XEL12BO 3072 2150 640 XEL12O 3072 2149 640 XKO10 2048 1096 400 XKO10B 2048 1097 400 XKO12 2048 1096 400 XKO12B 2048 1097 400 XKO14 2048 1096 400 XKO6 2048 1095 400 XKO8 2048 1095 400 XKO8B 2048 1096 400 XLG10BO 3072 2157 640 XLG10O 3072 2156 640 XLG12 2048 1102 400 XLG12BO 3072 2157 640 XLG12O 3072 2156 640 XLG15BO 3072 2157 640 XLG15O 3072 2156 640 XMA12BO 3072 2151 640 XMA12O 3072 2150 640 XOA10 2048 1094 400 XOB10 2048 1094 400 XSC10 2048 1097 400 XSP10 2048 1099 400 XSP10BO 3072 2154 640 XSP10O 3072 2153 640 XTI10 2048 1095 400 XTI10B 2048 1096 400 XTI10BIO 3072 2151 640 XTI10BO 3072 2150 640 XTI10I 2048 1096 400 XTI10IO 3072 2150 640 XTI10O 3072 2149 640 XTI12BO 3072 2150 640 XTI12IO 3072 2150 640 XTI12O 3072 2149 640 XTJ10BO 3072 2151 640 XTJ10O 3072 2150 640 XTRPS 2048 1095 400 XTRPSBO 3072 2150 640 XTRPSO 3072 2149 640 XVI10BO 3072 2152 640 XVI10O 3072 2151 640 XVI12 2048 1097 400 XVI12BO 3072 2152 640 XVI12O 3072 2151 640
The code currently begins by allocating 2048 bytes and then increases the block, if necessary, by multiples of 1024. The above suggests that this should work all right in almost all cases. It appears that realloc() could be used to shrink each the cop_font instance to the actual size needed, freeing the additional space, in which case starting at 3072 would be fastest for all of the fonts listed above, whether used by Open Watcom or not, since no expansion would be needed.
Padding
All available binary device files (in general, that is, including both directory files and binary member files) have been checked by the research program cfcheck.exe and have a length which is a multiple of 16. This is true for both version 3.33 and version 4.1 files. Whether this is necessary (that is, whether wgml requires it) is not yet known.

