-- 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.