
                           OBJ/LIB file format
                           

.OBJ/.LIB ( object file )
-------------------------
This is the standard Intel object file format, with extra coment
records used by the 'make'. Only the subset generated by
TopSpeed compilers is described here. (The linker does however
support other record types such as iterated data etc.)

BNF

  <lib file>    ::= <lib-coment> { <object file> }
  <object file> ::= <header> { <item> } <trailer>

  <header> ::= 80H Length <string> Crc (* string is source name *)
  <trailer> ::=
              | 8AH Length 0 Crc    (* not program entry point *)
              | 8AH Length 0C1H 0 <segment-index> <segment-index> 0 0 Crc
                                    (* program entry point *)

  <item> ::=
           | <lnames>
           | <segdef>
           | <grpdef>
           | <extdef>
           | [ <io-priv-coment> ] <pubdef>
           | <ledata> [ <fixupp> ]
           | <source-date-coment>        (* used by make *)
           | <option-coment>             (* used by make *)
           | <include-object-coment>     (* used by make *)
           | <stack-heap-size-coment>
           | <shared-data-coment>   (* applies to last segdef *)


  <lnames> ::= 96H Length { <string> } Crc

  <segdef> ::= 98H Length Attr SegLen <name-index> <name-index> <name-index> Crc

  <grpdef> ::= 9AH Length <name-index> { 0FFH <segment-index> } Crc

  <extdef> ::= 8CH Length { <string> Type } Crc

  <pubdef> ::= 90H Length <group-index> <segment-index> [ Frame ] { <string> Offset Type } Crc

  <ledata> ::= 0A0H Length <segment-index> Offset { Byte } Crc

  <fixupp> ::= 9CH Length { Locat FixDat Index [ Index ] [ Offset ] } Crc

  <lib-coment> ::= COMENT Length 0C700H Hash Crc (* used by make *)

  <source-date_coment> ::= COMENT Length 0C500H Date { Char } Crc

  <option-coment> ::= COMENT Length 0C900H { Char } Crc

  <project-command-coment> ::= COMENT Length 0CF00H { Char } Crc

  <include-object-coment>  ::= COMENT Length 0CB00H { Char } Crc

  <stack-heap-size-coment> ::= COMENT Length 0CD00H HeapSize StackSize Crc

  <shared-data-coment> ::= COMENT Length 0CA00H Crc

  <io-priv-coment> ::= COMENT Length 0C800H Crc

  <string> ::= Len { Char }

  <name-index> ::= Index

  <group-index> ::= Index

  <segment-index> ::= Index

