DIRECTORY
ParserTypeDefs, IntDefs, IntStorageDefs, IntUtilityDefs, ParserErrorDefs, Rope;
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.