.TITLE RUNOFF .IDENT /BL3.6/ ; ; COPYRIGHT (C) 1976 ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A ; SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY WITH THE INCLU- ; SION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE, OR ANY ; OTHER COPIES THEREOF, MAY NOT BE PROVIDED OR OTHERWISE MADE ; AVAILABLE TO ANY OTHER PERSON EXCEPT FOR USE ON SUCH SYSTEM ; AND TO ONE WHO AGREES TO THESE LICENSE TERMS. TITLE TO AND ; OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES REMAIN IN DEC. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT ; NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL ; EQUIPMENT CORPORATION. ; ; DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS ; SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC. ; ; VERSION M02 ; ; AUTHOR: L. WADE 1-JUN-72 ; ; MODIFIED BY: ; ; E. POLLACK U. OF W. 19-DEC-73 ; ; D. N. CUTLER 27-JUL-75 ; ; SIG MODIFICATIONS ; SIG01 CLEAN UP OPERATOR WAIT ; SIG02 RSTS CHANGES ; ; CARTS LUG MODIFICATIONS ; CAR 1 ADD CHANGE BARS AND RIGHT SHIFT FUNCTION ; ; 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 INI$SW:: .WORD HYPSW!SPLSW!CRSW ; INITIAL VALUE FOR $SWTCH IUL:: .WORD 'N ; INITIAL UNDERLINE SWITCH IPARIN:: .WORD 5 ; INITIAL PARAG INDENTATION HWLPP:: .WORD HWPLN ; INITIAL VALUE FOR LPPG .PSECT $VARS,LCL,RW,D,CON ; ; General input switches and variables ; VARBEG:: ; This marks first variable F.1:: .BLKW 1 ; Flag word $HDRSW:: .BLKB 1 ; DISABLE PAGE HEADER (0=NO) $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 (0=NO BACKSPACE) $ULNSW:: .BLKB 1 ; UNDERLINE SUPPRESS (0=NO) $ULSSW:: .BLKB 1 ; UNDERLINE SIMULATE (0=NO) $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 EOFSW:: .BLKB 1 ; NON ZERO IS END OF FILE $GCEND:: .BLKB 1 ; Non zero for immediate input stop $BFSTC:: .BLKB 1 ; SETBF, keep line intact if non zero $AUTSW:: .BLKB 1 ; Autoparagraph active (0=NO) $AUTTL:: .BLKB 1 ; Autotitle active (0=yes) $AUSTL:: .BLKB 1 ; Autosubtitle (0=NO) $AUHYP:: .BLKB 1 ; Autohyphenation disabled (0=enabled) $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 $TOCSW:: .BLKB 1 ; Zero if TOC enabled $TOCBE:: .BLKB 1 ; Non zero if TOC Begun $OUTSW:: .BLKB 1 ; Zero if output enabled $PERSW:: .BLKB 1 ; Double spaces after punctuation (0=NO) $UNLSP:: .BLKB 1 ; underline spaces (0=NO) $EQUSW:: .BLKB 1 ; Equation mode on ? (0=yes) $NOSPC:: .BLKB 1 ; If non zero converts spaces to NXS $HSPSW:: .BLKB 1 ; If zero enables half spacing $TABPD:: .BLKB 1 ; Right justified tab pending .EVEN ; ; 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 .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 ; $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) $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 $NFLSW:: .WORD '. ; CONTROL FLAG $SPFLSW:: .WORD 0 ; Special flag word switch $EQFSW:: .WORD 0 ; Equation flag switch NFLAG== <$NFLSW-$AFLSW>/2 ; NUMBER OF FLAG SWITCHES ; ; ; ALL VARIABLES BETWEEN SAVBEG/SAVEND ARE SAVED DURING FOOTNOTING ; SAVBEG==. ; DISABLE SWITCHES (0=ENABLED) (200=DISABLED) (100=OFF)(1=OFF FOREVER) ; $ESCSW:: .BLKB 1 ; ESCAPE SEQUENCES DISABLED $SUBSW:: .BLKB 1 ; substitute disabled flag $UNLSW:: .BLKB 1 ; UNDERLINING OFF $OVRSW:: .BLKB 1 ; OVERSTRIKING DISABLED $HYPSW:: .BLKB 1 ; Non zero disable hyphenation $INXSW:: .BLKB 1 ; INDEXING ENABLED $CBRSW:: .BLKB 1 ; CHANGE BAR SWITCH $TABSW:: .BLKB 1 ; NON ZERO DISABLES TABS $CENSW:: .BLKB 1 ; NON ZERO = CENTER TEXT $RIGSW:: .BLKB 1 ; Non zero = right justify text .EVEN OVRCT:: .BLKW 1 ; COUNTS BACKSPACE ABORTS ESCCNT:: .BLKW 1 ; COUNTS ESCAPE SEQUENCES CASE:: .BLKB 1 ; -=LOWER CASE ONLY, +=UPPER CASE ONLY ; *** ULOCK:: .BLKB 1 ; SAVES PERMENANT CASE LOCK ; ; The following 3 variables are saved by permanent footnotes ; PFSBEG:: 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 ; LINE TEMPS SPCNT:: .BLKW 1 ; Expandable space count SPCNSV:: .BLKW 1 ; Same before last space BRCNT:: .BLKW 1 ; number of breaks this line CASSAV:: .BLKW 1 ; SAVE CASE AT LAST SPACE LINBK:: .BLKW 1 ; Line break count (+ no break) SPCH:: .BLKW 1 ; Number of spacing characters LSPCH:: .BLKW 1 ; Number of spacing chars before last space LUNLSW:: .BLKW 1 ; Underline switch at last space LCH:: .BLKB 1 ; LAST CHAR LSCH:: .BLKB 1 ; Last char before space (break) LSTSP:: .BLKW 1 ; Address of char before last space in output LTAB:: .BLKW 1 ; Address of last tab output count INDCT:: .BLKW 1 ; CURRENT INDENTATION CURVS:: .BLKW 1 ; Current vertical spacing MAXVS:: .BLKW 1 ; Max vertical spacing MINVS:: .BLKW 1 ; Min vertical spacing EBSIZ1:: .BLKW 1 ; Change bar initital indentation EBSIZ2:: .BLKW 1 ; Change bar second indentation LESMSK:: .BLKW 1 ; Last escape stack ESMSK:: .WORD 0 ; Address of current location in escape stack SAVEND=. SAVSZ==SAVEND-SAVBEG ; SIZE OF FOOTNOTE SAVE BUFFER ; ; MISC SWITCHES ; $NUMSW:: .BLKW 1 ; NUMBER PAGES (0=NO) TESMSK:: .BLKW 1 ; Temporary escape mask $PAGSW:: .BLKW 1 ; OUTPUT 'PAGE' SWITCH (0=YES) $CHPSW:: .BLKW 1 ; output chapter (0 = yes) $SBPSW:: .BLKW 1 ; SUBPAGE MODE ACTIVE (0=NO) ; ; ADDRESS POINTERS ; ERSTR:: .BLKW 1 ; SAVES ADDRESS OF STRING LNINS:: .BLKW 1 ; ADDRESS OF LAST CHAR IN LINE LSPIN:: .BLKW 4 ; ADDRESSES OF LAST INPUT SPACE LSSTK:: .BLKW 1 ; last input stack value $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 PHSP:: .BLKW 1 ; Permanent 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 $FIGDF:: .BLKW 1 ; Number of lines to skip deferred 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 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 CMADR:: .BLKW 1 ; SPECIAL PROCESSING COMMAND ADDRESS PARPT:: .BLKW 1 ; Paragraph page test count PARSP:: .BLKW 1 ; Paragraph spacing count PARIND:: .BLKW 1 ; Paragraph indentation LINEC1:: .BLKW 1 ; Number of lines left to bottom active page LINEC2:: .BLKW 1 ; Number of lines left this page LINEC3:: .BLKW 1 ; Number of free lines left this page TEXLN:: .BLKW 1 ; Number of deferred text lines FOTLN:: .BLKW 1 ; Number of lines permanent footnote PFOTX:: .BLKW 1 ; Permanenat footnote index PFOTHD:: .BLKW 1 ; Permanent footnote header LITCM:: .BLKW 1 ; SAVED EXPECTED COMMAND ADDRESS (LITERAL) LITSV:: .BLKW 1 ; SAVED FLAGS MASK ON LITERAL PROCESSING LSTVS:: .BLKW 1 ; LIST ELEMENT VERTICAL SPACING LSTKP:: .BLKW 1 ; CURRENT LIST STACK POINTER LSTK:: .BLKW 5*5 ; LIST STACK (5 lists by 5 saved variables) TKPEND:: .BLKW 2 ; End of list stack LSTCT:: .BLKW 1 ; CURRENT LIST ELEMENT COUNT NOTCM:: .BLKW 1 ; SAVED EXPECTED COMMAND ADDRESS (NOTE) NOTLM:: .BLKW 1 ; NOTE SAVED LEFT MARGIN NOTRM:: .BLKW 1 ; NOTE SAVED RIGHT MARGIN NOTSV:: .BLKW 1 ; SAVED FLAG WORD ON NOTE PROCESSING 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 CPOS:: .BLKW 1 ; CURRENT CHAR POSITION XFIRST:: .BLKW 1 ; First index entry (first in alphabet) EQSTK:: .BLKW 60. ; Equation stack EQSEN:: ; End of equation stack FOTSV:: .BLKB SAVSZ+4 ; FOOTNOTE SAVE PARAM TABLE PFTSV:: .blkb PFSIZ+2 ; 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 ; PERMENANT MAX LINES/PAGE VAREND:: .BLKW 1 ; end of variables .psect TEXT,RO,D,LCL,CON ONPGTX: .ASCIZ / page / ONLNTX: .ASCIZ /On or after output line / JUSRM1: .ASCIZ /RNO -- Can't justify line/ EQERTX: .ASCIZ /RNO -- Missing right braces in equation/ OPRTXT: .ASCIZ <7>/ /<15>/ /<15>/ /<7> ; Message to wake up operator (page wait) UPTAB:: .BYTE ESC,2 ; Multiple escape processing UPMOV:: .BYTE ESC,'D,0 ; Move text up 1/2 space DNTAB:: .BYTE ESC,2 DNMOV:: .BYTE ESC,'U,0 ; Move text down 1/2 space .PSECT $CODE,RO,I,LCL,CON ; ; INPUT LINE ; LINUC:: CALL SHFUC ; Get input in Uppercase LIN:: CALL OUTAD ; GET OUTPUT BUFFER ADDRESS CALL GCIN ; Get input text CMPNEB R1,#LF,10$ ; NOT LINE FEED RETURN 10$: TSTEQ BRCNT,70$ ; NO SPACES TO ALLOW HYPHENATION CMPEQB LCH,#SPC,60$ ; Last char space? TST LINBK ; Line <= max length? BGE 70$ ; yes, keep it intact TSTNEB $HYPSW,60$ ; No hyphenation ? ; Inhibit hyphenation at bottom of page MOV LINEC3,R1 ; Check if at bottom of page SUB #LINSP,R1 ; Subtract space necessary BLT 12$ ; Past the bottom ? SUB NSPNG,R1 ; Now is lines - 1 BLT 60$ ; Current line at bottom of current ? 12$: MOV LSTSP,R1 ; LAST SPACE INC R1 ; PLUS 1 SUB R1,LNINS ; Number of chars from end of lin BLE 60$ ; None so no hyphenation CALL FNDBF ; SET POINTER TO IT MOV #TTBUF,R2 ; GET TEMPORARY BUFFER MOV #50.,R4 ; MAX NUMBER OF CHAR 14$: CALL GBYT ; GET CHARACTER BCS 17$ ; DONE BIT #140,R1 ; PRINTABLE CHAR? BNE 15$ ; Yes DEC LNINS ; Decrement char count to test BEQ 60$ ; No hyphenation BR 14$ ; ignore non printable 15$: MOV R1,R0 ; Save BIC #^C<177>,R0 ; clear extra bits CMPNEB GCTABL(R0),#GC.UC,16$ ; not uppercase ? ADD #40,R1 ; make it lowercase 16$: MOVB R1,(R2)+ ; SAVE CHAR SOB R4,14$ ; CONTINUE TILL DONE 17$: CLRB (R2)+ ; NULL FOR END OF STRING MOV #TTBUF,R0 ; BUFFER WITH HYPHENATION INFO TSTNEB $AUHYP,20$ ; USER SPECIFIED HYPHENATION? CALL HYPHEN ; TRY TO HYPHENATE THE WORD MOV #TTBUF,R0 20$: BICB #SW.TDS,$AUHYP ; Temporarily enable auto hyphenation MOV LNINS,R4 ; Char count BLE 60$ ; NO HYPHENATION ADD R4,R0 ; POINTS TO END OF WORD 30$: TSTB -(R0) ; HYPHENATION? BMI 40$ ; YES SOB R4,30$ ; CONTINUE TILL DONE BR 60$ ; NO HYPHENATION 40$: CMP R4,#2 ; ENUF CHAR? BLT 60$ ; NO MOV R4,LINBK ; NUMBER OF CHAR TO TRANSFER CALL BKUP ; BACKUP TO LAST SPACE DECB $GCEND ; Immediate return on LINBK=0 CALL GCSPC ; AT BEGINNING INSERT SPACE CLRB $GCEND ; Regular return restored MOV #'-,R1 ; INSERT HYPHEN CALL PBYT ; OUTPUT IT INC SPCH ; ONE MORE CHAR BR 70$ ; hyphenation done 60$: CALL BKUP ; BACKUP TO CORRECT LOCATION 70$: CALL OUTLIN ; OUTPUT LINE,JUSTIFIED IF FLAGS 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: 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 CALL OUTAD ; OUTPUT BUFFER ADDRESS BKOUT: MOV LSTSP,R1 ; LAST SPACE ADDRESS CALL RSTBF ; GO BACK TO PREVIOUS POINT IN BUFFER 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 DEC BRCNT ; One fewer break 10$: RETURN ; ; The .NO SPACE COMMAND ; NOSPC:: CMPNE LCH,#SPC,10$ ; Last char space ? BITNE #FILLF,F.1,BKOUT ; Fill on ? 10$: RETURN ; ; ENDBCM--END OF BREAK COMMAND ; ENDBCM::CALL LINSET ; SET FOR NEW LINE (BREAK COMMAND) ; ; 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,LCR ; 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,LCR ; 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 FILE CHARACTER LCR1: CMPNE R1,#LF,LCR ; NOT A LINEFEED? ;+ ; READ AND PROCESS NEXT LINE ;- .ENABL LSB 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? BIC #TEXF,F.1 ; No deferred text now CALL OUTNJ ; FLUSH OUT LAST LINE TSTEQ $FIGDF,10$ ; No deferred figures ? CALL PAGEC 10$: MOVB #-1,$HDRSW ; SET NO HEADER CLR TMARG ; No top margin CALL PAGEC ; FORCE A PAGE JMP ENDFIL ; END OF FILE 20$: CMPEQ R1,#LF,LGO ; FORMFEED ON INPUT? BITNE #LITFG,F.1,70$ ; PROCESSING LITERAL? BITEQ #FILLF,F.1,60$ ; NOT FILLING FROM INPUT FILE? TSTEQB $AUTSW,60$ ; AUTOPARAGRAPH NOT ACTIVE? CMPEQ #CR,R1,40$ ; NULL LINE? CMPEQ #TAB,R1,30$ ; LEADING TAB? CMPNE #SPC,R1,70$ ; NOT LEADING SPACE? 30$: CALL CCIN ; READ NEXT CHARACTER CMPEQ #SPC,R1,30$ ; SPACE? CMPEQ #TAB,R1,30$ ; TAB? CMPNE #CR,R1,50$ ; NOT CARRIAGE RETURN? 40$: CALL CCIN ; BYPASS LINE FEED 45$: CALL CCIN ; READ NEXT CHARACTER MOV BUFADD,R0 ; INPUT BUFFER HEADER MOV BF.ADD(R0),ERSTR ; SAVE FOR ERROR OUTPUT CMPEQ #SPC,R1,45$ ; SPACE? CMPEQ #TAB,R1,45$ ; TAB? CMPEQ $NFLSW,R1,90$ ; LEADING PERIOD? 50$: CALL OUTNJ ; BREAK CURRENT LINE CALL PARTP ; PERFORM PARAGRAPH BREAK CALL LINSET ; RESET LINE PARAMETERS BR TEXT ; PROCESS TEXT 60$: CMPEQ #CR,R1,LCR ; NULL LINE? 70$: CMPEQ R1,$NFLSW,90$ ; PERIOD AS FIRST CHAR? 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,85$ ; Filling from input file? 81$: CALL OUTNJ ; Output either not just, cent, or right just. 85$: CALL LINBEG ; Set up beginning of line TEXTF:: CALL LIN ; Start input BR LGO ; End of input line 90$: 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 MOV #ENDBCM,4(SP) ; SET FOR BREAK COMMAND 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 .DSABL LSB ; ; ERROR OUTPUT ; HLTER:: MOV #9.,R0 ; Error message BR ILINP ; And kill program ILINP:: CALL ERMSG ; Output error message 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 #LCR,(SP) ; FINISH UP SECTION ILMSG:: CALL ERMSG ; Output error message ONLIN:: MOV BUFADD,R3 ; GET CURRENT BUFF ADDRESS MOV ERSTR,R1 ; POINTS TO BUFFER MOV BF.ADD(R3),R2 ; CURRENT CHAR ADDRESS SUB R1,R2 ; NUMBER OF BYTES INC R2 CMP R2,#79. ; OK? BLE 10$ ; YES MOV #79.,R2 ; YES 10$: CALL TTOUT ; PRINT OFFENDING LINE CALL TTINOU ; Type whole line for ident. ONPAG:: MOV #TTBF,R3 ; BUFFER FOR OUTPUT CALL CLRBF ; CLEAR BUFFER MOV #ONLNTX,R0 ; On line text string CALL PSTRZB ; MOVE IT TO BUFFER MOV LPPG,R0 ; Lines/page SUB LINEC2,R0 ; - distance to bottom CALL DECTY ; Convert to number MOV #ONPGTX,R0 ; ON PAGE STRING CALL PSTRZB ; Into buffer CALL PUTPAG ; PUT PAGE NUMBER INTO BUFFER MOV #15,R1 ; Carriage ret CALL PBYT MOV #12,R1 ; Line feed CALL PBYT MOV #TTBUF,R1 ; BUFFER ADDRESS MOV BF.FUL(R3),R2 ; SIZE OF STRING JMP TTOUT ; OUTPUT IT ; ; 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 TSTEQ $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 ; ; 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$: CALL $DIV ; get rhand digit 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 PBYT 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 80$: TSTEQ R0,110$ ; done yet? MOVB (R2)+,R1 ; get next numeral value TSTB (R2)+ ; skip over letter CALL $DIV ; convert TSTEQ R1,80$ ; none this letter? CMPEQ R1,#4,100$ ; reversed letters? 90$: MOVB -1(R2),-(SP) ; save letters SOB R1,90$ ; till done BR 80$ 100$: MOVB 1(R2),-(SP) ; output next higher letter MOVB -1(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 PBYT ; save in buffer INC BF.SPC(R3) ; Count spacing chars BIC #10000,R4 ; set lower? after first byte BR 110$ RMTAB: .BYTE 5,'I, 2,'V, 5,'X, 2,'L, 5,'C, 2,'D,5,'M ; ; CONVERTS R0 TO NUMERIC STRING ; R3=BUFFER HEADER TO PUT STRING ; DECTY: CLR -(SP) ; SET INDICATOR 10$: MOV #12,R1 ; SET DIVISOR CALL $DIV ; DIVIDE 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 PBYT ; 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 ; ; SUBROUTINE TO INITIALIZE COUNTS AND POINTERS FOR A NEW LINE ; LINSET::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 PERMENANT CASE CLR BRCNT ; no breaks yet this line CLR SPCNT ; INITIAL COUNTS OF SPACING CLR SPCNSV CLR SPCH ; AND NON-SPACING CHARS CLR LSPCH MOV ESMSK,LESMSK ; Current end of escape stack MOVB $UNLSW,LUNLSW ; Save underline switch CLR ESCCNT ; NO ESCAPES PENDING CLR OVRCT ; NO BACKSPACE ABORTION MOV #1,CPOS ; CARRIAGE POSITION IS FAR LEFT CLR LCH ; CLEAR LAST CHARACTERs CLR LTAB ; Address of last tab char CLRB $TABPD ; Set no tab pending CALL OUTAD ; GET OUTPUT BUFFER ADDRESS BITNE #FOTF!TEXF,F.1,10$ ; Footnote or text in progress? CALL CLRBF ; RESET IT BR 20$ ; 10$: MOV BF.HED(R3),R1 ; GET ADDRESS OF CURRENT HEADER ADD #BFHED-1,R1 ; POINT TO START OF TEXT CMPEQ R1,BF.FUL(R3),40$ ; SAME? (ALREADY SET) 20$: MOV BF.FUL(R3),BF.HED(R3) ; LAST HEADER ADDRESS INC BF.HED(R3) ; CORRECT ADDRESS MOV #BFHED,R2 ; NUMBER OF TIMES THRU CLR R1 ; NULL FOR HEADER 30$: CALL PBYT ; DEPOSIT PART OF HEADER SOB R2,30$ ; TILL DONE 40$: MOV BF.FUL(R3),LSTSP ;SET LAST SPACING CHARACTER BACK HERE CLR BF.SPC(R3) MOV CASE,CASSAV ; SAVE CASE 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 ; ; BEGINS A LINE OR CONTINUES LINE AFTER COMMANDS BY SETTING FLAGS ; LINBEG: CALL OUTAD ; GET OUTPUT ADDRESS TSTNEB $CBRSW,10$ ; NO CHANGE BAR NEEDED? MOV BF.HED(R3),R1 ; HEADER BYTE INC R1 ; points to status bits CALL FNDBF ; get the location BISB #1,@BF.ADD(R3) ; SET CHANGE BAR BIT CALL ENDBF ; go to end of buffer 10$: MOV #ULEND,R1 ; SET UNDERLINING OFF TSTNEB $UNLSW,20$ ; IS IT OFF? MOV #ULBEG,R1 ; NO, TURN IT ON TSTEQB $UNLSP,20$ ; no underline spaces? MOV #ULSBG,R1 ; underline spaces 20$: CALL PBYT ; SET UNDERLINING ON OR OFF MOV ESMSK,R4 ; Escape sequences locked on BEQ 30$ ; None ? MOV BF.FUL(R3),R1 ; Current location SUB BF.HED(R3),R1 ; Subtract off header CMP R1,#BFHED ; Escapes already taken care of ? BGT 30$ ; Yes ? CALL ESCBEG ; Begin them 30$: RETURN ; ; ; RESET UNDERLINE BUFFER ; ULBSET:: TSTNEB $ULNSW,20$ ; UNDERLINE SUPPRESSED? TSTNEB $ULMSW,20$ ; UNDERLINE BY BACKSPACE? MOV #UBUFF,R0 ; UNDERLIN BUFFER MOV #ULNSZ,R1 ; SIZE OF BUFFER 10$: MOVB #SPC,(R0)+ ; PUT SPACE INTO IT SOB R1,10$ ; TILL FULL CLR ULNMAX 20$: RETURN ; ;+ ; RCNR--RELATIVE DECIMAL CONVERSION ROUTINE ; ; INPUTS: ; ; R3=BASE VALUE TO BE AUGMENTED. ; ; OUTPUTS: ; ; NONSKIP RETURN IF NO NUMBER IS PRESENT. ; ; SKIP RETURN WITH R3 UPDATED TO NEW VALUE. ;- .ENABL LSB RCNR:: MOV R3,-(SP) ; SAVE BASE VALUE CALL RCNO ; CONVERT DECIMAL NUMBER JMP 40$ ; NONSKIP RETURN IF NULL BEQ 30$ ; IF EQ NO SIGN SPECIFIED ADD (SP),R3 ; AUGMENT BASE VALUE BR 30$ ; SKIP RETURN ; ; READ SIGNED DECIMAL NUMBER FOR COMMAND DECODER ; NON-SKIP RETURN IF NONE FOUND ; RCNO:: CLR R3 ; CLEAR ANSWER AC CLR R5 ; Count number of chars converted CLR -(SP) ; AND SIGN FLAG CALL SKPSP ; skip spaces BCS 40$ ; null param CMPNE #'+,R1,10$ ; NOT PLUS SIGN? INC (SP) ; SET PLUS SIGN PRESENT 10$: CMPNE R1,#'-,20$ ; NOT MINUS SIGN? COM (SP) ; SET NEGATE FLAG 20$: TSTEQ (SP),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 TST (SP) ; NEGATIVE SIGN? BPL 30$ ; IF PL NO NEG R3 ; NEGATE NUMBER 30$: ADD #4,2(SP) ; SET SKIP RETURN 40$: TST (SP)+ ; CLEAN STACK RETURN ; .DSABL LSB 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 CALL $MUL ; mult R0 by R1 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 ; 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$: MOV BUFADD,R0 ; GET BUFFER HEADER MOV R1,-(SP) ; char to compare MOV BF.ADD(R0),R2 ; ADDRESS OF START OF BUFF INC R2 ; FIRST BYTE 20$: CALL CCIN ; NEXT CHAR BCS 50$ ; NO MORE CMPEQB R1,(SP),30$ ; END OF LITERAL? CMPNE R1,#CR,20$ ; not end of buffer? CALL BKSPI ; backspace over carriage return 30$: MOV BUFADD,R0 ; BUFFER ADDRESS TST (SP)+ ; unstack test char MOV BF.ADD(R0),-(SP) ; SAVE CURRENT ADDRESS 31$: CALL CCIN ; GET NEXT CHAR CALL NEXPAR ; SKIP TO NEXT PARAM MOV (SP)+,R1 ; LAST CHAR IN LIT +1 ADDRESS 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: MOVB #-1,TJFSW ; SET JUSTIFYY FLAG COMB EXSP4 TSTNEB $CENSW,OUTNJ ; CENTERED/NOT JUSTIFIED? TSTNEB $RIGSW,OUTNJ ; Not justify if right justified BITNE #JUSTF,F.1,OUTJ2 ;JUSTIFYING? OUTNJ:: CLRB TJFSW ; CLEAR JUSTIFY FLAG CLRB EXSP4 ; CLEAR LEFT RIGHT SPACING CLRB EXSP2 CLRB EXSP1 OUTJ2: CALL OUTAD ; Get address of header MOV BF.HED(R3),R0 ; ADDRESS OF HEADER ADD #BFHED-1,R0 ; NOW POINTS TO TEXT CMPNE R0,BF.FUL(R3),1$ ; Text present to output ? JMP LINSET ; NO, RESET 1$: BITEQ #FILLF,F.1,2$ ; No fill ? TSTEQ SPCH,3$ ; No spacing chars ? 2$: CALL TESTL ; Test and break page if necessary 3$: CALL OUTAD ; GET BUFF ADDRESS CMPEQ EQSTK,#EQSTK+2,10$ ; Is equation 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 BICB #20,$TABSW ; Allow tabs BICB #20,$NOSPC ; And expandable spaces 10$: MOV ESMSK,R4 ; Escapes locked on BEQ 11$ ; None ? 11$: CALL ESCEND TSTEQB TJFSW,OUTNJ1 ; NOT JUSTIFYING LINE? CLRB TJFSW ; IN CASE TST SPCNT ; YES, ANY SPACES IN LINE? BGT 30$ ; IF GT YES MOV #JUSRM1,R0 ; Can't justify line message CALL EROUT ; Output message CALL ONLIN ; INDICATE WHAT PAGE BR OUTNJ1 ; 30$: MOV SPCNT,R1 ; NOW FIND HOW MANY MULT SPACES EACH SPACE IS 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 ADD R1,R0 ; ADD NUMBER OF SPACES CALL $DIV ; DIVIDE MOVB R0,EXSP1 ; MULTIPLIER FOR ALL SPACES TSTNEB EXSP4,40$ ; EXTRAS TO LEFT? NEG R1 ; RIGHT. GET SPACES BEFORE EXTRAS ADD SPCNT,R1 ; .. 40$: MOVB R1,EXSP2 ; STORE FOR LATER OUTNJ1: CALL OUTAD ; GET BUFF ADDRESS MOV BF.HED(R3),R1 ; GET LIN HEADER CALL FNDBF ; get buffer location TSTNE SPCH,4$ ; Any spacing chars ? BITEQ #FILLF,F.1,4$ ; No fill ? CLR R1 ; Set no characteristics CALL PBYT ; Into buffer BR 50$ ; Output but no skip at end 4$: MOV LMARG,R2 ; GET LEFT MARGIN TSTEQB $RIGSW,5$ ; 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 NEG INDCT ; Switch indentation 5$: ADD INDCT,R2 ; GET INDENTING IN CASE OF PARAGRAPH CLR INDCT ; (ONCE ONLY) TSTEQB $CENSW,10$ ; 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 10$: ADD EBSIZ2,R2 ; ADD ON CHANGE BAR SIZE CALL GBYT ; get status bit BITEQB #1,R1,20$ ; CHANGE BAR PENDING? DEC R2 ; 1 CHAR IS OUT SO STOP ITS SPACE 20$: 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 21$ ; Margin ok? CLR R1 ; No, make it 0 21$: 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 25$: CALL 50$ JMP SKIPS ; Set up next line skip 50$: CALL ENDBF ; go back to end of buffer CLR R1 ; Null terminates the line CALL PBYT ; Put at end of line BITNE #FOTF!TEXF,F.1,30$ ; Footnote or deferred text? CALL OUTL0 ; NO OUTPUT THE LINE 30$: JMP LINSET ; Reset line params ; ; DO ACTUAL OUTPUT TO PRINTER OF TEXT STRING ; OUTL0:: CALL OUTAD ; GET HEADER ADDRESS TSTNEB $OUTSW,100$ ; No output ? CALL BEGBF ; SET TO TOP OF BUFFER 10$: CLRB $ULOSW ; No underlining yet CALL GBYT ; GET BAR STATUS FIRST BCS 100$ ; DONE MOV R1,R2 ; Now is skip count BLE 20$ ; Skip count bad ? CALL $SKIP0 20$: CALL GBYT ; Get status MOV R1,-(SP) ; Save status CALL GBYT ; Get initial spacing MOV R1,R2 ; BIC #177400,R2 ; Clear extra bits CALL NSPAC ; Output n spaces BITEQB (SP)+,#1,30$ ; NO BAR? MOVB #'|,R1 ; NOPE CALL FOUT ; Output change bar INC CPOS ; Increment position counter 30$: CALL GBYT ; Spaces after bar 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 CCOUT ; Output + format text BCC 10$ ; Not end of buffer ? ; ; END OF LINE, AND FOOTNOTE PROCESSING ; 100$: CLRB EXSP1 ; Clear spacing controls CLRB EXSP2 CLRB EXSP3 BITEQ #FOTF,F.1,110$ ; No footnote in progress? MOV PFOTX,R1 ; Permanent footnote buffer index MOV PFOTHD,BF.HED(R3) ; Restore header address JMP RSTBF ; Reset to permanent bottom 110$: JMP CLRBF ; CLEAR THE BUFFER ; ; Subroutine to skip N text lines ; R1=skip count ; SKIPL is unconditional skip ; SKPLIF is conditions 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 ; SKIPS:: MOV NSPNG,R2 ; SET TO SKIP TO NEXT LINE BR SKIPN ; SKIP1:: MOV #LINSP,R2 ; SET TO SKIP ONE LINE SKIPN:: TST R2 ; TOO BIG? BLE SKRET ; YES DO NOT SKIP TSTB $PFOOT ; Permanent footnote not in progress? BGE 10$ ; No? ADD R2,FOTLN ; Count permanent footnote lines BR 40$ 10$: CMP R2,LINEC3 ; LINE COUNT BLT 30$ ; Skip count not too many ? MOV LINEC3,R2 ; Skip to bottom BGT 20$ ; Good skip? MOV #LINSP,R2 ; No, make it 1 20$: DECB $PAGPD ; New page pending 30$: SUB R2,LINEC3 ; Now line count BITEQ #FOTF!TEXF,F.1,$SKIP0 ; No footnote or deferred text? BITEQ #TEXF,F.1,40$ ; No deferred text ADD R2,TEXLN ; Count deferred line count 40$: CALL OUTAD ; GET BUFFER ADDRESS MOV BF.HED(R3),R1 ; GET LAST NUMBER OF LINES CALL FNDBF ; get the location MOVB @BF.ADD(R3),R0 ; get old skip ADD R2,R0 ; new skip MOVB R0,@BF.ADD(R3) ; TOTAL NUMBER NOW CALL ENDBF ; return buuffer to end SKRET: RETURN $SKIP: SUB R2,LINEC3 ; ADD LINES TO TOTAL $SKIP0: MOV R3,-(SP) ; SAVE R3 MOV R2,-(SP) ; SAVE NUMBER OF LINES TO BE OUTPUT INCB $PAGBR ; NOT AT TOP OF PAGE TSTNEB $ULMSW,50$ ; NO NEED TO CONSIDER SAVED UNDERLINES? TSTEQ ULNMAX,50$ ; NO UNDERLINES IN BUFFER? TSTNEB $ULNSW,50$ ; UNDERLINES SUPPRESSED? TSTNEB $OUTSW,40$ ; No output ? TSTEQB $ULSSW,10$ ; USE UNDERLINE CHARACTER? SUB #LINSP,LINEC3 ; ACCOUNT FOR EXTRA LINE CALL CRLF ; SPACE TO NEXT LINE BR 20$ ; 10$: MOV #CR,R1 ; OUTPUT A CARRIAGE RETURN BITEQB #CRSW,$SWTCH,15$ ; No CRLF output? CALL FOUT ; 15$: CALL OUTPUT ; Start a new line 20$: MOV #UBUFF,R3 ; GET UNDERLINE BUFFER MOV ULNMAX,R2 ; MAX CHAR 30$: MOVB (R3)+,R1 ; GET UNDERLINE CHAR CALL FOUT SOB R2,30$ ; TILL DONE 40$: CALL ULBSET ; RESET UNDERLINE BUFFER POINTER 50$: MOV #1,CPOS ; CLEAR CHAR POSITION INDICATOR BITEQ #1,(SP),55$ ; No half lines required ? DEC LINEC1 ; Account for half lines DEC LINEC2 MOV #DNMOV,R2 ; Get buffer to transfer 53$: MOVB (R2)+,R1 ; Get char BEQ 54$ ; Done ? CALL FOUT BR 53$ 54$: CALL OUTPUT ; Now output the line 55$: MOV (SP)+,R2 ; RESTORE NUMBER OF LINES BIC #1,R2 ; Clear half bit BLE 65$ ; No more to output 60$: CALL CRLF ; SPACE TO NEXT LINE SUB #LINSP,R2 ; Lines left BGT 60$ ; Not done ? 65$: MOV (SP)+,R3 ; RESTORE R3 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 ; ; ; SUBROUTINE PUTS CURRENT CHAR ADDRESS INTO R3 ; OUTAD:: BITEQ #FOTF,F.1,10$ ; NOT FOOTNOTE BUFFER? MOV #FOTBF,R3 ; GET FOOTNOTE BUFFER ADDRESS RETURN ; 10$: MOV #TX2BF,R3 ; NORMAL SECONDARY BUFFER RETURN ; ; ;ROUTINE TO SPACE TO TOP OF FORM ; FORM: CLRB $PAGPD ; No longer page pending TSTEQ $SBPSW,10$ ; NO SUBPAGE? MOVB SUBNX,SUBPGE ; set to current subpage MOV PAGNX,PAGENO ; now current page number INCB SUBNX ; yes increment it BNE 20$ ; Non zero? INCB SUBNX ; No, make it 1 BR 20$ 10$: MOV PAGNX,PAGENO ; now current page number INC PAGNX ; increment next page number BNE 20$ ; Non zero? INC PAGNX ; No, set to 1 20$: DECB $OUTSW ; Set for no output CMP PAGENO,LOWPAG ; ONLY PRINT IN THE SELECTED PAGE BLO 50$ ; RANGE CMPB CHPTN,LOWCHP ; chapter # too small? BLO 50$ ; yes CMPB APNDN,LOWAPN ; appendix too small? BLO 50$ ; yes CMP PAGENO,HGHPAG ; page number too big? BHI 23$ ; yes CMPB CHPTN,HGHCHP ; too big? BHI 23$ ; yes CMPB APNDN,HGHAPN ; appendix too big? BLOS 24$ ; No ? 23$: MOV #ENDFIL,(SP) ; Set to terminate file 24$: CLRB $OUTSW ; Set output on TSTNEB $FIRPG,40$ ; First page? BITEQ #FFDSW,$SWTCH,25$ ;SPACING WITH LINE FEEDS? MOV #FF,R1 ; OUTPUT A FORMFEED CALL FOUT CALL OUTPUT ; Output separate line BR 40$ ; ADJUST COUNTS 25$: MOV LINEC2,R2 ; Number of lines to skip 30$: BGT 35$ ; Go skip em BEQ 40$ ; Already at bottom ADD LPPG,R2 ; GET - NUMBER OF LINES TO TOP OF PAGE BR 30$ ; 35$: CALL CRLF ; SPACE TO NEXT LINE SOB R2,35$ 40$: CALL OPRWAT ; WAIT FOR OPERATOR TO POSITION FORMS 50$: 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 BITEQ #FOTF,F.1,60$ ; Footnote not in progress ? TSTB $PFOOT ; Permanent footnote in progress ? BLT 60$ ; Yes ? SUB FOTLN,LINEC3 ; Subtract off header size 60$: MOV LPPG,LINEC2 ; Number of lines this page SUB TEXLN,LINEC3 ; Account for deferred lines CLR TEXLN BIC #TEXF,F.1 ; Clear out deferred text flag 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 CALL $MUL ; Find adjusted lines to skip 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:: MOV #LINSP,R1 ; Number of lines to test BITEQB #FOTF,F.1,TESTP ; No footnote or deferred text? ADD NSPNG,R1 ; Add in line spacing ; ; R1 = number of lines requested, check if break page? ; TESTP:: TSTB $PFOOT ; Permanent footnote in progress? BLT 10$ ; Yes ? CMP R1,LINEC3 ; COMPARE TO LENGTH BGT BPAGE ; START A NEW PAGE 10$: SEC ; NO 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:: CLR $SBPSW ; CLEAR SUBPAGE FLAG CLR SUBPGE ; reset subpage MOVB #1,SUBNX ; clear next subpage BR BPAGE ; ; PAGE command (new page only if not already at top-of-page) ; CPAGE:: TSTNEB $PAGBR,BPAGE ; Page not already boken? CLC ; Signify page broken ; ; BREAK COMMAND ; BREAK:: RETURN ; ; Start new page routine ; BPAGE:: BITEQ #FOTF,F.1,10$ ; No footnote in progress? CALL OUTL0 ; Do footnote output CALL LINSET ; Reset line params 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 CLRB $FOTPD ; CLEAR PENDING CALL OUTL0 ; OUTPUT IT BIC #FOTF,F.1 ; CLEAR FLAG 30$: CLRB $ULOSW ; No underlining of headers! TSTNEB $FIRPG,35$ ; First page? BITEQB #LAY.NB,$LAYOU,35$ ; Not number at bottom of page? MOV LINEC1,R2 ; Lines remaining this page ADD $EOPSP,R2 ; Add on end of page spacing SUB #LINSP,R2 ; Compensate for number to print BLE 32$ ; None? CALL $SKIP ; Skip em 32$: 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 35$: 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 TSTNE $NTITL,50$ ; no title? MOV #TTLBF,R3 ; HEADER BUFFER CALL CENTIT ; Center title if necessary CALL PSTRPA ; PRINT STRING FROM PA 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 TSTNE $NTITL,70$ ; no title? MOV #STLBF,R3 ; OUTPUT THE SUBTITLE, IF ANY CALL HDMRG ; Set up margins CALL CENTIT ; Center the subtitle? CALL PSTRPA ; .. 70$: MOV HSPAC,R2 ; LINES TO SKIP BGT 80$ MOV #LINSP,R2 ; Only 1 skip 80$: CALL $SKIP ; DO IT 90$: BICB #SW.TDS,$HDRSW ; Reset temporary header disable CLRB $ULOSW ; No underlining CLRB $PAGBR ; INDICATES AT TOP OF PAGE MOV $FIGDF,R2 ; Lines to skip at end BLE 110$ ; None CMP R2,LINEC3 ; Compare BLT 100$ ; Not too many MOV LINEC3,R2 ; Make it enough 100$: CALL $SKIP ; Skip them 110$: CLR $FIGDF ; Clear deferred lines CLRB $FIRPG ; Indicates not first page of document CLC ; INDICATE PAGE BROKEN RETURN ; HDMRG: MOV EBSIZ1,R2 ; SPACE FOR CHANGE BAR OFFSET ADD EBSIZ2,R2 ADD RIGSHI,R2 ; ADD ON RIGHT SHIFT ADD PLMRG,R2 ; ADD ON PERMENANT LEFT MARGIN CALL NSPAC ; SPACE TO MARGIN RETURN ; CENTIT: MOV PRMRG,R2 ; Permanent right margin SUB PLMRG,R2 SUB BF.SPC(R3),R2 ; Subtract off char count BLE 50$ ; None to do BITNEB #LAY.CT,$LAYOU,10$ ; Center title? BITEQB #LAY.LR,$LAYOU,50$ ; No odd even layout BITEQB #1,PAGENO,50$ ; Not odd page number? BR 20$ ; Shift to right justify 10$: CLC ASR R2 20$: CALL NSPAC ; Space over to margin 50$: RETURN HDPAG: TSTEQ $NUMSW,60$ ; NO PAGE NUMBER? MOV #TTBF,R3 ; GET TEMPORARY BUFFER CALL CLRBF ; CLEAR IT TSTNEB $PAGSW,50$ ; OUTPUT 'PAGE'? MOV #PAGHD,R0 ; PAGE HEADER CALL PSTRZB ; MOVE IT TO BUFFER 50$: CALL PUTPAG ; PUT PAGE INTO BUFFER ALSO MOV #PAGH2,R0 ; And second header CALL PSTRZB ; Put it also MOV PRMRG,R2 ; PERMENANT RIGHT MARGIN SUB CPOS,R2 ; Minus current position ADD EBSIZ1,R2 ADD EBSIZ2,R2 ADD RIGSHI,R2 INC R2 ; Compensate for CPOS SUB BF.FUL(R3),R2 ; Minus number size BITNEB #LAY.CP,$LAYOU,51$ ; Centered page number? BITEQB #LAY.LR,$LAYOU,55$ ; No odd even layout BITEQB #1,PAGENO,57$ ; Not odd page number? BR 55$ 51$: CLC ASR R2 ; Center it 55$: CALL NSPAC ; SPACE TO PAGE NUMBER 57$: CALL PSTRPA ; OUTPUT STRING IN BUFFER 60$: RETURN ; ; ROUTINE TO PROMPT OPERATOR AND WAIT FOR SIGNAL TO ; CONTINUE ; OPRWAT::; BITEQ #PAUSW,$SWTCH,10$ ; DON'T WAIT FOR NEW PAPER? BITEQB #FD.TTY,TTBLK+F.RCTL,10$ ; IS TI: DEVICE A TERMINAL BICB #FD.CR,TTBLK+F.RATT ; KEEP FCS FROM ADDING LINE FEED MOV #OPRTXT,R0 ; Operator wake up message CALL EROUT ; Output it BISB #FD.CR,TTBLK+F.RATT ; RE-ENABLE CARRIAGE CONTROL CALL TTC4N ; READ A CHARACTER 10$: RETURN ; RETURN ; ; SUBTITLE COMMAND ; SETSTL:: MOV #STLBF,R3 ; SUBTITLE BUFFER BR SETBF ; ; ; no title command ; NTITL:: MOV SP,$NTITL ; set no title print RETURN ; ; FIRST TITLE COMMAND ; UCTTL:: CALL SHFUC ; Set mode to uppercase BR SETTL FTITL:: BITNE #LCKF,F.1,SETTL ; Params locked? CLRB $HDRSW ; ENABLE HEADER ON FIRST PAGE ; ; TITLE COMMAND ; SETTL:: MOV #TTLBF,R3 ; SET FOR TITLE BUFFER BITEQ #LCKF,F.1,SETBF ; param not locked? CLR $NTITL ; set for print of titles SETBF:: CALL CLRBF ; SET BUFFER EMPTY CLRB $BFSTC ; Clear the buffer counters CLR BF.SPC(R3) ; NO SPACING CHAR SETB1:: BISB #40,$TABSW ; DISABLE TABS BISB #40,$ESCSW ; DISABLE ESCAPE SEQ. BISB #40,$EQFSW+1 ; Disable equation mode SETB2:: CALL $FRCND ; FORCE TO LOGICAL END OF COMMAND TSTNEB $BFSTC,10$ ; Keep buffer structure same MOV BRCNT,-(SP) ; Save break count MOV LCH,-(SP) ; SAVE LAST CHAR MOV LSTSP,-(SP) ; location of last space MOV LTAB,-(SP) ; Location of last tab MOVB $TABPD,-(SP) ; And pending tab MOV SPCH,-(SP) ; SAVE SPACIN CHAR MOV LSPCH,-(SP) ; char count at last space MOVB $UNLSW,-(SP) ; Save current underline switch MOVB LUNLSW,-(SP) ; Last underline switch MOV SPCNT,-(SP) ; SPACES/LINE MOV SPCNSV,-(SP) MOV LINBK,-(SP) ; LINE COUNTER MOV F.1,-(SP) ; SAVE MORE FLAGS BIS #FILLF,F.1 ; SET TO FILL (GET RID OF SPACES) CLRB LCH ; START OF LINE CLR SPCH ; No spacing chars CLR LSPCH CLR SPCNT ; Space count CLR SPCNSV CLR BRCNT CLR LTAB ; No tabs pending CLRB $TABPD MOV PRMRG,LINBK ; Max number of char in buffer SUB PLMRG,LINBK ; Minus permanent right margin SUB #8.,LINBK ; Minus a little bit for numbers 10$: CALL GCIN ; READ TITLE OR SUBTITLE CMPNE R1,#LF,11$ ; End of line? CALL BKSPI ; Backspace over LF CALL BKSPI ; Backspace over CR 11$: TST LINBK ; Past end of line? BLT 15$ ; No CMPNEB LCH,#SPC,20$ ; Last char in buffer not space? 15$: CALL BKOUT ; Back up over last space 20$: MOV SPCH,BF.SPC(R3) ; SPACING CHAR COUNT TSTNEB $BFSTC,30$ ; Keep buffer structure? MOV (SP)+,F.1 ; RESTORE MOV (SP)+,LINBK MOV (SP)+,SPCNSV MOV (SP)+,SPCNT MOVB (SP)+,LUNLSW MOVB (SP)+,$UNLSW MOV (SP)+,LSPCH MOV (SP)+,SPCH MOVB (SP)+,$TABPD MOV (SP)+,LTAB MOV (SP)+,LSTSP MOV (SP)+,LCH MOV (SP)+,BRCNT ; Restore break count 30$: BICB #40,$TABSW ; ENABLE TABS BICB #40,$ESCSW ; ENABLE ESCAPE SEQ. BICB #40,$EQFSW+1 BICB #40,$UNLSW ; ENABLE UNDERLINING BICB #40,$OVRSW ; ENABLE OVERSTRIKING CLRB $BFSTC ; Clear the buffer counters RETURN ; ; ; START OF RUNOFF ; START: CALL $START ; RUNOFF::MOV SPSAV,SP ; Reset stack CALL INITL ; INITIALIZE VARIABLES JMP RESTRT ; Continue .END START