-- file Kernel.Mesa
-- last edited by Sandman, July 10, 1980  2:45 PM
-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  BcdDefs USING [VersionStamp],
  BootmesaOps,
  CommanderDefs USING [CommandBlockHandle, AddCommand],
  ControlDefs USING [FrameHandle, GlobalFrameHandle],
  IODefs USING [CR, NUL, ReadChar, Rubout, WriteChar, WriteLine, WriteString],
  SegmentDefs USING [FileNameError],
  StreamDefs USING [NewByteStream, Read, StreamError, StreamHandle],
  String USING [AppendString],
  Time USING [Append, Unpack];

Kernel: PROGRAM
  IMPORTS
    BootmesaOps, CommanderDefs, IODefs, SegmentDefs, StreamDefs, String, Time =
  BEGIN OPEN BootmesaOps;
  
  FrameHandle: TYPE = ControlDefs.FrameHandle;
  GlobalFrameHandle: TYPE = ControlDefs.GlobalFrameHandle;
  
  root: STRING ← [40];
  
  Initialize: PROCEDURE =
    BEGIN OPEN Time, IODefs;
    timeofbuilding: STRING ← [18];
    version: BcdDefs.VersionStamp ← InitializeBootmesa[root];
    Append[timeofbuilding, Unpack[LOOPHOLE[version.time]]];
    timeofbuilding.length ← timeofbuilding.length - 3;
    WriteChar[CR];
    WriteString[root];
    WriteString[".Image -- "];
    WriteLine[timeofbuilding];
    RETURN
    END;
    
  Write: PROCEDURE =
    BEGIN OPEN BootmesaOps;
    InitializeImage[];
    MapResidentCode[];
    MapLoadStates[];
    MapSwappedInCode[];
    TurnOffStartTrap[];
    DeclareSegs[];
    DeclareCodeLinks[];
    WriteScriptSegments[];
    WriteImage[];
    AdjustBcd[fakebcdseg];
    InitializeLoadState[];
    XFER[dest: WartFrame[]];
    RETURN
    END;
    
  Load: PROCEDURE [name: STRING] =
    BEGIN OPEN SegmentDefs;
    s: STRING ← [40];
    String.AppendString[s, name];
    String.AppendString[s, ".bcd"];
    InitializeLoading[s];
    LoadModules[resident];
    InitializeHeap[];
    FinishLoading[];
    END;
    
  Build: PROCEDURE [name: STRING] =
    BEGIN
    OpenSource[name];
    ParseInput[];
    Initialize[];
    Load[name];
    Write[];
    CloseSource[];
    END;
    
  EndOfInput: SIGNAL = CODE;
  
  GetFromStream: PROCEDURE RETURNS [c: CHARACTER] =
    BEGIN
    c ← IODefs.NUL;
    c ← source.get[source ! StreamDefs.StreamError => GOTO end];
    RETURN
    EXITS end => SIGNAL EndOfInput;
    END;
    
  source: StreamDefs.StreamHandle;
  
  OpenSource: PROCEDURE [s: STRING] =
    BEGIN
    name: STRING ← [40];
    String.AppendString[name, s];
    String.AppendString[name, ".bootmesa"L];
    source ← StreamDefs.NewByteStream[
      name, StreamDefs.Read !
      SegmentDefs.FileNameError => BootmesaError["Input file not found!"L]];
    InitParse[GetFromStream, EndOfInput];
    RETURN
    END;
    
  CloseSource: PROCEDURE =
    BEGIN source.destroy[source]; FinishParse[]; RETURN END;
    
  -- main body code
  
  debugging: BOOLEAN ← FALSE;
  
  BuildSystem: PROCEDURE [n: STRING] =
    BEGIN OPEN IODefs;
    root.length ← 0;
    String.AppendString[root, n];
    Build[
      root ! Rubout => RETRY;
      BootAbort =>
	BEGIN
	WriteLine[" StartPilot aborted. Type any character to exit"L];
	[] ← ReadChar[];
	CONTINUE
	END];
    END;
    
  MakeSystem: PROCEDURE [input, output: STRING] =
    BEGIN OPEN IODefs;
    root.length ← 0;
    String.AppendString[root, output];
    Build[
      input ! Rubout => RETRY;
      BootAbort =>
	BEGIN
	WriteLine[" StartPilot aborted. Type any character to exit"L];
	[] ← ReadChar[];
	CONTINUE
	END];
    END;
    
  Init: PROCEDURE =
    BEGIN OPEN CommanderDefs;
    c: CommandBlockHandle;
    AddCommand["Build", LOOPHOLE[BuildSystem], 1].params[0] ←
      [type: string, prompt: "System Name"];
    c ← AddCommand["Make", LOOPHOLE[MakeSystem], 2];
    c.params[0] ← [type: string, prompt: "Input"];
    c.params[1] ← [type: string, prompt: "Output"];
    END;
    
  Init[];
  
  END..