.TITLE GCIN .IDENT /V01/ ; ; These are general input/output character interpretation routines ; .PSECT $TEMP,RW,D,OVR,GBL .BLKB 1 TBUFF: .BLKB SUBMAX+2 .even ADDR: .BLKW 1 .PSECT GCTABL,RW,D,GBL ; ; INPUT CHARACTER PARSING TABLES ; TO ADD MORE FLAGS THESE TABLES MUST BE CHANGED ; THE FLAG DEFINITIONS COORESPOND TO THE FLAG SWITCHES ; GC.UC==0 ; Upper case letters GC.LC==2 ; Lower case letters GC.AFL==4 ; Accept flag GC.CFL==6 ; Capitalize flag GC.UFL==10 ; Underline flag GC.LFL==12 ; Lowercase flag GC.SFL==14 ; Uppercase flag GC.QFL==16 ; Quoted space flag GC.OFL==20 ; Overstrike flag GC.IFL==22 ; Index flag GC.HFL==24 ; Hyphenation flag GC.EFL==26 ; Escape flag GC.SUB==30 ; substitute flag GC.BRK==32 ; break flag GC.NFL==34 ; COMMAND FLAG GC.CR==36 ; CARRIAGE RETURN GC.TAB==40 ; tab input char GC.LF==42 ; lin feed input GC.DIG==44 ; digit (0-9) GC.SPC==46 ; space GC.MSC==50 ; MISCELLANEOUS CHARS GC.SPF==52 ; Special flag GC.EQ1==54 ; Equation flags GC.EQ2==56 ; Equation flags GC.SIX==60 ; Subindex flag GC.PFL==62 ; PEriod flag GO.UNL==-2 ; underline 1 char GO.ESC==-12 ; begin escape sequence GO.QTS==-14 ; quoted space output GO.BS==-16 ; backspace output GO.TAB=-20 ; Tab count byte follows GO.ELP=-22 ; Ellipses count follows this GC.ILL=-24 ; illegal character GO.REP=-26 ; Repeat characters GO.INX=-30 ; Index entry GO.TOC=-32 ; TOC entry GO.PAG=-34 ; Page number ; ; THE FOLLOWING CORRESPOND TO THE ASCII CHARACTERS ; GCTABL:: .BYTE GC.ILL,GC.ILL,GC.ILL,GC.ILL,GC.ILL,GC.ILL ; NUL-ENQ .BYTE GC.ILL,GC.ILL,GO.BS ; ACK-BS .BYTE GC.TAB,GC.LF,GC.ILL,GC.ILL ; TAB,LF,VT,FF .BYTE GC.CR,GC.ILL,GC.ILL,GC.ILL ; CR,SO,SI,DLE .BYTE GC.ILL,GC.ILL,GO.PAG,GO.TOC,GC.ILL ; DC1-nak .BYTE GO.INX,GO.REP,GO.TAB,GO.ELP,GC.ILL ; SYN-SUB .BYTE GO.ESC,GO.UNL,GC.ILL,GC.ILL,GC.ILL ; ESC-US .BYTE GC.SPC ; SPACE .BYTE GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC ; - & .BYTE GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC ; ' - , .BYTE GC.MSC,GC.MSC,GC.MSC ; - . / .BYTE GC.DIG,GC.DIG,GC.DIG,GC.DIG,GC.DIG ; 0 - 4 .BYTE GC.DIG,GC.DIG,GC.DIG,GC.DIG,GC.DIG ; 5 - 9 .BYTE GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC ; : - @ .BYTE GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC ; UPPER CASE .BYTE GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC ; UPPER CASE .BYTE GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC ; UPPER CASE .BYTE GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC ; UPPER CASE .BYTE GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC ; [ - ` .BYTE GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC ; LOWER CASE .BYTE GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC ; LOWER CASE .BYTE GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC ; LOWER CASE .BYTE GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC ; LOWER CASE .BYTE GC.MSC,GC.MSC,GC.MSC,GC.MSC ; { - ~ .BYTE GO.QTS ; DEL ; ; CHARACTER DEFINITION TABLE ; CH.BRK==1 ; Char is followed by break CH.BRB==2 ; Char is preceeded by break CH.FLC==4 ; CHAR MAY BE FLAG CHAR CH.FLG==10 ; CHAR IS CURRENTLY FLAG CHAR CH.PER==20 ; CHAR IS PUNCTUATION CH.VOW==40 ; character is a vowel CH.PNC==100 ; char is punctuation (for routine HYPHEN) CH.UNL==200 ; char is not underlinable CHTABL:: .BLKB 9. ; Nul-BS .BYTE CH.FLC ; Tab .BLKB 22. ; LF-US .BYTE CH.PNC!CH.UNL ; "space" .BYTE CH.FLC!CH.PNC!CH.PER ; ! .BYTE CH.FLC!CH.PNC ; " .BYTE CH.FLC ; # .BYTE CH.FLC ; $ .BYTE CH.FLC ; % .BYTE CH.FLC ; & .BYTE CH.FLC ; ' .BYTE CH.FLC!CH.PNC ; ( .BYTE CH.FLC!CH.PNC ; ) .BYTE CH.FLC ; * .BYTE CH.FLC ; + .BYTE CH.FLC!CH.PNC ; , .BYTE CH.FLC ; - .BYTE CH.FLC!CH.PER!CH.PNC ; . .BYTE CH.FLC!CH.PNC ; / .BLKB 10. ; 0 - 9 .BYTE CH.FLC!CH.PER,CH.FLC!CH.PER ; : ; .BYTE CH.FLC,CH.FLC,CH.FLC ; < = > .BYTE CH.FLC!CH.PER,CH.FLC!CH.PNC ; ? @ .BYTE CH.VOW,0,0,0,CH.VOW,0,0,0 ; A-H .BYTE CH.VOW,0,0,0,0,0,CH.VOW,0 ; I-P .BYTE 0,0,0,0,CH.VOW,0,0,0 ; Q-X .BYTE CH.VOW,0 ; Y-Z .BYTE CH.FLC ; [ .BYTE CH.FLC!CH.PNC ; \ .BYTE CH.FLC ; ] .BYTE CH.FLC ; ^ .BYTE CH.FLC ; _ underscore .BYTE CH.FLC ; ` .BYTE CH.VOW,0,0,0,CH.VOW,0,0,0 ; A-H .BYTE CH.VOW,0,0,0,0,0,CH.VOW,0 ; I-P .BYTE 0,0,0,0,CH.VOW,0,0,0 ; Q-X .BYTE CH.VOW,0 ; Y-Z .BYTE CH.FLC,CH.FLC,CH.FLC,CH.FLC ; { - ~ .BYTE CH.PNC ; DEL .even .psect $TABL,RO,D,LCL,CON BITABL:: .WORD 1,2,4,10,20,40,100,200,400 .WORD 1000,2000,4000,10000,20000,40000,100000 .PSECT TEXT,RO,D,LCL,CON ILSBCM: .ASCIZ /RNO -- Unrecognized command/ ILSBST: .ASCIZ /RNO -- Too many nested substitutions/ ILSBND: .ASCIZ /RNO -- Undefined substitution/ ILUNES: .ASCIZ /RNO -- Undefined escape seq./ EQER3: .ASCIZ /RNO -- Too many nested fractions/ EQER4: .ASCIZ /RNO -- Syntax error in equation/ .even .PSECT $CODE,I,RO,LCL,CON ; ; THE JUMP TABLE TO PARSE CHARS ; .WORD HLTER,GOPAG,GOTOC,GOINX,GOREP,HLTER,GOELP,GOTAB .WORD GOBS,GOQTS,GOESC,HLTER,HLTER,HLTER,GOUNL GCJMP: .WORD GCDN,GCUP,GCACC,GCCAP .WORD GCUNL,SHFDN,SHFUP,GCQTS .WORD GCOVR,GCIFL,GCHYP,GCESC .WORD GCSUB,GCBRK,GCINR,GCCR .WORD GCTAB,GCLF,GCINR,GCSPC .WORD GCINR,GCSPF,GCEQN1,GCEQN2 .WORD GCSIX,GCPER ; ; GET INPUT CHARACTER FROM SOURCE FILE AND INTERPRET IT ; All registers except for R3 are destroyed ; GCIN:: CALL CCIN ; GET CHARACTER FROM FILE. GCIN1: MOVB GCTABL(R1),R0 ; GET CHARACTER TYPE DSPTCH: JMP @GCJMP(R0) ; DISPATCH ACCORDING TO TABLE ; ; HERE ARE SPECIAL CHARACTER CASES ; ; UPPER CASE GCDN: TSTB CASE ; CONVERSION NECESSARY BGE GCINR ; NO GCDN1: ADD #40,R1 ; CONVERT CASE IF NECESSARY BR GCINR ; ; LOWER CASE LETTERS GCUP: TSTB CASE ; CONVERSION NECESSARY BLE GCINR ; NO GCUP1: SUB #40,R1 ; CONVERT TO UPPER CASE BR GCINR ; ; CAPITALIZE FLAG GCCAP: TSTNEB $CFLSW+1,GCINR ; Flag temporarily disabled ? MOVB #1,CASE ; SET WORD CAPITALIZE CONVERSION VALUE BR GCIN ; ; UNDERLINE FLAG GCUNL: TSTNEB $UFLSW+1,GCINR ; Flag temporarily disabled ? BITNEB #^C,$UNLSW,GCIN ; Permanently disabled ? TSTNE @EQSTK,GCIN ; Equation in progress ? MOV #ULCHS,R1 ; SET TO UNDERLINE CHARACTER MOVB R1,$UNLLN ; Set to mark this line as underlined JMP GCINO ; ; OVERSTRIKE FLAG GCOVR: TSTNEB $OFLSW+1,GCINR ; Flag temporarily disabled ? BISB #SW.TDS,$AUHYP ; Temporary disable hyphenation TSTNEB $OVRSW,GCIN ; Overstrike disabled ? MOV #BS,R1 ; MAKE IT BACK SPACE ADD PHSP,LINBK ; Add to remaining chars SUB PHSP,SPCH ; Subtract from spacing characters BR GCINO ; ; HYPHENATE FLAG GCHYP: TSTNEB $HFLSW+1,GCINR ; Flag temporarily disabled ? TSTNEB RETSW,GCLF ; Return ? TSTNE @EQSTK,50$ ; Equation being formatted ? BISB #SW.TDS,$AUHYP ; Set temporary no auto hyphenation TST LINBK ; Check room on page BLE GCIN ; No room for hyphenation ? CMPEQB LCH,#SPC,GCIN ; Last char space ? CMPEQB LCH,#TAB,GCIN ; or tab ? CMPEQB LCH,#NXS,GCIN ; or non expandable space ? CALL BRKSV MOV SPCH,HYPSP ; Hyphenation spacing chars. 50$: JMP CONTIN ; QUOTED SPACE FLAG GCQTS: TSTNEB $QFLSW+1,GCINR ; Flag temporarily disabled ? TSTNEB RETSW,GCLF ; Return ? MOVB ULOCK,CASE ; RESET CASE GCQTS1: MOV #NXS,R1 ; SET NON EXPANDABLE SPACE BISB #SW.TDS,$AUHYP ; Set temporary no auto hyphenation BR GCINR1 ; AND SAVE IT GCINR:: BIC #1002,CASE ; Reset temporary upper case conversion GCINR1: CALL PUBYT0 ; OUTPUT CHAR MOV TESMSK,R4 ; Cancel escapes ? BEQ 20$ ; No ? CALL ESCEND ; Cancel them 20$: MOVB LCH,R1 BITEQB #CH.BRK,CHTABL(R1),GCINR2 ; No AutoBreak ? CMPEQB R1,#SPC,GCINR2 ; Space ? TSTNEB $AUBRK,GCINR2 ; No break ? TSTNE @EQSTK,GCINR2 ; Equation being formatted ? TST LINBK ; Past end of line ? BLE GCINR2 ; Yes ? BISB #SW.TDS,$AUHYP ; set temporary no hyphenation TSTEQB $TABPD,30$ ; No right tabs ? CALL BRKTS ; Set them up BR GCINR2 ; done 30$: CALL BRKSV ; Set up break here GCINR2: SUB PHSP,LINBK ; Subtract from char count remaining BEQ 20$ BCC 70$ ; NO CMPEQ PHSP,#1,70$ ; Single decrement ? 20$: MOV SPCH,LNINS ; Char count at last character TSTNE BRCNT,30$ ; NO breaks this line? CALL BRKSV ; Save break here 30$: TSTNEB $GCEND,GCLF ; Immediate end requested? 70$: JMP GCIN ; Continue GCLF: RETURN GCINO: CALL PBYT ; OUTPUT CHAR JMP GCIN ; CONTINUE PARSING INPUT ; ACCEPT FLAG GCACC: TSTNEB $AFLSW+1,GCINR ; Flag temporarily disabled ? CALL CCIN ; READ CHARACTER NO TRANSLATION CMPEQB R1,#SPC,GCQTS1 ; Space ? Make it quoted space BGT 1$ ; Printable ? JMP GCIN1 ; Less than space ? 1$: BIC #1002,CASE ; Reset temporary upper case conversion CALL PUBYT0 ; OUTPUT CHAR BIS #200,LCH ; Set for quoted char MOV TESMSK,R4 ; Cancel escapes ? BEQ 20$ ; No ? CALL ESCEND ; Cancel them 20$: BR GCINR2 ; ; ROUTINE TO READ INPUT FROM FILE AND REMOVE BAD INPUT ; R1= CHARACTER READ ; R2-R5 are saved ; CCIN:: MOV BUFAD,R1 ; input buffer header CALL GBYT1 ; get input BLOS 20$ ; At end of buffer ? BIC #^C<177>,R1 ; CLEAR EXCESS BITS TSTB GCTABL(R1) ; LEGAL CHARACTER? BLT CCIN ; NO GET ANOTHER RETURN 20$: TSTEQB SUBSTK,30$ ; End of input line ? CALL POPINS ; Go down one entry BR CCIN ; try again 30$: CALL FIN ; NO. READ FROM FILE BCC CCIN ; Successful input ? RETURN ; None to get ; ; routine to parse substitution - SUBSTITUTE FLAG ; GCSUB: TSTEQB $SBFSW+1,1$ ; Flag not disabled ? JMP GCINR 1$: MOV R3,-(SP) ; save MOV BUFAD,R3 ; get buffer header for input MOV #TBUFF-1,R2 ; temporary buffer MOVB R1,(R2)+ ; Save flag CLRB (R2) ; Clear in case no more MOV BF.FUL(R3),-(SP) ; save current location MOV #SUBMAX,R4 ; max number of char/label 50$: CALL GBYT ; get input CMP R1,#SPC ; non printable? BLE 60$ ; yes, done CMPNEB GCTABL(R1),#GC.LC,55$ ; Not lower case ? CMPEQ R2,#TBUFF,55$ ; Not first char ? SUB #40,R1 ; Make it lower case 55$: MOVB R1,(R2)+ ; Save char SOB R4,50$ ; no, continue 60$: CLRB (R2)+ ; Chock end of string MOV #TBUFF,R2 ; Start of buffer CMPNEB (R2),$SBFSW,65$ ; First char not substitute flag ? MOVB #'$,(R2) ; Make first char $ 65$: MOV (SP)+,R1 ; current location CALL FNDBF ; go back to it CALL FNDSB ; Find substitution MOV (SP)+,R3 ; restore JMP GCIN ; ; Find substitutions All registers destroyed ; FNDSB:: CMPB SUBSTK,SUBSTK+1 ; max stack reached? BLO 40$ ; no MOV #ILSBST,R0 ; Too many nestings error BR 20$ 10$: CALL POPINS ; Back in stack MOV #ILSBCM,R0 ; Undefined command TSTB TBUFF BLT 20$ ; command ? .ifdf $PASS ; 2 pass ? BITNEB #SW.DIS,$OUTSW,110$ ; First of 2 passes ? .endc MOV #ILSBND,R0 ; Undefined substitution error 20$: CALL EROUT MOV #TBUFF-1,R0 ; Print substitution BICB #200,1(R0) ; Clear extra bits CALL ONLIN ; Output traceback 30$: SEC return 40$: CALL PSHINS ; Set up input stack CALL BEGBF ; Start at beginning CALL GWRD ; First index BCS 10$ ; None? 50$: TSTEQ R1,10$ ; None ? CALL FNDBF ; Find next entry CALL GWRD ; get next index BCS 10$ ; end, no escape found MOV R1,R4 ; save MOV #TBUFF,R2 ; temporary buffer MOV BF.FUL(R3),BF.SPC(R3) ; Save index for traceback 60$: CALL GBYT ; Get next char in key word table BCS 10$ ; None? BITEQ R1,#140,90$ ; End of search ? 70$: CMPEQB R1,(R2)+,60$ ; match? TSTB TBUFF ; Check first byte BGT 80$ ; Not command ? DEC R2 ; Go back to last char checked CMPEQB R1,#SPC,60$ ; Space in table ? CMPNEB -1(R2),#SPC,80$ ; Char before last not space ? CMPEQB (R2)+,#SPC,70$ ; Current space ? 80$: MOV R4,R1 ; Next entry index BR 50$ ; search again 90$: TSTB TBUFF ; Check for command BGT 92$ ; Not commad MOVB (R2),R0 ; Get terminal char CMPEQB GCTABL(R0),#GC.UC,80$ ; Upper case char ? 92$: BITEQB R1,#7,95$ ; Not a number ? MOV R1,R5 CLR -(SP) ; Chock stack 93$: CALL GWRD ; get the number TSTEQ R1,94$ ; Zero ? MOV R1,-(SP) ; Save number 94$: SOB R5,93$ MOVB #'-,$SEPR ; Page separator CALL ENDBF ; Set to end of buffer MOV BF.FUL(r3),R4 ; Save index MOV BF.SPC(R3),BF.VSP(R3); Save traceback CALL PAGCV ; And convert number MOV BF.VSP(R3),BF.SPC(R3); Restore CALL CBYT ; Chock it MOV R4,R1 ; Beginning of string CALL FNDBF ; Set to scratch location 95$: MOV R2,R1 ; end of string SUB #TBUFF,R1 ; find string length MOVB SUBSTK,R3 ; Get subst stack MOV BUFADD-2(R3),R3 ; Old stack ADD BF.FUL(r3),R1 ; Add offset to start of string CALL FNDBF ; And new location TSTB TBUFF BLT 110$ ; Command ? TSTEQB $SUBSW,110$ ; substitution not suppressed? 100$: JMP POPINS ; Reset subst 110$: CLC RETURN ; done, continue with normal sequence ; ; TAB character handled here. It is expanded. ; GCTAB: TSTNEB $TBFSW+1,1$ ; Flag disabled ? TSTNE @EQSTK,1$ ; Equation being formatted ? TSTNEB $CENSW,1$ ; Centering enabled ? TSTNEB $RIGSW,1$ ; Right justify enabled TSTEQB $TABSW,2$ ; Tabs allowed ? 1$: JMP GCSPC ; NO! 2$: BISB #SW.TDS,$AUHYP ; No autohyphenation now MOVB ULOCK,CASE ; RESTORE CASE CALL BRKTS ; Test + execute right tabs CLR R2 CALL TABB ; FIND WHERE NEXT TAB STOP IS CMP R2,LINBK ; Does this exceed line size? BLE 20$ ; It is OK ? TST LINBK ; Currently too long ? BLT 10$ ; Yes CALL BKSPI ; Backup over tab to save it CALL BRKSV ; No, put break here 10$: MOVB #TAB,R1 ; Current char RETURN 20$: MOV #TABBF,R1 ; Get status CALL GBYT1 ; BITNE #TB.L,R1,30$ ; Tab only left BITNE #TB.R!TB.C,R1,25$; Tab only right TSTEQB $TABLF,30$ ; Left justify tabs ? 25$: MOV #1,R2 ; Only 1 space for right justify MOVB R2,$TABPD ; Now set 1 tab pending BISB R1,$TABPD ; Set for right tab 30$: CMPNEB LCH,#TAB,35$ ; Was last char not tab ? TSTEQ LTAB,35$ ; No tab pending SUB R2,LINBK ; AND DECREMENT LINBK COUNT BY THAT AMOUNT ADD R2,SPCH ; Add to spacing characters CALL ADDTAB ; Add r2 to previous tab BR TABXIT ; 35$: SUB R2,LINBK ; Subtrac from remaining space ADD R2,SPCH ; Add to spacing characters TSTEQB BRCNT,36$ ; Beginning of line ? CALL BKSPI ; Backup over tab to save it CALL BRKSV ; Save break before tab CALL CCIN BR 37$ 36$: CALL BRKSV ; Set break after tab 37$: MOVB #TAB,LCH ; LAST CHAR MOVB #TABO,R1 ; Set to output tab MOVB @TABBF+BF.ADD,R4; Ellipses count BIC #^C,R4 ; Clear count BNE 39$ ; Ellipses spec ? TSTEQB $ELIPS,40$ ; No ellipses? 39$: MOVB #ELIP,R1 ; Yes, set to output ellipses 40$: CALL PBYT ; Into buffer MOV R2,R1 ; Number of spaces CALL PBYT ; Into buffer MOV BF.ADD(R3),LTAB ; Address of last tab char TSTNEB $ELIPS,45$ ; Ellipses ? TSTEQ R4,TABXIT ; No ellipses ? 45$: MOV R4,R1 ; Ellipses count CALL PBYT TSTEQ R4,TABXIT ; Done ? 50$: MOV #TABBF,R1 CALL GBYT1 ; Put ellipses into buffer CALL PBYT SOB R4,50$ TABXIT: JMP GCIN ; Next char ; ; End of line action, space if fill disabled ; GCCR: CALL BRKTS ; Test tab + break TSTNEB $CENSW,10$ ; Centering enabled ? TSTNEB $RIGSW,10$ ; Right justify enabled BITNE #FILLF,F.1,GCSPC ; Fill enabled ? 10$: TST LINBK ; Past end of line ? BGE TABXIT ; No ? RETURN ; Yes ! ; ; Handle spaces in input stream ; GCSPC:: TSTNEB RETSW,SPCRET ; Return ? MOVB ULOCK,CASE ; RESTORE CASE TSTNE @EQSTK,25$ ; Equation being formatted ? TST LINBK ; Line full ? BGE 10$ ; NO ? RETURN ; Yes, break for full line 10$: BITEQB #CH.BRK,CHTABL+SPC,15$ ; No AutoBreak ? CALL BRKTS ; Test and set up right tabs 15$: BITEQ #FILLF,F.1,30$ ; FILL disabled ? MOVB LCH,R1 ; GET PREVIOUS CHARACTER WHAT WAS IT? BEQ TABXIT ; Start of new line ? BLT 30$ CMPEQB R1,#SPC,TABXIT ; Space before space ? CMPEQB R1,#TAB,TABXIT ; Tab before space ? CMPEQB R1,#NXS,TABXIT ; Non expandable space before space ? CMPEQB R1,#CPER,17$ ; Is it following period char? TSTEQB $PERSW,30$ ; Automatic punctuation spacing disabled ? BITEQB #CH.PER,CHTABL(R1),30$ ; Not Punctuation before space ? 17$: CMP LINBK,#1 ; Space left ? BLE 30$ ; No 20$: CALL 50$ ; Set up for space CALL PUBYT0 ; Save space SUB PHSP,LINBK ; And subtract from char left 25$: MOV #NXS,R1 ; Next output non expandable space BR 40$ ; 30$: CALL 50$ ; 40$: BICB #SW.TDS,$HYPSW ; Allow hyphenation BICB #SW.TDS,$AUHYP ; Allow auto hyphenation CLR HYPSP 45$: JMP GCINR1 ; RETURN CHAR. ; ; Section to insert spaces ; 50$: BITEQB #CH.BRK,CHTABL+SPC,55$ ; No AutoBreak ? CALL BRKSV ; Set up for break here 55$: TSTNEB $NOSPC,70$ ; No expandable spaces allowed ? INC SPCNT ; COUNT THIS SPACE MOV #SPC,R1 ; SPACE CHARACTER (EXPANDABLE) 60$: RETURN ; 70$: MOV #NXS,R1 ; Make it non expandable SPCRET: RETURN GCPER: TSTNEB $PFLSW+1,10$ ; Period flag disabled ? MOVB #CPER,LCH ; Last is period flag JMP GCIN 10$: JMP GCINR ; Output char ; ; break flag here ; GCBRK: TSTEQB $BRFSW+1,1$ ; Flag not disabled ? JMP GCINR 1$: TSTNEB RETSW,SPCRET ; Return ? TSTNE @EQSTK,CONTIN ; Equation being formatted ? BISB #SW.TDS,$AUHYP ; set temporary no hyphenation TST LINBK ; Past end of line BGE 10$ ; Not yet RETURN 10$: TSTEQB $TABPD,20$ ; No right tabs ? CALL BRKTS ; Set them up BR CONTIN ; done 20$: CALL BRKSV ; Set up break here CONTIN: TSTNEB $CONT,20$ ; Continue disabled ? CALL CCIN ; Get next char CMPNEB R1,#CR,40$ ; Not CR CALL FIN ; Next line CALL LSINSV ; Save input line 20$: JMP GCIN ; And next line 40$: JMP GCIN1 ; next char ; ; Test and set up right tab ; .ENABL LSB BRKTS: MOVB $TABPD,R0 ; Check pending tabs BEQ 10$ ; No tab pending? CLRB $TABPD ; No more tabs pending TSTEQ LTAB,10$ ; No tab address ? MOV #-1,R2 ; Initial tab BITEQ #TB.C,R0,5$ ; No centered tabs ? MOV SPCH,R0 ; Get text size SUB LSPCH,R0 ; Minus previous size DEC R0 ; Account for tab ASR R0 ; Divided by 2 SUB R0,R2 ; Subtract from Offset 5$: CALL TABB ; Find next tab stop DEC R2 ; CMP R2,LINBK ; Too many for line ? BGT 10$ ; YES. TREAT AS SPACE, NOT TAB ADD R2,SPCH ; Spacing chars SUB R2,LINBK ; Current length this line ADDTAB: MOVB @LTAB,R1 ; Get last tab ADD R2,R1 ; Add on more MOVB R1,@LTAB ; Increment old tab 10$: RETURN .DSABL LSB ; ; Set up break (save current character status) ; BRKSV:: CLR HYPSP CALL LSINSV ; save input addresses INC BRCNT ; count breaks this line MOV PHSP,LPHSP ; Spacing at break MOV CASE,CASSAV ; SAVE CURRENT CASE MOV BF.FUL(R3),LSTSP ; POSITION IN BUFFER MOV ESMSK,LESMSK ; Save current escape mask MOVB $UNLSW,LUNLSW ; And underline status MOVB LCH,LSCH ; SAVE CHAR BEFORE SPACE MOV SPCNT,SPCNSV ; Save old space count MOV SPCH,LSPCH ; Save current spacing char count RETURN ; ; Here we handle Index flag ; GCIFL: TSTEQB $IFLSW+1,10$ ; Autoindex flag on ? JMP GCINR ; No, ouput char 10$: CALL AINDEX ; Do autoindex JMP GCIN ; Continue ; ; SUBINDEX FLAG ; GCSIX: TSTEQB $SIFSW+1,10$ ; Autoindex flag on ? JMP GCINR ; No, ouput char 10$: CMPNEB LCH,#SPC,20$ ; Not last space MOV LSTSP,R1 ; Abort last space CALL RSTBF ; Terminate buffer here 20$: CLR LCH ; Set last to null MOVB #SXCHR,R1 ; Get subindex character JMP GCINO ; Save subindex flag ; ; HERE WE HANDLE SEPARATE ESCAPE SEQUENCES ; GCESC: TSTEQB $EFLSW+1,1$ ; Flag not disabled ? JMP GCINR 1$: MOV R1,R5 ; First character CALL CCIN ; GET NEXT CHAR GCES1: CALL ESCSEQ ; ESCAPE SEQUENCE? BCC 10$ ; No ? MOV #ILUNES,R0 ; Message undefined escape CALL ILCMC ; Output error message 10$: JMP GCIN ; NEXT CHAR ; ; Special Flag character detected ; GCSPF: TSTEQB $SPFSW+1,1$ ; Flag not disabled ? JMP GCINR 1$: MOV #'^+100000,R5 ; Move in shift up operator+ temp flag CALL ESCSEQ ; Execute sequence BCC 10$ ; Not executed ? MOV #ILUNES,R0 ; Message undefined escape CALL ILCMC ; Output error message 10$: JMP GCIN ; Continue ; ; SUBROUTINE TO FIND ESCAPE SEQUENCE FROM TABLE ; ; R4=Escape sequence mask ; R3 is preserved/ all other registers changed .enabl LSB ESCBEG:: CLR R5 ; Look for begin sequence BR 1$ ESCEND:: MOV #177,R5 ; Look for end sequence 1$: TSTEQ R4,7$ ; No escapes ? TSTNEB $ESCSW,7$ ; Escapes disabled ? MOV R3,-(SP) ; Save current buffer MOV #ESCBF,R3 ; Escape buffer CALL BEGBF ; Start at beginning MOV (SP)+,R3 ; Restore 2$: TSTEQ R4,7$ ; Done ? CALL 11$ ; Do next sequence BCC 2$ ; Ok ? 7$: RETURN 11$: MOV R3,-(SP) ; Save current buffer MOV #ESCBF,R3 ; Escape buffer 12$: CALL GBYT ; Get count BCS 17$ ; Done ? MOV BF.FUL(R3),-(SP) ; And current index MOV R1,R2 ; Character count CALL GBYT ; Skip 1 byte CALL GBYT ; Skip 1 byte CALL GBYT ; Skip 1 byte MOV R1,-(SP) ; Save status BITNEB #ES.LCK,R1,4$ ; Is this lock status ? 3$: TST (SP)+ ; Pop status MOV R2,R1 ; number of bytes to skip ADD (SP)+,R1 ; New index CALL FNDBF ; skip them BR 12$ ; Try again 4$: CALL GBYT ; Get lock byte BLT 5$ ; Unlock ? TSTNEB R5,3$ ; Lock desired ? ADD #BITABL,R1 ; Now points to table BITEQ (R1),R4,3$ ; Not requested escape ? BIC (R1),R4 ; Clear 1 bit BR 31$ ; Ok! 5$: TSTEQB R5,3$ ; Unlock desired ? ADD #BITABL-177600,R1 ; Compensate for hi bits BITEQ (R1),R4,3$ ; Not requested escape ? BIC (R1),R4 ; Clear 1 bit BITNE (R1),TESMSK,32$ ; Clearing temporary bit? BR 31$ ; ; R5 = first char ; R1 = second char ; R3,R5 are preserved ; C = set if sequence not found ; ESCSEQ: MOV R3,-(SP) ; save current buffer MOV #ESCBF,R3 ; escape buffer MOV R1,R4 ; SAVE CHAR CALL BEGBF ; Start at beginning 10$: CALL GBYT ; get beginning of sequence BCC 20$ ; not end of table? MOVB R4,R1 ; GET CHAR BACK 17$: MOV (SP)+,R3 ; restore 15$: SEC ; NO SEQ FOUND RETURN 20$: MOV BF.FUL(R3),-(SP) ; And save current index MOV R1,R2 ; number of bytes in sequence CALL GBYT ; get next bytes CMPNEB R5,R1,25$ ; MATCH WITH CHAR? CALL GBYT ; get next bytes CMPEQB R4,R1,30$ ; MATCH WITH CHAR? 25$: MOV R2,R1 ; number of bytes to skip ADD (SP)+,R1 ; add on current index CALL FNDBF ; skip them BR 10$ 30$: TSTEQB $ESCSW,27$ ; ESCAPE SEQUENCES not DISABLED? JMP 55$ ; Disabled 27$: BISB #SW.TDS,$AUHYP ; set temporary no hyphenation CALL GBYT ; Get flag byte BEQ 40$ ; No flag byte ? MOVB R1,-(SP) ; Save bit mask BITEQB #ES.LCK,(SP),31$ ; Not lock/Unlock ? CALL GBYT ; Get lock word BLT 21$ ; Unlock ? ADD #BITABL,R1 ; Points to bit table BITNE (R1),ESMSK,54$ ; Is it currently locked on ? BIS (R1),ESMSK ; Lock it on TST R5 ; Do we do temporary lock BGT 31$ ; No BITEQB #ES.CHR,(SP),31$ ; Not temporary sequence BIS (R1),TESMSK ; Set temporary mask BR 31$ 21$: ADD #BITABL-177600,R1 ; Compensate for hi bits BITEQ (R1),ESMSK,54$ ; Currently locked off ? 32$: BIC (R1),ESMSK ; Lock it off BIC (R1),TESMSK ; Clear temporary mask also 31$: BITEQB #ES.VSP,(SP),33$ ; No vertical spacing CALL GBYT ; Get vertical spacing TSTNEB $PAGNG,299$ ; No paging ? SUB R1,LINEC3 ; Decrement lines left ADD R1,BF.VSP(R3) ; Add to saved spacing 299$: ADD CURVS,R1 ; Add on current VS MOV R1,CURVS ; Save current CMP R1,MINVS ; Compare with min BGT 311$ ; Bigger ? MOV R1,MINVS ; New min 311$: CMP R1,MAXVS ; Compare with max BLT 312$ ; Smaller ? MOV R1,MAXVS ; New max 312$: ADD R1,BF.VSP(R3) ; Count deferred text line 33$: BITEQB #ES.HSP,(SP),37$ ; No Horizontal spacing CALL GBYT ; Get horizontal spacing BITNEB #ES.PSP,(SP),35$ ; Permanent spacing ? MOVB R4,LCH ; Set last char ADD R1,SPCH ; Count spacing chars SUB R1,LINBK ; And remove from available spaces BR 37$ 35$: BICB #40,$NOSPC ; Set for expandable spaces ok BICB #40,$TABSW ; Enable tabs MOV R1,PHSP ; Set permanent horiz spacing BICB #SW.TD2,$AUHYP ; Temporary hyphenation off CMPEQ R1,#1,37$ ; Spacing 1 ? BISB #SW.TD2,$AUHYP ; set temporary no hyphenation BISB #40,$NOSPC ; Set no expandable spaces BISB #40,$TABSW ; Set no tabs 37$: TST (SP)+ ; Pop saved flags 40$: MOV (SP)+,R1 ; Index for transfer ADD #2,R1 ; Points to status now SUB #2,R2 ; Number of bytest to transfer CALL FNDBF ; Go back to start of sequence MOV (SP)+,R3 ; Output buffer MOV #ESC,R1 ; Mark escape sequence in output buffer 45$: CALL PUBYT ; OUTPUT IT 50$: MOV #ESCBF,R1 ; escape buffer CALL GBYT1 ; get next bytes CALL PBYT ; OUTPUT CHAR SOB R2,50$ CALL CBYT ; Null Into buffer BR 60$ 54$: TST (SP)+ ; Pop stack 55$: TST (SP)+ ; Pop stack MOV (SP)+,R3 ; Restore buffer address 60$: CLC ; SUCCESS RETURN ; .DSABL LSB ; ; ROUTINE TO FIND NEXT TABSTOP FOR OUTLIN ROUTINE. ; INPUT R2= Space to include ; OUTPUT R2= DISTANCE TO NEXT STOP ; R0,R1 are destroyed ; TABB: MOV R3,-(SP) ; Save R3 MOV #TABBF,R3 ; Set to search tab buffer CALL BEGBF ; Start at beginning ADD SPCH,R2 ; NUMBER OF SPACING CHARS ADD LMARG,R2 ; ADD ON LEFT MARGIN ADD INDCT,R2 ; PLUS INDENTATION 10$: CALL GWRD ; Get next tab BCS 30$ ; End of buffer ? CMP R1,R2 ; Compare tab with current position BGT 20$ ; Larger than current ? CALL GBYT ; Get status BIC #^C,R1 ; Chars to skip BEQ 10$ ; None ADD BF.FUL(R3),R1 ; Add on current location CALL FNDBF ; Skip em BR 10$ 20$: CMP R1,RMARG ; Compare with right margin BLE 40$ ; Is it smaller than margin ? 30$: MOV RMARG,R1 ; No ASSUME A TABSTOP AT RIGHT END 40$: SUB R2,R1 ; GET DISTANCE TO TABSTOP MOV R1,R2 ; ANSWER IN A BGT 50$ ; At least 1 space? MOV #1,R2 ; No make it 1 50$: MOV (SP)+,R3 ; Restore RETURN ; ; ; UPPER CASE FLAG ; .ENABL LSB SHFUP: TSTEQB $SFLSW+1,1$ ; Flag not disabled ? JMP GCINR 1$: CALL CCIN ; READ A CHARACTER BITEQB CHTABL(R1),#CH.FLG,40$ ; Not flag character ? CMPNE R1,$UFLSW,10$ ; LOCK ON UNDERLINE? BICB #SW.TDS,$UNLSW ; UNDERLINING POSSIBLY ON BR 30$ 10$: CMPNE R1,$CFLSW,20$ ; NOT LOCK UPPER CASE? MOV #401,CASE ; SET UPPER CASE + LOCK BR 30$ ; READ ONOTHER CHAR 20$: CMPNE R1,$SFLSW,40$ ; NOT UNLOCK ALL? CALL UPCAS ; SET TO UPPER CASE 30$: JMP GCIN ; AND GO READ ANOTHER CHARACTER 40$: MOVB $SFLSW,R5 ; MATCH CHAR CALL ESCSEQ ; SEARCH FOR ESCAPE SEQUENCE BCC 30$ ; FOUND ONE! MOVB GCTABL(R1),R0 ; CHAR TYPE? CMPNE R0,#GC.LC,50$ ; NOT LOWER CASE? JMP GCUP1 ; LOWER CASE, SHIFT IT. 50$: CMP R0,#GC.LC ; ALPHABETIC CHAR? BLE 60$ ; YES, DO NOT EXECUTE IT JMP @GCJMP(R0) ; DISPATCH IT 60$: JMP GCINR ; ; LOWER CASE FLAG DETECTED ; SHFDN: TSTEQB $LFLSW+1,2$ ; Flag not disabled ? JMP GCINR 2$: CALL CCIN ; GET ANOTHER CHARACTER BITEQB CHTABL(R1),#CH.FLG,80$ ; Not flag character ? CMPNE R1,$UFLSW,70$ ; UNLOCK UNDERLINE? BISB #SW.TDS,$UNLSW ; UNDERLINING OFF BR 30$ ; 70$: CMPNE R1,$LFLSW,80$ ; NOT LOWERCASE LOCK? CALL LWCAS ; SET LOWER CASE SHIFT BR 30$ ; 80$: MOVB $LFLSW,R5 ; MATCH CHAR CALL ESCSEQ ; HANDLE ESCAPE SEQUENCES BCC 30$ ; FOUND ESC SEQ MOVB GCTABL(R1),R0 ; CHAR TYPE? CMPNE R0,#GC.UC,50$ ; NOT UPPER CASE? BITNE #UPCSW,$SWTCH,60$ ; IS UP SHIFT MANDATED? JMP GCDN1 ; SHIFT TO LOWER CASE .DSABL LSB ; ; CASE SELECTION COMMANDS ; .ENABL LSB LWCAS:: MOV #-1,R1 ; SET FOR CONVERSION TO LOWER CASE BR 10$ ; UPCAS:: CLR R1 ; SET FOR NO CASE CONVERSION 10$: BITEQ #UPCSW,$SWTCH,20$ ; Not Upper case only? MOV #401,R1 ; FORCE TO UPPER CASE 20$: MOV R1,CASE ; SET CASE CONVERSION RETURN ; .DSABL LSB ; ; COROUTINE TO SHIFT TO UPPER CASE TEMPORARILY ; SHFUC:: MOV (SP),-(SP) ; COPY RETURN ADDRESS MOV CASE,2(SP) ; SAVE CURRENT CASE MOV #401,CASE ; UPPER CASE ONLY CALL @(SP)+ ; CALL THE CALLER BACK MOV (SP)+,CASE ; RESTORE PREVIOUS CASE SHXIT: RETURN ; ; ; PUT STRING ENDED BY ZERO BYTE TO BUFFER ; R0= STRING ADDRESS ; PSTRZB::MOV R2,-(SP) ; Save R2 MOV R0,R2 10$: MOVB (R2)+,R1 ; Get char BEQ 20$ ; If zero done ? CALL PBYT ; PUT IT INC BF.SPC(R3) ; Count chars BR 10$ ; CONTINUE 20$: MOV (SP)+,R2 ; Restore RETURN ; ; ROUTINES TO OUTPUT A STRING TO THE OUTPUT FILE ; R3=BUFFER ADDRESS FOR STRING ; Output terminates at either null or end of input buffer ; Z or C tell user what form of termination occurred. ; ; This one starts at top of buffer PSTRPA::CALL BEGBF ; SET TO TOP OF BUFFER CLRB EXSP1 ; No multiple spaces CLRB EXSP2 ; No multiple spaces CLRB EXSP3 ; No multiple spaces CLRB EXSTAT ; No status MOVB #-1,EXMSP ; No multiple micro spaces ; ; This one starts anywhere in buffer ; R3 is preserved all other registers destroyed ; CCOUT:: CLRB $ULOSW ; No underlining at first CCOUT1: CLRB $ULOSW ; Reset underlining CCOUT2: CALL GBYT ; Get 1 byte BCS GOEND BGT 10$ ; No extra bits BEQ GOEND ; End of input buffer ? INCB $ULOSW ; Set underline BIC #^C<177>,R1 ; Clear extra bits 10$: CMPEQB R1,#SPC,GOSPC ; Is it space ? MOVB GCTABL(R1),R0 ; GET CHAR TYPE BGE GOPRN ; PRINTABLE JMP @GCJMP(R0) ; EXECUTE FUNCTION ; Handle single underline GOUNL: INCB $ULOSW BR CCOUT2 ; Printable char GOPRN: CALL CCPRN ; Print 1 char BR CCOUT1 GOSPC: MOVB EXSP1,-(SP) ; YES. HOW MANY MULTIPLE SPACES? MOVB EXMSP,1(SP) ; Micro spaces DECB EXSP2 ; TO EXTRA BLANKS YET? BGE 70$ ; NO. TSTEQB EXSP3,80$ ; EXTRA SPACES TO RIGHT? BR 90$ ; LEFT. NO MORE EXTRAS, JUST LOOP 70$: TSTEQB EXSP3,90$ ; NO EXTRA SPACES LEFT OR RIGHT? 80$: BITEQB #HD.VAR,EXSTAT,85$ ; No micro spacing ? INCB 1(SP) ; Micro spacing count BR 90$ 85$: INCB (SP) ; Extra space to output 90$: BITEQB #HD.VAR,EXSTAT,110$ ; No micro spacing ? MOVB 1(SP),R1 ; count BLE 110$ ; micro count too small ? TSTEQB $ULMSW,94$ ; Underline by BS ? MOV CPOS,R0 ; Current position CMP R0,#ULNSZ ; check with max BHI 95$ ; Too big ? BIS #200,R1 ; Now is count for underline buffer MOVB R1,UBUFF-1(R0) ; Into buffer MOVB #-1,$UNLRS INC CPOS ; Next position BR 95$ 94$: TSTEQB $ULOSW,95$ ; No underlining ? MOV #1,R2 ; Number of chars to underline CALL CCUNL 95$: DECB 1(SP) ; Count micro spaces BLT 110$ ; None ? MOV #VARESC+1,R2 ; Address of escape sequence buffer 100$: MOVB (R2)+,R1 ; Data to output BEQ 95$ ; Another to output CALL FOUT ; Output it BR 100$ ; And try again 110$: CALL CCSPC ; OUTPUT SPACES DECB (SP) ; Decrement counter BGT 110$ ; Not done ? TST (SP)+ ; Pop counter JMP CCOUT1 GOQTS: CALL CCSPC ; Turn quoted space to single space JMP CCOUT1 GOEND: RETURN GOESC: CALL GBYT ; Get flag byte BEQ 90$ ; No flag byte ? MOVB R1,-(SP) ; Save bit mask BITEQB #ES.LCK,(SP),10$ ; Not lock/Unlock ? CALL GBYT ; Get lock word 10$: BITEQB #ES.VSP,(SP),20$ ; No vertical spacing CALL GBYT ; Get vertical spacing TSTNEB $PAGNG,20$ ; No paging SUB R1,LINEC1 ; Decrement lines left SUB R1,LINEC2 ; Decrement lines left 20$: BITEQB #ES.HSP,(SP),80$ ; No Horizontal spacing CALL GBYT ; Get horizontal spacing BLE 80$ ; Too small ? BITNEB #ES.PSP,(SP),40$ ; Permanent spacing ? TSTNEB $ULOSW,30$ ; Underline ? ADD R1,CPOS ; No BR 80$ 30$: MOV R1,R2 ; Number of undelines CALL CCUNL ; Perform underlining BR 80$ 40$: MOV R1,PHSPOU ; Set permanent horiz spacing ; ; Now output escape sequence ; 80$: TST (SP)+ 90$: CALL GBYT ; Get escape sequence chars BEQ 100$ ; Done ? CALL FOUT ; Output char with no interpretation BR 90$ ; More ? 100$: JMP CCOUT1 ; End of escape seq buffer ? ; Handle backspaces GOBS: SUB PHSPOU,CPOS ; New position BGT 10$ ; OK ? MOV #1,CPOS ; No, make it 1 10$: CALL FOUT ; Output backspace JMP CCOUT1 ; Handle tabs GOTAB: CALL GBYT ; Get next input byte MOVB R1,-(SP) ; Save it 10$: DECB (SP) ; Done? BGE 20$ ; Not done yet TST (SP)+ ; Pop stack JMP CCOUT1 20$: CALL CCSPC ; Output a space BR 10$ ; Check it ; Handle tabs with ellipses GOELP: CALL GBYT ; Get 1 byte CLR -(SP) ; Clear counter on stack MOVB R1,(SP) ; Save count CALL GBYT ; Get ellipses count MOV #TBUFF,R4 ; Temporary buffer MOV R1,R2 ; Count MOV R1,R5 ; Count BEQ 6$ ; No ellipse spec ? 5$: CALL GBYT ; Get chars MOVB R1,(R4)+ ; Till done SOB R5,5$ ; Get them all BR 7$ 6$: MOVB #' ,(R4)+ ; set first MOVB #'.,(R4)+ ; second MOV #2,R2 ; And count 7$: CLRB (R4)+ ; chock buffer DEC (SP) ; Output 1 char ? BLE 15$ ; No, done CALL CCSPC ; DIV$ R2,CPOS ; Divide CPOS/R2 result = R0 ADD #TBUFF-1,R1 ; Add on temporary buffer address MOV R1,ADDR 10$: DEC (SP) BGT 20$ ; Spaces to output ? 15$: BLT 16$ ; No output ? CALL CCSPC ; Output 1 space 16$: TST (SP)+ ; Done so pop stack JMP CCOUT1 20$: INC ADDR MOVB @ADDR,R1 ; Char to print BNE 30$ ; Char ok ? MOV #TBUFF-1,ADDR ; No, start at beginning BR 20$ 30$: CALL CCPRN ; Output printable char BR 10$ ; ; Handle repeated output ; GOREP: CALL GBYT ; Get repeat count BEQ 50$ ; Repeat zero ? CLR -(SP) ; Clear count on stack MOVB R1,(SP) ; Save count MOV BF.FUL(R3),-(SP) ; Save input index 10$: CALL CCOUT1 ; Now output string DEC 2(SP) ; Done ? BLE 20$ ; Yes ? MOV (SP),R1 ; Rewind input buffer CALL FNDBF ; Back over string BR 10$ ; Repeat 20$: ADD #4,SP ; Pop stack JMP CCOUT1 ; And continue 50$: CALL 55$ ; Stack up reequest to kill repeat JMP CCOUT1 ; And continue 55$: CALL GBYT ; Get char BNE 60$ ; Not done ? RETURN 60$: CMPEQB R1,#ESC,70$ ; Escape sequence ? CMPNEB R1,#REPO,55$ ; No repeat ? CALL GBYT ; Skip count CALL 55$ ; Stack another skip BR 55$ ; Done with imbedded repeat 70$: CALL GBYT ; Skip status 80$: CALL GBYT ; Get sequence BNE 80$ ; Not terminator ? BR 55$ ; ; section to fill in index entries ; GOINX: CALL GWRD ; Get address inside index buffer MOV R1,R4 ; backward link MOV R3,-(SP) ; Save MOV #INXBF,R3 ; Get index buffer address CALL FNDBF ; get next entry BCS 90$ CALL GWRD ; get link to next MOV R1,R5 10$: MOV R5,R1 ; next entry BEQ 15$ ; End of line ? CALL FNDBF ; find it BCS 90$ ; OK ? CALL GWRD ; get next foreward link BCS 90$ ; end of input MOV R1,R2 CALL GBYT ; get status byte BCS 90$ ; end of input BITNE #X.ENT,R1,15$ ; No entry ? MOV R5,R4 ; R4 has backward link MOV R2,R5 ; next foreward link BR 10$ 15$: MOV R4,R1 ; Go back to last one CALL FNDBF ; Get the index entry address BCS 90$ MOV BF.MAX(R3),R1 ; New entry address CALL PWRD ; Link to end CALL ENDBF ; Now go to end MOV R5,R1 ; Save foreward link CALL PWRD MOV #X.PAG,R1 ; Set for page number TSTNEB $CHPSW,30$ ; no chapter print? TSTEQB APNDN,20$ ; No appendix? BIS #X.AP,R1 ; Set appendix status BR 30$ ; no chapter if appendix 20$: TSTEQB CHPTN,30$ ; No chapter? BIS #X.CH,R1 30$: TSTEQB SUBPGE,40$ ; No subpage? BIS #X.SPG,R1 40$: CALL PBYT ; Save status bits TSTNEB $CHPSW,60$ ; no chapter print? MOV APNDN,R1 BEQ 50$ CALL PBYT ; put appendix BR 60$ 50$: MOVB CHPTN,R1 BIC #^C<377>,R1 ; Clear extra BEQ 60$ CALL PBYT ; put chapter 60$: MOV PAGENO,R1 BNE 65$ ; Not zero ? INC R1 ; Make it 1 65$: BIS PAGDSP,R1 ; Add on display bits CALL PWRD ; put chapter 70$: MOV SUBPGE,R1 BEQ 80$ CALL PBYT ; put subpage 80$: MOV (SP)+,R3 ; Restore JMP CCOUT1 90$: CALL HLTER ; ; Routine to output TOC entries ; GOTOC: MOV #TTBUF,R2 ; Get temporary buffer 10$: CALL GBYT ; Get 1 byte MOVB R1,(R2)+ ; Into buffer BNE 10$ MOV #TTBUF+1,R1 ; Address of array SUB R1,R2 ; Size of array DEC R2 ; Final BLE 40$ ; None ?? CALL OUTTOC ; Output the toc line TSTB TTBUF ; Check type of output BLE 40$ ; No number requested ?? MOV R3,-(SP) ; Save R3 MOV #TTBF,R3 ; Get temporary buffer CALL CLRBF ; Clear it MOV #TAB,R1 ; Tab char. CALL PBYT ; into buffer CALL PUTPAG ; Get page number MOV BF.FUL(R3),R2 ; Get size MOV (SP)+,R3 ; Restore MOV #TTBUF,R1 ; Start of buffer CALL OUTTOC ; And output it 40$: JMP CCOUT1 ; ; Set up page number ; GOPAG: MOV R3,-(SP) CALL GWRD ; Get page number index MOV R1,R2 MOV #SUBF0,R3 ; Substitution buffer CALL BEGBF ; Reset to beginning of buffer MOV R2,R1 CALL FNDBF ; Get location BCS 10$ CALL GETPAG ; Get page number 10$: MOV (SP)+,R3 ; Restore JMP CCOUT1 ; Return ; ; Routine to get page number into buffer in symbolic rep. ; GETPAG::CLR R1 TSTNEB $CHPSW,20$ ; No chapter ? MOV APNDN,R1 ; Get appendix BEQ 10$ BIS APNDSP,R1 ; And format BR 20$ 10$: MOVB CHPTN,R1 ; Chapter number BIC #^C<377>,R1 ; Clear extra BEQ 20$ ; None ? BIS CHPDSP,R1 ; And format 20$: CALL PWRD MOV PAGENO,R1 ; Get page number BNE 25$ ; Not zero ? INC R1 ; Set it to 1 25$: BIS PAGDSP,R1 ; Set format CALL PWRD ; Save current page CLR R1 ; Incase no subpage TSTEQB $SBPSW,30$ ; No subpage ? MOVB SUBPGE,R1 ; Get subpage BIS SUBDSP,R1 ; And format 30$: CALL PWRD RETURN ; ; Subroutine to output printable chars ; CCSPC:: MOV #SPC,R1 ; GET SPACE CCPRN: TSTEQB $ULOSW,NOUNL ; No underlining ? MOV PHSPOU,R2 ; Number of underlines CALL CCUNL ; YES, DO IT JMP FOUT ; output character NOUNL: ADD PHSPOU,CPOS ; INCREMENT POSITION COUNTER JMP FOUT ; OUTPUT CHAR ; ; Do underlining ; CCUNL: MOV R1,-(SP) ; SAVE CHAR 80$: TSTB $ULMSW BNE 90$ ; Underline by line or sim. ? MOV R2,-(SP) ; Save count ADD R2,CPOS ; New position 82$: MOV #LPUS,R1 ; GET UNDERLINE CALL FOUT ; OUTPUT IT SUB PHSPOU,R2 ; Remaining count BGT 82$ ; More to do ? MOV (SP)+,R2 ; Get count again 84$: MOV #BS,R1 ; GET BACKSPACE CALL FOUT ; OUTPUT IT SUB PHSPOU,R2 ; Remaining count BGT 84$ ; More to do ? BR 100$ 90$: MOV CPOS,R0 ; POSITION CMP R0,#ULNSZ ; TOO BIG? BHI 95$ ; YES MOVB $ULCH,UBUFF-1(R0) ; PUT IT INTO BUFFER CMP R0,ULNMAX ; SMALLER DUE TO BS BLOS 100$ ; YES, KEEP MAX MOV R0,ULNMAX ; AND SAVE LAST ADDRESS 95$: INC CPOS SOB R2,90$ ; Do it for each char 100$: MOV (SP)+,R1 ; GET SAVED CHAR RETURN ; ; Output byte underlined ; PUBYT0: ADD PHSP,SPCH ; Add to spacing char count MOVB R1,LCH ; SAVE LAST CHARACTER PUBYT:: TSTNEB $UNLSW,11$ ; No underline this char ? TSTNE @EQSTK,11$ ; Equation in progress ? BIC #^C<177>,R1 ; Set to proper range BITNEB #CH.UNL,CHTABL(R1),11$ ; Underlining not allowed ? BIS #200,R1 ; Mark it as underlined 11$: JMP PBYT ; OUTPUT CHAR ; ; This is an equation writing routine ; It will parse fractions written in the form: ; { . . . }/{. . .} ; and using standard letter quality printer escape sequences ; generate factions. ; ; ; The first left brace generates: ; 1. Shift up ; 2. Multiple spaces = 0 ; ; The numerator right brace ( }/{ ) ; 1. Shift down ; 2. Multiple BS ; 3. Multiple underscore ; 4. Multiple BS ; 5. Shift down ; ; Denominator right brace ; 1. Multiple spaces ? ; 2. Shift up ; ; EQSTK contains the following ; Word 0 = 0 ; . . . . . . . ; 1+N = Index points to beginning of numerator ; 2+N = Shift up count ; 3+N = Vertical space occupied ; 3+N = Current spacing ; 4+N = Type (1 = Numerator, 2 = Denom.) ; . . . . . . . ; EQ.HS=-2 ; Offset from type EQ.VSZ=-4 ; Offset to vertical size EQ.VSP=-6 ; Offset from type for horiz spacing param EQ.AD=-8. ; Offset from type for address of output EQ.NX=-10. ; Offset to next stack entry ; ; Add word to equation stack ; R0=word to add ; STACK: CMP EQSTK,#EQSEN-2 ; Past end of stack ? BHIS EQERR3 ; Yes ? ADD #2,EQSTK ; Incrment stack pointer MOV R0,@EQSTK ; Save value RETURN EQERR3: MOV #EQER3,R0 CALL ILCMC ; Output error message JMP GCIN ; ; ; Routine to alter shifts if necessary ; SHIFT: CMP R1,EQ.VSP(R5) ; Extra shift needed BLE 10$ ; No extra needed MOV R1,EQ.VSP(R5) 10$: MOV EQ.VSP(R5),R1 ; New shift count CMP R2,EQ.VSZ(R5) ; Check vertical size BLE 20$ ; Not larger than saved ? MOV R2,EQ.VSZ(R5) ; Save new one 20$: MOV EQ.VSZ(R5),R2 ; New vertical size RETURN ; ; Found left brace { ; ; ; Service equation flags ; GCEQN1: TSTNEB $EQFSW+1,NOEQ ; No equations allowed ? MOVB #'(,R1 ; Just in case no flag TSTNEB $EQUSW,NOEQ ; Equation disabled ? CALL PADIT ; Check for subscripts/superscripts MOV BF.FUL(R3),R0 ; And current buffer pointer INC R0 CALL STACK ; EQ.AD MOV #1,R2 ADD EQSPC,R2 ; Plust extra MOV R2,R0 ; Save on stack CALL STACK ; EQ.VSP CALL UP ; Shift up CLR R0 ; Vertical size CALL STACK ; EQ.VSZ MOV SPCH,R0 ; Save the current spacing chars CALL STACK ; EQ.HS MOV #1,R0 ; And now the type CALL STACK ; EQ.TYP MOV #NXS,R4 ; Character to store CLR R2 ; Number of times CALL REPEAT JMP GCIN ; Continue NOEQ: JMP GCINR ; No char formation ; ; Found right brace } ; GCEQN2: TSTNEB $EQFSW+1,NOEQ ; No equations allowed ? MOVB #'),R1 ; In case no equation TSTNEB $EQUSW,NOEQ ; Equation disabled ? CALL PADIT ; Check for subscripts/superscripts MOV EQSTK,R5 ; Get current stack CMPNE (R5),#1,10$ ; End of denominator ? JMP GCEQ3 ; Parse End of numerator 10$: CMPEQ (R5),#2,11$ ; End of denom ? JMP EQERR4 11$: MOV EQ.VSP(R5),R2 ; Shift back up CALL UP MOV SPCH,R2 ; Current spacing SUB EQ.NX+EQ.HS(R5),R2 ; - previous spacing BGT 12$ ; OK ? JMP EQERR4 ; Bad ? 12$: SUB EQ.HS(R5),R2 ; Subtract numerator spacing BEQ 50$ ; Done ? BGT 40$ ; Denom bigger ? NEG R2 ADD R2,SPCH ; Adjust spacing char count SUB R2,LINBK MOV R2,-(SP) ; Save ASR R2 ; Divide by 2 BEQ 20$ ; No spaces at end MOV #NXS,R4 ; Add on spaces at end CALL REPEAT 20$: SUB R2,(SP) ; Now spacing at beginning of line MOV (SP)+,R2 ; Get result BEQ 50$ ; None at beginning MOV EQ.AD(R5),R1 ; Buffer index for spacing CALL FNDBF 30$: CALL ENDREP ; Skip shift down 1. CALL ENDREP ; Skip BS 2. CALL ENDREP ; Skip underline 3. MOV EQ.HS(R5),R1 ; Previous spacing SUB R2,R1 ; New Backspace count CALL PBYT ; Save the space count BR 50$ ; Now handle vertical spacing 40$: MOV R2,-(SP) ; Save count ASR R2 ; Divide by 2 BEQ 45$ ; No count MOV EQ.NX+EQ.AD(R5),R1 ; left brace output index CALL FNDBF CALL ENDREP ; Now have spacing count MOV R2,R1 ; Actual number of spaces CALL PBYT 45$: MOV EQ.AD(R5),R1 ; Get index CALL FNDBF ; Get location CALL ENDREP ; Skip shift param MOV EQ.HS(R5),R1 ; Backspace count ADD R2,R1 ; + spaces at beginning CALL PBYT ; And save it CALL ENDREP ; Now have underline repeat ADD EQ.HS(R5),(SP) ; Total number of char in denom MOV (SP),R1 ; Actual underline size CALL PBYT CALL ENDREP ; Next BS MOV (SP)+,R1 ; Number to do CALL PBYT 50$: MOV EQ.NX+EQ.AD(R5),R1 ; Adjust the vertical spacing CALL FNDBF ; Get vertical spacing repeat MOV EQ.NX+EQ.VSP(R5),R1 ; Adjusted vertical spacing MOV R1,R2 ; Save CALL PBYT MOV EQ.AD(R5),R1 ; Denominator CALL FNDBF DEC R2 ; MOV R2,R1 ; Back to line vs CALL PBYT MOV #4,R4 ; Skip 4 params 60$: CALL ENDREP SOB R4,60$ MOV EQ.VSP(R5),R1 INC R1 ; Plus 1 CALL PBYT ; New vertical spacing MOV EQSTK,R0 ; Current stack address MOV EQ.VSZ(R0),R1 ; Denominator ADD EQ.VSP(R0),R1 ; Total denom size ADD #EQ.NX,R0 ; Next entry MOV EQ.VSZ(R0),R2 ; Numerator size ADD EQ.VSP(R0),R2 ; Total numerator size ADD #EQ.NX,R0 ; Next entry MOV R0,EQSTK TSTNE (R0),80$ ; Equation not ended ? TSTEQB $SEQSW,80$ ; No separated equations ? BITNE #FOTF,F.1,80$ ; Footnote in progress ? TST LINBK ; Past end of line ? BLT 80$ ; Do not save size DEC R1 ; Size -1/2 line already accounted for DEC R2 ; Ditto CMP R1,EQBOT ; Compare with current value BLE 65$ ; Smaller ? MOV R1,EQBOT ; Save size 65$: CMP R2,EQTOP ; Compare with current value BLE 68$ ; Smaller ? MOV R2,EQTOP ; Save top size 68$: CALL BRKSV ; Put line break here 80$: CALL ENDBF ; Back at end of buffer JMP GCIN ; Continue ; ; Error during text processing ; EQERR4: MOV #EQER4,R0 CALL ILCMC ; Output error message JMP GCIN ; Next char ; ; End numerator ; GCEQ3: CALL CCIN ; Get next char (look for /) CMPEQB R1,#SPC,GCEQ3 ; Space ? CMPEQB R1,#TAB,GCEQ3 ; Tab ? CMPNEB R1,#'/,EQERR4 ; Error in parsing ? not slash ? 10$: CALL CCIN ; Get next char (look for } ) CMPEQB R1,#SPC,10$ ; Space ? CMPEQB R1,#TAB,10$ ; Tab ? CMPNEB R1,#'{,EQERR4 ; Error in parsing ? not left brace ? MOV BF.FUL(R3),R0 ; And current buffer pointer INC R0 CALL STACK ; EQ.AD MOV EQ.VSP(R5),R2 ; Previous vertical shift DEC R2 ; - 1 CALL DOWN ; Now execute a shift down MOV #1,R0 ADD EQSPC,R0 ; Vertical shift for stack CALL STACK ; EQ.VSP Save shift on stack CLR R0 ; Vertical size CALL STACK ; EQ.VSZ MOV SPCH,R0 ; Current spacing SUB EQ.HS(R5),R0 ; Horizontal movement MOV R0,R2 ; Save BLE EQERR4 ; Bad ? SUB R0,SPCH ADD R0,LINBK ; Set back to old spacing char CALL STACK ; EQ.HS Save it for convenience MOV #2,R0 ; And now the type CALL STACK ; EQ.TYP MOV #BS,R4 ; Repeat backspace CALL REPEAT MOV #'_,R4 ; Repeat underline CALL REPEAT MOV #10,R4 ; Back space again CALL REPEAT MOV #2,R2 ; Down shift to execute CALL DOWN ; Now shift down JMP GCIN ; ; Pad the equation with 1/2 lines as necessary ; PADIT: MOV EQSTK,R5 ; Get stack location TSTEQ (R5),100$ ; First time thru ? MOV MINVS,R2 ; Subscripts NEG R2 ; Correct sign MOV MAXVS,R1 ; Plus Superscripts INC R1 ; Account for 1/2 line INC R2 ; Ditto 5$: CMPEQ (R5),#1,10$ ; Numerator ? MOV R2,-(SP) MOV R1,R2 ; Reverse order MOV (SP)+,R1 10$: TSTEQ (R5),100$ ; Done ? CALL SHIFT ; Check if spacing is correct CMPEQ (R5),#1,30$ ; Current is numerator ? ADD #EQ.NX,R5 ; Next entry ADD R2,R1 ; Now is shift up MOV EQ.VSZ(R5),R2 ; Get size above numerator ADD EQ.VSP(R5),R2 ; Add shift up ADD #EQ.NX,R5 ; Next entry BR 5$ 30$: ADD #EQ.NX,R5 ; Next entry CMPEQ (R5),#1,40$ ; Another numerator? ADD R2,R1 ; Add size to shift CLR R2 ; Clear shift BR 10$ 40$: ADD R1,R2 ; Add shift to spacing CLR R1 BR 10$ 100$: CLR MAXVS ; Maximum vertical spacing CLR MINVS ; Minimum vertical spacing CLR CURVS ; And clear current RETURN ; ; Enter repeating char into output ; R4=Char to repeat ; R2=Repeat count ; REPEAT: MOV #REPO,R1 ; Set for repeat CALL PBYT MOV R2,R1 ; Repeat count CALL PBYT MOV R4,R1 ; Char to repeat CALL PBYT ; Now output character CALL CBYT RETURN ; ; Put up/down shifts into output ; UP: MOV #REPO,R1 ; Get repeat char CALL PBYT ; To output MOV R2,R1 ; Number of shifts CALL PBYT 10$: MOV #UPTAB,R2 ; Characters to transfer 20$: MOVB (R2)+,R1 ; Get char BEQ 30$ ; End of buffer CALL PBYT ; Into output buffer BR 20$ 30$: CALL PWRD ; Terminate escape + repeat RETURN DOWN: MOV #REPO,R1 ; Get repeat char CALL PBYT ; To output MOV R2,R1 ; Number of shifts CALL PBYT 10$: MOV #DNTAB,R2 ; Characters to transfer 20$: MOVB (R2)+,R1 ; Get char BEQ 30$ ; End of buffer CALL PBYT ; Into output buffer BR 20$ 30$: CALL PWRD ; Terminate sequence RETURN ; ; Subroutine to find end of repeat function ; ENDREP: CALL GBYT ; Get next char in output buffer 1$: CALL GBYT BNE 1$ ; Not at end of repeat 20$: CALL GBYT ; Begin next param BEQ 20$ ; Another null ? RETURN ; ; End equation by end of line ; GCEQN: CALL BKSPI ; Again ? CMPNE EQSTK,#EQSTK+2,10$ ; Not at end of stack JMP GCIN 10$: JMP EQERR4 ; Bad equation .END