.TITLE RUNOFF .IDENT /BL5.1/ .globl DSPAT ; ; ; AUTHOR: L. WADE 1-JUN-72 ; ; MODIFIED BY: ; ; E. POLLACK U. OF W. 19-DEC-73 ; ; D. N. CUTLER 27-JUL-75 ; ; ; BONNER LAB MODIFACATIONS ; ADDED OPTIONAL ESCAPE SEQUENCE HANDLING ; Substitution flags, Layout, Most DSR commands ; Table driven parsing, Rewrote most sections!!!! ; ; J. CLEMENT November 1982 ; ; THIS PROGRAM WAS TRANSLATED FROM THE PDP-10 VERSION OF RUNOFF ; AUTHORED BY B. CLEMENTS. ; NOTES ON REGISTER USAGE ; R0 IS COMPLETELY VOLATILE ; R1-R3 SUBROUTINE PARAMETER PASSING ; R1 IS CURRENT CHARACTER ; R2 IS SPACE/LINE COUNT ; R3 IS USED AS BUFFER HEADER ADDRESS ; R4 SUBROUTINE ADDRESS FOR COMMAND EXECUTION ; J. CLEMENT AUG 82 ; ; LOCAL MACROS ; ; ; Initial switch setting tables ; .PSECT $CONST,LCL,RO,D,CON RMTAB: .BYTE 'I,'V,'X,'L,'C,'D,'M,' ; Roman numeral table .even INI$SW::.WORD HYPSW!FFDSW ; Initial value for $SWTCH IUL:: .ifdf rt11 .rad50 /L/ .iff .WORD 'L ; Initial underline switch .endc .PSECT $VARS,LCL,RW,D,CON SPSAV:: .WORD 0 ; Saves initial stack pointer ; ; UP/DOWN escape sequences ; UPTAB:: .BYTE ESC,ES.NUL ; Multiple escape processing UPMOV:: .BLKB CH.HD1+1 ; Move text up 1/2 space DNTAB:: .BYTE ESC,ES.NUL ; Multiple escape processing DNMOV:: .BLKB CH.HD1+1 ; Move text down 1/2 space VARESC::.BLKB 2*CH.HD1+1 ; Holds variable spacing string .EVEN ; ; General input switches and variables ; STSIZE=4 ; Number of status words saved VARBEG:: ; This marks first variable $SWTCH::.BLKW 1 ; Input switch USTAT:: .BLKW STSIZE ; User status block HDSTAT::.BLKW STSIZE ; header status block CHSTAT::.BLKW STSIZE ; chapter status block APSTAT::.BLKW STSIZE ; Appendix status block LVSTAT::.BLKW STSIZE ; level status block ULSWT:: .BLKW 1 ; Underline stat RIGSHI::.BLKW 1 ; Right shift for text $IFSTK::.BLKB 1 ; Number of nested ifs $IFUSW::.BLKB 1 ; If unconditional switch $HDSTS::.BLKB 1 ; Auto header status (0=enabled) $DEBSW::.BLKB 1 ; Debug switch $HDRSW::.BLKB 1 ; DISABLE PAGE HEADER (0=NO) $PAGNG::.blkb 1 ; Non zero if no paging $COLMN::.blkb 1 ; Non zero for multiple columns $COLMS::.blkb 1 ; Current column mode $FIRPG::.BLKB 1 ; Non zero if first page of document $PAGPD::.BLKB 1 ; Page pending $PAGBR::.BLKB 1 ; 0=AT TOP OF PAGE $ULMSW::.BLKB 1 ; UNDERLINE MODE (-1=Line,0=BS,1=simulate) $FOTPD::.BLKB 1 ; FOOTNOTE PENDING (0=NO) $PFOOT::.BLKB 1 ; Permanent footnote in progress $ULOSW::.BLKB 1 ; UNDERLINE OUTPUT? (0=NO) $ULCH::.BYTE '_ ; UNDERLINE CHARACTER $SEPR:: .BYTE '- ; separator character CSMOR::.BLKB 1 ; Non zero if more input files pending EOFSW::.BLKB 1 ; NON ZERO IS END OF FILE $GCEND::.BLKB 1 ; Non zero for immediate input stop $AUTTL::.BLKB 1 ; Autotitle active (0=yes) $AUSTL::.BLKB 1 ; Autosubtitle (0=NO) $LAYOU: .BLKB 1 ; Layout value NXLAY:: .BLKB 1 ; Next layout parameter PRLAY:: .BLKB 1 ; Permanent layout parameter CHLAY:: .BLKB 1 ; Chapter layout parameter $ELIPS::.BLKB 1 ; Non zero enables ellipses $TABLF::.BLKB 1 ; 0=Left justify tabs , Non=Right justify $TOCBE::.BLKB 1 ; Non zero if TOC Begun $OUTSW::.BLKB 1 ; Zero if output enabled $SEQSW::.BLKB 1 ; Separated equation mode on (0=no) $NOSPC::.BLKB 1 ; If non zero converts spaces to NXS $HSPSW::.BLKB 1 ; If zero enables half spacing $KEPSW::.BLKB 1 ; Keep blank filled lines RETSW:: .BLKB 1 ; Non zero return from GCIN on #=|sp tab $VARSP::.BLKB 1 ; Non zero if variable spacing active $UNLRS::.BLKB 1 ; Non zero if must reset underline buffer $NUMSW::.BLKB 1 ; NUMBER PAGES (0=yes) $ODPAG::.BLKB 1 ; Produce odd numbered pages $SETPG::.BLKB 1 ; Page has been set $SBPSW::.BLKB 1 ; SUBPAGE MODE ACTIVE (0=NO) HYPOP:: .BLKB 1 ; Hyphenation option .EVEN HYPLO:: .BLKW 1 ; Chars in front of autohyphenation HYPHI:: .BLKW 1 ; Chars in back HYPSZ:: .BLKW 1 ; -Minimum size word for hyphenation ; ; SWITCH PARAMS ; LOWPAG::.BLKW 1 ; Lowest page number to print HGHPAG::.BLKW 1 ; Highest page number to print LOWCHP::.BLKW 1 ; lowest chapter to print HGHCHP::.BLKW 1 ; highest chapter to print LOWAPN::.BLKW 1 ; lowest appendix to print HGHAPN::.BLKW 1 ; highest appendix to print CHPMG:: .BLKB CH.HD1+1 ; Chapter header text CHPM2:: .BLKB CH.HD2+1 ; Appendix trailing text APNMG:: .BLKB CH.HD1+1 ; Appendix header text APNM2:: .BLKB CH.HD2+1 ; Appendix trailing text PAGHD:: .BLKB CH.HD1+1 ; Page number text prototype PAGH2:: .BLKB CH.HD2+1 ; Second page header prototype TTLHD1::.BLKB CH.HD1+1 ; Title headers TTLHD2::.BLKB CH.HD2+1 ; Title headers STLHD1::.BLKB CH.HD1+1 ; Subtitle headers STLHD2::.BLKB CH.HD2+1 ; Subtitle headers LVHD1A::.BLKB CH.HD1+1 ; Header level 1 LVHD1B::.BLKB CH.HD2+1 ; Header level 1 LVHD2A::.BLKB CH.HD1+1 ; Header level 2 LVHD2B::.BLKB CH.HD2+1 ; Header level 2 LVHD3A::.BLKB CH.HD1+1 ; Header level 3 LVHD3B::.BLKB CH.HD2+1 ; Header level 3 LVHD4A::.BLKB CH.HD1+1 ; Header level 4 LVHD4B::.BLKB CH.HD2+1 ; Header level 4 LVHD5A::.BLKB CH.HD1+1 ; Header level 5 LVHD5B::.BLKB CH.HD2+1 ; Header level 5 LVHD6A::.BLKB CH.HD1+1 ; Header level 6 LVHD6B::.BLKB CH.HD2+1 ; Header level 6 .EVEN LPPG:: .BLKW 1 ; Hardware lines per page ; ; SWITCH FLAGS (WORD) ; TJFSW: .BLKW 1 ; TEMPORARY JUSTIFY FLAG (0=NO) ; ; FLAG WORDS ; ; BYTE 0= The character to test (flag character) ; BYTE 1= 0 Flag enabled ; 200 Disabled by NO FLAG command ; 100 Disabled for literal ; ; Enable bit saved for SAVE command ; $AFLSW::.WORD '_ ; FLAG ACCEPT (-=NO) $CFLSW::.WORD '<+100000 ; FLAG CAPITALIZE ENABLE (-=NO) $UFLSW::.WORD '& ; UNDERLINE SWITCH (-=NO) $LFLSW::.WORD '\ ; LOWERCASE SWITCH (-=NO) $SFLSW::.WORD '^ ; UPPERCASE SHIFT SWITCH (-=NO) $QFLSW::.WORD '# ; QUOTED SPACE SWITCH (-=NO) $OFLSW::.WORD '%+100000 ; OVERSTRIKE FLAG ENABLE (-=NO) $IFLSW::.WORD '>+100000 ; INDEX FLAG ENABLE (-=NO) $SIFSW::.WORD '>+100000 ; Subindex flag enable $HFLSW::.WORD '=+100000 ; FLAG HYPHENATE (-=NO) $EFLSW::.WORD 100000 ; ESCAPE FLAG $SBFSW::.WORD '$+100000 ; substitute flag switch $BRFSW::.WORD '|+100000 ; break flag switch $SPFSW::.WORD 0 ; Special flag switch $EQFSW::.WORD 0 ; Equation flag switch $TBFSW::.WORD 0 ; Tab flag $NFLSW::.WORD '. ; CONTROL FLAG ; ; ; ALL VARIABLES BETWEEN SAVBEG/SAVEND ARE SAVED DURING FOOTNOTING ; SAVBEG==. ; DISABLE SWITCHES (0=ENABLED) (200=DISABLED) (100=OFF)(1=OFF FOREVER) ; ; Switch table saved by SSTAT (only .DIS bits) ; SWITS: $AUBRK::.BLKB 1 ; Autobreak disabled (0=yes) $AUHYP::.BLKB 1 ; Autohyphenation disabled (0=enabled) $AUTSW::.BLKB 1 ; Autoparagraph active (0=NO) $CBRSW::.BLKB 1 ; CHANGE BAR SWITCH $ESCSW::.BLKB 1 ; ESCAPE SEQUENCES DISABLED $EQUSW::.BLKB 1 ; Equation mode on ? (0=yes) $HYPSW::.BLKB 1 ; Non zero disable hyphenation $INXSW::.BLKB 1 ; INDEXING ENABLED $OVRSW::.BLKB 1 ; OVERSTRIKING DISABLED $PERSW::.BLKB 1 ; Double spaces after punctuation (0=NO) $SUBSW::.BLKB 1 ; substitute disabled flag $TABSW::.BLKB 1 ; NON ZERO DISABLES TABS $TOCSW::.BLKB 1 ; Zero if TOC enabled $UNLSW::.BLKB 1 ; UNDERLINING OFF NSWITS=.-SWITS ; Number of switches ; ; Not saved in status ; $UNLLN::.BLKB 1 ; Counts underlines pending $TABPD::.BLKB 1 ; Right justified tab pending $CENSW::.BLKB 1 ; NON ZERO = CENTER TEXT $RIGSW::.BLKB 1 ; Non zero = right justify text HYPCT:: .BLKB 1 ; Counts hyphenated lines .EVEN HYPSV:: .BLKW 1 ; Potential savings by hyphenation ; (Set by VARSET) CASE:: .BLKB 1 ; -=LOWER CASE ONLY, +=UPPER CASE ONLY ; *** ULOCK:: .BLKB 1 ; Saves permanent case lock TTLCAS::.BLKW 1 ; Title case STLCAS::.BLKW 1 ; Subtitle case ; ; The following 3 variables are saved by permanent footnotes ; PFSBEG:: F.1:: .BLKW 1 ; Flag word NSPNG:: .BLKW 1 ; SPACING BETWEEN LINES LMARG:: .BLKW 1 ; CURRENT LEFT MARGIN RMARG:: .BLKW 1 ; CURRENT RIGHT MARGIN PFSEND: ; End of permanent footnote save PFSIZ==PFSEND-PFSBEG ; Number of bytes to save CMARG:: .BLKW 1 ; MARGIN FOR CENTERING TEXT ; ; Variables saved by VARSAV and set by VARSET ; LCH:: .BLKB 1 ; LAST CHAR LSCH:: .BLKB 1 ; Last char before space (break) .even BRCNT:: .BLKW 1 ; number of breaks this line CASSAV::.BLKW 1 ; SAVE CASE AT LAST SPACE ESCCNT::.BLKW 1 ; COUNTS ESCAPE SEQUENCES LESMSK::.BLKW 1 ; Last escape stack LINBK:: .BLKW 1 ; Line break count (+ no break) LSPCH:: .BLKW 1 ; Number of spacing chars before last space LTAB:: .BLKW 1 ; Address of last tab output count LUNLSW::.BLKW 1 ; Underline switch at last space OVRCT:: .BLKW 1 ; COUNTS BACKSPACE ABORTS SPCH:: .BLKW 1 ; Number of spacing characters SPCNSV::.BLKW 1 ; Same before last space SPCNT:: .BLKW 1 ; Expandable space count ; ; Saved by VARSAV ; HYPSP:: .BLKW 1 ; Spacing chars at last hyphen PHSP:: .BLKW 1 ; Permanent horizontal spacing LPHSP:: .BLKW 1 ; Last permanent horizontal spacing LSTSP:: .BLKW 1 ; Address of char before last space in output INDCT:: .BLKW 1 ; CURRENT INDENTATION EBSIZ1::.BLKW 1 ; Change bar initital indentation EBSIZ2::.BLKW 1 ; Change bar second indentation ESMSK:: .BLKW 1 ; Address of current location in escape stack CURVS:: .BLKW 1 ; Current vertical spacing MAXVS:: .BLKW 1 ; Max vertical spacing MINVS:: .BLKW 1 ; Min vertical spacing SAVEND=. SAVSZ==SAVEND-SAVBEG ; SIZE OF FOOTNOTE SAVE BUFFER ; ; MISC SWITCHES ; TESMSK::.BLKW 1 ; Temporary escape mask $PAGSW::.BLKW 1 ; OUTPUT 'PAGE' SWITCH (0=YES) $CHPSW::.BLKW 1 ; output chapter (0 = yes) ; ; INPUT ADDRESS POINTERS ; ERSTR:: .BLKW 1 ; SAVES ADDRESS OF STRING LNINS:: .BLKW 1 ; ADDRESS OF LAST CHAR IN LINE LSPIN:: .BLKW 8. ; ADDRESSES OF LAST INPUT SPACE LSSTK:: .BLKW 1 ; last input stack value ; ; Page format variables ; $NTITL::.BLKW 1 ; non zero prevents title in header TMARG:: .BLKW 1 ; CURRENT TOP MARGIN HSPAC:: .BLKW 1 ; CURRENT HEADER SPACING PRMRG:: .BLKW 1 ; PERMANENT RIGHT MARGIN PLMRG:: .BLKW 1 ; PERMANENT LEFT MARGIN PTMRG:: .BLKW 1 ; PERMANENT TOP MARGIN PSPNG:: .BLKW 1 ; Permanent spacing PHSPOU::.BLKW 1 ; Permanent output horizontal spacing EQSPC:: .BLKW 1 ; Equation spacing $EOPSP::.BLKW 1 ; Current End of page spacing NXEPSP::.BLKW 1 ; Next End of page spacing PREPSP::.BLKW 1 ; Permanent End of page spacing CHEPSP::.BLKW 1 ; Chapter End of page spacing APNDSP::.BLKW 1 ; appendix display format CHPDSP::.BLKB 10. ; chapter/level display format PAGDSP::.BLKW 1 ; page number display format SUBDSP::.BLKW 1 ; subpage display format (letter) PAGNX:: .BLKW 1 ; next page number SUBNX:: .BLKW 1 ; next subpage APNNX:: .BLKW 1 ; next appendix number CHPNX:: .BLKW 1 ; next chapter number PAGENO::.BLKW 1 ; CURRENT PAGE NUMBER SUBPGE::.BLKW 1 ; current subpage number APNDN:: .BLKW 1 ; Current appendix number(must be before CHPTN) CHPTN:: .BLKB 8. ; Current chapter number + header levels CHSK1:: .BLKB 1 ; Skip count 1 CHSK2:: .BLKB 1 ; Skip count 2 CHSK3:: .BLKB 1 ; Skip count 3 CHSP1:: .BLKB 1 ; Spacing count 1 CHSP2:: .BLKB 1 ; Spacing count 2 CHSP3:: .BLKB 1 ; Spacing count 3 LEVEL:: .BYTE 1 ; Current level number LINLV:: .BYTE 3 ; Lowest level with text-title run on CAPLV:: .BYTE 1 ; Highest all caps level MIXLV:: .BYTE 6 ; Highest level with first letter in caps NONLV:: .BYTE 7 ; Level - lowest without header number CENLV:: .BYTE 7 ; Level - lowest centered title BEGLV:: .BYTE 2 ; Level begin spacing ENDLV:: .BYTE 1 ; Level end spacing TPGLV:: .BYTE 8. ; Level test page SPCLV:: .BYTE 2 ; Spaces between number and title UNILV:: .BLKB 1 ; Unitary level number STLLV:: .BLKB 1 ; Autosubtitle level number OUTLV:: .BLKB 1 ; Levels enabled (0-6) TOCLV:: .BLKB 1 ; Levels enabled for TOC .even LIDLV:: .BLKW 1 ; Left level indent RIDLV:: .BLKW 1 ; Level indentation PARIND::.BLKW 1 ; Paragraph indentation PARSP:: .BLKW 1 ; Paragraph spacing count PARPT:: .BLKW 1 ; Paragraph page test count PARTT2::.BLKW 1 ; Paragraph post test count PARDFO::.BLKW 1 ; Paragraph deferred output PARDFT::.BLKW 1 ; Paragraph deferred top spacing PARDFB::.BLKW 1 ; Paragraph deferred bottom spacing PARDFH::.BLKW 1 ; Paragraph deferred hyphenation ; LINEC1&2 count lines as output, 3 when formatted LINEC1::.BLKW 1 ; Number of lines left to bottom active page LINEC2::.BLKW 1 ; Number of lines left (physical page) LINEC3::.BLKW 1 ; Number of free lines (counts saved data) FOTLN:: .BLKW 1 ; Number of lines permanent footnote LN3SAV::.BLKW 1 ; Saves old LINEC3 during text deferred TXDHED::.BLKW 1 ; Saves current text deferred header PFOTHD::.BLKW 1 ; Permanent footnote header CMADR:: .BLKW 5 ; Next expected command addresses LITSV:: .BLKW 1 ; SAVED FLAGS MASK ON LITERAL PROCESSING LSTKP:: .BLKW 1 ; CURRENT LIST STACK POINTER LSTK:: .BLKB 5*LS.SIZ ; LIST STACK (5 lists by SIZ saved bytes) TKPEND::.BLKB LS.SIZ ; End of list stack .even NOTLM:: .BLKW 1 ; NOTE SAVED LEFT MARGIN NOTRM:: .BLKW 1 ; NOTE SAVED RIGHT MARGIN NOTSV:: .BLKW 1 ; SAVED FLAG WORD ON NOTE PROCESSING EXSTAT::.BLKB 1 ; I/O status EXLINE: .BLKB 1 ; Post line count EXSP1:: .BLKB 1 ; REAL SPACES/EXPANDABLE SPACE EXSP2:: .BLKB 1 ; COUNT TO NEXT EXTRA SPACE EXSP3:: .BLKB 1 ; -1=EXTRA SPACES TO LEFT 0=TO RIGHT EXSP4: .BLKB 1 ; Permanent EXSP3 EXMSP:: .BLKB 1 ; Extra micro spaces .even CPOS:: .BLKW 1 ; CURRENT CHAR POSITION (set by VARSET) EQBOT:: .BLKW 1 ; Vertical size of equation denominator EQTOP:: .BLKW 1 ; Vertical size of equation numerator EQSTK:: .BLKW 62. ; Equation stack EQSEN:: ; End of equation stack FOTSV:: .BLKB SAVSZ ; FOOTNOTE SAVE PARAM TABLE PFTSV:: .blkb PFSIZ ; Permanent footnote save table .EVEN ESCTAB::.BLKB 18. ; Saves locked escape sequences TABTAB::.BLKB TABTL ; Table of tabstops .even NTABS:: .BLKW 1 NLPG:: .BLKW 1 ; MAX LINES THIS PAGE PNLPG:: .BLKW 1 ; Permanent max lines/page VAREND::.BLKW 1 ; end of variables .psect TEXT,RO,D,LCL,CON ONPGTX: .ASCIZ / file: / ONLNTX: .ASCIZ /On input line / JUSRM1: .ASCIZ /RNO -- Can't justify line/ EQERTX: .ASCIZ /RNO -- Missing right braces (}) in equation/ TXDERR: .ASCIZ /RNO -- Deferred page overflow/ .even .PSECT $CODE,RO,I,LCL,CON ; ; INPUT LINE ; LINUC:: CALL SHFUC ; Get input in Uppercase LIN:: CALL OUTAD ; GET OUTPUT BUFFER ADDRESS CALL LINBEG ; Begin line if necessary CALL GCIN ; Get input text CMPNEB R1,#LF,5$ ; NOT LINE FEED RETURN 5$: TSTNE BRCNT,7$ ; NO SPACES TO ALLOW HYPHENATION JMP 70$ ; Output 7$: CMPEQB LCH,#SPC,60$ ; Last char space? TST LINBK ; Line <= max length? BGE 70$ ; yes, keep it intact TSTNEB $HYPSW,60$ ; No hyphenation ? CMPB HYPCT,#2 ; Check previous hyphenation count BGE 60$ ; Prevent 3 in a row ; Inhibit hyphenation at bottom of page MOV LINEC3,R2 ; Check if at bottom of page SUB NSPNG,R2 ; Number of lines to test SUB EQBOT,R2 SUB EQTOP,R2 BLT 12$ ; Past the bottom ? SUB NSPNG,R2 SUB PARDFH,R2 ; Add deferred lines BLT 60$ ; Current line at bottom of current ? 12$: ; Allow hyphenation ; ********************************************************** .ifDF H$$PHN ; Autohyphenation ???? TSTNEB $AUHYP,50$ ; No autohyphenation ? MOV LNINS,R1 ; Char count at last char on line SUB LSPCH,R1 ; Subtract char at last break MOV R1,LNINS ; Number of chars from end of lin CMP R1,HYPSV ; Check if too few chars BLT 60$ ; Too few for hyphenation MOV LSTSP,R1 ; Address of last space CALL FNDBF ; SET POINTER TO IT MOV #TTBUF,R2 ; GET TEMPORARY BUFFER CLRB (R2)+ ; Chock beginning MOV #49.,R4 ; Maximum number of chars 14$: CALL GBYT ; GET CHARACTER BCS 17$ ; DONE BITEQB #140,R1,14$ ; Non printable char? BIC #^C<177>,R1 ; clear extra bits CMPEQB GCTABL(R1),#GC.LC,270$ ; lowercase ? CMPEQB GCTABL(R1),#GC.UC,260$ ; uppercase ? BITEQB CHTABL(R1),#CH.PNC,60$ ; Not legal punctuation ? BR 270$ ; Save punctuation 260$: ADD #40,R1 ; make it lowercase 270$: MOVB R1,(R2)+ ; SAVE CHAR SOB R4,14$ ; CONTINUE TILL DONE 17$: CLRB (R2)+ ; NULL FOR END OF STRING MOV #TTBUF+1,R0 ; BUFFER WITH HYPHENATION INFO CALL HYPHEN ; TRY TO HYPHENATE THE WORD BEQ 60$ ; No hyphenation ? MOV #TTBUF+1,R0 ADD LNINS,R0 ; POINTS TO END OF WORD 30$: TSTB -(R0) ; HYPHENATION? BMI 40$ ; YES BNE 30$ ; Not done ? BR 60$ ; NO HYPHENATION 40$: SUB #TTBUF+1,R0 ; Now is number of chars to transfer BR 55$ .endc ; ; *********************************************** 50$: MOV HYPSP,R0 ; Spacing at hyphenation SUB LSPCH,R0 ; Subtract off last spacing char count 55$: MOV R0,HYPSP ; NUMBER OF CHAR TO TRANSFER BLE 60$ ; No hyphenation set up ? CALL BKUP ; BACKUP TO LAST SPACE MOV HYPSP,LINBK ; Number of char left on line DECB $GCEND ; Immediate return on LINBK=0 CALL GCSPC ; AT BEGINNING INSERT SPACE CLRB $GCEND ; Regular return restored MOV #'-,R1 ; INSERT HYPHEN 56$: CALL PUBYT ; OUTPUT IT INC SPCH ; ONE MORE CHAR INCB HYPCT ; Count this hyphenation BR 70$ ; hyphenation done 60$: CALL BKUP ; BACKUP TO CORRECT LOCATION CLRB HYPCT ; Reset hyphenation count 70$: CALL OUTLIN ; OUTPUT LINE,JUSTIFIED IF FLAGS LINFIL: BITEQ #FILLF,F.1,110$ ; No fill ? 90$: CALL CCIN ; Get a char CMPEQB R1,#SPC,90$ ; Space ? CMPEQB R1,#CR,90$ ; Carriage return CMPNEB R1,#LF,100$ ; Not line feed RETURN ; Kill input line 100$: CALL BKSPI ; Backspace 1 110$: CALL LINBEG ; BEGIN A NEW LINE JMP LIN ; START NEXT LINE BKSPI:: MOVB SUBSTK,R0 MOV BUFADD(R0),R0 ; current input header TSTEQ BF.FUL(R0),10$ ; at beginning? DEC BF.FUL(R0) ; Decrement index DEC BF.ADD(R0) ; Previous address INC BF.CNT(R0) ; Increment count 10$: RETURN ; ; ROUTINE TO BACKUP OVER LAST SPACE (INPUT + OUTPUT) ; BKUP:: CALL LSINRS ; Restore input stack CALL OUTAD ; OUTPUT BUFFER ADDRESS BKOUT:: TSTEQ BF.HED(R3),10$ ; No header ?? MOV LSTSP,R1 ; LAST SPACE ADDRESS CALL RSTBF ; GO BACK TO PREVIOUS POINT IN BUFFER MOV SPCH,R1 ; Current spacing char SUB LSPCH,R1 ; - previous = excess ADD R1,LINBK ; Restore remainder count SUB R1,BF.SPC(R3) ; And buffer char count MOV LSPCH,SPCH ; RESTORE CHAR COUNT MOV LESMSK,ESMSK ; Restore escape stack MOVB LUNLSW,$UNLSW ; Restore underline switch MOV CASSAV,CASE ; RESTORE PREVIOUS CASE MOV SPCNSV,SPCNT ; Restore previous space count MOVB LSCH,LCH ; RESTORE LAST CHAR BEFORE SPACE MOV LPHSP,PHSP ; Restore character spacing DEC BRCNT ; One fewer break 10$: RETURN ; ; The .NO SPACE COMMAND ; NOSPC:: CMPNEB LCH,#SPC,10$ ; Last char space ? CALL OUTAD BITNE #FILLF,F.1,BKOUT ; Fill on ? 10$: RETURN ; ; ENDCM--END OF COMMAND ; ENDCM:: CALL $FRCND ; FORCE TO LOGICAL END OF LINE CMPEQ $NFLSW,R1,LGO ; COMMAND FLAG NEXT CHARACTER? CMPEQ #SEMI,R1,LGO ; MORE TEXT ON LINE? CMPEQ R1,#CR,COMNT ; END OF LINE CMPEQ R1,#LF,LGO ; FINAL END OF LINE CALL CCIN ; Advance pointer for extra char. MOV #27.,R0 ; Error message CALL ILMSG KILCM:: CALL CCIN ; FORCE TO LOGICAL END OF LINE CMPEQ $NFLSW,R1,10$ ; COMMAND FLAG NEXT CHARACTER? CMPEQ #SEMI,R1,LGO ; MORE TEXT ON LINE? CMPEQ R1,#CR,COMNT ; END OF LINE CMPEQ R1,#LF,LGO ; FINAL END OF LINE BR KILCM 10$: CALL BKSPI ; Backspace over this char BR LGO ; Process next command ; ; END OF LINE PROCESSING ; COMNT:: ; Process comment lime LCR:: CALL CCIN ; Get next char CMPNEB R1,#LF,COMNT ; Continue till end of line ; ; READ AND PROCESS NEXT LINE ; LGO:: MOV SPSAV,SP ; RELOAD STACK POINTER CALL CCIN ; READ INITIAL CHARACTER ON LINE MOV BUFADD,R0 ; INPUT BUFFER MOV BF.ADD(R0),ERSTR ; SAVE FOR ERROR OUTPUT TSTEQB EOFSW,20$ ; NOT END OF FILE? TSTNEB CSMOR,15$ ; Another input file pending ? CALL OUTNJ ; End current line BIC #FOTF,F.1 ; Kill any footnotes CALL OUTNJ ; End current line CALL TXDMP ; Dump out all text 10$: MOVB #-1,$HDRSW ; SET NO HEADER CLR TMARG ; No top margin CALL PAGEC ; FORCE A PAGE 15$: JMP ENDFIL ; END OF FILE 20$: CMPEQB R1,#LF,LGO ; FORMFEED ON INPUT? CMPEQ $NFLSW,R1,COMAN ; LEADING PERIOD? BITNE #IFFLG,F.1,COMNT; If flag on ?? BITNE #LITFG,F.1,TEXT ; PROCESSING LITERAL? BITEQ #FILLF,F.1,60$ ; NOT FILLING FROM INPUT FILE? TSTEQB $AUTSW,TEXT ; AUTOPARAGRAPH NOT ACTIVE? CMPEQ #CR,R1,40$ ; NULL LINE? CMPEQ #TAB,R1,30$ ; LEADING TAB? CMPNE #SPC,R1,TEXT ; NOT LEADING SPACE? 30$: CALL CCIN ; READ NEXT CHARACTER 35$: CMPEQ #SPC,R1,30$ ; SPACE? CMPEQ #TAB,R1,30$ ; TAB? CMPNE #CR,R1,50$ ; NOT CARRIAGE RETURN? 40$: CALL CCIN ; BYPASS LINE FEED CALL CCIN ; READ NEXT CHARACTER CMPEQ $NFLSW,R1,COMAN ; LEADING PERIOD? MOV BUFADD,R0 ; INPUT BUFFER HEADER MOV BF.ADD(R0),ERSTR ; SAVE FOR ERROR OUTPUT BR 35$ ; Now kill spaces 50$: CALL OUTNJ ; BREAK CURRENT LINE CALL PARTP ; PERFORM PARAGRAPH BREAK CALL LINBEG ; RESET LINE PARAMETERS BR TEXT ; PROCESS TEXT 60$: TSTNEB $KEPSW,TEXT ; Keep on ? CMPEQ #CR,R1,COMNT ; NULL LINE? TEXT:: CALL BKSPI ; BACKSPACE THE INPUT CALL LSINSV ; Save address of last space CALL OUTAD ; GET OUTPUT BUFFER 80$: TSTNEB $CENSW,81$ ; Centered text? TSTNEB $RIGSW,81$ ; Right justified text? BITNE #FILLF,F.1,TEXTF; Filling from input file? 81$: CALL OUTNBJ ; Output either not just, cent, or right just. TEXTF:: CALL LINFIL ; Start input BR LGO ; End of input line COMAN: CALL CMN ; PARSE COMMAND MOV #ENDCM,-(SP) ; ASSUME NONBREAK COMMAND MOV (R3),-(SP) ; SET ADDRESS OF COMMAND ROUTINE MOVB (R2),-(SP) ; GET FLAG BYTE BITEQB #BRKF,(SP),100$ ; NOT BREAK COMMAND? CALL OUTNJ ; BREAK CURRENT LINE 100$: MOV #RCNO,R4 ; SET ADDRESS OF NUMBER CONVERSION ROUTINE BITEQB #RELF,(SP)+,120$ ;ABSOLUTE CONVERSION REQUIRED? MOV #RCNR,R4 ; SET ADDRESS OF RELATIVE CONVERSION ROUTINE 120$: JMP @(SP)+ ; DISPATCH TO COMMAND ROUTINE ; ; ERROR OUTPUT ; HLTER:: MOV #9.,R0 ; Error message ILINP:: CALL ERMSG ; Output error message CALL ONLIN ; Output line number JMP RUNOFF ; And begin again ILCM:: MOV #4,R0 ; Illegal command message ILCMA:: MOV #KILCM,(SP) ; Finish up by finding next command BR ILMSG ; After printing line and page number ILTXT: MOV #COMNT,(SP) ; FINISH UP SECTION ILMSG:: CALL ERMSG ; Output error message ; ; Here we generate traceback through the substitutions ; ONLIN:: MOVB SUBSTK,R4 ; Get substitute stack 20$: TSTEQB R4,70$ ; No substitutions MOV BUFADD(R4),R2 ; Now have substitute header SUB #2,R4 ; Next subs. CALL GETTBF ; Get temporary buffer into R3 MOV BF.FUL(R3),-(SP); Current index MOV BF.SPC(R3),R1 ; Start of substitution CALL FNDBF MOV #TTBUF,R2 ; Temporary output buffer 30$: CALL GBYT ; Get 1 byte BLOS 40$ ; Till done CMP BF.FUL(R3),(SP) ; Check if at end BHI 60$ ; Done ? MOVB R1,(R2)+ ; Move it BR 30$ ; Continue till whole label trans. 40$: MOVB #':,(R2)+ ; And colon 50$: CALL GBYT ; And next substitute BLOS 60$ ; Done ? CMP BF.FUL(R3),(SP) ; Check if at end BHI 60$ ; Done ? MOVB R1,(R2)+ ; Save char CMP R2,#TTBUF+79. ; Too much ? BLO 50$ ; No ? 60$: TST (SP)+ ; Pop saved address MOV #TTBUF,R1 ; Address to output SUB R1,R2 CALL TTOUT ; Output traceback BR 20$ ; ; Print input line ; 70$: MOV BUFADD,R3 ; GET CURRENT BUFF ADDRESS MOV ERSTR,R1 ; POINTS TO BUFFER BEQ 81$ MOV BF.ADD(R3),R2 ; CURRENT CHAR ADDRESS SUB R1,R2 ; NUMBER OF BYTES BLT 81$ INC R2 CMP R2,#79. ; OK? BLE 80$ ; YES MOV #79.,R2 ; YES 80$: CALL TTOUT ; PRINT OFFENDING LINE 81$: CALL TTINOU ; Type whole line for ident. ; ; Tracback through the input files ; ONPAG:: BISB #20,$UNLSW ; No underlining MOV TRCBUF,-(SP) ; Traceback begin 1$: TSTEQ @(SP),30$ ; No traceback ? MOV #TTBF,R3 ; BUFFER FOR OUTPUT CALL CLRBF ; CLEAR BUFFER MOV #ONLNTX,R0 ; On line text string CALL PSTRZB ; MOVE IT TO BUFFER MOV (SP),R4 ; Get line MOV (R4)+,R0 ; Input Line number CALL DECTY ; Convert to number MOV #ONPGTX,R0 ; ON PAGE STRING CALL PSTRZB ; Into buffer 10$: MOVB (R4)+,R1 ; Get byte BEQ 20$ ; Done CALL PBYT BR 10$ 20$: MOV #TTBUF,R1 ; BUFFER ADDRESS MOV BF.FUL(R3),R2 ; SIZE OF STRING CALL TTOUT ; OUTPUT IT 30$: SUB #TRCLN,(SP) ; Next string ? CMP (SP),#TRCBUF ; At end ? BHI 1$ ; No BICB #20,$UNLSW ; underlining TST (SP)+ RETURN ; ; Put converted page number into buffer ; PUTPAG:: CLR -(SP) ; stop for conversion routine MOVB #'-,$SEPR ; specify separator character TSTNEB $CHPSW,20$ ; no chapter print? MOV APNDN,R1 ; GET CURRENT APPENDIX LEVEL BEQ 10$ ; IF EQ NONE BIS APNDSP,R1 ; set display format MOV R1,-(SP) ; Save for conversion BR 20$ ; 10$: MOVB CHPTN,R1 ; GET CURRENT CHAPTER NUMBER BEQ 20$ ; IF EQ NONE BIS CHPDSP,R1 ; set display format MOV R1,-(SP) ; Save for conversion 20$: MOV PAGENO,R1 BIS PAGDSP,R1 ; set display format MOV R1,-(SP) ; Save for conversion TSTEQB $SBPSW,40$ ; NO SUBPAGE? MOV SUBPGE,R1 ; SUB PAGE NUMBER BEQ 40$ ; none BIS SUBDSP,R1 ; set format MOV R1,-(SP) ; Save for conversion 40$: CALL PAGCV ; convert numbers RETURN ; ; ; CONVERTS PAGENUMBERS on stack terminated by null ; R3 = buffer header to recieve the final string ; Format NUMBER ; +100000 = Letters (upper case) ; +120000 = Letters (lower case) ; +140000 = Roman numeral (upper case) ; +160000 = Roman (lower case) ; +010000 = (upper case first letter) ; Roman numerals go from 0-2047 ; ; - sign appears after letters, before numbers. ; ex. 10-5 A-10 10A A-10B ; ; This destroyes R0-R2 and R4 ; PAGCV:: MOV (SP),-(SP) ; save stack MOV SP,R2 ; To find base entry 1$: TST (R2)+ ; base entry? BNE 1$ ; not yet CLR 2(SP) ; clear old return address ; now reverse stack between R1,R2 MOV SP,R1 ; current stack pointer 2$: MOV (R1),R0 ; save lower entry MOV -(R2),(R1)+ ; move upper to lower MOV R0,(R2) ; move lower to upper CMP R1,R2 ; not done? BLO 2$ ; yes TST (SP)+ ; unstack extra entry 3$: MOV (SP)+,R0 ; number? BNE 10$ ; YES 5$: RETURN 10$: MOV R0,R4 ; save status BITNE #100000,R0,20$ ; Is it letter? CALL DECTY ; convert number BR 50$ ; next! 20$: BIC #170000,R0 ; clear extra BITNE #40000,R4,70$ ; Roman? CLR -(SP) 30$: MOV #26.,R1 ; 26 letters/ alphabet CMP R0,R1 ; last letter? BHI 31$ ; No DEC R0 ; yes, decrement it 31$: .if df $EIS MOV R1,-(SP) ; Save divisor MOV R0,R1 ; Dividend CLR R0 DIV (SP)+,R0 ; Divide (R0=quotient) .iff CALL $DIV ; get rhand digit .endc ADD #'A,R1 ; convert to letter MOV R1,-(SP) ; save it TSTNE R0,30$ ; more? BR 110$ ; no, put into buffer 50$: MOV (SP)+,R2 ; end? BEQ 5$ ; yes BGT 60$ ; Number? BITNE #40000,R2,60$ ; Roman numeral? TST R4 ; last one letter? BGT 65$ ; no 60$: MOVB $SEPR,R1 ; output a separator CALL PUBYT INC BF.SPC(R3) ; Count spacing chars 65$: MOV R2,R0 ; save char BR 10$ 70$: CLR -(SP) ; end of stack table MOV #RMTAB,R2 BR 85$ 80$: ADD #2,R2 ; Next numeral 85$: TSTEQ R0,110$ ; done yet? .if df $EIS MOV R0,R1 ; Dividend CLR R0 DIV #10.,R0 ; Divide (R0=quotient) .iff MOV #10.,R1 ; Divide by 10 CALL $DIV ; Divide R0 by R1 .endc TSTEQ R1,80$ ; none this letter? CMPEQ R1,#4,100$ ; reversed letters? BLT 90$ ; Less than 4 ? SUB #5,R1 ; Now is less 5 BEQ 88$ CMPNE R1,#4,86$ ; reversed letters? MOVB 2(R2),-(SP) ; ex. IX BR 101$ 86$: MOVB (R2),-(SP) ; save letters 87$: SOB R1,86$ ; till done 88$: MOVB 1(R2),-(SP) ; Save 5 char BR 80$ 90$: MOVB (R2),-(SP) ; save letters SOB R1,90$ ; till done BR 80$ 100$: MOVB 1(R2),-(SP) ; output next higher letter 101$: MOVB (R2),-(SP) ; and current one ex. 4 = IV BR 80$ 110$: MOVB (SP)+,R1 ; unstack numerals BEQ 50$ ; done? BITEQ #20000,R4,120$ ; NOT (lower case)? BITNE #10000,R4,120$ ; Not (lower case first char)? ADD #40,R1 ; make it lower 120$: CALL PUBYT ; save in buffer INC BF.SPC(R3) ; Count spacing chars BIC #10000,R4 ; set lower? after first byte BR 110$ ; ; CONVERTS R0 TO NUMERIC STRING ; R3=BUFFER HEADER TO PUT STRING ; DECTY: TST R0 ; Zero ? CLR -(SP) ; SET INDICATOR 10$: .if df $EIS MOV R0,R1 ; Dividend CLR R0 DIV #10.,R0 ; Divide (R0=quotient) .iff MOV #10.,R1 ; SET DIVISOR CALL $DIV ; DIVIDE .endc ADD #60,R1 MOV R1,-(SP) ; SAVE RH DIGIT TSTNE R0,10$ ; CONTINUE IF NON ZERO 20$: MOVB (SP)+,R1 ; 1 DIGIT BEQ 30$ ; DONE CALL PUBYT ; PUT INTO BUFFER INC BF.SPC(R3) ; Count spacing chars BR 20$ ; CONTINUE TILL DONE 30$: RETURN ; ; ; EXPAND MEMORY ; EXPAND::MOV #12.,R0 ; Insufficient memory error JMP ILINP ; Give message and kill program ; ; BEGINS A LINE OR CONTINUES LINE AFTER COMMANDS BY SETTING FLAGS ; R3 is set to point to output buffer ; All other registers are destroyed ; ; LINFAK - Fake begin if line not in existance ; LINFAK::CALL OUTAD TSTNE BF.HED(R3),LINBEG; Line already begun ? CALL ENDBF ; Go to end of buffer MOV #BFHED-2,R2 ; NUMBER OF TIMES THRU CLR R1 CALL PBYT ; Spacing before MOV #HD.LIN,R1 ; Set it up as line CALL PBYT CLR R1 10$: CALL PBYT SOB R2,10$ CALL VARSET BR LSINSV RETURN LINBEG::CALL OUTAD ; GET OUTPUT ADDRESS MOV BF.HED(R3),R1 ; HEADER BYTE BEQ 20$ ; New line ?? CALL FNDBF ; get the location CALL GBYT ; get status byte TSTNEB $CBRSW,10$ ; NO CHANGE BAR NEEDED? BISB #HD.BAR,R1 ; SET CHANGE BAR BIT 10$: MOVB R1,@BF.ADD(R3); New status JMP ENDBF ; go to end of buffer 20$: CALL VARSET CALL ENDBF MOV BF.FUL(R3),R1 ; Start of header INC R1 ; Points to header MOV R1,BF.HED(R3) ; LAST HEADER ADDRESS MOV #BFHED-3,R2 ; NUMBER OF TIMES THRU CLR R1 CALL PBYT ; Spacing before TSTNEB $CBRSW,30$ ; NO CHANGE BAR NEEDED? BISB #HD.BAR,R1 ; SET CHANGE BAR BIT 30$: TSTEQB $VARSP,40$ ; No variable spacing BISB #HD.VAR,R1 40$: CALL PBYT ; Status MOVB NSPNG,R1 ; Line spacing after CALL PBYT CLR R1 ; NULL FOR HEADER 50$: CALL PBYT ; DEPOSIT PART OF HEADER SOB R2,50$ ; TILL DONE MOV ESMSK,R4 ; Escape sequences locked on BEQ 60$ ; None ? CALL ESCBEG ; Begin them 60$: MOV BF.FUL(R3),LSTSP;SET LAST SPACING CHARACTER BACK HERE CLR BF.SPC(R3) ; ; Save current input stack ; LSINSV::MOVB SUBSTK,R1 ; input stack MOV R1,LSSTK ; save old value 10$: MOV BUFADD(R1),R0 ; INPUT BUFFER MOV BF.FUL(R0),LSPIN(R1) ; LAST SPACE ON INPUT SUB #2,R1 ; next member BGE 10$ ; save more RETURN ; ; Set up variables at beginning of line ; VARSET::MOV RMARG,R2 ; COMPUTE REAL WIDTH OF LINE SUB LMARG,R2 ; AS DIFFERENCE OF MARGINS SUB INDCT,R2 ; MINUS INDENTING MOV R2,LINBK ; STORE IN LINE-BREAK COUNT MOVB ULOCK,CASE ; Restore permanent case MOV CASE,CASSAV ; SAVE CASE CLR BRCNT ; no breaks yet this line CLR SPCNT ; INITIAL COUNTS OF SPACING CLR SPCNSV CLR SPCH ; AND NON-SPACING CHARS CLR LSPCH CLR ESCCNT ; NO ESCAPES PENDING CLR OVRCT ; NO BACKSPACE ABORTION CLR LCH ; CLEAR LAST CHARACTERs CLR LTAB ; Address of last tab char CLRB $TABPD ; Set no tab pending MOV ESMSK,LESMSK ; Current end of escape stack MOVB $UNLSW,LUNLSW ; Save underline switch MOV #1,CPOS ; CARRIAGE POSITION IS FAR LEFT RETURN ; ; Restore last input stack ; LSINRS::MOV R3,-(SP) ; Save regs MOV R4,-(SP) MOVB LSSTK,R4 ; stack at last space MOVB R4,SUBSTK ; restore previous substitute stack 10$: MOV BUFADD(R4),R3 ; CURRENT BUFFER ADDRESS MOV LSPIN(R4),R1 ; LAST SPACE ADDRESS CALL FNDBF ; GO BACK TO PREVIOUS POINT IN BUFFER SUB #2,R4 ; more in stack? BGE 10$ ; yes MOV (SP)+,R4 ; Restore MOV (SP)+,R3 ; Restore RETURN ; ; RESET UNDERLINE BUFFER ; R0,R1 are destroyed ; ULBSET::MOV #UBUFF,R0 ; UNDERLIN BUFFER MOV #ULNSZ,R1 ; SIZE OF BUFFER MOV #SPC,R2 ; Char to transfer 10$: MOVB R2,(R0)+ ; PUT SPACE INTO IT SOB R1,10$ ; TILL FULL 20$: CLR ULNMAX CLRB $UNLRS MOV #1,CPOS RETURN ; ; ; INPUTS: ; ; R3=BASE VALUE TO BE AUGMENTED. ; ; OUTPUTS: ; If input skip return is taken ( to (SP)+4 ) ; non-skip return if none found ( to (SP) ) ; C set if number prefaced by + or - ; C clear if no sign ; N,Z are determined by number ; V undefined ; ; RCNO--ABSOLUTE DECIMAL INPUT ROUTINE ; R3=signed decimal number ; R3=0 if no input ; ; ; RCNR--RELATIVE DECIMAL CONVERSION ROUTINE ; R3=R3 + input if input prefaced by + or - ; R3 unchanged If no input ; RCNO:: CLR R3 ; CLEAR ANSWER AC RCNR:: MOV R3,-(SP) ; Save Old R3 MOV R2,-(SP) ; Save MOV R4,-(SP) MOV R5,-(SP) CLR R3 ; Now start with clean slate CLR R5 ; Count number of chars converted CLR R4 ; AND SIGN FLAG CALL SKPSP ; skip spaces BCS 40$ ; null param CMPNE #'+,R1,10$ ; NOT PLUS SIGN? INC R4 ; SET PLUS SIGN PRESENT 10$: CMPNE R1,#'-,20$ ; NOT MINUS SIGN? COM R4 ; SET NEGATE FLAG 20$: TSTEQ R4,22$ ; SIGN NOT SPECIFIED? 21$: CALL CCIN ; READ ANOTHER CHARACTER 22$: CMPNEB GCTABL(R1),#GC.DIG,23$ ; NOT A DIGIT? INC R5 ASL R3 ; MULTIPLY BY 10. MOV R3,-(SP) ; ASL R3 ; ASL R3 ; ADD (SP)+,R3 ; SUB #60,R1 ; SUBTRACT OUT CHARACTER BIAS ADD R1,R3 ; ADD IN DIGIT BR 21$ ; AND LOOP FOR MORE. 23$: TSTNE R5,24$ ; Number? CALL BKSPI ; back over param BR 40$ ; And signal no input 24$: CALL NEXPAR ; SKIP TO NEXT PARAM ADD #4,8.(SP) ; SET SKIP RETURN TST R4 ; check sign BEQ 30$ ; No sign ? BGT 27$ ; Plus sign ? NEG R3 ; NEGATE NUMBER 27$: ADD R3,6(SP) ; Relative value SEC ; Note signed number BR 40$ 30$: MOV R3,6(SP) ; Absolute value CLC 40$: MOV (SP)+,R5 MOV (SP)+,R4 MOV (SP)+,R2 MOV (SP)+,R3 ; Get current value RETURN ; ; ; Routine to skip to next param ; SKPSP:: CALL CCIN ; READ CHARACTER FROM COMMAND LINE CMPEQ R1,#CR,10$ ; LEADING CARRIAGE RETURN? CMPEQ $NFLSW,R1,10$ ; LEADING CONTROL CHARACTER? CMPEQ #SEMI,R1,10$ ; LEADING CHARACTER SEMICOLON? CMPEQ R1,#CMA,20$ ; LEADING COMMA? CMPEQ R1,#SPC,SKPSP ; SPACES AND TABS? CMPEQ R1,#TAB,SKPSP ; LEADING TAB? CLC ; done, no null params RETURN 10$: CALL BKSPI ; BACKUP TO SAVE CHAR. 20$: SEC ; null param RETURN ; ; SKIP OVER SPACE,BLANKS, AND 1 COMMA ONLY ; NEXPAR: CMPEQ R1,#CMA,30$ ; COMMA? CMPEQ R1,#SPC,10$ ; SPACE? CMPNE R1,#TAB,20$ ; TAB? (DISCARD ALL TABS + SPACES) 10$: CALL CCIN ; NEXT CHAR BR NEXPAR ; AND WHAT IS IT? 20$: CALL BKSPI ; NEXT CHAR FOR NEXT TIME AROUND 30$: RETURN ; ; ; routine to get up to 3 char alphameric string ; String is in right justified RAD50 format ; C = SET IF No param + R3 = 0 ; R3 = Result + Carry clear ; Null param leaves R3 unchanged, but C clear ; ; ALPGT:: CALL SKPSP ; skip leading spaces BCC 10$ ; no null param? 5$: CLC RETURN ; null param 10$: CLR -(SP) ; initial number 20$: CMP (SP),#3100 ; Done ? BHIS 40$ ; Found 3 letters ? CMPB GCTABL(R1),#GC.LC ; letter? BGT 40$ ; no BNE 30$ ; upper case? SUB #40,R1 ; convert to upper 30$: SUB #'@,R1 ; convert letter to number MOV (SP),R0 ; previous sum MOV R1,(SP) ; save current char MOV #50,R1 ; multiplier .if df $EIS MUL R1,R0 ; Mult R1 by R0 .iff CALL $MUL ; mult R1 by R0 .endc ADD R1,(SP) ; new total CALL CCIN ; next BR 20$ 40$: CALL NEXPAR ; set up for next param MOV (SP)+,R3 ; get result BNE 5$ ; Input ? SEC ; no RETURN ; ; ; SUBROUTINE TO PARSE INPUT FOR LITERAL ; R2=ADDRESS OF LITERAL R1=LENGTH OF LITERAL ; CARRY CLEAR IF SUCCESS SET IF NONE FOUND ; Literal is in TTBUF maximum of 80 bytes! ; GETLIT:: CALL CCIN ; GET 1 CHAR BCS 50$ ; BAD, NO FILE SPEC CMPEQ R1,#SPC,GETLIT ; IGNORE CMPEQ R1,#TAB,GETLIT ; IGNORE CMPEQ R1,#'',10$ ; START OF LITERAL CMPNE R1,#'",40$ ; NOT START OFF LITERAL? 10$: MOVB R1,-(SP) ; Save initial char MOV #TTBUF,R2 ; Buffer for literal CALL LSINSV ; Save this spot 20$: CALL CCIN ; NEXT CHAR BCS 50$ ; NO MORE CMP R2,#TTBUF+80. ; Check if at end of buffer BLO 25$ ; No ? JMP ILCM ; Yes kill this command 25$: MOVB R1,(R2)+ ; Now save char CMPEQB R1,(SP),30$ ; END OF LITERAL? CMPNE R1,#CR,20$ ; not end of buffer? CALL BKSPI ; backspace over carriage return 30$: CALL CCIN ; Get next char CMPEQB R1,(SP),20$ ; 2'nd delimiter ??? CLRB -(R2) ; Now chock end of literal MOV R2,(SP) ; Save end of buffer CALL NEXPAR ; SKIP TO NEXT PARAM MOV (SP)+,R1 ; LAST CHAR IN LIT +1 ADDRESS MOV #TTBUF,R2 ; Buffer for literal SUB R2,R1 ; NUMBER OF BYTES CLC ; OK! RETURN 40$: CALL BKSPI ; BACKUP 1 CHAR 50$: SEC ; NOT OK RETURN ; ; ; $FRCND-FORCE TO LOGICAL END OF COMMAND ; $FRCND::CALL CCIN ; READ CHARACTER FROM FILE CMPEQ #SPC,R1,$FRCND ; SPACE? CMPEQ #TAB,R1,$FRCND ; TAB? CMPEQ #SEMI,R1,10$ ; SEMICOLON? CALL BKSPI ; BACKSPACE 1 CHAR 10$: RETURN ; ; ; Line output routine. two entry points ; OUTLIN - No break ; OUTNJ - Output with break ; OUTLIN::BITNE #FOTF!TEXF,F.1,10$ ; Footnote or Text ? TSTNEB $PAGNG,10$ ; No paging ? MOV PARDFT,R1 ; Get deferred count BEQ 10$ ; None ?? ADD EQTOP,R1 ADD EQBOT,R1 CMP R1,LINEC3 ; Check if deferred text BLE 10$ ; Not yet BIS #PARF,F.1 ; Set deferred lines 10$: MOVB #-1,TJFSW ; SET JUSTIFY FLAG COMB EXSP4 TSTNEB $CENSW,OUTNJ0 ; CENTERED/NOT JUSTIFIED? TSTNEB $RIGSW,OUTNJ0 ; Not justify if right justified BITNE #JUSTF,F.1,OUTJ2 ;JUSTIFYING? BR OUTNBJ OUTNJ:: BIS #BRKF,F.1 ; Set for break OUTNBJ: CLRB HYPCT ; Clear hyphenation count OUTNJ0: CLRB TJFSW ; CLEAR JUSTIFY FLAG CLRB EXSP4 ; CLEAR LEFT RIGHT SPACING OUTJ2: CLRB EXSP2 CLRB EXSP1 MOVB #-1,EXMSP CLR HYPSP ; Reset hyphenation spacing CALL OUTAD ; GET BUFF ADDRESS TSTNE BF.HED(R3),10$ ; Line exists ?? JMP OUTNJ3 ; Do not process output line 10$: TSTEQ @EQSTK,40$ ; Is equation not being formatted ? MOV #EQERTX,R0 ; Error message for equation CALL EROUT ; Output message CALL ONLIN ; INDICATE WHAT PAGE MOV #EQSTK+2,EQSTK ; Reset equation stack MOV #SW.EDS,R0 ; Equation disable bits BICB R0,$TABSW ; ALLOW tabs BICB R0,$NOSPC ; expandable spaces BICB R0,$UFLSW+1 ; underlining BICB R0,$BRFSW+1 ; break flags BICB R0,$AUBRK ; autobreak BICB R0,$HYPSW ; hyphenation 40$: MOV ESMSK,R4 ; Escapes locked on BEQ 50$ ; None ? CALL ESCEND ; End the escape sequence 50$: TSTEQB TJFSW,OUTNJ1 ; NOT JUSTIFYING LINE? CLRB TJFSW ; IN CASE MOV RMARG,R0 ; YES. COMPUTE WHERE TO EXPAND THEM SUB LMARG,R0 ; SIZE OF LINE SUB INDCT,R0 ; .. SUB SPCH,R0 ; SUBTRACT NUMBER OF SPACING CHARS BEQ OUTNJ1 ; No justifacation needed ? MOV SPCNT,R1 ; NOW FIND HOW MANY MULT SPACES EACH SPACE IS BNE 60$ ; Spaces present to allow justif. ? MOV #JUSRM1,R0 ; Can't justify line message CALL EROUT ; Output message CALL ONLIN ; INDICATE WHAT PAGE BR OUTNJ1 ; 60$: ADD R1,R0 ; ADD NUMBER OF SPACES .if df $EIS MOV R1,-(SP) ; Save divisor MOV R0,R1 ; Dividend CLR R0 DIV (SP)+,R0 ; Divide (R0=quotient) .iff CALL $DIV ; Divide tot spac/SPCNT = R0/R1 .endc MOVB R0,EXSP1 ; MULTIPLIER FOR ALL SPACES TSTEQB $VARSP,70$ ; No variable spacing ? MOVB VARESC,R0 ; Number of steps per space BLE 70$ ; Bad value ? .if df $EIS MUL R1,R0 ; Mult R1 by R0 .iff CALL $MUL ; mult R1 by R0 .endc .if df $EIS CLR R0 DIV SPCNT,R0 ; Divide SPCNT into R0,R1 .iff MOV R1,R0 ; Into R0 MOV SPCNT,R1 ; Get number of spaces again CALL $DIV ; DIVIDE .endc MOVB R0,EXMSP ; Number of extra micro spaces 70$: TSTNEB EXSP4,80$ ; EXTRAS TO LEFT? NEG R1 ; RIGHT. GET SPACES BEFORE EXTRAS ADD SPCNT,R1 ; .. 80$: MOVB R1,EXSP2 ; STORE FOR LATER OUTNJ1: CALL OUTAD ; GET BUFF ADDRESS MOV BF.HED(R3),R1 ; GET LIN HEADER DEC R1 ; Points to first byte CALL FNDBF ; Set to point to it CALL GBYT ; Get the line count ADD EQTOP,R1 ; Add on top of equation TSTNEB $PAGNG,10$ ; No paging ? TSTB $PFOOT ; Permanent footnote in progress ? Blt 5$ ; YES ? SUB R1,LINEC3 ; Account for extra lines 5$: ADD R1,BF.VSP(R3) ; And vertical spacing this buffer 10$: MOVB R1,@BF.ADD(R3) ; And save it CLR EQTOP ; No more pre spacing CALL GBYT ; Get status byte BISB #HD.LIN,R1 ; Set it as output line TSTNE SPCH,12$ ; Spacing chars ? BICB #HD.BAR,R1 ; No change bar 12$: MOVB R1,@BF.ADD(R3) ; Output line MOVB R1,EXSTAT ; Save status CALL GBYT ; Get post line count ADD EQBOT,R1 ; Get bottom spacing TSTNEB $PAGNG,20$ ; No paging ? TSTB $PFOOT ; Permanent footnote in progress ? BLT 15$ ; YES ? SUB R1,LINEC3 ; Account for extra lines 15$: ADD R1,BF.VSP(R3) ; Account for vertical spacing 20$: MOVB R1,@BF.ADD(R3) ; Save lines CLR EQBOT ; Clear bottom MOV LMARG,R2 ; GET LEFT MARGIN TSTEQB $RIGSW,50$ ; Not right justify? BICB #SW.TDS,$RIGSW ; Reset temporary right justify MOV RMARG,R2 ; right margin SUB SPCH,R2 ; Now have indentation for right justify SUB INDCT,R2 ; Subtract indentation TSTNEB $RIGSW,55$ ; Still right justify ? BR 54$ 50$: ADD INDCT,R2 ; GET INDENTING IN CASE OF PARAGRAPH 54$: CLR INDCT ; (ONCE ONLY) 55$: TSTEQB $CENSW,60$ ; NO CENTERING? BICB #SW.TDS,$CENSW ; CLEAR TEMPORARY CENTERING MOV CMARG,R2 ; CENTERING MARGIN MOV SPCH,R0 ; NUMBER OF CHAR IN LINE CLC ; CLEAR C JUST IN CASE ASR R0 ; DIVIDE BY 2 SUB R0,R2 ; NOW IS CHARS TO CENTER 60$: ADD EBSIZ2,R2 ; ADD ON CHANGE BAR SIZE BITEQB #HD.BAR,EXSTAT,70$ ; CHANGE BAR PENDING? DEC R2 ; 1 CHAR IS OUT SO STOP ITS SPACE 70$: MOV RIGSHI,R1 ; Right shift ADD EBSIZ1,R1 ; Plus bar spacing #1 CALL PBYT ; Output for initial spacing MOV R2,R1 ; Spacing after bar BGT 80$ ; Margin ok? CLR R1 ; No, make it 0 80$: CALL PBYT ; in buffer MOVB EXSP1,R1 CALL PBYT ; in buffer MOVB EXSP2,R1 CALL PBYT ; in buffer MOVB EXSP4,R1 ; SAVED EXPANSIONS CALL PBYT ; in buffer MOVB EXMSP,R1 ; Saved micro expansion CALL PBYT CALL ENDBF ; go back to end of buffer CLR R1 ; Null terminates the line CALL PBYT ; Put at end of line CLR BF.HED(R3) ; No line available OUTNJ3: TSTNEB $PAGNG,20$ ; No paging ?? BITNE #FOTF!TEXF,F.1,10$ ; Text or footnote flags on ? BITEQ #BRKF,F.1,1$ ; No break this line ?? TST LINEC3 ; Check room this page BGE 8$ ; Room for all deferred ? 1$: BITEQ #PARF,F.1,10$ ; No deferred ? MOV PARDFT,R0 ; Get paragraph line deferral MOV PARDFB,R1 ; Get bottom deferred BITEQ #BRKF,F.1,7$ ; No break this line ?? CMPEQ R0,R1,2$ ; Same as bottom ? CMP R0,BF.VSP(R3) ; Deferr all ? BGT 3$ ; Yes 2$: MOV R1,R0 ; Deferred lines at bottom ADD LINEC3,R0 ; Subtract off number past endpage 3$: MOV R0,PARDFO ; Deferred lines BR 9$ 7$: ADD LINEC3,R1 ; Add to lines to test BLE 8$ ; Enough lines ? RETURN ; No continue 8$: CLR PARDFO 9$: BIC #PARF,F.1 ; No more deferred CALL OUTL0 ; Do the output BITEQ #BRKF,F.1,10$ ; Line not broken ? CLR PARDFB ; Yes, reset paragraph deferred CLR PARDFT ; CLR PARDFH 10$: BIC #BRKF,F.1 ; No break flag CALL TESTL BITNE #FOTF!TXDEF,F.1,40$ ; Footnote or deferred text? BITEQ #TEXF!PARF,F.1,20$ ; No text saved ?? TSTNEB $PAGBR,40$ ; not at top of page ?? 20$: BIC #BRKF!TEXF!PARF,F.1 ; Reset text flag JMP OUTL0 ; NO OUTPUT THE LINE 40$: RETURN ; ; ; DO ACTUAL OUTPUT TO PRINTER OF TEXT STRING ; OUTL0:: CLRB EXLINE CALL OUTAD ; GET HEADER ADDRESS CALL BEGBF ; SET TO TOP OF BUFFER OUTL1: MOVB EXLINE,R2 ; Get skip count CALL $SKIP0 ; Skip R2 lines CLRB EXLINE ; Clear skip CALL GBYT ; Get skip count BCC 5$ ; Not done JMP OUTL2 ; Done 5$: BIC #^C<377>,R1 ; Strip off extra byte MOV R1,R2 ; Now is skip count CALL GBYT ; Get status BITEQB #HD.TXD,R1,10$ ; Not end of text deferred buffer ? JMP TXDOU2 10$: MOVB R1,EXSTAT ; Save status BGE 15$ ; Normal line ?? TSTNEB $PAGNG,12$ ; No paging ? BITEQB #HD.FIG,R1,11$ ; Mandatory skip ? TSTNEB $PAGBR,11$ ; Page not already broken? ADD R2,LINEC3 ; Compensate for missing skip SUB R2,BF.VSP(R3) BR OUTL1 11$: TSTEQB $PAGBR,12$ ; Page already broken? CMP R2,LINEC1 ; Enough space left ?? BLE 12$ ; No ? ADD R2,BF.VSP(R3) ; Adjust vertical spacing MOV LINEC1,R2 ; MAKE IT MAX SUB R2,BF.VSP(R3) ; Adjust vertical spacing 12$: CALL $SKIP0 BR OUTL1 15$: BITNEB #HD.LIN,R1,16$ ; Output line ? TSTNE BF.HED(R3),13$ ; Header exists ? JMP HLTER ; No, this is fatal error 13$: JMP TXDOU3 16$: CALL GBYT ; Get post line count BIC #^C<377>,R1 ; Strip off extra byte MOVB R1,EXLINE ; Save it TSTNEB $PAGNG,20$ ; No paging ? ADD R2,R1 ; Total lines this one ADD PARDFO,R1 ; Add deferred lines CMP R1,LINEC1 ; Check if too big BLE 20$ ; Is it OK ? CLRB EXLINE MOV BF.FUL(R3),R1 ; Get current address DEC R1 BR TXDOU4 ; And save line 20$: CALL $SKIP0 ; Skip R2 lines CALL GBYT ; Get initial spacing BIC #^C<377>,R1 ; Strip off extra byte MOV R1,R2 ; CALL NSPAC ; Output n spaces BITEQB EXSTAT,#HD.BAR,30$ ; NO BAR? MOVB #'|,R1 ; NOPE CALL FOUT ; Output change bar INC CPOS ; Increment position counter 30$: CALL GBYT ; Spaces after bar BIC #^C<377>,R1 ; Strip off extra byte MOV R1,R2 ; MARGIN BIC #177400,R2 ; Clear extra bits CALL NSPAC ; OUTPUT SPACES CALL GBYT ; Get spacing control parameters MOVB R1,EXSP1 CALL GBYT MOVB R1,EXSP2 CALL GBYT MOVB R1,EXSP3 CALL GBYT MOVB R1,EXMSP CALL CCOUT ; Output + format text BCS 40$ ; End of buffer ? CALL UNLOUT ; Output underlines JMP OUTL1 40$: CALL UNLOUT ; Output underlines MOVB EXLINE,R2 ; Get skip count CALL $SKIP0 ; Skip R2 lines ; ; END OF LINE, AND FOOTNOTE PROCESSING ; OUTL2: CLRB EXLINE ; Clear skip CLRB EXSTAT ; Clear status CLRB EXSP1 ; Clear spacing controls CLRB EXSP2 CLRB EXSP3 MOVB #-1,EXMSP BITEQ #FOTF,F.1,20$ ; No footnote in progress? CLRB $FOTPD ; CLEAR PENDING MOV PFOTHD,R1 ; Permanent footnote header BEQ 20$ ; Zero ? MOV FOTLN,BF.VSP(R3); Permanent footnote size JMP RSTBF ; Return to previous header 20$: JMP CLRBF ; CLEAR THE BUFFER ; ; Reshuffle buffer containing output lines ; TXDOU2: TSTEQB $PAGBR,5$ ; At top of page ? MOV R2,BF.VSP(R3) ; New vertical spacing BEQ 5$ CMP R2,LINEC3 ; Compare with available space BGT TXDOU3 ; Too big ? 5$: SUB R2,LINEC3 ; Subtract from LINEC3 JMP OUTL1 ; And do more TXDOU3: MOV BF.FUL(R3),R1 ; Get current index TXDOU4: SUB #2,R1 ; Backspace 2 BNE 1$ ; Not at beginning ? JMP ENDBF ; Go to end of buffer 1$: CALL FNDBF ; Move over to it MOV BF.HED(R3),R0 ; Get current header value BEQ 10$ ; None ? SUB R1,R0 ; Subtrac off offset MOV R0,BF.HED(R3) ; New header 10$: MOV R3,R2 ; Save address CALL GETTBF ; Get temporary header CALL BEGBF ; Start at beginning of buffer BITEQ #FOTF,F.1,20$ ; No footnote ? MOV PFOTHD,R1 ; Permanent footnote header BEQ 20$ ; None ? ADD FOTLN,BF.VSP(R3); Add on permanent lines to header TSTEQ BF.HED(R3),15$ ; No header ? ADD R1,BF.HED(R3) ; Add on permanent header 15$: CALL FNDBF 20$: CALL GBYT2 ; Get a byte BCS 30$ ; Done ? CALL PBYT ; Save it BR 20$ 30$: MOV BF.FUL(R3),R1 ; Reset buffer to end here MOV R2,R3 ; Switch to primary buffer JMP RSTBF ; ; Output underlines from buffer ; UNLOUT: MOV R3,-(SP) ; SAVE R3 TSTEQB $ULMSW,50$ ; Mode backspace or none TSTEQ ULNMAX,40$ ; NO UNDERLINES IN BUFFER? TSTB $ULMSW ; Now test mode BLT 10$ ; Line ? TSTNEB $PAGNG,5$ ; No paging SUB #LINSP,LINEC3 ; ACCOUNT FOR EXTRA LINE 5$: CALL CRLF ; SPACE TO NEXT LINE BR 20$ ; 10$: TSTNEB $OUTSW,40$ ; No output ? MOV #CR,R1 ; OUTPUT A CARRIAGE RETURN BITEQB #CRSW,$SWTCH,15$; No CRLF output? CALL FOUT ; 15$: CALL OUTPUT ; Start a new line 20$: MOVB #-1,$UNLRS ; Set up reset underline MOV #UBUFF,R3 ; GET UNDERLINE BUFFER MOV ULNMAX,R2 ; MAX CHAR 30$: MOVB (R3)+,R1 ; GET UNDERLINE CHAR BGT 36$ ; Not microspace ? BIC #177600,R1 ; Strip extra bits MOV R1,-(SP) ; Save counter 31$: MOV #VARESC+1,R4 ; Microspace escape seq. DEC (SP) ; ANother time through ? BGE 32$ ; Yes ? TST (SP)+ ; Pop stacke BR 37$ 32$: MOVB (R4)+,R1 ; Get char BEQ 31$ ; Done yet ? CALL FOUT ; Output it BR 32$ 36$: CALL FOUT 37$: SOB R2,30$ ; TILL DONE 40$: TSTEQB $UNLRS,50$ ; No changes in underline buffer ? CALL ULBSET ; RESET UNDERLINE BUFFER POINTER 50$: MOV #1,CPOS CLRB $ULOSW ; No underlining yet MOV (SP)+,R3 ; RESTORE R3 RETURN ; ; OUTPUT deferred text ; TXDOUT::BITNE #TXDEF!FOTF,F.1,10$ ; Currently in deferred or footn. mode ? TSTEQ BF.VSP+TXDBF,10$; No data in buffer ? MOV F.1,-(SP) BIS #TXDEF!TEXF,F.1 ; Set up for deferred text CALL OUTAD ; Get buffer address CALL BEGBF ; Start at beginning of buffer CALL OUTL1 ; Output it MOV (SP)+,F.1 ; Restore 10$: RETURN ; ; END text deferred ; TXDEND::BITEQ #TXDEF,F.1,10$ ; Not text deferred ? CALL OUTAD ; Get address MOV TXDHED,R1 ; Get header CALL FNDBF ; Get it MOV BF.VSP(R3),R1 ; Spacing CALL PBYT ; Save it CALL ENDBF MOV #-1,BF.VSP(R3) ; Set up line size MOV LN3SAV,LINEC3 ; Restore saved size BIC #TXDEF!TEXF,F.1 ; No deferred text now 10$: BR TXDOUT ; Try to output text ; ; Dump all text ; TXDMP:: BITNE #TXDEF,F.1,1$ ; No text deferred ? BIC #TEXF,F.1 ; No text now 1$: CALL OUTNJ ; Dump current text CALL TXDEND CALL TXDOUT ; And any deferred 10$: TSTEQ BF.VSP+TXDBF,20$; No deferred text ? CALL BPAGE ; Output 1 page CALL OUTNJ ; Flush any normal text BR 10$ 20$: RETURN ; ; Subroutine to skip N text lines ; R1=skip count ; SKIPL is unconditional skip ; SKPLIF is conditional on if not at top of page ; SKPLIF:: TSTEQB $PAGBR,SKRET ; Not at top of page SKIPL:: CALL MULSP ; Adjust spacing by the line spacing MOV R1,R2 ; Now is correct spacing BR SKIPN ; ; SUBROUTINE TO SKIP N LINES ON OUTPUT FILE ; R2 = NUMBER OF LINES TO SKIP ; bit 15 clear this is mandatory skip ; set no skip at top of page ; SKIPS:: MOV NSPNG,R2 ; SET TO SKIP TO NEXT LINE BR SKIPN ; SKIPN:: MOV R2,R0 ; Skip in R0 CALL OUTAD ; GET BUFFER ADDRESS TSTEQ BF.HED(R3),1$ ; No header ?? JMP HLTER ; Yes, generate error message 1$: TSTNEB $PAGNG,$SKIP0 ; No paging ?? BIC #^C<377>,R0 ; Strip extra bits BEQ SKRET ; YES DO NOT SKIP TSTB $PFOOT ; Permanent footnote BLT 40$ ; in progress ? 10$: CMP R0,LINEC3 ; LINE COUNT BLT 30$ ; Skip count not too many ? MOV LINEC3,R0 ; Skip to bottom BGT 20$ ; Good skip? MOV #LINSP,R0 ; No, make it 1 20$: DECB $PAGPD ; New page pending 30$: SUB R0,LINEC3 ; Now line count 40$: ADD R0,BF.VSP(R3) ; Add to vertical spacing this buffer BIC #377,R2 ; Clear extra bits ADD R0,R2 ; And subs R0 BITEQ #FOTF!TEXF!PARF,F.1,$SKIP0 ; No footnote or deferred text? CALL ENDBF ; get the location MOVB R2,R1 ; Skip count CALL PBYT ; Save it MOV #HD.SKP,R1 ; Make this skip TST R2 ; Check if mandatory skip BGE 50$ ; Mandatory ? BISB #HD.FIG,R1 ; Set it as optional 50$: CALL PBYT ; Save skip header SKRET: RETURN $SKIP: TSTNEB $PAGNG,$SKIP1 ; No paging SUB R2,LINEC3 ; ADD LINES TO TOTAL BR $SKIP1 $SKIP0: BIC #^C<377>,R2 ; Strip extra bits BNE 10$ ; Any skip ?? RETURN 10$: TSTNEB $PAGNG,$SKIP1 ; No paging ? SUB R2,BF.VSP(R3) ; Number of lines this buffer $SKIP1: MOVB #-1,$PAGBR ; NOT AT TOP OF PAGE ; ; Perform half line skips ; R2=half line count ; SKIP01: BITEQ #1,R2,30$ ; No half lines required ? MOV R2,-(SP) ; save half line spacing TSTNEB $PAGNG,5$ ; No paging DEC LINEC1 ; Account for half lines DEC LINEC2 5$: MOV #DNMOV,R2 ; Get buffer to transfer 10$: MOVB (R2)+,R1 ; Get char BEQ 20$ ; Done ? CALL FOUT BR 10$ 20$: CALL OUTPUT ; Start a new line MOV (SP)+,R2 ; RESTORE NUMBER OF LINES 30$: BIC #1,R2 ; Clear half bit BLE 70$ ; No more to output 60$: CALL CRLF ; SPACE TO NEXT LINE SUB #LINSP,R2 ; Lines left BGT 60$ ; Not done ? 70$: RETURN ; ; ; ROUTINE TO OUTPUT SPACES TO FILE ; NSPAC:: DEC R2 ; ANY MORE SPACES TO OUTPUT? BLT SKRET ; IF LT NO CALL CCSPC ; OUTPUT A SPACE BR NSPAC ; ; ; End of line output routine ; CRLF:: BITEQB #CRSW,$SWTCH,10$ ; No CRLF output? MOVB #CR,R1 ; Get carriage return CALL FOUT ; Output it MOVB #LF,R1 ; And line feed CALL FOUT 10$: TSTNEB $PAGNG,20$ ; No paging ? SUB #LINSP,LINEC1 ; Counts active lines SUB #LINSP,LINEC2 ; And total lines 20$: JMP OUTPUT ; And end line ; ; SUBROUTINE PUTS CURRENT CHAR ADDRESS INTO R3 ; OUTAD:: BITNE #FOTF!TXDEF,F.1,10$ ; Deferred or footnote ? MOV #TX2BF,R3 ; NORMAL SECONDARY BUFFER RETURN ; 10$: BITEQ #FOTF,F.1,20$ ; NOT FOOTNOTE BUFFER? MOV #FOTBF,R3 ; GET FOOTNOTE BUFFER ADDRESS RETURN ; 20$: MOV #TXDBF,R3 ; Text deferred buffer RETURN ; ;ROUTINE TO SPACE TO TOP OF FORM ; FORM: CLRB $PAGPD ; No longer page pending MOVB $COLMN,$COLMS ; Set next columns mode ; ; Output FF or adjust to correct page height ; TSTNEB $FIRPG,40$ ; First page? TSTNEB $OUTSW,50$ ; No output ? BITEQ #FFDSW,$SWTCH,10$ ;SPACING WITH LINE FEEDS? MOV #FF,R1 ; OUTPUT A FORMFEED CALL FOUT CALL OUTPUT ; Start a new line BR 40$ ; ADJUST COUNTS 10$: MOV LPPG,R1 ; Number of lines/page BLE 40$ ; Too small ? MOV LINEC2,R2 ; Number of lines to skip 15$: BGT 20$ ; Skip correct ? BEQ 40$ ; none ? ADD R1,R2 ; Add on lines/page BR 15$ 20$: CALL SKIP01 ; Skip over lines 40$: CALL OPRWAT ; WAIT FOR OPERATOR TO POSITION FORMS ; ; Setup current page number ; 50$: CALL ULBSET ; Reset underline buffer in case MOVB $SBPSW,R0 ; Get subpage status BEQ 80$ BITEQ #SW.DIS,R0,70$ ; No subpage requested ? BISB #SW.TDS,$SBPSW ; Set keep bit TSTEQB $SETPG,60$ ; Page reset ? MOV PAGNX,R0 ; Keep page requested MOV R0,PAGENO ; Current page number INC R0 MOV R0,PAGNX ; Next page 60$: MOVB SUBNX,SUBPGE ; set to current subpage INCB SUBNX ; yes increment it BNE 90$ ; Non zero? INCB SUBNX ; No, make it 1 BR 90$ 70$: MOVB #1,SUBNX ; Next subpage number CLRB $SBPSW ; No subpage CLRB SUBPGE ; No subpage 80$: MOV PAGNX,R0 ; now current page number MOV R0,PAGENO INC R0 ; increment next page number MOV R0,PAGNX ; Save new page number ; ; Test if this page output ; 90$: TSTNE PAGENO,100$ ; Page number ok ? INC PAGENO ; No make it 1 100$: CLRB $SETPG MOVB #-1,$OUTSW ; Set for no output CMP PAGENO,LOWPAG ; ONLY PRINT IN THE SELECTED PAGE BLO 150$ ; RANGE CMPB CHPTN,LOWCHP ; chapter # too small? BLO 150$ ; yes CMPB APNDN,LOWAPN ; appendix too small? BLO 150$ ; yes CMP PAGENO,HGHPAG ; page number too big? BHI 110$ ; yes CMPB CHPTN,HGHCHP ; too big? BHI 110$ ; yes CMPB APNDN,HGHAPN ; appendix too big? BLOS 120$ ; No ? 110$: MOV #ENDFIL,(SP) ; Set to terminate file 120$: BITNE #1,PAGENO,130$ ; Current page number odd ? BITNE #EVESW,$SWTCH,150$; Even pages off ? BR 140$ 130$: BITNE #ODDSW,$SWTCH,150$; Odd pages off ? 140$: CLRB $OUTSW ; Set output on ; ; Set up params next page ; 150$: MOVB NXLAY,$LAYOU ; Current layout is now Next layout MOVB PRLAY,NXLAY ; Next is permanent layout MOV NXEPSP,$EOPSP ; Next end-of-page spacing MOV PREPSP,NXEPSP ; Permanent eop spacing MOV NLPG,LINEC1 ; Active lines this page SUB $EOPSP,LINEC1 ; Subtract off bottom lines MOV LINEC1,LINEC3 ; Potential lines per page TSTEQB $FOTPD,160$ ; Footnote not pending ? SUB FOTBF+BF.VSP,LINEC3 ; Subtract off header size 160$: MOV LPPG,LINEC2 ; Number of actual lines remaining this page RETURN ; ; Routine to convert vetical spacing to appropriate number ; CVSP:: TSTEQB $HSPSW,10$ ; Half spacing ? ASL R3 ; Convert to half space count 10$: RETURN ; ; Find actual adjusted lines ; R1=# of text lines ; R0,R1=hi,low order result ; MULSP:: MOV NSPNG,R0 ; Get line spacing .if df $EIS MUL R1,R0 ; Mult R1 by R0 .iff CALL $MUL ; mult R1 by R0 .endc RETURN ; ; Test if room for lines of text ; TESTT:: CALL MULSP ; Convert to actual spacing BR TESTP ; ; Test if enough room for 1 more line, and if not break page ; TESTL: CLR R1 ; Check if no more room ; ; R1 = number of lines requested, check if break page? ; TESTP:: TSTNEB $PAGNG,10$ TSTB $PFOOT ; Permanent footnote in progress? BLT 10$ ; Yes ? CMP R1,LINEC3 ; COMPARE TO LENGTH BLE 10$ ; Enough lines ? MOV R1,-(SP) ; Save R1 CALL BPAGE MOV (SP)+,R1 ; Restore TSTEQB $PAGBR,20$ ; Currently at top of page ? BR TESTP ; START A NEW PAGE 10$: SEC ; NO PAGE BROKEN RETURN ; 20$: CLC ; Page broken RETURN ; ; SUBPAGE command ; TPAGE:: BISB #SW.DIS,$SBPSW ; Set subpage flag BR BPAGE ; ; Reset to page # 0 and begin new page ; PAGRST:: TSTNEB $CHPSW,PAGEC ; Not chapter oriented? MOV #1,PAGNX ; Next page number is 1 ; ; END SUBPAGE command ; PAGEC:: BICB #SW.DIS,$SBPSW ; CLEAR SUBPAGE FLAG BR BPAGE ; ; PAGE command (new page only if not already at top-of-page) ; CPAGE:: TSTNEB $PAGBR,BPAGE ; Page not already broken? CLC ; Signify page broken ; ; BREAK COMMAND ; BREAK:: RETURN ; ; Start new page routine ; BPAGE:: MOV F.1,-(SP) ; Save 1$: MOV (SP),F.1 ; Get flags BITEQ #TXDEF,F.1,5$ ; No text deferred ? MOV #TXDERR,R0 ; Error message CALL EROUT ; Text deferred is illegal here CALL TXDEND ; End the deferred buffer 5$: TSTNEB $FIRPG,30$ ; First page of document ?? BITEQ #FOTF,F.1,10$ ; No footnote in progress? CALL OUTL0 ; Do footnote output MOVB #-1,$FOTPD ; Reset pending in case it is reset BR 30$ 10$: TSTEQB $FOTPD,30$ ; NO FOOTNOTE PENDING? MOV LINEC3,R2 ; LINES LEFT BLE 20$ ; NONE CALL $SKIP ; SKIP THEM 20$: BIS #FOTF,F.1 ; SET FLAG CALL OUTL0 ; OUTPUT IT 30$: BIC #FOTF,F.1 ; Now set no footnote CALL BPAG2 ; Actually output page header BICB #SW.TDS,$HDRSW ; Reset temporary header disable CLRB $FIRPG ; Indicates not first page of document CLRB $ULOSW ; No underlining CLRB $PAGBR ; INDICATES AT TOP OF PAGE TSTNEB $SBPSW,100$ ; Currently in subpage ? CALL TXDOUT ; Check for deferred text output 100$: SUB TX2BF+BF.VSP,LINEC3 ; Subtract off saved lines BGE 120$ ; Is it OK ? BITEQ #TEXF,F.1,120$ ; No text ? TSTNEB $PAGBR,1$ ; text on page ? 120$: BIC #PARF,(SP) ; No paragraph deferred CLR PARDFO BITNE #FOTF,(SP),130$ ; Footnote in progress ? CALL OUTL0 ; Dump rest of paragraph 130$: MOV (SP)+,F.1 ; Get flags CLC ; page break indicated RETURN ; ; Output page header ; BPAG2: CALL VARSAV ; Save all necessary variables CALL STKSAV BIC #FOTF!TEXF!TXDEF!PARF,F.1 ; Remove inconvenient flags ADD $EOPSP,LINEC1 ; restore bottom lines MOVB #SUBLEV*4,SUBSTK+1 ; Set up for extra levels of nesting MOV #HDSTAT,R2 ; Header status buffer CALL RSTAT ; Get header status MOV #1,PHSP ; Set permanent horiz spacing CLR INDCT ; Clear indentation MOV PRMRG,RMARG ; Use permanent margins MOV PLMRG,LMARG ; Use permanent margins BIS #FILLF,F.1 ; Set fill BIC #JUSTF,F.1 ; No justify BISB #SW.TDS,$UNLSW ; Set underlining off CLRB $ULOSW ; No underlining of headers! TSTNEB $FIRPG,30$ ; First page? BITEQB #LAY.NB,$LAYOU,30$ ; Not number at bottom of page? MOV LINEC1,R2 ; Lines remaining this page SUB #LINSP,R2 ; Compensate for number to print BLE 10$ ; None? CALL $SKIP ; Skip em 10$: CALL HDMRG ; Set up left margin CALL HDPAG ; Get page to output MOV #LINSP,R2 ; Skip 1 line CALL $SKIP ; To end number at bottom of page 30$: CALL FORM ; OUTPUT FORMFEEDS OR LINEFEEDS MOV TMARG,R2 ; LINES TO SKIP BLE 40$ ; NONE CALL $SKIP ; SKIP N LINES 40$: TSTNEB $HDRSW,90$ ; NO HEADERS TO BE PRINTED? CALL HDMRG ; Set up left margin TSTNEB $NTITL,50$ ; no title? MOV #TTLBF,R3 ; HEADER BUFFER CALL CENTIT ; Center title if necessary 50$: BITNEB #LAY.NB,$LAYOU,60$ ; Page number at bottom? CALL HDPAG ; Get page number 60$: MOV #LINSP,R2 ; LINES TO SKIP CALL $SKIP ; DO IT TSTNEB $NTITL,70$ ; no title? MOV #STLBF,R3 ; OUTPUT THE SUBTITLE, IF ANY CALL HDMRG ; Set up margins CALL CENTIT ; Center the subtitle? 70$: MOV HSPAC,R2 ; LINES TO SKIP BGT 80$ MOV #LINSP,R2 ; Only 1 skip 80$: CALL $SKIP ; DO IT 90$: RETURN ; ; Get margin and space over to it ; HDMRG: CLR ESMSK ; No escape seq yet. CALL VARSET MOV EBSIZ1,R2 ; SPACE FOR CHANGE BAR OFFSET ADD EBSIZ2,R2 ADD RIGSHI,R2 ; ADD ON RIGHT SHIFT ADD PLMRG,R2 ; Add on Permanent left margin CALL NSPAC ; SPACE TO MARGIN RETURN ; ; ; Subroutine to form title/subtitle for output ; CENTIT: CALL BEGBF ; Start at beginning of buffer MOV CASE,-(SP) ; Save case CLR -(SP) ; Offset to account for CMPNE R3,#TTLBF,1$ ; Not title buffer BIS TTLCAS,CASE ; Set up case BITNEB #LAY.NB,$LAYOU,2$ ; Page number at bottom? MOV #10.,(SP) ; Make room for it SUB (SP),LINBK ; For page number 1$: BIS STLCAS,CASE ; Set subtitle case 2$: MOV R3,R2 ; Set up to get data as input MOV BUFAD,-(SP) ; Save input buffer address MOVB SUBSTK,-(SP) ; Save substitute stack MOV #TTBF,R3 ; Will be output buffer CALL CLRBF CALL TMPINB ; Set up temporary input BCS 5$ ; None ?? BISB #SW.HDR,$EQFSW+1; Prevent equations BISB #SW.HDR,$IFLSW+1; Prevent indexing BISB #SW.HDR,$TABSW ; Prevent tabs CALL GCIN ; Get input BICB #SW.HDR,$TABSW ; Allow tabs BICB #SW.HDR,$IFLSW+1; Allow indexing BICB #SW.HDR,$EQFSW+1; Allow equations TST LINBK ; Check chars count left BGE 5$ ; OK ? CALL BKOUT ; Backup output 5$: MOVB (SP)+,SUBSTK ; Restore MOV (SP)+,BUFAD ; Restore ADD (SP)+,LINBK ; For page number MOV (SP)+,CASE ; Restore MOV LINBK,R2 ; get remaining char count BLE HDPRN ; None to do BITNEB #LAY.CT,$LAYOU,10$ ; Center title? BITNEB #LAY.RT,$LAYOU,20$ ; Right title BITEQB #LAY.OT,$LAYOU,HDPRN ; No odd even layout BITEQB #1,PAGENO,HDPRN ; Not odd page number? BR 20$ ; Shift to right justify 10$: CLC ASR R2 20$: CALL NSPAC ; Space over to margin HDPRN: MOV ESMSK,R4 ; Get escape mask CALL ESCEND ; Terminate escapes CLR ESMSK ; No escape seq MOV #1,PHSP ; Reset permanent spacing BISB #SW.TDS,$UNLSW ; Set underlining off CALL PSTRPA JMP UNLOUT HDPAG: TSTNEB $NUMSW,60$ ; NO PAGE NUMBER? MOV #TTBF,R3 ; GET TEMPORARY BUFFER CALL CLRBF ; CLEAR IT TSTNEB $PAGSW,50$ ; OUTPUT 'PAGE'? MOV #PAGHD,R2 ; PAGE HEADER CALL HDOUT ; MOVE IT TO BUFFER 50$: CLR BF.SPC(R3) ; Reset space count CALL PUTPAG ; PUT PAGE INTO BUFFER ALSO SUB BF.SPC(R3),LINBK; And subtract from remaining MOV #PAGH2,R2 ; And second header CALL HDOUT ; Put it also MOV LINBK,R2 ; Number of chars left BLE HDPRN ; None ? BITNEB #LAY.CP,$LAYOU,51$ ; Centered page number? BITNEB #LAY.LP,$LAYOU,HDPRN ; left page ? BITEQB #LAY.OP,$LAYOU,55$ ; No odd even layout BITEQB #1,PAGENO,HDPRN ; Not odd page number? BR 55$ 51$: CLC ASR R2 ; Center it 55$: CALL NSPAC ; SPACE TO PAGE NUMBER BR HDPRN ; OUTPUT STRING IN BUFFER 60$: RETURN ; ; Output headers ; HDOUT:: TSTEQB (R2),20$ ; No header to output MOV BUFAD,-(SP) ; Save input buffer address MOVB SUBSTK,-(SP) ; Save substitute stack CALL TMPIN ; Set up temporary input buffer BCS 10$ ; None ?? BISB #SW.HDR,$EQFSW+1; Prevent equations BISB #SW.HDR,$IFLSW+1; Prevent indexing BISB #SW.HDR,$TABSW ; Prevent tabs MOV F.1,-(SP) ; Save BIC #FILLF,F.1 ; No fill from literal CALL GCIN ; Get input MOV (SP)+,F.1 BICB #SW.HDR,$TABSW ; Allow tabs BICB #SW.HDR,$IFLSW+1; Allow indexing BICB #SW.HDR,$EQFSW+1; Allow equations 10$: MOVB (SP)+,SUBSTK ; Restore MOV (SP)+,BUFAD ; Restore 20$: RETURN ; ; SSTAT saves status (flags,switches,caps mode etc.) ; RSTAT restores status ; R2=address of STSIZE word block to contain status ; R0,R1 destroyed ; SSTATS save status on stack ; R0-R2 destroyed SSTATS::MOV (SP),R0 ; Return address SUB #STSIZE*2,SP ; Set up stack MOV R0,(SP) ; Set up return MOV SP,R2 ; Where to save status TST (R2)+ ; Beginning of table CALL SSTAT ; Store status CALL @(sp)+ ; Come back later MOV SP,R2 ; Restore status CALL RSTAT MOV R2,SP ; Restore stack RETURN SSTAT:: MOV R3,-(SP) ; Save regs MOV #switS,R1 ; swit address MOV #NswitS,R3 ; Size of table MOV R3,(R2)+ ; start of status CLR (R2) ; Set up this entry MOV #1,R0 30$: BITB #SW.DIS,(R1)+ ; Check swit BEQ 40$ ; No bit ? BIS R0,(R2) ; Set bit in mask 40$: ASL R0 ; Next mask SOB R3,30$ TST (R2)+ ; Next entry in table MOV F.1,(R2)+ ; Save status MOV CASE,(R2)+ ; And case MOV (SP)+,R3 RETURN RSTAT:: MOV R3,-(SP) ; Save regs MOV #switS,R1 ; swit address MOV #NswitS,R3 ; Size of table CMPNE R3,(R2)+,50$ ; Not correct status MOV (r2)+,R0 30$: ASR R0 ; Get bit BCC 40$ ; No bit ? BISB #SW.DIS,(R1)+ ; Set status bit BR 45$ 40$: BICB #SW.DIS,(R1)+ 45$: SOB R3,30$ MOV (R2)+,F.1 ; restore status MOV (R2)+,CASE ; And case 50$: MOV (SP)+,R3 ; Restore RETURN ; ; This saves all necessary variables ; R0,R1,R2 are destroyed ; VARSAV::MOV #SAVBEG,R0 ; Variables to save MOV #SAVSZ/2,R1 ; Number of variables MOV (SP)+,R2 ; Return address 10$: MOV (R0)+,-(SP) ; Save the variables SOB R1,10$ ; Till done MOV R0,-(SP) MOV R2,-(SP) CALL @(SP)+ ; Back to main prog MOV (SP)+,R0 ; Variables to save MOV #SAVSZ/2,R1 ; Number of variables 20$: MOV (SP)+,-(R0) ; Save the variables SOB R1,20$ ; Till done RETURN STKSAV::MOV (SP)+,R0 ; Return address MOV SUBSTK,-(SP) ; Save status MOV R0,-(SP) ; Return address CALL @(SP)+ ; Back to main prog MOV (SP)+,SUBSTK ; status RETURN PARTP:: MOV PARSP,R1 ; Paragraph line spacing CALL SKPLIF ; Skip if not at top of page MOV PARIND,INDCT ; SET INDENTATION PART0:: MOV PARPT,R1 ; Get test page count PART1:: CALL MULSP ; Get total lines MOV R1,R5 ; Top count saved MOV PARTT2,R1 ; Deferred lines CALL MULSP ; Calculate deferred line spacing MOV R1,R4 ; Save it PARTS:: BITNE #FOTF!TEXF,F.1,10$ ; No allowed during footnote or text TSTNEB $PAGNG,10$ ; Not allowed during no paging MOV R4,R1 ; Post count CMP R1,NSPNG ; Is it trivial BLE 5$ ; Yes ? MOV R1,PARDFB ; Save line spacing MOV R1,PARDFT ; Save line spacing SUB NSPNG,R1 ; Subtract 1 line MOV R1,PARDFH ; Save line spacing CMP R5,NSPNG ; Top trivial ? BLE 5$ ; Yes ADD R5,R4 ; Top + bottom CMP R4,LINEC3 ; Enough room ? BLE 5$ ; Yes ? MOV R4,PARDFT ; Set separate top MOV LINEC3,R1 ; Number of lines left SUB R5,R1 MOV R1,PARDFH ; Set hyphenation inhibit 5$: MOV R5,R1 ; Get final value TSTEQB $PAGBR,10$ ; Already at top of page? JMP TESTP ; TEST AND OUTPUT PAGE IF NECESSARY 10$: RETURN ; ; ; START OF RUNOFF ; START: CALL $START ; Set up to receive commands RUNOFF::MOV SPSAV,SP ; Reset stack CALL INITL ; INITIALIZE VARIABLES JMP RESTRT ; Continue .END START