.title ESCAPE .ident /BL1.0/ ; ; Programs to define escapes and substitutions ; .PSECT $TEMP,GBL,D,RW,OVR .WORD 0 ; Chock list SAV1: ; Current name address in buffer (SUBS) LITCNT: .WORD 0 SAV2: ; previous name address in buffer (SUBS) LITADD: .WORD 0 SAV3: .WORD 0 SAV4: .WORD 0 CHAR1: .BLKB 1 CHAR2: .BLKB 1 CHAR3: .BLKB SUBMAX+1 WARN: .BLKB 1 .even .PSECT $TABL,RO,D,LCL,CON MODTAB: .RAD50 \LCK\ .BYTE ES.LCK,1 .RAD50 \VSP\ .BYTE ES.VSP,2 .RAD50 \HSP\ .BYTE ES.HSP,3 .RAD50 \PSP\ .BYTE ES.PSP,0 .RAD50 \CHR\ .BYTE ES.CHR,0 .WORD 0 ; End of table .PSECT $CODE,RO,I,LCL,CON ; ; Define subscripts ; DFSUP:: MOV #UPMOV,SAV3 ; Subscript buffer BR DFSUP1 DFSUB:: MOV #DNMOV,SAV3 ; Superscript buffer DFSUP1: MOV #CH.HD1,SAV4 ; Maximum number of chars DFSUP2: CLR LITCNT CLR LITADD ; Set up no literal yet 1$: CALL LITNO ; Get literal BCS 10$ ; Done ? MOVB R1,@SAV3 ; Save char INC SAV3 ; Next address DEC SAV4 ; Count data trans. BGT 1$ ; Continue ? JMP ILCM 10$: CLRB @SAV3 RETURN ; ; Define variable spacing ; DFVSP:: MOV #VARESC,SAV3 ; Buffer to fill MOV #2*CH.HD1,SAV4 ; Size of buffer BR DFSUP2 ; Now fill buffer ; ; Variable spacing command ; VARSP:: BISB #SW.TDS,$VARSP ; Enable variable spacing RETURN NVSP:: BICB #SW.TDS,$VARSP ; Disable variable spacing RETURN ; ; RESET ESCAPE COMMAND ; RSESC:: MOV #ESCTAB,R0 ; Table to clear MOV #16.,R1 ; Number of entries 10$: CLRB (R0)+ ; Clear 1 entry SOB R1,10$ ; Till done ? CLR ESMSK ; Clear current escape mask MOV #ESCBF,R3 ; ESCAPE TABLE JMP CLRBF ; CLEAR IT OUT ; ; DEFINE ESCAPE COMMANDS ; ILSAD: MOV #3,R0 ; Symbol already defined error JMP ILCMA ESCERR: JMP ILCM ; Illegal command error DFESC:: CLR LITCNT ; Initialize variables CLR LITADD ; CLEAR POINTERS CALL LITNO ; GET INPUT first escape char BCS ESCERR ; ERROR/NO INPUT ? MOVB R1,CHAR1 ; Save first char CALL LITNO ; GET CHAR TO COMPARE second escape char BCS ESCERR ; ERROR/NO INPUT ? CMPEQB CHAR1,$SFLSW,4$ ; Unlock ? CMPNEB CHAR2,$LFLSW,5$ ; not Lock ? 4$: BISB #CH.ES2,CHTABL(R1) ; Note this char as escape seq. char 5$: MOVB R1,CHAR2 ; Save second char MOV #ESCBF,R3 ; ESCAPE BUFFER CALL BEGBF ; Start at beginning of buffer 10$: CALL GBYT ; Get first char BCS 15$ ; Done at end of table? MOV R1,R2 ; Save count DEC R2 CALL GBYT ; First escape char CMPNEB R1,CHAR1,12$ ; Not the same ? DEC R2 CALL GBYT ; Second escape char CMPEQB R1,CHAR2,ILSAD ; Second char the same ? 12$: MOV BF.FUL(R3),R1 ; Get current location ADD R2,R1 ; Next location CALL FNDBF ; Find it BR 10$ ; And try again 15$: CALL ENDBF ; Go to end of buffer MOV BF.FUL(R3),-(SP) ; CURRENT TABLE SIZE CLR R1 CALL PBYT ; null will be count later MOVB CHAR1,R1 ; First char CALL ESCCHR ; SAVE IT MOVB CHAR2,R1 ; Second char CALL ESCCHR ; SAVE IT ; ; Here parse auxiliary commands ; MOV #CHAR3,R0 ; Clear temporary buffer CLR (R0)+ CLR (R0)+ CLR (R0)+ CLR (R0)+ ESCOMD: CLR R3 ; No default CALL ALPGT ; get 2 char sequence BCS 70$ ; Now get sequence MOV #MODTAB,R0 ; table to search 10$: TSTEQ (R0),ERR2 ; At end of table? CMPEQ R3,(R0)+,20$ ; match? TST (R0)+ ; NO BR 10$ ; continue 20$: MOVB (R0)+,R3 ; get code MOVB (R0),R2 ; Get byte number BITNEB R3,CHAR3,ERR2 ; Bit already set ? BISB R3,CHAR3 ; Set flag byte TSTEQ R2,ESCOMD ; No extra bytes to get ? CMPEQ R3,#ES.LCK,40$ ; Lock function ? CALL RCNO ; Get number JMP ERR2 ; None is error CMP R3,#177 ; Check upper bound ? BGT ERR2 ; Too big ? CMP R3,#177600 ; Now check low bound BLT ERR2 ; Too small ? MOVB R3,CHAR3(R2) ; Save it BEQ ERR2 ; Null ?? BR ESCOMD ; Next command 40$: MOV #ESCTAB,R3 ; Table to search 41$: TSTEQB (R3),45$ ; End of table ? CMPNEB (R3)+,CHAR2,41$ ; No match ? DEC R3 ; Point to char match 45$: CMP R3,#ESCTAB+16. ; Past end of table ? BHIS ERR2 MOVB CHAR2,(R3) ; Save char SUB #ESCTAB,R3 ; Now is index CLC ASL R3 ; Word index CMPNEB CHAR1,#'\,46$ ; Not end sequence ? BIS #200,R3 ; Mark it as end sequence 46$: MOVB R3,CHAR3(R2) ; Save byte BR ESCOMD ; Next command 70$: MOV #CHAR3,R2 ; Save commands MOVB (R2)+,R1 ; Get first byte MOVB R1,R4 ; Save for later CALL ESCSAV ; Save it MOVB (R2)+,R1 ; Next byte BITEQB #ES.LCK,R4,81$ ; No lock ? CALL ESCSAV ; Save it 81$: MOVB (R2)+,R1 ; Next byte BITEQB #ES.VSP,R4,82$ ; No vert. space ? CALL ESCSAV ; Save it 82$: MOVB (R2)+,R1 ; Next byte BITEQB #ES.HSP,R4,83$ ; No horiz space ? CALL ESCSAV ; Save it 83$: ; ; Here parse for escape sequence definition ; SEQENC: CALL LITNO ; GET NEXT CHAR BCS 30$ ; NO MORE CALL ESCSAV ; SAVE IT BR SEQENC ; GET MORE 30$: MOV (SP)+,R1 ; point to start of sequence MOV #ESCBF,R3 MOV BF.FUL(R3),R2 ; Current location SUB R1,R2 ; Minus previous one DEC R2 ; Now is number of bytes CMP R2,#377 ; too big? BHI ERR3 ; yes CALL FNDBF ; find this location MOV R2,R1 ; escape count CALL PBYT ; fill it in RETURN ; ; Saves characters in escape table ; ESCCHR: CMP R1,#40 ; Not a character? BLE ERR1 ; Yes CMP R1,#177 ; Not a character? BGE ERR1 ; Yes ESCSAV: MOV #ESCBF,R3 ; BUFFER CALL PBYT ; PUT CHAR INTO BUFFER BCS ERR1 ; ERROR RETURN ERR1: TST (SP)+ ERR2: MOV (SP)+,R1 ; INDEX TO LAST LOCATION ERR3: MOV #ESCBF,R3 CALL RSTBF ; RESTORE TOP OF TABLE JMP ILCM ; ILLEGAL COMMAND ; ; Gets characters entered as literals or numbers ; LITNO: TSTNE LITCNT,10$ ; LITERAL ALREADY FOUND? CALL GETLIT ; TRY FIRST TO FIND LITERAL BCS 30$ ; NONE MOV R2,LITADD ; ADDRESS OF LITERAL MOV R1,LITCNT ; SIZE BR LITNO ; Now check size 10$: MOVB @LITADD,R1 ; GET CHAR INC LITADD ; POINTS TO NEXT VALUE DEC LITCNT ; DECREMENT # CHAR REMAINING 20$: CLC ; SUCCESS RETURN ; 30$: CALL RCNO ; TRY FOR NUMBER JMP 40$ ; NONE MOV R3,R1 ; NUMBER FOUND BR 20$ ; RETURN WITH SUCCESS 40$: SEC ; FAILURE RETURN ; ; ; reset substitute ; RSSUB:: MOV #SUBF0,R3 ; first header address is herer CALL CLRBF ; clear it RETURN SUBERR: JMP ILCM ; ILLEGAL COMMAND ; ; parse substitution/command label ; FNDSBS: MOV #CHAR1,R2 ; Start of temporary buffer MOV #SUBMAX,R4 ; Max number of char MOV R4,R1 ; Number of bytes to clear CLRB WARN ; No warning initially MOV #SAV1,R0 5$: CLRB (R0)+ ; Clear SOB R1,5$ ; Till done 10$: CALL CCIN ; get input data CMPEQB R1,#TAB,10$ ; skip tabs CMPEQB R1,#SPC,10$ ; skip spaces BLT SUBERR ; no label MOV R1,-(SP) ; save delimiter 20$: CALL CCIN ; get next char CMPEQ R1,(SP),30$ ; done? TSTNE R5,22$ ; commands ? CMP R1,#SPC ; Check for spaces BLE SUBERR ; Space or Tab error ? CMPEQ R2,#CHAR1,25$ ; First char? 22$: CMPNEB #GC.LC,GCTABL(R1),25$ ; Not lower case ? SUB #40,R1 ; Make it upper 25$: TSTEQ R5,29$ ; Not commands ? CMPEQ R2,#CHAR1,26$ ; First char? CMPNEB R1,#SPC,26$ ; printable character? CMPEQB R1,-1(R2),20$ ; 2 spaces in row ? BR 29$ ; Include space 26$: CMPNEB #GC.UC,GCTABL(R1),SUBERR ; Not letter ? 29$: MOVB R1,(R2)+ ; Save in temporary buffer SOB R4,20$ ; Continue till done, or overflow BR SUBERR ; Too many chars! 30$: TST (SP)+ ; pop delimiter CMPEQ R4,#SUBMAX,SUBERR ; No characters ? BISB R5,CHAR1 CLRB (R2)+ ; Clear next byte MOV #SUBF0,R3 ; SUBSTITUTE BUFFER CALL BEGBF ; Start at beginning of buffer CALL GWRD ; Get starting address BCC 31$ ; Inited? CALL CLRBF CLR R1 CALL PWRD ; First word is zero BR 35$ ; Start saving substitution 31$: CALL FNDBF ; Find it MOV SAV1,SAV2 ; Stash previous one MOV BF.FUL(R3),SAV1 ; Save current pointer address CALL GWRD ; Next index MOV R1,R4 ; Save it MOV #CHAR1,R2 ; Input char buffer 32$: CALL GBYT ; Get 1 char of name TSTNE R1,33$ ; Not end of symbol? TSTNEB (R2),100$ ; Only partially identical? SEC ; Symbol defined already RETURN 100$: INCB WARN ; Warn the user TSTNE SAV3,34$ ; Already found partial? MOV SAV1,SAV3 MOV SAV2,SAV4 33$: CMPEQB R1,(R2)+,32$ ; Match ? TSTNEB -1(R2),34$ ; Not partially identical ? INCB WARN ; Set up warning message 34$: MOV R4,R1 BNE 31$ ; Not end of buffer? 35$: CLC ; Ok not already defined RETURN ; ; DEFINE COMMAND ; DFCOM:: MOV #200,R5 ; Command flag BR DFMAC1 ; ; DEFINE SUBSTITUTE COMMANDS ; DFMAC:: CLR R5 DFMAC1: CALL FNDSBS ; Find substitution BCC 10$ ; Ok, not already defined ? CALL BEGBF ; Set buffer back to beginning JMP ILSAD ; ERROR - Symbol already defined 10$: CALL ENDBF ; START AT END OF BUFFER READY FOR PUT MOV BF.FUL(R3),-(SP) ; CURRENT TABLE SIZE MOV #CHAR1,R2 ; Temporary buffer CLR R1 CALL PBYT ; Will be address later 37$: CALL PBYT ; null will be count later MOVB (R2)+,R1 ; Next byte to save BNE 37$ ; Save it 40$: CALL PBYT ; save 1 char CALL CCIN ; char for macro CMPNEB R1,#CR,40$ ; done? CLR R1 ; fill in with null CALL PBYT ; into buffer TSTEQ SAV3,45$ ; No partial identical buffer? MOV SAV4,R1 ; Buffer before partial ident one CALL FNDBF MOV (SP),R1 ; Current buffer address goes into it CALL PWRD MOV (SP)+,R1 ; Current buffer address CALL FNDBF MOV SAV3,R1 ; Points to partial ident BR 46$ 45$: MOV SAV1,R1 ; Pointer address CALL FNDBF ; find it MOV (SP)+,R1 ; Beginning of current entry 46$: CALL PWRD ; Save pointer address CALL BEGBF ; go to end of buffer TSTNEB WARN,50$ ; No warning ? RETURN 50$: MOV #44.,R0 ; Message number JMP ILCMA ; Give error message ; ; DELETE command ; DELCOM::MOV #200,R5 ; Set up for command BR DELSB1 ; ; DELETE substitution ; DELSUB::CLR R5 ; Set up for substitution DELSB1: CALL FNDSBS ; Find the substitution BCC 50$ ; None ? MOV SAV1,R1 ; Address of last label CALL FNDBF ; Get it CALL GWRD ; Get size MOV R1,R2 ; Kill label MOV SAV2,R1 ; get previous one CALL FNDBF MOV R2,R1 ; Now zap substitution CALL PWRD ; By bypassing it !!! 50$: CALL BEGBF ; Go back to beginning RETURN .END