LayerFile.mesa
Updated: November 17, 1979 2:27 AM
Last Edited by: McCreight, January 31, 1985 3:08:00 pm PST
DIRECTORY
Basics,
FS,
IO,
IODefs,
LayerFileDefs,
PartitionDefs,
Rope;
LayerFile: CEDAR PROGRAM IMPORTS FS, IO, IODefs, PartitionDefs, Rope EXPORTS LayerFileDefs
=
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: BOOLTRUE ] 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: BOOLFALSE ] =
BEGIN
state: EBESStreamStateRef = NARROW[self.streamData];
self.Flush[];
state.dest.Close[];
END;
word: REF CARDINALNEW[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 CHARALL[' ];
month [01..12], day [01..31], year [00..99]
FileName: TYPE = PACKED ARRAY [0..12) OF CHARALL[' ];
[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 CHARALL[' ]
];
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 TEXTNEW[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.STREAMNIL;
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.