Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
utilities/srccom.mid
There are no other files named srccom.mid in the archive.
; -*-MIDAS-*-
TITLE SRCCOM
;;SRCCOM COMMAND ;; SRCCOM_/@/A/L/C/S
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; NOTE: THE CANONICAL SOURCE FOR THIS PROGRAM LIVES IN
;;; [MIT-AI] SYSENG;SRCCOM >
;;; ALL CHANGES, BUG FIXES, ETC SHOULD BE REFLECTED THERE.
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;WAS ONCE DEC SRCCOM VERSION 16, MINIMALLY ADAPTED TO ITS.
;ALMOST TOTALLY REWRITTEN BY RMS, DEC '75.
;MUNGED FOR 10X/20X ASSEMBLY BY KLH, MAR '79.
IF1 [
IFE .OSMIDAS-SIXBIT/ITS/,ITS==1
IFE .OSMIDAS-SIXBIT/TENEX/,TNX==1
IFE .OSMIDAS-SIXBIT/TWENEX/,TNX==1 ? TWX==1
IFNDEF ITS,ITS==0
IFNDEF TNX,TNX==0
IFE ITS,IFE TNX,DEC==1
IFNDEF DEC,DEC==0
IFNDEF TWX,TWX==0
]
IFN TNX,[
.DECSAV ; Why go through LINK?
DEFINE HLPFIL ; SPECIFIES LOC OF HELP FILE
ASCIZ "INFO:SRCCOM.INFO"!TERMIN
]
;I/O CHANNELS. FOR TNX THESE ARE INDICES INTO JFNCHS.
CHTTI==0 ;TTY INPUT.
CHIN1==1 ;FIRST INPUT FILE
CHIN2==2 ;SECOND INPUT FILE.
CHIN3==3 ;THIRD INPUT FILE, FOR 3-WAY MERGES.
CHMRG==4 ;/M OUTPUT DEVICE FOR MERGE FILE
CHTTO==5 ;ITS NEEDS TYO CHANNEL
CHERR==6 ;FOR ERR DEVICE.
CHOUT==7 ;OUTPUT CHNL FOR DIFFERENCES.
CHCMD==10 ;COMMAND FILE READING CHANNEL.
CHUIN1==11 ;/$ USR INPUT
CHUIN2==12 ;/$ USR INPUT
CHUO1==13 ;/$ and output chans, since need both.
CHUO2==14 ;/$
;MAIN AC DEFINITIONS
W1=1
W2=2
W3=3
F1=4 ;LINE POINTER FILE 1 (CONTAINS ADDRESS OF LINE BLOCK)
F2=5 ;DITTO FILE 2
F3=6 ;DITTO FILE 3
FR=7 ;FLAG REGISTER (LH) AND FILE #(0 OR 1 OR 2)(RH)
CS=10
C=11 ;CONTAINS 1 CHAR FOR PROCESSING
T=12 ;TEMPORARY AC (MUNGED BY XJSYS CALLS)
TT=13 ;TEMP AC
BP=14 ; (RDLIN AC LOOP) BYTE POINTER IN FILENAME READER.
FP=15 ; BP+1 (RDLIN AC LOOP) ADDR OF FILE BLK
;=16 ; BP+2 (RDLIN AC LOOP)
P=17 ;PUSH DOWN POINTER
; ACC DEFS FOR TNX JSYS CODE
IFN TNX, R1=1 ? R2=2 ? R3=3 ? R4=4 ? R5=5
; ACC DEFS FOR STUFF BORROWED FROM MIDAS
IFN TNX, AA=6 ? A=1 ? B=2 ? D=4 ? E=5 ? F=FP ; NOTE A NOT AA+1
;ASCII CHARACTERS
TAB==11
ALTM==33 ;/M ALT-MODE TO END TTY INPUT FOR MERGE(/M)
;FLAGS - LH OF AC FR:
FL==1,,525252 ;BIT TYPEOUT MODE MASK.
FLINDR==1 ;/@ - FILE NAME FOLLOWS THE STRING ";COMPARISON OF " IN SPEC'D FILE.
;APPLIES TO 1ST INPUT FILE ONLY.
FLXCTF==2 ;/X - OPEN A COMMAND FILE AND START EXECUTING FROM IT.
FLISWT==4 ;/I - MERGE, BUT AUTOMATICALLY ANSWER "I" TO EVERY QUESTION
;AND DON'T TYPE ON THE TTY.
FLARCH==10 ;/A SWITCH - "ARCHIVE". APPEND OUTPUT TO FRONT OF EXISTING FILE.
FLLABL==20 ;/L SWITCH - REMEMBER FOR EACH FILE AND LINE THE PREVIOUS LABEL,
;AND PRINT IT IN THE HEADER LINE.
FLENDL==40 ;/E SWITCH - PRINT OUT THE FIRST MATCHING LINE FROM EACH FILE
;AFTER EACH RUN OF DIFFERENCES.
FLSPAC==100 ;/S SWITCH - IGNORE SPACING
FLCMNT==200 ;/C SWITCH - IGNORE COMMENTS
FLALL==400 ;/B OR /M SWITCH (ALLOWS COMPARING BLANK LINES)
; CR,LF,FF STORED LIKE DATA AND COMPARED
FLEOF1==1000 ;EOF SEEN ON FILE 1
FLEOF2==2000 ;EOF SEEN ON FILE 2
FLEOF3==4000 ;EOF SEEN ON FILE 3
FLFNUM==10000 ;/W SAYS PRINT FILE # ON EACH LINE OF DIFFERENCES.
FLFLAG==20000 ;/F SAYS MAKE COPY OF FILE 2, FLAGGING CHANGED LINES WITH VERT. BARS.
FLCASE==40000 ;/K SAYS IGNORE DIFFERENCES IN ALPHABETIC CASE
FLOVRD==100000 ;/! SAYS DO THE COMPARISON EVEN IF FILE1 AND FILE2 ARE SAME FILE.
FLXLBL==200000 ;/Y SAYS ANY UNINDENTED LINE NOT STARTING WITH A ";" IS A LABEL.
FLMERG==400000 ;/M SWITCH-MERGE 2 FILES INTO ONE CONVERSATIONALLY
;RH OF FR TELLS CERTAIN FUNCTIONS WHICH INPUT FILE TO OPERATE ON: 0 => FILE 1, 1 => FILE 2.
; Memory flags (cuz no more room in LH of FR!)
.SCALAR FVBIN ; -1 if doing binary compare (like FILCOM /W)
.SCALAR FSBIN ; -1 if doing SBLK/CSAVE compare
.SCALAR QFLAG ; -1 if doing /Q message at end of compare
;NAMES OF THE HEADER WORDS OF A FILE LINE
LNNEXT==0 ;MUST BE 0! ADDR OF HEADER OF NEXT LINE, OR 0 FOR LAST LINE.
LNSIZE==1 ;# OF CHARACTERS IN THE LINE, NOT COUNTING TERMINATING ZERO.
LNLLBL==2 ;1ST WORD OF ASCIZ OF MOST RECENT LABEL, OR 0.
LNLLB1==3 ;2ND WORD OF ASCIZ. COLON IS INCLUDED.
LNLLB2==4 ;4 WORDS IN ALL FOR HOLDING A LABEL.
LNLLB3==5
LNLBLN==4
LNPGNM==6 ;PAGE # THIS LINE STARTED ON
LNLNNM==7 ;LINE NUMBER THIS LINE STARTED ON
LNCHNM==10 ;CHARACTER NUMBER IN FILE OF 1ST CHARACTER IN LINE
LNDATA==11 ;INDEX OF THE FIRST DATA WORD. THE DATA ARE AN ASCIZ STRING
;THERE ARE ASSUMED TO BE JUST ENOUGH DATA WORDS
;TO HOLD THE NUMBER OF CHARACTERS THAT LNSIZE SAYS THERE ARE.
;PARAMETERS
IFNDEF MATCH,MATCH==3 ;# LINES TO BE MATCHED BEFORE RUN OF DIFFERENCES ENDS.
IFNDEF WPL,WPL==<40.*4>/5+1 ;# WORDS FOR FILENAMES FOR HEADER LINES.
IFNDEF LPDL,LPDL==30 ;LENGTH OF PUSH DOWN LIST
IFNDEF FILBFL,FILBFL==100 ;LENGTH OF INPUT FILE BUFFERS.
MRGBSZ==FILBFL*5 ;MERGE OUTPUT BUFFER LENGTH IN CHARS.
;/M THIS SRCCOM ALSO PERFORMS A MERGE FUNCTION IF /M IS TYPED
;/M DESTINATION FILE BECOMES MERGE OF 2 SOURCE FILES.
;/M DIFFERENCES ARE TYPED ON TTY, USER SELECTS WHICH HE WANTS
;/M AND IN WHAT ORDER BY TYPING IN 1 LINE COMMAND AFTER EACH PAIR
;/M OF DIFFERENCES IS TYPED OUT.
;/M HE MAY TYPE 1, 2, AND/OR T IN ANY ORDER FOLLOWED BY CR
;/M OR HE MAY CHANGE THE LAST COLUMN TYPED OUT TO ### BY TYPING
;/M C### FOLLOWED BY CR AS A SEPARATE COMMAND AFTER ANY PAIR OF DIFFERENCES
;/M TYPED OUT. SRCCOM WILL RESPOND WITH ANOTHER *, SO THE USER CAN TYPE
;/M ANOTHER COMMAND TO SELECT WHICH DIFFERENCES HE WANTS. INITIALLY THE
;/M MAX. COLUMN IS SET TO 72 WHENEVER SRCCOM IS RESTARTED WITH START COMMAND
;/M IT IS NOT RESET AFTER EACH FILE COMPARED.
;/M SIMILARLY THE USER MAY SET THE MAXIMUM
;/M NUMBER OF LINES TYPED FROM EACH FILE WITH L###.
;OPDEFS
CALL=PUSHJ P,
RET=POPJ P,
SAVE=PUSH P,
REST=POP P,
PJRST==JRST
IFN ITS,ERRHLT==.LOSE
IFN TNX,ERRHLT==HALT
;MACROS
IFN ITS,[
DEFINE SYSCAL A,B
.CALL [ SETZ ? SIXBIT/A/ ? B ((SETZ))]
TERMIN
]
; This may not work right on TENEX anymore, if so, fix the opsys flags
; so that we can tell 10x from 20x.
IFN TNX, .INSRT MID:XJSYS
DEFINE DBP7J AC,TAG=.+2
ADD AC,[070000,,]
JUMPGE AC,TAG
SUB AC,[430000,,1]
IFSN [TAG].+2,JRST TAG
TERMIN
DEFINE INSIRP INSN,ADDRS
IRPS ADDR,,[ADDRS]
INSN,ADDR
TERMIN TERMIN
;ADVANCE TO THE NEXT LINE IN FILE FILN, READING IT FROM THE FILE IF NECESSARY.
;GO TO EOFA IF THERE IS NO LINE DUE TO EOF.
DEFINE NEXTLN FILN,(EOFA)
SKIPE LNNEXT(F1+FILN-1)
JRST .+4
HRRI FR,FILN-1
CALL RDLIN
IFNB EOFA, JRST EOFA
.ELSE CAIA
MOVE F1+FILN-1,LNNEXT(F1+FILN-1)
TERMIN
; SOME MACROS TO MAKE I/O A LITTLE LESS SYSTEM DEPENDENT.
; OPTIMIZED IN FAVOR OF ITS.
IFN ITS,[
DEFINE M.CLS CH ; CLOSE CHAN
.CLOSE CH,
TERMIN
DEFINE M.MVCH CH1,CH2 ; MOVE CHANNEL FROM CH1 TO CH2
.IOPUS CH1,
.IOPOP CH2,
TERMIN
DEFINE MOUTC CH,?LOC ; SINGLE CHAR OUTPUT
.IOT CH,LOC
TERMIN
DEFINE M.BIN CH,LOC
.IOT CH,LOC
TERMIN
DEFINE M.SOUT CH,BPA,CNTA
SYSCAL SIOT,[MOVEI CH ? BPA ? CNTA]
.LOSE %LSFIL
TERMIN
DEFINE M.SIN CH,BPA,CNTA
SYSCAL SIOT,[MOVEI CH ? BPA ? CNTA]
.LOSE %LSFIL
TERMIN
] ;IFN ITS
IFN TNX,[
DEFINE M.CLS CH ; CLOSE CHAN
SAVE R1
SKIPLE R1,JFNCHS+CH
CLOSF
ERJMP .+1
SETZM JFNCHS+CH
REST R1
TERMIN
DEFINE M.MVCH CH1,CH2 ; MOVE CHANNEL FROM CH1 TO CH2
SAVE R1
SETZ R1,
EXCH R1,JFNCHS+CH1
EXCH R1,JFNCHS+CH2
CAILE R1,
CLOSF
ERJMP .+1
REST R1
TERMIN
DEFINE MOUTC CH,?LOC ; OUTPUT BYTE AT LOC
CALL [ PUSH P,JFNCHS+CH
PUSH P,LOC
PJRST TOUTC]
TERMIN
DEFINE M.BIN CH,LOC ; INPUT BYTE TO LOC
CALL [ PUSH P,JFNCHS+CH
PUSH P,[LOC]
JRST TINC]
TERMIN
DEFINE M.SOUT CH,BPA,CNTA ; OUTPUT STRING
MOVNS CNTA
SYSCAL SOUT,[JFNCHS+CH ? BPA ? CNTA][JUNK ? BPA ? CNTA]
MOVNS CNTA
TERMIN
DEFINE M.SIN CH,BPA,CNTA ; INPUT STRING
MOVEI T,[JFNCHS+CH ? BPA ? CNTA]
CALL TINS
TERMIN
] ;IFN TNX
DEFINE MOUTI CH,VAL ; OUTPUT IMMEDIATE VALUE
MOUTC CH,[VAL]
TERMIN
; SO MIDAS-BORROWED CODE WILL INTEGRATE BETTER.
DEFINE ETF ?ASCZ
JRST [ JSP T,ERRMSG
ASCZ
]
TERMIN
DEFINE TYPE &STR
CALL [ PUSH P,[[ASCIZ STR]]
PJRST TYPM]
TERMIN
DEFINE PRINTI &STR&
MOVEI C,.LENGTH STR
MOVE W2,[440700,,[ASCIZ STR]]
CALL PNTCNT
TERMIN
SUBTTL File Description Storage (FILBLK's)
; Definitions for indices into a FILBLK.
; Scratch block FB is formed while defining indices...
OFFSET -.
; Lots of crocks depend on the exact order of these 4 items.
IFN ITS\DEC,[
$F6DEV:: 0 ; SIXBIT Device name
$F6FN1:: 0 ; SIXBIT Filename (on ITS, FN1)
$F6FN2:: 0 ; SIXBIT Extension (on ITS, FN2)
$F6DIR:: 0 ; SIXBIT Directory (may be numerical PPN)
$FDEV==:$F6DEV ; These definitions made so some common code can do
$FDIR==:$F6DIR ; the right things.
$FNAME==:$F6FN1
$FEXT==:$F6FN2
$FVERS==:$F6FN2
]
IFN TNX,[ ; Almost all entries here are BP's to ASCIZ strings.
$FDEV:: 0 ; Device name
$FDIR:: 0 ; Directory name
$FNAME:: 0 ; File name (i.e. main name)
$FEXT:: 0 ; File type (or extension)
$FVERS:: 0 ; File version (or generation). NUMBER, not string.
$FTEMP:: 0 ; -1 => File is a temporary file.
$FACCT:: 0 ; Account string
$FPROT:: 0 ; Protection string
$FJFN:: 0 ; JFN for file (may be <desired JFN>,,<temp JFN>)
]
L$FBLK==. ; Length of a FILBLK.
OFFSET 0 ; End of index definitions.
INFB: BLOCK L$FBLK
LSTFB: BLOCK L$FBLK
IFN TNX,[
JFNCHS: BLOCK 20 ; INDEXED BY CHAN #, HOLDS JFNS
]
;SRCCOM STARTS HERE
BEG: MOVE P,[-LPDL,,PPSET-1] ;SET UP PDL.
IFN ITS,[
.OPEN CHTTI,[.UAI,,'TTY]
ERRHLT
.OPEN CHTTO,[.UAO,,'TTY]
ERRHLT
.SUSET [.RSNAM,,DEFDIR] ;GET DEFAULT DIR.
.SUSET [.ROPTIO,,W1]
TLO W1,OPTOPC
.SUSET [.SOPTIO,,W1]
.SUSET [.SMASK,,[%PIMPV]]
.SUSET [.SMSK2,,[1_CHTTO+1_CHOUT]] ;ENABLE --MORE-- INTERRUPTS
] ;IFN ITS
IFN TNX,[
RESET
CALL SEE20X ; SEE IF 10X OR 20X.
MOVEI W1,.PRIIN
MOVEM W1,JFNCHS+CHTTI
MOVEI W1,.PRIOU
MOVEM W1,JFNCHS+CHTTO
]
CALL GETJCL ; LOOK FOR JCL, SKIP IF FOUND
CAIA ; NONE
JRST RESTR1 ; HAVE SOME, GO EXECUTE.
MOVE 0,[SIXBIT/SRCCOM/] ;NO COMMAND STRING FROM SUPERIOR:
CALL TTOSIX ;IDENTIFY SELF TO USER.
MOUTI CHTTO,40 ;SPACE
IFDEF .FVERS,[
MOVE 0,[.FVERS]
CALL TTODEC
]
.ELSE [
MOVE 0,[.FNAM2] ;PRINT VERSION NUMBER.
CALL TTOSIX
]
JRST RESTRT
;COME HERE FOR A NEW COMMAND, AFTER FINISHED OR ERROR.
RESTRT: SETZM TTIBUF
RESTR1: MOVE P,[-LPDL,,PPSET-1] ;SET UP PUSH DOWN LIST
IFN ITS,.SUSET [.SWHO1,,[0]] ;CLEAR USER-SPEC'D WHOLINE FIELDS.
IFN ITS,.SUSET [.SMEMT,,[ENDCOR]]
SETZB FR,BEGP ;THIS IS THE ZERO WHICH WILL
;BE "BLT"ED TO CLEAR CORE
MOVE 0,[BEGP,,BEGP+1]
BLT ENDP-1
IFN TNX,[
MOVE 0,[FNBUF,,FNBUF+1]
SETZM FNBUF
BLT 0,FNBUF+LFNBUF-1
];TNX
MOVE W1,[440700,,MRGBF]
MOVEM W1,MRGBP
MOVEI W1,MRGBSZ
MOVEM W1,MRGCT
MOVE W1,SEG1
MOVEM W1,LBUFP1
MOVE W1,SEG2
MOVEM W1,LBUFP2
MOVE W1,SEG3
MOVEM W1,LBUFP3
AOS PAGNUM+0 ;ZEROED BY BLT ABOVE-1ST PAGE IS 1
AOS PAGNUM+1 ;DITTO FOR SECOND FILE
AOS PAGNUM+2
AOS LINNUM+0 ;SAME TRUE FOR 1ST LINE
AOS LINNUM+1
AOS LINNUM+2
SKIPE TTIBUF ;IF HAVE A JCL COMMAND,
SETOM CTLCF ;SAY RETURN AFTER JUST THIS CMD.
SKIPN TTIBUF
CALL CMDLIN ;NO DDT CMD, READ TTY LINE.
CALL TRYHLP ;IF COMMAND IS JUST "?" OR "HELP", PRINT HELP.
MOVE C,FSTTY ;OUTPUT DEFAULTS TO TTY IF NOT SPEC'D,
SKIPN CMDFIL ;UNLESS WE'RE IN A COMMAND FILE.
MOVEM C,LSTFB+$FDEV
MOVEI FP,INFB
CALL RFILE ;READ FILE NAME
CAIE C,"=
IFE TWX,[ ;Don't recognize "_" on Twenex, screws filenames
CAIN C,"_ ;IF FOLLOWED BY "_", IS OUTPUT SPEC,
CAIA
]
JRST CMD3
MOVE C,[INFB,,LSTFB]
BLT C,LSTFB+L$FBLK-1 ;SO USE AS LST FILE NAMES.
SETOM LSTEXP ;SAY LST FILE WAS EXPLICITLY SPECIFIED.
SETZM INFB+$FDEV
SKIPE CMDFIL ;IF NOT IN A COMMAND FILE, 1ST INPUT FILE SNAME
SETZM INFB+$FDIR ;DEFAULTS TO OUTPUT FILE SNAME.
CALL RFILE ;AND READ ANOTHER SPEC FOR 1ST INPUT FILE.
JRST CMD3
;NOW HAVE READ WHAT IS CERTAINLY THE 1ST INPUT SPEC.
CMD3: MOVE W2,DEFDIR ;DEFAULT THE OUTPUT FILE DEV AND SNAME NOW.
SKIPE CMDFIL ;CAN DO IT SINCE IT DOESN'T DEPEND ON SWITCH SETTINGS
MOVE W2,CMDOS ;AND MUST DO IT SINCE MIGHT GO TO CMDXCT AND WANT
SKIPN LSTFB+$FDIR ;TO KNOW THEIR FINAL VALUES.
MOVEM W2,LSTFB+$FDIR
MOVE W2,FSDSK
SKIPE CMDFIL
MOVE W2,CMDOD
SKIPN LSTFB+$FDEV
MOVEM W2,LSTFB+$FDEV
TLNN FR,FLINDR ;IF THE FIRST INPUT FILE IS INDIRECT, DEFAULT THE FN2
JRST CMD6 ;OF THE FILE TO GO INDIRECT THROUGH TO
MOVE W1,FSCMP ;TO THE FN2 OF THE LISTING FILE, AS WELL AS WE CAN.
TLNE FR,FLARCH ;CAN LOSE IN OBSCURE SITUATIONS THAT THE DOCUMENTATION
MOVE W1,FSCMPA ;WARNS USERS TO AVOID.
SKIPE LSTFB+$FEXT
MOVE W1,LSTFB+$FEXT
SKIPN INFB+$FEXT
MOVEM W1,INFB+$FEXT
MOVE W1,LSTFB+$FDIR ;ALSO DEFAULT SNAME AND DEV THAT WAY, BUT NEVER USE TTY:
SKIPN INFB+$FDIR ;NOTE THAT THE FN1 WILL DEFAULT TO THE LIST FILE'S
MOVEM W1,INFB+$FDIR ;ANYWAY.
MOVE W1,LSTFB+$FDEV
CAMN W1,FSTTY
MOVE W1,FSDSK
SKIPN INFB+$FDEV
MOVEM W1,INFB+$FDEV
CMD6: MOVE W1,CMDIS
SKIPN CMDFIL
MOVE W1,DEFDIR
SKIPN INFB+$FDIR
MOVEM W1,INFB+$FDIR
MOVE W1,CMDID ;DEFAULT DEVICE FOR 1ST INPUT FILE DEPENDS ON
SKIPN CMDFIL ;WHETHER WE'RE IN A COMMAND FILE.
MOVE W1,FSDSK
SKIPN INFB+$FDEV
MOVEM W1,INFB+$FDEV
SKIPN W1,INFB+$FVERS
MOVE W1,FVLOW ;IF ONLY ONE INPUT FILE SPECIFIED, DEFAULT ITS FN2 TO "<",
SKIPG TTICNT ;SINCE 2ND INPUT FILE WILL BE THE ">" OF THE SAME FILE.
MOVEM W1,INFB+$FVERS
RFIND1: MOVEI W1,CHIN1
CALL INOPEN ;NOW OPEN CHANNEL CHIN1.
TLNE FR,FLXCTF ;IS THIS AN EXECUTE FILE?
JRST CMDXCT
TLNE FR,FLINDR ;MAYBE THE FILE WE OPENED JUST HAS THE NAMES OF THE
JRST RFINDR ;REAL 1ST INPUT FILE. IF SO, READ THEM.
CALL RFILE ;READ NAMES OF & OPEN 2ND INPUT.
MOVEI W1,CHIN2
CALL INOPEN
TLNE FR,FLINDR\FLXCTF
JRST ERRIN2 ;FILE 2 INDIRECT? THAT ISN'T ALLOWED.
SKIPG TTICNT ;MORE FILES? MUST BE A 3-WAY MERGE.
JRST CMD4
CALL RFILE ;READ THE THIRD FILE'S NAME.
TLNN FR,FLMERG
JRST ERR3NM ;ERROR IF /M NOT SPECIFIED.
SETOM 3WAY
MOVEI W1,CHIN3
CALL INOPEN
TLNE FR,FLINDR\FLXCTF ;ERROR IF THIRD FILE IS INDIRECT.
JRST ERRIN3
SKIPG TTICNT ;ERROR IF ANYTHING LEFT AFTER THIRD FILE NAME.
JRST ERRXTRA
JRST CMD4
;NOW OPEN THE OUTPUT FILE.
CMD4: MOVEI FP,LSTFB
MOVE W2,FSCMP ;NORMAL DEFAULT OUTPUT FN2.
TLNE FR,FLARCH
MOVE W2,FSCMPA
MOVEI W1,CHOUT ;NORMALLY, SPEC'D FILE IS OUTPUT FILE,
TLNN FR,FLMERG
JRST CMD5
TLNE FR,FLARCH
JRST ERRARC
MOVEI W1,CHMRG ;BUT IF /M, IT IS MERE FILE NAME,
IFN ITS,[
.OPEN CHOUT,[.UAO,,'TTY] ;AND OUTPUT IS TO TTY:
ERRHLT
]
IFN TNX,[
PUSH P,JFNCHS+CHTTO
POP P,JFNCHS+CHOUT
]
MOVE W2,FSDMF2
TLNE FR,FLFLAG ;ALSO, WE HAVE DIFFERENT DEFAULT FN2'S
MOVE W2,FSFLGD
MOVE T,FSTTY
SKIPL LSTEXP ;AND DON'T DEFAULT TO TTY:; USE DSK: INSTEAD.
CAME T,LSTFB+$FDEV
JRST CMD5
MOVE T,FSDSK
MOVEM T,LSTFB+$FDEV
CMD5: SKIPN LSTFB+$FEXT ;DEFAULT THE FN2 IF NEC.
MOVEM W2,LSTFB+$FEXT
IFN ITS,[
SYSCAL TRANS,[
$FDEV(FP) ? $FNAME(FP) ? $FEXT(FP) ? $FDIR(FP)
MOVEI .UAO
MOVEM $FDEV(FP) ? MOVEM $FNAME(FP)
MOVEM $FEXT(FP) ? MOVEM $FDIR(FP)]
CALL OPENL
SYSCAL OPEN,[5000,,.UAO ? W1
$FDEV(FP) ? ['_SRCCO] ? ['OUTPUT] ? $FDIR(FP)]
CALL OPENL ;ERROR RTN, IN CASE FAILED.
SYSCAL TTYGET,[MOVEI CHOUT ? MOVEM TTYST1 ? MOVEM TTYST2 ? MOVEM W1]
JRST CMD2 ;JUMP IF OUTPUT FILE ISN'T A TTY.
SETOM OUTTTY
MOVEM W1,TTYSTS ;IT IS A TTY; SAVE THE TTYSTS TO RESTORE LATER
TLZE W1,%TSMOR ;AND TURN ON **MORE**'ING NOW.
SYSCAL TTYSET,[MOVEI CHOUT ? TTYST1 ? TTYST2 ? W1]
JFCL
] ;IFN ITS
IFN TNX,[
MOVE T,FSTTY
CAMN T,LSTFB+$FDEV ; ABOUT TO OPEN TTY FOR OUTPUT?
JRST [ PUSH P,JFNCHS+CHTTO ; IF SO JUST DUPLICATE TTY JFN
POP P,JFNCHS+CHOUT
SETOM OUTTTY
JRST CMD20]
MOVEI FP,LSTFB
HRLI FP,(W1) ; GET <CHAN>,,<FB PTR>
CALL OPNWR
CALL OPENL
CMD20:
]
;FINAL INITIALISATION, AND PRINTING OF THE FILE HEADER.
CMD2: SETZB F1,F2 ;RIGHT NOW WE HAVE NO LINES OF EITHER FILE IN CORE.
TLNE FR,FLMERG ;IF MERGING, LINES FLUSHED FROM FILE 1
SETOM MRGOUT+0 ;GO OUT TO THE MERGE FILE.
SETZ 0,
IFN ITS,[
.SUSET [.SWHO1,,[.BYTE 8 ? 166 ? 0 ? 55 ? ",]]
.SUSET [.SWHO3,,[1,,1]] ;INITIALIZE THE USER WHO-LINE FIELDS.
.SUSET [.SWHO2,,['HEADER]]
]
SKIPE 3WAY ;3-WAY MERGES HAVE A SPECIAL MAIN LOOP.
JRST 3LOOP
TLNE FR,FLMERG
JRST ENTER
MOVSI W1,-WPL
MOVE T,HBUF1(W1) ;LOOK FOR DIFFERENCES BETWEEN REAL FILE NAMES
CAMN T,HBUF2(W1) ;OF OUR TWO INPUT FILES.
AOBJN W1,.-2
TLNN FR,FLOVRD ;UNLESS FORCED BY /!,
JUMPGE W1,FIN5 ;IF THE NAMES ARE THE SAME, DON'T WASTE TIME COMPARING.
MOVEI W1,[ASCIZ /
;COMPARISON OF /]
CALL PRINT
MOVE W1,RCHSTP
CALL PRINT
MOVEI W1,[ASCIZ / AND /];RFINDR DEPENDS ON EXACT STRINGS USED HERE.
CALL PRINT
MOVE W1,RCHSTP+1
CALL PRINT
MOVEI W1,[ASCIZ /
;OPTIONS ARE /] ;NOTE RFINDR DEPENDS ON PRECISE STRING USED HERE.
CALL PRINT
IRPS X,,FLARCH FLALL FLCMNT FLENDL FLCASE FLLABL FLSPAC FLFNUM FLXLBL,Y,,A B C E K L S W Y
MOVEI W1,[ASCIZ * /Y*]
TLNE FR,X
CALL PRINT
TERMIN
MOVEI W1,[ASCIZ " /#"]
SKIPE FVBIN
CALL PRINT
MOVEI W1,[ASCIZ " /$"]
SKIPE FSBIN
CALL PRINT
MOVEI W1,[ASCIZ * /*]
CALL PRINT
MOVE T,NUMLIN
AOS T
CALL PNTDEC
CALL PCRLF
CALL PCRLF
JRST ENTER
ENTER:
IFN ITS,.SUSET [.SWHO2,,[SIXBIT/SAME/]]
SKIPE FVBIN ; Normally no binary compare
JRST BSAME ; Gadzooks! Use special routine.
SKIPE FSBIN
JRST SBSAME ; Use special SBLK compare routine
;THIS IS THE MAIN LOOP OF SRCCOM.
;COME HERE WHEN THE LAST TWO LINES MATCHED, TO TRY THE NEXT TWO.
SAME: SKIPE F1,LNNEXT(F1) ;ADVANCE PAST THE LINE THAT MATCHED
JRST SAME1
TRZ FR,-1 ;IF NO MORE LINES IN CORE, FLUSH ALL
SKIPE MRGOUT+0 ;THE LINES WE PASSED BY,
CALL MOVEUP
SETZM NLINE1 ;(IN THE SIMPLE COMMON CASE, FLUSH THEM FAST)
CALL RDLIN ;AND READ ANOTHER.
JRST END0 ;EOF => CHECK FILE 2 FOR EOF.
ERRHLT
SAME1: SKIPE F2,LNNEXT(F2) ;SIMILAR FOR F2,
JRST SAME2
SETZM NLINE2 ;BUT SINCE MRGOUT+1 SHOULD BE ZERO, IT'S SIMPLE.
HRRI FR,1
CALL RDLIN
JRST DIFF ;EOF IN FILE 2 BUT NOT IN FILE 1 => IT'S A DIFFERENCE.
ERRHLT
SAME2: CALL COMPL
JRST SAME ;THE TWO LINES ARE IDENTICAL; KEEP SCANNING.
JRST DIFF ;ELSE SEE HOW BIG THIS RUN OF DIFFERENCES IS.
; BINARY COMPARE - Main loop.
BSAME: TRZ FR,-1
CALL RDWRD ; Get word in W1
JRST BEND0 ; EOF => check file 2 for EOF
MOVE W2,W1
HRRI FR,1
CALL RDWRD ; Get another word from file 2
JRST BEND1 ; EOF on file 2, it"s a difference.
CAMN W1,W2 ; Compare words
JRST BSAME ; Won, get next one.
JRST BDIFF
BEND0: MOVE W2,W1 ; EOF on file 1, check file 2
HRRI F1,1
CALL RDWRD
JRST FIN2 ; If EOF on file 2 also, win!
PRINTI " EOF on file 1
"
AOS ERRCNT
JRST FIN2
BEND1: PRINTI " EOF on file 2
"
AOS ERRCNT
JRST FIN2
; Words are different. Must print out and show
; addr: <wd 1> <wd 2> <xor>
BDIFF: AOS ERRCNT ; Bump count of diffs
PUSH P,W1
PUSH P,W2
MOVE T,GWORDL(FR)
SUB T,GWORDC(FR) ; Find # words read thus far
CALL PNTOCT
PRINTI ": "
MOVE T,(P)
CALL PNTHWD
PRINTI " "
MOVE T,-1(P)
CALL PNTHWD
PRINTI " XOR= "
POP P,T
XOR T,(P)
CALL PNTHWD
POP P,T
CALL PCRLF
JRST BSAME
; Program ("SBLK") BINARY COMPARE - Main loop.
.SCALAR GWADR ; Address of word to get
SBSAME: TRZ FR,-1
CALL RDUWRD ; Get word in W1
JRST SBEND0 ; EOF => check file 2 for EOF
MOVE W2,W1
HRRI FR,1
CALL RDUWRD ; Get another word from file 2
JRST SBEND1 ; EOF on file 2, it"s a difference.
CAME W1,W2 ; Compare words
JRST SBDIFF
SBSAM0: AOS W1,GWADR
CAIG W1,-1
JRST SBSAME
JRST FIN2
SBEND0: MOVE W2,W1 ; EOF on file 1, check file 2
HRRI F1,1
CALL RDWRD
JRST FIN2 ; If EOF on file 2 also, win!
PRINTI " EOF on file 1
"
AOS ERRCNT
JRST FIN2
SBEND1: PRINTI " EOF on file 2
"
AOS ERRCNT
JRST FIN2
; Words are different. Must print out and show
; addr: <wd 1> <wd 2> <xor>
SBDIFF: AOS ERRCNT ; Bump count of diffs
PUSH P,W2
PUSH P,W1
MOVE T,GWADR ; Find # words read thus far
CALL PNTOCT
PRINTI ": "
MOVE T,-1(P) ; Get wd from file 1
CALL PNTHWD
PRINTI " "
MOVE T,(P) ; Then wd from file 2
CALL PNTHWD
PRINTI " XOR= "
POP P,T
XOR T,(P)
CALL PNTHWD
POP P,T
CALL PCRLF
JRST SBSAM0
;COME HERE WHEN A DIFFERENCE IS SEEN. F1 AND F2 POINT TO THE 1ST PAIR OF NON-MATCHING
;LINES, OR ARE ZERO TO SAY THAT AN ENTIRE FILE HAS BEEN MATCHED OFF.
DIFF: CALL MOVEUP ;FLUSH ANY MATCHING LINES STILL IN CORE BEFORE THOSE TWO.
TRC FR,1
CALL MOVEUP
SKIPE 0 ;0 SHOULD ALWAYS HOLD 0 FOR NEXTLN'S SAKE.
ERRHLT
IFN ITS,.SUSET [.SWHO2,,[SIXBIT/DIFF/]]
SETZM NCOMP1 ;NCOMP1 GETS NUMBER OF LINES OF FILE 1 WE HAVE FOR
SKIPE F1 ;CONSIDERATION.
AOS NCOMP1
SETZM NCOMP2 ;NCOMP2 GETS THE SAME THING FOR FILE 2.
SKIPE F2
AOS NCOMP2
DIFFRD: NEXTLN 1,END2 ;READ ANOTHER LINE FROM EACH FILE.
AOS NCOMP1
NEXTLN 2,DIFF2 ;NO NEW LINE FROM FILE 2 => DON'T COMPARE FILE 1 WITH IT
DIFF3: AOS NCOMP2
SKIPN CS,NCOMP1 ;HOW MANY FILE 1 LINES SHOULD WE CONSIDER?
JRST DIFFRD ;NONE?
SKIPA F1,LBUFP1 ;ELSE COMPARE ALL THE NON-MATCHING LINES OF FILE 1, 1 AT A TIME,
DIFF0: MOVE F1,W1 ;WITH THE NEW LINE FROM FILE 2.
CALL COMPL
CALL MULTI ;MATCH => CHECK FOR MULTI-LINE MATCH, GO TO SAME IF FOUND.
SKIPE W1,LNNEXT(F1)
SOJG CS,DIFF0
;AFTER COMPARING ALL THE FILE 1 LINES WITH THE NEW FILE 2 LINE, OR IF THERE IS NO NEW
;FILE 2 LINE, COME HERE TO COMPARE THE NEW FILE 1 LINE WITH ALL THE FILE 2 LINES.
;F1 IS ALREADY POINTING AT THE NEW FILE 1 LINE ("NEW" MEANS THAT DIFFRD GOT IT.
;IT MIGHT HAVE BEEN IN CORE ALREADY DUE TO NEXTLN'S DONE INSIDE MULTI).
DIFF2: SKIPE EOFFL1 ;BUT DON'T DO IT IF NO NEW FILE 1 LINE.
JRST DIFFRD
SKIPN CS,NCOMP2 ;HOW MANY LINES ARE WE CONSIDERING YET FROM FILE 2?
JRST DIFFRD ;NONE => NOTHING TO COMPARE WITH THE NEW LINE FROM 1.
SKIPA F2,LBUFP2 ;(MAY NOT BE SAME AS NLINE2, IF MULTI READ SOME LINES.)
DIFF1: MOVE F2,W1 ;ELSE LOOP HERE OVER THE FILE 2 LINES.
CALL COMPL
CALL MULTI
SKIPE W1,LNNEXT(F2)
SOJG CS,DIFF1
JRST DIFFRD ;NO MATCH => READ ANOTHER PAIR OF LINES AND TRY MATCHING THEM.
END0: SKIPE F2,LNNEXT(F2) ;HERE WHEN EOF IN FILE 1 AT SAME.
JRST DIFF ;MORE LINES IN FILE 2 => THEY'RE DIFFERENT.
SETZM NLINE2
HRRI FR,1
CALL RDLIN
JRST FIN2 ;EOF IN FILE 2 => ALL DONE.
ERRHLT
JRST DIFF
END2: NEXTLN 2,FINDIF ;NO NEW FILE 1 LINE IN DIFFRD. NO NEW FILE 2 LINE EITHER =>
JRST DIFF3 ;ALL THE NON-MATCHING LINES WE HAVE ARE DIFFERENCES.
;NEW LINE FROM FILE 2 => TRY MATCHING IT AGAINST FILE 1 LINES.
;AT THIS POINT NEITHER FILE HAS ANY MORE LINES TO BE READ.
;PRINT AS DIFFERENCES ANY LINES REMAINING FOR EITHER FILE.
FINDIF: SETZB F1,F2 ;MAKE SURE ALL LINES PRINTED IN CASE NO /E.
CALL COMSPC ;SEE IF DIFFERENCES VANISH IF WE IGNORE SPACES AND COMMENTS.
JRST FIN2 ;THEY DO; DON'T PRINT AS DIFFERENCES.
CALL PNTBTH ;PRINT ANY LINES
CALL TRYMRG
JRST FIN2
MOVEI W1,[ASCIZ/***************
/]
CALL PRINT
;COME HERE WHEN THE OUTPUT AND MERGE FILES ARE ALL GENERATED.
FIN2: TRZ FR,-1 ;OUTPUT THE STUFF IN FILE 1, IN CASE IN /M MODE.
CALL MOVEUP
TLNN FR,FLARCH ;IF SUPOSED TO BE ARCHIVING, DO THE APPEND NOW.
JRST FIN3
SKIPN ERRCNT ;BUT IF NO NEW STUFF TO APPEND, DO NOTHING,
JRST FIN5 ;AND THROW AWAY OUR 0-BLOCK FILE.
MOVE FP,[CHIN1,,LSTFB]
CALL OPNRDA
JRST FIN3 ;NO OLD FILE => JUST MAKE NEW ONE.
MOUTI CHOUT,^L
FIN4: MOVE W2,GCHARB ;IF SO, IF WE'RE ABOUT TO OVERWRITE A FILE,
MOVEI C,FILBFL*5 ;APPEND ITS OLD CONTENTS TO OUR OUTPUT, WITH ^L BETWEEN.
M.SIN CHIN1,W2,C ; INPUT
MOVNS C
ADDI C,FILBFL*5
JUMPE C,FIN3
MOVE W2,GCHARB
CALL PNTCNT
JRST FIN4
FIN5:
M.CLS CHOUT
IFN ITS,[
SYSCAL DELETE,[LSTFB+$FDEV ? ['_SRCCO] ? ['OUTPUT] ? LSTFB+$FDIR]
JFCL
]
FIN3: TLNE FR,FLMERG
CALL MRGFRC ;IF MERGING, FORCE OUT OUR BUFFER.
MOVEI W1,CHOUT ;WHICH CHANNEL IS OUR MOST IMPORTANT OUTPUT FILE ON?
TLNE FR,FLMERG
MOVEI W1,CHMRG
CALL RENMLO
MOVEI T,[ASCIZ /NO DIFFERENCES ENCOUNTERED/]
SKIPN ERRCNT ;ANY DIFFERENCES?
CALL TYPMS0 ;NO, PRINT MESSAGE
MOVEI T,[ASCIZ /? FILES ARE DIFFERENT/]
SKIPE QFLAG ;/Q MODE ON?
SKIPN ERRCNT ;/Q YES, ANY DIFFERNCES
SKIPA ;/Q NO
CALL TYPMS0 ;/Q YES
SKIPE ERRCNT ;/M ANY DIFFERENCES?
TLNN FR,FLMERG ;/M YES, MERGE IN PROGRESS?
JRST RELDEV ;/M NO, END OF SOURCE COMPARE
MOVEI T,[ASCIZ /END OF MERGE/]
TLNN FR,FLISWT\FLFLAG
CALL TYPMSG ;/M YES, PRINT END OF MERGE
JRST RELDEV ;END OF SOURCE COMPARE
;CALL MULTI TO CHECK FOR A MULTI-LINE MATCH, IF NECESSARY.
;IF THERE IS ONE, OR IT ISNT NECESSARY (NUMLIN = 0), RETURNS TO SAME
;AFTER PRINTING THE DIFFERENCES. IF THE MATCH FAILS, IT RETURNS
;NON-SKIPPING TO ITS CALLER.
;IN A 3-WAY MERGE, WE ARE USED TO COMPARE FILES 1 AND 2.
;WHEN WE FIND A MULTI-LINE MATCH, WE PUSH AN ENTRY ON
;12MTAB, THE TABLE OF PLACES WHERE FILES 1 AND 2 MATCH.
;EACH SUCH PLACE GETS COMPARED AGAINST FILE 3 LATER.
MULTI: SAVE CS
MOVEM F1,TEMPF1 ;SAVE CURRENT POINTERS
MOVEM F2,TEMPF2
SKIPG NUMLIN ;MULTIPLE LINE TEST?
JRST MULT8 ;NO
SETZM NUMTMP ;INIT MULTI-LINE COUNTER
MULT2: NEXTLN 1,MULTE ;MUST GET A NEW LINE FROM BOTH FILES
NEXTLN 2,MULT4 ;TO CONTINUE THE MULTI-LINE MATCH.
CALL COMPL ;COMPARE THEM
JRST MULT6 ;MATCH, TEST MULTI COUNTER
MULT4: SKIPE F1,TEMPF1 ;NO MATCH, RESET REGS
SETZM EOFFL1 ;IF NO LONGER AT LAST LINE, CAN'T BE AT EOF.
SKIPE F2,TEMPF2
SETZM EOFFL2
REST CS
RET
MULTE: NEXTLN 2,MULT8
JRST MULT4
MULT6: AOS W1,NUMTMP ;INDEX MULTI-LINE COUNTER
CAMGE W1,NUMLIN ;TEST FOR ENOUGH LINES MATCHED
JRST MULT2 ;COMPARE NEXT TWO.
MULT8: SKIPE 3WAY
JRST [ MOVE W1,TEMPF2 ;IN A 3-WAY MERGE, RECORD THIS MATCH OF FILES 1 AND 2
HRL W1,TEMPF1
IDPB W1,12MTBP
JRST MULT4] ;AND RETURN TO OUR CALLER (JUST AS IF WE HAD FAILED).
EXCH F1,TEMPF1 ;REMEMBER WHERE THE MULTI-LINE MATCH STOPPED,
EXCH F2,TEMPF2 ;GO BACK TO WHERE IT STARTED.
SUB P,[2,,2] ;FLUSH MULTI'S RETURN ADDRESS.
CALL COMSPC ;SEE IFF ALL DIFFERENCES VANISH WHEN IGNORE SPACES & COMMENTS.
JRST MULT10
CALL PNTBTH ;PRINT DIFFERENCES
;THE TEXT OF DIFFERENCES HAS BEEN PRINTED--PUT IN ******
;AND A CARRIAGE RETURN-LINE FEED AND GO BACK AND START COMPARING
;WHEN WE START COMPARING AGAIN THE LINE POINTERA WILL
;BE POINTING TO THE FIRST TWO LINES AFTER THE MATCHING LINES
CALL TRYMRG ;/M CHECK IF /M IN EFFECT, ASK FOR COMMAND
;/M AND OUTPUT IF YES
JRST MULT10 ;/M IN EFFECT
MOVE W1,[440700,,[ASCIZ /***************
/]]
CALL PRINT
MULT10: SKIPE F1,TEMPF1 ;NOW MOVE FORWARD PAST THE LINES MATCHED
SETZM EOFFL1 ;IN THE MULTI-LINE MATCH.
SKIPE F2,TEMPF2
SETZM EOFFL2
JRST ENTER
;AFTER FINDING A RUN OF DIFFERENCES, SEE WHETHER THE FILES ARE IDENTICAL
;WHEN WE IGNORE SPACES AND COMMENTS ACCORDING TO THE /S AND /C SWITCHES.
;IF SO, RETURNS NON-SKIPPING. SKIPS IF THE DIFFERENCE SHOULD BE PRINTED.
;EVEN IF /S AND /C ARE NOT SET, THIS ROUTINE TAKES CARE OF IGNORING
;DIFFERENCES IN BLANK LINES. ALSO, IF /K, IGNORES DIFFERENCES IN CASE.
COMSPC: TLNE FR,FLSPAC ;THIS ROUTINE CAN MAKE A DIFFERENCE IF
TLNE FR,FLALL ;WE ARE IGNORING BOTH SPACING AND BLANK LINES
TLNE FR,FLCMNT ;OR WE ARE IGNORING COMMENTS.
CAIA
JRST POPJ1 ;NOTHING IGNORED => DO PRINT.
SAVE F1
SAVE F2
SKIPE F1,NLINES+0 ;MAKE F1 AND F2 POINT AT THE FIRST DIFFERING LINES.
MOVE F1,LBUFP+0
SKIPE F2,NLINES+1
MOVE F2,LBUFP+1
COMSPL: CAMN F1,-1(P) ;HAVE WE CONSIDERED ALL THE LINES FROM FILE 1?
JRST COMSP2
HRRI FR,0 ;NO.
TLNN FR,FLALL ;DON'T SKIP LINES WITH JUST COMMENTS IF NOT IGNORING BLANK LINES!
CALL BLANKP ;FIRST, TRY TO IGNORE ESSENTIALLY BLANK LINES
JRST COMSP2 ;IN FILE 1.
MOVE F1,LNNEXT(F1) ;FOUND ONE => SKIP PAST IT.
JRST COMSPL
COMSP2: CAMN F2,(P) ;THEN TRY FOR BLANK LINES IN FILE 2
JRST COMSPX ;NO LINES IN FILE 2 => CAN'T WIN.
HRRI FR,1
TLNN FR,FLALL
CALL BLANKP
JRST COMSP3
MOVE F2,LNNEXT(F2)
JRST COMSPL
COMSP3: CAMN F1,-1(P) ;IF BOTH FILES HAVE LINES,
JRST COMSPX
CALL COMPCS ;SEE IF THEY ARE EQUAL WHEN SPACES & COMMENTS ARE IGNORED.
JRST COMSPF
;HERE WHEN WE CAN'T ELIMINATE ANY MORE LINES BY IGNORING SPACES & COMMENTS
COMSPX: CAMN F1,-1(P) ;IF NO LINES LEFT FROM EITHER FILE, WE WIN
CAME F2,(P)
AOS -2(P) ;OTHERWISE, THE DIFFERENCES ARE ESSENTIAL.
REST F2
REST F1
RET
;COME HERE IF TWO LINES MATCH WHEN WE IGNORE APPROPRIATE STUFF.
COMSPF: MOVE F1,LNNEXT(F1) ;SKIP BOTH LINES.
MOVE F2,LNNEXT(F2)
JRST COMSPL
;SKIP IF THE LINE F1(FR) POINTS AT IS BLANK WHEN
;SPACES AND COMMENTS ARE IGNORED ACCORDING TO SWITCH SETTINGS.
BLANKP: HRRZ W1,F1(FR)
MOVE C,LNSIZE(W1)
ADD W1,[440700,,LNDATA]
BLANK1: ILDB T,W1
SOJLE C,POPJ1 ;WE WIN IF EXHAUST THE LINE AFTER JUST SPACES AND CRLFS.
CAIE T,^M
CAIN T,^J
JRST BLANK1
CAIE T,40
CAIN T,^I
TLNN FR,FLSPAC
CAIA
JRST BLANK1
TLNE FR,FLCMNT ;IF /C, WE ALSO WIN IF WE FIND A SEMICOLON.
CAIE T,";
RET
JRST POPJ1
3LOOP:
IFN ITS,.SUSET [.SWHO2,,[SIXBIT/SAME/]]
;THIS IS THE MAIN LOOP OF 3-WAY MERGING.
;COME HERE WHEN THE LAST LINES OF ALL 3 FILES MATCHED, TO TRY THE NEXT LINES OF ALL 3.
3SAME: SKIPE F1,LNNEXT(F1) ;ADVANCE PAST THE LINE THAT MATCHED
JRST 3SAME1
TRZ FR,-1 ;IF NO MORE LINES IN CORE, FLUSH ALL
SKIPE MRGOUT+0 ;THE LINES WE PASSED BY,
CALL MOVEUP
SETZM NLINE1 ;(IN THE SIMPLE COMMON CASE, FLUSH THEM FAST)
CALL RDLIN ;AND READ ANOTHER.
CAIA
JFCL
3SAME1: SKIPE F2,LNNEXT(F2) ;SIMILAR FOR F2,
JRST 3SAME2
SETZM NLINE2 ;BUT SINCE MRGOUT+1 SHOULD BE ZERO, IT'S SIMPLE.
HRRI FR,1
CALL RDLIN
CAIA
JFCL
3SAME2: SKIPE F3,LNNEXT(F3) ;FOR F3, JUST LIKE F2.
JRST 3SAME3
SETZM NLINE3
HRRI FR,3
CALL RDLIN
CAIA
JFCL
3SAME3: MOVE W1,EOFFL1 ;UNLESS EITHER ALL 3 FILES ARE ENDING OR NONE,
CAMN W1,EOFFL2 ;IT'S A DIFFERENCE.
CAME W1,EOFFL3
JRST 3DIFF
CALL COMPL ;COMPARE LINE FROM FILE 1 WITH THAT FROM FILE 2.
CAIA
JRST 3DIFF
EXCH F2,F3
CALL COMPL ;COMPARE FILE 1 WITH FILE 3.
CAIA
JRST [ EXCH F2,F3
JRST 3DIFF]
EXCH F2,F3 ;1 MATCHES 2 AND MATCHES 3 => ALL 3 STILL THE SAME.
SKIPE EOFFL1
JRST FIN2
JRST 3SAME
;COME HERE, DURING A 3-WAY MERGE, WHEN A DIFFERENCE IS SEEN.
;THAT IS, WHEN ALL 3 FILES CEASE TO BE IDENTICAL.
;F1, F2, F3 POINT AT THE FIRST NON-MATCHING LINES,
;OR ARE ZERO TO SAY THAT AN ENTIRE FILE HAS BEEN MATCHED OFF.
;COME HERE WHEN A DIFFERENCE IS SEEN. F1 AND F2 POINT TO THE 1ST PAIR OF NON-MATCHING
;LINES, OR ARE ZERO TO SAY THAT AN ENTIRE FILE HAS BEEN MATCHED OFF.
3DIFF: HRRI FR,0
CALL MOVEUP ;FLUSH ANY MATCHING LINES STILL IN CORE BEFORE THOSE TWO.
HRRI FR,1
CALL MOVEUP
HRRI FR,2
CALL MOVEUP
SKIPE 0 ;0 SHOULD ALWAYS HOLD 0 FOR NEXTLN'S SAKE.
ERRHLT
IFN ITS,.SUSET [.SWHO2,,[SIXBIT/DIFF/]]
SETZM NCOMP1
SKIPL EOFFL1
AOS NCOMP1
SETZM NCOMP2
SKIPL EOFFL2
AOS NCOMP2
SETZM NCOMP3
SKIPL EOFFL3
AOS NCOMP3
MOVE W1,12MTBB ;CLEAR THE TABLE OF MATCHES BETWEEN FILES 1 AND 2.
MOVEM W1,12MTBP
3DIFFR: NEXTLN 1 ;READ ANOTHER LINE FROM EACH FILE.
SKIPL EOFFL1
AOS NCOMP1
NEXTLN 2
SKIPL EOFFL2
AOS NCOMP2
NEXTLN 3
SKIPL EOFFL3
AOS NCOMP3
SKIPE EOFFL2
JRST 3DIFF2
SKIPN CS,NCOMP1 ;HOW MANY FILE 1 LINES SHOULD WE CONSIDER?
JRST 3DIFF2
SKIPA F1,LBUFP1 ;COMPARE ALL THE NON-MATCHING LINES OF FILE 1, 1 AT A TIME,
3DIFF0: MOVE F1,W1 ;WITH THE NEW LINE FROM FILE 2.
CALL COMPL
CALL MULTI ;MATCH => CHECK FOR MULTI-LINE MATCH, PUT IN 12MTAB IF FOUND.
SKIPE W1,LNNEXT(F1)
SOJG CS,3DIFF0
;AFTER COMPARING ALL THE FILE 1 LINES WITH THE NEW FILE 2 LINE, OR IF THERE IS NO NEW
;FILE 2 LINE, COME HERE TO COMPARE THE NEW FILE 1 LINE WITH ALL THE FILE 2 LINES.
;F1 IS ALREADY POINTING AT THE NEW FILE 1 LINE ("NEW" MEANS THAT DIFFRD GOT IT.
;IT MIGHT HAVE BEEN IN CORE ALREADY DUE TO NEXTLN'S DONE INSIDE MULTI).
3DIFF2: SKIPE EOFFL1 ;BUT DON'T DO IT IF NO NEW FILE 1 LINE.
JRST 3DIFF3
SKIPN CS,NCOMP2 ;HOW MANY LINES ARE WE CONSIDERING YET FROM FILE 2?
JRST 3DIFF3
SKIPA F2,LBUFP2 ;(MAY NOT BE SAME AS NLINE2, IF MULTI READ SOME LINES.)
3DIFF1: MOVE F2,W1 ;ELSE LOOP HERE OVER THE FILE 2 LINES.
CALL COMPL
CALL MULTI ;IF MULTI-LINE MATCH FOUND, PUT IT IN 12MTAB.
SKIPE W1,LNNEXT(F2)
SOJG CS,3DIFF1
;NOW WE KNOW ABOUT THE PLACES WHERE FILES 1 AND 2 MATCH.
;EACH SUCH PLACE (WITHIN THE RANGE BEING CONSIDERED) IS LISTED IN 12MTAB.
;WE NOW COMPARE EACH OF THOSE PLACES AGAINST WHAT WE HAVE OF FILE 3.
3DIFF3: PUSH P,F1
PUSH P,F2
MOVE W1,12MTBB
3DIFF6: CAMN W1,12MTBP
JRST 3DIFF4 ;NO MATCH => READ ANOTHER PAIR OF LINES AND TRY MATCHING THEM.
ILDB F2,W1
PUSH P,W1
ANDI F2,-1 ;FIND THE FILE 2 LOCATION OF THE NEXT 1-2 MATCH.
MOVE CS,NCOMP3
SKIPA F1,LBUFP3
3DIFF5: MOVE F1,W1
CALL COMPL ;COMPARE THAT AGAINST EACH POINT OF FILE 3.
CALL 3MULTI ;NOTE THAT WE ARE USING F1 TO HOLD THE FILE 3 POINTER.
SKIPE W1,LNNEXT(F1)
SOJG CS,3DIFF5
POP P,W1
JRST 3DIFF6
3DIFF4: POP P,F2
POP P,F1 ;NO MATCH FOUND.
SKIPE EOFFL1 ;NORMALLY, READ ANOTHER LINE FROM EACH FILE.
SKIPL EOFFL2
JRST 3DIFFR
SKIPL EOFFL3
JRST 3DIFFR
JRST 3ALDIF ;BUT IF ALL ARE AT EOF, TAKE ALL REMAINING LINES OF ALL FILES AS DIFFS.
; THIS IS A COLLECTION OF STUFF THAT WAS UNDEFINED AT THE
; TIME CONVERSION TO TNX WAS DONE. VALUES ARE FURNISHED HERE
; JUST TO MINIMIZE ASSEMBLY BARFAGE, BUT SOMEDAY PRESUMABLY
; SOMEONE WILL REPLACE WITH THE PROPER THINGS.
3ALDIF:
3MULTI: RET ; NOP FOR NOW
.SCALAR 3WAY ; -1 IF DOING 3-WAY COMPARE
.SCALAR 12MTBP ; SOMETHING TO DO WITH 3WAY MERGE?
.SCALAR 12MTBB ; DITTO
;/M ROUTINE TO TEST IF MERGE IN EFFECT AND IF YES
;/M ACCPT COMMAND AND PASS TO MERGE OUTPUT FILE
;/M COMMANDS ARE ANY COMBINATION OF 1,2,I AND/OR T (WITH NO COMMAS)
;/M ALL OTHER CHARACTERS ARE ILLEGAL
;/M CALL: CALL TRYMRG
; MERGER DONE RETURN
; /M NOT IN EFFECT RETURN
TRYMRG: TLNN FR,FLMERG ;/M /M SWITCH IN EFFECT?
JRST POPJ1 ;/M NO, SKIP RETURN
IFN ITS,.SUSET [.SWHO2,,[SIXBIT/MERGE/]]
TLNE FR,FLISWT ;/I => ASSUME "I" AS AN ANSWER.
JRST MRGI1
TLNE FR,FLFLAG ;/F => PUT OUT THE FILE 2 STUFF WITH FLAGS.
JRST MRGU1
CALL GETMRG ;/M TYPE *,GET ALL OF MERGE COMMAND(CHECK SYNTAX)
LISTEN: CALL MRGIN ;/M GET NEXT MERGE COMMAND INPUT CHAR
CAIE C,"1 ;/M DID HE TYPE 1?
CAIN C,"2 ;/M DID HE TYPE 2?
JRST MRG5 ;YES FOR ONE OF THEM!
CAIN C,"I
JRST MRGI ;"I"=> PUT IN BOTH FILES' TEXTS AND IDENTIFYING MARKS.
CAIE C,"T ;/M "T" TYPED?
JRST MRG4 ;/M NO, CHECK FOR END OF COMMAND
MRG3B: CALL TTILIN
MRG3A: CALL TTICHR ;GET TTY INPUT CHAR.
CAIE C,^C ;/M EOF OR
CAIN C,ALTM ;/M ALT-MODE?
JRST LISTEN ;/M YES, END OF INSERT FROM TTY
CALL MRGO ;/M NO, OUTPUT CHAR TO MERGE FILE
CAIE C,^M ;CR -> SPECIAL.
JRST MRG3A ;ELSE GET MORE
MOVEI C,^J ;PUT IN ^J AFTER ^M.
CALL MRGO
JRST MRG3B ;GET NEXT TTY LINE.
MRG4: CAIE C,0 ;/M MUST BE NULL(END OF COMMAND)
ERRHLT ;/M NO SOME THING IS VERY WRONG
HRRI FR,0 ;/M FLUSH DIFFERENCES IN FILE ONE IF NOT ALREADY
SETZM MRGOUT(FR) ;/M BUT DO NOT OUTPUT ON MERGE FILE
CALL MOVEUP ;/M NO, OUTPUT DIFFERENCES AND FLUSH
HRRI FR,1 ;/M FLUSH DIFFERENCES IN FILE TWO IF NOT ALREADY
SETZM MRGOUT(FR) ;BUT DO NOT OUTPUT ON MERGE FILE
CALL MOVEUP ;/M NO, OUTPUT DIFFERENCES AND FLUSH
SETOM MRGOUT+0
RET ;/M RETURN, LEAVING MATCH LINES STILL IN BUFFER
MRG5: HRRI FR,-"1(C)
SETOM MRGOUT(FR) ;/M YES, SET FLAG SO MOVEUP WILL OUTPUT
CALL MOVEUP ;/M MOVE BUFFER UP OVER DIFFERENCES USER WANTS
JRST LISTEN ;/M GO GET ANOTHER CHARACTER
;/F => WHEN DIFFERENCES ARE FOUND, OUTPUT THE LINES FROM FILE 2
;WITH A "|" AT THE FRONT OF EACH ONE.
MRGU1: SETOM MRGOUT+1
HRRI FR,1
SETOM MRGUFL ;TELL MOVEUP TO INSERT "|"'S
PUSH P,F1(FR)
CALL MOVEUP ;OUTPUT THE STUFF FROM FILE 2
REST W1
MOVEI W2,[ASCIZ /^^^^/] ;THEN OUTPUT "^^^^" IN FRONT OF NEXT LINE
CAMN W1,F1(FR) ;IF THERE WERE NO LINES FROM FILE 2 (A DELETION).
CALL MRGPNT
SETZB C,MRGUFL
JRST MRG4 ;THROW AWAY STUFF FROM FILE 1 AND RETURN.
;"I" MERGE COMMAND - PUT IN THE MERGE FILE THE FOLLOWING:
;*** MERGE LOSSAGE ***
;*** FILE FOOBAR 1001 HAS:
;<TEXT FROM FILE 1>
;*** FILE FOOBAR 1002 HAS:
;<TEXT FROM FILE 2>
;*** END OF MERGE LOSSAGE ***
MRGI: SAVE [LISTEN]
MRGI1: MOVEI W2,[ASCIZ /*** MERGE LOSSAGE ***
*** FILE /]
CALL MRGPNT
MOVE W2,RCHSTP ;-> NAMES OF FILE 1.
CALL MRGPNT
MOVEI W2,[ASCIZ / HAS:
/]
CALL MRGPNT
SETOM MRGOUT ;OUTPUT THE TEXT OF FILE 1
HRRI FR,0
CALL MOVEUP
MOVEI W2,[ASCIZ /*** FILE /]
CALL MRGPNT
MOVE W2,RCHSTP+1 ;-> NAMES OF FILE 2.
CALL MRGPNT
MOVEI W2,[ASCIZ / HAS:
/]
CALL MRGPNT
SETOM MRGOUT+1 ;OUTPUT TEXT FROM FILE 2.
HRRI FR,1
CALL MOVEUP
SETZM MRGOUT+1 ;CLEAR THIS OR WE'D GET 2 COPIES OF FURTHER UNCHANGED TEXT!
MOVEI W2,[ASCIZ /*** END OF MERGE LOSSAGE ***
/]
JRST MRGPNT
;PRINT ASCIZ STRING <- W2 ON THE MERGE FILE.
MRGPNT: HRLI W2,440700
MRGPN1: ILDB C,W2
JUMPE C,CPOPJ
CALL MRGO
JRST MRGPN1
;OUTPUT STRING <- W2 WITH # CHARS IN C.
MRGCNT: SAVE W1
SKIPN W1,C
JRST POPW1J
MRGCN1: ILDB C,W2
CALL MRGO
SOJG W1,MRGCN1
JRST POPW1J
;HERE TO OUTPUT ONE CHARACTER TO CHMRG VIA BUFFER.
MRGO: IDPB C,MRGBP
SOSLE MRGCT
RET
;EMPTY OUT OUR CHMRG BUFFER.
MRGFRC: SAVE W1
SAVE W2
MOVE W1,[440700,,MRGBF]
MOVEM W1,MRGBP
MOVEI W2,MRGBSZ
SUB W2,MRGCT ;# CHARS FILLED IN IT.
ADDM W2,MRGCT ;MARK IT EMPTY (AFTER WE WRITE DATA).
JUMPE W2,MRGFR1
M.SOUT CHMRG,W1,W2 ; OUTPUT STRING
MRGFR1: REST W2
POPW1J: REST W1
RET
;/M ROUTINE TO GET INPUT FOR MERGE COMMAND
;/M STORES ENTIRE COMMAND IN SPECIAL BUFFER
;/M IN CASE USER TYPES T COMMAND AS ONE OF COMMANDS
;/M WHICH WILL SLAO REQUIRE TTY INPUT
;/M CHECK SYSTAX, DO NOT RTURN UNTIL GOOD COMMAND LINE TYPED IN
GTMRG0: HLRZ C,(P)
MOVEM W1,(C)
GETMRG: CALL TTILNA ;READ TTY LINE, PROMPTING WITH A "*".
MOVE W1,[440700,,MRGCOM] ;/M SET UP BYTE POINTER TO MERGE
;/M COMMAND BUFFER
GTMRG1: MOVEI C,0 ;/M IN CASE TOO LONG COMMAND
CAME W1,[350700,,MRGCOM+MRGLEN-1]
CALL TTICHU
CAIGE C,40 ;/M ALTM,LF?
MOVEI C,0 ;/M YES, FLAG END OF MERGE COMAND WITH NULL
IDPB C,W1 ;/M STORE CHAR
CAIE C,"1 ;/M IS IT "1"?
CAIN C,"2 ;/M OR "2"?
JRST GTMRG1 ;/M YES, GET ANOTHER
CAIE C,"I
CAIN C,"T ;/M NO, IS IT "T"?
JRST GTMRG1 ;/M YES, GET ANOTHER
CAIN C,"L
JRST GTMRGL
CAIE C,"C ;/M C?
JRST GTMRG3 ;/M NO
SKIPA W1,[COLMAX]
GTMRGL: MOVEI W1,LINMAX
HRLM W1,(P)
MOVEI W1,0
GTMRG2: CALL TTICHR ;/M GE CHAR
CAIGE C,40 ;/M END OFLINE CHAR?
JRST GTMRG0 ;/M YES STORE NEW MAX.
CAIL C,"0 ;/M NO, A DECIMAL DIGIT?
CAILE C,"9 ;/M
JRST GTMRG4 ;/M NO, PRINT ERROR
IMULI W1,12 ;/M YES CONVERT TO BINARY
ADDI W1,-"0(C) ;/M ADD IN THIS DIGIT
JRST GTMRG2 ;/M GO GET NEXT DIGIT
GTMRG3: MOVE W1,[440700,,MRGCOM] ;/M ASSUME IT IS END OF LINE
MOVEM W1,MRGBYT ;/M AND STORE BYTE POINTER TO SCANNED STRING
JUMPE C,CPOPJ ;/M IS IT?
GTMRG4: MOVE W1,[440700,,[ASCIZ "?ONLY 1, 2, I, AND/OR T ARE LEGAL IN MERGE COMMANDS
OR C### TO SET MAX. COL. OR L### TO SET MAX. LINES TYPED.
"]]
CALL PRINT ;/M PRINT ERROR
JRST GETMRG ;/M AND ASK FOR COMMAND OVER AGAIN
;/M ROUTINE TO GET NEXT CHAR FROM MERGE COMMAND BUFFER
;/M CALL: CALL MRGIN
;/M RETURN WITH CHAR IN C
MRGIN: ILDB C,MRGBYT ;/M GET NEXT CHAR
RET
;MOVEUP FLUSHES ALL THE LINES OF THE FILE SPECIFIED BY RH(FR)
;THAT ARE BEFORE THE LINE POINTED BY F1 OR F2 OR F3.
;IF THERE ARE ANY LINES AFTER F1 OR F2 OR F3, THEY HAVE TO BE BLT'ED DOWN
;TO THE BEGINNING OF THE FILE'S SEGMENT. IF THERE ARE NONE,
;ONLY POINTER RELOCATION TAKES PLACE.
;F1 OR F2 OR F3 CONTINUES TO POINT AT THE SAME LINE, OR REMAINS 0.
;IF MRGOUT(FR) IS NONZERO, THE FLUSHED LINES ARE OUTPUT TO THE
;MERGE FILE.
MOVEUP: SKIPN FSBIN
SKIPE FVBIN
RET ; Ignore if doing binary compare.
SKIPE MRGOUT(FR) ;SKIP IF SHOULD OUTPUT TO MERGE FILE,
CALL MOVEU1 ;DO SO.
SKIPE W1,F1(FR) ;GET ADDR OF 1ST LINE NOT TO FLUSH.
JRST MOVEU5
SETZM NLINES(FR) ;FLUSHING ALL LINES => JUST SAY THERE ARE NONE.
RET
MOVEU5: MOVEI T,1 ;T COUNTS THE NUMBER OF LINES LEFT.
MOVN C,W1 ;WE MUST BLT FROM C(W1) TO C(LBUFP(FR))
ADD C,LBUFP(FR) ;HOW FAR IS THAT?
MOVEU3: MOVE W2,W1 ;W2 REMEMBERS THE LAST LINE'S ADDR
CAMN W1,TEMPF1(FR) ;RELOCATE TEMPF1 IF IT POINTS AT THIS LINE.
ADDM C,TEMPF1(FR)
SKIPN W1,LNNEXT(W1) ;FIND THE NEXT LINE WHERE IT NOW IS
JRST MOVEU4
ADDM C,LNNEXT(W2) ;RELOCATE POINTER -> WHERE IT WILL BE BLT'ED TO.
AOJA T,MOVEU3 ;ANOTHER LINE => COUNT IT.
MOVEU4: MOVEM T,NLINES(FR)
HRLZ W1,F1(FR) ;LH(W1) GETS CURRENT ADDRESS OF 1ST LINE TO KEEP
HRR W1,LBUFP(FR) ;RH GETS NEW ADDR
MOVE T,LNSIZE(W2) ;FIND END OF LAST LINE
ADDI T,5
IDIVI T,5 ;FIRST FIND LENGTH IN WORDS
ADDI W2,LNDATA-1(T) ;ADD ADDR OF START OF LINE
ADD W2,C ;FIND WHERE THAT END IS BEING RELOCATED TO.
BLT W1,(W2) ;COPY THE LINES THAT ARE LEFT TO THEIR NEW HOMES.
MOVE W1,LBUFP(FR)
MOVEM W1,F1(FR) ;NOW RELOCATE F1(FR).
RET
;OUTPUT THE LINES UP THE FILE IN FR THAT ARE BEFORE F1 OR F2 OR F3 TO THE MERGE FILE.
MOVEU1: MOVE W1,LBUFP(FR) ;GET ADDR OF 1ST LINE TO BE FLUSHED.
SKIPN NLINES(FR)
SETZ W1,
MOVEU2: CAMN W1,F1(FR) ;REACHED 1ST LINE NOT TO BE FLUSHED?
RET ;NO, OUTPUT LINE W1 POINTS AT.
TLNE FR,FLFLAG
SKIPGE LPHONY ;IF THIS LINE IS PHONY (NOT FIRST AFTER A CRLF)
JRST MOVEU6 ;OMIT ANY /F HACKERY.
SKIPLE LPHONY ;IF FOLLOWS A STRAY CR, JUST PUT IN A TAB.
JRST MOVEU7
MOVEI C,"|
SKIPE MRGUFL ;IF OUTPUTTING DIFFERENCES IN /F MODE, PREFIX WITH "|".
CALL MRGO
TLNN FR,FLFLAG ;IN /F MODE, PUT A TAB BEFORE EVERY LINE
JRST MOVEU6
MOVEU7: MOVEI C,^I ;SO "|"'S AND "^"'S CAN STAND OUT.
CALL MRGO
MOVEU6: MOVEI W2,LNDATA(W1)
HRLI W2,440700 ;GET ADDR OF 1ST DATA WORD
MOVE C,LNSIZE(W1) ;AND # OF CHARACTERS.
SETZM LPHONY ;SET LPHONY FOR NEXT LINE UNLESS THIS ONE ENDS IN A CRLF.
CAIGE C,2
SETOM LPHONY
CALL MRGCNT ;TRANSFER THE CHARACTERS.
SOS W2
REPEAT 3,IBP W2 ;DECREMENT W2 TWICE.
ILDB C,W2
CAIE C,^M
SETOM LPHONY ;CHECK FOR THE TERMINAL CRLF.
ILDB C,W2
CAIE C,^J
SETOM LPHONY
CAIN C,^M
MOVNS LPHONY ;LEAVE 1 IN LPHONY IF LINE ENDS IN JUST CR.
MOVE W1,LNNEXT(W1) ;GO TRY THE NEXT LINE.
JRST MOVEU2
;SKIP UNLESS THE TWO CURRENT LINES ARE EQUAL. IGNORES CASE CHANGES AND
;SPACING CHANGES IF SPECIFIED, BUT NEVER IGNORES COMMENTS.
;MUSTN'T CLOBBER CS.
COMPL: MOVE C,LNSIZE(F1) ;FIRST TEST FOR EXACT MATCH.
CAME C,LNSIZE(F2)
JRST COMPUL ;LINE LENGTHS DIFFER => NO EXACT MATCH,
MOVEI W1,5(C) ;ELSE COMPARE THE LINES WORD-BY-WORD.
IDIVI W1,5
MOVNS W1 ;-<# WDS OF DATA IN LINE>
HRLZS W1
HRRI W1,LNDATA(F1) ;AOBJN POINTER TO DATAT IN FILE 1 LINE.
MOVEI W2,LNDATA(F2) ;AND POINTER TO DATA OF FILE 2 LINE.
SUB W2,W1
HRRM W2,COMPLX
COMPL1: MOVE C,(W1) ;COMPARE WORD BY WORD, IGNORING LOW BITS.
COMPLX: XOR C,(W1) ;ADDR FIELD MAKES E.A. POINT TO SECOND FILE'S LINE.
TDNE C,[-2]
JRST COMPUL ;JUMP IF NO EXACT MATCH.
AOBJN W1,COMPL1
RET
COMPUL: TLNN FR,FLCASE\FLSPAC ;NO EXACT MATCH. CAN WE TRY IGNORING STUFF?
JRST POPJ1 ;NO, SO MUST RETURN "NO MATCH".
;IGNORING CASE OR SPACING => WE GET A SECOND CHANCE.
MOVEI W1,LNDATA(F1)
MOVEI W2,LNDATA(F2)
HRLI W1,440700
HRLI W2,440700
COMPU1: ILDB T,W1 ;GET A CHARACTER FROM LINE FROM FIRST FILE
ILDB TT,W2 ;AND ONE FROM SECOND FILE
CAME T,TT ;THEY'RE EXACTLY EQUAL => KEEP LOOKING
JRST COMPU2
JUMPN T,COMPU1 ;BUT DON'T LOOK PAST ENDS OF THE LINES.
POPJ P, ;REACH ENDS OF LINES => LINES MATCH.
COMPU2: TLNN FR,FLSPAC
JRST COMPU4
CAIE T,40 ;IF SUPPOSED TO IGNORE CHANGES IN SPACING, DO SO
CAIN T,^I ;BY SKIPPING ALL SPACES & TABS IN BOTH FILES.
JRST [ILDB T,W1
JRST .-2]
CAIE TT,40
CAIN TT,^I
JRST [ILDB TT,W2
JRST .-2]
COMPU4: TLNN FR,FLCASE
JRST COMPU3
CAIL T,"A+40 ;IF SUPPOSED TO IGNORE CHANGES IN CASE, CONVERT TO U.C.
CAILE T,"Z+40
CAIA
SUBI T,40
CAIL TT,"A+40
CAILE TT,"Z+40
CAIA
SUBI TT,40
COMPU3: CAMN T,TT ;DO THEY MATCH NOW?
JRST COMPU1
JRST POPJ1 ;NO => LINES DON'T MATCH.
;SKIP UNLESS THE TWO CURRENT LINES ARE THE SAME WHEN APPROPRIATE
;STUFF IS IGNORED (SPACES AND COMMENTS, OR ALPHABETIC CASE,
; ACCORDING TO SWITCHES).
COMPCS: MOVEI W1,LNDATA(F1)
MOVEI W2,LNDATA(F2)
HRLI W1,440700
HRLI W2,440700
COMPL3: ILDB T,W1 ;GET A CHARACTER FROM LINE FROM FIRST FILE
COMPL6: ILDB TT,W2 ;AND ONE FROM SECOND FILE
CAME TT,T ;THIS IS THE BIG TEST--ARE THEY EQUAL
JRST COMPL4 ;NO
COMPL7: CAIN T,"; ;YES, COMMENT?
TLNN FR,FLCMNT ;YES, SUPPRESS COMMENTS?
JUMPN T,COMPL3 ;NO,NO. TEST FOR END OF LINE
RET ;LINES MATCH, RETURN
COMPL4: TLNN FR,FLSPAC ;CHARS DIFFER: MAYBE TRY IGNORING SPACING
JRST COMPL8
CAIE TT,40 ;SPACE IN FILE 2, OR TAB?
CAIN TT,TAB
JRST COMPL6 ;IF SO, SKIP IT.
COMPL5: CAIE T,40 ;SPACE IN FILE 1?
CAIN T,TAB ;OR TAB?
JRST [ILDB T,W1 ;SKIP TO FIRST NON-SPACE NON-TAB.
JRST COMPL5]
CAMN T,TT ;ARE THE CHARACTERS NOW THE SAME?
JRST COMPL7 ;YES, TEST FOR END OF LINES
COMPL8: TLNN FR,FLCASE ;SPACES DIDN'T HELP - ARE WE IGNORING CASE?
JRST COMPL2
CAIL T,"A+40 ;CHARS DON'T MATCH => WE STILL HAVE A CHANCE
CAILE T,"Z+40 ;IF THEY'RE BOTH LETTERS; CONVERT BOTH TO UPPER CASE.
CAIA
SUBI T,40
CAIL TT,"A+40
CAILE TT,"Z+40
CAIA
SUBI TT,40
CAMN T,TT ;IF THIS HELPED, KEEP GOING
JRST COMPL3 ;NO USE CHECKING FOR EOL - THESE MUST BE BOTH LETTERS.
;LAST CHANCE - MAYBE ONE FILE HAS A COMMENT AND THE OTHER IS AT END OF LINE.
COMPL2: CAIE T,"; ;COMMENT IN FILE 1?
CAIN TT,"; ;OR IN FILE 2?
TLNN FR,FLCMNT ;AND ARE COMMENTS BEING IGNORED?
JRST POPJ1 ;NO, FILES DON'T MATCH, SKIP RETURN
JUMPE T,CPOPJ ;YES, OTHER CHAR MUST BE NULL OR ELSE ONE
JUMPE TT,CPOPJ ; LINE IS LONGER THAN OTHER AND FILES DIFFER
POPJ1: AOS (P)
APOPJ:
CPOPJ: RET
;WHEN WE GET TO THIS POINT WE HAVE FOUND
;THE EXTENT OF THE DIFFERENCES AND WE ARE READY TO PRINT
;THESE DIFFERENCES OUT. F1 AND F2 POINT AT THE TWO MATCHING LINES
;THAT END THE RUN OF DIFFERENCES.
PNTBTH: AOS ERRCNT ;INCREMENT # OF RUNS OF DIFFERENCES.
TLNE FR,FLISWT+FLFLAG
RET ;DON'T TYPE ON TTY IF /I OR /F.
IFN ITS,.SUSET [.SWHO2,,[SIXBIT/PRINT/]]
MOVEM P,FLUSHP ;SUPPLY P FOR --MORE--FLUSHED TO POPJ FROM.
TRZ FR,-1 ;OUTPUT FILE 1
CALL PNTTXT ;PRINT FILE 1 DIFFERENCES
HRRI FR,1 ;THEN PRINT FILE 2 DIFFERENCES
CALL PNTTXT
SETZM FLUSHP
RET
;OUTPUT THE LINES OF FILE (FR) BEFORE F1(FR), WITH A HEADER LINE.
;IF FLENDL=1, ALSO PRINTS THE LINE F1(FR) POINTS AT, IF ANY.
PNTTXT: CALL PNTHDL ;FIRST, THE HEADER LINE.
SKIPN NLINES(FR)
RET ;NO LINES => THAT'S ALL.
MOVE W1,LBUFP(FR)
SETZ W3,
SKIPE CS,F1(FR) ;CS GETS LINE TO STOP AT.
TLNN FR,FLENDL
CAIA
MOVE CS,LNNEXT(CS)
PNTTX1: CAME W1,CS ;REACHED 1ST LINE NOT TO OUTPUT => DONE.
CAML W3,LINMAX ;PRINTED MAX # OF LINES => STOP.
RET
TLNN FR,FLFNUM ;IF USER WANTS FILE # ON EVERY LINE,
JRST PNTTX2
SAVE W1
MOVEI W1,FNUMBR(FR) ;PRINT IT FOR HIM.
CALL PRINT
REST W1
PNTTX2: MOVEI W2,LNDATA(W1)
HRLI W2,440700
MOVE C,LNSIZE(W1)
CAML C,COLMAX ;IN /M MODE, LIMIT CHARS PRINTED TO COLMAX.
MOVE C,COLMAX
TLNN FR,FLMERG
MOVE C,LNSIZE(W1)
CALL PNTCNT ;OUTPUT THE TEXT OF THE LINE.
TLNN FR,FLALL ;IN /B MODE, THE CRLF IF ANY IS IN THE LINE.
CALL PCRLF ;OTHERWISE, MUST SUPPLY IT.
MOVE W1,LNNEXT(W1) ;MOVE TO NEXT LINE.
AOJA W3,PNTTX1 ;COUNT # LINES OUTPUT SO FAR.
FNUMBR: ASCIZ /1) / ;FILE NUMBER OF FILE, FOR PRINTING.
ASCIZ /2) /
IFN .-FNUMBR-2,.ERR STRING TOO LONG
;OUTPUT A CRLF TO THE DIFFERENCE FILE.
PCRLF: MOVE W2,[440700,,[.BYTE 7 ? ^M ? ^J]]
MOVEI C,2
PNTCNT: M.SOUT CHOUT,W2,C
RET
;OUTPUT A HEADER LINE TO THE DIFFERENCE FILE, FOR INPUT FILE (FR).
PNTHDL: MOVE W2,[440700,,[ASCIZ/**** FILE /]]
MOVEI C,10.
CALL PNTCNT
MOVE W1,RCHSTP(FR)
CALL PRINT ;PRINT THE ASCIZ STRING CONTAINING THE FILE'S NAMES.
MOVE W2,[440700,,[ASCIZ /, /]]
MOVEI C,2
CALL PNTCNT
MOVE W1,LBUFP(FR) ;GET THE PAGE # OF THE FIRST LINE FROM THE FILE.
SKIPN NLINES(FR)
SKIPA T,PAGNUM(FR) ;OR THE .IOT'ING PAGE # IF THERE AR NONE.
MOVE T,LNPGNM(W1)
CALL PNTDEC
MOUTI CHOUT,"-
SKIPN NLINES(FR) ;THEN THE LINE NUMBER
SKIPA T,LINNUM(FR)
MOVE T,LNLNNM(W1)
CALL PNTDEC
MOVEI W1,[ASCIZ/ (/] ;AND, IN PARENS, THE CHARACTER NUMBER.
CALL PRINT
MOVE W1,LBUFP(FR)
SKIPN NLINES(FR)
SKIPA T,CHRNUM(FR)
MOVE T,LNCHNM(W1)
CALL PNTDEC
MOUTI CHOUT,51 ; RIGHT PAREN (SCREWS MACRO)
TLNN FR,FLLABL\FLXLBL
JRST PCRLF
MOVE W1,LBUFP(FR) ;IF THE LAST LABEL IS KNOWN, PRINT IT TOO.
SKIPN NLINES(FR)
JRST [ MOVEI T,(FR)
IMULI T,LNLBLN
ADDI T,LLABEL
JRST PNTHD1]
MOVEI T,LNLLBL(W1)
PNTHD1: SKIPN (T)
JRST PCRLF
MOVEI W1,[ASCIZ / AFTER /]
SAVE T
CALL PRINT
REST W1
TLNE FR,FLXLBL
MOUTI CHOUT,""
SAVE LNLBLN(W1)
SETZM LNLBLN(W1) ;SUPPLY A ZERO TO END THE ASCIZ.
CALL PRINT
REST LNLBLN(W1)
TLNE FR,FLXLBL
MOUTI CHOUT,""
JRST PCRLF
; PNTHWD - Output number in T in halfword format.
PNTHWD: PUSH P,T
HLRZS T
CALL PNTOCT
MOVEI C,2
MOVE W2,[440700,,[ASCIZ /,,/]]
CALL PNTCNT
POP P,T
JRST PNTOCT
; Print number in T in octal to difference file
; Use RH only, pad to 6 positions.
PNTOCT: MOVE W2,[440700,,PNTDBF]
PUSH P,T
MOVE TT,[220300,,(P)]
MOVSI C,-6
PNTOC2: ILDB T,TT
JUMPN T,PNTOC3
MOVEI T,40
IDPB T,W2 ; PAD OUT WITH SPACES
AOBJN C,PNTOC2
MOVEI T,"0
DPB T,W2
JRST PNTOC5
PNTOC4: ILDB T,TT
PNTOC3: ADDI T,"0
IDPB T,W2
AOBJN C,PNTOC4
PNTOC5: MOVEI C,6
MOVE W2,[440700,,PNTDBF]
POP P,T
JRST PNTCNT
;PRINT NUMBER IN T IN DECIMAL TO DIFFERENCE FILE
PNTDEC: MOVE W2,[440700,,PNTDBF]
SETZ C,
CALL PNTDE1
MOVE W2,[440700,,PNTDBF]
JRST PNTCNT
PNTDE1: IDIVI T,10.
HRLM TT,(P)
SKIPE T
CALL PNTDE1
HLRZ TT,(P)
ADDI TT,"0
IDPB TT,W2
AOJA C,CPOPJ
;RH(W1) IS ADDR OF ASCIZ STRING; PRINT IT ON DIFFERENCE FILE.
PRINT: MOVEI W2,(W1)
HRLI W2,440700
SETZ C, ;FIRST COUNT CHARS IN THE STRING,
ILDB T,W2
SKIPE T
AOJA C,.-2
MOVEI W2,(W1) ;THEN OUTPUT THE STRING.
HRLI W2,440700
JRST PNTCNT
;ASSUMING THAT F1(FR) POINTS TO THE LAST LINE IN FILE (FR),
;READ ANOTHER LINE AND MAKE F1(FR) POINT AT IT.
;ALSO OK IS IF WE HAVE NO LINES FROM THAT FILE AND F1(FR) IS 0.
;SKIPS TWICE IF SUCCESSFUL. CAN FAIL AND NOT SKIP IF CAN'T GET A LINE
;BECAUSE OF EOF; WILL RETURN WITH F1(FR) UNCHANGED AND EOFFL1(FR) NONZERO.
;WE DON'T EXPLICITLY GET CORE - THE MPV INT HANDER DOES THAT.
;THE MPV INT HANDLER CHECKS THE PC - ANY INSN THAT CAN LEGITIMATELY GET AN MPV
;SHOULD HAVE A LABEL SUCH AS "MPVOK1" AND BE MADE KNOWN TO THE INT HANDLER.
RDLIN: TDNE FR,EOFTBL(FR) ;GIVE UP IF AT EOF IN FILE.
JRST [ SETOM EOFFL1(FR)
RET]
MOVE W1,LBUFP(FR) ;IF NO LINES IN CORE, NEXT LINE GOES AT START OF SEG.
SKIPN NLINES(FR)
JRST RDLIN0
SKIPN W1,F1(FR) ;ELSE, GET POINTER TO CURRENT LINE
ERRHLT
MOVE T,LNSIZE(W1) ;FIND WORD AFTER THE END OF IT
ADDI T,5
IDIVI T,5
ADDI W1,LNDATA(T) ;THAT WILL BE THE ADDRESS OF THE NEW LINE.
RDLIN0: SETZ W3, ;COUNT # OF CHARS WE SKIP IN T.
MOVE CS,@GCHARP(FR) ;SWAP THE FILE B.P. INTO AN AC FOR SPEED.
RDLIN1: ILDB C,CS
CAIG C,^M
XCT RDLT1(C) ;LOOP TILL 1ST CHAR OF NON-NULL LINE SEEN.
RDLIN4: ADDB W3,CHRNUM(FR) ;INITIALIZE THE LINE'S DATA,
MPVOK0: MOVEM W3,LNCHNM(W1) ;STORING THE LAST WORD FIRST TO MAKE SURE CORE EXISTS.
IFN LNDATA-LNCHNM-1,.ERR
TLNN FR,FLLABL\FLXLBL ;SAVE TIME IF LABEL FEATURE NOT IN USE.
JRST RDLIN5
MOVEI W3,LNLLBL(W1)
DPB FR,[240100,,W3] ;PUT 4*RH(FR) IN LH(W3)
ADD W3,[LLABEL,,] .SEE LNLBLN ;4 WORDS OF LABEL STRING.
BLT W3,LNLLB3(W1)
RDLIN5: MOVE W2,PAGNUM(FR)
MOVEM W2,LNPGNM(W1)
MOVE W2,LINNUM(FR)
MOVEM W2,LNLNNM(W1)
SETZM LNNEXT(W1)
MOVEI W2,LNDATA(W1)
HRLI W2,440700 ;THEN MAKE W2 A B.P. TO IDPB THE DATA AREA,
MOVE RDLIN7,[RDLIN6,,BP]
BLT RDLIN7,RDLIN7
TDZ W3,W3 ;AND COUNT CHARS STORED IN LINE IN W3.
JRST MPVOK1
RDLIN6: OFFSET BP-.
RDLIN2:: ILDB C,CS
MPVOK1:: XCT RDLT2(C) ;USUALLY IDPB C,W2, BUT MAY EXIT TO RDLIN3.
RDLIN7:: AOJA W3,RDLIN2
OFFSET 0
RDLIN3: AOS NLINES(FR) ;WHEN WE GET HERE, THE LINE REALLY EXISTS,
SKIPE F1(FR) ;SO PUT IT IN THE CHAIN
MOVEM W1,@F1(FR)
IFN LNNEXT,.ERR
MOVEM W1,F1(FR) ;AND POINT AT IT.
MOVEM W3,LNSIZE(W1) ;REMEMBER # CHARS IN THIS LINE.
ADDM W3,CHRNUM(FR) ;UPDATE CHAR POSITION IN FILE
MOVEM CS,@GCHARP(FR) ;STORE BACK THE FILE'S BUFFER B.P.
SETZB T,TT
MPVOK6: IDPB T,W2 ;STORE A TRAILING ZERO, THEN
LDB T,[360600,,W2] ;ZERO OUT REST OF LAST WORD.
DPB T,[301400,,W2]
DPB TT,W2
TLNE FR,FLXLBL ;IF ANY UNINDENTED NON-COMMENT LINE IS A LABEL
CALL LABEL ;GO SET UP LLABEL WITH THIS LINE'S LABEL IF IT HAS ONE.
AOS (P)
JRST POPJ1
;DISPATCH TABLE FOR FINDING A NON-NULL LINE.
RDLT1: JFCL
JFCL
JFCL
JRST RDLINC ;^C
REPEAT 6,JFCL
JRST RDLINJ ;^J
JFCL
JRST RDLINL ;^L
JRST RDLINM ;^M
IFN .-RDLT1-^M-1,.ERR WRONG LENGTH TABLE
;DISPATCH TABLE FOR ADDING MORE CHARS TO A LINE.
RDLT2: REPEAT 200,IDPB C,W2
LOC RDLT2+^C ? JRST RDLILC
LOC RDLT2+^J ? JRST RDLILJ
LOC RDLT2+^L ? JRST RDLILL
LOC RDLT2+^M ? JRST RDLILM
LOC RDLT2+": ? JRST RDLCLN
LOC RDLT2+200
;^J, ^L OR ^M WHEN LOOKING FOR START OF LINE:
;UPDATE PAGE OR LINE NUMBER, AND IGNORE CHAR UNLESS /B.
RDLINL: TLNE FR,FLALL
JRST RDLIN4
SETZM LINNUM(FR)
AOS PAGNUM(FR)
AOS LINNUM(FR)
IFN ITS,[
HRLZ T,PAGNUM+0
HRR T,PAGNUM+1
.SUSET [.SWHO3,,T]
]
AOJA W3,RDLIN1
RDLINJ: TLNE FR,FLALL
JRST RDLIN4
AOS LINNUM(FR)
AOJA W3,RDLIN1
RDLINM: TLNN FR,FLALL
AOJA W3,RDLIN1 ;NO /B; SKIP THE CHAR, BUT COUNT IT IN # THAT WERE SKIPPED.
JRST RDLIN4 ;/B, ANY CHAR STARTS A LINE.
;^J, ^L OR ^M WHEN ADDING TO A NON-NULL LINE:
;UPDATE PAGE OR LINE NUM, AND END THE LINE, STORING CHAR IFF /B.
RDLILL: SETZM LINNUM(FR)
AOS PAGNUM(FR)
IFN ITS,[
HRLZ T,PAGNUM+0
HRR T,PAGNUM+1
.SUSET [.SWHO3,,T]
]
RDLILJ: AOS LINNUM(FR)
TLNN FR,FLALL
JRST RDLIL1
MPVOK2: IDPB C,W2
AOJA W3,RDLIN3
RDLIL1: AOS CHRNUM(FR) ;NOT /B: MUST UPDATE # CHARS FROM FILE SINCE RDLIN3 WON'T.
JRST RDLIN3
RDLILM: TLNN FR,FLALL ;^M INSIDE A LINE.
JRST RDLIL1
MPVOK3: IDPB C,W2 ;IN /B MODE, STORE IT AND LOOK FOR FOLLOWING ^J.
RDLIL2: ILDB C,CS
CAIN C,^J
AOJA W3,RDLILJ ;FOUND => STORE IT TOO.
CAMN CS,GCHARE(FR) ;DON'T LOSE BECAUSE OF WRAPAROUND IN BUFFER.
JRST [ CALL RELOAD
JRST RDLIL2]
AOJ W3,
DBP7J CS,RDLIN3
;HANDLE COLON IN A LINE. IF /L, MAYBE SET THE FILE'S LLABEL VARIABLE.
RDLCLN: TLNN FR,FLLABL
JRST MPVOK4 ;COLON JUST GOES INTO LINE IF LABEL FEATURE OFF.
JUMPE W3,MPVOK4 ;COLON AT BEGINNING OF LINE ISN'T A LABEL.
MOVEI T,LNDATA(W1) ;MAKE SURE THERE ARE NO SPACES, TABS, COLONS OR SEMIS
HRLI T,440700 ;BEFORE THIS COLON.
RDLCL0: ILDB TT,T
CAIG TT,40
JRST MPVOK4
CAIE TT,":
CAIN TT,";
JRST MPVOK4 ;IT LOSES - IT'S JUST A NORMAL COLON.
CAME T,W2 ;SKIP IF IT WINS. MAKE IT THIS FILE'S LAST LABEL.
JRST RDLCL0
MPVOK5: MOVES LNDATA+1(W1) ;MAKE SURE AT LEAST 2 WORDS OF CORE EXIST
MPVOK7: MOVES 1(T) ;MAKE SURE THERE'S SPACE FOR THE COLON AND TRAILING 0.
MOVEI TT,":
IDPB TT,T ;STORE THE COLON IN THE LINE.
SETZ TT, ;STORE A ^@ AFTER THE COLON. IT WILL GET OVERWRITTEN
IDPB TT,T ;BY LINE'S NEXT CHAR, BUT WILL LIVE ON IN LLABEL.
HRRZ T,FR
LSH T,2
ADDI T,LLABEL-1 ;T GETS LLABEL-1, PLUS 4 TIMES FILE NUMBER.
PUSH T,LNDATA(W1) ;STORE 1ST 2 WORDS OF THIS LINE'S DATA THERE.
PUSH T,LNDATA+1(W1)
REPEAT LNLBLN-2,PUSH T,[0] ;2 WORDS ARE ENOUGH FOR A MIDAS LABEL, SO ZERO OUT THE REST.
JRST MPVOK4
;HERE IF /Y, AFTER READING IN THE LINE, TO SEE IF IT HAS A LABEL.
;A LINE HAS A LABEL IN /Y MODE IF IT STARTS WITH ANYTHING BUT A SPACE, TAB OR ;.
;W1 POINTS AT THE LINE.
LABEL: SKIPN W3,LNSIZE(W1)
RET ;IGNORE EMPTY LINES.
LDB T,[350700,,LNDATA(W1)] ;GET THE LINE'S FIRST CHARACTER.
CAILE T,40
JRST LABEL1 ;STARTS WITH NON-CONTROL NOT SPACE => PROBABLY A LABEL.
CAIN T,40
RET
CAIE T,^I
CAIN T,^L ;BUT LINES STARTING WITH FORMATTERS AREN'T.
RET
CAIE T,^M ;IN /B MODE A LINE CAN BE JUST ONE OF THESE. THEY AREN'T.
CAIN T,^J
RET
LABEL1: CAIN T,"; ;CHECK ; HERE - SAVES TIME FOR INDENTED LINES.
RET
HRRZ T,FR
IMULI T,LNLBLN
ADDI T,LLABEL-1 ;GET -1 + ADDR OF PLACE TO PUT LABEL.
MOVE TT,T ;SAVE THIS FOR LABEL2 WHICH ALSO NEEDS IT.
REPEAT LNLBLN,[
CAIL W3,.RPCNT*5+1 ;COPY START OF LINE INTO IT, BUT DON'T GO PAST END OF LINE
PUSH T,.RPCNT+LNDATA(W1) ;IF IT IS A SHORT ONE.
] ;NO NEED TO ZERO OUT REST OF WORDS CAUSE IF LINE IS SHORT
TLNN FR,FLALL ;THEN THE REAL DATA MUST HAVE A ^@ AFTER IT ANYWAY.
RET
MOVEI T,1(TT) ;IN /B MODE, THE LINE MAY HAVE A REAL ^M^J IN IT,
HRLI T,440700 ;AND IF IT IS SHORT THEN THE ^M^J WAS COPIED INTO THE LABEL.
MOVEI W3,5*LNLBLN ;SO REPLACE IT WITH A NULL, IN THE LABEL.
LABEL2: ILDB TT,T
JUMPE TT,CPOPJ ;LABEL ENDS WITH NULL AND HAS NO ^M OR ^J?
CAIE TT,^M
CAIN TT,^J
CAIA
SOJG W3,LABEL2 ;MAYBE WE EXHAUST THE WORDS OF LABEL AND THERE IS NONE.
JUMPE W3,CPOPJ
SETZ TT, ;IF THERE IS A ^M OR ^J, TRUNCATE LABEL AT THAT POINT.
DPB TT,T
RET
;HANDLE ^C WHEN LOOKING FOR START OF LINE.
RDLINC: CAMN CS,GCHARE(FR) ;IS THIS THE ^C AFTER THE BUFFER?
JRST [ CALL RELOAD ;YES, RELOAD THE BUFFER AND TRY AGAIN.
JRST RDLIN1]
CAME CS,@GCHARZ(FR) ;IS THIS EOF, OR A ^C IN THE FILE?
JRST RDLIN4 ;^C IN FILE STARTS A LINE.
IOR FR,EOFTBL(FR) ;IT IS EOF.
RDLIL5: SETOM EOFFL1(FR)
MOVEM CS,@GCHARP(FR)
RET
;HANDLE ^C WHEN ADDING TO A LINE.
RDLILC: CAMN CS,GCHARE(FR)
JRST [ CALL RELOAD
JRST RDLIN2]
CAME CS,@GCHARZ(FR) ;^C IN FILE GOES IN THE LINE.
JRST MPVOK4
IOR FR,EOFTBL(FR) ;EOF IN MIDDLE OF LINE: SAY EOF WAS REACHED.
MOVEI T,LNDATA-1(W1)
RDLIL4: CAIN T,(W2) ;FLUSH ALL ^C'S AND ^@'S OFF THE END OF THE LINE.
JRST RDLIL5 ;LINE WAS NOTHING BUT ^C'S AND ^@'S? SAY THERE WAS NO LINE.
LDB C,W2
CAIE C,^C
JUMPN C,RDLIN3 ;LINE HAS SOMETHING ELSE, SO RETURN IT.
SOJ W3,
DBP7J W2,RDLIL4
MPVOK4: IDPB C,W2 ;COME HERE TO INSERT A ^C OR : IN A LINE,
AOJA W3,RDLIN2 ;WITHOUT THE SPECIAL HANDLING THEY SOMETIMES GET.
; RDWRD - Read a word from file. This is completely independent of
; RDLIN and RELOAD.
; Returns .+1 if EOF
; Returns .+2 otherwise,
; W1/ word
RDWRD: SOSGE GWORDC(FR) ; Decrement total cnt for file
JRST [ SETOM EOFFL1(FR) ; Hit EOF.
SETOM GWORDB(FR)
SETZM GWORDC(FR) ; Keep this normalized.
RET]
AOSE W1,GWORDB(FR) ; Skip for initial loadup
CAMLE W1,GWORDE(FR)
JRST RDWRD2 ; Load up the buffer.
MOVE W1,(W1)
AOS (P)
RET
RDWRD2: MOVEI CS,FILBFL
MOVE C,GWORDI(FR)
HRRZM C,GWORDB(FR)
CALL @GCHARX(FR) ; Read another bufferful
MOVE W1,@GWORDB(FR) ; Get 1st wd of buffer
AOS (P)
RET
GWORDL: BLOCK 3 ; # words length of file
GWORDC: BLOCK 3 ; # words left in file
GWORDB: -1 ? -1 ? -1
GWORDI: 444400,,FILBF1
444400,,FILBF2
444400,,FILBF3
GWORDE: FILBE1 ? FILBE2 ? FILBE3
; RUDWRD - Read a word from inferior process.
; This is completely independent of RDLIN and RELOAD.
; Returns .+1 if EOF
; Returns .+2 otherwise,
; W1/ word
RDUWRD: SOSGE GWORDC(FR) ; Decrement total cnt for file
JRST [ SETOM EOFFL1(FR) ; Hit EOF.
SETOM GWORDB(FR)
SETZM GWORDC(FR) ; Keep this normalized.
RET]
AOSE W1,GWORDB(FR) ; Skip for initial loadup
CAMLE W1,GWORDE(FR)
JRST RDUWD2 ; Load up the buffer.
MOVE W1,(W1)
AOS (P)
RET
RDUWD2: MOVEI CS,FILBFL
MOVE C,GWORDI(FR)
HRRZM C,GWORDB(FR)
CALL RDUBUF
MOVE W1,@GWORDB(FR) ; Get 1st wd of buffer
AOS (P)
RET
RDUBUF:
IFN ITS,[
M.SIN CHUIN1(FR),C,CS
RET
] ;IFN ITS
IFN TNX,[
TYPE "Error - TNX version doesn't have /$ feature yet
"
HALT
] ;IFN TNX
;REFILL THE BUFFER OF THE FILE (FR). WORKS WHETHER READING IN CHAR
;OR WORD MODE, ON BOTH ITS AND TNX (WHICH UPDATE BP'S DIFFERENTLY).
RELOAD: MOVE C,GCHARI(FR) ;YES, JUST REFILL THE BUFFER. GET BP
MOVEI CS,FILBFL ;AND COUNT
CALL @GCHARX(FR) ;INPUT THE STUFF
TLZ C,7700
TLO C,0700 ;MAKE BP A CHAR B.P. (IF NOT ALREADY)
MOVEI CS,^C
IDPB CS,C ;PUT A ^C AFTER WHAT WE INPUT.
MOVEM C,@GCHARZ(FR) ;AND SAVE BP TO EOF CHAR.
MOVE CS,GCHARB(FR) ;RE-INIT THE B.P.
RET
GCHARP: FILPT1 ;ADDRESS OF BUFFER BP OF FILE.
FILPT2
FILPT3
GCHARZ: FILEP1 ;ADDR OF B.P. TO THE ^C AFTER WHAT WAS READ IN.
FILEP2
FILEP3
GCHARI: 444400,,FILBF1 ; BP TO IDPB 1ST WD OF BUFFER.
444400,,FILBF2
444400,,FILBF3
GCHARB: 440700,,FILBF1 ;B.P. TO ILDB 1ST CHAR OF BUFFER.
440700,,FILBF2
440700,,FILBF3
GCHARE: 350700,,FILBE1+1 ;B.P. TO ^C AFTER END OF BUFFER.
350700,,FILBE2+1
350700,,FILBE3+1
GCHARX: [M.SIN CHIN1,C,CS ;INSTRS TO INPUT ON CHIN1
RET]
[M.SIN CHIN2,C,CS ;DITTO FOR CHIN2
RET]
[M.SIN CHIN3,C,CS
RET]
EOFTBL: FLEOF1,, ;EOF FLAG FOR FILE 1
FLEOF2,, ;EOF FLAG FOR FILE 2
FLEOF3,,
RCHSTP: 440700,,HBUF1 ;BYTE POINTERS TO HEADER TABLES
440700,,HBUF2
440700,,HBUF3
; INT HANDLER, ITS ONLY - HANDLES MPV AND --MORE-- INTERRUPTS.
; TNX DOESN'T NEED MPV HANDLER (ALTHO IT MAKES ERRORS HARDER TO FIND)
; AND DOESN'T HAVE --MORE-- INTERRUPTS...
IFN ITS,[
TSINT:
LOC 42 ? JSR TSINT ? LOC TSINT ; ENSURE INT VECTOR SET UP
0
0
EXCH W1,TSINT
JUMPL W1,MORINT
CAIE W1,%PIMPV
ERRHLT
HRRZ W1,TSINT+1 ;MPV INTERRUPTS TO GET MORE CORE ARE LEGAL
CAIE W1,MPVOK7 ;ONLY FROM CERTAIN SPOTS.
CAIN W1,MPVOK6
JRST TSINT2
CAIE W1,MPVOK5
CAIN W1,MPVOK4
JRST TSINT2
CAIE W1,MPVOK3
CAIN W1,MPVOK2
JRST TSINT2
CAIE W1,MPVOK1
CAIN W1,MPVOK0
CAIA
ERRHLT
TSINT2: .SUSET [.RMPVA,,W1]
LSH W1,-10.
SYSCAL CORBLK,[MOVEI 400000 ? MOVEI -1 ? W1 ? MOVEI 400001]
JRST [ CALL TYLERR ? JRST ERRFIN]
MOVE W1,TSINT
.DISMI TSINT+1
MORINT: MOVE W1,TSINT
INSIRP PUSH P,C T
MOVEI T,[ASCIZ /--MORE--/]
CALL TYPMS0
SYSCAL IOT,[MOVEI CHTTI ? MOVE C ? 5000,,%TIPEK]
.LOSE 1000
CAIN C,^C
JRST MORKIL
CAIE C,40
CAIN C,177
.IOT CHTTI,C ;SPACE OR RUBOUT IS GOBBLED.
SKIPE FLUSHP
CAIN C,40 ;IF IT ISN'T SPACE, AND WE CAN FLUSH, DO SO.
JRST MORPRC
MOVEI T,[ASCIZ /FLUSHED
/]
CALL TYPMS0
MOVE P,FLUSHP
SETZM FLUSHP
.DISMI [CPOPJ]
MORKIL: .IOT CHTTI,C ;^C => GOBBLE IT AND KILL THE SRCCOM.
.LOGOUT
.BREAK 16,160000
MORPRC: MOVEI T,[ASCIZ /
/]
CALL TYPMS0
INSIRP POP P,T C
.DISMI TSINT+1
] ;IFN ITS
;OPEN INPUT FILE ON CHNL IN W1.
INOPEN: MOVEI FP,INFB
HRLI FP,(W1) ;MAKE <CH>,,<FB ADDR>
IFN ITS,[
MOVSI W2,(SIXBIT/>/)
SKIPN $F6FN2(FP) ;DEFAULT THE FN2 TO ">".
MOVEM W2,$F6FN2(FP)
]
MOVEI W2,OPNRDA ;USE UNIT MODE FOR /X FILES,
TLNN FR,FLXCTF
MOVEI W2,OPNRDW ;USE BLOCK MODE FOR OTHER INPUT FILES.
CALL (W2)
CALL OPENL ; LOST?? REPORT ERROR.
MOVE W2,INOPT3-CHIN1(W1) ;GET ADDR OF LAST WORD OF BUFFER.
MOVEI W1,(W2)
HRLI W1,10700 ;MAKE B.P. TO END OF BUFFER,
MOVEM W1,FILPT1-FILBE1(W2)
MOVE W1,[ASCIC//]
MOVEM W1,1(W2)
HRRI FR,0 ;PUT NUMBER OF FILE INTO FR.
CAIE W2,FILBE1
HRRI FR,1
PJRST RCHST ;SET UP FILE'S HEADER.
INOPT3: FILBE1
FILBE2
FILBE3
;COME HERE WHEN /@ IS SPECIFIED FOR THE 1ST INPUT FILE.
;THAT MEANS TO TREAT THE SPECIFIED 1ST INPUT FILE AS A COMPARISON
;FILE, EXTRACT THE NAME OF THE SECOND FILE USED IN THAT COMPARISON,
;AND USE THAT FILE AS OUR 1ST INPUT FILE THIS TIME.
;JUMPS BACK TO THE COMMAND PROCESSING LEVEL TO OPEN THE REAL 1ST INPUT FILE.
RFINDR: MOVE W1,GCHARI
MOVEI W2,FILBFL
M.SIN CHIN1,W1,W2 ;READ IN SOME OF THE FILE.
ADDI W1,1
ANDI W1,-1 ;MAKE SURE IT LOOKS LIKE A COMPARISON FILE.
CAIGE W1,FILBF1+10.
JRST ERRIND
MOVE W1,FILBF1
MOVE W2,FILBF1+1
CAMN W1,[ASCII /
;CO/]
CAME W2,[ASCII /MPARI/]
JRST ERRIND
MOVE W1,FILBF1+2
CAME W1,[ASCII /SON O/]
JRST ERRIND
MOVE W1,[350700,,FILBF1+3] ;POINT AT THE SPACE AFTER THE "OF".
MOVEI W2,4
RFIND2: ILDB C,W1 ;THEN SKIP PAST 3 SPACES, TO BE AFTER THE "AND".
CAIE C,40
JRST RFIND2
SOJG W2,RFIND2
SAVE TTIPNT ;WHICH IS JUST AT THE SECOND COMPARED FILE'S NAME.
SAVE TTICNT
HRLZM P,TTICNT
MOVEM W1,TTIPNT ;READ IN THAT FILE NAME
CALL RFILE ;RFILE RETURNS AFTER THE FN2 SINCE FLINDR=1.
ILDB C,TTIPNT
CAIE C,^J
JRST .-2 ;PASS THE LINEFEED OF THAT LINE
MOVEI C,3
ADDM C,TTIPNT ;SKIP THE ";OPTIONS ARE "
CALL RFILSW ;READ THE SWITCHES FROM THE COMPARISON FILE
REST TTICNT
REST TTIPNT
TLZ FR,FLINDR
JRST RFIND1
IFN ITS,[
;PUT FILE DESCRIPTION IN ASCII INTO HBUF FOR THIS FILE
RCHST: SYSCAL RFNAME,[ MOVEI CHIN1(FR)
2000,,RCHSTB
2000,,RCHSTB+1
2000,,RCHSTB+2
2000,,RCHSTB+3]
.LOSE 1000
SYSCAL FILLEN,[MOVEI CHIN1(FR) ? MOVEM W2]
.LOSE 1000
MOVEM W2,GWORDL(FR) ; Set length of file
MOVEM W2,GWORDC(FR) ; Also # of words left to read
MOVE W2,RCHSTP(FR) ;NOW SET UP BYTE POINTER TO HEADER AREA TO READ INTO
MOVE T,RCHSTB ;GET THE CHOSEN DEVICE NAME
JSP W1,RCHST6 ;DEVICE NAME
": ;END WITH COLON
MOVE T,RCHSTB+3
JSP W1,RCHST6 ;SYSTEM NAME
"; ;TERMINATED BY SEMICOLON
SKIPN T,RCHSTB+1
MOVE T,INFB+$FNAME ;IF REALLY NONE, USE SPEC'D.
SKIPN LSTFB+$FNAME ;DEFAULT OUTPUT FN1 TO INPUT.
MOVEM T,LSTFB+$FNAME
JSP W1,RCHST6 ;FNAM1
40 ;TERMINATED (ITS CONVENTION) BY SPACE
SKIPN T,RCHSTB+2
MOVE T,INFB+$FEXT
JSP W1,RCHST6 ;FNAM2
0 ;DON'T PRINT TERMINATING CHAR
MOVEI C,0
IDPB C,W2 ;MARK END OF STRING
SKIPN FSBIN ; If hacking inferior process addr space, skip
RET ; else return, done.
SKIPN UNQNAM
.SUSET [.RJNAME,,UNQNAM]
AOS UNQNAM
MOVEI T,CHUO1(FR)
HRLI T,.UIO
SYSCAL OPEN,[T ? ['USR,,] ? [0] ? UNQNAM]
.LOSE 1000
MOVEI T,CHUIN1(FR)
HRLI T,.UII
SYSCAL OPEN,[T ? ['USR,,] ? [0] ? UNQNAM]
.LOSE 1000
SYSCAL LOAD,[MOVEI (T) ? MOVEI CHIN1(FR)]
.LOSE 1000
SYSCAL ACCESS,[MOVEI (T) ? [0]]
.LOSE 1000
SYSCAL USRVAR,[MOVEI (T) ? [SIXBIT /MEMT/] ? MOVEM W2]
.LOSE 1000
MOVEM W2,GWORDL(FR)
MOVEM W2,GWORDC(FR)
RET
.SCALAR UNQNAM
;JSP W1,RCHST6 ;PRINT (IDPB ASCII VIA W2) SIXBIT WORD IN T
; "<TERMINATING CHAR OR 0> ;FOLLOW WITH TERMINATING CHAR UNLESS SIXBIT IS NULL
; ^ DOESN'T PRINT TRAILING SPACES
RCHST6: JUMPE T,1(W1) ;RETURN ON NULL ARG
RCHS6A: MOVEI C,0 ;CLEAR OUT C TO RECEIVE CHAR
LSHC C,6 ;SHIFT IN NEXT CHAR
ADDI C,40 ;CONVERT TO ASCII
IDPB C,W2 ;DEPOSIT WHEREVER IT'S GOING
JUMPN T,RCHS6A ;LOOP UNTIL WORD EMPTY
SKIPE C,(W1) ;NOW GET TERMINATOR
IDPB C,W2 ;NOT NULL, USE IT
JRST 1(W1)
] ;IFN ITS
;READ IN A COMMAND, PROCESSING RUBOUTS, PROMPTING WITH "#".
CMDLIN: SKIPE CMDFIL
JRST TTIFIL ;IF IN COMMAND FILE, READ FROM IT INSTEAD OF TTY.
TTILIN: HRROS (P) ;PROMPT WITH "#".
JRST TTILI1
TTILNA: HRRZS (P) ;FOR /M INPUT, PROMPT WITH "*"
JRST TTILI1
;READ A CHAR OF TTY INPUT (OR ^M IF NONE LEFT).
TTICHR: SOSGE TTICNT ;IF NO CHARS LEFT,
SKIPA C,[^M] ;SAY EOL.
ILDB C,TTIPNT ;ELSE GET NEXT CHAR FROM BUFFER.
RET
;READ AND UPCASE A CHAR OF INPUT.
TTICHU: CALL TTICHR ;GET CHAR
CAIL C,"A+40 ;SKIP IF LESS THAN LOWER CASE A
CAILE C,"Z+40 ;SKIP IF IN RANGE A-Z
CAIA ;SKIP IF NOT A-Z (LC)
SUBI C,40 ;LOWER CASE TO UPPER CASE
RET
IFN ITS,[
RUBOUT"A=1
RUBOUT"B=2
RUBOUT"C=3
RUBOUT"D=4
RUBOUT"$$PROMPT==1
.INSRT SYSENG;RUBOUT
RUBOUT"INCHR:
.IOT CHTTI,RUBOUT"A
RET
RUBOUT"OUTCHR:
SYSCAL IOT,[%CLIMM,,CHTTO ? RUBOUT"A ? %CLBIT,,%TJMOR]
.LOSE %LSFIL
RET
RUBOUT"DISPLAY:
SYSCAL IOT,[%CLIMM,,CHTTO ? RUBOUT"A ? %CLBIT,,%TJMOR+%TJDIS]
.LOSE %LSFIL
RET
RUBOUT"PROMPT:
MOVEI RUBOUT"A,"#
SKIPL PRMNUM
MOVEI RUBOUT"A,"*
JRST RUBOUT"OUTCHR
RUBOUT"DISPATCH:
CAIN RUBOUT"A,%TXCTL+"Q ;MAKE ^Q NOT SPECIAL FOR RUBOUT PROCESSING.
JRST RUBOUT"INSECH ;THAT IS, IT WON'T QUOTE A RUBOUT.
CAIN RUBOUT"A,%TXCTL+"M ;^M SHOULD JUST INSERT A ^M, NOT ^M^J
JRST RUBOUT"BRKINS
JRST RUBOUT"RB$DSP
.SCALAR PRMNUM ;NEGATIVE => PROMPT WITH #. POS OR ZERO => PROMPT WITH *.
.VECTOR RBBLK(RUBOUT"RB.LEN) ;RUBOUT PROCESSOR ARGUMENT BLOCK.
;READ A LINE BY CALLING THE RUBOUT PACKAGE. ASSUMES LH OF (P) NEGATIVE => PROMPT WITH #.
TTILI1: CALL CRLF
MOVE W1,(P)
MOVEM W1,PRMNUM
TTILI9: CALL RUBOUT"PROMPT
MOVE W1,[010700,,TTIBUF-1]
MOVEM W1,TTIPNT ;SET UP FOR FETCHING CHARS LATER.
MOVEM W1,RBBLK+RUBOUT"RB.BEG
ADDI W1,TTIBFL
MOVEM W1,RBBLK+RUBOUT"RB.END
MOVEI RUBOUT"A,CHTTO
MOVEI RUBOUT"B,RBBLK
CALL RUBOUT"INIT
TTILI8: CALL RUBOUT"READ ;READ CHARACTERS UP TO BREAK CHAR.
CAMN RUBOUT"A,[-1]
JRST [ .IOT CHTTO,[^G] ;BUFFER FULL: DING, AND LET USER RUB OUT SOME.
JRST TTILI8]
JUMPL RUBOUT"A,TTILI1 ;OVER-RUBOUT => CRLF AND TRY AGAIN.
MOVEI W2,0
DPB W2,RBBLK+RUBOUT"RB.PTR ;REPLACE BREAK CHAR WITH 0.
CAIN RUBOUT"A,%TXCTL+"M
JRST TTILI4
CALL CRLF ;IF BREAK WASN'T A CR, TYPE A CR,
TLNN FR,FLMERG ;AND IF READING A COMMAND, REMEMBER TO RETURN TO DDT
SETOM CTLCF ;AFTER EXECUTING IT.
TTILI4: MOVE W1,TTIPNT ;COUNT THE CHARACTERS WE GOT. SET UP TTICNT.
SETZM TTICNT
TTILI2: CAMN W1,RBBLK+RUBOUT"RB.PTR
JRST TTILI3
IBP W1
AOS TTICNT
JRST TTILI2
TTILI3: SOSE TTICNT ;DON'T COUNT THE TERMINAL 0 IN TTICNT.
RET ;RETURN IF LINE IS NON NULL.
SKIPL (P) ;IF IT ISN'T A COMMAND, RETURN IT EVEN THOUGH NULL.
RET
SKIPGE CTLCF ;NULL COMMAND LINE ENDED BY ^C MEANS EXIT.
JRST QUIT
JRST TTILI9 ;OTHERWISE READ ANOTHER COMMAND LINE.
]
IFN TNX,[
TTILI1: CALL CRLF
TTILI2: SKIPE FLG20X ;ON A 20?
JRST TTIL20 ;YES
;COME HERE AFTER NULL LINE.
SETZM TTICNT ;NO CHARS READ YET.
SKIPGE (P)
MOUTI CHTTO,"#
SKIPL (P)
MOUTI CHTTO,"*
MOVE C,[440700,,TTIBUF]
MOVEM C,TTIPNT
TTILUP: CALL TYI ;READ A CHAR FROM TTY.
CAIN C,^M
JRST TTICR ;^M MEANS ALL READ.
CAIE C,^D
CAIN C,^U
JRST TTILI1 ;^U CANCELS CMD.
CAIN C,177
JRST TTIRUB
CAIN C,^L ;IF USER TYPES ^L, RETYPE THE BUFFERED INPUT.
JRST TTICTL
CAIE C,^Z
CAIN C,^C
JRST TTICTC ;^C MEANS DO CMD, THEN VALRET :KILL.
IDPB C,TTIPNT ;NORMAL CHAR.
AOS TTICNT
JRST TTILUP
TTICTC: CALL CRLF ;INDICATE COMMAND HAS BEEN TERMINATED.
TLNN FR,FLMERG ;^C DOES NOTHING IF INPUT TO MERGE.
SETOM CTLCF ;REMEMBER TO VALRET WHEN CMD DONE.
;HERE AFTER ORDINARY LINE TERMINATOR.
TTICR: SKIPL (P)
JRST TTICR1
SKIPN TTICNT ;IF NULL COMMAND LINE, RETRY.
JRST TTILI3
TTICR1: SETZ C,
IDPB C,TTIPNT ; TERMINATE WITH ASCIZ
MOVE C,[440700,,TTIBUF]
MOVEM C,TTIPNT ;SET UP FOR REMOVAL OF CHARS.
RET
TTILI3: SKIPE CTLCF ;NULL LINE:
JRST QUIT ;...IF ^C ENDED LINE.
JRST TTILI2
TTICTL: MOVEI T,[ASCIZ /#/] ;COME HERE FOR ^L. SCREEN ALREADY CLEARED ON DISPLAY.
SKIPL (P)
MOVEI T,[ASCIZ /*/]
CALL TYPMSG ;PRINT CRLF AND ASTERISK.
MOVE TT,[440700,,TTIBUF]
MOVE C,TTICNT ;THEN RETYPE THE BUFFERED INPUT.
M.SOUT CHTTO,TT,C
JRST TTILUP
TTIRUB: SOSGE TTICNT ;IF NO CHAR TO RUB, RETRY.
JRST TTILI1
LDB C,TTIPNT
MOUTC CHTTO,C ;PRINT RUBBED CHAR.
MOVSI C,070000
ADD C,TTIPNT
JUMPGE C,TTIRU1 ;IF STILL IN SAME WD.
MOVEI C,-1(C ) ;ELSE, MOVE TO END OF PREV. WD.
HRLI C,010700
TTIRU1: MOVEM C,TTIPNT
JRST TTILUP
;USE SYSTEM ROUTINES ON A 20
TTIL20: HRROI R3,[ASCIZ /#/] ;PROMPTING TEXT
SKIPL (P)
HRROI R3,[ASCIZ /*/]
MOVE R1,R3 ;HAVE TO OUTPUT PROMPT BY HAND, SIGH
PSOUT
HRROI R1,TTIBUF
MOVE R2,[RD%TOP+5*TTIBFL]
RDTTY
JRST RESTRT
TLZ R2,-1 ;FIGURE COUNT
SUBI R2,5*TTIBFL
LDB C,R1
CAIE C,^J
JRST TTIL21
MOVNI R3,1
ADJBP R3,R1
LDB C,R3
CAIE C,^M
JRST TTIL21
MOVE R1,R3
ADDI R2,1
TTIL21: MOVNI R3,1
ADJBP R3,R1
MOVEM R3,TTIPNT
SETCAM R2,TTICNT ; TTICNT := -R2-1
CAIE C,^Z
JRST TTICR
JRST TTICTC
] ;IFN TNX
;COME HERE TO SEE IF THE COMMAND STRING IS JUST "?" OR "HELP".
;IF NOT, RETURNS. IF SO, PRINTS HELP (FROM INFO;SRCCOM >)
;AND RETURNS TO RELDEV.
TRYHLP: SAVE TTIPNT
SAVE TTICNT
CALL TTINSP ;GO PAST INITIAL SPACES.
CAIN C,"?
JRST TRYHL1 ;"?" MIGHT BE START OF GOOD STUFF
CAIE C,"H ;SO MIGHT "H".
JRST TRYHLL ;ANYTHING ELSE => USER ISN'T ASKING FOR HELP.
CALL TTICHU
CAIE C,"E
JRST TRYHLL
CALL TTICHU
CAIE C,"L
JRST TRYHLL
CALL TTICHU
CAIE C,"P
JRST TRYHLL
TRYHL1: CALL TTINSP
CAIE C,^M
CAIN C,^C
CAIA
JRST TRYHLL
;USER WANTS HELP - GIVE IT TO HIM.
CALL OPNHLP
JRST ERRHLP
TRYHL3: M.BIN CHIN1,C
CAIN C,^L
JRST RELDEV
JUMPL C,RELDEV
MOUTC CHTTO,C
JRST TRYHL3
TRYHLL: REST TTICNT
REST TTIPNT
RET
;READ 1 CHAR FROM THE COMMAND STRING, THEN KEEP READING TILL READ A NON-SPACE.
;CONVERTS TO UPPER CASE.
TTINSP: CALL TTICHU
CAIN C,40
JRST TTINSP
RET
;COME HERE TO HANDLE A COMMAND WITH /X IN IT.
CMDXCT: SKIPE CMDFIL
JRST ERRXCT ;/X INSIDE AN EXECUTE FILE??
SKIPLE TTICNT ;ANY EXTRA FILES SPECIFIED?
JRST ERRXTRA
M.MVCH CHIN1,CHCMD ;MAKE THE ALREADY OPEN 1ST INPUT FILE BE OUR COMMAND FILE.
MOVE W1,INFB+$FDIR
MOVEM W1,CMDIS ;MAKE INPUT DEV AND SNAME THE INPUT DEFAULTS
MOVE W1,INFB+$FDEV
MOVEM W1,CMDID
MOVE W1,LSTFB+$FDIR
MOVEM W1,CMDOS ;AND OUR OUTPUT DEV AND SNAME THE OUTPUT DEFAULTS
MOVE W1,LSTFB+$FDEV
CAMN W1,FSTTY
MOVE W1,FSDSK
MOVEM W1,CMDOD
SETOM CMDFIL ;SAY WE ARE NOW EXECUTING A COMMAND FILE.
JRST RELDEV ;GO READ THE NEXT COMMAND.
;COME HERE TO READ A COMMAND LINE FROM A COMMAND FILE.
TTIFIL: SETZM TTICNT ;INITIALIZE THE COMMAND BUFFER EMPTY.
MOVE BP,[440700,,TTIBUF]
MOVEM BP,TTIPNT
;NOW SEE IF THERE ARE ANY MORE COMMANDS IN THE FILE.
TTIFI0: M.BIN CHCMD,C
TTIFI1: ANDI C,-1
CAIE C,^C ;EOF OR END OF 1ST PAGE => COMMAND FILE IS OVER.
CAIN C,^L
JRST TTIEOF
CAIE C,"; ;ELSE, A COMAND LINE IS IDENTIFIED BY
JRST TTIFI0 ;STARTING WITH ";;SRCCOM COMMAND ;;"
IRPC X,,[;SRCCOM COMMAND ;;]
M.BIN CHCMD,C
CAIE C,"X
JRST TTIFI1
TERMIN
;WE FOUND ANOTHER COMMAND LINE'S BEGINNING.
;NOW, EVERYTHING UP TO NEXT ^C, ^L, ^M OR ";;" IS PART OF THE COMMAND.
TDZA W1,W1
TTIFI2: MOVE W1,C ;REMEMBER THE PREVIOUS CHAR FOR FINDING ";;".
M.BIN CHCMD,C
ANDI C,-1
CAIE C,^C
CAIN C,^M
JRST TTIFI3
CAIN C,^L ;STOP BEFORE A ^C, ^L OR ^M.
JRST TTIFI3
CAIN C,"; ;BEFORE THE SECOND ";" OF A ";;",
CAIE W1,";
AOSA TTICNT
JRST TTIFI4 ;MUST STOP, AND FLUSH THE PREVIOUS ";".
IDPB C,BP ;ELSE STORE THE CHAR AND COUNT IT.
JRST TTIFI2
TTIFI4: SOS TTICNT
DBP7J BP,
TTIFI3: SETZ C, ;NOW WE HAVE READ IN A WHOLE LINE.
IDPB C,BP ;SO MAKE IT ASCIZ
MOVEI T,TTIBUF ;AND TYPE IT ON THE TTY SO USER CAN MONITOR PROGRESS.
CALL TYPMS0
JRST CRLF
TTIEOF: M.CLS CHCMD ;HERE AT END OF COMMAND FILE.
SETZM CMDFIL ;STOP TRYING TO USE IT, AND COMMIT SUICIDE IF A ^C
SKIPE CTLCF ;IS STILL LEFT FROM WHEN IT WAS SPECIFIED.
JRST QUIT
JRST TTILIN ;ELSE, READ FROM TTY.
SUBTTL ITS - FILESPEC READER
;READ FILE SPEC.
IFN ITS,[
RFILE: SETZM $F6FN2(FP) ;DEFAULT FN2 UP TO CALLER.
RFILSW: SETZ CS,
RFNAME: MOVE BP,[440600,,0]
MOVEI 0,6 ;SET UP TO READ IN A FILENAME.
MOVEM 0,RFILC
SETZ 0,
RFLOOP: CALL TTICHU ;READ A CHAR. UPPER CASE
CAIN C,^Q
JRST RFCTQ ;^Q QUOTES NEXT CHAR.
CAIE C,"=
CAIN C,",
JRST RFSPAC ;COMMAS TERMINATE SPEC.
CAIE C,"_
CAIG C,"
JRST RFSPAC ;THESE ALSO.
CAIN C,":
JRST RFCOL ;COLON SETS DEV.
CAIN C,";
JRST RFSEM ;SEMI SETS SNAME.
CAIN C,"/
JRST RFSPAC ;SLASH ENDS NAME.
JRST RFNORM ;ALL OTHER CHARS.
RFCTQ: CALL TTICHU ;READ UPPER CASE CHAR
CAIGE C,40
JRST RFSPAC ;DON'T TRY TO QUOTE A CONTROL CHARACTER.
RFNORM: MOVEI C,-40(C) ;CONV. TO SIXBIT.
SOSL RFILC ;PUT IN NAME IF ROOM LEFT.
IDPB C,BP
JRST RFLOOP
RFXCTB: MOVEM 0,$F6FN1(FP)
MOVEM 0,$F6FN2(FP)
MOVEM 0,$F6DEV(FP)
MOVEM 0,$F6DIR(FP)
SKIPA
RFCOL: SKIPE 0
MOVEM 0,$F6DEV(FP) ;SET DEVICE FIELD.
JRST RFNAME
RFSEM: SKIPE 0
MOVEM 0,$F6DIR(FP)
JRST RFNAME
RFSPAC: JUMPE 0,RFSPA0 ;IF NAME WAS READ,
XCT RFXCTB(CS) ;STORE IT,
AOJ CS, ;INCR. STORING POS.
TLNN FR,FLINDR
JRST RFSPA0
CAIN CS,2
RET
RFSPA0: CAIN C,^X ;AS 1ST NAME AVOIDS SETTING IT, ALLOWS FN2 TO BE SET.
JRST [ JUMPN CS,RFNAME
AOJA CS,RFNAME]
CAIN C,40
JRST RFNAME ;SPACE -- GET ANOTHER NAME.
CAIN C,^C
MOVEI C,^M
CAIE C,"/
RET ;NOT SLASH, RETURN.
CALL RDSW ; AHA, READ SWITCH.
JRST RFNAME ; THEN RETURN TO LOOP.
] ;IFN ITS
SUBTTL TNX - FILESPEC READER
IFN TNX,[
RFILE: SETZM $FVERS(FP) ; DEFAULT VERSION UP TO CALLER
RFILSW: SETZM RDFLG ; SAY HAVEN'T READ FILESPEC YET.
RFILE2: CALL TTICHR ; READ CHAR FROM LINE
CAIE C,^J
CAIN C,^M ; EOL?
JRST RFILE8 ; YES, EXIT
CAIE C,^C
CAIN C,0
JRST RFILE8
CAIN C,", ; COMMA?
JRST RFILE8 ; ALSO EXIT
IFE TWX,CAIE C,"_ ; Not on Twenex, thank you
CAIN C,"= ; EITHER OF THESE ARE VALID OUTPUT FILSPEC INDICATORS.
JRST RFILE8
CAIN C,"/ ; START OF SWITCH?
JRST [ CALL RDSW ; YES, READ IT & CONTINUE.
JRST RFILE2]
CAIE C,^I
CAIN C,40
JRST RFILE2 ; FLUSH WHITESPACE
; HERE HAVE FIRST CHAR OF FILENAME...
MOVE W2,[440700,,RFLBUF]
RFILE3: IDPB C,W2
CALL TTICHR ;ACCUMULATE CHARACTERS VALID IN FILE NAME
CAIE C,^J
CAIN C,^M
JRST RFILE4
CAIE C,^C
CAIN C,0
JRST RFILE4
CAIE C,",
CAIN C,"/
JRST RFILE4
IFE TWX,CAIE C,"_ ; Not on Twenex, thank you
CAIN C,"=
JRST RFILE4
CAIE C,^I
CAIN C,40
JRST RFILE4
CAIE C,^V
JRST RFILE3
IDPB C,W2
CALL TTICHR
JRST RFILE3
RFILE4: MOVEI A,0 ;MARK END OF ASCIZ STRING
IDPB A,W2
MOVE W2,TTIPNT
DBP7J W2, ; SKIP BACK ONE
MOVEM W2,TTIPNT
AOS TTICNT
RFILE5: SKIPE RDFLG ; ALREADY READ A FILESPEC?
JRST RFILE8 ; YES, DON'T READ THIS SPEC YET...
HRROI W2,RFLBUF
SYSCAL GTJFN,[[GJ%OFG+GJ%SHT] ? W2][$FJFN(FP) ? W2]
JRST RFILE9 ; SOME SORT OF SYNTAX ERROR
;HERE COULD COMPARE W2 AGAINST TTIPNT IN CASE EXTRA GARBAGE IN FILENAME
CALL JFNSTB ; STORE FILENAME SPEC IN FB
SYSCAL RLJFN,[$FJFN(FP)]
JFCL
SETZM $FJFN(FP)
; FILESPEC READ...
SETOM RDFLG ; SAY SO, SO IF SEE ANOTHER WILL STOP
JRST RFILE2
RFILE8: RET ; RETURN
RFILE9: HRROI W1,RFLBUF
PSOUT
MOUTI CHTTO,^I
CALL TYLERR ;TYPE LAST ERROR
JRST ERRFIN
.SCALAR RDFLG ; -1 WHEN FILESPEC READ
.VECTOR RFLBUF(20.) ;BUFFER FOR READING FILENAME INTO FOR GTJFN
] ;IFN TNX
SUBTTL SWITCH PROCESSING
;FOR SWITCH "A, SET OR CLEAR BIT D ACCORDING TO B.
DEFINE SWITCH A,B,D
CAIN C,"A
HRR!B!I BP,D
TERMIN
RDSW: CALL TTICHU ; READ A SWITCH (SHOULD BE NEXT CHAR).
SETZ BP,
SWITCH !,O,FLOVRD ;/! - FORCE COMPARISON BETWEEN A FILE AND ITSELF
SWITCH @,O,FLINDR ;/@ - GO INDIRECT THROUGH A COMPARISON FILE
;TO FIND THE FILE NAMES TO USE.
CAIN C,"# ;/# - Binary compare (= FILCOM /W)
JRST [ SETOM FVBIN ; Set memory flag (sigh)
RET]
CAIN C,"$ ;/$ - SBLK or CSAVE compare
JRST [ SETOM FSBIN
RET]
CAIN C,"Q ;/Q - Like FILCOM /Q, gives error
JRST [ SETOM QFLAG ; if files are different
RET] ; (for BATCON, mostly)
SWITCH B,O,FLALL ;/B - DON'T IGNORE BLANK LINES.
SWITCH C,O,FLCMNT ;/C - IGNORE COMMENTS.
CAIN C,"D
PJRST SWDISN ;/D - DISOWN SELF.
SWITCH E,O,FLENDL ;/E - PRINT THE MATCHING LINES THAT END THE
;RUN OF DIFFERENCES.
SWITCH F,O,FLFLAG+FLALL+FLMERG ;/F - GEN COPY OF FILE 2 WITH CHANGED LINES
;FLAGGED WITH VERTICAL BARS.
SWITCH I,O,FLMERG+FLISWT+FLALL ;/I - /M, BUT ANSWER ALL QUESTIONS WITH "I".
SWITCH K,O,FLCASE ;/K - IGNORE ALPHABETIC CASE DIFFERENCES
SWITCH L,O,FLLABL ;/L - EACH HEADER LINE MENTIONS PREVIOUS LABEL.
SWITCH M,O,FLALL+FLMERG ;/M - MERGE FILES.
SWITCH S,O,FLSPAC ;/S - IGNORE SPACES.
SWITCH W,O,FLFNUM ;/W - PRINT FILE # ON EACH LINE.
SWITCH X,O,FLXCTF ;/X - EXECUTE COMMANDS FROM FILE
SWITCH Y,O,FLXLBL ;/Y - ANY UNINDENTED TEXT IS A LABEL.
CAIL C,"1 ;DIGIT - SET NUMLIN.
CAILE C,"9
CAIA
JRST [MOVEI C,-"1(C) ;SET NUM. EXTRA LINES TO MATCH
MOVEM C,NUMLIN ;TO THE DIGIT, -1.
RET]
JUMPE BP,ERRSW ;ERROR UNLESS ONE OF ABOVE SWITCHES.
TLO FR,(BP) ;SET THE FLG.
RET ;SWITCH DONE, RETURN.
SUBTTL ERROR MESSAGES/HANDLING
;COME HERE AFTER FAILING INPUT OR OUTPUT OPEN.
OPENL:
IFN ITS,.LOGOUT
CALL LSTFIL ;PRINT NAME OF LOSING FILE (WHAT FP POINTS TO).
MOUTI CHTTO,^I
CALL TYLERR ;TYPE LAST ERROR
JRST ERRFIN
ERRXTR: JSP T,ERRMSG
ASCIZ "Extra input files specified"
ERRHLP: MOVEI T,[ASCIZ "Can't find help file!"]
CALL TYPMSG
; JRST OPENL
JRST ERRFIN
ERRIND: JSP T,ERRMSG
ASCIZ "Bad format /@ indirect file"
ERRIN2: JSP T,ERRMSG
ASCIZ "Can't use /@ or /X with second input file"
ERRIN3: JSP T,ERRMSG
ASCIZ "Can't use /@ or /X with third input file"
ERR3NM: JSP T,ERRMSG
ASCIZ "Three input files but /M not specified"
ERRXCT: JSP T,ERRMSG
ASCIZ "Recursive /X attempted"
ERRARC: JSP T,ERRMSG
ASCIZ "Can't archive and merge at once"
ERRSW: JSP T,ERRMSG
ASCIZ "Illegal switch"
ERRMSG: CALL TYPMSG ;FOR SIMPLE ERROR MESSAGES; TYPE & DROP THRU
;ALL ERROR MESSAGES COME THROUGH HERE.
ERRFIN:
IFN ITS,.RESET CHTTI, ; FLUSH TTY INPUT BUFFER
IFN TNX,CFIBF
SETZM CMDFIL ;STOP READING COMMAND FILE.
M.CLS CHCMD
SETZM CTLCF ;DON'T KILL SELF; READ ANOTHER CMD STRING INSTEAD.
;COMMAND TERMINATION, SUCCESSFUL OR NOT, ALWAYS COMES THROUGH HERE.
RELDEV: M.CLS CHIN1
M.CLS CHIN2
M.CLS CHMRG
IFN ITS,[
MOVE W1,TTYSTS
TLNE W1,%TSMOR
SYSCAL TTYSET,[MOVEI CHOUT ? TTYST1 ? TTYST2 ? W1]
JFCL
]
M.CLS CHOUT
SKIPE CMDFIL ;EXECUTING A FILE => READ MORE FROM IT.
JRST RELDE1
IFN ITS,.LOGOUT ;CAN'T GET ANOTHER CMD IF DISOWNED.
SKIPE CTLCF ;EXIT IF USER GAVE ^C.
JRST QUITX
RELDE1: CALL CRLF
JRST RESTRT ;ELSE, GET NEW CMD.
;ROUTINES FOR OUTPUTING ERROR MESSAGES
TYPMSG:
IFN ITS,.LOGOUT ;CAN'T PRINT MSG WITHOUT TTY.
CALL CRLF ;OUTPUT A CARRIAGE RETURN
TYPMS0: HRLI T,440700 ;THIS IS POINTER FOR ERROR MESSAGE
TYPMS1: ILDB C,T
JUMPE C,CPOPJ
CALL TYO
JRST TYPMS1
; TYPM - FOR USE WITH "TYPE" MACRO. STACK HAS ADDR OF ASCIZ STR.
TYPM: PUSH P,C
PUSH P,T
MOVE T,-2(P) ; GET ADDR OF ASCIZ
CALL TYPMSG ; OUTPUT
POP P,T
POP P,C
SUB P,[1,,1] ; FLUSH ARG
RET
;OUTPUT 6BIT WD IN 0 TO TTY.
TTOSIX: MOVE BP,0
TTOSI0: SETZ TT,
ROTC TT,6 ;GET NEXT CHAR.
MOVEI TT," (TT) ;CONV. 6BIT TO ASCII.
MOUTC CHTTO,TT
JUMPN BP,TTOSI0
RET
; OUTPUT DECIMAL # IN 0 TO TTY.
TTODEC: IDIVI 0,10.
HRLM W1,(P)
SKIPE 0
CALL TTODEC
HLRZ W1,(P)
ADDI W1,"0
MOUTC CHTTO,W1
RET
TYO: MOUTC CHTTO,C
RET
CRLF: MOUTI CHTTO,^M
MOUTI CHTTO,^J
RET
SUBTTL Auxiliary ITS Routines
IFN ITS,[
; GETJCL - Get JCL input
; W1/ <.OPTION var>
GETJCL: SETZM TTIBUF
TLNE W1,OPTCMD ; Don't do the .BREAK unless superior says so.
.BREAK 12,[5,,TTIBUF]
SKIPN TTIBUF
RET
MOVE W1,[440700,,TTIBUF] ; If have command string from superior,
MOVEM W1,TTIPNT ; set up to read from it.
SETZ CS,
GTJCL2: ILDB C,W1 ; Count chars. in it.
CAIE C,^M
CAIN C,0
CAIA
AOJA CS,GTJCL2
MOVEM CS,TTICNT ; Save num. chars to read.
AOS (P) ; Success return.
RET
; TYLERR - Type last error
TYLERR: .SUSET [.RBCHN,,C]
SYSCAL STATUS,[C ? MOVEM ERRFIL+2]
ERRHLT
.OPEN CHERR,ERRFIL
ERRHLT
TYLER2: M.BIN CHERR,C
CAIN C,^M
RET
MOUTC CHTTO,C
JRST TYLER2
ERRFIL: SIXBIT/ ERR/
3 ? 0
; LSTFIL - Print name of current file on LST ior TTY.
LSTFIL: MOVE 0,$F6DEV(FP)
CAMN 0,FSDSK
JRST LSTFI1
CALL TTOSIX ; Print dev if not DSK.
MOUTI CHTTO,":
LSTFI1: MOVE 0,$F6DIR(FP) ; Print sname
CAMN 0,DEFDIR ; If different from user's.
JRST LSTFI2
CALL TTOSIX
MOUTI CHTTO,73 ; ";
LSTFI2: MOVE 0,$F6FN1(FP)
CALL TTOSIX ; Print 1st name.
MOUTI CHTTO,40 ; Space
MOVE 0,$F6FN2(FP)
JRST TTOSIX ; , 2nd name.
SWDISN: .OPEN CHTTI,[SIXBIT/ NUL/]
ERRHLT
.OPEN CHTTO,[SIXBIT/ !NUL/]
ERRHLT
.VALUE [ASCIZ/:DISOWN :VK /] ; Give back tty.
RET
; TYI - Read char from TTY, return in C
TYI: .IOT CHTTI,C
RET
; OPNRDW - Open filblk for reading, word mode
; OPNRDA - Open filblk for reading, ascii mode
; FP/ <ch>,,<fb addr>
; Skip returns if opened.
OPNRDW: SAVE W1
HRLZI W1,.UII
JRST OPNRD2
OPNRDA: SAVE W1
HRLZI W1,.UAI ; Actually 0
OPNRD2: HLR W1,FP
SYSCAL OPEN,[W1 ? $F6DEV(FP) ? $F6FN1(FP) ? $F6FN2(FP) ? $F6DIR(FP)]
CAIA
AOS -1(P)
REST W1
RET
; RENMLO - Rename listing file
; W1/ <ch>
RENMLO: SYSCAL RENMWO,[W1 ? LSTFB+$FNAME ? LSTFB+$FEXT]
JFCL
RET
QUIT: .BREAK 16,140000 ; Die and echo ":KILL"
QUITX: .BREAK 16,160000 ; Die, announce "Finished" if not current
OPNHLP: SYSCAL OPEN,[MOVEI CHIN1 ? ['DSK,,]
['SRCCOM] ? [SIXBIT/>/] ? [SIXBIT/INFO/]]
RET
AOS (P)
RET
] ;IFN ITS
SUBTTL TNX - Auxiliary Routines
IFN TNX,[
; SEE20X - See if running under 20x or 10x
.SCALAR FLG20X ; -1 if 20x, 0 if 10x.
SEE20X: SETZM FLG20X
SYSCAL SYSGT,[['LOADTB]][B ? B]
SKIPN B ; If LOADTB is not defined
SETOM FLG20X ; It must be a twenex
RET
QUIT:
QUITX:
; Tell an MIT EXEC to flush this fork, like .BREAK 16,160000 on ITS
; This PRARG% code should be meaningless to (and ignored by) non-MIT EXECs.
IFDEF PRARG%,{ ; I don't know if PRARG% exists on 10X or not
IFNDEF .PRKIL, .PRKIL==:2
MOVE 1,[.PRAST,,.FHSLF]
MOVEI 2,[.PRKIL,,0]
MOVEI 3,1
PRARG% ; Tell the EXEC that we have a death wish
ERJMP .+1 ; Oh well
};IFNDEF PRARG%
HALTF
JRST RESTRT
; OPNWR - Open filblk for writing, ascii mode
; FP/ <ch>,,<fb addr>
OPNWR: SAVE W1
SAVE W2
MOVE W2,[070000,,OF%WR] ; Mode for char write
CALL GETJFO ; Get output jfn
JRST OPNRD8
JRST OPNRD5 ; Rest is same as OPNRD.
; OPNRDW - Open filblk for reading, word mode
; OPNRDA - Open filblk for reading, ascii mode
; FP/ <ch>,,<fb addr>
; Skip returns if opened.
OPNRDW: SAVE W1
SAVE W2
MOVE W2,[440000,,OF%RD] ; Mode for full-wd
JRST OPNRD2
OPNRDA: SAVE W1
SAVE W2
MOVE W2,[070000,,OF%RD] ; Mode for char
OPNRD2: CALL GETJFI ; Get input jfn
JRST OPNRD8 ; Failed
OPNRD5: SYSCAL OPENF,[$FJFN(FP) ? W2]
JRST [ SYSCAL CLOSF,[$FJFN(FP)]
JFCL
JRST OPNRD8]
PUSH P,$FJFN(FP)
HLRZ W1,FP
POP P,JFNCHS(W1)
CALL JFNSTB
AOS -2(P)
OPNRD8: REST W2
REST W1
RET
OPNHLP: PUSH P,R1
PUSH P,R2
MOVSI R1,(GJ%OLD+GJ%SHT)
HRROI R2,[HLPFIL] ; Filename defined as macro
GTJFN
JRST OPNHL7 ; Failed.
HRRZS R1
PUSH P,R1
MOVE B,[070000,,OF%RD]
OPENF
JRST [ POP P,R1
CLOSF
JFCL
JRST OPNHL7]
POP P,R1
MOVEM R1,JFNCHS+CHIN1
AOS -2(P)
OPNHL7: POP P,R2
POP P,R1
POPJ P,
; RENMLO - Rename listing file
; For moment, we don't hack temp filename, so this is a no-op.
RENMLO: RET
TYI: SAVE R1
TYI2: PBIN
CAIN R1,37
MOVEI R1,^M
CAIN R1,^J ; Actually for 20x only
JRST TYI2
MOVE C,R1
REST R1
RET
SWDISN: TYPE "Cannot disown on this losing system; continuing."
RET
LSTFIL: PJRST TYPFB
; TYLERR - Type last error
TYLERR: SKIPA A,[-1]
TERSTR: MOVE A,ERRCOD
HRLI A,.FHSLF
SYSCAL ERSTR,[[-1,,ERSTRB] ? A ? [-LERSTR,,]][A ? B ? B]
JRST TERST7 ; undefined err #?
HALT ; destination bad?
SETZ B,
IDPB B,A ; Ensure ASCIZ.
MOVEI T,ERSTRB
PJRST TYPMSG
; TYPR ERSTRB
; POPJ P,
TERST7: TYPE "Unknown error"
POPJ P,
LERSTR==80.
.VECTOR ERSTRB(<LERSTR+4>/5)
; RCHST - Set up filename string of input file as part of header output.
; Also set length vars.
RCHST: MOVEI A,CHIN1(FR) ; What a crock.
MOVE A,JFNCHS(A) ; Get jfn for file
PUSH P,A
MOVE B,RCHSTP(FR) ; Get bp to dest buffer
SYSCAL JFNS,[B ? A ? [111110,,1]][B]
SETZ A,
IDPB A,B ; Ensure asciz
POP P,A ; Get JFN again
SYSCAL SFPTR,[A ? [-1]][A] ; Set pointer to EOF
JFCL
SYSCAL RFPTR,[A][A ? B] ; Get # words to read
JFCL
MOVEM B,GWORDL(FR) ; Set length of file
MOVEM B,GWORDC(FR) ; Also # of words left to read
SYSCAL SFPTR,[A ? [0]] ; Point back to beg of file
JFCL
RET
] ;IFN TNX
SUBTTL TNX JCL reading
; This routine is taken from MIDAS and so has some CCL hackery that
; currently is commented out, but at some future time might prove useful.
IFN TNX,[
; GETJCL - Read "JCL" - RSCAN buffer or nnnMID.TMP file (from CCL)
GETJCL: SETZM TTIPNT
IFN 0,[
SKIPE CCLFLG ; Started at CCL location?
JRST JCLIN5 ; Yep, go snarf stuff specially.
]
SKIPN FLG20X ; Is this Tenex?
JRST [ MOVEI R1,.PRIIN ; Yes
BKJFN ; see what previous character was
RET ; *Gasp*
PBIN
CAIE R1,^_ ; Tenex newline?
SETOM TTIPNT ; No, set flag saying "TTY but no prompt"
RET] ; and skip the Twenex hackery below
SETZ R1, ; If not, check RSCAN.
RSCAN ; See if have anything in RSCAN buffer.
RET ; Huh? Shouldn't happen, but ignore it.
JUMPLE R1,APOPJ ; Also return if char cnt says nothing there.
MOVNI R3,(R1) ; Aha, set up cnt for SIN
HRROI R2,TTIBUF
MOVEI R1,.PRIIN ; Now ready for business...
SIN
LDB R1,R2 ; Now examine wages thereof
CAIE R1,^J ; Last char LF?
JRST [ MOVEI R1,^J
IDPB R1,R2 ; If not, make it so.
JRST .+1]
;;; Don't try to change the terminating character from LF to CR without
;;; giving it careful thought. GTJFN likes the filename to be terminated
;;; with LF, and can be quite intransigent in its behavior.
;;; Instead, make the other scan routines accept LF. --WBA
SETZ R1,
IDPB R1,R2 ; Must also ensure ASCIZ.
MOVE B,[440700,,TTIBUF] ; If the rescan line starts with "RUN ", skip that.
IRPC X,,[RUN ]
ILDB A,B
TRZ A,40 ; Convert to upper case
CAIE A,"X
JRST JCLIN4
TERMIN
CAIA
JCLIN4: MOVE B,[440700,,TTIBUF] ; Now flush the name of the file we were run from.
ILDB A,B
CAILE A,40
JRST .-2 ; Flush until random ctl seen (space, ^M)
CAIE A,40 ; If it wasn't a space,
RET ; then forget about the whole thing.
JCLIN3: MOVE C,B ; Now flush spaces. Save last ptr for chars.
ILDB A,B
CAIN A,40
JRST JCLIN3
CAIN A,^J ; And is first non-space something besides LF?
RET ; Bah, there wasn't anything in the JCL!!
MOVEM C,TTIPNT ; Else save ptr to start of real goods.
MOVE W1,C
SETZ CS,
GTJCL2: ILDB C,W1 ; Count chars. in it.
JUMPE C,GTJCL3 ; Null? (Shouldn't happen, but...)
CAIE C,^M ; CR or LF?
CAIN C,^J
CAIA ; Yes, must convert to null
AOJA CS,GTJCL2 ; Otherwise just count it
SETZ C,
DPB C,W1
GTJCL3: MOVEM CS,TTICNT ; Save num. chars to read.
AOS (P) ; Success return.
RET
IFN 0,[
; TNX snarf of CCL file. No such thing as tmpcor, so just
; look for real file with appropriate name.
JCLIN5: SETZM CCLFLG ; Want 0 in case abort out, will reset if win.
GJINF ; Get job # in R3
HRROI R1,CMBUF ; Use CMBUF to form filename string.
MOVEI R2,(R3)
MOVE R3,[NO%LFL+NO%ZRO+<3_18.>+10.]
NOUT ; ship out job num in 3 digits, radix 10.
HALT
HRROI R2,[ASCIZ /MID.TMP/]
SETZ R3,
SOUT ; Flesh out rest of filename string.
SETZ R2, ; Make sure it's ASCIZ.
BOUT
MOVE R1,[GJ%OLD+GJ%SHT] ; Use short-form GTJFN
HRROI R2,CMBUF ; and gobble name from CMBUF.
GTJFN
RET ; If failed, forget it.
MOVE R2,[070000,,OF%RD] ; Read 7-bit bytes
OPENF
RET ; Bah
HRROI R2,CMBUF ; Gobble stuff up.
MOVEI R3,CMBFL*5 ; Read until buffer full,
MOVEI R4,^J ; or LF seen.
SIN
JUMPLE R3,APOPJ ; Forget it if too big for buffer!!
MOVE R2,[440700,,CMBUF] ; Aha, we've got something, so set
MOVEM R2,CMPTR ; pointer to slurped stuff.
SETOM CCLFLG
HRROI R2,UTIBUF ; Slurp rest into larger buffer,
MOVNI R3,UTIBFL*5 ; using count only.
SIN
JUMPGE R3,APOPJ ; Refuse to hack grossly large file.
ADDI R3,UTIBFL*5
JUMPLE R3,APOPJ ; if nothing read, need write nothing out.
HRLI R1,(CO%NRJ) ; Don't release JFN,
CLOSF ; but stop reading from file.
RET
MOVE R2,[070000,,OF%WR] ; Now try to hack write access.
OPENF
RET
MOVE R2,R1 ; Source becomes destination...
HRROI R1,UTIBUF ; and UTIBUF becomes source,
MOVNS R3 ; for just as many bytes as were read.
SOUT
MOVEI R1,(R2) ; done, now just close file.
CLOSF ; (this time, release JFN).
RET
SETOM CCLMOR ; say that more CCL remains.
RET
] ;IFN 0 FOR NOW
] ;IFN TNX
SUBTTL TENEX misc. Filename Routines, FS string storage
IFN TNX,[ .SEE FSDSK ; Part of this page is NOT conditionalized!!
; To handle filenames of ASCIZ strings instead of SIXBIT words, each
; word has instead a byte pointer to an ASCIZ string. For purposes of
; easy comparison, all of these bp's point into FNBUF, and a routine
; (FNCHK) is provided which checks a just-stored string and returns a bp
; to either this string, if unique, or to a previously stored string if
; it is the same as the one just stored (which is then flushed). Thus
; strings can be compared for equality simply by a comparison of their
; byte pointers. While not necessary, strings are stored beginning on
; word boundaries for easier hacking.
; <# files>*<avg # strings/file>*<avg # words/string>+<# wds for constants>
IFNDEF MAXIND,MAXIND==10 ; # files
LFNBUF==<MAXIND+5>*5*3+20 ; Enough to hold strings for all output files,
; all translated files, and all .insrt files encountered.
; Later a GC'er can be hacked up so that of the latter only
; enough for the max .insrt level need be allocated.
FNBUF: BLOCK LFNBUF
; Macro to easily define constant strings for comparison purposes
DEFINE DEFSTR &STR&
440700,,%%FNLC
%%LSAV==.
LOC %%FNLC
ASCIZ STR
%%FNLC==.
LOC %%LSAV
TERMIN
%%FNLC==FNBUF
] ; IFN TNX!!!
; If not assembling for TENEX, the following strings become
; simple SIXBIT values. This makes it possible to write simple
; code to work for both TENEX and non-TENEX without messy conditionals.
IFE TNX,[
DEFINE DEFSTR &X&
.1STWD SIXBIT X!TERMIN
]
; This stuff defines various BP's into FNBUF to
; use for comparison purposes later.
FSDSK: DEFSTR /DSK/
FSTTY: DEFSTR /TTY/
FSNUL: DEFSTR /NUL/
FSCMP: DEFSTR /COMPARE/
FSCMPA: DEFSTR /CMPARC/
FSFLGD: DEFSTR /FLAGGD/
IFN ITS, FSDMF2:DEFSTR />/ ; default merge FN2
IFN TNX, FSDMF2:DEFSTR //
IFN ITS, FVLOW: DEFSTR /</
IFN TNX, FVLOW: .GJLEG ; -2 for lowest version
IFN TNX,[
FNBBP: 440700,,FNBUF ; Points to beg of FNBUF (hook for dynamic alloc)
FNBEP: FNBUF+LFNBUF-1 ; Points to last wd in FNBUF (address, not BP)
FNBWP: 440700,,%%FNLC ; Write Pointer into FNBUF.
FNBLWP: 440700,,%%FNLC ; Last Write Pointer, points to beg of string being stored
EXPUNG %%FNLC
; NOTE - provided MIDAS never restarts, no initialization is necessary to
; start using FNCHK. (Unless of course FNBUF is dynamically allocated someday)
; FNCHK - Check out just-stored filename. Returns BP in A to ASCIZ string,
; which will be "canonical" for comparison purposes.
; Clobbers A,B,T,TT,AA
; FNCHKZ - Makes sure just-writ string is ASCIZ'd out before FNCHK'ing.
FNCHKZ: MOVE B,FNBWP ; Get write ptr,
LDB A,B ; see if last char was 0,
JUMPE A,FNCHK0 ; if so can skip one clobberage.
SETZ A,
IDPB A,B ; zero out bytes,
FNCHK0: TLNE B,760000 ; until at end of word.
JRST .-2
ADD B,[<440700,,1>-<010700,,>] ; bump BP to point canonically at next.
MOVEM B,FNBWP
FNCHK: HRRZ B,FNBWP ; See if write ptr
CAML B,FNBEP ; has hit end of FNBUF, and
ETF [ASCIZ /Filename buffer overflow/] ; barf horribly if so.
MOVE A,FNBBP ; A - bp to start of existing string
MOVE AA,FNBLWP ; AA - bp to start of new string to store
FNCHK2: MOVEI T,(A) ; T - current addr being checked, existing str
MOVEI TT,(AA) ; TT - current addr, new str
CAIL T,(TT) ; If addrs are same, or overran somehow,
JRST [ MOVE A,AA ; didn't find any match, accept new string.
MOVE B,FNBWP
MOVEM B,FNBLWP ; Set up new last-write-ptr
POPJ P,]
FNCHK3: MOVE B,(T)
CAMN B,(TT) ; Compare strings, full word swoops.
JRST [ TRNE B,377 ; equal, last char zero?
AOJA T,[AOJA TT,FNCHK3] ; no, continue for whole string
; Found it! Flush just-stored string, don't want duplicate.
MOVEM AA,FNBWP ; Clobber write ptr to previous value.
POPJ P,]
; Not equal, move to next string to compare
MOVEI B,377 ; Check for ASCIZ,
TDNE B,(T) ; moving to end of current string
AOJA T,.-1
HRRI A,1(T) ; and updating BP to point at new string.
JRST FNCHK2 ; (T gets pointed there too at FNCHK2).
] ;IFN TNX
IFN TNX,[
; TYPFB - Type out FB pointed to by F
TYPFB: SKIPE B,$FDEV(F) ; First, device name?
JRST [ PUSHJ P,TYPZ
MOVEI A,":
PUSHJ P,TYOERR
JRST .+1]
SKIPE B,$FDIR(F) ; Directory?
JRST [ MOVEI A,"<
PUSHJ P,TYOERR
PUSHJ P,TYPZ
MOVEI A,">
PUSHJ P,TYOERR
JRST .+1]
SKIPE B,$FNAME(F)
PUSHJ P,TYPZ
MOVEI A,".
PUSHJ P,TYOERR
SKIPE B,$FEXT(F)
PUSHJ P,TYPZ
MOVEI A,". ; 20X uses "." to set off version,
SKIPN FLG20X ; but 10X uses ";".
MOVEI A,";
PUSHJ P,TYOERR
HRRE A,$FVERS(F)
JUMPL A,[MOVM B,A ; Is possible to have -1, -2, etc.
MOVEI A,"-
PUSHJ P,TYOERR
MOVE A,B
JRST .+1]
PUSHJ P,DPNT ; Version # output in decimal.
SKIPE $FTEMP(F)
TYPE ";T" ; May be temporary.
SKIPE B,$FPROT(F)
JRST [ TYPE ";P"
PUSHJ P,TYPZ
JRST .+1]
SKIPE B,$FACCT(F)
JRST [ TYPE ";A"
PUSHJ P,TYPZ
JRST .+1]
POPJ P,
; Takes BP in B, outputs to TYOERR until zero byte seen.
TYPZ: CAIA
PUSHJ P,TYOERR
ILDB A,B
JUMPN A,TYPZ+1
POPJ P,
DPNT: MOVE 0,A ; This entry pt for code borrowed from midas
PJRST TTODEC
TYOERR: MOVE C,A ; Ditto.
PJRST TYO
] ; IFN TNX
IFN TNX,[
; JFNSTR - Get filename strings for active JFN.
; A/ active JFN
; F/ addr of filename block to clobber.
; JFNSTB - Same, but ignores A and assumes JFN is already stored in block.
; Clobbers A,C
JFNSTB: SKIPA A,$FJFN(F) ; JFNSTB gets the JFN from block itself.
JFNSTR: MOVEM A,$FJFN(F) ; whereas JFNSTR stores it there...
MOVSI D,-NJSTRF ; Set up aobjn thru table.
JFNST2: PUSH P,T
SYSCAL JFNS,[FNBWP ? $FJFN(F) ? JSTRFX+1(D)][FNBWP]
POP P,T
MOVE C,JSTRFX(D) ; Now get index to place it belongs in file block,
CAIN C,$FVERS ; and check for this, because
JRST [ MOVE A,FNBLWP ; it wants to be a number, not a string.
MOVEM A,FNBWP ; Zap write pointer back to forget string,
PUSHJ P,CVSDEC ; and quickly convert before anything clobbers it.
JRST JFNST4] ; Skip over the FNCHKZ call.
MOVE A,FNBLWP ; Get previous write ptr
CAMN A,FNBWP ; and compare to make sure something written.
TDZA A,A ; If nothing, store zero.
PUSHJ P,FNCHKZ ; Fix up string, and get BP to it.
JFNST4: ADDI C,(F) ; make it an addr, and
MOVEM A,(C) ; store BP. (or value, for $FVERS)
ADDI D,1
AOBJN D,JFNST2
POPJ P,
; Filblk idx, output format wd for JFNS call
JSTRFX: $FDEV ? 100000,,
$FDIR ? 010000,,
$FNAME ? 001000,,
$FEXT ? 000100,,
$FVERS ? 000010,,
NJSTRF==<.-JSTRFX>/2
; CVSDEC - Converts ASCIZ string to decimal, assumes only digits seen, with
; a possible minus-sign prefix (ie negative # is allowed).
; A/ BP to ASCIZ
; Returns value in A, clobbers nothing else.
CVSDEC: PUSH P,B
PUSH P,C
MOVE C,A
SETZ A,
ILDB B,C ; Get 1st char
JUMPE B,CVSDC9
CAIN B,"- ; Minus sign?
JRST [ MOVE A,C ; Yes, parse rest of number
PUSHJ P,CVSDEC
MOVNS A ; and negate result.
JRST CVSDC9]
CVSDC2: IMULI A,10.
ADDI A,-"0(B)
ILDB B,C
JUMPN B,CVSDC2
CVSDC9: POP P,C
POP P,B
POPJ P,
; CVSSIX - Converts ASCIZ string to SIXBIT word.
; A/ BP to ASCIZ string,
; Returns SIXBIT word in A. Clobbers nothing else.
CVSSIX: PUSH P,B
PUSH P,C
PUSH P,D
MOVE D,A
SETZ A,
MOVE B,[440600,,A]
JRST CVSSX3
CVSSX2: CAIL C,140
SUBI C,40 ; Uppercase force
SUBI C,40 ; cvt to 6bit
IDPB C,B ; deposit
TLNN B,770000 ; If BP at end of word,
JRST CVSSX5 ; leave loop.
CVSSX3: ILDB C,D
JUMPN C,CVSSX2
CVSSX5: POP P,D
POP P,C
POP P,B
POPJ P,
] ; IFN TNX
IFN TNX,[
; Get a JFN for current FILBLK (in F) and stick it into $FJFN(F).
; A should hold flags in LH to use in 1st wd of block.
; GETJFI - sets usual flags for input
; GETJFO - sets " " output
; GETJFN - takes whatever A holds.
GETJFO: SKIPA A,[GJ%FOU+GJ%NEW] ; If hacking output, ask for new version.
GETJFI: MOVSI A,(GJ%OLD) ; If hacking input, file must exist.
GETJFN: PUSHJ P,TFMAP ; Stick filblk stuff into GTJFN scratch block.
PUSH P,R1
PUSH P,R2
MOVEI R1,GTJBLK
SETZ R2,
GTJFN
JRST [ MOVEM R1,ERRCOD ; failure, save error code.
JRST GETJF5]
HRRM R1,$FJFN(F) ; Win, save JFN.
AOS -2(P)
GETJF5: POP P,R2 ; Can't return in ACs cuz don't know what R1 etc are,
POP P,R1 ; and might clobber them here.
POPJ P,
.SCALAR ERRCOD
; TFMAP - Map Tenex filenames from filblk pointed to by F into
; standard scratch block for long-form GTJFN.
; A/ <flags>,,0 ; flags will go into LH of .GJGEN.
; Clobbers only A.
TFMAP: HRR A,$FVERS(F) ; Put version # in RH
SKIPE $FTEMP(F) ; If asking for temp file,
TLO A,(GJ%TMP) ; set appropriate flag.
MOVEM A,GTJBLK+.GJGEN
IRP FROM,,[$FDEV,$FDIR,$FNAME,$FEXT,$FPROT,$FACCT,$FJFN]TO,,[.GJDEV,.GJDIR,.GJNAM,.GJEXT,.GJPRO,.GJACT,.GJJFN]
MOVE A,FROM(F)
MOVEM A,GTJBLK+TO
TERMIN
MOVE A,[.NULIO,,.NULIO]
MOVEM A,GTJBLK+.GJSRC ; Don't hack I/O in gtjfn.
POPJ P,
.VECTOR GTJBLK(10.) ; Need exactly this many wds for non-extended long call
] ;IFN TNX
SUBTTL TNX - SUPPORT FOR I/O MACROS
IFN TNX,[
; TAKES -1(P)/ <JFN>, (P)/ <CHAR> AND OUTPUTS
TOUTC: EXCH R1,-1(P) ; GET JFN
EXCH R2,(P) ; AND CHAR
BOUT ; OUT IT GOES.
REST R2 ; RESTORE ACS AND RETURN
REST R1
RET
; TINC - TAKES -1(P)/ <JFN>, (P)/ <LOC> AND INPUTS FROM CHAN TO LOC
TINC: EXCH R1,-1(P) ; GET JFN
PUSH P,R2
BIN
ERJMP [HRROI R2,^C ; EOF (20X ONLY)
JRST .+1]
MOVEM R2,@-1(P) ; STORE BYTE IN DESIRED LOC
POP P,R2
SUB P,[1,,1] ; FLUSH LOC FROM STACK
POP P,R1
RET
; TINS - INPUT STRING
; TAKES T/ ADDR--> <JFN ADDR> ? <BP ADDR> ? <CNT ADDR>
TINS: SAVE R1
SAVE R2
SAVE R3
MOVE R1,@(T) ; GET JFN
MOVE R2,@1(T) ; AND BP
MOVN R3,@2(T) ; AND -COUNT
SIN
ERJMP .+1 ; ASSUME EOF AND PTRS UPDATED PROPERLY.
; THIS ONLY WINS ON 20X!
MOVNM R3,@2(T) ; RESTORE NEW CNT
MOVEM R2,@1(T) ; AND NEW BP
REST R3
REST R2
REST R1
RET
] ;IFN TNX
PATCH: BLOCK 100
CONSTA ;ITS
BEGP:: ;BEGINNING OF STORAGE ZEROED AT INIT.
JUNK: 0
PPSET: BLOCK LPDL ;PUSH DOWN LIST STORAGE
BLOCK 20
FLUSHP: BLOCK 1 ;P SAVED FOR RESTORATION IF A --MORE-- IS FLUSHED.
;0 => NOT POSSIBLE TO FLUSH NOW.
ERRCNT: BLOCK 1 ;DIFFERENCES COUNTER (0 MEANS NO DIFFERENCES)
LBUFP:
LBUFP1::BLOCK 1 ;POINTER TO BEGINNING OF LINE STORAGE FOR FILE #1
LBUFP2: BLOCK 1 ;DITTO FILE #2
LBUFP3: BLOCK 1
NLINES:
NLINE1::BLOCK 1 ;# OF LINES OF FILE 1 NOW IN CORE
NLINE2: BLOCK 1
NLINE3: BLOCK 1
EOFFL1: BLOCK 1 ;-1 => LAST NEXTLN ON FILE 1 WAS NO-OP'ED DUE TO EOF.
EOFFL2: BLOCK 1
EOFFL3: BLOCK 1
NCOMP1: BLOCK 1 ;HOW MANY LINES DIFF IS CONSIDERING FROM FILE 1
NCOMP2: BLOCK 1
NCOMP3: BLOCK 1
HBUF1: BLOCK WPL ;HOLDS TITLE FROM FIRST FILE
HBUF2: BLOCK WPL ;FROM SECOND FILE
HBUF3: BLOCK WPL
IFN ITS,[
RCHSTB: BLOCK 10. ;BLOCK WRITTEN INTO BY .RCHST
;WORD 0 RH DEV NAME, LH IF NON-ZERO THEN DEVICE NAME TO PRINT
;WRD 1 FNAM1
;WRD 2 FNAM2
;WRD 3 SYSTEM NAME
;WRD 4 NON-NEGATIVE => .ACCESS POINTER
;REST ROOM FOR EXPANSION OF SYSTEM CALL
]
PAGNUM: BLOCK 3 ;PAGE NUMBERS FOR THE TWO FILES, AT THE LEVEL OF RDLINE.
;THAT IS, THE PAGE # THAT THE NEXT LINE READ WILL START ON.
LINNUM: BLOCK 3 ;LINE NUMBERS FOR THE FILES, AT RDLINE LEVEL.
CHRNUM: BLOCK 3 ;# OF CHARS RDLINE HAS READ SO FAR FROM EACH FILE.
LLABEL: BLOCK 3*LNLBLN ;LNLBLN (4) WDS/FILE, 0 OR ASCIZ OF LAST LABEL AND A COLON.
MRGOUT: BLOCK 3 ;/M NON-ZERO MEANS OUTPUT TO MERGE FILE ALL
;/M LINES BEFORE WIPING OUT IN "MOVEUP" ROUTINE
;/M ALWAYS 0 IF /M NOT TYPED
LPHONY: BLOCK 1 ; -1 IFF LAST LINE OUTPUT BY MOVEUP DIDN'T END IN A CRLF,
;EXCEPT 1 => ENDED IN JUST A CR. 0 => ENDED IN A CRLF.
MRGLEN==2 ;/M LEAVE ROOM FOR 2 WORDS (10 CHAR) OF MERGE COMMAND.
MRGCOM: BLOCK MRGLEN ;/M BUFFER FOR MERGE COMMAND
BLOCK 1 ;/M GUARANTEE A NULL TERMINATION
MRGBYT: BLOCK 1 ;/M BYTE POINTER TO MERGE COMMAND STRING
MRGUFL: BLOCK 1 ;-1 => OUTPUTTING DIFFERENCES IN /F MODE; FROM MRGU1 TO MOVEUP.
OUTTTY: BLOCK 1 ;-1 => CHOUT IS OUTPUTTING TO A TTY.
IFN ITS,[
TTYSTS: BLOCK 1 ;SAVED TTYSET OF CHANNEL CHOUT, FOR RESTORATION AT RELDEV.
TTYST1: BLOCK 1
TTYST2: BLOCK 1
]
NUMTMP: BLOCK 1 ;TEMP FOR NUMLIN
TEMPF1: BLOCK 1 ;TEMP FOR F1
TEMPF2: BLOCK 1 ;TEMP FOR F2
TEMPF3: BLOCK 1
RFILC: 0 ;TEMP. FOR RFILE.
LSTEXP: 0 ;-1 => A BACKARROW WAS PRESENT IN COMMAND STRING.
FILBF1: BLOCK FILBFL ;FILE 1 BUFFER.
FILBE1=.-1
ASCIC//
FILPT1: 0 ;FILE 1 BUFFER PTR.
FILEP1: 0 ;FILE 1 B.P. TO THE ^C AFTERWHAT WAS READ IN.
FILBF2: BLOCK FILBFL ;FILE 2 BUFFER,
FILBE2=.-1
ASCIC//
FILPT2: 0 ;FILE 2 BUFFER PTR.
FILEP2: 0
FILBF3: BLOCK FILBFL ;FILE 3 BUFFER.
FILBE3=.-1
ASCIC//
FILPT3: 0 ;FILE 3 BUFFER PTR.
FILEP3: 0 ;FILE 3 B.P. TO THE ^C.
MRGBF: BLOCK MRGBSZ/5 ;BUFFER FOR MERGE OUTPUT
MRGBP: 0 ;B.P. FOR STUFFING BUFFER.
MRGCT: 0 ;# CHARS SPACE LEFT IN BUFFER.
PNTDBF: BLOCK 12./5+1 ;BUFFER FOR DECIMAL PRINT.
ENDP:: ;END OF STORAGE THAT'S ZEROED BEFORE EVERY COMMAND.
DEFDIR: 0 ;INITIAL (DEFAULT) DIRECTORY.
CMDFIL: 0 ;-1 => READING FROM THE FILE OPEN ON CHCMD
CMDIS: 0 ;DEFAULT INPUT DIR WHILE EXECUTING COMMAND FILE
CMDID: 0 ;DEFAULT INPUT DEVICE
CMDOS: 0 ;DEFAULT OUTPUT DIR
CMDOD: 0 ;DEFAULT OUTPUT DEVICE
CTLCF: 0 ;IF NOT 0, COMMIT SUICIDE AFTER FINISHING COMMAND.
COLMAX: <-1>_-1 ;/M MAX COLUMN TYPED OUT ON /M DIALOG
;/M CHANGED BY C COMMAND
LINMAX: <-1>_-1 ;/M MAX LINS TO TYPE OUT ON /M
NUMLIN: MATCH-1 ;# LINES FOR A MATCH
SEG1: 10000 ;START OF SEGMENT FOR FILE 1 LINES
SEG2: 201000 ;START OF SEGMENT FOR FILE 2 LINES
SEG3: 401000 ;START OF SEGMENT FOR FILE 3 LINES
TTIBUF: BLOCK 30 ;COMMAND BUFFER.
TTIBFL==.-TTIBUF
TTIPNT: 0 ;BYTE POINTER INTO TTIBUF.
TTICNT: 0 ;NUM. UNREAD CHARS LEFT IN TTIBUF.
CONSTANTS
FOO:
VARIABLES
-1
ENDCOR:
END BEG