--File:	ILTInstallImpl.mesa
--Created by
--   JFung.PASA	  	22-Sep-83 10:21:23
--	This is a modified version taken from InstallMuImpl.mesa

--last edited by
--   JFung.PASA	   	29-Nov-83 11:14:31


DIRECTORY
     Ascii,
     Display,
     Environment USING [bytesPerPage, PageCount, PageOffset],
     File USING [
          Capability, Create, Delete, DeleteImmutable, GetAttributes, GetSize,
          MakePermanent, nullCapability, PageCount, PageNumber, SetSize, Unknown],
     FileName: TYPE USING [AllocVFN, FreeVFN, VFN],
     FileTransfer,
     FileTypes USING [tUntypedFile],
     Inline USING [LowHalf],
     LispToolOps,
     NSName USING [maxFullNameLength],
     OthelloOps USING [
          GetPhysicalVolumeBootFile, GetVolumeBootFile, MakeBootable,
          MakeUnbootable, SetPhysicalVolumeBootFile, SetVolumeBootFile,
          VoidPhysicalVolumeBootFile, VoidVolumeBootFile],
     PhysicalVolume USING [GetContainingPhysicalVolume, ID],
     Process USING [Pause, SecondsToTicks],
     PrincOps USING [Port],
     Put,
     Space USING [
          CopyOut, Create, CreateUniformSwapUnits, Delete, Handle,
          InsufficientSpace, LongPointer, Map, nullHandle, PageCount, PageOffset,
          virtualMemory],
     Stream USING [Delete, GetBlock, Handle],
     TemporaryBooting USING [InvalidParameters],
     ToolWindow,
     UserInput,
     Volume USING [
          Close, GetAttributes, ID, InsufficientSpace, maxNameLength, nullID,
          PageCount],
     Window;

