-- File: PressNetListener.mesa: Routines for getting for a file at a printing server.
-- GetBits is called by Press.mesa
-- Last Edited: December 10, 1981 4:24 PM By: GWilliams
-- In InitTfsBuffer, was loading vda of 2nd page of bits file with firstVda.
DIRECTORY
AltoDefs USING [BytesPerWord, PageSize],
AltoRam USING [CantFindFile, FileLooksCrufty],
EFTPDefs USING [EFTPAbortReceiving, EFTPAlreadyReceiving, EFTPEndReceiving, EFTPFinishReceiving, EFTPGetBlock, EFTPNotReceiving, EFTPOpenForReceiving, EFTPTimeOut, EFTPTroubleReceiving],
IODefs USING[CR, SP, WriteChar, WriteDecimal, WriteOctal, WriteLine, WriteString],
InlineDefs USING [BITOR, BITSHIFT, COPY],--COPY[from, nwords, to]
MiscDefs USING[CallDebugger, Zero],
PressDefs USING [PageG, PressPassword, RamBoot, uCodeLoaded],
PressNetDefs USING [attributesCode, imageCode, PageAttributes],
PupDefs USING [GetPupAddress, PupPackageDestroy, PupPackageMake],
PupStream USING [AppendPupAddress],
PupTypes USING[PupAddress, PupSocketID],
SegmentDefs USING[DataSegmentHandle, DefaultBase, DeleteDataSegment, NewDataSegment, SegmentAddress],
TridentDefs USING [BadErrorRtn, dcReadLD, dcWriteD, ddMgrPtr, DefaultTfsCleanupRtn, DefaultTfsErrorRtn, eofDA, fillInDA, FP, PAGE, TfsActOnPages, TfsCloseDisk, TfsDestroyDDMgr, tfsdskPtr, TfsInit, TfsOpenFile, TFSwordsPerPage];
PressNetListener: PROGRAM
IMPORTS AltoRam, EFTPDefs, IODefs, InlineDefs, MiscDefs, PressDefs, PupDefs, PupStream, SegmentDefs, TridentDefs
EXPORTS PressNetDefs =
BEGIN OPEN AltoDefs, AltoRam, EFTPDefs, IODefs, InlineDefs, MiscDefs, PressDefs, PressNetDefs, PupDefs, PupStream, PupTypes, SegmentDefs, TridentDefs;
EndReason: TYPE = {alreadyOpen, cantFindFile, doneReason, eftpError, emptyBuffReason, errorNotReceiving, errorTroubleReceiving, hitEOF, illegalReason, noTrident, tridentError, dANotFilled};
TerminationReason: TYPE = {errorTermination, fileDoneTermination, pageDoneTermination, nullTerminationReason};
--Press Stuff
bandWidth: CARDINAL = 16;
FirstPage: TYPE = MACHINE DEPENDENT RECORD
[nPages: CARDINAL ← 1,
pageGSize: CARDINAL ← SIZE[PageG],
printerMode: CARDINAL,--3=portrait, 8=Landscape
password: CARDINAL ← PressPassword,
pageGs: ARRAY[0..92) OF PageG--enough to fit into a Trident Page
];
scanSeg: DataSegmentHandle ← NIL;
scanLength: CARDINAL;
wordAddrInTfsBuffer: CARDINAL;
scanInBand: CARDINAL;
--net stuff
connectionOpen: BOOLEAN ← FALSE;
gotAJob: BOOLEAN ← FALSE;
hostAddress: PupAddress;
pupPtr: POINTER TO PupAddress ← @hostAddress;
senderAddress: PupAddress;
pupPkgExtant: BOOLEAN ← FALSE;
--Tfs stuff
disk: tfsdskPtr ← NIL;
bufferWordLen: CARDINAL = TFSwordsPerPage;
bufferByteLen: CARDINAL = BytesPerWord*bufferWordLen;
pagesLength: CARDINAL = 4;
firstVda: CARDINAL ← 0;--allways holds page 1 of the file
fp: FP;--fp gets filled in by TfsOpenFile
filePtr: POINTER TO FP ← @fp;
tfsSeg: DataSegmentHandle ← NIL;
tfsBuff: POINTER TO ARRAY[0..TFSwordsPerPage) OF CARDINAL;
pages: ARRAY[0..pagesLength] OF PAGE;
dAsLength: CARDINAL;
dAsBase: POINTER;--this is modified after ea call on TfsActOnPages.
pageNum: CARDINAL;
--Debugging Switches
fileLengthReport: BOOLEAN ← TRUE;--print out length of received file in pages
dasMonitor: BOOLEAN ← FALSE;--for debugging tfs file handler.
debuggerIfTfsError: BOOLEAN ← TRUE;
checkTermination: BOOLEAN ← TRUE;
--Signals & Errors
CommErr: TYPE = {alreadyHaveJob, nullComErr, endReceiving, noisyChannel, protocolError, illegalEnd, notReceiving, alreadyReceiving};
errorComm: ERROR[e: CommErr, wordsTransferred: CARDINAL ← 0, s: STRING ← NIL] = CODE;
errorTfs: ERROR[e: EndReason] = CODE;
GetBits: PUBLIC PROC[] RETURNS[okToProceed: BOOLEAN ← FALSE]=
--Raises no signals or errors
BEGIN
pa: PageAttributes ← [0, 0, 0, 0];
endReason: EndReason ← illegalReason;
inCoreAddress: POINTER TO ARRAY OF WORD;
receivedFile: BOOLEAN ← FALSE;
scanLineLength: CARDINAL;--copy of scanLength
wordsInBuff: CARDINAL;
BEGIN
IF ~FirstPageCheck[] THEN RETURN[FALSE];
WHILE ~receivedFile
DO
OpenPressBits[filePtr! errorTfs => {SELECT e FROM noTrident => WriteLine["Trident not up"L];
cantFindFile => WriteLine["Can’t find Press.bits"L];
ENDCASE; GOTO getOut}];
pa ← GetAJob[! errorComm => IF e = alreadyReceiving THEN {PupPackageDestroy[]; GOTO getOut}];
inCoreAddress ← InitScanBuffer[pa];--get enough space for a scan line, it may be more than 1K
InitTfsBuffer[];
scanLineLength ← scanLength;--scan Length is valid now.
BEGIN ENABLE BEGIN
errorComm =>
{SELECT e FROM
noisyChannel => {WriteLine["Noisy Channel, aborting transfer"L];
EFTPAbortReceiving["Channel too noisy, aborting transfer"L!
EFTPNotReceiving => CONTINUE]};
endReceiving => WriteLine["Transfer aborted, not enough data received"L];
ENDCASE;
GOTO incompleteXFer};
errorTfs => SELECT e FROM tridentError, hitEOF, dANotFilled => {endReason ← e; GOTO done}; ENDCASE;
END;--of catch series
FOR iii: CARDINAL IN [0..pa.lastScan-pa.firstScan]
DO
wordsInBuff ← GetBuffer[inCoreAddress, 1];--check header word
IF inCoreAddress[0] # imageCode THEN
{WriteLine["Buffer doesn’t contain image data"L]; GOTO incompleteXFer};
wordsInBuff ← GetBuffer[inCoreAddress, scanLineLength];--get scan line
IF wordsInBuff = 0 THEN {endReason ← emptyBuffReason; GOTO done};--blow up
StoreScanLine[inCoreAddress];--buffers data and writes to disk.
ENDLOOP;
EXITS
incompleteXFer =>
{IF checkTermination THEN
CallDebugger["File transfer trouble"];
[]←TfsCloseDisk[disk, FALSE];
ReleaseScanBuffer[TRUE, inCoreAddress, pa];
ReleaseTfsBuffer[];
CloseServerConnection[];
LOOP};--restart @ WHILE ~ receivedFile
END;
--transfer completed, now write firstPage
ReleaseScanBuffer[FALSE, inCoreAddress, pa];--write out blank scan lines if last band is not full & free storage
WritePageGPage[pa!--get out if error
errorTfs => IF (e = tridentError)
THEN {WriteLine["Transfer Complete, but"L]; endReason ← tridentError; GOTO done}];
ReleaseTfsBuffer[];
disk←LOOPHOLE[TfsCloseDisk[disk, FALSE]];
CloseServerConnection[];
receivedFile ← TRUE;
ENDLOOP;
okToProceed ← TRUE;
EXITS
getOut=> NULL;
done=>
{
ReleaseScanBuffer[FALSE, inCoreAddress, pa];--write out blank scan lines if last band is not full & free storage
ReleaseTfsBuffer[];
CloseServerConnection[];
SELECT endReason FROM
emptyBuffReason=>WriteLine["Empty Page: error!"L];
illegalReason =>WriteLine["illegal End."L];
tridentError =>{WriteLine["Trident error"L];
EFTPAbortReceiving["Trident error"L];};
hitEOF => {WriteLine["Ran into EOF on write"L];
EFTPAbortReceiving["Trident ran into EOF on file write"L];};
dANotFilled =>{WriteLine["Trident software trouble -- bad DA multiple times"L];
EFTPAbortReceiving["Trident software trouble -- bad DA"L];};
ENDCASE;
SELECT endReason FROM
tridentError => NULL;
emptyBuffReason, hitEOF, dANotFilled => disk ← LOOPHOLE[TfsCloseDisk[disk, FALSE]];
ENDCASE;
};
END;
IF checkTermination THEN
IF ~okToProceed THEN CallDebugger["Exiting with error from GetBits"L];
END;--of GetBits
GetAJob: PROC[] RETURNS [pa: PageAttributes]=
{typedMessage: BOOLEAN ← FALSE;
getAJobEndReason: EndReason ← illegalReason;
code: CARDINAL;
wordsReturned: CARDINAL;
pupAddressString: STRING ← [30];
IF gotAJob THEN ERROR errorComm [alreadyHaveJob, , ];
WHILE ~gotAJob DO
IF ~connectionOpen THEN
{IF ~pupPkgExtant THEN
{PupPackageMake[];
pupPkgExtant ← TRUE;
GetPupAddress[pupPtr, "ME"];
--don’t use the normal socket for debugging!
pupPtr.socket ← PupSocketID[1, 25B];--[0, 20B] is the normal printer socket
};
senderAddress ← EFTPOpenForReceiving[pupPtr↑!
EFTPTimeOut =>
{IF ~typedMessage
THEN {WriteLine["Listening for print request."]; typedMessage ← TRUE;};
RESUME};
EFTPAlreadyReceiving =>
{WriteLine["Connection Already Open!"L];
ERROR errorComm[alreadyReceiving, 0, NIL]};
];
connectionOpen ← TRUE;
};
WriteString["Connection open to "L];
AppendPupAddress[pupAddressString, senderAddress];
WriteLine[pupAddressString];
typedMessage ← FALSE;
[wordsReturned] ← GetBuffer[@code, 1!
errorComm =>
SELECT e FROM
noisyChannel, protocolError, endReceiving =>
{EFTPFinishReceiving[!
EFTPNotReceiving => CONTINUE];
connectionOpen ← FALSE; LOOP;};
ENDCASE
];--get code to see if it is a Page Attributes code
IF code # attributesCode THEN
{EFTPAbortReceiving["I Expect Page Attributes first"];
WriteLine["Connection Refused, protocol error."L];
typedMessage ← connectionOpen ← FALSE; LOOP};--get rid of this customer & type init message
wordsReturned ← GetBuffer[@pa, SIZE[PageAttributes]!
errorComm =>
SELECT e FROM
noisyChannel, protocolError, endReceiving => LOOP;
ENDCASE
];
gotAJob ← TRUE;
ENDLOOP;
};--GetAJob
FirstPageCheck: PROC [] RETURNS[goAhead: BOOLEAN ← TRUE]=
{IF SIZE[FirstPage] > TFSwordsPerPage THEN
{WriteLine["First page description exceeds Trident Page Length"];
RETURN[FALSE]};
};--FirstPageCheck
GetBuffer: PROC[buffer: POINTER, len: CARDINAL] RETURNS [wordsInBufCt: CARDINAL ← 0]=
--copy from net Stream to buffer len amount of words
BEGIN
blockByteLen, bytesToGet: CARDINAL ← 0;
bufferEnd: POINTER ← buffer + len;--actually is first word past buffer
bufferPos: POINTER ← buffer;
getABuffEndReason: EndReason ← illegalReason;
BEGIN
UNTIL bufferPos = bufferEnd
DO
bytesToGet ← (bufferEnd - bufferPos) + (bufferEnd - bufferPos);--remember, bufferEnd is one past end of buffer
blockByteLen ← 0;
blockByteLen ← EFTPGetBlock[bufferPos, bytesToGet!
EFTPNotReceiving => {getABuffEndReason ← errorNotReceiving; GOTO done;};
EFTPEndReceiving => {getABuffEndReason ← doneReason; GOTO done;};
EFTPTroubleReceiving => {getABuffEndReason ← errorTroubleReceiving; GOTO done;};
EFTPTimeOut => RETRY];
bufferPos ← bufferPos + blockByteLen/2;
wordsInBufCt ← wordsInBufCt + BITSHIFT[blockByteLen, -1];--divide by bytes/word
ENDLOOP;
EXITS
done=>
{CloseServerConnection[];
wordsInBufCt ← wordsInBufCt + blockByteLen;
SELECT getABuffEndReason FROM
doneReason =>ERROR errorComm[endReceiving, wordsInBufCt, NIL];--not necessarily an error
errorTroubleReceiving =>ERROR errorComm[noisyChannel, wordsInBufCt, NIL];
errorNotReceiving =>ERROR errorComm[notReceiving, 0, NIL];
illegalReason =>ERROR errorComm[illegalEnd, wordsInBufCt, NIL];
ENDCASE;
};
END;
END;--of GetBuffer
StoreScanLine: PROC [p: POINTER]=
--Put scan line into Press.bits. Breaks scan line up if it overflows a Trident Page. Also pads the band out to 1K boundary.
--Now, if we overflow the Tfsbuffer, we automatically write out the full page and add remainder of scan to newly emptied buffer. If that was the last scan line of the buffer, we write out the partial page regardless whether we just flushed the full buffer since we’re padding the trident page at the end of a band. Hence the test for scanInBand at end.
{wordsLeft: CARDINAL;
wordsLeft ← (TFSwordsPerPage-wordAddrInTfsBuffer);
COPY[p, MIN[wordsLeft, scanLength], tfsBuff + wordAddrInTfsBuffer];
IF wordsLeft < scanLength--wordsLeft can be zero
THEN
{WriteTfsPage[];
COPY[p+wordsLeft, wordAddrInTfsBuffer ← (scanLength-wordsLeft), tfsBuff];
}
ELSE wordAddrInTfsBuffer ← wordAddrInTfsBuffer + scanLength;--can = TFSwordsPerPage
IF (scanInBand ← scanInBand + 1) = bandWidth THEN
{WriteTfsPage[];
--reset wordAddrInTfsBuffer to 0 to avoid an empty page next go around
wordAddrInTfsBuffer ← 0;
scanInBand ← 0;
};
};--StoreScanLine
WriteTfsPage: PROC[]=
{endReason: EndReason ← illegalReason;
loopCtr: CARDINAL;--this detects infinite loops in GetBits
maxTries: CARDINAL = 3;
nmChars: CARDINAL ← BytesPerWord*TFSwordsPerPage;
dAs: DESCRIPTOR FOR ARRAY OF PAGE ← DESCRIPTOR[dAsBase, dAsLength];
BEGIN
IF (dAs[pageNum] ← dAs[pageNum+1]) = eofDA
THEN{endReason ← hitEOF; GOTO done;};--by now the vda of the next page to write is in
IF (dAs[pageNum] = fillInDA)
THEN--the vda is not valid
IF debuggerIfTfsError
THEN CallDebugger["disk address is fillInDA"L]
ELSE{endReason ← dANotFilled; GOTO done};
dAs[pageNum+1] ← fillInDA;--reset the to-be-pagenum+1 vda
dAsLength ← dAsLength + 1;--extend range of descriptor from new base
dAsBase ← dAsBase - 1;--must reset base because the low-level disk routines write pageNum onto
pageNum ← pageNum + 1;-- the disk label; and the vda is accessed from dAs using pageNum!
dAs ← DESCRIPTOR[dAsBase, dAsLength];
--TypeOutStatus[dAs, pageNum, charsInPage, TRUE];----the TRUE means "before ActOnPages"
[]← TfsActOnPages[disk, NIL, dAs, filePtr↑, pageNum, pageNum, dcWriteD, @nmChars, dcWriteD, tfsBuff, DefaultTfsCleanupRtn, DefaultTfsErrorRtn, TRUE, 0!
BadErrorRtn => {endReason ← tridentError; GOTO done;};];
--TypeOutStatus[dAs, pageNum, charsInPage, FALSE];----the FALSE means "after ActOnPages"
loopCtr ← 0;
UNTIL dAs[pageNum+1] # fillInDA
DO--the Default TfsCleanupRtn didn’t fill in the next DA, try again, but don’t write data this time
IF (loopCtr ← loopCtr + 1) > maxTries
THEN
IF debuggerIfTfsError
THENCallDebugger["disk address is fillInDA after some retries"L]
ELSE{endReason ← dANotFilled; GOTO done};
IF dAs[pageNum+1] = eofDA THEN EXIT;
[]←TfsActOnPages[disk, NIL, dAs, filePtr↑, pageNum, pageNum, dcReadLD, @nmChars, dcReadLD, tfsBuff, DefaultTfsCleanupRtn, DefaultTfsErrorRtn, TRUE, 0!
BadErrorRtn => {endReason ← dANotFilled; GOTO done;};];
ENDLOOP;
EXITS
done=>
SELECT endReason FROM
illegalReason =>WriteLine["illegal End."L];
tridentError, hitEOF, dANotFilled =>errorTfs[endReason];
ENDCASE;
END;
};--WriteTfsPage
InitTrident: PROC[]=
BEGIN
--load microcode
IF ~uCodeLoaded THEN
{RamBoot["MesaSlotMc.br"! CantFindFile => GOTO noUcode;
FileLooksCrufty =>GOTO badUcode];
uCodeLoaded ← TRUE;};
IF disk # NIL THEN disk ← LOOPHOLE[TfsCloseDisk[disk, FALSE]];
disk ← TfsInit[TRUE,,,];--initmode=TRUE, drive, ddMgr, freshDisk=FALSE
EXITS
noUcode => WriteLine["Can’t find file MesaSlotMc.br."L];
badUcode => WriteLine["Microcode file ""MesaSlotMc.br"" is malformed."L];
END;--of InitTrident
InitTfsBuffer: PROC[]=
{IF tfsSeg # NIL THEN DeleteDataSegment[tfsSeg];
tfsSeg ← NewDataSegment[DefaultBase, (TFSwordsPerPage + PageSize-1)/PageSize];
tfsBuff ← SegmentAddress[tfsSeg];
pages ← [fillInDA, fillInDA, fillInDA, fillInDA, fillInDA];
dAsLength ← pagesLength;--this varies with the bits file writing
--in next line, we are assuming that Press.bits is contiguous!!!!
pages[2] ← firstVda + 1;--this will be accessed as dAs[pageNum+1] to set up dAs[pageNum]
dAsBase ← @pages[0];
pageNum ← 1;--this gets incremented before using
};--InitTfsBuffer
ReleaseTfsBuffer: PROC[]=
{DeleteDataSegment[tfsSeg];
tfsSeg ← NIL;
};--ReleaseTfsBuffer
InitScanBuffer: PROC[pa: PageAttributes] RETURNS [coreAddress: POINTER]=
{padding: CARDINAL;
IF scanSeg # NIL THEN DeleteDataSegment[scanSeg];
scanSeg ← NewDataSegment[DefaultBase, (pa.bitWc + PageSize-1)/PageSize];
coreAddress ← SegmentAddress[scanSeg];
scanInBand ← wordAddrInTfsBuffer ← 0;--init the scan line # we’re on
scanLength ← pa.bitWc;
--will never need more than bandWidth scans
IF (padding ← pa.firstScan MOD bandWidth) > 0 THEN
{Zero[coreAddress, pa.bitWc];
FOR i: CARDINAL IN [0..padding)
DO StoreScanLine[coreAddress]; ENDLOOP;
};
};--InitScanBuffer
ReleaseScanBuffer: PROC[aborting: BOOLEAN ← FALSE, address: POINTER, pa: PageAttributes]=
--Pads the first and last bands with blank scan lines if, for instance, firstScan is not = to a (multiple of bandWidth + 1)
{padding: CARDINAL;
IF ~aborting THEN
{padding ← pa.lastScan MOD bandWidth;
IF padding # bandWidth-1 THEN
{Zero[address, pa.bitWc];
FOR i: CARDINAL IN [1..bandWidth-padding)--output bandWidth-padding-1 lines
DOStoreScanLine[address];
ENDLOOP};};
DeleteDataSegment[scanSeg];
scanSeg ← NIL;
};--ReleaseScanBuffer
WritePageGPage: PROC[pa: PageAttributes]=
--can raise errorTfs[tridentError]
{pageBuf: ARRAY[0..TFSwordsPerPage) OF WORD; --Plug in PageG info and write this buffer to disk
firstPage: POINTER TO FirstPage ← LOOPHOLE[@pageBuf[0]];
nmChars: CARDINAL ← BytesPerWord*TFSwordsPerPage;
dAs: DESCRIPTOR FOR ARRAY OF PAGE ← DESCRIPTOR[@pages[1], dAsLength];
dAs[1] ← firstVda;
Zero [@pageBuf[0], TFSwordsPerPage];
firstPage.nPages ← 1;
firstPage.pageGSize ← SIZE[PageG];
firstPage.printerMode ← 8;
firstPage.password ← PressPassword;
firstPage.pageGs[0].FirstBand ← pa.firstScan/bandWidth;
firstPage.pageGs[0].LastBand ← pa.lastScan/bandWidth;
firstPage.pageGs[0].BitMargin ← pa.margin;
firstPage.pageGs[0].BitWc ← pa.bitWc;
firstPage.pageGs[0].BitPage ← 1;--i.e., first page after the firstPge
firstPage.pageGs[0].PageNumber ← 1;--i.e., from first page of Press file
[]← TfsActOnPages[disk, NIL, dAs, filePtr↑, 1, 1, dcWriteD, @nmChars, dcWriteD, @pageBuf[0], DefaultTfsCleanupRtn, DefaultTfsErrorRtn, TRUE, 0!
BadErrorRtn => GOTO done];
EXITS
done => errorTfs[tridentError];
};--WritePageGPage
OpenPressBits: PROC[filePtr: POINTER TO FP]=
{ddMgr: ddMgrPtr;
fileSys: CARDINAL ← 1;--TP0:sys 1
InitTrident[];--loads disk object
IF disk = NIL THEN ERROR errorTfs[noTrident];
[, firstVda,] ← TfsOpenFile[disk, "Press.bits.", read, filePtr];--must fool Open with read. Only other option is create.
IF firstVda=0 AND disk.tfskd.model = 80 THEN --"not found" if not on 1st file system.
{disk←LOOPHOLE[TfsCloseDisk[disk, FALSE]];
ERROR errorTfs[cantFindFile];};
ddMgr ← disk.tfskd.ddMgr;
WHILE firstVda = 0 AND fileSys < 23 --check all filesystems on a T300
DO--drives 0-7 and 3 filesystems/drive
IF disk # NIL THEN
disk←LOOPHOLE[TfsCloseDisk[disk, TRUE]];--keep ddMgr, and make disk NIL
disk ← TfsInit[TRUE, BITOR[BITSHIFT[(fileSys MOD 3), 8], (fileSys/3)], ddMgr,];
fileSys ← fileSys + 1;
IF disk = NIL THEN LOOP;
[, firstVda, ] ← TfsOpenFile[disk, "Press.bits.", read, filePtr];
ENDLOOP;
IF firstVda = 0 THEN
{TfsDestroyDDMgr[ddMgr];--get here only when not found on T300
ERROR errorTfs[cantFindFile];
};
pageNum ← 2;
};--OpenPressBits
CloseServerConnection: PROC[]=
{
IF ~gotAJob THEN GOTO done;
EFTPFinishReceiving[!
EFTPNotReceiving => CONTINUE];--acknowledge to sender.
PupPackageDestroy[];
gotAJob ← pupPkgExtant ← connectionOpen ← FALSE;
EXITS
done => NULL;
};--CloseServerConnection
TypeOutStatus: PROC[dAs: DESCRIPTOR FOR ARRAY OF PAGE, pageNum, charsInPage: CARDINAL, beforeActOnPages: BOOLEAN ← TRUE]=
{--for debugging
i: CARDINAL;--debugging variable
IF ~dasMonitor THEN RETURN;
IF beforeActOnPages
THEN WriteLine["Before ActOnPages"L]
ELSE WriteLine["After ActOnPages"L];
WriteString["page number: "L];
WriteDecimal[pageNum]; WriteChar[CR];
IF beforeActOnPages
THEN {WriteString["Before ActOnPages -- chars received from GetAPage: "L];
WriteDecimal[charsInPage]; WriteChar[CR];};
WriteLine["dAs[0]..dAs[dAsLength] (length changes with page#)"];
FOR i IN [0..dAsLength) DO
WriteOctal[dAs[i]]; WriteChar[SP]; WriteChar [SP]; ENDLOOP;
WriteChar[CR]; WriteChar[CR];
};--TypeOutStatus
--initialization (for debugging only)
--filePtr ← @fp; Use this if Mesa doesn’t allow startup assignment
END. -- PressNetListener.mesa
-- Last Edited: October 27, 1981 4:35 PM By: GWilliams
-- added code to try for the next vda again if not filled by TfsActOnPages the first -- Last Edited: October 27, 1981 3:12 PM By: GWilliams
-- added debuggerIfTfsError
-- Last Edited: October 26, 1981 2:38 PM By: GWilliams
-- added check that filled-in DA is valid at GetBits & added EFTPFinishReceiving.
-- Last Edited: October 26, 1981 10:54 AM By: GWilliams
--added fileLengthReport
-- Last Edited: October 27, 1981 5:17 PM By: GWilliams
-- put check at end of GetBits to stop if not continuing
-- Last Edited: November 24, 1981 3:04 PM By: GWilliams
-- In middle of revamping to accept bits on a scan line basis rather than read a whole Press.bits file.
-- Last Edited: December 2, 1981 11:16 AM By: GWilliams
-- Back again - - took time out to help Starkweather & to write Performance appraisal.
-- Last Edited: December 8, 1981 6:03 PM By: GWilliams
-- Back again - - Press.fonts broke, now debugging.
-- Last Edited: December 9, 1981 4:38 PM By: GWilliams
-- Fixing OpenPressBits for when can’t find Press.bits on T300.