-- File: DisjointAlloc.mesa
-- Allocation routines for Disjoint
-- Written by Martin Newell/Dan Fitzpatrick June 1981
-- Last edited (Alto/Pilot): September 1, 1981 7:34 PM

DIRECTORY

DisjointTypes: FROM "DisjointTypes" USING [DisCell, DisCellRecord, Instance,
InstanceRecord, Symbol, SymbolRecord, Rectangle, RectangleRecord, PIP,
PIPRecord, Geometry, GeometryRecord, PropID, PropList, PropListRecord],
DisjointAllocDefs: FROM "DisjointAllocDefs",
DisjointIODefs: FROM "DisjointIODefs" USING [WriteLongDecimal],
DisjointPropDefs: FROM "DisjointPropDefs" USING [GetProp],
IODefs: FROM "IODefs" USING [WriteString, WriteLine,WriteDecimal],
Runtime: FROM "Runtime" USING [CallDebugger],
String: FROM "String" USING [AppendString, EqualString],
SystemDefs: FROM "SystemDefs" USING [AllocateHeapString],
XFSPDefs: FROM "XFSPDefs" USING [XAllocateHeapNode];

DisjointAlloc: PROGRAM
IMPORTS DisjointIODefs, DisjointPropDefs, IODefs, Runtime, String, SystemDefs, XFSPDefs
EXPORTS DisjointAllocDefs =
BEGIN
OPEN DisjointIODefs, DisjointPropDefs, DisjointTypes, IODefs, Runtime, String, SystemDefs, XFSPDefs;

-- Allocation for symbols

MakeSymbol: PUBLIC PROCEDURE [name: STRING, l,b,r,t: REAL] RETURNS[Symbol] =
BEGIN
s: Symbol ← LookupSymbol[name];
IF s=NIL THEN {
s ← AllocateSymbol[];
s.name ← AllocateHeapString[name.length];
AppendString[s.name, name];
};
s.windows ← MakeRectangle[l,b,r,t];
RETURN[s];
END;

AllocateSymbol: PUBLIC PROCEDURE[] RETURNS[symb: Symbol] =
BEGIN
symb ← GetSymbol[];
symb↑ ← [
next: SymbolList,
name: NIL,
geom: NIL,
insts: NIL,
windows: NIL
];
SymbolList ← symb;
END;

GetSymbol: PUBLIC PROCEDURE[] RETURNS[symb: Symbol] =
-- More primitive than AllocateSymbol, doesn’t put returned symbol on SymbolList
BEGIN
symbAllocCount ← symbAllocCount+1;
symb ← Alloc[SIZE[SymbolRecord]];
symb.insts ← NIL;
symb.prop ← NIL;
END;

FreeSymbol: PUBLIC PROCEDURE[symb: Symbol] =
BEGIN
sptr: LONG POINTER TO Symbol;
FOR sptr ← @SymbolList, @sptr.next UNTIL sptr↑=NIL DO
IF sptr↑ = symb THEN {
sptr↑ ← symb.next;
EXIT;
};
ENDLOOP;
symbAllocCount ← symbAllocCount-1;
Free[symb,SIZE[SymbolRecord]];
END;

FreeMarkedSymbols: PUBLIC PROCEDURE[id: PropID] =
BEGIN
sptr,next: Symbol;
FOR sptr ← SymbolList, next UNTIL sptr=NIL DO
next ← sptr.next;
IF GetProp[sptr.prop,id] # NIL THEN FreeSymbol[sptr];
ENDLOOP;
END;

LookupSymbol: PUBLIC PROCEDURE [name: STRING] RETURNS[s: Symbol] =
BEGIN
FOR s ← SymbolList, s.next UNTIL s = NIL DO
IF EqualString[name,s.name] THEN RETURN;
ENDLOOP;
END;

EnumerateSymbols: PUBLIC PROCEDURE[proc: PROC[s: Symbol]RETURNS[BOOLEAN]]
RETURNS[BOOLEAN] =
--BOOLEAN returns are both abort flags
BEGIN
FOR s:Symbol ← SymbolList, s.next UNTIL s=NIL DO
IF proc[s] THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
END;

InsertSymbolList: PUBLIC PROCEDURE [list: Symbol] =
BEGIN
next: Symbol;

FOR s:Symbol ← list, next UNTIL s = NIL DO
next ← s.next;
s.next ← SymbolList;
SymbolList ← s;
ENDLOOP;
END;

