Geoff Chappell - Software Analyst
A module definition file specifies in text the information that LIB uses for creating an import library and export file.
LIB reads a module definition file with the usual text-mode translation of the C Run-Time Library. An end-of-file character (Ctrl-Z) terminates the text before the end of the actual file. A combination of carriage-return and line-feed in the actual file is seen by LIB as a lone line-feed in the text.
The presence of null bytes in the text complicates parsing from the very start. It is not usual to have these characters in a text file and LIB plainly does not expect them. Strange outcomes that may follow the presence of these characters in a module definition file have negligible consequence in practice, and it is assumed henceforth that the module definition file does not contain null bytes.
LIB parses the text as a sequence of lines. For this purpose, a line is a maximum of 4095 characters up to and including either a line-feed character or the last byte of text, whichever comes first.
A slightly different definition applies when numbering lines to aid the descriptions of warnings and errors. A whole line is any number of characters up to and including a line-feed. If the text does not end with a line-feed, then the partial line that starts immediately after the last line-feed is numbered as belonging to the preceding whole line.
On any given line, a terminating line-feed is ignored, as is a carriage-return immediately before it (which means as many as two carriage-returns in the actual file). In all that follows, a line is understood as ending immediately before such terminators.
On any given line, all leading white space is ignored. In all that follows, a line is understood as beginning only after leading white space has been ignored. White space is understood in the sense of the _ismbcspace function in Microsoft’s C Run-Time Library: namely, spaces, tabs, carriage-returns and line-feeds, but also some other control characters.
On any given line, all characters from the first semicolon onwards are ignored. The semicolon thus serves to introduce comments. A line that consists just of a comment is effectively empty. In all that follows, a line is understood as ending immediately before any semicolon.
A module definition file is also a sequence of statements. Each statement is a tag and some number of definitions, including none, whose interpretation depends on the tag. A statement that has a tag but no definitions is said to be empty. Whether an empty statement is an error depends on the tag.
A statement typically but not necessarily consists of whole lines. A definition always runs to the end of whatever line it starts on.
Wherever a statement starts, it begins with the tag, which is the remaining text on the same line up to but not including a space or tab (or, in a contrived case, an equals sign). After the space or tab, there may be any amount of white space, including none, before the statement’s first definition.
Some types of statement allow at most one definition, necessarily on the same line as the tag. This one definition is said to comprise the statement’s arguments. After a single-definition statement, the next non-empty line is expected to begin a new statement.
For a statement that allows more than one definition, each definition except the first is required to begin on a new line. A multi-definition statement ends where a new definition is permitted but a statement tag is recognised instead (and begins the next statement).
Statement tags are case-sensitive. The following are recognised:
CODE, DATA, DESCRIPTION, EXETYPE, EXPORTS, HEAPSIZE, IMPORTS, LIBRARY, NAME, PROTMODE, SECTIONS, SEGMENTS, STACKSIZE, STUB, VERSION, VXD
To have anything else where a new statement is expected causes a warning (LNK4017). The remainder of the line is ignored and a new statement is expected at the beginning of the next non-empty line.
The CODE, DATA, IMPORTS, PROTMODE statements are recognised but not supported. The DESCRIPTION, EXETYPE, STUB and VXD statements join this list unless LIB is given the /vxd switch (to build an export file for linking a VxD).
To have any of these where a new statement is either expected or permitted causes a warning (LNK4017). The remainder of the line is ignored and a new statement is expected at the beginning of the next line.
The multi-definition statements are EXPORTS, SECTIONS and SEGMENTS (which is anyway an alias of SECTIONS).
They are responsible for the contrivances noted above. A statement is able to start mid-line by following an empty multi-definition statement (the new statement being accepted where the multi-definition statement is permitted a first definition). A statement is able to have its tag be terminated by an equals sign if it follows an EXPORTS statement (due to a curiosity in the parsing of EXPORTS definitions).
LIB is not often run directly to process a module definition file. Instead, the module definition file is presented first to LINK, which then re-runs LINK.EXE as the Library Manager to generate a .EXP file such as might have been given to LINK in the first place as a LINK input file.
When a module definition file is processed this way, a fatal error during the processing of the module definition file therefore produces not just a message from LIB to describe the error in the module definition file but also a fatal error (LNK1141) from LINK.
When LINK prepares to re-run itself as LIB, not all options on the LINK command line carry to the LIB command line. Among those that do not is the undocumented /wx option. Thus, warnings that arise while LIB processes a module definition file for LINK cannot be arranged to be treated as errors.