File IntUtilities.mesa
March 12, 1981 3:46 PM
Last Edited by: Pier, January 29, 1985 10:51:12 pm PST Converting to Cedar5.2
Last Edited by: McCreight, January 31, 1985 1:19:49 pm PST
DIRECTORY
ParserTypeDefs, IntDefs, IntStorageDefs, IntUtilityDefs, ParserErrorDefs, Rope;
IntUtilities: CEDAR PROGRAM
IMPORTS ParserErrorDefs, ParserTypeDefs
EXPORTS IntDefs, IntUtilityDefs =
BEGIN OPEN IntStorageDefs, IntUtilityDefs;
aScale, bScale: LONG CARDINAL;  -- scale factors for DS
tooBigLong: LONG CARDINAL;  -- largest number that can be scaled without overflow
tooBigInt: INT;
noScale: BOOLEAN;  -- identity flag for scale
TableSize: CARDINAL = 199;  -- symbol table size
sTable: ARRAY [0..TableSize) OF IntStorageDefs.STEntryList;
MaxMMStack: CARDINAL = 50;  -- max depth minmax stack
left,right,bottom,top: ARRAY [1..MaxMMStack] OF INT;
mmPtr: CARDINAL;      -- minmax stack pointer
InitUtilities: PUBLIC PROCEDURE RETURNS [BOOLEAN] =
BEGIN
FOR i: CARDINAL IN [0..TableSize) DO sTable[i] ← NIL ENDLOOP;
mmPtr ← 0;
noScale ← TRUE;
warned ← FALSE;
errorCount ← 0;
RETURN[TRUE];
END;
FinishUtilities: PUBLIC PROCEDURE RETURNS [BOOLEAN] =
BEGIN
FOR i: CARDINAL IN [0..TableSize) DO
FOR cur: STEntryList ← sTable[i], cur.rest WHILE cur#NIL DO
cur.first.calledBy ← NIL; -- breaks reference loops
ENDLOOP; -- the rest is a tree, so should be collectable
sTable[i] ← NIL;
ENDLOOP;
RETURN[TRUE];
END;
SemanticError: PUBLIC ERROR = CODE;
warned: BOOL;
errorCount: CARDINAL;
LogError: PUBLIC PROCEDURE [s: Rope.ROPE] =
BEGIN
errorCount ← errorCount + 1;
ParserErrorDefs.Report[s, FatalSemantic];
ERROR SemanticError[];
END;
OKToContinue: PUBLIC PROCEDURE RETURNS [BOOLEAN] =
BEGIN
IF errorCount > 0 AND NOT warned THEN
BEGIN
warned ← TRUE;
ParserErrorDefs.Report["Fatal Semantic Errors Exist, Strange Results May Occur If You Proceed", Advisory];
RETURN [FALSE];
END
ELSE RETURN[TRUE];
END;
reentrant minimum/maximum stuff for finding bounding boxes
InitMM: PUBLIC PROCEDURE [x,y: INT] =
BEGIN
IF (mmPtr ← mmPtr+1) > MaxMMStack THEN
BEGIN
ParserErrorDefs.Report["InitMM: no stack space", FatalInternal];
RETURN;
END
ELSE
BEGIN
left[mmPtr] ← x; right[mmPtr] ← x;
bottom[mmPtr] ← y; top[mmPtr] ← y;
RETURN;
END;
END;
MinMax: PUBLIC PROCEDURE [x,y: INT] =
BEGIN
IF x > right[mmPtr] THEN right[mmPtr] ← x
ELSE BEGIN IF x < left[mmPtr] THEN left[mmPtr] ← x; END;
IF y > top[mmPtr] THEN top[mmPtr] ← y
ELSE BEGIN IF y < bottom[mmPtr] THEN bottom[mmPtr] ← y; END;
END;
DoneMM: PUBLIC PROCEDURE =
BEGIN
IF mmPtr = 0 THEN ParserErrorDefs.Report["DoneMM: empty stack", FatalInternal]
ELSE mmPtr ← mmPtr-1;
END;
Extent: PUBLIC PROCEDURE RETURNS [l,r,b,t: INT] =
BEGIN
RETURN [left[mmPtr],right[mmPtr],bottom[mmPtr],top[mmPtr]];
END;
LookUp: PUBLIC PROCEDURE [symNumber: LONG CARDINAL] RETURNS [ent: STEntry] =
BEGIN
hAddr: CARDINAL = Hash[symNumber];
prev: STEntryList ← NIL;
FOR cur: STEntryList ← sTable[hAddr], cur.rest WHILE cur#NIL DO
IF cur.first.symNumber=symNumber AND NOT cur.first.deleted THEN
BEGIN
IF prev=NIL THEN RETURN[cur.first]
ELSE
BEGIN
prev.rest ← cur.rest;
cur.rest ← sTable[hAddr];
sTable[hAddr] ← cur;
RETURN[cur.first];
END;
END;
prev ← cur;
ENDLOOP;
sTable[hAddr] ← CONS[
NEW[STEntryRec ← [
bb: BBoxRecord[left:0,right:0,bottom:0,top:0],
bbValid: FALSE,
guts: NIL,
symNumber: symNumber,
deleted: FALSE, expanded: FALSE, bound: FALSE, defined: FALSE,
calledBy: NIL]],
sTable[hAddr]];
RETURN[sTable[hAddr].first];
END;
call proc on all symbols thus far defined or called
MapSymbols: PUBLIC PROCEDURE [proc: PROC[IntStorageDefs.STEntry]] =
BEGIN
FOR hAddr: NAT IN [0..TableSize) DO
FOR cur: STEntryList ← sTable[hAddr], cur.rest WHILE cur#NIL DO
proc[cur.first];
ENDLOOP;
ENDLOOP;
END;
set up scale factors for DS
SetScale: PUBLIC PROCEDURE [a,b: LONG CARDINAL] =
BEGIN
IF a = 0 OR b = 0 THEN LogError["Illegal Scale Factor"];
IF a = b THEN noScale ← TRUE  -- no need to do any computation
ELSE
BEGIN
aScale ← a; bScale ← b;
tooBigLong ← LAST[LONG CARDINAL]/aScale;
tooBigInt ← LAST[INT]/aScale;
noScale ← FALSE;
IF ((aScale/bScale)*bScale) # aScale THEN
ParserErrorDefs.Report["Scale Factor not an Integer, precision may be lost", Advisory];
END;
END;
scale a long cardinal by factors set up by a call to SetScale
ScaleLong: PUBLIC PROCEDURE [n: LONG CARDINAL] RETURNS [LONG CARDINAL] =
BEGIN
IF noScale THEN RETURN[n]
ELSE
BEGIN
IF n > tooBigLong THEN
BEGIN
LogError["Number Too Large to Scale"];
RETURN[LAST[LONG CARDINAL]];
END;
RETURN[(aScale*n)/bScale];
END;
END;
scale all the points in a path
ScalePath: PUBLIC PROCEDURE [s,d: ParserTypeDefs.Path] =
BEGIN
pt: ParserTypeDefs.Point;
scale all points in path
IF noScale THEN
BEGIN
ParserTypeDefs.CopyPath[s,d];
RETURN;
END
ELSE
THROUGH [1..ParserTypeDefs.PathLength[s]] DO
[,pt] ← ParserTypeDefs.RemovePoint[s];
ParserTypeDefs.AppendPoint[d,ScalePoint[pt]];
ENDLOOP;
END;
scale a point by factors set up by a call to SetScale
ScalePoint: PUBLIC PROCEDURE [p: ParserTypeDefs.Point] RETURNS [ParserTypeDefs.Point] =
BEGIN
temp: ParserTypeDefs.Point;
temp.x ← ScaleLongInt[p.x];
temp.y ← ScaleLongInt[p.y];
RETURN[temp];
END;
scale a long integer by factors set up by a call to SetScale
ScaleLongInt: PUBLIC PROCEDURE [n: INT] RETURNS [INT] =
BEGIN
IF noScale THEN RETURN[n]
ELSE
BEGIN
IF ABS[n] > tooBigInt THEN
BEGIN
LogError["Integer Magnitude Too Large to Scale"];
RETURN[IF n < 0 THEN FIRST[INT] ELSE LAST[INT]];
END;
RETURN[(aScale*n)/bScale];
END;
END;
private procedures
Hash: PROCEDURE [n: LONG CARDINAL] RETURNS [[0..TableSize)] =
BEGIN
RETURN[n MOD TableSize];
END;
END.