DIRECTORY Basics, BasicTime, BcdDefs, BCDery, FS, IO, IOClasses, List, ListerUtils, MakeDo, RedBlackTree, Rope, TimeStamp; ConfigAndMesaDeps: CEDAR MONITOR IMPORTS BasicTime, BCDery, FS, IO, IOClasses, ListerUtils, MakeDo, RedBlackTree, Rope = BEGIN OPEN MakeDo; GotoSyntaxError: ERROR = CODE; ROPE: TYPE = Rope.ROPE; StampRef: TYPE = REF StampRep; StampRep: TYPE = RECORD [ created: BasicTime.GMT, stamp: TimeStamp.Stamp]; SourceData: TYPE = REF SourceDataRep; SourceDataRep: TYPE = RECORD [ bcdName, shortName: ROPE, sourceType: SourceType, supports: RedBlackTree.Table, sourceNode, switchesNode, bcdNode: Node, sourceStamp: Stamp _ TimeStamp.Null, bcdCreateTime: BasicTime.GMT, bcdReadable, supportsInvalid: BOOL _ FALSE, cmd: ROPE _ NIL ]; SourceType: TYPE = {Mesa, Config}; Support: TYPE = REF SupportRep; SupportRep: TYPE = RECORD [ node: Node, version: Stamp]; ParseData: TYPE = REF ParseDataRep; ParseDataRep: TYPE = RECORD [ source: ROPE, sourceType: SourceType, stamp: Time _ notExistTime, refdModules: RopeList _ NIL]; parses: RedBlackTree.Table _ RedBlackTree.Create[GetParseKey, CompareParses]; configAndMesaClass: ActionClass _ NEW [ActionClassRep _ [ CheckConsistency: CheckConsistency, Rederive: RederiveSource ]]; GetParseKey: PROC [data: REF ANY] RETURNS [ROPE] --RedBlackTree.GetKey-- = { pd: ParseData = NARROW[data]; RETURN[pd.source]}; CompareParses: PROC [k, data: REF ANY] RETURNS [Basics.Comparison] --RedBlackTree.Compare-- = { k1: ROPE = NARROW[k]; k2: ROPE = GetParseKey[data]; RETURN [k1.Compare[s2: k2, case: FALSE]]}; GetSupportKey: PROC [data: REF ANY] RETURNS [Node] --RedBlackTree.GetKey-- = { s: Support = NARROW[data]; RETURN[s.node]}; CompareSupport: PROC [k, data: REF ANY] RETURNS [Basics.Comparison] --RedBlackTree.Compare-- = { k1: INT = LOOPHOLE[k]; k2: INT = LOOPHOLE[GetSupportKey[data]]; RETURN [SELECT k1 FROM less, =k2 => equal, >k2 => greater, ENDCASE => ERROR]; }; SourceFind: PROC [resultName: ROPE, finderData: REF ANY] RETURNS [found: BOOLEAN, sought: Node, makes, cmdFrom: NodeList, from: From, cmd: ROPE, class: ActionClass, foundData: REF ANY] -- FinderProc -- = BEGIN bcdExpanded, shortName, baseName, sourceName, bcdName, configName, switches: ROPE; bcdCP: FS.ComponentPositions; sourceNode, bcdNode, configNode, switchesNode: Node; bcdCreateTime: BasicTime.GMT; supports: RedBlackTree.Table; md: SourceData; sourceType: SourceType; NoteDep: PROC [fileName: ROPE] = { n: Node = GetNode[fileName.Cat[".BCD"], fileClass]; s: Support _ NARROW[supports.Lookup[n]]; IF s = NIL THEN { s _ NEW [SupportRep _ [n, TimeStamp.Null]]; supports.Insert[s, n]; }; from.mustHave _ CONS[n, from.mustHave]; }; found _ TRUE; [bcdExpanded, bcdCP, ] _ FS.ExpandName[resultName !FS.Error => {found _ FALSE; CONTINUE}]; IF NOT found THEN RETURN; IF NOT (found _ bcdExpanded.Substr[start: bcdCP.ext.start, len: bcdCP.ext.length]. Equal[s2: "BCD", case: FALSE] OR (bcdCP.ext.length = 0)) THEN RETURN; baseName _ bcdExpanded.Substr[start: 0, len: bcdCP.base.start + bcdCP.base.length]; shortName _ bcdExpanded.Substr[start: bcdCP.base.start, len: bcdCP.base.length]; bcdName _ baseName.Cat[".BCD"]; switchesNode _ GetNode[bcdName.Concat[".Switches"], fileClass]; switches _ GetSwitches[bcdName]; makes _ LIST[sought _ bcdNode _ GetNode[bcdName, fileClass]]; bcdCreateTime _ InnerGetCreated[bcdNode]; from _ [mustHave: NIL, optional: LIST[switchesNode]]; supports _ RedBlackTree.Create[GetSupportKey, CompareSupport]; sourceType _ Mesa; sourceName _ baseName.Concat[".Mesa"]; cmd _ Rope.Cat["RCompile ", switches, " ", shortName]; IF (NOT EnumerateDependancies[ (sourceNode _ GetNode[sourceName, fileClass]), sourceType, NoteDep]) AND EnumerateDependancies[ (configNode _ GetNode[configName _ baseName.Concat[".Config"], fileClass]), Config, NoteDep] THEN { sourceName _ configName; sourceNode _ configNode; sourceType _ Config; cmd _ Rope.Cat["Bind ", switches, " ", shortName]}; cmdFrom _ LIST[sourceNode, switchesNode]; foundData _ md _ NEW [SourceDataRep _ [bcdName: bcdName, shortName: shortName, sourceType: sourceType, supports: supports, sourceNode: sourceNode, switchesNode: switchesNode, bcdNode: bcdNode, bcdCreateTime: bcdCreateTime, cmd: cmd]]; IF bcdCreateTime # MakeDo.notExistTime THEN MakeSupports[md]; from.mustHave _ CONS[sourceNode, from.mustHave]; class _ configAndMesaClass; END; GetSwitches: PROC [bcdName: ROPE] RETURNS [switches: ROPE] = BEGIN ss: IO.STREAM _ NIL; ss _ FS.StreamOpen[bcdName.Cat[".Switches"] !FS.Error => CONTINUE]; IF ss = NIL THEN RETURN [NIL]; [] _ ss.SkipWhitespace[]; IF ss.EndOf[] THEN RETURN [NIL]; switches _ ss.GetTokenRope[IO.IDProc].token; ss.Close[]; END; CheckConsistency: PROC [a: Action, result: Node] RETURNS [consistent: BOOL, reason: ROPE] --ConsistencyChecker-- = BEGIN md: SourceData = NARROW[a.PublicPartsOfAction[].foundData]; switchesCreate: BasicTime.GMT = InnerGetCreated[md.switchesNode]; curSourceStamp: Stamp; CheckSupport: PROC [data: REF ANY] RETURNS [stop: BOOL _ FALSE] --RedBlackTree.EachNode-- = { s: Support = NARROW[data]; curBCDStamp: Stamp = CurBCDStamp[s.node]; IF curBCDStamp = TimeStamp.Null THEN { consistent _ TRUE; reason _ IO.PutFR["input %g doesn't exist", [rope[s.node.PublicPartsOfNode[].name]] ]; RETURN [TRUE]; }; IF curBCDStamp # s.version THEN { out: IO.STREAM _ IO.ROS[]; out.PutRope["last used version "]; TRUSTED {ListerUtils.PrintVersion[s.version, out, FALSE]}; out.PutF[ " of %g, but current version is ", [rope[s.node.PublicPartsOfNode[].name]] ]; TRUSTED {ListerUtils.PrintVersion[curBCDStamp, out, FALSE]}; consistent _ FALSE; reason _ out.RopeFromROS[]; RETURN [TRUE]; }; }; UpdateSupport[md]; IF md.bcdCreateTime = MakeDo.notExistTime THEN RETURN [FALSE, "BCD doesn't exist"]; IF NOT md.bcdReadable THEN RETURN [FALSE, "BCD not readable"]; curSourceStamp _ CurSourceStamp[md.sourceNode]; IF curSourceStamp = TimeStamp.Null THEN RETURN [TRUE, "source doesn't exist"]; IF curSourceStamp # md.sourceStamp THEN { out: IO.STREAM _ IO.ROS[]; out.PutRope["last used source "]; TRUSTED {ListerUtils.PrintVersion[md.sourceStamp, out, TRUE]}; out.PutRope[", but current source is "]; TRUSTED {ListerUtils.PrintVersion[curSourceStamp, out, TRUE]}; RETURN [FALSE, out.RopeFromROS[]]; }; IF switchesCreate # MakeDo.notExistTime AND BasicTime.Period[md.bcdCreateTime, switchesCreate] > 0 THEN RETURN [FALSE, "switches file created later than result"]; consistent _ TRUE; reason _ "all version stamps match"; md.supports.EnumerateIncreasing[CheckSupport]; END; UpdateSupport: PROC [md: SourceData] = { oldBcd: Time = md.bcdCreateTime; md.bcdCreateTime _ InnerGetCreated[md.bcdNode]; IF md.bcdCreateTime = MakeDo.notExistTime THEN RETURN; IF md.bcdCreateTime = oldBcd AND NOT md.supportsInvalid THEN RETURN; MakeSupports[md]; }; CurSourceStamp: PROC [node: Node] RETURNS [stamp: Stamp] = BEGIN time: Time _ InnerGetCreated[node]; IF time = MakeDo.notExistTime THEN RETURN [TimeStamp.Null]; stamp _ [net: 0, host: 0, time: BasicTime.ToPupTime[time]]; END; CurBCDStamp: ENTRY PROC [node: Node] RETURNS [stamp: Stamp] = BEGIN ENABLE UNWIND => {}; sr: StampRef _ NARROW[node.GetProp[$Stamp]]; created: BasicTime.GMT _ InnerGetCreated[node]; bcd: ListerUtils.RefBCD; IF sr = NIL THEN node.SetProp[ prop: $Stamp, val: sr _ NEW [StampRep _ [ created: notExistTime, stamp: TimeStamp.Null]] ]; IF created = sr.created THEN RETURN [sr.stamp]; sr.created _ created; IF created = MakeDo.notExistTime THEN sr.stamp _ TimeStamp.Null ELSE { TRUSTED {bcd _ ListerUtils.ReadBcd[node.PublicPartsOfNode[].name !FS.Error => {bcd _ NIL; CONTINUE}]}; sr.stamp _ IF bcd = NIL OR bcd.versionIdent # BcdDefs.VersionID THEN TimeStamp.Null ELSE bcd.version; }; stamp _ sr.stamp; END; MakeSupports: PROC [md: SourceData] = BEGIN NoteSupport: PROC [name: ROPE, version: Stamp] = BEGIN extName: ROPE = FS.ExpandName[name.Cat[".BCD"]].fullFName; node: Node = GetNode[extName, fileClass]; s: Support = NARROW[md.supports.Lookup[node]]; IF s # NIL THEN s.version _ version; END; bcd: ListerUtils.RefBCD; md.sourceStamp _ TimeStamp.Null; md.bcdReadable _ FALSE; TRUSTED {bcd _ ListerUtils.ReadBcd[md.bcdName !FS.Error => {bcd _ NIL; CONTINUE}]}; IF bcd = NIL THEN RETURN; IF bcd.versionIdent # BcdDefs.VersionID THEN RETURN; md.sourceStamp _ bcd.sourceVersion; [] _ BCDery.EnumerateFiles[bcd: bcd, bcdFileName: md.bcdName, to: NoteSupport]; md.bcdReadable _ TRUE; md.supportsInvalid _ FALSE; END; RederiveSource: PROC [a: Action] RETURNS [from: From, cmd: ROPE] --RederiveProc-- = BEGIN md: SourceData _ NARROW[a.PublicPartsOfAction[].foundData]; NoteDep: PROC [fileName: ROPE] = { n: Node = GetNode[fileName.Cat[".BCD"], fileClass]; s: Support _ NARROW[md.supports.Lookup[n]]; IF s = NIL THEN { s _ NEW [SupportRep _ [n, TimeStamp.Null]]; md.supports.Insert[s, n]; }; from.mustHave _ CONS[n, from.mustHave]; }; from _ [NIL, NIL]; md.supports.DestroyTable[]; [] _ EnumerateDependancies[md.sourceNode, md.sourceType, NoteDep]; md.supportsInvalid _ TRUE; UpdateSupport[md]; from.mustHave _ CONS[md.sourceNode, from.mustHave]; md.cmd _ cmd _ Rope.Cat[ SELECT md.sourceType FROM Mesa => "RCompile ", Config => "Bind ", ENDCASE => ERROR, GetSwitches[md.bcdName], " ", md.shortName]; END; Break: IO.BreakProc = {RETURN [SELECT char FROM IN ['a .. 'z], IN ['A .. 'Z], IN ['0 .. '9] => other, IO.SP, IO.CR, IO.TAB, IO.LF, IO.FF => sepr, ENDCASE => break]}; Letter: PROC [c: CHAR] RETURNS [letter: BOOLEAN] = INLINE {letter _ (c IN ['a .. 'z]) OR (c IN ['A .. 'Z])}; EnumerateDependancies: PROC [sourceNode: Node, sourceType: SourceType, consume: PROC [fileName: ROPE]] RETURNS [exists: BOOLEAN] = BEGIN sourceName: ROPE = sourceNode.PublicPartsOfNode[].name; pd: ParseData _ NARROW[parses.Lookup[sourceName]]; cur: BasicTime.GMT; IF pd = NIL THEN { pd _ NEW [ParseDataRep _ [source: sourceName, sourceType: sourceType]]; parses.Insert[pd, sourceName]; }; cur _ InnerGetCreated[sourceNode]; IF NOT (exists _ cur # notExistTime) THEN RETURN; IF cur # pd.stamp THEN { NoteDep: PROC [fileName: ROPE] = { pd.refdModules _ CONS[fileName, pd.refdModules]; consume[fileName]}; pd.stamp _ cur; pd.refdModules _ NIL; SELECT pd.sourceType FROM Mesa => [] _ EnumerateMesaDependancies[sourceName, NoteDep]; Config => [] _ EnumerateConfigDependancies[sourceName, NoteDep]; ENDCASE => ERROR; } ELSE { FOR rml: RopeList _ pd.refdModules, rml.rest WHILE rml # NIL DO consume[rml.first] ENDLOOP}; END; EnumerateMesaDependancies: PROC [sourceName: ROPE, consume: PROC [fileName: ROPE]] RETURNS [exists: BOOLEAN] = BEGIN NextToken: PROC RETURNS [ROPE] = {RETURN [source.GetTokenRope[Break].token]}; ParseDirectory: PROC RETURNS [next: ROPE] = BEGIN firstClause: BOOL _ TRUE; ParseClause: PROC RETURNS [next: ROPE] = BEGIN fileName: ROPE _ "?"; next _ NextToken[]; IF firstClause THEN {firstClause _ FALSE; IF next.Equal[";"] THEN RETURN}; IF NOT Letter[next.Fetch[0]] THEN ERROR GotoSyntaxError; fileName _ next; next _ NextToken[]; IF next.Equal[":"] THEN BEGIN next _ NextToken[]; IF next.Equal["TYPE"] THEN { next _ NextToken[]; IF Letter[next.Fetch[0]] AND NOT next.Equal["USING"] THEN next _ NextToken[]; } ELSE IF next.Equal["FROM"] THEN { fileName _ source.GetRopeLiteral[]; next _ NextToken[]; } ELSE ERROR GotoSyntaxError; END; IF next.Equal["USING"] THEN BEGIN IF NOT (next _ NextToken[]).Equal["["] THEN ERROR GotoSyntaxError; WHILE NOT (next _ NextToken[]).Equal["]"] DO NULL ENDLOOP; next _ NextToken[]; END; consume[fileName]; END; IF (next _ NextToken[]).Equal["DIRECTORY"] THEN BEGIN DO IF (next _ ParseClause[]).Equal[";"] THEN EXIT; IF NOT next.Equal[","] THEN ERROR GotoSyntaxError; ENDLOOP; next _ NextToken[]; END; IF NOT Letter[next.Fetch[0]] THEN ERROR GotoSyntaxError; END; source: IO.STREAM _ NIL; source _ FS.StreamOpen[fileName: sourceName, accessOptions: $read !FS.Error => {source _ NIL; CONTINUE}]; exists _ source # NIL; IF NOT exists THEN RETURN; source _ IOClasses.CreateCommentFilterStream[source]; [] _ source.GetIndex[]; [] _ ParseDirectory[!GotoSyntaxError => BEGIN SIGNAL Warning[IO.PutFR["Syntax error in %g; parse aborted at %g", IO.rope[sourceName], IO.int[source.GetIndex[]]]]; CONTINUE END]; source.Close[]; END; IsConfig: PROC [word: ROPE] RETURNS [is: BOOLEAN] = {is _ word.Equal["CONFIGURATION"] OR word.Equal["CONFIG"]}; EnumerateConfigDependancies: PROC [sourceName: ROPE, Consume: PROC [fileName: ROPE]] RETURNS [exists: BOOLEAN] = { locals: LIST OF LIST OF ROPE _ NIL; AddDef: PROC [name: ROPE] = {locals.first _ CONS[name, locals.first]}; MaybeConsume: PROC [moduleName: ROPE] = { FOR l: LIST OF LIST OF ROPE _ locals, l.rest WHILE l # NIL DO FOR m: LIST OF ROPE _ l.first, m.rest WHILE m # NIL DO IF m.first.Equal[moduleName] THEN RETURN; ENDLOOP; ENDLOOP; Consume[moduleName]}; NextToken: PROC RETURNS [ROPE] = {RETURN [source.GetTokenRope[Break].token]}; ParseConfigDescription: PROC = { next: ROPE _ ParseCDirectory[]; next _ ParseCPacking[next]; next _ ParseConfiguration[next]; IF NOT next.Equal["."] THEN ERROR GotoSyntaxError; }; ParseConfiguration: PROC [first: ROPE] RETURNS [next: ROPE] = { IF NOT Letter[first.Fetch[0]] THEN ERROR GotoSyntaxError; IF NOT (next _ NextToken[]).Equal[":"] THEN ERROR GotoSyntaxError; IF NOT IsConfig[next _ NextToken[]] THEN ERROR GotoSyntaxError; next _ ParseConfigurationRemains[]; }; ParseConfigurationRemains: PROC RETURNS [next: ROPE] = { next _ ParseCHeadRemains[]; IF NOT (next.Equal["="] OR next.Equal["~"]) THEN ERROR GotoSyntaxError; ParseCBody[]; next _ NextToken[]; }; ParseCBody: PROC = { next: ROPE _ NextToken[]; curly: BOOLEAN; IF next.Equal["BEGIN"] THEN curly _ FALSE ELSE IF next.Equal["{"] THEN curly _ TRUE ELSE ERROR GotoSyntaxError; locals _ CONS[NIL, locals]; next _ NextToken[]; DO semiSeen: BOOL _ FALSE; next _ ParseCStatement[next]; WHILE next.Equal[";"] DO next _ NextToken[]; semiSeen _ TRUE; ENDLOOP; IF next.Equal[IF curly THEN "}" ELSE "END"] THEN EXIT; IF NOT semiSeen THEN ERROR GotoSyntaxError; ENDLOOP; locals _ locals.rest; }; ParseCStatement: PROC [first: ROPE] RETURNS [next: ROPE] = { next _ first; IF next.Equal["["] THEN BEGIN next _ ParseItemList[FALSE]; IF NOT next.Equal["]"] THEN ERROR GotoSyntaxError; next _ NextToken[]; IF NOT next.Equal["_"] THEN ERROR GotoSyntaxError; next _ ParseCExpression[]; END ELSE BEGIN lhs, rhs: ROPE; named: BOOL _ FALSE; lhs _ rhs _ next; IF named _ (next _ NextToken[]).Equal[":"] THEN BEGIN IF IsConfig[rhs _ NextToken[]] THEN { AddDef[lhs]; next _ ParseConfigurationRemains[]; RETURN}; next _ NextToken[]; END; IF next.Equal["_"] THEN BEGIN AddDef[lhs]; next _ ParseCExpression[]; END ELSE BEGIN IF named THEN AddDef[lhs]; MaybeConsume[rhs]; IF next.Equal["["] THEN BEGIN IF NOT (next _ NextToken[]).Equal["]"] THEN next _ EatIDList[next, FALSE]; IF NOT next.Equal["]"] THEN ERROR GotoSyntaxError; next _ ParseCLinks[]; END ELSE IF next.Equal["LINKS"] THEN { SIGNAL Warning[IO.PutFR["[] missing before %g in %g", IO.int[source.GetIndex[]], IO.rope[sourceName]]]; next _ ParseCLinks[next]; }; END; END; }; ParseCExpression: PROC RETURNS [next: ROPE] = { next _ ParseCRightSide[]; WHILE next.Equal["PLUS"] DO next _ ParseCRightSide[]; ENDLOOP; WHILE next.Equal["THEN"] DO next _ ParseCRightSide[]; ENDLOOP; }; ParseCRightSide: PROC RETURNS [next: ROPE] = { next _ ParseItem[NIL, TRUE]; IF next.Equal["["] THEN BEGIN IF NOT (next _ NextToken[]).Equal["]"] THEN next _ EatIDList[next, FALSE]; IF NOT next.Equal["]"] THEN ERROR GotoSyntaxError; next _ ParseCLinks[]; END; }; ParseCHeadRemains: PROC RETURNS [next: ROPE] = { next _ ParseCLinks[]; next _ ParseImports[next]; next _ ParseCExports[next]; next _ ParseControlClause[next]; }; ParseCLinks: PROC [first: ROPE _ NIL] RETURNS [next: ROPE] = { next _ IF first # NIL THEN first ELSE NextToken[]; IF NOT next.Equal["LINKS"] THEN RETURN; IF NOT (next _ NextToken[]).Equal[":"] THEN ERROR GotoSyntaxError; next _ NextToken[]; IF NOT (next.Equal["CODE"] OR next.Equal["FRAME"]) THEN ERROR GotoSyntaxError; next _ NextToken[]; }; ParseImports: PROC [first: ROPE] RETURNS [next: ROPE] = { IF NOT first.Equal["IMPORTS"] THEN RETURN [first]; next _ ParseItemList[FALSE]; }; ParseCExports: PROC [first: ROPE] RETURNS [next: ROPE] = { IF NOT first.Equal["EXPORTS"] THEN RETURN [first]; next _ ParseItemList[FALSE]; }; ParseControlClause: PROC [first: ROPE] RETURNS [next: ROPE] = { IF NOT first.Equal["CONTROL"] THEN RETURN [first]; next _ EatIDList[NIL, FALSE]; }; ParseItemList: PROC [notice: BOOLEAN] RETURNS [next: ROPE] = { DO next _ ParseItem[NIL, notice]; IF NOT next.Equal[","] THEN EXIT; ENDLOOP; }; ParseItem: PROC [first: ROPE, notice: BOOLEAN] RETURNS [next: ROPE] = { lhs, rhs: ROPE; named: BOOL _ FALSE; lhs _ rhs _ IF first = NIL THEN NextToken[] ELSE first; IF named _ (next _ NextToken[]).Equal[":"] THEN BEGIN rhs _ NextToken[]; next _ NextToken[]; END; IF notice THEN { IF named THEN AddDef[lhs]; MaybeConsume[rhs]}; }; ParseCDirectory: PROC RETURNS [next: ROPE] = { firstClause: BOOL _ TRUE; ParseClause: PROC RETURNS [next: ROPE] = { moduleName: ROPE _ "?"; fileName: ROPE _ "?"; next _ NextToken[]; IF firstClause THEN {firstClause _ FALSE; IF next.Equal[";"] THEN RETURN}; IF NOT Letter[next.Fetch[0]] THEN ERROR GotoSyntaxError; moduleName _ fileName _ next; next _ NextToken[]; IF next.Equal[":"] THEN BEGIN next _ NextToken[]; IF next.Equal["TYPE"] THEN { next _ NextToken[]; IF Letter[next.Fetch[0]] THEN next _ NextToken[]; } ELSE IF next.Equal["FROM"] THEN { fileName _ source.GetRopeLiteral[]; next _ NextToken[]; } ELSE ERROR GotoSyntaxError; END; Consume[fileName]; AddDef[moduleName]; }; locals _ CONS[NIL, locals]; IF NOT (next _ NextToken[]).Equal["DIRECTORY"] THEN RETURN; DO IF (next _ ParseClause[]).Equal[";"] THEN EXIT; IF NOT next.Equal[","] THEN ERROR GotoSyntaxError; ENDLOOP; next _ NextToken[]; }; ParseCPacking: PROC [first: ROPE] RETURNS [next: ROPE] = { next _ first; WHILE next.Equal["PACK"] DO next _ EatIDList[NIL, FALSE]; IF NOT next.Equal[";"] THEN ERROR GotoSyntaxError; next _ NextToken[]; ENDLOOP; }; EatIDList: PROC [first: ROPE, notice: BOOLEAN] RETURNS [next: ROPE] = { next _ IF first = NIL THEN NextToken[] ELSE first; DO IF NOT Letter[next.Fetch[0]] THEN ERROR GotoSyntaxError; IF notice THEN Consume[next]; next _ NextToken[]; IF NOT next.Equal[","] THEN EXIT; next _ NextToken[]; ENDLOOP; }; source: IO.STREAM _ NIL; source _ FS.StreamOpen[fileName: sourceName, accessOptions: $read !FS.Error => {source _ NIL; CONTINUE}]; exists _ source # NIL; IF NOT exists THEN RETURN; source _ IOClasses.CreateCommentFilterStream[source]; [] _ source.GetIndex[]; ParseConfigDescription[!GotoSyntaxError => BEGIN SIGNAL Warning[IO.PutFR["Syntax error in %g; parse aborted at %g", IO.rope[sourceName], IO.int[source.GetIndex[]]]]; CONTINUE END]; source.Close[]; }; AddFinder[["Compiler and Binder", SourceFind], front]; END. ΜConfigAndMesaDeps.Mesa Last Edited by: Spreitzer, May 9, 1986 9:52:47 pm PDT Mike Spreitzer July 31, 1986 1:01:55 pm PDT Carl Hauser, April 11, 1985 3:52:50 pm PST INVARIANT StampRef in node props Κ}– "cedar" style˜Icode™™5K™+K™*—K˜KšΟk œ%œœF˜zK˜šΠbxœœ˜ Kšœœœ6˜W™ Kšœ™——K˜Kšœœ˜K˜KšΠblœœœ˜K˜Kšœœœ˜K˜š œ œœœœ˜8Kšœœ˜K˜—K˜š œ œœœœ˜DKšœœ˜K˜Kšœ˜K˜(K˜$Kšœœ˜Kšœœœ˜+Kšœœ˜K˜—K˜Kšœ œ˜"K˜š œ œœœœ˜;K˜ K˜—K˜š œ œœœœ˜AKšœœ˜ K˜Kšœ˜Kšœœ˜—K˜KšœM˜MK˜šœ"œ˜9Kšœ#˜#K˜K˜—K˜šΟn œœœœœœΟcœ˜LKšœœ˜Kšœ ˜K˜—š   œœ œœœ‘œ˜_Kšœœœ˜Kšœœ˜Kšœœ˜*—K˜š   œœœœœ‘œ˜NKšœ œ˜Kšœ ˜K˜—š  œœ œœœ‘œ˜`Kšœœœ˜Kšœœœ˜(šœœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœœ˜—Kšœ˜—K˜š  œœœœœœ œ;œ!œœ‘œ˜ΛKš˜KšœMœ˜RKšœœ˜Kšœ4˜4Kšœœ˜Kšœ˜K˜K˜š œœ œ˜"Kšœ3˜3Kšœ œ˜(šœœœ˜Kšœœ$˜+K˜K˜—Kšœœ˜'Kšœ˜—Kšœœ˜ Kš œœœœœ˜ZKšœœœœ˜š˜šœ ˜ šœB˜BKšœœ˜—Kšœ˜—Kšœœ˜ —KšœS˜SKšœP˜PK˜Kšœ?˜?Kšœ ˜ Kšœœ1˜=Kšœ)˜)Kšœœ œ˜5Kšœ>˜>Kšœ˜Kšœ&˜&Kšœ6˜6š˜˜šœœ˜Kšœ.˜.Kšœ ˜ Kšœ ˜ —šœ˜KšœK˜KKšœ˜Kšœ˜——šœ˜K˜K˜Kšœ˜Kšœ3˜3——Kšœ œ˜)KšœœΦ˜κKšœ%œ˜=Kšœœ˜0J˜Kšœ˜—K˜š   œœ œœ œ˜Kšœ/˜/Kšœ!œœœ˜Nšœ!œ˜)Kš œœœœœ˜K˜!Kšœ0œ˜>K˜(Kšœ0œ˜>Kšœœ˜"K˜—Kš œ&œ8œœœ-˜’Kšœ œ˜Kšœ$˜$Kšœ.˜.Kšœ˜—K˜š  œœ˜(Kšœ ˜ Kšœ/˜/Kšœ(œœ˜6Kš œœœœœ˜DKšœ˜K˜—K˜š œœœ˜:Kš˜Kšœ#˜#Kšœœœ˜;K˜;Kšœ˜—K˜š  œœœœ˜=Kš˜Kšœœ˜Kšœœ˜,Kšœœ˜/Kšœ˜šœœœ˜Kšœ ˜ šœ œ˜Kšœ˜Kšœ˜—K˜—Kšœœœ ˜/K˜šœ˜ Kšœ˜šœ˜Kšœ;œœœ˜fšœ œœœ%˜?Kšœ˜Kšœ ˜—K˜——K˜Kšœ˜—K˜š  œœ˜%Kš˜š  œœœ˜0Kš˜Kšœ œœ(˜:K˜)Kšœ œ˜.Kšœœœ˜$Kšœ˜—K˜Kšœ ˜ Kšœœ˜Kšœ(œœœ˜SKšœœœœ˜Kšœ&œœ˜4K˜#KšœO˜OKšœœ˜Kšœœ˜Kšœ˜—K˜š  œœ œœ‘œ˜SKš˜Kšœœ$˜;š œœ œ˜"Kšœ3˜3Kšœ œ˜+šœœœ˜Kšœœ$˜+K˜K˜—Kšœœ˜'Kšœ˜—Kšœœœ˜K˜K˜BKšœœ˜Kšœ˜Kšœœ˜3˜Kšœœ)œœ˜SK˜K˜K˜—Kšœ˜—K˜šœœœœ˜/Kšœ œ œ˜5Kšœœœœœœœœœœ ˜+Kšœ ˜—K˜š  œœœœ œ˜9Kšœ œ œœ˜2—K˜š  œœ5œ œœ œ˜‚Kš˜Kšœ œ'˜7Kšœœ˜2Kšœœ˜šœœœ˜Kšœœ?˜GKšœ˜Kšœ˜—Kšœ"˜"Kšœœœœ˜1šœœ˜š œœ œ˜"Kšœœ˜0Kšœ˜—Kšœ!œ˜%šœ˜Kšœ<˜Kš œœ œœœ ˜2Kšœœœœ˜'Kšœœ!œœ˜BK˜Kš œœœœœ˜NK˜Kšœ˜—š   œœ œœœ˜9Kšœœœœ ˜2Kšœœ˜Kšœ˜—š   œœ œœœ˜:Kšœœœœ ˜2Kšœœ˜Kšœ˜—š  œœ œœœ˜?Kšœœœœ ˜2Kšœœœ˜Kšœ˜—š   œœ œœœ˜>š˜Kšœœ ˜Kšœœœœ˜!Kšœ˜—Kšœ˜—š   œœ œ œœœ˜GKšœ œ˜Kšœœœ˜Kš œ œ œœ œ˜7šœ)˜/Kš˜Kšœ˜K˜Kšœ˜—šœœ˜Kšœœ ˜Kšœ˜—Kšœ˜—š œœœœ˜.Kšœ œœ˜š  œœœœ˜*Kšœ œ˜Kšœ œ˜K˜šœ ˜Kš œœœœœ˜6—Kšœœœœ˜8Kšœ˜K˜šœ˜Kš˜Kšœ˜šœœ˜K˜Kšœœ˜1K˜—šœœœ˜!K˜#K˜K˜—Kšœœ˜Kšœ˜—K˜K˜Kšœ˜—Kšœ œœ ˜Kšœœ)œœ˜;š˜Kšœ#œœ˜/Kšœœœœ˜2Kšœ˜—Kšœ˜Kšœ˜—š   œœ œœœ˜:K˜ šœ˜Kšœœœ˜Kšœœœœ˜2K˜Kšœ˜—Kšœ˜—š   œœ œ œœœ˜GKš œœ œœ œ˜2š˜Kšœœœœ˜8Kšœœ˜K˜Kšœœœœ˜!K˜Kšœ˜—Kšœ˜—Kšœœœœ˜Kš œ œ8œœœ˜iKšœœ˜Kšœœœœ˜Kšœ5˜5K˜šœ*˜*Kš˜Kšœ œ2œœ˜tKš˜Kšœ˜—K˜Kšœ˜—K˜K˜6K˜Kšœ˜—…—Ifd―