.TITLE TYPE - GENERAL TYPE-OUT UTILITY .IDENT /X04.04/ .SBTTL TITLE PAGE ;**- ; Module name: TYPE - GENERAL TYPE-OUT UTILITY ; ; Version X04.04 Last edit: 22-SEP-80 13:29 ; Status: Development/Debugging ; ; Revision history: ; ; Version X04.00 24-JUL-80 16:38 - 25-JUL-80 08:16 ; Created by: K.J. CROSS ; ; Version X04.01 25-JUL-80 08:16 - 25-JUL-80 14:25 ; Modified by: K.J. CROSS ; RE-ORDER LOCAL SYMBOLS, GENERAL CLEANUP ; ; Version X04.02 25-JUL-80 14:25 - 30-JUL-80 14:46 ; Modified by: K.J. CROSS ; DELETE TRAILING SPACES AND TABS BEFORE PRINTING LINE ; ; Version X04.03 30-JUL-80 14:46 - 22-SEP-80 13:29 ; Modified by: K.J. CROSS ; FIXED BUG IN DETECTING SWITCHES WITH WILDCARDS ; ; Version X04.04 22-SEP-80 13:29 - 22-SEP-80 13:29 ; Modified by: KJC ; OPEN THE FILE FOR SHARED ACCESS (FA.SHR) ; ;**- ; ; TYPE/PRINT ; ; DESCRIPTION ; TYPES A FILE ON THE USERS TERMINAL, WITH ^Z ARMED AS AN ; UNCONDITIONAL EXIT. ; .LIST MEB .ENABL LC ;ALLOW LOWER-CASE IN TEXT MESSAGES ; ; SYSTEM MACRO CALLS. ; .MCALL GCMLB$,GCML$,CSI$,CSI$1,CSI$2 .MCALL FDBDF$,FDOP$A,OFNB$,FDBF$A,NMBLK$ .MCALL FSRSZ$,FINIT$,QIOW$,EXIT$S .MCALL GET$,CLOSE$,FDRC$A,DIR$,GLUN$,ALUN$,GTSK$ .MCALL ASTX$S,FHDOF$,CSI$SW,CSI$SV,CSI$ND ; ; MACRO TO CHECK FOR ANOTHER EXTENSION FOR THE FILE IF THE OPEN FAILED. ; .MACRO NEXEXT EXT,?AA .LIST CMP #OLDEXT,DFNB+N.FTYP ;WAS THIS EXTENSION ".'EXT'" ? BNE AA ;IF NE, NO - CHECK NEXT ONE MOV #^R'EXT,DFNB+N.FTYP ;TRY IT WITH A ".'EXT'" EXTENSION JMP TRYEXT ;TRY THE OPEN AGAIN AA: OLDEXT = ^R'EXT ;SET OLD EXTENSION VALUE .NLIST .ENDM OLDEXT = ^RFLE ;INITIALIZE EXTENSION TO ".FLE" .NLIST MEB ; ; INVOKE DEFINITION MACRO(S) ; FHDOF$ DEF$L ;LOCAL DEFINITIONS .SBTTL LOCAL DEFINITIONS ; ; DEFINITION OF LOCAL CONSTANTS ; BUFLEN=140. ;SIZE OF MAXIMUM LINE IN BYTES EFLGIN=1 ;EVENT FLAG # FOR INPUT FROM FILE EFLGOT=2 ;EVENT FLAG # FOR OUTPUT TO TERMINAL LUNIN=1 ;LUN FOR INPUT LUNOT=2 ;LUN FOR OUTPUT LUNTI=3 ;LUN FOR ERROR MESSAGES ;+ ; DEFINE CSI SWITCHES ;- TTLFLG=1 ;SWITCH FOR PROVIDING TITLES TRNFLG=2 ;SWITCH FOR TRUNCATING LINES HEFLG=4 ;SWITCH FOR DISPLAYING HELP INFO COFLG=10 ;SWITCH TO SUPPRESS COMMENT LINES HOFLG=20 ;SWITCH TO SET HOLD-SCREEN MODE .SBTTL LOCAL DATA ; ; DPB'S ; DETQIO: QIOW$ IO.DET,LUNTI,EFLGOT ;DETACH TI: ASTQIO: QIOW$ IO.ATA,LUNTI,EFLGOT,,,, ;SETS UP AST ON TI: INPUT OUTQIO: QIOW$ IO.WVB,LUNOT,EFLGOT,,IOSB,, ATTQIO: QIOW$ IO.ATT,LUNOT,EFLGOT ERRQIO: QIOW$ IO.WVB,LUNTI,EFLGOT,,IOSB,,<0,0,40> RATQIO: QIOW$ IO.RAT,LUNIN,EFLGIN,,IOSB,,<0,ATTLST> ERASCR: QIOW$ IO.WLB,LUNTI,EFLGOT,,IOSB,, ERASTR: .BYTE 33,'H,33,'J,33,'[ ;ERASE SCREEN, SET HOLD MODE ERALEN = .-ERASTR SETHLD: QIOW$ SF.SMC,LUNTI,EFLGOT,,IOSB,, SETADR: .BYTE TC.HLD,1 ;SET HOLD-SCREEN MODE SETLEN = .-SETADR GLUN: GLUN$ LUNOT,TIMDAT GTSK: GTSK$ TIMDAT ALUN: ALUN$ LUNOT,CL,0 ;ASSIGN OUTPUT LUN TO CL: ; ; SETUP FOR GET-COMMAND-LINE AND COMMAND STRING INTERPRETER ; GCML: GCMLB$ 0,TYP,,LUNTI ;ESTABLISH PROMPT CHARS AND AT. DEPTH LEVEL CSI$ .EVEN CSI: .BLKB C.SIZE ;BUFFER FOR CSI CSISWD: CSI$SW TI,TTLFLG,CSIWD,SET,NEG CSI$SW HE,HEFLG,CSIWD,SET,NEG CSI$SW TR,TRNFLG,CSIWD,SET,NEG,TRVAL CSI$SW CO,COFLG,CSIWD,SET,NEG CSI$SW HO,HOFLG,CSIWD,SET CSI$ND TRVAL: CSI$SV DECIMAL,TRNSIZ,2 CSI$ND ; ; ESTABLISH FCS MACROS FOR FILE PROCESSING ; FSRSZ$ 2 INFDB: FDBDF$ ;DEFINE OFFSET AND OTHER DEFINITIONS FDOP$A LUNIN,CSI+C.DSDS,DFNB,FO.RD FDRC$A ,CHBUF,BUFLEN FDBF$A EFLGIN .EVEN .LIST MEB ;+ ; DEFINE LOCAL STORAGE ;- ATTLST: .BYTE -12,BUFLEN ;READ MOST OF HEADER TO GET WHAT WE WANT .WORD CHBUF ;POINTER TO THE LARGEST BUFFER AVAIL. .WORD 0 ;END OF ATTRIBUTE LIST DFNB: NMBLK$ ,FLE,,SY,0 ;DEFINE DEFAULT DEVICE CSIWD: .WORD TTLFLG ;WORD FOR STATE OF COMMAND-LINE SWITCHES ; INITIAL VALUES: TITLE ON, TRUNCATE OFF TRNSIZ: .WORD 0 ;LENGTH OF LINE TO TRUNCATE TO INADDR: .WORD 0 ;INPUT BUFFER POINTER LINCNT: .WORD 0 ;COUNT OF # CHARS. PRINTED ON ONE LINE FTNFLG: .WORD 0 ;FLAG FOR FORTRAN C.C. IOSB: .WORD 0,0 ;I/O STATUS BLOCK RETURN LOCATION QUITCH: .WORD 0 ;FLAG FOR THE ^Z EXIT LPFLAG: .WORD 0 ;0 -> OUTPUT TO TERMINAL, -1 -> OUTPUT TO CL: GOTFIL: .WORD 0 ;0 -> A FILE WAS NOT OUTPUT, -1 -> ONE WAS CHBUF: .BLKB BUFLEN ;STORAGE FOR LINES READ FROM FILE TIMDAT: ;REF. LABEL (USE AREA FOR A COUPLE OF THINGS) OUTBUF: .BLKB BUFLEN ;OUTPUT BUFFER USED WHEN TRUNCATING LINES WLDVER: .BLKW 1 ;STORAGE FOR WILDCARD VERSION NUMBER TEMPLT: .BLKB 80. ;FILENAME TEMPLATE NEWSTR: .BLKB 80. ;INPUT COMMAND STRING AFTER PRECSI IFWILD: .BLKW 1 ;NON-ZERO IF ANY WILDCARDS WERE SPECIFIED NB.SFL = 1470 ;INDICATION OF ANY WILDCARDS S.WUIC = 14. AUXFNB: .BLKB S.FNB+S.WUIC ;AUXILLIARY STORAGE FOR WILDCARD LOOKUPS LF: .BYTE 12 ;A LINEFEED WHEN NEEDED FOR IMBEDDED C.C. FILES FF: .BYTE 14 ;A FORMFEED AT END OF OUTPUT TO CL: ; ; THE FOLLOWING TABLE CORRELATES THE FILE TYPE WITH THE COMMENT ; DELIMITER FOR THAT FILE TYPE. UP TO TWO CHARACTERS ARE ALLOWED ; FOR THE COMMENT DELIMITER. ; COMCHR: .BLKW 1 ;STORAGE FOR COMMENT DELIMITERS COMTBL: .WORD ^RFLE,'C .WORD ^RFTN,'C .WORD ^RDEF,'C .WORD ^RMAC,'; .WORD ^RCMD,'; .WORD ^RODL,'; .WORD ^RRNO,".; .WORD ^RPAS,"(* .WORD 0 ;TABLE TERMINATOR .NLIST BEX PRIPRO: .ASCII <15><12>/PRI>/ ;"PRI>" PROMPT STRING FOR ...PRI BEGEND: .ASCII / ** / BENSIZ=.-BEGEND ASOF: .ASCII / -- Last written / ASOFSZ=.-ASOF OPNMSG: .ASCII "Error in opening file" OPNLEN=.-OPNMSG NSFMSG: .ASCII "NO such file" NSFLEN=.-NSFMSG ECSMSG: .ASCII /Error in Command-line/ ECSSIZ=.-ECSMSG ERDMSG: .ASCII /Error in reading record/ ERDSIZ=.-ERDMSG HELTXT: .ASCII /Command format: TYPe filespec1.ext/ .ASCII %[,filespec2.ex2][/SW]% .ASCII <15><12><11><11>/where the items in brackets are optional./ .ASCII <15><12>%Switches are: /-TI to suppress the TItle.% .ASCII <15><12><11><11>%/TR[:nn] to TRuncate lines. The default% .ASCII % width is% .ASCII <15><12><11><11>%terminal width-1 and :nn is optional to change% .ASCII / the default./ .ASCII <15><12><11><11>%/-CO to suppress comment lines (starting with% .ASCII <15><12><11><11>% "C" for .FTN files, or ";" for% .ASCII % .MAC files)% .ASCII <15><12><11><11>%/CO to print only comment lines.% .ASCII <15><12><11><11>%/HO to set HOLD-SCREEN mode.% .ASCII <15><12><11><11>%/HE for this HElp text.% .ASCII <15><12>/Wildcard filename, type, version, and / .ASCII /characters are allowed./ .ASCII / For wildcard /<15><12>/characters, ? matches any character, / .ASCII /and * matches any group of characters./ .ASCII <15><12>/^Z will terminate typing the current file./ .ASCII <15><12>/^C will cause the program to exit./ HELSIZ=.-HELTXT PRIHEL: .ASCII /Command format: PRInt filespec1.ext/ .ASCII %[,filespec2.ex2][/SW]% .ASCII <15><12><11><11>/where the items in brackets are optional./ .ASCII <15><12>%Switches are: % .ASCII %/-CO to suppress comment lines (starting with% .ASCII <15><12><11><11>% "C" for .FTN files, or ";" for% .ASCII % .MAC files)% .ASCII <15><12><11><11>%/CO to print only comment lines.% .ASCII <15><12><11><11>%/-TI to suppress filenames printed on TI:.% .ASCII <15><12><11><11>%/HE for this HElp text.% .ASCII <15><12>/Wildcard filename, type, version, and / .ASCII /characters are allowed./ .ASCII / For wildcard /<15><12>/characters, ? matches any character, / .ASCII /and * matches any group of characters./ .ASCII <15><12>/^Z will terminate printing the current file./ .ASCII <15><12>/^C will cause the program to exit./ PRISIZ=.-PRIHEL NULL: .BYTE 0 ;NULL TO OUTPUT FOR EMPTY RECORD .EVEN .LIST BEX .SBTTL TYPE ENTRY POINT ; ; TYPE ENTRY POINT. EXECUTION STARTS HERE. ; DETERMINE TASK NAME. IF IT IS "PRINT", ASSIGN OUTPUT TO CL:. ; TYPE:: FINIT$ ;INITIALIZE FCS REGION MOV #GCML+G.DPRM,R1 ;ASSUME THIS IS A "TYPE" OPERATION DIR$ #GTSK ;GET TASK NAME CMP #^RPRI,TIMDAT+G.TSTN ;IS THE TASK NAME "PRIxxx"? BEQ 10$ ;IF EQ, YES - OUTPUT TO CL: CMP #^RPRI,TIMDAT+G.TSTN+2 ;IS THE TASK NAME "xxxPRI"? BNE 20$ ;IF NE, NO 10$: MOV #-1,LPFLAG ;OTHERWISE, SET FLAG DIR$ #ALUN ;ASSIGM OUTPUT TO CL: DIR$ #ATTQIO ;ATTACH TO CL: BEFORE DOING ANYTHING MOV #PRIPRO,R1 ;CHANGE PROMPT TO "PRI>" 20$: MOV R1,GCML+G.PSDS+2 ;INIT PROMPT STRING ADDRESS NEXT: GCML$ #GCML,GCML+G.PSDS+2,#6 ;LEAVE HOOKS IN FOR @ PROCESSING TSTB GCML+G.ERR ;ANY ERROR? BEQ GO ;NO IF EQ CMPB GCML+G.ERR,#GE.EOF ;EOF ON INPUT? BNE CSIERR ;NO IF NE TST LPFLAG ;OUTPUT TO CL:? BEQ 999$ ;IF EQ, NO - GET OUT TST GOTFIL ;WAS A FILE EVER OPENED? BEQ 999$ ;IF EQ, NO CLR OUTQIO+Q.IOPL+4 ;SET TO OUTPUT FORM FEED AT END MOV #FF,OUTQIO+Q.IOPL ;ADDRESS OF FORM FEED MOV #1,OUTQIO+Q.IOPL+2 ;OUTPUT LENGTH = 1 DIR$ #OUTQIO ;OUTPUT FORM FEED TO CL: 999$: EXIT$S ;YES. SIMPLY EXIT OPNERR: TST (SP)+ ;REMOVE RETURN FROM STACK CMPB INFDB+F.ERR,#IE.NSF ;IS THE ERROR "NONEXISTENT FILE"? BEQ NSFERR ;YES IF EQ MOV #OPNMSG,ERRQIO+Q.IOPL ;NO, GIVE GENERAL ERROR MSG MOV #OPNLEN,ERRQIO+Q.IOPL+2 BR ERRDIR ;SEND THE MESSAGE TO USER NSFERR: MOV #NSFMSG,ERRQIO+Q.IOPL MOV #NSFLEN,ERRQIO+Q.IOPL+2 BR ERRDIR OUTERR: EXIT$S ;FOR ERROR ON OUTPUT TO TERMINAL CSIERR: MOV #ECSMSG,ERRQIO+Q.IOPL ;SET ADDR & LENGTH OF ERROR MESSAGE MOV #ECSSIZ,ERRQIO+Q.IOPL+2 ERRDIR: DIR$ #ERRQIO BR NEXT ; ;GOT DATA FROM A COMMAND LINE OR A RESPONSE TO A PROMPT ;PARSE IT FOR AN 'OUTPUT' FILENAME ; GO: MOV GCML+G.CMLD,R1 ;GET INPUT STRING LENGTH MOV GCML+G.CMLD+2,R0 ;GET INPUT STRING ADDRESS MOV #TEMPLT,R5 ;GET ADDRESS OF TEMPLATE MOV #NEWSTR,R2 ;GET ADDRESS TO STORE NEW STRING CALL PRECSI ;CHECK FOR WILD-CARD CHARACTERS BCS CSIERR ;IF CS, ERROR MOV R5,IFWILD ;SAVE WILDCARD INDICATOR CSI$1 #CSI,#NEWSTR,R2 ;MAKE 1ST PASS BCS CSIERR ;IF CS, ERROR TST CSI+C.CMLD ;ANYTHING ON COMMAND LINE AT ALL? BEQ NEXT ;NO IF NE (GO BACK FOR ANOTHER LINE) AGAIN: CSI$2 #CSI,OUTPUT,#CSISWD ;2ND PASS, LOOKING FOR AN 'OUTPUT' FILENAME BCS CSIERR ;C SET IF ERROR (NO OTHER INFO) BIT #HEFLG,CSIWD ;A REQUEST FOR HELP INFO? BEQ NOHELP ;NO IF OFF JMP HELP ;OUTPUT THE HELP STUFF NOHELP: BIT #HOFLG,CSIWD ;/HOLD? BEQ NOHOLD ;IF EQ, NO DIR$ #ERASCR ;ERASE THE SCREEN DIR$ #SETHLD ;SET HOLD-SCREEN MODE NOHOLD: BITB #CS.NMF,CSI+C.STAT ;ANYTHING LEFT ON LINE? BEQ NEXT ;IF NOT, GO GET A NEW LINE OR EXIT CMPB #'$,@ ;IS THE FILE "$FILENAME"? BNE TRYEXT ;IF NE, NO MOV #CSI+C.FILD,R0 ;GET ADDRESS OF FILENAME DESCRIPTOR DEC (R0)+ ;DECREMENT THE FILENAME LENGTH INC (R0) ;POINT PAST THE "$" MOV #"LB,DFNB+N.DVNM ;DEFAULT DEVICE TO "LB0:" MOV (PC)+,R1 ;SET NEW DEFAULT UIC .BYTE 6,201 ; TO [201,6] CALL .WDFUI ;WRITE NEW DEFAULT UIC INTO $$FSR2 TRYEXT: MOV #INFDB,R0 ;GET FDB ADDRESS MOV #INFDB+F.FNB,R1 ;AND FNB ADDRESS MOV F.DSPT(R0),R2 ;DATASET DESCRIPTOR ADDRESS MOV F.DFNB(R0),R3 ;DEFAULT NAME BLOCK ADDRESS MOV #AUXFNB,R4 ;AUXILLIARY STORAGE CALL .WPARS ;PARSE WILDCARD STRING BCC OPENOK ;IF CC, NO PROBLEMS OPERR: CALL OPNERR ;ERROR OPENING FILE OPENOK: MOV N.FVER(R1),WLDVER ;SAVE ORIGINAL VERSION NUMBER MOV R4,R2 ;COPY AUX STORAGE ADDRESS CALL .FNDNX ;LOOKUP FIRST FILE BCS 123$ ;IF CS, NO LUCK JMP DOIT ;OTHERWISE, WE FOUND IT 123$: BIT #NB.TYP!NB.STP,INFDB+F.FNB+N.STAT ;WAS A FILETYPE SPECIFIED? BNE OPERR ;IF NE, YES ; ; TRY SEVERAL OTHER DEFAULT EXTENSIONS. IF THEY ALL FAIL, BOMB OUT. ; .IRP DEFEXT, NEXEXT DEFEXT ;TRY .DEXEXT EXTENSION .ENDR .IRP DEFEXT, NEXEXT DEFEXT ;TRY .DEXEXT EXTENSION .ENDR DOXX: JMP OPERR ;BETTER LUCK NEXT TIME ; ; THE FILENAME BLOCK OF THE FDB IS NOW FILLED. IF THERE WERE ; ANY WILD-CARDS SPECIFIED, CONVERT THE FILENAME TO ASCII AND ; CHECK TO SEE IF WE HAVE A MATCH. ; DOIT: TST IFWILD ;ANY WILD-CARDS? BEQ 30$ ;IF EQ, NO MOV R0,R5 ;GET FDB ADDRESS ADD #F.FNB+N.FNAM,R5 ;POINT TO FILENAME IN FNB MOV R0,-(SP) ;SAVE R0 MOV #CHBUF,R0 ;POINT TO AREA TO STORE ASCII FILENAME MOV #3,R3 ;SET COUNTER FOR 3 WORDS 10$: MOV (R5)+,R1 ;GET RAD50 WORD CALL $C5TA ;CONVERT TO ASCII DEC R3 ;COUNT NO. OF WORDS DONE BGT 10$ ;IF GT, STILL DOING NAME BMI 20$ ;IF MI, ALL DONE MOVB #'.,(R0)+ ;PUT "." AFTER FILENAME AND BEFORE TYPE BR 10$ ;CONTINUE WITH TYPE 20$: MOVB #';,(R0)+ ;TERMINATE TYPE MOV #CHBUF,R1 ;GET FILENAME IN ASCII ADDRESS MOV #TEMPLT,R2 ;GET MATCH TEMPLATE ADDRESS CALL MATCH ;TRY FOR A MATCH MOV (SP)+,R0 ;RESTORE R0 BCC 30$ ;IF CC, WE GOT ONE JMP CHKNXT ;CHECK THE NEXT ONE 30$: OFNB$ R0,#FA.SHR!FO.RD ;OPEN THE FILE BCS DOXX ;OH, WELL - WE TRIED .SBTTL OUTPUT BANNER LINE ;+ ;CREATE NAME BANNER (IF DESIRED) ;- 40$: BIT #TTLFLG,CSIWD ;DO WE OUTPUT A BANNER? BNE 50$ ;YES, GENERATE TITLE BANNER TST LPFLAG ;OUTPUT TO CL:? BNE 50$ ;IF NE, YES - ALWAYS OUTPUT BANNER JMP CCTYP ;NO, GO RECORD-TYPE CHECKING 50$: MOV R0,-(SP) ;YES, SAVE R0 FOR LATER USE MOV R0,R4 ;SAVE LOW REGISTERS FOR CONVERSION USE DIR$ #RATQIO ;READ FILE ATTRIBUTES MOV #,R1 ;SET TO COPY OUT REVISION DATE & TIME MOV #TIMDAT,R0 MOV #13.,R2 ;13. BYTES OF DATE & TIME CALL MBR1R0 ;COPY IT CLR FTNFLG ;INITIALIZE FORTRAN C.C. FLAG OFF MOV #CHBUF,OUTQIO+Q.IOPL ;SET ADDRESS TO BEGINNING OF RECORD MOVB #40,OUTQIO+Q.IOPL+4 ;START W/ IMPLIED C.C. ADD #F.FNB,R4 ;OFFSET FDB POINTER TO FILENAME BLOCK MOV #CHBUF,R0 ;SET POINTER TO OUTPUT AREA MOVB #15,(R0)+ ;START THE BANNER ON MOVB #12,(R0)+ ; A NEW LINE CALL INSBEN ;INSERT BEGINNING STRING OF BANNER MOVB N.DVNM(R4),(R0)+ ;MOVE DEVICE NAME TO BANNER FIELD MOVB N.DVNM+1(R4),(R0)+ MOV N.UNIT(R4),R1 ;GET UNIT # CLR R2 ;SET FOR ZERO-SUPPRESSION CALL $CBTMG ;CONVERT TO ASCII OCTAL MOVB #':,(R0)+ ;INSERT COLON SEPARATOR BIT #NB.DIR,N.STAT(R4) ;DID USER SPECIFY A UIC FOR THIS FILE? BEQ GTDFLT ;NO, GO GET DEFAULT MOV CSI+C.DSDS+4,R1 ;YES, GET HIS UIC DESCRIPTOR LENGTH MOV CSI+C.DSDS+6,R2 ; & LOCATION BR CPYUIC ;GO COPY TO OUTPUT BUFFER GTDFLT: CALL .RDFDR ;GET THE DEFAULT UIC LENGTH & LOCATION CPYUIC: MOVB (R2)+,(R0)+ ;COPY A CHARACTER TO OUTPUT SOB R1,CPYUIC ;COPY UNTIL ALL OF UIC IS MOVED MOV N.FNAM(R4),R1 ;CONVERT NAME CALL $C5TA MOV N.FNAM+2(R4),R1 CALL $C5TA MOV N.FNAM+4(R4),R1 CALL $C5TA BACKNM: CMPB -(R0),#40 ;DO WE HAVE TO BACK UP OVER SPACES? BEQ BACKNM ;YES INC R0 ;NO, MOVE POINTER BACK MOVB #'.,(R0)+ ;INSERT '.' BETWEEN NAME & EXTENSION MOV N.FTYP(R4),R1 ;CONVERT EXTENSION CALL $C5TA BACKEX: CMPB -(R0),#40 ;BACK UP OVER SPACES IN EXTENSION? BEQ BACKEX INC R0 ;RESTORE R0 TO PAST LAST NON-SPACE CHAR. MOVB #';,(R0)+ ;INSERT SEMI-COLON SEPARATOR MOV N.FVER(R4),R1 ;CONVERT VERSION # CLR R2 ;ZERO-SUPPRESS FLAG ON CALL $CBOMG ;CONVERT TO OCTAL MOV #ASOF,R1 ;COPY 'AS OF' PART OF MESSAGE MOV #ASOFSZ,R2 CALL MBR1R0 MOV #TIMDAT,R1 ;SET ADDR. FOR SOURCE OF DATE & TIME INFO MOV #2,R2 ;COPY DAY CALL MBR1R0 MOVB #'-,(R0)+ ;INSERT '-' AS DELIMITER MOV #3,R2 CALL MBR1R0 ;COPY MONTH MOVB #'-,(R0)+ ;INSERT ANOTHER DELIMITER MOV #2,R2 ;COPY YEAR CALL MBR1R0 MOVB #40,(R0)+ ;INSERT A SPACE CALL MBR1R0 ;COPY HOUR MOVB #':,(R0)+ ;INSERT APPROPRIATE DELIMITER CALL MBR1R0 ;COPY MINUTES MOVB #':,(R0)+ ;AGAIN A DELIMITER CALL MBR1R0 ;COPY THE SECONDS TOO CALL INSBEN ;APPEND THE END STRING MOVB #12,(R0)+ ;APPEND A LF TO SEPARATE THE BANNER SUB #CHBUF,R0 ;CALC. LENGTH OF BANNER MESSAGE MOV R0,OUTQIO+Q.IOPL+2 ;SET INTO QIO TST LPFLAG ;IS THIS OUTPUT TO CL: BEQ 15$ ;IF EQ, NO MOVB #'1,OUTQIO+Q.IOPL+4 ;IF SO, DO FORM FEED FIRST 15$: DIR$ #OUTQIO ;DISPLAY NAME & TIME TST LPFLAG ;OUTPUT TO CL:? BEQ 50$ ;IF EQ, NO BIT #TTLFLG,CSIWD ;OUTPUT A BANNER TO TI:? BEQ 50$ ;IF EQ, NO MOV R0,ERRQIO+Q.IOPL+2 ;SET LENGTH OF STRING MOV #CHBUF,ERRQIO+Q.IOPL ;AND ADDRESS OF STRING MOVB #40,ERRQIO+Q.IOPL+4 ;AND CARRIAGE CONTROL DIR$ #ERRQIO ;OUTPUT BANNER TO TI: 50$: MOV (SP)+,R0 ;RESTORE R0 .SBTTL DETERMINE RECORD TYPE ;+ ; SELECT RECORD-TYPE PROCESSING (I.E. IMPLIED, IMBEDDED, FORTRAN C.C.) ;- CCTYP: MOV #-1,GOTFIL ;A FILE HAS BEEN OPENED AND OUTPUT STARTED MOV #CHBUF,OUTQIO+Q.IOPL ;INITIALIZE BUFFER LOCATION MOV #40,OUTQIO+Q.IOPL+4 ; AND FORMAT BITB #FD.CR,F.RATT(R0) ;SEE IF INPUT FILE IS IMPLIED BNE ATA ;IF YES, SKIP TO ATTACH W/ AST BITB #FD.FTN,F.RATT(R0) ;CHECK IF FORTRAN C.C. BEQ IMBED ;NO IF BIT OFF MOV #1,FTNFLG ;YES, SET FLAG INC OUTQIO+Q.IOPL ;BUMP POINTER PAST C.C. CHARACTER BR ATA ; & SKIP THE IMBEDDED C.C. CASE IMBED: CLRB OUTQIO+Q.IOPL+4 ;NO, CHANGE TO NO C.C. MOV #LF,ERRQIO+Q.IOPL ; & SEPARATE TEXT BY A LINEFEED MOV #1,ERRQIO+Q.IOPL+2 DIR$ #ERRQIO ATA: DIR$ #ASTQIO,OUTERR ; ; SET UP THE COMMENT DELIMITER, IF REQUIRED. ; CLR COMCHR ;ASSUME NO COMMENT PROCESSING BIT #COFLG,CSI+C.MKW1 ;WAS /CO OR /-CO SPECIFIED? BEQ 50$ ;IF EQ, NO MOV #COMTBL,R0 ;GET COMMENT TABLE ADDRESS 10$: CMP (R0)+,INFDB+F.FNB+N.FTYP ;IS THIS THE RIGHT EXTENSION? BEQ 40$ ;IF EQ, YES TST (R0)+ ;SKIP THE COMMENT CHARACTERS TST (R0) ;END OF TABLE? BNE 10$ ;IF NE, NO BR 50$ ;NOT IN TABLE 40$: MOV (R0),COMCHR ;SAVE COMMENT CHARACTERS 50$: ;REF LABEL ;+ ; SET UP POSSIBLE TRUNCATE CONDITIONS ;- MOV CSIWD,R5 ;SET R5 TO CORRESPOND TO THE TRUNCATE SW. BIC #^CTRNFLG,R5 BEQ GETREC ;JUST OUTPUT BUFFER IF NO-TRUNCATE MOV OUTQIO+Q.IOPL,INADDR ;SAVE THE INPUT RECORD POINTER MOV #OUTBUF,OUTQIO+Q.IOPL ; & REPLACE IT W/ THE OUTPUT POINTER TST TRNSIZ ;HAS THE USER SPECIFIED A TRUNCATE WIDTH? BNE INICPY ;SKIP IF USER GAVE US A VALUE DIR$ #GLUN ; ELSE GET TERMINAL WIDTH MOV TIMDAT+G.LUCW+6,TRNSIZ DEC TRNSIZ ;REDUCE BY 1 FOR FUNNY TERMINALS THAT WRAP INICPY: MOV TRNSIZ,R3 ;GET THE SIZE TO TRUNCATE TO CLR LINCNT ;CLEAR COUNT OF CHARS PRINTED ON A LINE ;+ ; START COPYING INPUT RECORDS TO OUTPUT ;- GETREC: GET$ #INFDB,,,GETERR ;GET A RECORD MOV INFDB+F.NRBD,OUTQIO+Q.IOPL+2 ;RETRIEVE # OF BYTES READ TST FTNFLG ;DO WE HAVE FORTRAN C.C.? BEQ CHKOUT ;NO IF FLAG=0 MOVB CHBUF,OUTQIO+Q.IOPL+4 ;YES, MOVE C.C. CHAR TO QIO FIELD DEC OUTQIO+Q.IOPL+2 ; AND DECR. COUNT OF CHARS TO OUTPUT CHKOUT: TST R5 ;DO WE NEED TO TRUNCATE? BEQ DOOUT ;NO, GO OUTPUT THE INCOMING RECORD ;+ ; HANDLE LINE TRUNCATION ;- MOV OUTQIO+Q.IOPL+2,R4 ;GET THE TOTAL RECORD COUNT BEQ GETREC ;GET ANOTHER IN CASE COUNT WAS ZERO CLR OUTQIO+Q.IOPL+2 ;RESET THE COUNT TO ZERO MOV INADDR,R2 ;SET UP POINTER FOR INCOMING CHARS MOV #OUTBUF,R1 ; & AN OUTPUT POINTER TOO TSTCHR: CMPB (R2),#15 ;A CARRIAGE RETURN? BNE NOTCR ;NO MOV TRNSIZ,R3 ;YES, RESET TRUNCATE COUNT & CARRIAGE POSITION CLR LINCNT BR OKCHAR ;GO MOVE CHAR TO OUTPUT NOTCR: CMPB (R2),#10 ;A BACKSPACE? BNE NOTBS ;NO INC R3 ;YES, INC. AVAIL. SPACE DEC LINCNT ;AND MOVE CARR. POS. BACK 1 BGE OKCHAR ;GO COPY TO OUTPUT CLR LINCNT ;CAN'T GO BACK PAST BEGINNING OF LINE BR OKCHAR NOTBS: CMPB (R2),#11 ;A TAB? BNE NOTTAB ;NO MOV LINCNT,R0 ;YES, GET CARR. POSITION BIC #177770,R0 ;MAKE MODULO 8 SUB #8.,R0 ;NOW HAVE # SPACES TO INSERT FOR THE TAB ; (AS A NEGATIVE VALUE) SUB R0,LINCNT ;ADVANCE CARRIAGE POSITION ADD R0,R3 ;DO WE HAVE ROOM TO REALLY OUTPUT THE TAB? BLT SKPCHR ;NO, SKIP THIS ONE BR OKCHAR ;YES, TRANSFER TAB TO OUTPUT BUFFER NOTTAB: CMPB (R2),#31. ;A CONTROL CHAR? BLE OKCHAR ;YES, COPY IT SINCE WON'T MOVE CARRIAGE DEC R3 ;NO, SEE IF THERE'S ROOM FOR IT BLT SKPCHR ;NO ROOM, SKIP THIS ONE INC LINCNT ;YES, MOVE CARRIAGE OKCHAR: INC OUTQIO+Q.IOPL+2 ;COUNT IT FOR THE QIO MOVB (R2),(R1)+ ;COPY IT TO OUTPUT BUFFER SKPCHR: INC R2 ;ADVANCE THE INPUT POINTER (EVEN IF NOT ; COPYING IT TO OUTPUT BUFFER) DEC R4 ;DECR. COUNT OF REMAINING IN INPUT BUFFER BGT TSTCHR ;IF MORE, GO TEST ONE DOOUT: MOVB COMCHR,R0 ;GET THE FIRST COMMENT CHARACTER BEQ 70$ ;IF EQ, NO COMMENT PROCESSING MOV #CHBUF,R1 ;GET ADDRESS OF FIRST CHARACTER ON THE LINE CMP #^RCMD,INFDB+F.FNB+N.FTYP ;IS THE FILE TYPE ".CMD"? BNE 40$ ;IF NE, NO - PROCEED 10$: CMPB #11,(R1) ;IS THE FIRST CHARACTER A TAB? BEQ 20$ ;IF EQ, YES CMPB #40,(R1) ;IS IT A SPACE? BNE 30$ ;IF NE, NO 20$: INC R1 ;SKIP LEADING TABS AND SPACES BR 10$ ;GO CHECK FOR MORE 30$: CMPB #'.,(R1) ;SECOND CHARACTER A "."? BNE 40$ ;IF NE, NO INC R1 ;CHECK FOR ".;" AS A COMMENT, ALSO 40$: CMPB R0,(R1)+ ;FIRST COMMENT CHARACTER MATCH? BNE 60$ ;IF NE, NO MOVB COMCHR+1,R0 ;GET SECOND COMMENT CHARACTER BEQ 50$ ;IF EQ, WE FOUND A COMMENT LINE CMPB R0,(R1)+ ;SECOND COMMENT CHARACTER MATCH? BNE 60$ ;IF NE, NO - NOT COMMENT LINE ; ; COMMENT LINE FOUND. ; 50$: BIT #COFLG,CSI+C.MKW2 ;PRINT COMMENT LINES? BEQ TSTSTP ;IF EQ, NO BR 70$ ;YEP ; ; NOT COMMENT LINE. ; 60$: BIT #COFLG,CSI+C.MKW2 ;PRINT NON-COMMENT LINES? BNE TSTSTP ;IF NE, NO 70$: TST OUTQIO+Q.IOPL+2 ;MAKE SURE NON-ZERO BYTE COUNT BGT DOQIO DONULL: MOV #1,OUTQIO+Q.IOPL+2 ;ELSE SET TO OUTPUT 1 NULL CHAR. MOV OUTQIO+Q.IOPL,-(SP) ;SAVE THE OLD BUFFER POINTER MOV #NULL,OUTQIO+Q.IOPL DIR$ #OUTQIO,OUTERR MOV (SP)+,OUTQIO+Q.IOPL ;RESTORE THE BUFFER POINTER BR TSTSTP ; & SKIP TO TEST FOR STOP OUTPUT DOQIO: TSTB OUTQIO+Q.IOPL+4 ;IMBEDDED CARRIAGE CONTROL? BEQ 30$ ;IF EQ, YES - CAN'T CHECK FOR TRAILING BLANKS MOV OUTQIO+Q.IOPL,R4 ;GET ADDRESS OF STRING ADD OUTQIO+Q.IOPL+2,R4 ;COMPUTE END ADDRESS 10$: CMPB -(R4),#40 ;IS IT A SPACE AT THE END? BEQ 20$ ;IF EQ, YES CMPB (R4),#11 ;HOW 'BOUT A TAB? BNE 30$ ;IF NE, NO - DO IT 20$: DEC OUTQIO+Q.IOPL+2 ;DON'T PRINT TRAILING SPACES BGT 10$ ;IF GT, CONTINUE CHECKING BR DONULL ;NULL LINE 30$: DIR$ #OUTQIO,OUTERR ;OUTPUT THE LINE TSTSTP: TST QUITCH ;DID THE USER TYPE A ^Z YET? BNE QUIT ;YES IF NON-ZERO TST R5 ;TRUNCATING IN PROGRESS? BEQ 10$ ;NO, GO GET ANOTHER RECORD TST OUTQIO+Q.IOPL+4 ;IMBEDDED C.C.? BEQ 10$ ;YES, JUST GET A NEW RECORD JMP INICPY ;NO, GO RESET COUNTS FIRST 10$: JMP GETREC ;GO TO IT QUIT: CMP #3,QUITCH ;WAS ^C TYPED? BNE 10$ ;IF NE, NO EXIT$S ;QUICK EXIT 10$: CLR QUITCH ;CLEAR QUIT FLAG FOR REUSE BR GETEOF ;PRETEND THAT WE HAVE AN EOF GETERR: TST (SP)+ ;REMOVE RETURN FROM STACK CMPB INFDB+F.ERR,#IE.EOF ;WAS ERROR AN EOF ON INPUT FILE? BEQ GETEOF ;YES IF EQ MOV #ERDMSG,ERRQIO+Q.IOPL ;NO, OUTPUT GENERAL ERROR MESSAGE MOV #ERDSIZ,ERRQIO+Q.IOPL+2 JMP ERRDIR GETEOF: DIR$ #DETQIO,OUTERR CLOSE$ #INFDB ;CLOSE INPUT FILE BEFORE PROCEEDING CHKNXT: MOV #INFDB+F.FNB,R1 ;GET FNB ADDRESS BIT #NB.SFL,N.STAT(R1) ;ANY WILD CARDS? BEQ 10$ ;IF EQ, NO MOV #AUXFNB,R2 ;AUX STORAGE AREA MOV WLDVER,N.FVER(R1) ;RESTORE DEFAULT VERSION CALL .FNDNX ;LOOK UP NEXT FILE BCS 10$ ;IF CS, NO MORE FILES FOR THIS WILDCARD JMP DOIT ;OTHERWISE, GO FIND IT 10$: BITB #CS.MOR,CSI+C.STAT ;ANY MORE FILES ON CURRENT LINE? BEQ NOMORE ;IF NOT, GO GET NEW LINE (OR EXIT) JMP AGAIN ;YES, SO GO BACK FOR ANOTHER FILENAME NOMORE: JMP NEXT ;DO A JUMP TO GET BACK (BR WON'T REACH) .SBTTL OUTPUT HELP MESSAGE ;+ ; HELP OUTPUT HERE ;- HELP: TST LPFLAG ;OUTPUT TO CL:? BEQ 20$ ;IF EQ, NO - OUTPUT "TYPE" HELP MESSAGE MOV #PRIHEL,ERRQIO+Q.IOPL ;SET ADDR AND LENGTH OF HELP MESSAGE MOV #PRISIZ,ERRQIO+Q.IOPL+2 BR 30$ 20$: MOV #HELTXT,ERRQIO+Q.IOPL ;SET ADDR AND LENGTH MOV #HELSIZ,ERRQIO+Q.IOPL+2 30$: DIR$ #ERRQIO ;DO IT BIC #HEFLG,CSIWD ;TURN OFF HELP REQUEST JMP NEXT ;GO GET ANOTHER COMMAND LINE IF NEEDED. .SBTTL UNSOLICITED INPUT CHARACTER AST ;+ ; *** AST ROUTINE FOR CHARACTER INPUT *** ;- ASTCHR: CMP (SP),#3 ;WE WILL ACCEPT ^C'S AS EXIT...IS THIS ONE? BEQ SETFLG ;YES, IF EQ CMP (SP),#32 ;WE WILL ALSO EXIT ON ^Z'S...IS THIS ONE? BNE ASTEXI ;NO IF NE (IGNORE IT) SETFLG: MOV (SP),QUITCH ;YES. RAISE FLAG TO EXIT WHEN CONVENIENT ASTEXI: TST (SP)+ ;GET RID OF CHAR FROM STACK BEFORE EXIT ASTX$S ;EXIT FROM AST .SBTTL MISC SUBROUTINES ;+ ; SUBROUTINE TO MOVE BEGIN/END MESSAGE TO (R0) ;- ; FALLS THROUGH TO MBR1R0 ; INSBEN: MOV #BENSIZ,R2 ;SET SIZE MOV #BEGEND,R1 ;SET STRING ADDR. ; ;+ ; SUBROUTINE TO MOVE CHARACTERS FROM (R1) TO (R0) ;- ; COUNT IS IN R2, RESTORED ON EXIT MBR1R0: MOV R2,-(SP) ;SAVE COUNT CPYCHR: MOVB (R1)+,(R0)+ ;COPY A CHARACTER SOB R2,CPYCHR ;COPY UNTIL COUNT IS ZERO MOV (SP)+,R2 ;RESTORE COUNT FOR ANOTHER USE RETURN ;THAT'S ALL THERE IS TO THIS ROUTINE .END TYPE