.title rt11io .ident /V01.00/ .enable gbl .enable lc ; ; This code is designed to replace the RSX/IAS/VMS system dependent ; code required to handle device I/O for the program RUNOFF. ; ; Written by : Gary McMillian ; Physics Department ; Rice University ; P. O. Box 1892 ; Houston, Texas 77251 ; .mcall .close,.csispc,.lookup,.print .mcall .readw,.ttinr,.ttyout,.wait,.writw ; .sbttl Word Definitions ; wcnt = 256. ;Word count for .readw and .writw l.lun == 0 ;Offset to logical unit number l.blk == 2 ;Offset to file block number l.chr == 4 ;Offset to current character address l.beg == 6 ;Offset to beginning buffer address l.end == 10 ;Offset to ending buffer address infile = 30. ;Offset to dev:filnam.ext in ttbuf ; .sbttl Macro Definitions ; .macro push mov r4,-(sp) ;Push r4 on stack mov r5,-(sp) ;Push r5 on stack .endm ; .macro pop mov (sp)+,r5 ;Pop r5 off stack mov (sp)+,r4 ;Pop r4 off stack .endm .sbttl Define storage blocks .psect $vars,rw,lcl,d,con rnobuf: .blkb 512. ;.RNO input buffer rnoend == .-1 ;Address of buffer end docbuf: .blkb 512. ;.DOC output buffer docend == .-1 ;Address of buffer end rntbuf: .blkb 512. ;.RNT output buffer rntend == .-1 ;Address of buffer end depth:: .word 0 ;.REQUIRE level nesting depth lev:: .word level0,level1,level2 ;Level pointer table .word level3,level4,level5 .word level6 level0: .word rno.ch ;Logical unit number .word 0 ;Block number .word rnoend+1 ;Current character address level1: .word 11 ;Logical unit number .word 0 ;Block number .word rnoend+1 ;Current character address level2: .word 12 ;Logical unit number .word 0 ;Block number .word rnoend+1 ;Current character address level3: .word 13 ;Logical unit number .word 0 ;Block number .word rnoend+1 ;Current character address level4: .word 14 ;Logical unit number .word 0 ;Block number .word rnoend+1 ;Current character address level5: .word 15 ;Logical unit number .word 0 ;Block number .word rnoend+1 ;Current character address level6: .word 16 ;Logical unit number .word 0 ;Block number .word rnoend+1 ;Current character address docblk::.word doc.ch ;Logical unit number .word 0 ;Block number .word docbuf ;Current character address .word docbuf ;Beginning buffer address .word docend ;Ending buffer address rntblk::.word rnt.ch ;Logical unit number .word 0 ;Block number .word rntbuf ;Current character address .word rntbuf ;Beginning buffer address .word rntend ;Ending buffer address csibuf: .byte '= ;CSI format buffer .blkb 15. ;DEV:FILNAM.EXT buffer .even ; ; Text storage block ; .psect text,ro,d,lcl,con .even oprtxt: .ascii <7><7><7><7><7><200> ;Ring user's bell return: .ascii <15><12> ;Carriage return, line feed .even .sbttl Line input routines .psect $code,ro,i,lcl,con ; ; Call fin ; carry set if no line transfered ; carry clear if line transfered ; fin:: tstneb eofsw,6$ ;End of all files? push ;Save r4 and r5 inc @trcbuf ;Next line number clr r4 ;Clear transfer count MOV #IBUF1,R1 ;Input buffer address mov bf.cad(r1),r1 ;Point r1 to actual data buffer add #bflnk+1,r1 ;Skip over forward/backward links mov depth,r5 ;Get file nesting depth asl r5 ;Form table offset mov lev(r5),r5 ;Get current file descriptor pointer 5$: mov l.chr(r5),r0 ;Get current character address ; 2$: cmp r0,#rnoend ;Test for end of block buffer ble 3$ ;Within buffer boundary 1$: call read ;Read next block from device bcc 5$ ;Renter transfer loop pop ;Restore r4 and r5 6$: sec ;No line transfered return ; 3$: tsteqb (r0),1$ ;Null character? inc r4 ;Increment character count cmp r4,#IBFSZ ;Overflowed line buffer? ble 4$ ;Inside buffer boundary mov #11.,r0 ;Input file error call ERMSG ;Send error message to user jmp RUNOFF ;Restart program ; 4$: movb (r0)+,(r1) ;Transfer character cmpneb #LF,(r1)+,2$ ;Watch for end of line ; mov r0,l.chr(r5) ;Save current character address mov bufadd,r1 ;Point r1 to actual line buffer mov r4,bf.cnt(r1) ;Enter count of characters remaining mov r4,bf.max(r1) ;Enter maximum number of bytes mov bf.cad(r1),r0 ;Point r0 to actual buffer add #bflnk,r0 ;Calculate current character address mov r0,bf.add(r1) ;Save address clr bf.ful(r1) ;Set pointer to bottom of buffer pop ;Restore r4 and r5 clc ;Successful line transfer return ; ; Call read ; Carry set if end of all files ; Carry clear if transfer successful ; r5 = Address of file descriptor block ; read: mov #rnobuf,l.chr(r5) ;Initialize character address 5$: .readw #area,l.lun(r5),#rnobuf,#wcnt,l.blk(r5) bcs 1$ ;Go process input error inc l.blk(r5) ;Increment block number clc ;Successful block transfer return ; 1$: tsteqb @#errbyt,2$ ;End of file on input? mov #11.,r0 ;Input file error call ERMSG ;Send error message to user jmp RUNOFF ;Restart program ; 2$: .close l.lun(r5) ;Close .RNO file tst depth ;Can we decrease nesting depth? beq 3$ ;No. dec depth ;Decrease nesting depth mov depth,r5 ;Get file nesting depth asl r5 ;Form table offset mov lev(r5),r5 ;Get current file descriptor pointer dec l.blk(r5) ;Read previous block sub #trcln,trcbuf ;Backup to previous file br 5$ ;Continue block read ; 3$: cmp l.lun(r5),#10 ;Can we move to next .RNO file bge 4$ ;No. inc l.lun(r5) ;Move to next .RNO file .wait l.lun(r5) ;Has this file been opened? bcs 3$ ;No. clr l.blk(r5) ;Initialize block number br read ;Continue block read ; 4$: movb #-1,eofsw ;Set end of file switch scc ;End of input files return .sbttl REQUIRE command ; ; Call requr ; requr:: push ;Save r4 and r5 cmp depth,#6. ;Maximum file nesting depth is 6 blt 1$ ;Depth's O.K. mov #20.,r0 ;Too many nested .REQ jmp ILCMA ;Send error message to user 1$: call GETLIT ;Get literal address and length bcs 3$ ;Literal error cmp r1,#14. ;Compare literal length to legal size bgt 3$ ;Literal too long, file spec error add #trcln,trcbuf ;Point to next traceback buffer mov trcbuf,r5 ;Point r5 to current buffer clr (r5)+ ;Clear line count mov #csibuf+1,r0 ;Point to CSI buffer 6$: movb (r2),(r0)+ ;Load CSI buffer movb (r2)+,(r5)+ ;Load traceback buffer sob r1,6$ ;Transfer complete string clrb (r5) ;Null string, make ASCIZ clrb (r0) ;Null string, make ASCIZ mov sp,r4 ;Save stack pointer .csispc #ttbuf,#defext,#csibuf ;Process command string bcc 4$ ;No error mov r4,sp ;Restore stack pointer 7$: sub #trcln,trcbuf ;Backup to file with error 3$: mov #18.,r0 ;Input file specification error jmp ILCMA ;Send error message to user 4$: mov r4,sp ;Restore stack pointer tsteq #ttbuf+infile+2,7$ ;Make sure file name specified inc depth ;Increment file nesting depth mov depth,r5 ;Point r5 to file nesting depth asl r5 ;Form table offset mov lev(r5),r5 ;Get current file descriptor pointer clr l.blk(r5) ;Initialize block number mov #rnoend+1,l.chr(r5) ;Initialize current character address .lookup #area,l.lun(r5),#ttbuf+infile ;Open input file bcc 5$ ;File opened mov #19.,r0 ;Input file open error jmp ILCMA ;Send error message to user 5$: mov bufadd,r3 ;Point r3 to current line buffer call clrbf ;Clear the buffer mov #CR,r1 ;Put carriage return into r1 call pbyt ;Put byte into buffer mov #LF,r1 ;Put line feed into r1 call pbyt ;Put byte into buffer call begbf ;Set to top of buffer pop ;Restore r4 and r5 return .sbttl Character output routines ; ; Call fout ; r1 = character ; fout:: tstneb $outsw,OUTPUT ;No output? cmp docblk+l.chr,docblk+l.end ;Check for end of block buffer ble 1$ ;Continue until buffer full push ;Save r4 and r5 mov #docblk,r4 ;Point r4 to DOC descriptor block call write ;Transfer buffer to device pop ;Restore r4 and r5 1$: movb r1,@docblk+l.chr ;Transfer data to buffer inc docblk+l.chr ;Point to next byte address OUTPUT::return ; ; Output Table of Contents ; r1 = String address ; r2 = Length of string ; outtoc::push ;Save r4 and r5 mov #rntblk,r4 ;Point r4 to .RNT descriptor block mov l.chr(r4),r5 ;Point r5 to current character address call tocout ;Transfer string mov #return,r1 ;Address of CR-LF string mov #2,r2 ;Transfer two characters call tocout ;Transfer string mov r5,l.chr(r4) ;Save current character address pop ;Restore r4 and r5 return ; tocout: cmp r5,l.end(r4) ;Check for end of buffer ble 1$ ;Continue until buffer full call write ;Transfer buffer to device mov l.chr(r4),r5 ;Point r5 to beginning of buffer 1$: movb (r1)+,(r5)+ ;Transfer data to buffer sob r2,tocout ;Branch until transfer complete return ; ; Close out Document and Table of Contents files ; endfil::mov #docblk,r4 ;Point r4 to .DOC descriptor block call null ;Null out rest of buffer .close l.lun(r4) ;Close output file tstneb $tocsw,1$ ;Did we make a Table of Contents? mov #rntblk,r4 ;Point r4 to .RNT descriptor block call null ;Null out rest of buffer .close l.lun(r4) ;Close output file 1$: jmp runoff ;Start over ; ; Call Null ; r4 = Address of file descriptor block ; null: mov l.chr(r4),r0 ;Point r0 to current character address cmpeqb r0,l.beg(r4),3$ ;Ignore empty buffers 1$: cmp r0,l.end(r4) ;Test for end of buffer bgt 2$ ;End of buffer, write last block clrb (r0)+ ;Null character br 1$ ;Next byte 2$: call write ;Transfer last block to device 3$: return ; ; Call Write ; r4 = Address of file descriptor block ; write: .writw #area,l.lun(r4),l.beg(r4),#wcnt,l.blk(r4) bcc 1$ ;Successful write mov #10.,r0 ;Output file error call ERMSG ;Send error message to user jmp RUNOFF ;Restart program 1$: inc l.blk(r4) ;Increment block number mov l.beg(r4),l.chr(r4) ;Initialize current character address return .sbttl Terminal I/O Routines ; ; Call erout ; r0 = ASCIZ string address ; erout:: .print ;Print out ASCIZ string return ; ; Call ttout ; r1 = string address ; r2 = length ; ttout:: mov r1,-(sp) ;Save r1 on stack mov r2,-(sp) ;Save r2 on stack out: .ttyout (r1)+ ;Print character sob r2,out ;Loop until complete .ttyout #CR ;Send carriage return .ttyout #LF ;Send line feed mov (sp)+,r2 ;Pop r2 off stack mov (sp)+,r1 ;Pop r1 off stack return ; ; Call ttinou ; Type out the whole input line buffer ; ttinou::mov r1,-(sp) ;Push r1 on the stack mov r2,-(sp) ;Push r2 on the stack mov #ibuf1,r1 ;Point r1 to input buffer address mov bf.ful(r1),r2 ;Number of bytes processed add bf.cnt(r1),r2 ;Add in number remaining mov bf.beg(r1),r1 ;Point r1 to data area add #bflnk+1,r1 ;Skip over forward/backward links br out ;Print input line buffer ; ; Call oprwat ; Finish page print, print message, read input ; oprwat::biteq #pausw,$swtch,1$ ;Don't wait mov #docblk,r4 ;Point r4 to .DOC descriptor block call null ;Null out rest of buffer mov #oprtxt,r0 ;Point r0 to operator text call erout ;Output operator text bis #10000,@#jsw ;Set special mode terminal bit .ttinr ;Input character bcs .-2 ;Loop until character entered bis #100,@#jsw ;FB, XM, and TSX+ Inhibit terminal wait .ttinr ;Clear out rest of characters bcc .-2 ;Loop until complete bic #10100,@#jsw ;Clear special mode and terminal wait 1$: return .end