DIRECTORY Ascii: TYPE USING [ControlZ], ComData: TYPE USING [bodyIndex, cedar, nErrors, nWarnings, ownSymbols, switches, textIndex], CompilerUtil: TYPE USING [AcquireStream, AcquireTable, ReleaseStream, ReleaseTable], ConvertUnsafe: TYPE USING [SubString], ErrorTable: TYPE USING [CSRptr], IO: TYPE USING [card, char, CR, GetChar, EndOf, int, Put, PutChar, PutF, PutRope, rope, SetIndex, SP, STREAM], LiteralOps: TYPE USING [Value, StringValue, WordIndex], Log: TYPE USING [ErrorCode, Type], Rope: TYPE USING [ROPE], SourceMap: TYPE USING [nullLoc], Symbols: TYPE USING [Name, ISEIndex, Type, TransferMode, nullName, ISENull, nullType, BTNull], SymbolOps: TYPE USING [RCType, SubStringForName], SymbolTable: TYPE USING [Base], Tree: TYPE USING [Base, Index, Link, NodeName, Scan, Null, treeType], TreeOps: TYPE USING [ScanList]; LogPack: PROGRAM IMPORTS CompilerUtil, IO, LiteralOps, SymbolOps, TreeOps, dataPtr: ComData EXPORTS Log, SourceMap = { OPEN Symbols; ErrorCode: TYPE = Log.ErrorCode; FileByteIndex: TYPE = INT; Loc: PUBLIC TYPE = CARDINAL; nullLoc: Loc = SourceMap.nullLoc; chunkSize: NAT = 256; maxChunks: NAT = NAT.LAST/chunkSize + 1; IndexChunk: TYPE = ARRAY [0..chunkSize) OF INT; ChunkMap: TYPE = ARRAY [0..maxChunks) OF REF IndexChunk; map: REF ChunkMap _ NIL; next: CARDINAL _ 0; Init: PUBLIC PROC = Reset; Reset: PUBLIC PROC = { IF map # NIL THEN { FOR i: NAT IN [0..maxChunks) DO IF map[i] # NIL THEN FREE[@map[i]] ENDLOOP; FREE[@map]}; next _ 0}; Cons: PUBLIC PROC[index: INT] RETURNS[loc: Loc] = { IF index IN [0..NAT.LAST] THEN loc _ index ELSE { chunk: NAT = next/chunkSize; slot: NAT = next MOD chunkSize; IF map = NIL THEN map _ NEW[ChunkMap _ ALL[NIL]]; IF map[chunk] = NIL THEN map[chunk] _ NEW[IndexChunk]; map[chunk][slot] _ index; loc _ next + (NAT.LAST+1); next _ next + 1; IF next > NAT.LAST THEN ERROR}; RETURN}; Val: PUBLIC PROC[loc: Loc] RETURNS[index: INT] = { IF loc <= NAT.LAST THEN index _ loc ELSE { d: NAT = loc - CARDINAL[NAT.LAST+1]; index _ map[d/chunkSize][d MOD chunkSize]}; RETURN}; Error: PUBLIC PROC[code: ErrorCode] = { Enter[]; WriteErrorString[code]; ErrorLog[TRUE]; Exit[]}; ErrorHti: PUBLIC PROC[code: ErrorCode, name: Name] = { ErrorTree[code, [hash[name]]]}; ErrorN: PUBLIC PROC[code: ErrorCode, n: INTEGER] = { Enter[]; errorStream.Put[IO.int[n]]; errorStream.PutChar[' ]; WriteErrorString[code]; ErrorLog[TRUE]; Exit[]}; ErrorNode: PUBLIC PROC[code: ErrorCode, node: Tree.Index] = { ErrorTree[code, [subtree[node]]]}; ErrorNodeOp: PUBLIC PROC[code: ErrorCode, node: Tree.Index, op: Tree.NodeName] = { ErrorTreeOp[code, [subtree[node]], op]}; ErrorSei: PUBLIC PROC[code: ErrorCode, sei: ISEIndex] = { ErrorTree[code, [symbol[sei]]]}; ErrorTree: PUBLIC PROC[code: ErrorCode, t: Tree.Link] = { Enter[]; PrintOperand[t, 0, 0]; errorStream.PutRope[" "]; WriteErrorString[code]; ErrorLog[TRUE]; Exit[]}; ErrorTreeOp: PUBLIC PROC[code: ErrorCode, t: Tree.Link, op: Tree.NodeName] = { Enter[]; PrintOperand[t, 0, 0]; errorStream.PutRope[" "]; WriteErrorString[code]; PrintOperator[op]; errorStream.PutRope[" operation"]; ErrorLog[TRUE]; Exit[]}; ErrorType: PUBLIC PROC[code: ErrorCode, t: Tree.Link, type: Log.Type] = { Enter[]; PrintOperand[t, 0, 0]; errorStream.PutRope[" "]; WriteErrorString[code]; PrintType[type]; ErrorLog[TRUE]; Exit[]}; Warning: PUBLIC PROC[code: ErrorCode] = { IF dataPtr.switches['w] THEN { Enter[]; errorStream.PutRope["warning: "]; WriteErrorString[code]; ErrorLog[FALSE]; Exit[]}}; WarningNode: PUBLIC PROC[code: ErrorCode, node: Tree.Index] = { WarningTree[code, [subtree[node]]]}; WarningSei: PUBLIC PROC[code: ErrorCode, sei: ISEIndex] = { WarningTree[code, [symbol[sei]]]}; WarningSubString: PUBLIC PROC[code: ErrorCode, s: ConvertUnsafe.SubString] = { IF dataPtr.switches['w] THEN { Enter[]; WriteSubString[s]; errorStream.PutChar[' ]; WriteErrorString[code]; ErrorLog[FALSE]; Exit[]}}; WarningRope: PUBLIC PROC[code: ErrorCode, s: Rope.ROPE] = { IF dataPtr.switches['w] THEN { Enter[]; errorStream.Put[IO.rope[s], IO.char[' ]]; WriteErrorString[code]; ErrorLog[FALSE]; Exit[]}}; WarningTree: PUBLIC PROC[code: ErrorCode, t: Tree.Link] = { IF dataPtr.switches['w] THEN { Enter[]; errorStream.PutRope["warning: "]; PrintOperand[t, 0, 0]; errorStream.PutRope[" "]; WriteErrorString[code]; ErrorLog[FALSE]; Exit[]}}; PrintTextLine: PROC[i: Loc] = { start, lineIndex: FileByteIndex; char: CHAR; n: [1..100]; sourceStream: IO.STREAM _ CompilerUtil.AcquireStream[$source]; start _ lineIndex _ Val[i]; FOR n IN [1..100] UNTIL lineIndex = 0 DO lineIndex _ lineIndex - 1; sourceStream.SetIndex[lineIndex]; IF sourceStream.GetChar[] = IO.CR THEN EXIT; start _ lineIndex; ENDLOOP; sourceStream.SetIndex[start]; FOR n IN [1..100] WHILE ~sourceStream.EndOf[] DO SELECT (char _ IO.GetChar[sourceStream]) FROM IO.CR, Ascii.ControlZ => EXIT; ENDCASE => errorStream.PutChar[char]; ENDLOOP; errorStream.PutChar['\n]; CompilerUtil.ReleaseStream[$source]}; errorStream: IO.STREAM _ NIL; CSRp: ErrorTable.CSRptr; ss: ConvertUnsafe.SubString _ [NIL, 0, 0]; Enter: PROC = { errorStream _ CompilerUtil.AcquireStream[$log]; CSRp _ CompilerUtil.AcquireTable[error]; ss.base _ @CSRp[CSRp.stringOffset]}; Exit: PROC = { CompilerUtil.ReleaseTable[error]; CompilerUtil.ReleaseStream[$log]; errorStream _ NIL}; WriteSubString: PROC[s: ConvertUnsafe.SubString] = { FOR i: CARDINAL IN [s.offset .. s.offset+s.length) DO errorStream.PutChar[s.base[i]] ENDLOOP }; WriteId: PROC[stb: SymbolTable.Base, name: Name] = { IF name # nullName THEN { s: ConvertUnsafe.SubString _ stb.SubStringForName[name]; WriteSubString[s]} }; WriteErrorString: PROC[n: ErrorCode] = { ss.offset _ CSRp.ErrorMessages[n].offset; ss.length _ CSRp.ErrorMessages[n].length; WriteSubString[ss]}; WriteName: PROC[name: Name] = { IF name = nullName THEN errorStream.PutRope["(anonymous)"] ELSE WriteId[dataPtr.ownSymbols, name]}; WriteSei: PROC[sei: ISEIndex] = { WriteName[IF sei = ISENull THEN nullName ELSE dataPtr.ownSymbols.seb[sei].hash] }; WriteLti: PROC[t: Tree.Link.literal] = { WITH t.index SELECT FROM word => errorStream.Put[IO.int[LiteralOps.Value[lti]]]; string => { s: LONG STRING = LiteralOps.StringValue[sti]; errorStream.PutChar['"]; FOR i: CARDINAL IN [0..s.length) DO errorStream.PutChar[s[i]] ENDLOOP; errorStream.PutChar['"]}; ENDCASE }; OpPrec: ARRAY Tree.NodeName[$assignx..$uparrow] OF CARDINAL = [ 1, 1, 2, 3, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 10, 10, 10, 1, 4, 8, 9, 10]; WriteOpName: PROC[n: Tree.NodeName[$assignx..$uparrow]] = { ss.offset _ CSRp.OpName[n].offset; ss.length _ CSRp.OpName[n].length; WriteSubString[ss]}; WriteFnName: PROC[n: Tree.NodeName[$min..$new]] = { ss.offset _ CSRp.FnName[n].offset; ss.length _ CSRp.FnName[n].length; WriteSubString[ss]}; WriteApplName: PROC[n: Tree.NodeName[$apply..$joinx]] = { ss.offset _ CSRp.ApplName[n].offset; ss.length _ CSRp.ApplName[n].length; WriteSubString[ss]}; WriteFApplName: PROC[n: Tree.NodeName[$restart..$broadcast]] = { ss.offset _ CSRp.FApplName[n].offset; ss.length _ CSRp.FApplName[n].length; WriteSubString[ss]}; PrintOperator: PROC[op: Tree.NodeName] = { IF op IN Tree.NodeName[$apply..$joinx] THEN WriteApplName[op] ELSE IF op IN Tree.NodeName[$assignx..$uparrow] THEN WriteOpName[op] ELSE IF op IN Tree.NodeName[$min..$new] THEN WriteFnName[op] ELSE IF op = $ord THEN errorStream.PutRope["ORD"] ELSE IF op IN Tree.NodeName[$call..$join] THEN { applMap: ARRAY Tree.NodeName[$call..$join] OF Tree.NodeName = [ call: $callx, portcall: $portcallx, signal: $signalx, error: $errorx, syserror: $syserrorx, xerror: $errorx,start: $startx, join: $joinx]; PrintOperator[applMap[op]]} ELSE IF op IN Tree.NodeName[$restart..$broadcast] THEN WriteFApplName[op] ELSE errorStream.PutRope["..."]}; Cutoff: CARDINAL = 3; PrintOperand: PROC[t: Tree.Link, tPrec, depth: CARDINAL] = { IF t = Tree.Null THEN RETURN; WITH e: t SELECT FROM hash => WriteName[e.index]; symbol => WriteSei[e.index]; literal => WriteLti[e]; subtree => { node: Tree.Index = e.index; tb: Tree.Base _ dataPtr.ownSymbols.tb; op: Tree.NodeName = tb[node].name; IF depth > Cutoff THEN {errorStream.PutRope["..."]; RETURN}; SELECT op FROM syserror, syserrorx => errorStream.PutRope["ERROR"]; lengthen, --abs,-- IN [first..succ], IN [length..base], nil => { IF tb[node].son[1] # Tree.Null THEN { PrintOperand[tb[node].son[1], OpPrec[dot], depth+1]; errorStream.PutChar['.]}; WriteFnName[op]}; ord => { -- pending reordering of node names PrintOperand[tb[node].son[1], OpPrec[dot], depth+1]; errorStream.PutRope[".ORD"]}; IN [call .. rowcons], stringinit, IN [min .. loophole], val => { OPEN tb[node]; args: Tree.Link; SELECT op FROM IN [call .. rowcons], stringinit => { IF son[1] # Tree.Null THEN PrintOperand[son[1], 0, depth]; args _ son[2]}; IN [min .. loophole] => {WriteFnName[op]; args _ son[1]}; val => {errorStream.PutRope["VAL"]; args _ son[1]}; -- until reordered ENDCASE; IF args # Tree.Null OR op # nil THEN { errorStream.PutChar['[]; IF depth = Cutoff AND args.tag = subtree THEN errorStream.PutRope["..."] ELSE PrintOperandList[args, depth+1]; IF op IN [call .. joinx] AND nSons > 2 THEN errorStream.PutRope[" !..."]; errorStream.PutChar[']]}}; IN [assignx .. uparrow] => { OPEN tb[node]; prec: CARDINAL = OpPrec[op]; IF prec < tPrec THEN errorStream.PutChar['(]; SELECT op FROM IN [create .. addr] => {WriteOpName[op]; PrintOperand[son[1], prec, depth]}; IN [assignx .. dollar] => { PrintOperand[son[1], prec, depth+1]; WriteOpName[op]; PrintOperand[son[2], prec+1, depth+1]}; uparrow => { PrintOperand[son[1], prec, depth]; errorStream.PutChar['^]}; ENDCASE => errorStream.PutChar['?]; IF prec < tPrec THEN errorStream.PutChar[')]}; IN [intOO .. intCC] => { OPEN tb[node]; errorStream.PutChar[IF op = intOO OR op = intOC THEN '( ELSE '[]; PrintOperand[son[1], 0, depth]; errorStream.PutRope[".."]; PrintOperand[son[2], 0, depth]; errorStream.PutChar[IF op = intOO OR op = intCO THEN ') ELSE ']]}; clit => { c: CHAR = VAL[LiteralOps.Value[ LiteralOps.WordIndex[NARROW[tb[node].son[1], Tree.Link.literal].index]]]; errorStream.PutChar['']; IF c >= IO.SP THEN errorStream.PutChar[c] ELSE {errorStream.PutF["\\%3b", IO.card[c.ORD]]}}; new, cons, listcons => { IF tb[node].son[1] # Tree.Null THEN { PrintOperand[tb[node].son[1], OpPrec[dot], depth+1]; errorStream.PutChar['.]}; errorStream.PutRope[ SELECT op FROM new => "NEW", cons => "CONS", ENDCASE => "LIST"]; errorStream.PutChar['[]; IF depth = Cutoff THEN errorStream.PutRope["..."] ELSE PrintOperandList[tb[node].son[2], depth+1]; errorStream.PutChar[']]}; atom => { errorStream.PutChar['$]; WITH e1: tb[node].son[1] SELECT FROM hash => WriteName[e1.index]; ENDCASE}; llit, IN [cast .. openx], thread => PrintOperand[tb[node].son[1], tPrec, depth]; item => PrintOperand[tb[node].son[2], tPrec, depth]; ENDCASE => errorStream.PutRope["..."]}; ENDCASE}; PrintOperandList: PROC[t: Tree.Link, depth: CARDINAL] = { firstSon: BOOL _ TRUE; PrintItem: Tree.Scan = { IF ~firstSon THEN errorStream.PutRope[", "]; firstSon _ FALSE; IF t # Tree.Null THEN PrintOperand[t, 0, depth]}; TreeOps.ScanList[t, PrintItem]}; PrintType: PROC[root: Log.Type] = { seb: Tree.Base _ root.stb.seb; PrintTypeExp: PROC[type: Symbols.Type, depth: NAT] = { IF depth <= Cutoff THEN WITH t: seb[type] SELECT FROM id => WriteId[root.stb, t.hash]; cons => WITH s: t SELECT FROM mode => errorStream.PutRope["TYPE"]; enumerated => errorStream.PutRope["{...}"]; record => errorStream.PutRope["RECORD[...]"]; ref => { IF s.var THEN errorStream.PutRope[IF s.readOnly THEN "READONLY " ELSE "VAR "] ELSE { errorStream.PutRope[IF s.counted THEN "REF " ELSE "POINTER TO "]; IF s.readOnly THEN errorStream.PutRope["READONLY "]}; PrintTypeExp[s.refType, depth+1]}; array => { IF s.packed THEN errorStream.PutRope["PACKED "]; errorStream.PutRope["ARRAY "]; PrintTypeExp[s.indexType, depth+1]; errorStream.PutRope[" OF "]; PrintTypeExp[s.componentType, depth+1]}; arraydesc => { errorStream.PutRope["DESCRIPTOR FOR "]; PrintTypeExp[s.describedType, depth+1]}; transfer => { xferName: ARRAY Symbols.TransferMode OF Rope.ROPE = [ "PROC", "PORT", "SIGNAL", "ERROR", "PROCESS", "PROGRAM", NIL]; IF s.safe # dataPtr.cedar THEN errorStream.PutRope[IF s.safe THEN "SAFE " ELSE "UNSAFE "]; errorStream.PutRope[xferName[s.mode]]; IF s.typeIn # Symbols.nullType THEN errorStream.PutRope["[...]"]; IF s.typeOut # Symbols.nullType THEN errorStream.PutRope[" RETURNS[...]"] }; subrange => { PrintTypeExp[s.rangeType, depth+1]; errorStream.PutRope["[...)"]}; long => { IF SymbolOps.RCType[type] = $simple THEN PrintTypeExp[s.rangeType, depth] ELSE {errorStream.PutRope["LONG "]; PrintTypeExp[s.rangeType, depth+1]}}; zone => { IF ~s.counted THEN errorStream.PutRope["UNCOUNTED "]; errorStream.PutRope["ZONE"]}; any => errorStream.PutRope["ANY"]; ENDCASE => errorStream.PutRope["..."]; ENDCASE; }; errorStream.PutRope[" (expected "]; PrintTypeExp[root.type, 0]; errorStream.PutChar[')]}; ErrorLog: PROC[error: BOOL] = { bodyId: ISEIndex; index: Loc = dataPtr.textIndex; IF error THEN dataPtr.nErrors _ dataPtr.nErrors + 1 ELSE dataPtr.nWarnings _ dataPtr.nWarnings + 1; errorStream.PutRope[", at "]; IF dataPtr.bodyIndex # BTNull THEN { bodyId _ dataPtr.ownSymbols.bb[dataPtr.bodyIndex].id; IF bodyId # ISENull THEN WriteSei[bodyId]}; IF index # nullLoc THEN errorStream.PutF["[%d]", IO.int[Val[index]]]; errorStream.PutChar[':]; errorStream.PutChar['\n]; IF index # nullLoc THEN PrintTextLine[index] ELSE errorStream.PutRope["(source from inline)\n"]; errorStream.PutChar['\n]}; }. .LogPack.Mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Satterthwaite, April 15, 1986 10:07:06 am PST Maxwell, August 11, 1983 8:32 am Russ Atkinson (RRA) March 6, 1985 10:21:16 pm PST source location encoding public interface source printing errorStream, CSRp and desc.base are set by Enter tables used for printing trees (pending reordering of node names) OpName: ARRAY Tree.NodeName[$assignx..$uparrow] OF STRING = [ "_", " OR ", " AND ", "=", "#", "<", ">=", ">", "<=", " IN ", " ~IN ", "+", "-", "*", "/", " MOD ", ".", ".", ".", " NEW ", "~", "-", "@", "^"]; FnName: ARRAY Tree.NodeName[$min..$new] OF STRING = [ "MIN", "MAX", "LONG", "ABS", "ALL", "SIZE", "FIRST", "LAST", "PRED", "SUCC", "DESCRIPTOR", "LENGTH", "BASE", "LOOPHOLE", "NIL", "NEW"]; ApplName: ARRAY Tree.NodeName[$apply..$joinx] OF STRING _ [ "APPLY", "APPLY", "", "SIGNAL", "ERROR", "ERROR", "START", "FORK", "JOIN"]; FApplName: ARRAY Tree.NodeName[$restart..$broadcast] OF STRING _ [ "RESTART", "STOP", "LOCK", "WAIT", "NOTIFY", "BROADCAST"]; error-handling routines Κ«˜codešœ ™ Kšœ Οmœ1™K˜šžœžœ žœž˜(K˜Kšœ!˜!Kš žœžœžœžœžœ˜,K˜Kšžœ˜—Kšœ˜šžœžœ žœž˜0šžœ#ž˜-Kšžœžœžœ˜Kšžœ˜%—Kšžœ˜—Kšœ˜K˜%K˜K˜—Kšœ0™0K˜Kšœ žœžœžœ˜K˜K˜Kšœžœ˜*K˜šŸœžœ˜K˜/K˜(K˜$K˜—šŸœžœ˜K˜!Kšœ1žœ˜6K˜K˜—šŸœžœ ˜4šžœžœžœ!ž˜5Kšœ˜Kšž˜—Kšœ˜K˜—šŸœžœ'˜4šžœžœ˜Kšœ9˜9Kšœ˜—Kšœ˜K˜—K˜šŸœžœ˜(K˜)K˜)Kšœ˜K˜—šŸ œžœ˜Kšžœžœ#˜:Kšžœ$˜(K˜—šŸœžœ˜!šœ žœ˜Kšžœ ˜ Kšžœ"˜&—šœ˜K˜K˜——šŸœžœ˜(šžœ žœž˜Kšœžœ˜7˜ Kšœžœžœ˜-Kšœ˜šžœžœžœž˜#Kšœžœ˜"—Kšœ˜—Kšž˜—šœ˜K˜K˜——KšœA™AK˜šœ=™=Kšœ™KšœA™AKšœ™Kšœ™Kšœ™——˜šœžœ#žœžœ˜?K˜K˜K˜K˜ K˜K˜—šŸ œžœ*˜;K˜"K˜"Kšœ˜K˜K˜—šœ5™5KšœL™LKšœ:™:——˜šŸ œžœ"˜3K˜FKšœ˜K˜—K˜šœ;™;KšœK™K——˜šŸ œžœ&˜9K˜JKšœ˜K˜—K™šœB™BKšœ:™:——˜šŸœžœ,˜@K˜LKšœ˜K˜—K˜šŸ œžœ˜*Kšžœžœžœ˜=Kšžœžœžœ#žœ˜DKšžœžœžœžœ˜—šžœž˜Kšœžœžœ žœ ˜;—K˜&Kšžœžœ˜Ašžœž˜$K˜$—K˜—šœ ˜ K˜#Kšœ˜—˜ šžœ"ž˜(Kšœ ˜ —KšžœE˜I—šœ ˜ Kšžœ žœ#˜5Kšœ˜—Kšœ"˜"Kšžœ˜&——Kšžœ˜——Kšœ˜K˜—K˜YK˜K˜——šœ™K˜šŸœžœžœ˜K˜Kšœ˜Kšžœžœ&˜3Kšžœ+˜/Kšœ˜šžœžœ˜$K˜5Kšžœžœ˜+—Kšžœžœžœ˜EKšœ3˜3Kšžœžœ˜,Kšžœ/˜3Kšœ˜K˜—˜K˜———…—4ώIΧ