Trailing-Edge
-
PDP-10 Archives
-
-
There are no other files named in the archive.
!
Copyright (c) 1977 by Pentti Kanerva
All rights reserved
;
!****** SEGMENT FINISH ******
*******************************;
FORWARD SUBROUTINE textInit;
FORWARD SUBROUTINE dpyWindow;
FORWARD SUBROUTINE goToPlace (INTEGER pg, ln, bt);
FORWARD STRING SUBROUTINE getTop;
FORWARD STRING SUBROUTINE getBot;
FORWARD SUBROUTINE putTop (STRING line);
FORWARD SUBROUTINE putBot (STRING line);
FORWARD SUBROUTINE read;
FORWARD SUBROUTINE write;
DEFINE fin0 = "finSegment";
FORWARD SUBROUTINE fin1;
FORWARD SUBROUTINE finish (BOOLEAN abortSw);
SUBROUTINE finSegment;
! ----------
Write text buffer first, don't touch window buffer.
To reduce wasted space, write subsequent read pages as long
as they fit on current write page.
To eliminate null bytes inside a line (FAIL fails on them),
move last partial line to bottom of write page (FIXEOP).
Finish read and write pages.
Move read segment from end of write segment to hold chain.
;
IF segment > 1 THEN
BEGIN "finSegment"
SUBROUTINE fixEOP;
! ------
Move last partial line to end of file page to prevent lines
with null butes inside them.
;
START!CODE "fixEOP" LABEL loop, put, nxt, xit;
DEFINE n# = "2", ch# = "3", zro# = "4", gp# = "5", pp# = "6";
movei n#, '5000;
sub n#, n.output; ! # text bytes on page;
! IF 0 < N.CH < '5000..;
caile n#, 0;
cail n#, '5000;
jrst xit;
! ..THEN move last line to bottom of file page;
setz zro#, ;
move pp#, ['010700000777 + oBuf];
move gp#, p.output;
loop: ldb ch#, gp#;
trne ch#, LNOT (LF LOR FF);
jrst put;
caie ch#, LF;
cain ch#, FF;
jrst xit; ! LF or FF terminates transfer;
jumpe ch#, nxt; ! Ignor null bytes;
put: dpb ch#, pp#;
DECBP (pp#);
nxt: dpb zro#, gp#;
DECBP (gp#);
sojg n#, loop;
xit:
END "fixEOP"
;
! + + + + ;
inc (saving); ! Prevent PMAPOUT from calling FINCONTINUE;
IF readOnly THEN finRdPage
ELSE
BEGIN
! Write all of TEXT array;
WHILE bot NEQ free DO putTop (getBot);
WHILE top NEQ gap DO write;
DO
BEGIN "pack" INTEGER pg;
! Output rest of input page;
START!CODE acDef;
push sp, n.input;
push sp, p.input;
pushj p, pMapOUT; ! PMAPOUT (INPUTSTRING);
setzm n.input; ! N.INPUT _ 0;
END
;
! Transfer next input page to current output page if fits;
IF (pg _ rightOf (rdPage)) < 0 THEN eof _ TRUE
ELSE
BEGIN
dirEntry (pg); ! Make sure dir entry exists;
IF nCh.(pg) > n.output THEN DONE; ! Does not fit;
turnRdPage;
END
;
END "pack" UNTIL eof
;
! Null byte prevention:
Guard against partially filled pages with no line breaks, but also
don't copy rest of file in case of small overflow;
IF failFile THEN
BEGIN "fix"
IF NOT n.lfOut AND NOT n.ffOut AND NOT eof THEN
BEGIN
DO pMapOUT (pMapINPUT)
UNTIL n.lfOut OR n.ffOut OR eof
;
IF n.input > 0 THEN ! Finish the page that we borrowed from;
BEGIN
turnWrPage;
START!CODE acDef;
push sp, n.input;
push sp, p.input;
pushj p, pMapOUT; ! PMAPOUT (INPUTSTRING);
setzm n.input; ! N.INPUT _ 0;
END
;
END
;
END
;
! Finish for input and output pages;
IF rightOf (rdPage) GEQ 0 THEN fixEOP;
END "fix"
;
finRdPage; finWrPage;
! Move read segment to beg. of hold;
movePStr (wrPage, rdPage, holdP0); secure (linkPage);
END
;
textInit;
IF iBufMP > (minIBufMP + maxIBufMP) DIV 2 THEN salvage;
dec (saving);
END "finSegment"
;
!****** SEGMENT START ******
******************************;
SUBROUTINE mapPgLn (INTEGER page, line);
! -------
Initialization according to text page and line.
Determines RDPAGE by scanning page directory to accumulate
page and line counts.
Stores LEFT (RDPAGE) in WRPAGE, as required by WRMAP (causes
WRMAP to link FREEP just to the left of RDPAGE).
Does initial read and write mapping.
Side effects: Sets TPAGE, TLINE, WPAGE, WLINE.
;
BEGIN "mapPgLn" INTEGER tP, tL, nlf, lRdP; STRING str;
! TP and TL are the P.L of first complete (top) line of next file page;
segment _ (segment + 1) LAND '377 MAX 2; eof _ FALSE; iCount _ 500;
IF writeMode AND nExtraFree LEQ 0 THEN
BEGIN
warning ("
File is filling up.
CONTINUE, even if this message appears twice, and then
FINISH. (Use $$2F if you want to keep old version for backup).
");
haltPending _ TRUE; ! To abort T-search;
END
;
line _ line - slack; ! Reserve space for backing up;
tPage _ tLine _ tP _ tL _ 1; nlf _ 0;
wrPage _ lRdP _ rdPage _ textP0;
WHILE (tP < page OR (tP = page AND tL < line))
AND (rdPage _ rightOf (rdPage)) GEQ 0 ! EOF?; DO
BEGIN
! Conditional WRPAGE _ LRDP and subsequent RDPAGE _ RIGHTOF
(WRPAGE) guarantee that reading starts from a page with at least
one line break or from BEGINNING of text page 1. The troublesome
spots are beginning and end of file (if first or last file page
contains no line break).;
loadN.xxIn; ! (N.FFIN, N.LFIN, N.CHIN) _ DIR (RDPAGE);
IF n.lfIn OR n.ffIn THEN
BEGIN
tPage _ tP; tLine _ tL; ! Save P.L before adding;
addFFLF (tP, nlf, n.ffIn, n.lfIn);
tL _ nlf + 2; ! +2 since (split) line thrown away below;
wrPage _ lRdP;
END
;
lRdP _ rdPage;
END
;
rdPage _ rightOf (wrPage); rdMap; ! Can set EOF;
IF writeMode THEN BEGIN wrMap; IF eof THEN putBot(eolStr) END;
! Transfer (tail end of split) line into write page (unless BOF);
IF tPage > 1 OR tLine > 1 THEN
DO
BEGIN
str _ pMapINPUT;
! Don't let page mark slip by;
IF breakChar = FF THEN
BEGIN
backFF; IF empty (str _ most(str)) THEN dec(tLine);
END
;
IF writeMode THEN pMapOUT (str);
END
UNTIL breakChar OR eof
;
wPage _ tPage; wLine _ tLine; starting _ FALSE;
END "mapPgLn"
;
SUBROUTINE mapByte (INTEGER byteP);
! -------
Initial map with a byte pointer as an argument.
Invalid 'BYTEP' opens the edit at EOF.
;
START!CODE "mapByte"
END "mapByte"
;
SUBROUTINE freeHold;
! --------
Move pages from HOLD to SAFE or FREE. Pages of the original
file (WRSEG = 1) are saved, others are freed.
;
BEGIN "freeHold"
salvage;
WHILE inRange (holdP) DO
IF wrSeg.(holdP) = 1 THEN moveP1 (holdP0, safeP0)
ELSE BEGIN moveP1 (holdP0, freeP0); inc (nFree) END
;
END "freeHold"
;
SUBROUTINE finContinue (BOOLEAN doFin1, dotFin);
! -----------
Finish-and-continue. Called by:
(a) PMAPOUT of IOIO when file full (will FIN1 to make space),
(b) GETTOP of TVFIL when top part of text buffer is empty,
(c) PUTBOT of TVFIL when gap full and MAKESGAP fails.
(d) FCOMMAND of TVCOM in response to $$.F (FIN1, DOTFIN true).
DOing FIN1 frees pages from hold.
For DOTF don't mark place with page marks (we are not in the
midst of a window shuffle).
Sets user word of FDP to GPAGE, GLINE (for crash recovery).
A gap of positive length is guaranteed (for PUTBOT).
WARNING: This is most delicate subroutine for it can be called
while window shuffle is in progress. It is imperative
that before FIN0/1 we put to top text only (to prevent
recursive call of FINCONTINUE).
;
BEGIN "finContinue" INTEGER gP, gL, y; BOOLEAN dotF, wOk;
SUBROUTINE markT1; IF NOT dotF THEN putTop (pageMark);
! ------;
SUBROUTINE markTop; BEGIN markT1; markT1 END;
! -------;
! + + + + ;
inc (saving); ! Semaphore-flag;
wOk _ TRUE;
dpyMessage (IF dotF _ dotFin
THEN ".SAVING.."
ELSE ".WAIT.0..");
! Remember place, save window lines, but leave also in window buffer;
gp _ gPage; gL _ gLine;
IF writeMode THEN
BEGIN
markTop; FOR y _ 1 upto maxY DO putTop (w[y]); markTop;
END
;
IF doFin1 THEN fin1 ELSE fin0; ! --Finish--;
dpb (gP, p.page); dpb (gL, p.line);
! ! changeUSW (rdJfn);
mapPgLn (gP, gL); ! --Restart--;
! Read to where we left off;
IF writeMode AND NOT dotF THEN gL _ zillion;
WHILE (gPage < gP OR (gPage = gP AND gLine < gL)) AND NOT lastWindow
DO putTop (getBot)
;
! Next should come the window lines--make sure;
IF readOnly THEN
BEGIN
IF nonEmpty (w[1]) ! Don't junk if it is $-T;
THEN FOR y _ maxY - 1 downto 1 DO getBot ! Junk;
END
ELSE
BEGIN "wChk" STRING str, wStr;
DEFINE markBot =
! -------;
"BEGIN putBot (pageMark); putBot (pageMark) END";
SUBROUTINE xferStr; putTop (str _ getBot);
! -------;
SUBROUTINE xferMark;
! --------;
IF NOT dotF
THEN BEGIN xferStr; wOk _ wOk AND isPageMark (str) END
;
! + + + + ;
IF dotF THEN BEGIN gP _ gPage; gL _ gLine END
ELSE BEGIN wOk _ gPage = gP + 1 AND gLine = 1; xferMark END
;
y _ 0;
WHILE (inc(y)) LEQ maxY DO
IF nonEmpty (wStr _ w[y])
THEN BEGIN xferStr; wOk _ wOk AND equ (str, wStr) END
;
xferMark; xferMark;
! Remove saved lines if ok;
IF wOk THEN
WHILE top NEQ gap
AND (gPage > gP OR (gPage = gP AND gLine > gL))
DO getTop
ELSE
BEGIN "notOk"
newVersion _ TRUE;
IF dotF THEN
BEGIN
FOR y _ maxY downto 1 DO w[y] _ NIL;
goToPlace (ldb(p.page), ldb(p.line), 1);
END
ELSE
BEGIN
markTop; markBot;
goof (".FILE.MIXUP--LOOK.FOR.DOUBLE.PAGE.MARKS..");
END
;
clearStack;
END "notOk"
;
END "wChk"
;
read; ! To set EOF-flag if at end;
putBot (eolStr); getBot; ! Guarantee at least one empty gap line;
IF wOk THEN dpyMessage (NIL);
dec (saving); ! Must come after last GETBOT;
END "finContinue"
;
COMMENT End of file IOS;