.TITLE Terminal Control Function .IDENT \V01.2\ .ENABL LC .NLIST BEX ; ; ; Written by Rick Webster ; MSDGO, Process Control Applications ; 12-MAY-81 ; Caterpillar Tractor Co. ; ; ; VERSION 01 ; File = TCF.MAC ; ; ;****************************************************************************** ; ; This software is provided on an "as is" basis only. Caterpillar Tractor Co., ; disclaims all warranties on the program, including without limitation, all ; implied warranties of merchantablity and fitness. ; ; Full permission and consent is hereby given to DECUS and to the DECUS ; special interest groups to reproduce, distribute, and publish and permit ; others to reproduce in whole or in part, in any form and without restriction ; this program and any information relating thereto ; ;****************************************************************************** ; ; ; Modifications: ; ; 5/24/82 Modified by Rick Webster to add GCML$ processing to ; allow input to TCF via command files. ; ;+ ; File description: ; ; This program allows echoing of octal characters to selected ; terminal. ; ; Usage: ; ; TCF parameters ; or ; TCF @commandfile ; ; where parameters can be any of the following: ; ; 1. octal values separated by commas ; for example TCF 15,12 will output a carriage return, linefeed ; ; 2. Ascii text delimited by the bar (|) character ; for example TCF 15,12,|TEXT TO BE OUTPUT| ; ; 3. One of the following special characters: ; ; a. L - convert all succeeding text to lower case unless a ; character is proceeded by '^' which makes the next ; character upper case. For example: ; ; TCF 15,12,L,|^LOWER ^CASE ^EXAMPLE| ; ; would output carriage return, linefeed and the string ; Lower Case Example ; ; b. U - Turn off lowercase mode (L) ; ; c. Rn1,n2 - Repeat the next octal byte (n2) n1 times. For example ; ; TCF 15,12,R10.,101 ; ; will output carriage return, linefeed followed by ; 10 A's (octal 101) ; d. B - Change big letter width, default is 1 character pixels ; valid sizes are 1, 2 or 3 (See item 4 below) ; ; 4. Alphanumeric text delimited by '[' and ']'. The characters between ; the brackets will be output as big characters, with each character ; taking up space of 6 X 7 for size 1, 12 X 14 for size 2 and ; 18 X 21 for size 3 matrix of normal sized characters. ; Only the upper case characters A-Z, numbers 0-9 and special ; characters . ; and : will be printed. All others will be printed ; as blanks. Also due to buffer limitations in the program, each ; big character string is restricted to the following: ; ; Size 1 - 22 characters maximum ; Size 2 - 10 characters maximum ; Size 3 - 6 characters maximum ; ; Larger strings will be truncated. The following example will output ; 5 linefeeds, then TEST in large characters, followed by a carriage ; return and 5 more line feeds. ; ; TCF 12,12,12,12[TEST]15,12,12,12,12,12 ; ; 5. The output can also be directed to another device by preceeding ; the parameters with a device specification. For example: ; ; TCF TT10:=14 outputs a formfeed on TT10: ; TCF ID:=14 outputs a formfeed on pseudo device ID0: ; ; Comma's are required to separate similar syntatic elements but ; are optional where the syntax is evident. For example: ; ; TCF 15,12,|TEXT|,15,12,R5,101,L,|LOWER CASE| ; ; is identical to ; ; TCF 15,12|TEXT|15,12R5,101L|LOWER CASE| ;- ; ; ; Local data ; ; ; .MCALL QIOW$,ALUN$,DIR$,ISTAT$,STATE$,TRAN$,GCML$,EXIT$S .MCALL GCMLB$,FSRSZ$ ; SIZERR: .WORD 0 ;set non-zero if invalid Big letter size given LTHERR: .WORD 0 ;set non-zero if output will exceed 256 bytes RCOUNT: .WORD 0 ;temporary storage for repeat count (R option) OUTPTR: .WORD 0 ;current byte offset in output buffer IOSTAT: .WORD 0,0 ;I/O status block for output qio DEVM: .ASCII /TT/ ;temporary storage for output device mnemonic TI: .ASCII /TI/ ;device mnemonic for device TI: LOWER: .WORD 0 ;set non-zero if in lower case mode UCNXT: .WORD 0 ;set non-zero if next char is to be upper case ALUN: ALUN$ 1,TI,0 CMDBUF: .BLKW 41. OUTBUF: .BLKW 128. OUTQIO: QIOW$ IO.WAL,1,1,,IOSTAT,, BIGBUF: .BLKW 80. ;buffer to store big chars to output BIGPTR: .WORD 0 ;number of big chars to output BCSIZ: .WORD 1 ;use 1 char elements for big chars MAXSIZ: .WORD 22. ;maximum # of Big letters at above size ISTAT$ STATBL,KEYTBL FSRSZ$ 1 GCMCTL: GCMLB$ 4,TCF,CMDBUF,2 CRLF: .BYTE 15,12 ; ; Error messages: ; ERMSG1: .ASCII <15><12>/TCF -- Syntax error/ ERMS1L=.-ERMSG1 ERMSG2: .ASCII <15><12>/TCF -- Error, requires output buffer greater / .ASCII /than 256 characters/ ERMS2L=.-ERMSG2 ERMSG3: .ASCII <15><12>/TCF -- Error, invalid Big letter size, only/ .ASCII / 1, 2 or 3 are valid/ ERMS3L=.-ERMSG3 OPERR: .ASCIZ <15><12>/TCF -- Open failure on command file/ OPERRL=.-OPERR IOERR: .ASCIZ <15><12>|TCF -- I/O error on command line| IOERRL=.-IOERR BIFER: .ASCIZ <15><12>/TCF -- Syntax error on command file name/ BIFERL=.-BIFER MDEER: .ASCIZ <15><12>/TCF -- Maximum nesting level exceeded/ MDEERL=.-MDEER RBGER: .ASCIZ <15><12>/TCF -- Command line exceeds 80 characters/ RBGERL=.-RBGER .EVEN ; ; TCF: BISB #GE.LC,GCMCTL+G.MODE ;do not convert lower case GCMD: GCML$ #GCMCTL ;get next command line BCC ASNLUN ;branch if successful JMP ERRHAN ;go figure out what the error was ASNLUN: DIR$ #ALUN ;assign lun 1 to TI: CLR OUTPTR ;initialize output buffer offset CLR SIZERR ;clear invalid Big let size indicator CLR LTHERR ;clear output > 256 error MOV #1,R1 ;set .TPARS for space recognition MOV #KEYTBL,R2 ;set up R2 for .TPARS MOV GCMCTL+G.CMLD,R3 ;set up R3 for .TPARS BEQ GCMD ;branch if no chars to process MOV GCMCTL+G.CMLD+2,R4 ;set up R4 for .TPARS MOV #STATE1,R5 ;set up R5 for .TPARS CALL .TPARS ;parse command line BCS ERR1 ;if error go output error message MOV OUTPTR,OUTQIO+Q.IOPL+2 ;put number of chars to output in qio BEQ GCMD ;get next command if nothing to do MOV #OUTBUF,OUTQIO+Q.IOPL ;put buffer address in QIO DIR$ #OUTQIO ;do the output BR GCMD ; ; ; ** ERRHAN ** Command line error processing ; ERRHAN: CMPB GCMCTL+G.ERR,#GE.EOF ;Terminate program? BNE 10$ ;no - branch JMP EXIT ;yes - exit 10$: MOV TI,ALUN+A.LUNA ;assign logical unit 1 to CLR ALUN+A.LUNU ; device DIR$ #ALUN ; TI: MOV #CRLF,OUTQIO+Q.IOPL ;output carriage return MOV #2,OUTQIO+Q.IOPL+2 ; line feed DIR$ #OUTQIO MOV GCMCTL+G.CMLD+2,OUTQIO+Q.IOPL ;move bad command line MOV GCMCTL+G.CMLD,OUTQIO+Q.IOPL+2 ;into output buffer DIR$ #OUTQIO ;output bad command line CMPB GCMCTL+G.ERR,#GE.IOR ;I/O error on command line? BNE 20$ ;NO - branch MOV #IOERR,OUTQIO+Q.IOPL ;set up to output error MOV #IOERRL,OUTQIO+Q.IOPL+2 ; message BR 100$ ;go output error message 20$: CMPB GCMCTL+G.ERR,#GE.OPR ;open failure on command file? BNE 30$ ;NO - branch MOV #OPERR,OUTQIO+Q.IOPL ;set up to output error MOV #OPERRL,OUTQIO+Q.IOPL+2 ; message BR 100$ ;go output error message 30$: CMPB GCMCTL+G.ERR,#GE.BIF ;syntax error on command file name? BNE 40$ ;NO - branch MOV #BIFER,OUTQIO+Q.IOPL ;set up to output error MOV #BIFERL,OUTQIO+Q.IOPL+2 ; message BR 100$ ;go output error message 40$: CMPB GCMCTL+G.ERR,#GE.MDE ;maximum nesting leve exceeded? BNE 50$ ;NO - branch MOV #MDEER,OUTQIO+Q.IOPL ;set up to output error MOV #MDEERL,OUTQIO+Q.IOPL+2 ; message BR 100$ ;go output error message 50$: CMPB GCMCTL+G.ERR,#GE.RBG ;command line too big? BNE 60$ ;NO - branch MOV #RBGER,OUTQIO+Q.IOPL ;set up to output error MOV #RBGERL,OUTQIO+Q.IOPL+2 ; message BR 100$ ;go output error message 60$: MOV #ERMSG1,OUTQIO+Q.IOPL MOV #ERMS1L,OUTQIO+Q.IOPL+2 100$: DIR$ #OUTQIO ;output error message EXIT: EXIT$S ; ERR1: MOV TI,ALUN+A.LUNA ;assign logical unit 1 to CLR ALUN+A.LUNU ; device DIR$ #ALUN ; TI: MOV #CRLF,OUTQIO+Q.IOPL ;output carriage return MOV #2,OUTQIO+Q.IOPL+2 ; line feed DIR$ #OUTQIO MOV GCMCTL+G.CMLD+2,OUTQIO+Q.IOPL ;move bad command line MOV GCMCTL+G.CMLD,OUTQIO+Q.IOPL+2 ;into output buffer DIR$ #OUTQIO ;output bad command line TST LTHERR ;was error due to output > 256 bytes? BEQ 10$ ;no - branch MOV #ERMSG2,OUTQIO+Q.IOPL ;set up qio to output length MOV #ERMS2L,OUTQIO+Q.IOPL+2 ; error message BR 30$ 10$: TST SIZERR ;was error, invalid Big let size? BEQ 20$ ;no - branch MOV #ERMSG3,OUTQIO+Q.IOPL ;set up qio to output MOV #ERMS3L,OUTQIO+Q.IOPL+2 ; invalid size message BR 30$ 20$: MOV #ERMSG1,OUTQIO+Q.IOPL ;set up qio to output MOV #ERMS1L,OUTQIO+Q.IOPL+2 ; syntax error message 30$: DIR$ #OUTQIO ;output appropriate error message JMP GCMD .PAGE ;+ ; State tables and action routines for .TPARS ;- STATE$ STATE1 TRAN$ !DEV,GETNXT ;check if there was a device spec TRAN$ $LAMDA,GETNXT ;if not go check for valid parameters ; STATE$ DEV TRAN$ $ANY,,LET1 ;check for 1st char of device spec ; STATE$ TRAN$ $ANY,,LET2 ;check for 2nd char of device spec ; STATE$ TRAN$ ':,PASEQU,STUN0 ;check for implied unit 0 (ie. TT:, TI: etc) TRAN$ $NUMBR,,STUNIT ;check for unit number ; STATE$ TRAN$ ': ;check for ':' after unit number ; STATE$ PASEQU TRAN$ '=,$EXIT ;if '=' after ':' return with success ; STATE$ GETNXT TRAN$ 'R,REPCNT ;check for repeat option TRAN$ 'L,PASCOM,SETLC ;check for lower case mode TRAN$ 'U,PASCOM,SETUC ;check for cancel lower case mode TRAN$ 'B,LETSIZ ;check for change Big letter size TRAN$ !STRING,PASCOM ;check for char string (ie: |...|) TRAN$ !BIGLET,PASCOM ;check for big letters TRAN$ $NUMBR,PASCOM,PUTNUM ;check for octal byte ; STATE$ STRING TRAN$ '|,GETSTR ;check for start of string ; STATE$ GETSTR TRAN$ '|,$EXIT ;check for end of string TRAN$ $ANY,GETSTR,PUTCHR ;put next string element in output buffer ; STATE$ BIGLET TRAN$ '[ ;check for start of big letter string ; STATE$ GETBIG TRAN$ '],$EXIT,WRTBIG ;check for end of big letter string TRAN$ $ANY,GETBIG,PUTBIG ;put next big letter in output ; STATE$ PASCOM TRAN$ <',>,GETNXT ;check for comma TRAN$ $EOS,$EXIT ;check for end of input string TRAN$ $LAMDA,GETNXT ;if neither, look for next syntactic element ; STATE$ REPCNT TRAN$ $NUMBR,,GETCNT ;get repitition count ; STATE$ TRAN$ <',> ;next element of repeat option must be comma ; STATE$ TRAN$ $NUMBR,PASCOM,REPCHR ;item to be repeated must be octal byte ; ; STATE$ LETSIZ TRAN$ $NUMBR,PASCOM,SETSIZ ;set Big letter size ; STATE$ ;end of state table ; ; ; *** TPARS Action routines *** ; PUTNUM: TST .PNUMH ;is high order zero? BNE TPERR ;no - reject transition CMP #377,.PNUMB ;will value fit in a byte? BLT TPERR ;no - reject transition CMP #255.,OUTPTR ;output buffer exceeded? BLT LERROR ;set length error, and reject transition MOV OUTPTR,R1 ;put output buffer offset into R1 MOVB .PNUMB,OUTBUF(R1) ;put converted number into output buffer INC OUTPTR ;adjust output buffer offset RETURN TPERR: ADD #2,(SP) ;reject current transition RETURN ; ; PUTCHR: TST LOWER ;lower case mode in effect? BEQ 10$ ;no - branch CMPB #'^,.PCHAR ;leave next char upper case? BNE 5$ ;no - branch INC UCNXT ;yes - set indicator RETURN 5$: TST UCNXT ;leave current character as upper case? BNE 10$ ;yes - branch BICB #200,.PCHAR ;make sure we have 7 bit ascii CMPB #'A,.PCHAR ;if character is alphe (A thru Z) BGT 10$ ; then convert character CMPB #'Z,.PCHAR ; to its equivalent BLT 10$ ; lower case BISB #40,.PCHAR ; value 10$: MOV OUTPTR,R1 ;put output buffer offset into R1 CMP #255.,OUTPTR ;output buffer length exceeded? BLT LERROR ;yes - set indicator, reject transition MOVB .PCHAR,OUTBUF(R1) ;put current character in output buffer INC OUTPTR ;adjust output buffer pointer CLR UCNXT ;unconditionally clear upper case indicator RETURN ; STUN0: CLR ALUN+A.LUNU ;set for unit 0 BR STNXT ; STUNIT: TST .PNUMH ;is high order 16 bits = 0 BNE TPERR ;no - reject transition MOV .PNUMB,ALUN+A.LUNU ;put unit number into ALUN$ STNXT: MOV DEVM,ALUN+A.LUNA ;put device mnemonic into ALUN$ DIR$ #ALUN ;assign lun 1 to indicated device BCS TPERR ;if unsuccessful, reject transition RETURN ; ; GETCNT: TST .PNUMH ;is high order 16 bits zero BNE TPERR ;no - reject transition MOV .PNUMB,R1 ;put repeat count into R1 BLE TPERR ;if count is negative, reject transition MOV OUTPTR,R2 ;put output buffer offset into R2 ADD R1,R2 ;add repeat count to R2 CMP #255.,R2 ;will this make output exceed 256 chars? BLT LERROR ;yes - set indicator, reject transition MOV R1,RCOUNT ;save repeat count RETURN LERROR: INC LTHERR ;set length error indicator BR TPERR ;go reject transition ; ; REPCHR: MOV RCOUNT,R1 ;put repeat count into R1 TST .PNUMH ;high order = 0 BNE TPERR ;no - reject transition CMP #377,.PNUMB ;will number fit into a byte BLT TPERR ;no - reject transition MOV OUTPTR,R0 ;put output buffer offset into R0 ADD #OUTBUF,R0 ;R0 points to next byte in output buffer 1$: MOVB .PNUMB,(R0)+ ;mov repeated char into output buffer SOB R1,1$ ;loop until repeat count is satisfied ADD RCOUNT,OUTPTR ;update output buffer offset RETURN LET1: MOVB .PCHAR,DEVM ;save 1st char of device mnemonic RETURN LET2: MOVB .PCHAR,DEVM+1 ;save 2nd character of device mnemonic RETURN SETLC: INC LOWER ;set lower case mode indicator RETURN SETUC: CLR LOWER ;clear lower case mode RETURN ; SETSIZ: TST .PNUMH ;is high order 16 bits zero BNE SERROR ;no - reject transition CMP .PNUMB,#1 ;is the number GE 1 BLT SERROR ;no, reject transition CMP .PNUMB,#3 ;is number LE 3 BGT SERROR ;no, reject transition MOV .PNUMB,BCSIZ ;load new character size CMP BCSIZ,#1 ;size = 1 BNE 10$ ;no - branch MOV #22.,MAXSIZ ;set maximum number of Big letters BR 50$ 10$: CMP BCSIZ,#2 ;size = 2 BNE 20$ ;no - branch MOV #10.,MAXSIZ ;set maximum number of Big letters BR 50$ 20$: MOV #6.,MAXSIZ ;set maximum number of Big letters 50$: RETURN SERROR: INC SIZERR ;set SIZE error indicator JMP TPERR ;go reject transition ; ; PUTBIG: BICB #200,.PCHAR ;make sure we have 7 bit ascii MOV BIGPTR,R1 ;put output buffer offset into R1 MOVB .PCHAR,BIGBUF(R1) ;put current character in output buffer INC BIGPTR ;adjust output buffer pointer RETURN ; ; WRTBIG: MOV OUTPTR,OUTQIO+Q.IOPL+2 ;put number of chars to output in qio BEQ 10$ ;branch if nothing to do DIR$ #OUTQIO ;output anything entered before big letters 10$: CLR OUTPTR ;clear output count MOV BIGPTR,R1 ;get count of big chars to output CMP R1,MAXSIZ ;count greater than maximum? BLE 20$ ;no - branch MOV MAXSIZ,R1 ;yes - truncate to maximum size 20$: MOV #BIGBUF,R2 ;R2 has address of big chars to output MOV R3,-(SP) ;save R3 MOV R5,-(SP) ;save R5 MOV #1,R3 ;use logical unit 1 MOV BCSIZ,R5 ;R5 has width of big char elements CALL FLGPAG ;generate big chars. MOV (SP)+,R5 ;restore R5 MOV (SP)+,R3 ; and R3 CLR BIGPTR ;clear big char count RETURN .PAGE .SBTTL FLGPAG - Block letter routine ; ; LOCAL DATA ; ; ; BIT MASKS TABLE FOR LETTERS A-Z ; TABLE1: .WORD 143056,061770,030574,014276,007637,102041 .WORD 057740,030614,173706,074103,176041,141037 .WORD 020413,010370,107502,143056,061770,107214 .WORD 041020,101610,141020,056430,164614,014244 .WORD 004103,102041,073437,030615,014306,146547 .WORD 135061,061430,167214,174305,004102,143056 .WORD 111530,030575,111276,007642,040701,037370 .WORD 102041,011020,106143,177061,061430,105214 .WORD 014304,156543,043061,052105,030614,041052 .WORD 174410,010420,037021,0 ; ; BIT MASK TABLE FOR NUMBERS 0-9 ; TABLE2: .WORD 163056,121472,103043,041020,105634 .WORD 010420,056761,004204,113506,175122,120410,007037 .WORD 150602,010271,106136,040756,104210,027010,013506 .WORD 071643,075061,016410 ; ; BIT MASK TABLE FOR '.' ; DOT: .WORD 0,14000,3 ; ; BIT MASK TABLE FOR ';' ; SEMI: .WORD 614,10306,1 ; ; BIT MASK FOR ':' ; COLON: .WORD 30600,14300,0 ; ; BIT MASK TABLE FOR ' ' ; BLANK: .WORD 0,0,0 ; ; MISCELLANEOUS DATA ; ROWCNT: .WORD 0 ;TEMP VARIABLE FOR CHAR GENERATOR NULL: .BYTE 0 ;ZERO TO TERMINATE A STRING .EVEN ;+ ; **FLGPAG - GENERATE THE CHARACTER ROUTINE ; ; THIS SUBROUTINE GENERATES THE REQUESTED CHARS ; USING A TABLE OF MASKS. A BIT ON IN THE MASK ; MEANS PRINT A CHAR IN THIS POSITION. CHARS ARE ; 5X7 THEREFORE EACH MASK IS 35. BITS LONG (HANDY). ; ; INPUTS: ; ; R1 - STRING LENGTH ; R2 - STRING ADDRESS ; R3 - LOGICAL UNIT FOR OUTPUT ; R5 - CHAR SIZE - NUMBER OF CHARS TO PRINT PER BIT OF MASK ; ; OUTPUTS: ; ; CHAR STRING WRITTEN TO PRINTER ; ; ; ALL REGISTERS PRESERVED ;- BLKQIO: QIOW$ IO.WVB,,,,OUSTAT,, OUTCR: .BYTE 15 BLKBUF: .BLKB 132. .EVEN OUSTAT: .WORD 0,0 FLGPAG:: CALL $SAVAL ;SAVE ALL REGISTERS MOV R3,BLKQIO+Q.IOLU MOV R3,BLKQIO+Q.IOEF CLR ROWCNT ;RESET ROW COUNTER MOV R2,-(SP) ;SAVE ADDRESS OF STRING TO PROCESS ROW: MOV #BLKBUF,R0 ;ADDR OF OUTPUT BUFFER MOV R1,R3 ;GET STRING LENGTH IN R3 MOV (SP),R2 ;GET ADDR OF WHERE WE ARE IN STRING CHAR: CLR R4 ;RESET BIT COUNTER BIT: MOV R4,-(SP) ;SAVE BIT COUNTER MOV R3,-(SP) ;SAVE STRING LENGTH MOV R1,-(SP) ;SAVE STRING LENGTH MOV R0,-(SP) ;SAVE OUTPUT BUFFER ADDRESS CLR R1 ;SET UP FOR BISB BISB @R2,R1 ;GET THE CHAR CMPB #'A,R1 ;IS BGT 5$ ; IT CMPB #'Z,R1 ; AN BLT 5$ ; ALPHA SUB #'A,R1 ;YES - MAKE CHAR AN INDEX INTO TABLE MOV #TABLE1,R0 ;ADDR OF ALPHA TABLE BR 7$ 5$: CMPB #'0,R1 ;IS BGT 6$ ; IT CMPB #'9,R1 ; A BLT 6$ ; NUMBER SUB #'0,R1 ;YES - MAKE CHAR AN INDEX INTO TABLE MOV #TABLE2,R0 ;ADDR OF NUMBER TABLE BR 7$ 6$: CMPB #'.,R1 ;IS IT A '.' BNE 66$ ;BR IF NO MOV #DOT,R0 ;ADDR OF DOT MATIRX BR 77$ 66$: CMPB #';,R1 ;IS IT A ';' BNE 67$ ;BR IF NO MOV #SEMI,R0 ;ADDR OF SEMI MATRIX BR 77$ 67$: CMPB #':,R1 ;IS IT A ':' ? BNE 68$ ;IF NE NO MOV #COLON,R0 ;GET ADDRESS OF COLON BIT MASK BR 77$ ; 68$: MOV #BLANK,R0 ;NON-PRINTABLE CHAR - USE BLANK 77$: CLR R1 ;SET UP FOR OFFSET INTO APPROP TABLE 7$: MOV R0,-(SP) ;SAVE R0 MOV #35.,R0 ;35. BITS / CHAR MASK CALL $MUL ;CALC BIT OFFSET MOV R1,-(SP) ;SAVE R1 FOR A WHILE MOV ROWCNT,R1 ;GET ROW COUNTER MOV #5,R0 ;CHARS 5 POSITIONS WIDE CALL $MUL ;CALC OFFSET TO INDIVIDUAL PATTERN WORD ADD (SP)+,R1 ;ADD BIT OFFSET TO TEST ADD R4,R1 ;ADD 'WHICH BIT' COUNTER MOV R1,R4 ;COPY TO MAKE WORD OFFSET BIC #17,R4 ;MAKE ASR R4 ; WORD ASR R4 ; OFFSET ASR R4 ; INTO TABLE MOV #1,R3 ;SET UP A 1 FOR BIT TEST BIC #177760,R1 ;CALC BIT OFFSET IN WORD BEQ 9$ ;BR IF ZERO 8$: ASL R3 ;SHIFT '1' TO CORRECT POSITION SOB R1,8$ ;LOOP TIL DONE 9$: ADD (SP)+,R4 ;ADD TABLE ADDRESS BIT R3,@R4 ;IS THE NECESSARY BIT ON BNE 10$ ;BR IF YES - PRODUCE CHAR MOV #' ,R3 ;USE BLANK BR 20$ 10$: CLR R3 ;SET UP FOR BISB BISB @R2,R3 ;GET THE CHAR TO PRINT 20$: MOV (SP)+,R0 ;GET BUFFER POINTER MOV R5,R4 ;GET SIZE OF CHAR 30$: MOVB R3,(R0)+ ;MOVE THE CHAR INTO THE BUFFER 'N' TIMES SOB R4,30$ MOV (SP)+,R1 ;RESTORE LENGTH OF STRING MOV (SP)+,R3 ;RESTORE MOV (SP)+,R4 ;RESTORE BIT POSITION COUNTER INC R4 ;ADD 1 TO COUNTER CMP #5,R4 ;DONE BNE BIT ;BR IF NO INC R2 ;POINT TO NEXT CHAR IN STRING MOV R5,R4 ;GET SIZE OF CHAR ASL R4 ;CALC NUMBER OF SPACES DEC R4 ; BETWEEN CHARS 40$: MOVB #40,(R0)+ ;MOVE IN THE BLANK BETWEEN CHARS SOB R4,40$ DEC R3 ;DONE WITH CHAR BNE CHAR ;BR IF NO - DO REST MOV R0,R4 ;ADDR OF END OF STRING IN R4 SUB #BLKBUF,R4 ;CALC LENGTH OF STRING 47$: CMPB #40,-(R0) ;BLANK SUPPRESS THE LINE BNE 48$ SOB R4,47$ 48$: INC R4 ;ADD 1 TO LENGTH TO MAKE IT RIGHT MOV #' ,BLKQIO+Q.IOPL+4 ;SINGLE SPACE MOV R5,R0 ;CHAR SIZE IN R0 MOV R1,-(SP) ;SAVE R1 50$: MOV R4,BLKQIO+Q.IOPL+2 ;LENGTH OF STRING INC BLKQIO+Q.IOPL+2 ;ADJUST TO ACCOUNT FOR LEADING CARRIAGE RETURN DIR$ #BLKQIO ;PRINT THE LINE BCS RET ;BR IF ERROR SOB R0,50$ ;REPEAT FOR SIZE OF CHARS MOV (SP)+,R1 ;RESTORE R1 INC ROWCNT ;ADD 1 TO ROW COUNTER CMP #7,ROWCNT ;DONE BEQ RET ;BR IF YES JMP ROW ;DO NEXT ROW OF CHAR RET: TST (SP)+ ;CLEAN OFF R2 RET1: RETURN .END TCF