ILTInstallImpl: PROGRAM
     IMPORTS
          Display, File, FileName, FileTransfer, Inline, LispToolOps, OthelloOps,
          PhysicalVolume, Process, Put, Space, Stream, TemporaryBooting, UserInput,
          Volume, Window

     EXPORTS LispToolOps =

     BEGIN OPEN FileName, ILT: LispToolOps;

     PortRep: TYPE = PrincOps.Port;
     
     byteCount: LONG INTEGER ← 0;
     conn: FileTransfer.Connection;
     debug : BOOLEAN ← FALSE;
     defaultVMemSize: File.PageCount;
     fileName: LONG STRING ← NIL;
     indicatorBox: Window.Box = [[10, 10], [16, 16]];
     readStream: Stream.Handle ← NIL;
     space: Space.Handle ← Space.nullHandle;
     vfn: VFN ← NIL;
     volumeID: Volume.ID ← Volume.nullID;
     volumeOpen: BOOLEAN ← FALSE;


     CheckForAbort: FileTransfer.CheckAbortProc =
          BEGIN

          IF UserInput.UserAbort[ILT.windowHandle] THEN
               BEGIN
               ILT.toolData.busy ← FALSE;
               Put.Line[ILT.toolData.msgSW, "Aborted.. "L];
               Cleanup[];
               ILT.DisplayCommandSubwindow;
               --Process.Pause[Process.SecondsToTicks[10]];
               Put.Line[ILT.toolData.fileSW, "Aborted.. "L];
               DisplayOldVMemSize;
               RETURN[TRUE];
               END
          ELSE RETURN[FALSE];
          END;


     Cleanup: PROC =
          BEGIN
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Enter Cleanup....."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          IF readStream # NIL THEN
               BEGIN readStream.Delete[]; readStream ← NIL; END;

          IF space # Space.nullHandle THEN
               BEGIN
               IF debug THEN {
                    Put.Line[ILT.toolData.fileSW, "space # null handle..."L];
                    Process.Pause[Process.SecondsToTicks[5]];
                    };
               Space.Delete[space];
               space ← Space.nullHandle;
               END;

          IF vfn # NIL THEN {FreeVFN[vfn]; vfn ← NIL};
          IF conn # NIL THEN {conn.Destroy[]; conn ← NIL};
          --CloseVolume[];
          END;  --Cleanup




     CloseVolume: PROC =
          BEGIN
          IF volumeOpen THEN {Volume.Close[volumeID]; volumeOpen ← FALSE}
          END;


     DisplayOldVMemSize: PROC =
          BEGIN
          size: File.PageCount;

          size ← ILT.GetFileSize[];
          ILT.DisplayFileSize[size];
          END;


     GetFile: PORT [
          file: File.Capability ← File.nullCapability, name: LONG STRING ← NIL]
          RETURNS [BOOLEAN];



     InstallProc: PUBLIC PROCEDURE [volName: LONG STRING] =
          BEGIN

          byteCount ← 0;
          fileName ← ILT.toolData.filePathName;
          volumeID ← Volume.nullID;
          volumeOpen ← FALSE;

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Enter Install Proc "L];
               Put.LongString[ILT.toolData.fileSW, volName];
               --Process.Pause[Process.SecondsToTicks[5]];
               };

          IF ValidateString[fileName] THEN
               InstallFileOnVolume[volName ! UNWIND => CloseVolume[]];
          END;



     InstallFileOnVolume: PROC [volName: LONG STRING] =
          BEGIN OPEN OthelloOps;

          cap: File.Capability;
          created: BOOLEAN ← FALSE;
          currentSize: File.PageCount;
          firstPage: File.PageNumber;
          freePages: Volume.PageCount;
          maxSize: Volume.PageCount;
          volSize: Volume.PageCount;

          -- clean the PORT up from last time
          LOOPHOLE[GetFile, PortRep].in ← 0;
          -- CONNECT GetFile.out TO Retrieve;
          LOOPHOLE[GetFile, PortRep].out ← Retrieve;


          [volumeID, volumeOpen] ← ILT.GetVolumeID[volName];
          IF volumeID = Volume.nullID THEN RETURN;

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "File name ="L];
               Put.LongString[ILT.toolData.fileSW, fileName];
               Put.Line[ILT.toolData.fileSW, " ...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          conn ← FileTransfer.Create[];
          FileTransfer.SetProcs[
               conn: conn, clientData: NIL, messages: PostComment, login: NIL,
               checkAbort: CheckForAbort];



          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "GetVolumeBootFile....."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          [cap, firstPage] ← GetVolumeBootFile[volumeID, hardMicrocode];
          [volSize, freePages] ← Volume.GetAttributes[volumeID];
          -- set up default size to whatever pages (here aim at 14000-2000=12000)
          defaultVMemSize ← volSize - 2000;

          IF cap # File.nullCapability THEN
               BEGIN
               ENABLE File.Unknown => {cap ← File.nullCapability; CONTINUE};

               IF debug THEN {
                    Put.Line[ILT.toolData.fileSW, " not nullCapability...."L];
                    Process.Pause[Process.SecondsToTicks[5]];
                    };
               <<
               IF File.GetAttributes[cap].immutable THEN
                    BEGIN
                    pvID: PhysicalVolume.ID =
                         PhysicalVolume.GetContainingPhysicalVolume[volumeID];

                    IF debug THEN {
                         Put.Line[ILT.toolData.fileSW, "file immutable....."L];
                         Process.Pause[Process.SecondsToTicks[5]];
                         };
                    File.DeleteImmutable[cap, volumeID];
                    VoidVolumeBootFile[volumeID, hardMicrocode];
                    IF GetPhysicalVolumeBootFile[pvID, hardMicrocode].cap = cap
                         THEN VoidPhysicalVolumeBootFile[pvID, hardMicrocode];
                    cap ← File.nullCapability
                    END;
		    >>
               END;

          IF (created ← cap = File.nullCapability) THEN
               BEGIN
               IF debug THEN {
                    Put.Line[ILT.toolData.fileSW, " = nullCapability...."L];
                    Process.Pause[Process.SecondsToTicks[5]];
                    };
               cap ← File.Create[volumeID, 0, FileTypes.tUntypedFile];
               --set default vMem size
               --dont overwrite user's selection
               IF ILT.toolData.vMemSize = 0 THEN
                    BEGIN
                    ILT.toolData.vMemSize ← defaultVMemSize;
                    ILT.DisplayFileSize[ILT.toolData.vMemSize];
                    END;
               END
          ELSE
               BEGIN
               IF debug THEN {
                    Put.Line[ILT.toolData.fileSW, " MakeUnbootable.."L];
                    Process.Pause[Process.SecondsToTicks[5]];
                    };

               MakeUnbootable[
                    cap, hardMicrocode, firstPage !
                    TemporaryBooting.InvalidParameters =>
                         BEGIN
                         Put.Text[
                              ILT.toolData.msgSW,
                              "Warning: trouble making unbootable"L];
                         CONTINUE;
                         END];
               END;

          [volSize, freePages] ← Volume.GetAttributes[volumeID];

          IF cap = File.nullCapability THEN currentSize ← 0
          ELSE currentSize ← File.GetSize[cap];
          IF debug THEN {
               Put.LongDecimal[ILT.toolData.fileSW, currentSize];
               Put.CR[ILT.toolData.fileSW];
               };

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "GetFile...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          IF ~GetFile[name: fileName] THEN
               BEGIN
               CloseVolume[];
               Put.Line[
                    ILT.toolData.msgSW,
                    "File not found or Incorrect user/password or Connection timed out(2 mins)"L];
               Put.Line[ILT.toolData.fileSW, " Install failed."L];
               DisplayOldVMemSize;
               ILT.toolData.busy ← FALSE;
               RETURN;
               END;


          Put.Text[ILT.toolData.fileSW, " \n Volume size = "L];
          Put.LongDecimal[ILT.toolData.fileSW, volSize];
          Put.Line[ILT.toolData.fileSW, " pages"L];

          Put.Text[ILT.toolData.fileSW, " Default VMem size = "L];
          Put.LongDecimal[ILT.toolData.fileSW, defaultVMemSize];
          Put.Line[ILT.toolData.fileSW, " pages"L];

          Put.Text[ILT.toolData.fileSW, " Free pages on volume = "L];
          Put.LongDecimal[ILT.toolData.fileSW, freePages];
          Put.CR[ILT.toolData.fileSW];
          <<
	  -- calculate maximum vmem size
	  maxSize ← currentSize + freePages;
          File.SetSize[
               cap, maxSize !
               Volume.InsufficientSpace => {maxSize ← maxSize - 100; RETRY}];

          Put.Text[ILT.toolData.fileSW, " Approximate maximum VMem size = "L];
          Put.LongDecimal[ILT.toolData.fileSW, maxSize];
          Put.Line[ILT.toolData.fileSW, " pages"L];

	  -- restore original size
          File.SetSize[cap, currentSize];
>>
          Put.Text[ILT.toolData.fileSW, " Fetching... "L];
          IF ~GetFile[
               file: cap !
               UNWIND => {
                    IF created THEN File.Delete[cap];
                    --Put.Line[ILT.toolData.fileSW, " UNWIND  ~GetFile"L];
                    CloseVolume[]}] THEN
               BEGIN
               IF created THEN File.Delete[cap];
               CloseVolume[];
               Put.Line[ILT.toolData.msgSW, "cannot fetch file "L];
               DisplayOldVMemSize;
               RETURN;
               END;

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "SetVolumeBootFile..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          SetVolumeBootFile[cap, hardMicrocode, 0];
          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "MakePermanent..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };


          File.MakePermanent[cap];
          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "MakeBootable..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          MakeBootable[
               cap, hardMicrocode, 0 !
               TemporaryBooting.InvalidParameters =>
                    BEGIN
                    Put.Text[
                         ILT.toolData.msgSW, "Warning: trouble making bootable"L];
                    CONTINUE;
                    END];
          Put.Line[ILT.toolData.fileSW, " installed."L];

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "SetPhysicalVolumeBootFile..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          SetPhysicalVolumeBootFile[cap, hardMicrocode, 0];
          CloseVolume[];
          END;


     PostComment: FileTransfer.MessageProc =
          BEGIN
          IF ~ILT.toolData.busy THEN RETURN;
          IF level > terse THEN Post[ILT.toolData.msgSW, s1, s2, s3, s4];
          Post[ILT.toolData.fileSW, s1, s2, s3, s4];
          END;  --PostComment



     Post: PROCEDURE [w: Window.Handle, s1, s2, s3, s4: LONG STRING] =
          BEGIN
          IF s1 # NIL THEN Put.LongString[w, s1];
          IF s2 # NIL THEN Put.LongString[w, s2];
          IF s3 # NIL THEN Put.LongString[w, s3];
          IF s4 # NIL THEN Put.LongString[w, s4];
          END;  --Post




     Retrieve: PROC [file: File.Capability, name: LONG STRING]
          RETURNS [gotIt: BOOLEAN ← TRUE] =

          BEGIN OPEN FileTransfer;

          ResumeSetup: PORT [BOOLEAN]
               RETURNS [file: File.Capability, name: LONG STRING];
          --original source 
          --bufferPages: Space.PageCount = 64;
          bufferPages: Space.PageCount = 100;
          bufferBytes: CARDINAL;
          base: LONG POINTER ← NIL;
          --conn: Connection ← FileTransfer.Create[];
          --conn: Connection ← ILT.toolData.connection;
          fileSize: File.PageCount ← ILT.toolData.vMemSize;
          size: File.PageCount;
          sysoutSize: File.PageCount;

          -- CONNECT ResumeSetup.out TO GetFile
          LOOPHOLE[ResumeSetup, PortRep].out ← @GetFile;
          -- CONNECT GetFile.out TO ResumeSetup
          LOOPHOLE[GetFile, PortRep].out ← @ResumeSetup;

          bufferBytes ← bufferPages*Environment.bytesPerPage;

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Enter Retrieve"L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          <<
          FileTransfer.SetProcs[
               conn: conn, clientData: NIL, messages: PostComment, login: NIL,
               checkAbort: CheckForAbort];