Terminal symbols:
  Length is a 2-byte value present in every record which is
  the length in bytes of the record - 3.

  Len is a 1-byte string length.

  Char is a 1-byte character, which should be a printing
  character.

  Crc is a 1-byte checksum. It is either zero or -(sum of
  bytes in record).

  Index is a 2 byte value represented as 1 or 2 bytes. If getb()
  returns the next byte from the file, a routine to fetch an
  Index is as follows:
    tmp := CARDINAL( getb() );
    IF tmp < 128 THEN
      RETURN tmp;
    ELSE
      RETURN ( tmp - 128 ) * 256 + CARDINAL( getb() );
    END;

  <lnames>, <extdef>, <pubdef>, <segdef> and <grpdef> records
  implicitly define indices which are then used to refer to the
  objects defined. The indices start from 1.

  Offset is a 2-byte offset in a segment.

  Frame is present only when the segment index for the public is
  zero (an absolute public), and is normally 0.

  Type is a 1-byte hash value in the range 0..127 used by the
  JPI linker to perform type-consistency checks (note that
  this is a deviation from standard Intel format where this is
  interpreted as a type-index, but existing linkers mostly ignore
  this field. If there is a problem the field could be set to
  zero by a utility program or by disabling smart linking.

  Byte is a 1-byte data value.

  Attr is the 1-byte segment attribute.

  SegLen is the 2-byte length of the segment.

  Locat (2 bytes) defines the offset in the preceding ledata
  record which is to be fixed up (bits 0..9), the kind of
  location (bits 10..12) and whether the fixup is non-relative
  (bit 14). Bit 15 is always 1, Bit 13 is always 0. The
  location kinds are 1=>offset, 2=>segment, 3=>pointer

  FixDat (1 byte) defines what kind of index is used for the
  target of the fixup (bits 0..1), whether the offset is
  missing (bit 2), and what kind of index is used for the
  frame of the fixup (bits 4..6). The bits 3 and 7 are zero.
  The encoding of the index kind is 0=><segment-index>,
  1=><group-index>, 2=><external-index>, 5=>no frame index,
  use target

  Hash is a 4-byte hash value used by the make system.

  Date is a 4-byte file date in MSDOS/OS2 format.

  HeapSize and StackSize are 2-byte values for the heap
  and stack of the program (specified by the data pragma
  in the main module).


.EXE/.DLL ( executable file format )
------------------------------------
The .exe/.dll file format is as follows:
   <exe file> ::= <standard exe file> <debug info> <trailer>
   <debug info> ::= <header> { <module info> } <end marker>
   <module info> ::= <module name size> <module name> <lseg count> { <lseg address> }

   <trailer> ::= longcard size of <standard exe file>
   <end marker> ::= byte 0
   <module name size> ::= byte size of following <module name>
   <lseg count> ::= word count of following <lseg address>
   <seg address> ::= word offset followed by word segment
   <header> ::= 'jpi0'

where <standard exe file> is the standard Microsoft .exe/.dll
format.

.DBD file ( debug information )
-------------------------------
The BNF for a modules debug data is as follows :

<module debug data>  ::= Mod  { <item> } EndMod
<item>               ::= <proc> | <var> | <type>
<proc>               ::= Proc { <item> } EndProc

<type>           ::= Signed
                   | Unsigned
                   | Float
                   | Char
                   | Boolean
                   | Procedure
                   | Indirect
                   | Array <type> <type>
                   | OpenArray <type> Aux
                   | Pointer <type>
                   | SubRange <type>
                   | Set <type>
                   | ShortPtr <type> Aux
                   | <simple>
                   | Rec { <field> } EndRec
                   | (Enum|SparseEnum) { EnumVal } EndEnum
                   .

<var>            ::= Var <type>
<field>          ::= Field <type> | BitField <type>

The terminal symbols in the grammar correspond to records of the
following type:

TYPE DbRec = RECORD (* variable size *)
  recsize : SHORTCARD; (* record size in bytes, including this byte *)
  CASE tag: DbRecKind OF
  | Source:
    sourcename : string;
  | Module:
    lang : SHORTCARD;
    ofs   : CARDINAL;
    seg   : CARDINAL; (* -1 => external *)
    name : string;
  | EndModule:
    modulesize : t_offset;
  | LineNum:
    line : ARRAY [0..62] OF RECORD (* variable size *)
      ofs : CARDINAL;
      num : CARDINAL;
    END;
  | Rte:
    rteofs : CARDINAL;
    rtenum : CARDINAL;
    rtecol : CARDINAL;
  | Var, Aux:
    varflags  : DbVarFlags;
    ofs    : CARDINAL; (* 1 => no address if local or param *)
    seg    : CARDINAL;
    name   : string;
  | Field:
    fieldofs  : CARDINAL;
    fieldname : string;
  | BitField:
    fieldofs  : CARDINAL;
    bitfieldbitofs : SHORTCARD;
    bitfieldsize   : SHORTCARD;
    bitfieldname : string;
  | Proc:
    procflags : DbProcFlags; (* the complete set is only in EndProc !! *)
    ofs   : CARDINAL;
    seg   : CARDINAL;
    name  : string;
  | EndProc:
    procflags : DbProcFlags;
    procsize : t_offset;
  | Indirect:
    handle : Handle;
  | Rec:
    typesize : CARDINAL;
    id : Handle;
  | EndRec:
  | Enum:
    typesize : CARDINAL;
    id : Handle;
  | EnumVal:
    enumval   : INTEGER;
    enumname  : string;
  | EndEnum:
  | Subrange:
    typesize : CARDINAL;
    rangehigh, rangelow:LONGCARD;
  | Signed, Unsigned, Float, Char, Boolean, Pointer, Procedure,
    Array, OpenArray, Set, ShortPtr:
    typesize:CARDINAL;
  ELSE
    b:ARRAY [0..252] OF SHORTCARD;
  END;
END;

  where

TYPE Handle = LONGCARD;
CONST Nil = MAX(Handle); (* 0FFFFFFFFH *)
TYPE string = ARRAY [0..127] OF CHAR; (* variable length *)
TYPE DbRecKind =
  ( Module, EndModule, LineNum, Rte, Var, Proc, EndProc, Indirect, Rec,
    EndRec, Enum, EnumVal, Field, BitField, EndEnum, Subrange, Void,
    Signed, Unsigned, Float, Char, Boolean, Pointer, Procedure, Array,
    OpenArray, Set, ShortPtr, Source, Aux
  );

TYPE DbVarTypeEnum = ( varparam, valparam,local,nonvolatile);
TYPE DbVarFlags = SET OF DbVarTypeEnum;

TYPE DbProcTypeEnum = (near,NoFrame,VarArg,OptVarArg);
TYPE DbProcFlags = SET OF DbProcTypeEnum;


An Indirect record is a pointer to an Enumeration or Record type
so that these types can be re-used.

Note that the following records expect sub types to follow
(i.e. be defined immediately afterwards)
  Array     expects <Index type> + <Element type> to follow
  OpenArray expects <Element type> + Aux to follow
  Pointer   expects <dereferenced type> to follow
  Subrange  expects <base type> to follow
  Set       expects <element type> to follow
  ShortPtr  expects <dereferenced type> + Aux to follow

The segment values correspond to segment indices in the .OBJ
file, and are translated into run-time segment values using
the VID information at the end of the .EXE/.DLL file.

.SES, .CFG, .HLP files
----------------------
not yet done

