.TITLE CAT UNIX (tm) like cat (type) .IDENT \X1.3\ .PSECT PROG,I,RO,LCL ;++ ; File = CAT.MAC ; ; Edit history ; ; 19-Apr-87 Clean up a few more bugs. Seems to be working. This ; will be version X1.3. J. Stutt ; 18-Apr-87 Working on the multiple file opening. J. Stutt ; 17-Apr-87 Created. J. Stutt ; ; Function: ; ; This program simulates the UNIX (tm) utility of the same name. ; It works within the limitations of RT-11's user interface, i.e. ; no pipes. The benefit of this program over the one from the ; DECUS 'C' package is that the user command line interface is ; direct from KMON to the program with out going through a runtime ; packaged. CAT relies on the wildcard file lookup routines ; to provide the filenames. ;-- ; SYSMAC.SML macros used. ; .MCALL .CLOSE,.CSIGEN,.EXIT,.GTLIN,.PRINT,.READW,.WRITW .MCALL .LOOKUP ; .ENABL LC ; for text messages .DSABL GLOBL ; disable automatic global ; .GLOBL FFILE,FNFILE ; names of the 2 wildcard routines ; START: MOV SP,TMP ; save stack pointer for later START1: CALL INIT ; go initialize the global variables .GTLIN #LINE,#PROMPT ; get command line TSTB LINE ; null entry? BNE CSI ; we got something. parse it .PRINT #VERSN ; announce version BR START1 ; try again ; ; This next code can be canned into a subroutine to take care of ; generally parsing the command line. I'll get around to this ; later after all the bugs are worked out. JS ; CSI: MOV #LINE,R0 ; address of users command line MOV #CMDLIN,R1 ; address of cmd line for CSIGEN 1$: MOVB (R0)+,(R1)+ ; copy up to and including the '=' CMPB #'=,-1(R1) ; look for the '=' so we can stop BNE 1$ ; loop if not found MOV #LINE,R1 ; these 3 lines collapse the users 2$: MOVB (R0)+,(R1)+ ; command line down so that it can BNE 2$ ; be used as arg to FFILE MOV #LINE,R0 ; wildcard to find files from MOV #FNAME,R1 ; where to put the answer CALL FFILE ; go find the first matching name BCC 4$ ; branch if a match found .PRINT #FNF ; no matching names found, tell user BR START1 ; and restart program ; 4$: MOV #CMDLIN,R0 ; get the partial CSI command line 5$: CMPB #'=,(R0)+ ; look for the = to append input name BNE 5$ ; loop until we find it MOV #FNAME+8.,R1 ; where the ASCII name is returned 6$: MOVB (R1)+,(R0)+ ; append it to the CSI command line BNE 6$ ; loop until a null byte is detected .CSIGEN #HANDLR,#DEFEXT,#CMDLIN ; use CSIGEN to load handlers and ; ; open the output file MOV TMP,SP ; recover the SP .CLOSE #3 ; close the input, cat will open it 7$: MOV #M1,R2 ; arg for putlin CALL PUTLIN ; output the "file name" message MOV #FNAME+8.,R2 ; arg for putlin CALL PUTLIN ; output the file name CALL CAT ; go list the file MOV #FNAME,R1 ; arg for FNFILE CALL FNFILE ; look for the next matching filename BCC 7$ ; loop back if another file found .WRITW #IOARA,#0,#OUTBUF,#256.,OUTBLK ; write the last block .CLOSE #0 ; close the output I/O channel BR START1 ; loop back for next cmd line ; CAT: .LOOKUP #IOARA,#3,#FNAME ; Open the file to list. CLR INBLK ; Make sure we start at the beginning. .READW #IOARA,#3,#INBUF,#256.,INBLK ; Read a block. INC INBLK ; Increment the block count.... 1$: CALL GETLIN ; get a line of text TST EOF ; at eof? BNE 2$ ; branch to quit if so. MOV #IOLINE,R2 ; arg for putlin CALL PUTLIN ; put this line in the output buffer BR 1$ ; loop back for next line ; 2$: .CLOSE #3 ; Close the I/O channel. CLR EOF ; reset eof flag MOV #INBUF,INBFPT ; reset the input buffer pointer RETURN ; return to program main ; ; Global initialization of variables. ; INIT: CLR EOF ; clear the input eof marker MOV #512.,R1 ; number of bytes in BOTH buffers MOV #INBUF,R0 ; start of I/O buffer area 1$: CLR (R0)+ ; clear the input and output buffers SOB R1,1$ ; with this loop CLR INBLK ; clear the input block counter CLR OUTBLK ; clear the output block counter MOV #INBUF,INBFPT ; set pointer to beginning of buffer MOV #OUTBUF,OTBFPT ; set pointer to beginning of buffer RETURN ; return to program main ; ; The following 4 subroutines; GETLIN, PUTLIN, GETCHR, and PUTCHR; ; are my stand routines for doing character (text) oriented I/O. ; (see one of my other uploads for the commented sources) ; GETLIN: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV #IOLINE,R1 MOV #132.,R2 1$: CLRB (R1)+ SOB R2,1$ MOV #IOLINE,R1 2$: CALL GETCHR TST EOF BNE ENDLIN TSTB R0 BEQ 2$ CMPB #15,R0 BEQ ENDLIN CMPB #12,R0 BEQ 2$ CMP R1,#IOLINE+132. BGE 2$ MOVB R0,(R1)+ BR 2$ ; ENDLIN: MOV #IOLINE+132.,R2 1$: TSTB -(R2) BEQ 1$ CMP #IOLINE,R2 BGT 2$ CMPB #40,(R2) BNE 2$ CLRB (R2) BR 1$ 2$: MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RETURN ; PUTLIN: MOV R0,-(SP) TST EOF BNE 3$ 1$: MOVB (R2)+,R0 BEQ 2$ CMPB #200,R0 BEQ 3$ CALL PUTCHR BR 1$ 2$: MOV #15,R0 CALL PUTCHR MOV #12,R0 CALL PUTCHR 3$: MOV (SP)+,R0 RETURN ; GETCHR: CMP INBFPT,#INBUF+512. BLT 2$ .READW #IOARA,#3,#INBUF,#256.,INBLK BCC 1$ INC EOF RETURN 1$: INC INBLK MOV #INBUF,INBFPT 2$: MOVB @INBFPT,R0 INC INBFPT RETURN ; PUTCHR: MOVB R0,@OTBFPT INC OTBFPT CMP OTBFPT,#OUTBUF+512. BLT 2$ .WRITW #IOARA,#0,#OUTBUF,#256.,OUTBLK 1$: DEC OTBFPT CLRB @OTBFPT CMP #OUTBUF,OTBFPT BLT 1$ INC OUTBLK 2$: RETURN ; .PSECT DATA,D,RW,LCL ; .NLIST BEX PROMPT: .ASCII \*\<200> ; program prompt (standard CSI) VERSN: .ASCIZ \CAT X1.3\ ; version number and program name FNF: .ASCIZ \?CAT-E-File not found.\ M1: .ASCII <15><12>/*** File = /<200> LINE: .BLKB 80. ; for the users command line CMDLIN: .BLKB 80. ; for CSIGEN command line IOLINE: .BLKB 134. ; line buffer for GETLIN, PUTLIN .EVEN .LIST BEX TMP: .WORD 0 ; temporary storage for SP INBFPT: .WORD INBUF ; input buffer pointer OTBFPT: .WORD OUTBUF ; output buffer pointer DEFEXT: .RAD50 /LSTLSTLSTLST/ ; default extensions for CSIGEN FNAME: .BLKW 12. ; return arg area for FFILE, FNFILE EOF: .WORD 0 ; eof flag INBLK: .WORD 0 ; input block counter OUTBLK: .WORD 0 ; output block counter IOARA: .WORD 0,0,0,0,0 ; EMT argument area INBUF: .BLKW 256. ; input buffer OUTBUF: .BLKW 256. ; output buffer ; HANDLR = .+2 ; where CSIGEN can load handlers ; .END START