>>

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "AllocVFN..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          vfn ← AllocVFN[name];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "ReadStream...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          readStream ← conn.ReadStream[
               files: vfn ! Error => {gotIt ← FALSE; CONTINUE}];

          IF ~gotIt THEN {Cleanup[]; GOTO noGood};  -- FileTransfer has ML bug!

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "ResumeSetup...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          [file, ] ← ResumeSetup[gotIt];


          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "sysoutSize...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          sysoutSize ←
               (FileTransfer.GetStreamInfo[readStream].size +
                     Environment.bytesPerPage - 1)/Environment.bytesPerPage;

          Put.Text[ILT.toolData.fileSW, "Sysout size = "];
          Put.LongDecimal[ILT.toolData.fileSW, sysoutSize];
          Put.Text[ILT.toolData.fileSW, " pages; "];
          Put.LongDecimal[ILT.toolData.fileSW, sysoutSize*512];
          Put.Line[ILT.toolData.fileSW, " bytes."];

          -- set up initial default size
          <<
          IF LOOPHOLE[ILT.GetFileSize, CARDINAL] = 0 THEN
               ILT.toolData.vMemSize ← defaultVMemSize;
>>
          IF (ILT.toolData.vMemSize < sysoutSize) AND (ILT.toolData.vMemSize > 0)
               THEN
               BEGIN
               Put.Line[
                    ILT.toolData.msgSW,
                    "Virtual memory smaller than Sysout size, please respecify."L];

               --size ← ILT.GetFileSize[];
               --ILT.DisplayFileSize[size];
               --CloseVolume[];
               RETURN[FALSE];
               END;

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "SetSize...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          IF ILT.toolData.vMemSize = 0 THEN fileSize ← defaultVMemSize;
          File.SetSize[
               file, fileSize !
               Volume.InsufficientSpace => {
                    Put.Line[ILT.toolData.fileSW, " Not enough room for file!"L];
                    Cleanup[];
                    GOTO noGood}];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Create...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          space ← Space.Create[
               bufferPages, Space.virtualMemory !
               Space.InsufficientSpace => {
                    Put.Line[ILT.toolData.fileSW, " Insufficient Disk Space!"L];
                    Process.Pause[Process.SecondsToTicks[10]];
                    Cleanup[];
                    GOTO noGood}; ];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Map...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          Space.Map[
               space !
               Volume.InsufficientSpace => {
                    Put.Line[ILT.toolData.fileSW, " Insufficient disk space!"L];
                    Process.Pause[Process.SecondsToTicks[10]];
                    Cleanup[];
                    GOTO noGood}; ];

          Space.CreateUniformSwapUnits[size: 16, parent: space];
          --original source
          --Space.CreateUniformSwapUnits[size: 4, parent: space]; 
          base ← Space.LongPointer[space];

          FOR windowPage: Space.PageOffset ← 0, windowPage + bufferPages WHILE
               windowPage < Inline.LowHalf[sysoutSize] DO
               bytesTransferred: LONG INTEGER;
               bytesTransferred ← readStream.GetBlock[
                    [base, 0, bufferBytes]].bytesTransferred;
               Space.CopyOut[space, [file, windowPage]];
               byteCount ← byteCount + bytesTransferred;
               Put.Text[ILT.toolData.msgSW, "Bytes transfered: "];
               Put.LongDecimal[ILT.toolData.msgSW, byteCount];
               Put.CR[ILT.toolData.msgSW];
               ILT.InvertIndicator[];
               ENDLOOP;

          Cleanup[];
          RETURN[TRUE];
          EXITS noGood => RETURN[FALSE]
          END;  --Retrieve




     SetVolumeProc: PUBLIC PROCEDURE [vName: LONG STRING] RETURNS [BOOLEAN] =

          BEGIN OPEN OthelloOps;
          cap: File.Capability;
          firstPage: File.PageNumber;
          created: BOOLEAN ← FALSE;

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Enter SetVolume Proc "L];
               Put.LongString[ILT.toolData.fileSW, vName];
               --Process.Pause[Process.SecondsToTicks[5]];
               };

          [volumeID, volumeOpen] ← ILT.GetVolumeID[vName];
          IF volumeID = Volume.nullID THEN RETURN[FALSE];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "GetVolumeBootFile....."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          [cap, firstPage] ← GetVolumeBootFile[volumeID, hardMicrocode];
          IF cap # File.nullCapability THEN
               BEGIN
               ENABLE File.Unknown => {cap ← File.nullCapability; CONTINUE};
               IF File.GetAttributes[cap].immutable THEN
                    BEGIN
                    pvID: PhysicalVolume.ID =
                         PhysicalVolume.GetContainingPhysicalVolume[volumeID];

                    IF debug THEN {
                         Put.Line[ILT.toolData.fileSW, "file immutable....."L];
                         Process.Pause[Process.SecondsToTicks[5]];
                         };
                    File.DeleteImmutable[cap, volumeID];
                    VoidVolumeBootFile[volumeID, hardMicrocode];
                    IF GetPhysicalVolumeBootFile[pvID, hardMicrocode].cap = cap
                         THEN VoidPhysicalVolumeBootFile[pvID, hardMicrocode];
                    cap ← File.nullCapability
                    END
               END;

          IF (created ← cap = File.nullCapability) THEN
               BEGIN
               Put.Line[ILT.toolData.msgSW, " No Sysout file installed."L];
               RETURN[FALSE];
               --cap ← File.Create[volumeID, 0, FileTypes.tUntypedFile];
               END

          ELSE
               MakeUnbootable[
                    cap, hardMicrocode, firstPage !
                    TemporaryBooting.InvalidParameters =>
                         BEGIN
                         Put.Text[
                              ILT.toolData.msgSW,
                              "Warning: trouble making unbootable"L];
                         CONTINUE;
                         END];
          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "SetVolumeBootFile..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          SetVolumeBootFile[cap, hardMicrocode, 0];
          File.MakePermanent[cap];
          MakeBootable[
               cap, hardMicrocode, 0 !
               TemporaryBooting.InvalidParameters =>
                    BEGIN
                    Put.Text[
                         ILT.toolData.msgSW, "Warning: trouble making bootable"L];
                    CONTINUE;
                    END];

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "SetPhysicalVolumeBootFile..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          SetPhysicalVolumeBootFile[cap, hardMicrocode, 0];
          CloseVolume[];
          RETURN[TRUE];
          END;  --SetVolumeProc


     -- This procedure validates the syntax for the file name used by NS file server .
     -- Allowable string is an
     -- alpha-numeric string beginning with a capital or small letter ['A .. 'Z]
     -- followed by any number (up to maxStringSize) of letters or numbers.

     ValidateString: PROC [sName: LONG STRING] RETURNS [BOOLEAN] =
          BEGIN
          currentString: STRING = [maxStringSize];
          currentChar: CARDINAL ← 0;
          c: CHARACTER;
          maxStringSize: CARDINAL = NSName.maxFullNameLength;  -- bytes

          CheckChar: PROC[] RETURNS [BOOLEAN] =
               BEGIN
               IF currentString.length >= maxStringSize THEN
                    BEGIN
                    Put.Line[ILT.toolData.msgSW, "Scan Error: string length too long"L];
                    Put.LongString[ILT.toolData.msgSW, sName];
		    Put.CR[ILT.toolData.msgSW];
                    RETURN[FALSE];
                    END;
               currentString.text[currentString.length] ← c;
               currentString.length ← currentString.length + 1;
               currentChar ← currentChar + 1;
               RETURN[TRUE];
               END;  --CheckChar  
	       
          IF debug THEN {
          Put.Line[ILT.toolData.fileSW, "ValidateString"L];
          Put.Text[ILT.toolData.fileSW, sName];
          Put.CR[ILT.toolData.fileSW];
          Process.Pause[Process.SecondsToTicks[5]];
	  };

          WHILE (currentChar < sName.length) DO
               c ← sName.text[currentChar];

               --Put.Char[ILT.toolData.fileSW, c];
               --Process.Pause[Process.SecondsToTicks[5]];

               SELECT ILT.toolData.fileServer FROM
                    NS => BEGIN
                         IF
                              (c = '- OR c = '* OR c = '@ OR c = ': 
			      OR c = Ascii.SP OR c = '[ OR c = '] OR c = '< OR c = '>
                                   OR c IN ['a..'z] OR c IN ['A..'Z]
                                   OR c IN ['0..'9]) THEN RETURN[CheckChar[]]
                         ELSE
                              BEGIN
                              Put.Text[ILT.toolData.msgSW, "Scan Error on: "L];
                              Put.LongString[ILT.toolData.msgSW, sName];
			      Put.Text[ILT.toolData.fileSW, " Bad character detected: "];
			      Put.Char[ILT.toolData.fileSW, c];
                              RETURN[FALSE];
                              END;
                         END;
                    IFS => BEGIN
                         IF
                              (c = '- OR c = '* OR c = '@ OR c = Ascii.SP
			      OR c = '[ OR c = '] OR c = '< OR c = '>
                                   OR c IN ['a..'z] OR c IN ['A..'Z]
                                   OR c IN ['0..'9]) THEN RETURN[CheckChar[]]
                         ELSE
                              BEGIN
                              Put.Line[ILT.toolData.fileSW, "Scan Error"L];
                              Put.LongString[ILT.toolData.fileSW, sName];
                              RETURN[FALSE];
                              END;
                         END;
                    ENDCASE;
               ENDLOOP;
          RETURN[TRUE];
          END;  --ValidateString

     END. --ILTInstallImpl