-- Copyright (C) 1983 by Xerox Corporation. All rights reserved. -- IndirectionNoDisk.mesa, HGM, 9-Apr-83 23:38:33 DIRECTORY Ascii USING [CR, NUL], CmFile USING [Handle, ReadLineOrToken, TableError, TitleMatch], Heap USING [systemZone], StringLookUp USING [InTable, noMatch, TableDesc], Token USING [GetCharProcType, FreeTokenString, Item, Object], Indirect USING [], Parms USING [Error, GetMaxChars, GetParms]; IndirectionNoDisk: PROGRAM IMPORTS CmFile, Heap, StringLookUp, Token, Parms EXPORTS Indirect = BEGIN parmFileName: LONG STRING ← NIL; FindOurName: PROCEDURE = BEGIN cmFile: CmFile.Handle; Option: TYPE = MACHINE DEPENDENT{ parameterFile(0), noMatch(StringLookUp.noMatch)}; DefinedOption: TYPE = Option [parameterFile..parameterFile]; CheckType: PROCEDURE [h: CmFile.Handle, table: StringLookUp.TableDesc] RETURNS [index: CARDINAL] = NextValue; MyNextValue: PROCEDURE [ h: CmFile.Handle, table: LONG DESCRIPTOR FOR ARRAY DefinedOption OF LONG STRING] RETURNS [index: Option] = LOOPHOLE[CheckType]; optionTable: ARRAY DefinedOption OF LONG STRING ← [ parameterFile: "ParameterFile"L]; cmFile ← OpenSection["MyName"L]; IF cmFile = NIL THEN RETURN; DO option: Option; option ← MyNextValue[cmFile, DESCRIPTOR[optionTable] ! CmFile.TableError => RETRY]; SELECT option FROM noMatch => EXIT; parameterFile => BEGIN [] ← Token.FreeTokenString[parmFileName]; parmFileName ← Token.Item[cmFile, FALSE]; END; ENDCASE => ERROR; ENDLOOP; Close[cmFile]; END; GetParmFileName: PUBLIC PROCEDURE RETURNS [LONG STRING] = BEGIN RETURN[parmFileName]; END; OpenSection: PUBLIC PROCEDURE [section: LONG STRING] RETURNS [cmFile: CmFile.Handle] = BEGIN cmFile ← Open[]; IF cmFile = NIL THEN RETURN; IF ~FindSection[cmFile, section] THEN BEGIN Close[cmFile]; cmFile ← NIL; END; END; Open: PUBLIC PROCEDURE RETURNS [cmFile: CmFile.Handle] = BEGIN s: LONG STRING ← Heap.systemZone.NEW[StringBody[Parms.GetMaxChars[]]]; repH: Handle; [] ← Parms.GetParms[s ! Parms.Error => CONTINUE]; IF s.length = 0 THEN BEGIN Heap.systemZone.FREE[@s]; RETURN[NIL]; END; repH ← Heap.systemZone.NEW[Object ← [tokenData: [getChar: GetChar], s: s, index: 0]]; cmFile ← RepToAbs[repH]; END; NextValue: PUBLIC PROCEDURE [h: CmFile.Handle, table: StringLookUp.TableDesc] RETURNS [index: CARDINAL] = BEGIN localLine: STRING ← [lineSize]; DO GobbleRestOfLine[h]; -- consume any parts of preceding line left over by client ReadName[h, localLine]; IF h.break # nameBreak THEN RETURN[StringLookUp.noMatch]; index ← StringLookUp.InTable[localLine, table, TRUE, TRUE].index; IF index < LENGTH[table] THEN EXIT; SIGNAL CmFile.TableError[h, localLine]; ENDLOOP; END; Close: PUBLIC PROCEDURE [cmFile: CmFile.Handle] = BEGIN repH: Handle ← Validate[cmFile]; Heap.systemZone.FREE[@repH.s]; repH.tokenData.getChar ← NIL; -- make sure deallocated object will not look valid Heap.systemZone.FREE[@cmFile]; END; Handle: TYPE = LONG POINTER TO Object; Object: TYPE = MACHINE DEPENDENT RECORD [ tokenData: Token.Object, s: LONG STRING, index: CARDINAL]; AbsToRep: PROCEDURE [h: CmFile.Handle] RETURNS [Handle] = {RETURN[LOOPHOLE[h]]}; RepToAbs: PROCEDURE [h: Handle] RETURNS [CmFile.Handle] = { RETURN[@h.tokenData]}; Validate: PROCEDURE [h: CmFile.Handle] RETURNS [repH: Handle] = BEGIN repH ← AbsToRep[h]; IF repH.tokenData.getChar # GetChar THEN ERROR; END; GetChar: PRIVATE Token.GetCharProcType = BEGIN repH: Handle = AbsToRep[h]; IF repH.index = repH.s.maxlength THEN c ← Ascii.NUL ELSE BEGIN c ← repH.s[repH.index]; repH.index ← repH.index + 1; END; END; FindSection: PUBLIC PROCEDURE [h: CmFile.Handle, title: LONG STRING] RETURNS [opened: BOOLEAN] = BEGIN localLine: STRING ← [lineSize]; repH: Handle = Validate[h]; DO ReadLine[h, localLine]; IF h.break = Ascii.NUL THEN EXIT; IF localLine.length # 0 AND localLine[0] = beginSectionName THEN BEGIN IF CmFile.TitleMatch[localLine, title] THEN RETURN[TRUE]; END; ENDLOOP; RETURN[FALSE]; END; ReadLine: PROCEDURE [h: CmFile.Handle, buffer: LONG STRING] = -- Suppresses comment lines BEGIN DO CmFile.ReadLineOrToken[h, buffer, Ascii.CR]; IF h.break # Ascii.CR OR ~IsCommentLine[buffer] THEN EXIT; ENDLOOP; END; lineSize: CARDINAL = 250; beginSectionName: CHARACTER = '[; commentChar: CHARACTER = '-; nameBreak: CHARACTER = ':; ReadName: PROCEDURE [h: CmFile.Handle, buffer: LONG STRING] = -- Suppresses comment lines and any line that is neither a SectionName -- nor a SectionLine -- Output assertion: h.break = Ascii.NUL OR h.break = nameBreak OR -- h.getChar is positioned just after Ascii.CR BEGIN DO CmFile.ReadLineOrToken[h, buffer, nameBreak]; IF h.break = Ascii.NUL THEN EXIT; IF buffer.length # 0 AND ~IsCommentLine[buffer] THEN IF buffer[0] = beginSectionName THEN { GobbleRestOfLine[h]; h.break ← Ascii.NUL; EXIT} ELSE IF h.break = nameBreak THEN EXIT; GobbleRestOfLine[h]; ENDLOOP; END; GobbleRestOfLine: PROCEDURE [h: CmFile.Handle] = BEGIN WHILE SELECT h.break FROM Ascii.CR, Ascii.NUL => FALSE, ENDCASE => TRUE DO h.break ← h.getChar[h]; ENDLOOP; END; IsCommentLine: PROCEDURE [s: LONG STRING] RETURNS [BOOLEAN] = BEGIN RETURN[s.length > 1 AND s[0] = commentChar AND s[1] = commentChar]; END; -- Initialization FindOurName[]; END.