(*
    Title: 	Read and decode an M-Code file - Definitions
    LastEdit:	"Tue Sep 20 17:50:49 1983"
    Author: 	Mick Jordan
		Cambridge University Computer Laboratory
*)

DEFINITION MODULE ReadMcd;
(*  This module can be used to read and M-Code files.
    The M-Code file is decoded into
    a set of data structures which are exported by this module.
*)

FROM Streams IMPORT Stream;

EXPORT QUALIFIED 
    SetMcdStream,
    IMPORTFRAME, IMPORTFRAMEPTR, MCDERROR,
    KEY, KEYSIZE, MODULENAME, MODULENAMESIZE,
    Headerframe, Importlist, Version, McdError, Frametype,
    ReadMCode, CodeByte, SetCodeByte, Dataframe, Fixupframe, Stringframe,
    CodeSize, DataSize, FixupSize, StringSize, ProcadrSize,
    StringConstantBase, BytesperWord, ImportlistLength;

PROCEDURE SetMcdStream (s : Stream);

PROCEDURE ReadMCode(debug: BOOLEAN);
(*  Call ReadMCode to read and decode the M-Code file.
    If debug=TRUE, trace decoding to SysOut.
*)

CONST MODULENAMESIZE = 16;		(* The max size of a module name*)
CONST KEYSIZE = 3;			(* The size of a module key   *)

TYPE BYTE = [0 .. 255];
TYPE KEY = ARRAY [1 .. KEYSIZE] OF CARDINAL;
TYPE MODULENAME = ARRAY [0 .. MODULENAMESIZE-1] OF CHAR;

TYPE IMPORTFRAMEPTR = POINTER TO IMPORTFRAME;
TYPE IMPORTFRAME = 
(*  Used for Import frames and the header frame *)
    RECORD
        link: IMPORTFRAMEPTR;
        name: MODULENAME;		(* in string byte order	      *)
	key:  KEY;
        datasize: CARDINAL;		(* only for Headerframe - in words *)
    END;

TYPE MCDERROR =	
    (
        McdOK,
        UnknownFrametype,
        ModuleframeMissing,
        CodeframeOverflow,
        DataframeOverflow,
        FixupframeOverflow,
        StringframeOverflow
    );

VAR McdError: MCDERROR;
(*  If the M-Code file is corrupt or one of the frame arrays overflows,
    the variable McdError will be set to one of the above indicators.
    If McdError = McdOK then the decode was successful.
*)

VAR Frametype: CARDINAL;
(*  Set to the value of UnknownFrameType.
*)

(*  These values could be adjusted if one of the overflow errors occurs *)
CONST
    Maxcode = 10000;
    Maxdata = 4;
    Maxstring = 4000;
    Maxfixup = 1000;

(*    CodeFrame Array Hidden by these procedures (if you call this hiding)  *)

PROCEDURE SetCodeByte (ByteNo, Op : CARDINAL);

PROCEDURE CodeByte (ByteNo : CARDINAL) : CARDINAL;

VAR Dataframe: ARRAY [0 .. Maxdata-1] OF CARDINAL;
(*  This contains the contents of the separate dataframes,
    with the data (in words) stored at the correct offsets.
*)

VAR Stringframe: ARRAY [0 .. Maxstring-1] OF CHAR;
(*  This contains the contents of the separate stringframes.
    Individual strings are padded with nulls to an integral
    number of target implementation wordlengths.

    The base address of the constant string area (i.e where
    the string frame should be loaded is provided in the
    variable StringConstantBase.
*)

VAR Fixupframe: ARRAY [0 .. Maxfixup-1] OF CARDINAL;
(*  This contains a list of the byte-offsets in the codeframe
    which need fixing (external module numbers).
*)

CodeSize, DataSize, FixupSize, StringSize: CARDINAL;
(*  These variables hold the first free location in the
    above arrays respectively, in other words the number
    of elements in the array.
*)

VAR ProcadrSize: CARDINAL;
(*  This variable holds the offset of the first byte of real code
    in the Codeframe after the procedure entry table.
    In other words, the size of the table in BYTEs.
*)

VAR StringConstantBase: CARDINAL;
(*  This variable is set to the base address (as an index into
    the data frame) in the
    dataframe where the Stringframe should be loaded.
*)

VAR Version: ARRAY [0 .. 7] OF CHAR;
(*  This is the M-code version string from the version frame.
*)

VAR BytesperWord: CARDINAL;
(*  This is the number of bytes per word assumed by the M-code
    compiler when generating the M-code file.
*)

VAR Importlist: IMPORTFRAMEPTR;
(*  This is a pointer to a list of IMPORTFRAME records, which contain
    the data extracted from the import frames.
*)

VAR ImportlistLength: CARDINAL;
(*  The number of entries on the IMPORT list.
*)

VAR Headerframe: IMPORTFRAMEPTR;
(*  This is a pointer to an IMPORTFRAME record which contains
    the data from the header frame.
*)


END ReadMcd .