-- Allocation for instances

MakeInstance: PUBLIC PROCEDURE[parent: Symbol, name: STRING, x,y: REAL]
RETURNS[Instance] =
BEGIN
in: Instance;
s: Symbol ← LookupSymbol[name];
IF s=NIL THEN { -- a forward reference
s ← AllocateSymbol[];
s.name ← AllocateHeapString[name.length];
AppendString[s.name, name];
};
in ← AllocateInstance[];
in ↑ ← [
next: NIL,
symbol: s,
xOffset: x,
yOffset: y
];
in.next ← parent.insts;
parent.insts ← in;
RETURN[in];
END;

AllocateInstance: PUBLIC PROCEDURE[] RETURNS[inst: Instance] =
BEGIN
instAllocCount ← instAllocCount+1;
inst ← Alloc[SIZE[InstanceRecord]];
END;

FreeInstance: PUBLIC PROCEDURE[inst: Instance] =
BEGIN
instAllocCount ← instAllocCount-1;
Free[inst,SIZE[InstanceRecord]];
END;

-- Allocation for Geometry

MakeGeometry: PUBLIC PROCEDURE[parent: Symbol, layer: CARDINAL, l,b,r,t: REAL]
RETURNS[Geometry] =
BEGIN
g: Geometry ← AllocateGeometry[];
g ↑ ← [
next: NIL,
layer: layer,
l: l,
b: b,
r: r,
t: t
];
g.next ← parent.geom;
parent.geom ← g;
RETURN[g];
END;

AllocateGeometry: PUBLIC PROCEDURE[] RETURNS[g: Geometry] =
BEGIN
gAllocCount ← gAllocCount+1;
g ← Alloc[SIZE[GeometryRecord]];
END;

FreeGeometry: PUBLIC PROCEDURE[g: Geometry] =
BEGIN
gAllocCount ← gAllocCount-1;
Free[g,SIZE[GeometryRecord]];
END;

-- Allocation for PIP’s

AllocatePIP: PUBLIC PROCEDURE[] RETURNS[pip: PIP] =
BEGIN
pipAllocCount ← pipAllocCount+1;
pip ← Alloc[SIZE[PIPRecord]];
END;

FreePIP: PUBLIC PROCEDURE[pip: PIP] =
BEGIN
Free[pip,SIZE[PIPRecord]];
pipAllocCount ← pipAllocCount-1;
END;

-- Allocation for DisCells

AllocateDisCell: PUBLIC PROCEDURE[] RETURNS[dc: DisCell] =
BEGIN
discellAllocCount ← discellAllocCount+1;
dc ← Alloc[SIZE[DisCellRecord]];
END;

FreeDisCell: PUBLIC PROCEDURE[dc: DisCell] =
BEGIN
Free[dc,SIZE[DisCellRecord]];
discellAllocCount ← discellAllocCount-1;
END;

-- Allocation for Windows

MakeRectangle: PUBLIC PROCEDURE[l,b,r,t: REAL]
RETURNS[rec: DisjointTypes.Rectangle] =
BEGIN
rec ← AllocateRectangle[];
rec↑ ← [
next: NIL,
l: l,
b: b,
r: r,
t: t
];
END;

AllocateRectangle: PUBLIC PROCEDURE[] RETURNS[r: DisjointTypes.Rectangle] =
BEGIN
recAllocCount ← recAllocCount+1;
r ← Alloc[SIZE[RectangleRecord]];
END;

FreeRectangle: PUBLIC PROCEDURE[r: DisjointTypes.Rectangle] =
BEGIN
Free[r,SIZE[RectangleRecord]];
recAllocCount ← recAllocCount-1;
END;

-- Allocation for Property Cells

AllocateProp: PUBLIC PROCEDURE[] RETURNS[p: PropList] =
BEGIN
propAllocCount ← propAllocCount+1;
p ← Alloc[SIZE[PropListRecord]];
END;

FreeProp: PUBLIC PROCEDURE[p: PropList] =
BEGIN
Free[p,SIZE[PropListRecord]];
propAllocCount ← propAllocCount-1;
END;

Alloc: PUBLIC PROCEDURE[n:INTEGER] RETURNS[p: LONG POINTER] =
BEGIN
IF n < AllocMin OR AllocMax < n THEN {
WriteString["Alloc@DisjointAlloc:n is "]; WriteDecimal[n]; WriteLine[""];
CallDebugger["Tried to Alloc too big (or too small) a structure"];
p ← XAllocateHeapNode[n];
};
allocated[n] ← allocated[n] + 1;
IF FreeList[n] = NIL THEN p ← XAllocateHeapNode[n]
ELSE {
p ← FreeList[n];
FreeList[n] ← FreeList[n].next;
};
END;

