.title EQATN .ident /BL1.0/ ; ; This is an equation writing routine ; It will parse fractions written in the form: ; { . . . }/{. . .} ; and using standard letter quality printer escape sequences ; generate factions. ; .psect $TABL,RO,LCL,CON,D EQTAB: .ASCIZ \{}\ EQER3: .ASCIZ /RNO -- Too many nested fractions/ EQER4: .ASCIZ /RNO -- Syntax error in equation/ .even .PSECT $CODE,I,RO,LCL,CON ; ; 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 ; ; ENABLE EQUATION ; ENEQU:: BICB #SW.DIS,$EQUSW ; Enable equations CALL (R4) ; Get equation index JMP 50$ ; No params CMP R3,#6 ; Too big ? BHI EQERR0 ; Yes ? MOV R3,EQSPC ; Set equation spacing 50$: RETURN ; ; DISABLE EQUATION ; DSEQU:: BISB #SW.DIS,$EQUSW ; Disable equations RETURN ; ; EQUATION/END EQUATION commands ; BEGEQ:: BISB #SW.DIS,$SEQSW ; Enable separated equations RETURN ENDEQ:: BICB #SW.DIS,$SEQSW ; Disable separated equations RETURN ; ; FLAGS EQUATION ; EQERR0: JMP ILCM ; Illegal command error FLEQU:: MOV #EQTAB,R0 ; Equation character table TST $EQFSW ; Flags already enabled ? BGE 50$ ; Yes ? 10$: MOVB (R0)+,R1 ; First character BEQ 20$ ; Done ? BITNEB #CH.FLG,CHTABL(R1),60$ ; Already in use ? BR 10$ ; Try next 20$: MOV #EQTAB,R0 ; Table again 30$: MOVB (R0)+,R1 ; Character BEQ 40$ ; Done ? BISB #CH.FLG,CHTABL(R1) ; Set it as flag character BR 30$ 40$: MOV #EQTAB,R0 ; Now set up first character as trigger MOVB (R0)+,R1 ; Left braces MOVB #GC.EQ1,GCTABL(R1) ; First flag character MOVB (R0),R1 ; right braces MOVB #GC.EQ2,GCTABL(R1) ; second flag character BIC #100000,$EQFSW 50$: RETURN 60$: MOV #25.,R0 ; Error message JMP ILCMA NFLEQ:: TST $EQFSW ; Flag set ? BLT 50$ ; No BIS #100000,$EQFSW ; Set equation flag off MOV #EQTAB,R0 ; Get character table 10$: MOVB (R0)+,R1 ; Get character BEQ 50$ ; Done ? BICB #CH.FLG,CHTABL(R1) ; Reset flag characters MOVB #GC.MSC,GCTABL(R1) ; And pointers BR 10$ 50$: RETURN 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 EROUT CALL ONLIN 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 { ; GCEQ1:: MOVB #'(,R1 ; Just in case no flag TSTNEB $EQUSW,NOEQ ; Equation disabled ? MOVB #SW.EDS,R0 ; Get bit to set BISB R0,$NOSPC ; Set for no expandable spaces BISB R0,$TABSW ; Set for no tabs BISB R0,$HFLSW+1 ; Set no hyphenation flag BISB R0,$AUBRK ; Set no autobreak BISB R0,$UFLSW+1 ; Set no underline flag BISB R0,$BRFSW+1 ; No break flag BISB R0,$HYPSW ; No hyphenation 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 CONTIN: JMP GCIN ; Continue NOEQ: JMP GCINR ; No char formation ; ; Found right brace } ; GCEQ2:: 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,70$ ; No separated equations ? BITNE #FOTF,F.1,70$ ; Footnote in progress ? TST LINBK ; Past end of line ? BLT 70$ ; 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 70$: MOV #SW.EDS,R0 ; Bits to set BICB R0,$NOSPC ; Restore expandable spaces BICB R0,$TABSW ; Restore tabs BICB R0,$HFLSW+1 ; Restore hyphenation flag BICB R0,$AUBRK ; Restore autobreak BICB R0,$UFLSW+1 ; Restore underline flag BICB R0,$BRFSW+1 ; Restore break flag BICB R0,$HYPSW ; No hyphenation BR 80$ 80$: CALL ENDBF ; Back at end of buffer JMP GCIN ; Continue ; ; Error during text processing ; EQERR4: MOV #EQER4,R0 CALL EROUT CALL ONLIN JMP GCIN ; ; 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 CLR R1 ; Null marks end of repeat CALL PBYT 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:: ; End of equation by end of line CALL BKSPI ; Again ? CMPNE EQSTK,#EQSTK+2,10$ ; Not at end of stack ; CALL ENDEQ ; End equation mode JMP GCIN 10$: ;CALL ENDEQ ; End eq mode JMP EQERR4 ; Bad equation .END