=
BEGIN OPEN PartitionDefs;
This program produces Mebes layer files. A layer file is one of
the many files that will reside on the final magtape. It fetches
Mebes objects from the partition files. The partition files sort
the objects into their appropiate stripe.
StartStripe: CARDINAL = 7;
EndStripe: CARDINAL = 8;
EndBuffer: CARDINAL = 9;
EndDrawing: CARDINAL = 4;
EBESStreamStateRef: TYPE = REF EBESStreamState;
EBESStreamState:
TYPE =
RECORD [
dest: IO.STREAM,
eor: BOOL,
buf: REF TEXT];
ebesStreamProcs:
REF
IO.StreamProcs =
IO.CreateStreamProcs[
variety: output,
class: $EBESOutputStream,
unsafePutBlock: PutEBESBlock,
flush: FlushEBES,
close: CloseEBES
];
EBESOpen:
PROC [ dest:
IO.
STREAM, eor:
BOOL ←
TRUE ]
RETURNS [ self:
IO.
STREAM ] =
BEGIN
state: EBESStreamStateRef = NEW[EBESStreamState ←
[dest: dest, eor: eor, buf: NEW[TEXT[2048]]]];
state.buf.length ← 0;
self ←
IO.CreateStream[
streamProcs: ebesStreamProcs,
streamData: state
];
END;
PutEBESBlock:
PROC [ self:
IO.
STREAM, block:
IO.UnsafeBlock ] =
TRUSTED BEGIN
state: EBESStreamStateRef = NARROW[self.streamData];
FlushEBESIfNecessary[state, block.count];
FOR i:
INT
IN [0..block.count)
DO
CharArrayPtr: TYPE = LONG POINTER TO PACKED ARRAY [0..0) OF CHAR;
state.buf[state.buf.length+i] ← LOOPHOLE[block.base, CharArrayPtr][block.startIndex+i];
ENDLOOP;
state.buf.length ← state.buf.length+block.count;
END;
FlushEBESIfNecessary:
PROC [state: EBESStreamStateRef, newBytes:
NAT] =
INLINE
BEGIN
IF state.buf.maxLength<state.buf.length+newBytes+
(
IF state.eor
THEN Basics.bytesPerWord*
SIZE[
CARDINAL]
-- for end of record --
ELSE 0)
THEN
DoFlushEBES[state];
END;
FlushEBES:
PROC [ self:
IO.
STREAM ] = {DoFlushEBES[
NARROW[self.streamData]]};
BasicCommand: TYPE = MACHINE DEPENDENT RECORD [commandCode (0): NAT ←];
endRecord: BasicCommand = [commandCode: 9];
DoFlushEBES:
PROC [ state: EBESStreamStateRef ] =
BEGIN
IF state.buf.length>0
THEN
BEGIN
IF state.eor
THEN
BEGIN
IF state.buf.length+2<=state.buf.maxLength
THEN
TRUSTED BEGIN -- append an end-of-record command to the buffer
endRec: PACKED ARRAY [0..2) OF CHAR = LOOPHOLE[endRecord];
state.buf[state.buf.length] ← endRec[0];
state.buf[state.buf.length+1] ← endRec[1];
state.buf.length ← state.buf.length+2;
END
ELSE ERROR; -- can't terminate buffer properly
END;
FOR i:
CARDINAL
IN [state.buf.length..state.buf.maxLength)
DO
state.buf[i] ← 000C; -- pad out with 0's
ENDLOOP;
state.buf.length ← state.buf.maxLength;
state.dest.PutBlock[state.buf];
END;
state.buf.length ← 0;
END;
CloseEBES:
PROC [ self:
IO.
STREAM, abort:
BOOL ←
FALSE ] =
BEGIN
state: EBESStreamStateRef = NARROW[self.streamData];
self.Flush[];
state.dest.Close[];
END;
word: REF CARDINAL ← NEW[CARDINAL];
WriteCmd:
PROCEDURE [Word:
CARDINAL] = { WriteWord[Word] };
WriteWord:
PROCEDURE [Word:
CARDINAL] =
BEGIN
word^ ← Word;
TRUSTED {mebesLayerFile.UnsafePutBlock[[LOOPHOLE[word], 0, Basics.bytesPerWord*SIZE[CARDINAL]]]};
END;
WriteHeaderRecord:
PROCEDURE [
PatternName, PatternDate, PatternMask: Rope.ROPE,
PatternSizeX, PatternSizeY: CARDINAL, MebesUnitsPerMicron: CARDINAL] =
This writes the "START DRAWING" record of the layer file.
This record contains information such as the size in address
units, the Date, etc
BEGIN
stripeHeight: INT = 256; -- in EBES units
maxStripes: INT = 255;
maskHeight: INT = maxStripes*stripeHeight;
maskWidth: INT = 32768;
Date:
TYPE =
PACKED
ARRAY [0..6)
OF
CHAR ←
ALL[' ];
month [01..12], day [01..31], year [00..99]
FileName:
TYPE =
PACKED
ARRAY [0..12)
OF
CHAR ←
ALL[' ];
[9] must be '. , [10] is column ['A..'Z], [11] is row ['A..'Z]
StartDrawing:
TYPE =
MACHINE
DEPENDENT
RECORD [
nFields (0: 0..7): [0..256) ← 2,
addressCode (0: 8..15): [0..6],
cx (1): CARDINAL[0..maskWidth], -- 0 is illegal
cy (2): CARDINAL[0..maskHeight], -- 0 is illegal
moDayYr (3): Date,
field1Size (6): CARDINAL ← 6,
patternFileName (7): FileName,
field2Size (13): CARDINAL ← 2,
maskInfo (14): PACKED ARRAY [0..4) OF CHAR ← ALL[' ]
];
startDrawing:
REF StartDrawing ←
NEW[StartDrawing ← [
addressCode: MebesUnitsPerMicron/2*3,
cx: PatternSizeX,
cy: PatternSizeY
]];
FOR i: [0..6)
IN [0..6)
DO
startDrawing.moDayYr[i] ← Rope.Fetch[PatternDate, i]
ENDLOOP;
FOR i: [0..12)
IN [0..12)
DO
startDrawing.patternFileName[i] ← Rope.Fetch[PatternName, i]
ENDLOOP;
FOR i: [0..4)
IN [0..4)
DO
startDrawing.maskInfo[i] ← Rope.Fetch[PatternMask, i]
ENDLOOP;
TRUSTED {mebesLayerFile.UnsafePutBlock[[LOOPHOLE[startDrawing], 0, Basics.bytesPerWord*SIZE[StartDrawing]]]};
END;
object: REF TEXT ← NEW[TEXT[50]];
WriteStripe:
PROCEDURE [Stripe: PartitionDefs.stripeNumber, Layer: PartitionDefs.layerNumber] =
This copies one stripe from the partition file to the output file.
BEGIN
s: IO.STREAM ← PartitionDefs.ReadPartitionCreate[Stripe, Layer];
objectNumber: INT ← 0;
IF s=NIL THEN RETURN;
WriteCmd[StartStripe + 256*(Stripe + 1)]; -- Write out stripe header
DO
-- Loop reading and writing objects
[] ← PartitionDefs.ReadObject[s, object ! IO.EndOfStream => EXIT];
mebesLayerFile.PutBlock[object];
objectNumber ← objectNumber+1;
IF objectNumber
MOD 1000 = 0
THEN
IODefs.PostIt[IO.PutFR["Writing object %g of stripe %g on layer file...", IO.int[objectNumber], IO.int[Stripe]]];
ENDLOOP;
WriteCmd[EndStripe]; -- Write end of stripe
END;
mebesLayerFile: IO.STREAM ← NIL;
MakeLayerFile:
PUBLIC
PROCEDURE [
DiskFileName: Rope.ROPE, Layer: PartitionDefs.layerNumber, PatternName,
PatternDate, PatternMask: Rope.ROPE,
PatternSizeX, PatternSizeY: CARDINAL, MebesUnitsPerMicron: CARDINAL] =
BEGIN
Stripe: PartitionDefs.stripeNumber;
mebesLayerFile ← EBESOpen[FS.StreamOpen[fileName: DiskFileName, accessOptions: $create]];
WriteHeaderRecord[
PatternName, PatternDate, PatternMask, PatternSizeX, PatternSizeY,
MebesUnitsPerMicron];
FOR Stripe IN PartitionDefs.stripeNumber DO WriteStripe[Stripe, Layer]; ENDLOOP;
WriteCmd[EndDrawing];
mebesLayerFile.Close[];
mebesLayerFile ← NIL;
END;
END.