Free: PUBLIC PROCEDURE[p:LONG POINTER, n:INTEGER] =
BEGIN
ptr: DummyCell ← p;
IF n < AllocMin OR AllocMax < n THEN {
WriteString["Free@DisjointAlloc:n is "]; WriteDecimal[n]; WriteLine[""];
CallDebugger["Tried to Free too big (or too small) a structure"];
};
allocated[n] ← allocated[n] - 1;
ptr.next ← FreeList[n]; FreeList[n] ← ptr;
END;

AllocMin: CARDINAL = 4;
AllocMax: CARDINAL = 36;
allocated: ARRAY [AllocMin..AllocMax] OF LONG CARDINAL ← ALL[0];
FreeList: ARRAY [AllocMin..AllocMax] OF DummyCell ← ALL[NIL];
DummyCell: TYPE = LONG POINTER TO DummyRecord;
DummyRecord: TYPE = RECORD [
next: DummyCell
];

PrintAlloc: PUBLIC PROCEDURE =
BEGIN
free: LONG CARDINAL;
totalFree: LONG CARDINAL ← 0;
totalAlloc: LONG CARDINAL ← 0;
WriteLine["Alloc summary"];
FOR i:INTEGER IN [AllocMin..AllocMax] DO
free ← 0;
FOR p:DummyCell ← FreeList[i],p.next UNTIL p=NIL DO
free←free+1;
ENDLOOP;
WriteDecimal[i]; WriteString[": "];
WriteLongDecimal[allocated[i]]; WriteString[" allocated, "];
WriteLongDecimal[free]; WriteLine[" free"];
totalFree ← totalFree + i*free;
totalAlloc ← totalAlloc + i*allocated[i];
ENDLOOP;
WriteString["Totals: "];
WriteLongDecimal[totalAlloc/1024]; WriteString["K allocated, "];
WriteLongDecimal[totalFree/1024]; WriteLine["K free"];
CheckAlloc[];
WriteAlloc["Symbols", symbAllocCount, usedSymb];
WriteAlloc["Instances", instAllocCount, usedInst];
WriteAlloc["PIPs", pipAllocCount, 0];
WriteAlloc["DisCells", discellAllocCount, 0];
WriteAlloc["Windows", recAllocCount, usedWind];
WriteAlloc["Geometrys", gAllocCount, usedGeom];
WriteAlloc["Props", propAllocCount, 0];
END;

WriteAlloc: PROCEDURE[s: STRING, nAlloc,nUsed: LONG CARDINAL] =
BEGIN
WriteString[s];WriteString[": "];WriteLongDecimal[nAlloc];
WriteString[" allocated, "]; WriteLongDecimal[nUsed];
WriteLine[" used"];
END;

CheckAlloc: PUBLIC PROCEDURE =
BEGIN

Count: PROC[s: Symbol] RETURNS [BOOLEAN] =
BEGIN
usedSymb ← usedSymb + 1;
FOR i: Instance ← s.insts,i.next UNTIL i = NIL DO
usedInst ← usedInst + 1;
ENDLOOP;
FOR i: Rectangle ← s.windows,i.next UNTIL i = NIL DO
usedWind ← usedWind + 1;
ENDLOOP;
FOR i: Geometry ← s.geom,i.next UNTIL i = NIL DO
usedGeom ← usedGeom + 1;
ENDLOOP;
RETURN[FALSE];
END;

usedSymb ← 0;
usedInst ← 0;
usedWind ← 0;
usedGeom ← 0;
[] ← EnumerateSymbols[Count];
END;

usedSymb:LONG CARDINAL;
usedInst:LONG CARDINAL;
usedWind:LONG CARDINAL;
usedGeom:LONG CARDINAL;

SymbolList: Symbol ← NIL;

symbAllocCount: LONG CARDINAL ← 0;
instAllocCount: LONG CARDINAL ← 0;
gAllocCount: LONG CARDINAL ← 0;
pipAllocCount: LONG CARDINAL ← 0;
discellAllocCount: LONG CARDINAL ← 0;
recAllocCount: LONG CARDINAL ← 0;
propAllocCount: LONG CARDINAL ← 0;

END.