-- File: HelloLisp.mesa
-- Edit  23-Aug-84 10:18:20 Masinter
-- Created  9-Jul-84 15:06:38 Lichtenberg

DIRECTORY
  File USING [Type, 
    Create, Delete, File, MakePermanent, nullFile, PageNumber, PageCount, GetSize, SetSize, Unknown ],
  FileTypes USING [tUntypedFile],
  OthelloDefs,
  OthelloOps USING [
    BootFileType, 
    MakeBootable, MakeUnbootable, 
    GetPhysicalVolumeBootFile, VoidPhysicalVolumeBootFile,
    SetVolumeBootFile, GetVolumeBootFile, VoidVolumeBootFile
    ],
  PhysicalVolume USING [ID],
  Space USING [Map, CopyIn, Unmap, Window],
  TemporaryBooting USING [InvalidParameters],
  Volume USING [Close, ID, GetAttributes, nullID, InsufficientSpace, Open ];

-- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

HelloLisp: PROGRAM
  IMPORTS
   File, OthelloDefs, OthelloOps, Space, TemporaryBooting, Volume =
 
  BEGIN
  


  
  CopyVM: PROC = BEGIN
    fromVolume, toVolume: Volume.ID;
    fromFile, toFile: File.File;
    pvID: PhysicalVolume.ID;
    error: BOOLEAN ← FALSE;
    currentBase: File.PageNumber;
    nextCount: File.PageCount;
    fromWindow,toWindow: Space.Window;
    toPointer: LONG POINTER;
    fromFileSize: File.PageCount;
    tries: CARDINAL;
    toFileSize: File.PageCount;
    minFileSize: File.PageCount;
    
    OthelloDefs.MyNameIs[
      myNameIs: "Copy Lisp From Another Volume"L,
      myHelpIs: "Copies lisp from one volume to another"L];
      
      [pvID, fromVolume] ← OthelloDefs.GetLvIDFromUser[prompt:"Volume to copy from: "L];
      IF fromVolume = Volume.nullID THEN OthelloDefs.AbortingCommand["Invalid volume."L];
      toVolume ← OthelloDefs.GetLvIDFromUser[prompt:"Volume to copy to:  "L].lvID;
      IF toVolume = Volume.nullID THEN OthelloDefs.AbortingCommand["Invalid volume."L];
      
      -- Open up the volumes
      Volume.Open[fromVolume];
      Volume.Open[toVolume];
      
      -- Is there a source file?
      fromFile ← OthelloOps.GetVolumeBootFile[fromVolume,hardMicrocode].file;
      IF fromFile = File.nullFile THEN {
      		Volume.Close[fromVolume];
      		Volume.Close[toVolume];
      		OthelloDefs.AbortingCommand["No Lisp sysout on source volume"L];
		};
      
      -- Is there a dest file? Delete it if yes.
      
      toFile ← OthelloOps.GetVolumeBootFile[toVolume,hardMicrocode].file;
      IF toFile # File.nullFile THEN {
      	   OthelloOps.VoidVolumeBootFile[toVolume,hardMicrocode];
	   File.Delete[toFile];
	   IF OthelloOps.GetPhysicalVolumeBootFile[pvID,hardMicrocode].file = toFile
	   THEN OthelloOps.VoidPhysicalVolumeBootFile[pvID,hardMicrocode];
	   };
      
      -- Create the dest file
      
      fromFileSize ← File.GetSize[fromFile];
      toFileSize ← fromFileSize;
      tries ← 20;
      toFile ← File.Create[toVolume, toFileSize, FileTypes.tUntypedFile
      			! Volume.InsufficientSpace => 
			    { tries ← tries - 1;
			      toFileSize ← toFileSize - 100;
			      OthelloDefs.WriteString["."L];
			      IF tries = 0 OR toFileSize < 0 THEN {error ← TRUE;
			    		CONTINUE}
			      ELSE RETRY;};];
						    
      IF error THEN {Volume.Close[fromVolume];
      		     Volume.Close[toVolume];
      		     OthelloDefs.AbortingCommand["Destination volume does not contain sufficient space!"L];};
      File.MakePermanent[toFile];
      
      -- Create windows onto the file

      OthelloDefs.WriteString["Copying..."L];
      currentBase ← 0;
      nextCount ← 100;
      
      minFileSize ← fromFileSize;
      IF toFileSize < fromFileSize THEN minFileSize ← toFileSize;
      
      DO -- until file has been copied
       
         fromWindow ← [file: fromFile,
      		       base: currentBase,
		       count: nextCount];

         toWindow ← [file: toFile,
      		     base: currentBase,
		     count: nextCount];
     
         toPointer ← Space.Map[toWindow].pointer;
	 nextCount ← Space.CopyIn[toPointer,fromWindow];
	 toPointer ← Space.Unmap[toPointer];
	 
	 currentBase ← currentBase + nextCount;
	 
	 OthelloDefs.WriteString["."L];

         IF currentBase >= minFileSize THEN EXIT; 
	 
      ENDLOOP;
      
      OthelloDefs.WriteString["Installing..."L];
      OthelloOps.MakeBootable[toFile, hardMicrocode, OthelloDefs.leaderPages
           ! TemporaryBooting.InvalidParameters => {
             OthelloDefs.WriteLine["Warning, trouble making bootable"L]; CONTINUE}];

      OthelloOps.SetVolumeBootFile[toFile,hardMicrocode,OthelloDefs.leaderPages];

      OthelloDefs.WriteLine["done"L];
          
      Volume.Close[fromVolume];
      Volume.Close[toVolume];
      
      END;
      
