1
0
mirror of https://github.com/PDP-10/its.git synced 2026-01-18 01:02:15 +00:00
PDP-10.its/src/sysen2/srccom.129
Eric Swenson 7ed0d1d8ce Added SRCCOM program and documentation.
SRCCOM is a source/binary comparison program.
SRCCOM also support source merges.
2016-11-27 08:48:36 +01:00

3804 lines
101 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; -*-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