-- Copyright (C) 1981, 1982, 1983  by Xerox Corporation. All rights reserved. 
-- PilotBootToEtherBoot.mesa
-- HGM,  8-Jan-83 11:34:20
-- Bruce, 23-Sep-81 13:14:23
-- Johnsson, 20-Dec-82 12:19:20

-- Operation:  This is a small program that converts a Pilot boot file into a pseudo Alto format boot file, suitable for use by a Pup Boot server.  All that is necessary to do this is to prefix the Pilot boot file with a page containing some header information (time stamp).  The EtherGerm (or microcode booter) must discard the leader page.

-- Usage:  PilotBootToEtherBoot can only be invoked from the command line with the following:
--	PilotBootToEtherBoot outputEtherBootFile ← inputPilotBootFile


DIRECTORY
  Environment USING [Byte, bytesPerPage, wordsPerPage],
  Exec USING [
    AddCommand, ExecProc, FreeTokenString, GetToken, Outcome, OutputProc],
  Format USING [Line, StringProc],
  Inline USING [HighHalf, LowHalf],
  MFile USING [Acquire, dontRelease, Error, Handle, Release],
  MStream USING [Create],
  Stream USING [Delete, GetBlock, Handle, PutBlock, SetInputOptions],
  String USING [Empty, Equal],
  Time USING [Packed, Current];

PilotBootToEtherBoot: PROGRAM
  IMPORTS Exec, Format, Inline, MFile, MStream, Stream, String, Time =
  BEGIN

  CopyFile: Exec.ExecProc =
    BEGIN
    bytesPerPage: CARDINAL = Environment.bytesPerPage;
    page: ARRAY [0..Environment.wordsPerPage) OF WORD ← ALL[0];
    buffer: LONG POINTER TO PACKED ARRAY [0..0) OF Environment.Byte =
      LOOPHOLE[LONG[@page]];
    now: Time.Packed = Time.Current[];
    output: Format.StringProc = Exec.OutputProc[h];
    outName, separater, inName, switches: LONG STRING ← NIL;
    in, out: Stream.Handle ← NIL;
    inFile, outFile: MFile.Handle;

    Cleanup: PROC [s: STRING] =
      BEGIN
      Format.Line[output, s];
      outName ← Exec.FreeTokenString[outName];
      separater ← Exec.FreeTokenString[separater];
      inName ← Exec.FreeTokenString[inName];
      IF in # NIL THEN Stream.Delete[in];
      IF out # NIL THEN Stream.Delete[out];
      END;

    [outName, switches] ← Exec.GetToken[h];
    switches ← Exec.FreeTokenString[switches];
    [separater, switches] ← Exec.GetToken[h];
    switches ← Exec.FreeTokenString[switches];
    [inName, switches] ← Exec.GetToken[h];
    switches ← Exec.FreeTokenString[switches];

    IF String.Empty[outName] THEN {
      Cleanup["Output filename is empty."L]; RETURN[error]};
    IF String.Empty[inName] THEN {
      Cleanup["Input filename is empty."L]; RETURN[error]};
    IF ~String.Equal[separater, "←"L] THEN {
      Cleanup["Separater must be ""←""."L]; RETURN[error]};

    inFile ← MFile.Acquire[
      name: inName, access: readOnly, release: MFile.dontRelease !
      MFile.Error =>
        IF code = noSuchFile THEN
          BEGIN Cleanup["Can't find Input File"L]; GOTO GetOutOfHere; END];
    outFile ← MFile.Acquire[
      name: outName, access: writeOnly, release: MFile.dontRelease !
      MFile.Error =>
        BEGIN
        MFile.Release[inFile];
        Cleanup["Can't Access Output File"L];
        GOTO GetOutOfHere;
        END];
    in ← MStream.Create[inFile, [NIL, NIL]];
    out ← MStream.Create[outFile, [NIL, NIL]];

    output["Copying boot file..."L];

    -- Write prefix blocks to make this look like an Alto Boot file:
    -- The first 5 words must agree with the format of an Alto boot file

    page[0] ← 1;  -- microcode booter version number (probably doesn't matter)
    page[1] ← 0;  -- or else boot file will get reformated
    page[3] ← Inline.HighHalf[now];  -- BCPL format
    page[4] ← Inline.LowHalf[now];
    -- We should probably put a version stamp and our version stamp in here
    Stream.PutBlock[
      out, [blockPointer: buffer, startIndex: 0, stopIndexPlusOne: bytesPerPage]];

    -- Copy the Pilot boot file to the output file:
    Stream.SetInputOptions[in, [FALSE, FALSE, FALSE, FALSE, FALSE, FALSE]];
    DO
      inBytes: CARDINAL;
      [inBytes, ] ← Stream.GetBlock[
        in, [
        blockPointer: buffer, startIndex: 0, stopIndexPlusOne: bytesPerPage]];
      SELECT inBytes FROM
        0 => EXIT;
        bytesPerPage =>
          Stream.PutBlock[
            out, [
            blockPointer: buffer, startIndex: 0, stopIndexPlusOne: bytesPerPage]];
        ENDCASE =>
          BEGIN
          -- This isn't supposed to happen.
          -- Finish the copy anyway since the output file is already trashed.
          Stream.PutBlock[
            out, [
            blockPointer: buffer, startIndex: 0, stopIndexPlusOne: inBytes]];
          Cleanup["Input file ends in a partial page."L];
          RETURN[warning];
          END;
      ENDLOOP;

    Cleanup["Done"L];
    RETURN[normal];

    EXITS GetOutOfHere => RETURN[error];
    END;


  Init: PROC = {Exec.AddCommand["PilotBootToEtherBoot.~"L, CopyFile]};

  Init[];

  END.

LOG

January 22, 1980  8:46 AM		Knutsen	Created file.
February 5, 1980  4:12 PM		HGM	Layer of fixups.
May 20, 1980  10:01 AM			Forrest	Mesa 6 argument order
11-May-81 20:48:28			HGM, Munge to (Pre)Cascade
23-Sep-81 12:01:05			Bruce, Convert to 8.0c
26-Oct-81 18:16:32			HGM, Bug fix, cleanup
17-Nov-81 16:08:40			HGM, Convert to MFile/MStream
21-Dec-81 20:42:06			HGM, Another FALSE for Stream.SetInputOptions