-- UGH.. This kludge sets the file's size to be as big as Pilot will let it be, on 100 page increments.

  SetBootFileSize: PRIVATE PROC[file: File.File, lvID: Volume.ID] = BEGIN
    tries: CARDINAL; 
    oldSize: File.PageCount ← File.GetSize[file];
    newSize: File.PageCount ← oldSize + Volume.GetAttributes[lvID].freePageCount;
    tries ← 20;
    OthelloOps.MakeUnbootable[file, hardMicrocode, OthelloDefs.leaderPages];
    File.SetSize[file, newSize 
	  ! File.Unknown => {OthelloDefs.WriteLine["Warning: Trouble making file fill volume - File.Unknown"L];
	    CONTINUE};
	    Volume.InsufficientSpace => {OthelloDefs.WriteString["."L]; newSize ← newSize - 100;
	    tries ← tries - 1; 
	    IF tries = 0 OR newSize < oldSize THEN {OthelloDefs.WriteLine["Warning: Expanding volume failed!"]; CONTINUE;} ELSE RETRY};];
    OthelloOps.MakeBootable[file,hardMicrocode, OthelloDefs.leaderPages];
    END;
    
    
    ExpandVM: PROC = BEGIN
      pvID: PhysicalVolume.ID;
      exVolume: Volume.ID;
      exFile: File.File;
      
      OthelloDefs.MyNameIs[
         myNameIs: "Expand Vmem File"L,
	 myHelpIs: "Expand the lisp virtual mem file on a volume"L];
      
      [pvID, exVolume] ← OthelloDefs.GetLvIDFromUser[prompt:"Volume to expand: "L];
      IF exVolume = Volume.nullID THEN OthelloDefs.AbortingCommand["Invalid volume."L];
      Volume.Open[exVolume];
      exFile ← OthelloOps.GetVolumeBootFile[exVolume, hardMicrocode].file;
      IF exFile = File.nullFile THEN OthelloDefs.AbortingCommand["No sysout on volume."L];
      OthelloDefs.WriteString["Expanding file..."L];
      SetBootFileSize[exFile,exVolume];
      OthelloDefs.WriteLine["Done."L];
      Volume.Close[exVolume];
      END;

   --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  -- Central commands
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  commandProcessor: OthelloDefs.CommandProcessor ← [LispCommands];

  LispCommands: PROC [index: CARDINAL] = {
    SELECT index FROM
     0 => CopyVM[];
     1 => ExpandVM[];
    ENDCASE => OthelloDefs.IndexTooLarge};
     
  
  -- Initialize
  OthelloDefs.RegisterCommandProc[@commandProcessor];


END...