WriteByte:
PROC [file: File, b:
BYTE] ~ {
Write a byte into file and then update file checksum.
block: REF TEXT ← file.block;
IF block.length>=block.maxLength THEN ERROR; -- buffer overflowed
block[block.length] ← VAL[b];
block.length ← block.length+1;
file.ckSum ← Basics.BITAND[file.ckSum+b, 000FFH];
};
WriteRope:
PROC [file: File, r: Rope.
ROPE, length:
NAT] ~ {
EachChar: Rope.ActionType ~ { WriteByte[file, ORD[c]] };
[] ← Rope.Map[base: r, action: EachChar, start: 0, len: MIN[length, Rope.Length[r]]];
FOR i: INT IN [Rope.Length[r] .. length) DO WriteByte[file, 00H] ENDLOOP;
};
WritePin:
PROC [file: File, pin: Pin] ~ {
length: INT = Rope.Length[pin.name];
WriteByte[file, (IF pin.notConnected THEN 0FFH ELSE 00H)];
WriteByte[file, pin.group];
WriteByte[file, pin.pinNum];
WriteByte[file, (IF pin.hasPullup THEN 0FFH ELSE 00H)];
WriteCard[file, length];
WriteRope[file, pin.name, length];
};
WriteHeader:
PROC [file: File] ~ {
Write header. It is assumed that file.block is empty at this point. The file pointer is moved to the end of the header
headerSize: CARD32 ← 256; -- an upper bound on the fixed part of the header size
ckSumOffset: INT; -- this is where the checksum will go once completed...
endOfBlockOffset: INT; -- this is where the header ends
ckSumByte: BYTE;
IF file.block.length#0 THEN ERROR; -- block has not been flushed
IO.SetIndex[file.stream, 0]; -- backup to start of file
FOR p:
LIST
OF Pin ← file.pins, p.rest
UNTIL p=
NIL
DO
headerSize ← headerSize+PinRepLength[p.first]; -- for extra pin fields
ENDLOOP;
headerSize ← 1024*((MAX[headerSize+1, testFileHeaderSize]+1023)/1024); -- round up to 1K
WriteRope[file, headerSignature, 8];
WriteCard[file, headerSize];
WriteCard[file, file.nGroups];
WriteCard[file, vectorBlockLength];
WriteCard[file, file.nVects];
ckSumOffset ← file.block.length; -- note down where checksum should go finally
WriteByte[file, 00H]; -- this is the checksum position, patched at end
WriteRope[file, file.id, 120];
FOR p: LIST OF Pin ← file.pins, p.rest UNTIL p=NIL DO WritePin[file, p.first] ENDLOOP;
WriteByte[file, 080H]; -- end of pin list indicator
FlushBlock[file, headerSize];
ckSumByte ← Basics.BITAND[0100H-file.ckSum, 000FFH]; -- recompute checksum for total 0
endOfBlockOffset ← IO.GetIndex[file.stream];
IO.SetIndex[file.stream, ckSumOffset]; -- get back to where the checksum should be
IO.PutByte[file.stream, ckSumByte]; -- and write it
IO.SetIndex[file.stream, endOfBlockOffset]; -- get back to end of header
};
FlushBlock:
PROC [file: File, nBytes:
NAT] ~ {
Flush current block padded to nBytes with zeroes.
block: REF TEXT ← file.block;
IF block.length>nBytes THEN ERROR; -- internal bug
UNTIL block.length=nBytes DO WriteByte[file, 00H] ENDLOOP;
IO.PutBlock[file.stream, block, 0, nBytes];
block.length ← 0;
};