.MCALL .MODULE .MODULE SRCCOM,VERSION=13,COMMENT=,AUDIT=YES ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. .SBTTL Source File Comparison Program .ENABL LC,GBL .IIF NE STRIP$ .SRCWCD = 100000 .AUDIT .SRCWCD ; Edit History: ; ; 001 30-Sep-80 03:10 PM Metsch, James (29602) [240,122] ; Correct blank line comparison for sliding match ; (001) ; ; 21-FEB-85 GEORGE THISSELL ; Point to correct error message in $PUTLIN ; ; 20-MAR-85 GEORGE THISSELL ; SETTOP TO JUST BELOW BASE OF WHERE USR SWAPS ; ; 07-DEC-87 IHZ ; INSERT /I SWITCH OPTION LOGIC TO IGNORE CHARACTER CASE ON COMPARE ; ; 10-FEB-89 Matthew Sacks ; Fix /I switch so that it understands the values in the DCL command ; DIFF/CASE:xxx ; ; 16-Nov-1990 JFW ; setup JSX, bracket error messages with ;+/;ERROR/.../;- ; ; 013 06-Mar-1997 ARB ; Fix /L:n defaulting to 1 with .SLP file specified. ; Fix no .SLP file if other than /L:1 specified. .SBTTL Edit History ; CG01 28-Sep-78 STRIP added ; Edit Level 1 ; CG02 05-May-79 Some macros removed to ULBMAC ; CG03 05-May-79 SRCPAT added ; Edit Level 2 ; MG01 10-Aug-79 Added test for protected file in CLOSE ; Edit Level 3 ; CG04 20-Sep-79 Correct USR swapping problems ; CG05 20-Sep-79 Fix output file size specification bug ; Edit Level 4 ; CG05 30-Oct-79 Force /P => /L:1 ; CG06 30-Oct-79 Replace "lost" edit to fix "FOO" not ; matching "FOO" ; CG07 30-Oct-79 Fix SRCPAT bug .SBTTL General comments .IIF NDF STRIP$ STRIP$ = 0 ;Default to no STRIP ;CG01+ .IIF NDF SRCPT$ SRCPT$ = 0 ;Default to no SRCPAT ;CG03 ;+ ; ; The SRCCOM utility compares two ASCII source files. The files are ; compared line by line to determine whether parallel records are ; identical. Using SRCCOM, you can perform the following file ; compare functions: ; ; o Generate a listing showing the differences between the two ; files. Each differences is listed as a pair; First the ; lines in the first file that are different, then the lines ; the second that are different. ; ; o Generate a listing in the form of one list with differences ; marked by change bars. ; ; o Generate output suitable for input to the SLP utility. This ; output contains the SLP commands and input required to make ; the first input file identical to the second input file. ; ; The command syntax is: ; ; *[output_file[,patch_file[/options]]]=old_file[/options],new_file[/options] ; ; If no output files are specified, the console terminal is used. ; ; The old_file and new_file may both use wildcarding to compare ; more than one file pair with one command line. See module ; SRCWCD.MAC for an explanation of wildcarding. ; ; There can be no patch file with wildcarding. ; ; O P T I O N S ; ; ; /A Directs SRCCOM to prompt for an audit trail for use ; in the SLP output format. The audit trail is a ; 1- to 11-character ASCII string. /A is invalid ; with wildcarding. ; ; /B Specifies that blank lines should be used in the ; file comparison process. Blank lines are normally ; ignored. ; ; /C Specifies that comments should be ignored in the ; compare process. Comments are lines that begin ; with a semicolon or text preceded by a space or tab ; and a semicolon. ; ; /D Specifies that SRCCOM list new_file with change ; bars in the form of vertical bars (|) applied to ; each line that does not have a corresponding line ; in old_file. ; ; The change bar character can be changed from the ; vertical bar to any character you wish by means of ; the /V option, described below. ; ; When a section of lines in old_file has been ; deleted in new_file, the first line not deleted is ; marked with the 'o' character. This character may ; also be changed by means of the /V option. ; ; /F Specifies that form feeds are to be included in the ; output file. Form feeds are always used in the ; compare process, but are normally not listed in the ; output file. ; ; /I Ignore character case (a-to-z) when doing comparison. ; ; /L:n Specifies that a number of lines (specified by the ; value n) must be identical before SRCCOM recognizes ; a match. If this switch is not specified, SRCCOM ; will search for three identical lines to match. ; The value must be in the range of 1 to 310. ; ; /N Specifies that the file-identfication/page number ; should not be placed in the output file. This is ; the default if /D or a patch file is specified. ; ; /P This switch is ignored in V5. If the user wants a ; patch file, he must use the new CSI command line ; format. ; ; /S Specifies that any sequence of spaces and/or tabs ; are to be treated as a single space in the compare ; process. However, all spaces and tabs are placed ; in the output listing. ; ; /T Specifies that trailing spaces and tabs are to be ; used in the comparison process. Normally, they are ; ignored. ; ; /V:i:d Specifies the character codes for use as the change ; bar insertion and deletion characters. This option ; is used in conjunction with the /D option. The ; insertion character is specified by the value i, ; and the deletion character by the value d. The ; values must be in the range 40 to 176. If the ; /D option is not present, this option is ignored. ; ; U S E R P A T C H A B L E L O C A T I O N S ; ; Several locations starting at 1000 are reserved as user patchable ; locations. They provide a certain amout of customization for any ; user who wishes it. Currently defined are: ; ; 1000 DFCBD Change bar deletion character (byte) ; 1001 DFCBI Change bar insertion character (byte) ; 1002 DFLTM Number of lines needed to provid a match. ; (/L default value) (word) ; 1004 DFFLG Default options enabled. The value there ; may be changed, but any bits that are set ; must remain set. (word) ; 1006 DFMAX Maximum record size. Must be between 20. ; and 250., inclusive. (word) ; ; Known Problems: ; ; Possible Functionality to be Added: ; ; 1. The ability to specify which characters are comment ; indicators. ; ;- ;+ ; STRIP and SRCPAT ; ; Note 1: STRIP and SRCPAT are mutually exclusive ; ; Note 2: Wildcarding cannot be used with either STRIP or SRCPAT ; ; STRIP ; The STRIP program is used to strip comments and blank lines from ; MACRO source files. Trailing blanks and tabs are also removed. ; The only comments that will be left are those which do not have a ; blank, tab, formfeed, or carriage return separating them from the ; previous text. The first page of the file is not stripped so ; that the copyright will be retained. The command line format is: ; ; out_file=in_file ; ; The default extensions are: ; ; .STP for the output file ; .MAC for the input file ; ; All switches are ignored. ; ;- ;+ ;CG03+ ; ; SRCPAT ; The SRCPAT program is used to produce Software Dispatch source ; patches for the stripped sources shipped with RT-11. It can be ; used to compare the commented sources with the stripped sources ; and output the differences as a .SLP file. Its differences from ; SRCCOM are listed below: ; ; 1. The /C, /P, and /S options are defaulted on ; 2. The default /L value is 1 ; 3. The default output file type is .SLP ; 4. Blank lines and lines consisting entirely of comments ; are not placed in the output file ; ; The command line format is: ; ; ,slp_file=in_file1,in_file2 ;- ;CG03- .SBTTL Macro definitions .MCALL .PRINT, .CSISPC,.TTYOUT,.READW, .WRITW .MCALL .ENTER, .CLOSE, .PURGE, .FETCH, .LOOKUP .MCALL .EXIT, .RELEAS,.SETTOP,.GTIM, .DATE .MCALL .DSTAT, .RCTRLO,.GTLIN, .GVAL .MACRO SAVREG JSR PC,$SAVAL .ENDM SAVREG .MACRO PUTLIN BUF,LEN MOV LEN,-(SP) MOV BUF,-(SP) JSR PC,$PUTLIN .ENDM PUTLIN .MACRO GET$S FDB MOV FDB,R0 CALL $GETLN .ENDM GET$S .MACRO PUT$S FDB,BUFFER,LENGTH MOV FDB,R0 MOV BUFFER,F.NRBD+2(R0) MOV LENGTH,F.NRBD(R0) CALL $PUTLN .ENDM PUT$S .SBTTL Offsets and Symbolics ; ASCII symbolics HT = 11 ;Horizontal tab FF = 14 ;Form feed SPACE = 40 ;Space SEMI = 73 ;Semicolon ACGRAV = 140 ;Accent grave ;IHZ LBRACE = 173 ;Left brace :IHZ ; ASCII character mask LOWCAS = 40 ;Clear lower case mask ;IHZ ; Program symbolics .IF EQ STRIP$ ;CG01+ HICHAN = 3 ;Highest channel open .IFF ;EQ STRIP$ HICHAN = 2 ;Highest channel open .ENDC ;EQ STRIP$ ;CG01- OCHAN == 0 ;Output channel for list file OCHAN2 == 1 ;Output channel for patch file ICHAN1 == 2 ;Input channel #1 ICHAN2 == 3 ;Input channel #2 MAXMCH == 310. ;Maximum number of lines to produce match MAXREC == 250. ;Maximum record size for a line $ATSIZ == 11. ;Maximum size of audit trail STARL = 10. ;Length of long line of stars STARS = 4 ;Length of short line of stars SLASHL = 1 ;Length of a slash S$R0 = 2 ;Offset to saved R0 S$R1 = 4 ;Offset to saved R1 S$R2 = 6 ;Offset to saved R2 ; CSI offsets OUSPSZ == 12 ;Size of CSI output spec in bytes INSPSZ == 10 ;Size of CSI input spec in bytes SPCSIZ == + ;Size of CSI file spec area ; RMON offset for V5 test $JSX =: 4 ;offset for JSX ALL64$ =: 020 ;no simulated RMON VBGEX$ =: 200 ;may run under VBGEXE if SET RUN VBGEXE $JSW =: 44 ;offset for JSW GTLIN$ =: 000010 VIRT$ =: 002000 RSTRT$ =: 020000 $UFLOA =: 46 ;offset for USR float address $USRTO =: 50 ;offset for SETTOP value S.VER == 276 ;Offset from RMON to monitor version number USRLOC = 266 ;Offset in RMON for address of normal USR area .SBTTL Line Descriptor definitions ;+ ; ; EACH LINE INVOLVED IN THE CURRENT ATTEMPT TO FIND A MATCH OR ; WHICH HAS BEEN READ-AHEAD IN AN EARLIER ATTEMPT IS STORED IN ; A DYNAMICALLY ALLOCATED BLOCK WHICH CONTAINS: ; ; 1. A FEW BYTES OF HEADER INFORMATION ; 2. THE TEXT WHICH IS ACTUALLY TO BE USED IN COMPARISONS ; 3. A LIST OF MODIFICATIONS WHICH WERE MADE IN REDUCING THE ; TEXT FROM ITS ACTUAL FORM TO THAT STORED UNDER (2) ABOVE. ; ; THE HEADER OFFSETS AND MEANINGS ARE DEFINED BELOW. THE TEXT IS ; SIMPLY A LIST OF BYTES WHOSE LENGTH IS STORED IN THE HEADER. ; THE MODIFICATIONS ARE A BYTE STRING WHICH STARTS AT THE FIRST ; BYTE AFTER THE TEXT. FOR EACH SUBSTRING OF THE ORIGINAL LINE ; WHICH HAS BEEN REPLACED IN THE COMPARE-LINE BY SOME OTHER ; (POSSIBLY NULL) STRING, THERE IS AN ENTRY IN THE MODIFICATION ; LIST, OF THE FOLLOWING FORM: ; ; BYTE 1 POSITION IN COMPARE-LINE OF FIRST BYTE WHICH HAS BEEN ; REPLACED ; BYTE 2 LENGTH OF STRING IN COMPARE-LINE WHICH REPLACED THIS ; THIS STRING IN THE ORIGINAL (I.E. NUMBER OF BYTES IN ; COMPARE-LINE TO SKIP WHEN PRINING THE LINE) ; BYTE 3 LENGTH OF THE FOLLOWING TEXT ; BYTES 4... TEXT WHICH MUST BE INSERTED INTO COMPARE-LINE ON ; PRINTING. ; ; THE LIST IS TERMINATED BY A SINGLE BYTE OF VALUE 255., WHICH CAN ; NEVER BE A VALID POSITION IN A LINE AND WHICH WILL ALWAYS BE HIGHER ; THAN ANY VALID VALUE. ; ; THIS LIST IS CREATED BY THE ROUTINE $PREPR WHEN THE LINE IS READ ; IN, AND INTERPRETED BY $PRINT WHEN THE LINE IS PRINTED. ; ;- .DSECT DS L.LNO ; LINE NUMBER IN FILE DS L.NL ; POINTER TO NEXT LINE DESCRIPTOR BLOCK DS L.SIZ ; SIZE OF BLOCK IN BYTES DS L.LEN BYTE ; [BYTE] LENGTH OF TEXT IN BYTES DS L.FB BYTE ; [BYTE] FLAGS BYTE DS L.PAG ; Page number to print on this line DS L.TXT ; START OF TEXT AREA L.HDSZ == L.TXT ; SIZE OF HEADER ; FLAG BITS LF.IGN == 1 ; LINE IS TO BE IGNORED IN COMPARISONS LF.PRM == 2 ; LINE IS NOT IN DYNAMICALLY ALLOCATED BLOCK LF.EOF == 4 ; RECORD IS END-OF-FILE DUMMY LINE ; ** MUST NOT BE RETURNED TO THE ALLOCATOR .SBTTL Stream descriptor definitions ;+ ; ; EACH OF THE TWO FILES IN THE COMPARISON HAS A STREAM DESCRIPTOR ; BLOCK (SDB) WHICH CONTAINS INFORMATION ABOUT THE FILE AND ABOUT ; THE CURRENT POSITION WITHIN IT. ; ;- .DSECT .GLOBL S.LNO DS S.FDBP ; POINTER TO FDB FOR FILE DS S.FNUM ; NUMBER OF STREAM, AS AN ASCII CHARACTER DS S.ALT ; POINTER TO OTHER SDB DS S.LNO ; LINE NUMBER OF LAST LINE READ DS S.TOP ; LOWEST NUMBERED LINE IN CORE DS S.NEW ; HIGHEST NUMBERED LINE IN FILE DS S.MAT ; FIRST LINE OF CURRENT MATCH DS S.POS ; POSITION REACHED IN CURRENT COMPARISON DS S.CUR ; 'CURRENT LINE' DS S.EOF ; POINTER TO EOF RECORD FOR THIS STREAM DS S.CNT BYTE ; [BYTE] NUMBER OF LINES TO READ AT EACH TRY DS S.PGFL BYTE ;[Byte] Indicate a page number to be printed DS S.PAG ;Page number to be printed DS S.SIZ ;Size of the SDB .SBTTL PSECT definitions .PSECT USERP,D,RO ;User patchable items .PSECT IMPURE,D,RW ;Impure data .PSECT PUREB,D,RO ;Pure data (byte) ;CG04 .PSECT .LIBD. ;Data (library routines) SWPUSR:: ;USR swap location .PSECT .LIBP. ;Data (library routine pointers) .PSECT CLEAR,D,RO ;List of items to be cleared on start-up CLRLST:: ;Reference label .PSECT CLEAR1,D,RO ;List of blocks to be cleared on start-up .WORD 0 ;End of CLRLST CLRLS1:: ;Reference label .PSECT SWTCHR,D,RO ;Switch character table .WORD 0 ;End of clear block list SWLIST:: ;Reference label .PSECT ACTION,D,RO ;Action routine list ACTLST:: ;Reference label .PSECT .LIBC. ;Library routines .PSECT .LIBO.,OVR ;Library overlayed psect .PSECT SRCCOM,I,RO ;Code psect .SBTTL Switch declarations .IF EQ STRIP$ ;CG01+ .MACRO SWITCH CHR,ROUTINE,FLAG,EXCLUD .PSECT SWTCHR .IF NB FLAG FLAG == ...SWT ...SWT = ...SWT * 2 .ENDC .IF NB CHR .BYTE ''CHR .IFF .BYTE 0 .IFTF .PSECT ACTION .IFT .WORD ROUTINE .IF NB FLAG .WORD FLAG .IFF .WORD 0 .ENDC .IF NB EXCLUD .WORD EXCLUD .IFF .WORD 0 .ENDC .IFF .WORD 0 .ENDC .ENDM SWITCH ...SWT = 1 ACTSIZ == 6 SWITCH A SET FL.AUD ;Prompt for audit trail ;SWITCH A SET FL.AUD FL.CB ;Prompt for audit trail SWITCH B SET FL.BL ;Compare blank lines SWITCH C SET FL.COM ;Ignore comments ;SWITCH D SET FL.CB FL.SLP!FL.AUD ;Produce change bar output SWITCH D SET FL.CB ;Produce change bar output SWITCH F SET FL.FF ;Print form feeds SWITCH I CASE FL.ICA ;Ignore alpha character case ;IHZ SWITCH L LINVAL FL.LI ;Match n lines SWITCH N CLEAR FL.LN ;Don't list line numbers ;SWITCH P SET FL.SLP FL.CB ;Produce SLP output SWITCH P NOACT, , ;Ignore this switch SWITCH S SET FL.MBS ;Ignore multiple tabs, spaces SWITCH T CLEAR FL.TBS ;Ignore trailing tabs, spaces SWITCH V VBARVL, , ;Change change bar characters ;SWITCH W WRDVAL FL.WRD ;Word mode compare for doc. .WORD 0 ;Terminate switch table FL.SLP == 2000 ;Patch file wanted ;IHZ FL.WCD == 4000 ;Wildcarding in progress ;IHZ FL.DIF == 100000 ;NOT (FL.CB!FL.SLP) .ENDC ;EQ STRIP$ ;CG01- .SBTTL CLRLST - List of things to be cleared on start-up .IF EQ STRIP$ ;CG01+ ;+ ; ; The following list contains the addresses of all items which must be ; cleared on start-up and restart. ; ;- .PSECT CLEAR .WORD $DIFCT ;Count of number of differences .WORD CBDCHR ;Change bar insertion and deletion characters .WORD SWLSET ;Flag indicating user specified /L:n ;CG06 .WORD PRSLP ;Flag indicating print the SLP file .IFTF ;EQ STRIP$ ;+ ; ; This list contains blocks of words which must be initialized. The first ; word is the address, and the second is the number of words to clear ; ;- .PSECT CLEAR1 .IFT ;EQ STRIP$ .WORD $AUDMG, <$ATSIZ+1>/2 ;Audit trail buffer .WORD $SDB2+S.LNO, 6 ;Input file #2 SDB .IFTF ;EQ STRIP$ .WORD $SDB1+S.LNO, 6 ;Input file #1 SDB ; User patchable items ;+ ; ; The following items are place so that they are easily changed by the ; user. This allows a minimum customization ability. ; ;- .PSECT USERP .IFT ;EQ STRIP$ DFCBD:: .BYTE 'o ;Change bar deletion character 'o' DFCBI:: .BYTE '| ;Change bar insertion character '|' .IF EQ SRCPT$ ;CG03+ DFLTM:: .WORD 3 ;Number of lines for a match DFFLG:: .WORD FL.TBS!FL.LN ;Default flag bits .IFF ;EQ SRCPT$ DFLTM:: .WORD 1 ;Number of lines for a match DFFLG:: .WORD FL.COM!FL.SLP!FL.MBS!FL.TBS ;Default flag bits .ENDC ;EQ SRCPT$ ;CG03- .ENDC ;EQ STRIP$ ;CG01- DFMAX:: .WORD MAXREC ;Maximum record size. Must be <= 250. .SBTTL Pure data .PSECT PUREB .NLIST BEX VERSON:: ;Version number .IF EQ STRIP$ ;CG01+ .IF EQ SRCPT$ .NLCSI PATLEV=:.-2 .IFF ;EQ SRCPT$ .ASCII /SRCPAT/ .NLCSI PART=RLSVER .ENDC ;EQ SRCPT$ ;**-1 .IFF ;EQ STRIP$ .ASCII /STRIP/ .NLCSI PART=RLSVER .IFTF ;EQ STRIP$ .EVEN .IFT ;EQ STRIP$ AUDPRM::.ASCII \Audit trail? \<200> ;Prompt for /A SLPTBL::.ASCIZ ^- ERRMSG FRD, .IFTF ;EQ STRIP$ ERRMSG ILC, ERRMSG ERD, ERRMSG ILD, ERRMSG DNA, ERRMSG ISM, ERRMSG INE, ERRMSG FNF, ERRMSG VER, .IFT ;EQ STRIP$ ERRMSG ILO, ERRMSG IOV, ERRMSG NDF, ERRMSG TMD, .IFTF ;EQ STRIP$ MSGEND .PSECT IMPURE .IFT ;EQ STRIP$ .IF EQ SRCPT$ ;CG03+ ERRPRE: .ASCII \?SRCCOM-\ ;Error message prefix .IFF ;EQ SRCPT$ ERRPRE: .ASCII \?SRCPAT-\ .ENDC ;EQ SRCPT$ ;CG03- .IFF ;EQ STRIP$ ERRPRE: .ASCII \?STRIP-\ ;Error message prefix .ENDC ;EQ STRIP$ ;CG01- ;- ERRLEV: .ASCII \x-\<200> ;Error level .EVEN .LIST BEX .SBTTL Impure data ; Dummy Line Descriptor Blocks .PSECT IMPURE EOF1: ; DUMMY END-OF-FILE LINE .WORD 65535. ; LINE NUMBER .WORD EOF1 ; POINT TO SELF .WORD 0 ; SIZE (UNUSED) .BYTE 10. ; DUMMY RECORD LENGTH .BYTE LF.PRM!LF.EOF ; NEVER DELETE THIS RECORD .WORD 0 ;Page number .REPT 10. .BYTE 0 ; DUMMY RECORD TO COMPARE .ENDR .IF EQ STRIP$ ;CG01+ EOF2: .WORD 65535. .WORD EOF2 .WORD 0 .BYTE 10. .BYTE LF.PRM!LF.EOF .WORD 0 .REPT 10. .BYTE 0 .ENDR .IFTF ;EQ STRIP$ ; Define Stream Descriptor Blocks (SDB's) $SDB1:: .WORD $INFD1 ; FDB POINTER .BYTE '1,') ; DESCRIPTION .IFT ;EQ STRIP$ .WORD $SDB2 ; POINTER TO OTHER SDB .IFF ;EQ STRIP$ .WORD 0 ; .IFTF ;EQ STRIP$ .WORD 0 ; LINE NUMBER .WORD 0,0,0,0,0 ; LINE POINTERS .WORD EOF1 ; EOF RECORD .BYTE 1 ; NUMBER OF LINES TO READ .BYTE 0 ;Page # flag .WORD 0 ;Page number .IFT ;EQ STRIP$ $SDB2:: .WORD $INFD2 .BYTE '2,') .WORD $SDB1 .WORD 0 .WORD 0,0,0,0,0 .WORD EOF2 .BYTE 1 .BYTE 0 .WORD 0 .IFTF ;EQ STRIP$ $SDB0:: .WORD $LSTFD ;Dummy SDB for listing file wild .BYTE '0,') ; card check .ENDC ;EQ STRIP$ ;CG01- .SBTTL Define File Descriptor Blocks (FDB'S) .PSECT IMPURE $LSTFDB:: ; FDB FOR LIST FILE .FILE ,OCHAN,OUTFIL,RECSIZ=MAXREC,LEN=0,SEQNUM=-1,BUFSIZ=512. $PATFDB:: ; FDB FOR PATCH FILE .FILE ,OCHAN2,OUTFIL+OUSPSZ,RECSIZ=MAXREC,LEN=0,SEQNUM=-1,BUFSIZ=512. $INFD1:: ; FIRST INPUT FILE .FILE ,ICHAN1,INFILE,RECSIZ=MAXREC,SEQNUM=0,BUFSIZ=512. .IF EQ STRIP$ ;CG01+ $INFD2:: ; SECOND INPUT FILE .FILE ,ICHAN2,INFILE+INSPSZ,RECSIZ=MAXREC,SEQNUM=0,BUFSIZ=512. .ENDC ;EQ STRIP$ ;CG01- .SBTTL Buffers and Variables .PSECT IMPURE BUFADR: .WORD 0 ;Address of record returned by GET$S LENGTH: .WORD 0 ;Length of record just read MATCHR: .WORD 0 ;Workspace during match recovery PREBUF: .WORD 0 ;Address of input string for $PREPR SWLSET: .WORD 0 ;Flag indicating user specified /L:n ;CG06 TMPCH1: .BYTE 0 ;File 1 temporary character store ;IHZ TMPCH2: .BYTE 0 ;File 2 temporary character store ;IHZ EDTBUF: .BLKB MAXREC * 2 ;Buffer for line editing information MTAREA: .BLKW 2 ;EMT area .IF EQ STRIP$ ;CG01+ $DIFCT::.WORD 0 ;Count of number of differences $FLAGS::.WORD 0 ;Options flag word $LTMCH::.WORD 0 ;Number of lines to match before match found CBDCHR::.BYTE 0 ;Change bar deletion character CBICHR::.BYTE 0 ;Change bar insert character PRSLP:: .WORD 0 ;Flag to indicate when to print SLP file .IFTF ;EQ STRIP$ DATE:: .WORD 0 ;Date save area SAVBUF::.WORD 0 ;Address of buffer for $PRINT SAVFDB::.WORD 0 ;Address of FDB for PUTLIN SAVESP::.WORD 0 ;SP save area $FRHD:: .BLKW 2 ;Dynamic memory listhead TIME:: .BLKW 2 ;Time-of-day save area LIMITS::.LIMIT ;Program limits DEFEXT::.RAD50 \MAC\ ;Default input file extension .IFT ;EQ STRIP$ .IF EQ SRCPT$ ;CG03+ .RAD50 \DIF\ ;Default list file extension .RAD50 \SLP\ ;Default patch file extension .IFF ;EQ SRCPT$ .RAD50 \ \ ;Dummy default list file extension .RAD50 \SLP\ ;Default output file extension .ENDC ;EQ SRCPT$ ;CG03- .IFF ;EQ STRIP$ .RAD50 \STP\ ;Default output file extension .IFTF ;EQ STRIP$ .BLKW 2 ERAREA::.BYTE 0 ;Error code byte .BYTE 0 ;Error level/return flag .WORD ERRPRE ;-> Error message prefix .WORD ERRLEV ;-> Error level byte .WORD ERRTAB ;-> Error message offset table .WORD 0 ;-> File name block .WORD RETRY ;-> Abort entry IOAREA::.BLKW 12 ;EMT area block .IFT ;EQ STRIP$ $AUDMG::.BLKB $ATSIZ+1 ;Buffer to hold audit trail .EVEN .WORD 0 ;End of audit trail .IFTF ;EQ STRIP$ OUTFIL::.BLKB OUSPSZ * 3 ;CSI output file spec area INFILE::.BLKB INSPSZ * 6 ;CSI input file spec area $LSTBF::.BLKB MAXREC+16. ;Listing line buffer .IFT ;EQ STRIP$ $PATBF::.BLKB MAXREC+16. ;Patch line buffer .ENDC ;EQ STRIP$ ;CG01- .SBTTL Start-up and reentry code ;+ ; ; SRCCOM ; STRIP ; This is the start-up and reentry code for SRCCOM and STRIP. The ; re-entry point is SRCCOM-2 and STRIP-2. RETRY is the point for ; all restarts, error and command finished. ; ;- .ASECT . = $JSX .WORD VBGEX$!ALL64$ . = $JSW ;Set up the JSW .WORD RSTRT$ ; Re-enterable . = $UFLOA .WORD SWPUSR ;Let the USR swap here ORIGIN SRCCOM .ENABL LSB BR RETRY ;Reentry point SRCCOM:: MOV SP,SAVESP ;Save the initial stack pointer RETRY:: MOV SAVESP,SP ;Restore the initial stack pointer CALL INIT ;Go do some initialization .GVAL #IOAREA,#S.VER ;Get the system version number BIC #^C377,R0 ;Clear the update number CMP R0,#5 ;Is it the right version? BGE 5$ ;Branch if so ;+ ;ERROR .ERR #ERAREA,#VER,LEVEL=FATAL,RETURN=YES ;- CLR R0 ;Hard exit .EXIT ;Get out quick 5$: .CSISPC #OUTFIL,#DEFEXT,#0,#$LSTBF ;Get the command line BCS RETRY ;Retry on error TSTB $LSTBF ;Anything there? BNE 10$ ;Branch if yes .PRINT #VERSON ;Else print the version number BR RETRY ; and restart .IF EQ STRIP$ ;CG01+ 10$: CALL DECODE ;Decode the command line .IFF ;EQ STRIP$ 10$: .IFT ;EQ STRIP$ .IF EQ SRCPT$ CALL WILCRD ;Test for wildcarding TST WC.FLG ;Any wildcarding? BEQ 20$ ;If not, branch CALL WCDIO ;Yes, do wildcarding I/O .ENDC ;EQ SRCPT$ .IFTF ;EQ STRIP$ 20$: CALL FILES ;Do file processing .IFT ;EQ STRIP$ .IF EQ SRCPT$ MOV #$INFD1,R0 ;Get input file 1 FDB MOV F.IOBF(R0),BUFST1 ;Save EMT buffer 1 start MOV #$LSTFD,R0 ;Get list file FDB MOV F.BPTR(R0),OBUFPT ;Save original buffer ptr MOV #$INFD2,R0 ;Get input file 2 FDB MOV F.IOBF(R0),BUFST2 ;Save EMT buffer 2 start .ENDC ;EQ SRCPT$ CALL DEFALT ;Set up required defaults .IF EQ SRCPT$ 30$: BIT #FL.WCD,$FLAGS ;Wildcarding in progress? BEQ 60$ ;If not, branch BIT #WC.NXT,WC.FLG ;First time through wildcarding? BNE 40$ ;If not, branch BIS #WC.NXT,WC.FLG ;Say first wildcarding loop done BIT #FL.CB,$FLAGS ;Change bars wanted? BEQ 60$ ;If no, branch CALL WCDPUT ;Put filenames into print buffer BR 60$ ;Continue 40$: CALL WCDINT ;Reinit for wildcarding CALL WCDLKI ;Get next two input specs BIT #FL.WCD,$FLAGS ;Wildcarding finished? BNE 50$ ;If no, branch .CLOSE #OCHAN ;Close last open channel JMP RETRY ;Get next CSI line 50$: CALL WCDPUT ;Put filenames into print buffer .ENDC ;EQ SRCPT$ .IFTF ;EQ STRIP$ 60$: CALL $MAIN ;Execute the command line .IFT ;EQ STRIP$ MOV $DIFCT,R1 ;Get the number of differences BNE 120$ ;Branch if some .IF EQ SRCPT$ MOV $FLAGS,-(SP) ;Save flag bits BIC #^C,@SP ;Clear all except these 2 bits CMP #FL.CB+FL.WCD,(SP)+ ;Doing changebars and wildcarding? BNE 80$ ;If not, branch TST LSTFIL ;List file wanted? BEQ 70$ ;If no, branch CALL WCDPRT ;Print filenames 70$: MOV #$LSTFD,R0 ;Point to output FDB CALL BUFDMP ;Purge print file BR 90$ ;Go get error message 80$: BIT #FL.WCD,$FLAGS ;Wildcarding in progress? BEQ 100$ ;If not, branch CALL WCDPRT ;Print filename ;+ ;ERROR 90$: .ERR #ERAREA,#NDF,LEVEL=INFORM,RETURN=YES ;- TST WC.FLG ;Wildcarding finished? BNE 30$ ;If not, branch .CLOSE #ICHAN1 ;Close open channels .CLOSE #ICHAN2 .CLOSE #OCHAN JMP RETRY ;Get another CSI line 100$: BIT #FL.CB,$FLAGS ;Doing changebars? BEQ 110$ ;If not, branch MOV #$LSTFD,R0 ;Point to output FDB CALL BUFDMP ;Dump buffer .ENDC ;EQ SRCPT$ ;+ ;ERROR 110$: .ERR #ERAREA,#NDF,LEVEL=INFORM,RETURN=NO ;- 120$: BIT #FL.SLP,$FLAGS ;Getting SLP output? BEQ 130$ ;Branch if not MOV #$PATFD,SAVFDB ;Point to SLP buffer PUTLIN #SLASH,#SLASHL ;Output the final '/' MOV #$PATFD,R0 ;Point to the patch FDB MOV R0,R2 ;Save in case of error ;MG01 CALL $CLOSE ;Close it up BCS 155$ ;If errors...branch ;MG01+ .IF NE SRCPT$ BR 180$ ;For SRCPAT, go out .IFTF ;NE SRCPT$ 130$: .IFF ;NE SRCPT$ BIT #FL.CB,$FLAGS ;Change bar format? BNE 140$ ;Branch if so MOV #$LSTFD,SAVFDB ;Point to listing FDB PUTLIN #STAR,#STARL ;Finish up the differences 140$: MOV #$LSTFD,R0 ;Point to the listing FDB MOV R0,R2 ;Save in case of error ;MG01 BIT #FL.WCD,$FLAGS ;Wildcarding in progress? BNE 160$ ;If yes, branch 150$: CALL $CLOSE ;Close it up BCC 180$ ;No errors...continue ;MG01+ .ENDC ;EQ SRCPT$ .IFF ;EQ STRIP$ 140$: MOV #$LSTFD,R0 ;Point to the listing FDB MOV R0,R2 ;Save in case of error ;MG01 150$: CALL $CLOSE ;Close it up BCC 180$ ;No errors...continue ;MG01+ .IFTF ;EQ STRIP$ ;+ ;ERROR 155$: .ERR #ERAREA,F.ERR(R2),LEVEL=FATAL,FILE=F.OPNM(R2),RETURN=YES ;- .IFT ;EQ STRIP$ .IF EQ SRCPT$ 160$: TST LSTFIL ;A list file wanted? BEQ 170$ ;If not, branch CALL WCDPRT ;Print filename on TT: 170$: MOV #$LSTFD,R0 ;Point to output FDB CALL BUFDMP ;Dump buffer .ENDC ;EQ SRCPT$ .ENDC ;EQ STRIP$ ;CG01- 180$: .IF NE STRIP$!SRCPT$ ;CG03+ JMP RETRY ;Done... Loop .IFF ;NE STRIP$!SRCPT$ BIT #FL.WCD,$FLAGS ;Doing wildcarding? BEQ 200$ ;If no, branch TST WC.FLG ;Last pass finished? BEQ 190$ ;If yes, branch ;+ ;ERROR .ERR #ERAREA,#FRD,LEVEL=WARN,RETURN=YES ;- JMP 30$ ;No, continue wildcarding 190$: .CLOSE #OCHAN ;Close open files 200$: .CLOSE #ICHAN1 .CLOSE #ICHAN2 ;+ ;ERROR .ERR #ERAREA,#FRD,LEVEL=WARN,RETURN=NO ;- .ENDC ;NE STRIP$!SRCPT$ ;CG03- .DSABL LSB .SBTTL INIT - Start-up initialization ;+ ; ; INIT ; This next section of code cleans up for a restart. It purges all channels, ; releases all handlers, resets memory to the program hi-limit, and gets ; the time-of-day and the date (to cause date roll-over). ; ;- .ENABL LSB INIT:: .IF EQ STRIP$ .IF EQ SRCPT$ CLR WC.FLG ;Clear wildcarding flag .ENDC ;EQ SRCPT$ .ENDC ;EQ STRIP$ MOV #HICHAN,R1 ;Get the highest channel used 1$: .PURGE R1 ;Stop using it DEC R1 ;Loop until done BPL 1$ ; MOV #OUTFIL,R1 ;Point to the CSI file specs 2$: TST @R1 ;Anything there? BEQ 3$ ;Branch if not .RELEAS R1 ;Release the handler 3$: ADD #OUSPSZ,R1 ;Bump the pointer to the next spec CMP #,R1 ;Thru with the output file specs? BHIS 2$ ;Branch if not TST -(R1) ;Input specs are 1 word shorter CMP #,R1 ;Thru with input specs? BHIS 2$ ;Branch if not .SETTOP LIMITS+2 ;Release dynamic memory (return to only what ; we need... the program high limit) MOV @#$USRTO,$FRHD ;Save the program free memory pointer ;CG04 ADD #2,$FRHD ;Don't write on ourselves ;CG04 .IF EQ STRIP$ ;CG01+ MOV #CLRLST,R1 ;Point to list of things to clear 4$: CLR @(R1)+ ;Clear it TST @R1 ;Done? BNE 4$ ;Branch if not .IFTF ;EQ STRIP$ MOV #CLRLS1,R1 ;Point to list of blocks to be cleared 5$: MOV (R1)+,R0 ;Get the address BEQ 7$ ;Branch if done MOV (R1)+,R2 ;Get the size of the block 6$: CLR (R0)+ ;Clear a word SOB R2,6$ ; BR 5$ ; 7$: MOV #1,$SDB1+S.PAG ;Set up page number .IFT ;EQ STRIP$ MOV #1,$SDB2+S.PAG ; MOV DFFLG,$FLAGS ;Set the default flag bits. MOV DFLTM,$LTMCH ;Set the default lines to match DEC $LTMCH ;Fix it .IFTF ;EQ STRIP$ MOV DFMAX,R0 ;Get the maximum record size MOV R0,$INFD1+F.RSIZ ;Save it in the FDB .IFT ;EQ STRIP$ MOV R0,$INFD2+F.RSIZ ; of both input files .ENDC ;EQ STRIP$ ;CG01- .GTIM #IOAREA,#TIME ;Get time-of-day (and maybe cause date roll) .DATE ;Get the date MOV R0,DATE ;Save it .RCTRLO ;Reset CTRL/O RETURN .DSABL LSB .SBTTL DECODE - Decode the command line .IF EQ STRIP$ ;CG01+ ;+ ; ; DECODE ; This next section of code processes the command line. It determines ; whether or not an option is valid, and if so, it dispatches to the ; routine defined by the SWITCH macro for further processing. ; The routines are given the following information: ; ; R0 = switch value or 0 ; R1 -> word containing flag bit for this option ; word containing exclusion bits for this option ; ; R4 and R5 must not be modified by the switch processing routines. ; ;- .ENABL LSB DECODE:: MOV (SP)+,R4 ;Save the return address MOV (SP)+,R5 ;Get the number of options BEQ 4$ ;Branch if done 1$: MOV #SWLIST,R2 ;Point to the list of valid options MOV #ACTLST,R1 ;Point to the option action routine list MOV (SP)+,R3 ;Get the option BMI 15$ ;Branch if a value was given CLR -(SP) ; else fake one 15$: MOVB R3,ERROPT ;Save switch in case of error 2$: BICB #40,R3 ;Convert it to uppercase ;DBF CMPB R3,(R2)+ ;Is this the switch? BEQ 3$ ;Branch if so ADD #ACTSIZ,R1 ;Point to the next option TST @R1 ;Are we done? BNE 2$ ;Branch if not ;+ ;ERROR .ERR #ERAREA,#ILO,LEVEL=FATAL,RETURN=NO,ASCII=#ERROPT ;Then it must be an error ;- 3$: MOV (SP)+,R0 ;Get the value JSR PC,@(R1)+ ;Call the action routine SOB R5,1$ ;Branch if more switches 4$: MOV R4,-(SP) ;Restore the return address RETURN .DSABL LSB .ENDC ;EQ STRIP$ ;CG01- .SBTTL FILES - Lookup and enter files ;+ ; ; FILES ; The FILES routine initializes the dynamic memory allocation and opens ; the input and output files. If no output file is specified, TT: is used. ; Note that the output file is ENTERed in either case, to save on code later. ; ;- .ENABL LSB FILES:: MOV #$FRHD,R0 ;Point to the free memory listhead MOV @#$USRTO,@R0 ;Set up first free address ;CG04 ADD #2,@R0 ;Don't write on ourselves ;CG04 MOV R0,R4 ;Save it for later CALL FINDAD ;Set up dynamic memory MOV #$SDB0,R2 ;Point to the dummy list file SDB CALL $IDLIN ;Convert the file ID to ASCII 1$: MOV #$LSTFD,R2 ;Point to the list file FDB MOV F.OPNM(R2),R0 ;R0 -> list file spec from CSI ;CG05+ MOV 10(R0),F.OPLN(R2) ;Set up user specified file size TST @R0 ;Was a file specified? ;CG05- BNE 2$ ;Branch if so MOV #^RTT ,@F.OPNM(R2) ;Else use the TT: 2$: .IF NE SRCPT$ CMP #^RTT ,@F.OPNM(R2) ;Using the TT:? BNE ILCMND ;If no, error, go out .ENDC ;NE SRCPT$ .OPEN R2,R4 ;Open the list file BCC 25$ ;Branch if no error ;+ ;ERROR 22$: .ERR #ERAREA,F.ERR(R2),LEVEL=FATAL,RETURN=NO,FILE=F.OPNM(R2) ;MG01 ;- 25$: MOV #$PATFD,R2 ;Point to the patch file FDB MOV F.OPNM(R2),R0 ;R0 -> patch file spec from CSI ;CG05+ MOV 10(R0),F.OPLN(R2) ;Set up user specified file size TST @R0 ;Was a file specified? ;CG05- BEQ 3$ ;Branch if not .IF EQ STRIP$ .IF EQ SRCPT$ TST WC.FLG ;Wildcarding in progress? BNE ILCMND ;If yes, branch .ENDC ;EQ SRCPT$ BIS #FL.SLP,$FLAGS ;Say patch file wanted .OPEN R2,R4 ;Open the patch file BCS 22$ ;Branch if error .IFF ;EQ STRIP$ BR ILCMND ;No SLP file for STRIP .ENDC ;EQ STRIP$ 3$: MOV #$INFD1,R2 ;Point to the FDB for input file #1 TST @F.OPNM(R2) ;Is there a file there? BEQ ILCMND ;Branch if not... error .OPEN R2,R4 ;Lookup the file .IF EQ STRIP$ ;CG01+ BCS 5$ ;Branch on error .IFF ;EQ STRIP$ BCC 6$ ;Branch if no error .IFT ;EQ STRIP$ MOV #$INFD2,R2 ;Point to the FDB for input file #2 TST @F.OPNM(R2) ;Is there a filename there? BNE 4$ ;Branch if so .IFTF ;EQ STRIP$ ;+ ;ERROR ILCMND: .ERR #ERAREA,#ILC,LEVEL=FATAL,RETURN=NO ;Illegal command ;- .IFT ;EQ STRIP$ 4$: .OPEN R2,R4 ;Lookup file #2 BCC 6$ ;Branch if no error ;+ ;ERROR 5$: .ERR #ERAREA,F.ERR(R2),LEVEL=FATAL,RETURN=NO,FILE=F.OPNM(R2) ;- .ENDC ;EQ STRIP$ ;CG01- 6$: RETURN .DSABL LSB ;+ ; FINDAD ; The Initialize Dynamic Memory routine establishes the initial state of the ; free dynamic memory available to the executing task. The free dynamic ; memory consists of all memory extending from the end of the task to the base ; of where the USR swaps in. ; ; R0 -> .WORD FREESP ;Address of first free dynamic memory location ; .WORD 0 ;Must be 0 ; ; CALL FINDAD ; ; R0 = size of dynamic memory ; Free memory list is initialized ; Any previously allocated blocks are deallocated. ;- .ENABL LSB FINDAD::MOV R1,-(SP) ;Save R1 MOV R0,R1 ; and the address of the free memory list .GVAL #MTAREA,#USRLOC ;Find address of USR TST -(R0) ;Point to just before it .SETTOP ;Ask for memory SUB @R1,R0 ;Get the size BCS 2$ ;Less than we already have?!?!? BIT #VIRT$,@#$JSW ;Is this a virtual job? BEQ 1$ ;Branch if not SUB #500,R0 ;Else fix our offset 1$: MOV @R1,R1 ;Point to the free block CLR (R1)+ ;Clear the pointer to the next block TST -(R0) ;Back off a word BIC #3,R0 ;Round it to a 4 byte boundary MOV R0,@R1 ;Save the size 2$: MOV (SP)+,R1 ;Restore R1 RETURN .DSABL LSB .SBTTL DEFALT - Set up defaults .IF EQ STRIP$ ;CG01+ ;+ ; ; DEFALT ; This routine sets up default values if the user did not specify them, ; and sets the flags for options which are by other options. The audit ; trail is also collected here ; ;- .ENABL LSB DEFALT:: BIT #FL.CB,$FLAGS ;Differences wanted? BNE 1$ ;Branch if not BIS #FL.DIF,$FLAGS ;Else indicate it MOV #$SDB1,R2 ;Point to the SDB for file #1 CALL $IDLIN ;Convert file ID to ASCII MOV #$LSTFD,SAVFDB ;Get FDB for printing PUTLIN R3,R1 ;Output the file ID MOV #$SDB2,R2 ;Same for file #2 CALL $IDLIN ; MOV #$LSTFD,SAVFDB ;Get FDB for printing PUTLIN R3,R1 ; BR 3$ ;Ask about patch file 1$: BIC #FL.LN,$FLAGS ;Don't print line numbers .IF EQ SRCPT$ ;CG08+ BIS #FL.BL!FL.FF,$FLAGS ;Include form feeds in output ;Compare blank lines .IFF ;EQ SRCPT$ BIS #FL.FF,$FLAGS ;Include form feeds in output .ENDC ;EQ SRCPT$ ;CG08- TSTB CBDCHR ;Was a deletion indicator specified (/V)? BEQ 2$ ;Branch if not TSTB CBICHR ;How about the insertion character? BNE 5$ ;Branch if so. We're done. MOVB CBDCHR,CBICHR ;Else, we stored the insertion character here 2$: MOVB DFCBD,CBDCHR ;Get the default deletion marker TSTB CBICHR ;Insertion marker there? BNE 3$ ;Branch if so. MOVB DFCBI,CBICHR ;Else use the default 3$: BIT #FL.SLP,$FLAGS ;Patch file wanted? BEQ 5$ ;If not, branch .IF NE SRCPT$ ;013 TST SWLSET ;Did user specify /L? ;CG06+ BNE 35$ ;Branch if so CLR $LTMCH ;1 line to match (-1) ;CG06- 35$: .ENDC ;NE SRCPT$ ;013 BIT #FL.AUD,$FLAGS ;Does he want an audit trail? BEQ 5$ ;Branch if not MOV #$LSTBF,R1 ;Get the audit trail in a handy buffer BIS #GTLIN$,@#$JSW ;Set the non-termination bit .GTLIN R1,#AUDPRM ;Prompt for it BIC #GTLIN$,@#$JSW ;Clear the non-termination bit MOV #$ATSIZ,R0 ;Get the max size MOV #$AUDMG,R2 ;Point to the audit trail buffer 4$: MOVB (R1)+,(R2)+ ;Move a character in BEQ 5$ ;Branch if done SOB R0,4$ ;Go for the max TSTB @R1 ;Was there more? BEQ 5$ ;Branch if not ;+ ;ERROR .ERR #ERAREA,#ATT,LEVEL=WARNING,RETURN=YES ;Tell him we're ; truncating it ;- 5$: RETURN .DSABL LSB .SBTTL Option action routines .SBTTL LINVAL - Process /L LINVAL:: DEC R0 ;Make the value correct MOV R0,$LTMCH ;Get the value BLT ILOPTV ;Branch if out of range INC SWLSET ;Say that the user specified /L:n ;CG06 CMP #MAXMCH,R0 ;In range on the hi end? BGE FLAGIT ;Branch if yes. Process the option flag bit ;+ ;ERROR ILOPTV:: .ERR #ERAREA,#IOV,LEVEL=FATAL,RETURN=NO,ASCII=#ERROPT ;- .SBTTL VBARVL - Process /V VBARVL:: BIC #^C177,R0 ;Clear out ugly bits BNE 1$ ;Branch if non-zero MOV #SPACE,R0 ;Make a space 1$: CMP #40,R0 ;Is it a valid printing character? BHI ILOPTV ;Branch if not CMP #177,R0 ;? BEQ ILOPTV ;Too big TSTB CBDCHR ;Second time thru? BNE 2$ ;Branch if so MOVB R0,CBDCHR ;Save the character BR FLAGIT ; and go process the option flag bit 2$: TSTB CBICHR ;Third time thru? BNE ILCMD1 ;That's not fair MOVB R0,CBICHR ;Save the character BR FLAGIT ; and go process the option flag bit .SBTTL NOACT - Process /P NOACT:: BR RET ;No action for /P .SBTTL SET - Process /A/B/C/D/F/S SET:: TST R0 ;Got a value? BEQ FLAGIT ;Branch if not. Process option flag bit ILCMD1: JMP ILCMND ;Go give illegal command error .SBTTL CASE - Process /I CASE:: TST R0 ;Got a value? BEQ FLAGIT ;Branch if not. Process option flag bit CMP R0,GEN$ ; CASE:GEN ? BEQ FLAGIT ;branch if so -> same as CASE with no val CMP R0,EXA$ ; CASE:EXA ? BEQ CLEAR1 ; branch if so, otherwise invalid value JMP ILCMND ;Go give illegal command error GEN$: .RAD50 /GEN/ EXA$: .RAD50 /EXA/ .SBTTL CLEAR - Process /T/N CLEAR:: TST R0 ;Got a value? BNE ILCMD1 ;Branch if so. Error CLEAR1: BIC (R1)+,$FLAGS ;Clear the flag BR EXCLCK ;Go check for mutual exclusion .SBTTL FLAGIT - Process option flag bits FLAGIT:: BIS (R1)+,$FLAGS ;Set the bit for this option EXCLCK: BIT @R1,$FLAGS ;Is there a mutual exclusion? BNE ILCMD1 ;Branch if so RET: RETURN .ENDC ;EQ STRIP$ ;CG01- .SBTTL $MAIN - Main loop of file comparison ;+ ; ; $MAIN ; THIS ROUTINE IS CALLED WHEN ALL HAS BEEN SET UP TO CONTROL ; THE COMPARISON PROCESS. THE FIRST PART, BELOW, SIMPLY ; COMPARES LINES FROM EACH FILE, LOOPING UNTIL IT EITHER FINDS ; A MISMATCH OR IT SEES THAT BOTH FILES HAVE REACHED END-OF-FILE, ; INDICATED BY $OPNFL BEING SET TO ZERO. NORMALLY, GETTING THE ; NEXT LINE MEANS READING A LINE FROM THE FILE, BUT AFTER A ; MISMATCH THERE MAY BE LINES LEFT WHICH WERE READ AHEAD AND ; NOT PART OF THE MISMATCH WHICH REMAIN TO BE USED UP. THIS ; IS ALL LOOKED AFTER BY $GNLIN; THIS SECTION NEITHER KNOWS ; NOR CARES WHERE THE LINES COME FROM ; ;- $MAIN:: SAVREG ; KEEP TIDY LOOP: MOV #$SDB1,R1 ; DO THE FIRST FILE FIRST CALL $GNLIN ; GET THE NEXT LINE CALL $DISMS ; DISMISS ALL PREVIOUS LINES .IF EQ STRIP$ ;CG01+ MOV #$SDB2,R1 ; REPEAT THIS PROCESS FOR THE OTHER FILE CALL $GNLIN CALL $DISMS .IFTF ;EQ STRIP$ MOV #$SDB1,R1 ; GET SDB FOR FIRST FILE AGAIN MOV S.CUR(R1),R1 ; GET THE CURRENT LINE .IFT ;EQ STRIP$ MOV #$SDB2,R0 ; REPEAT FOR SECOND FILE MOV S.CUR(R0),R0 ; CALL $CMPAR ; COMPARE THE TWO LINES BCS MISMCH ; J IF NOT THE SAME BIT #FL.CB,$FLAGS ; IN CHANGE-BAR MODE? BEQ 1$ ; J IF NOT .IFTF ;EQ STRIP$ MOV R1,-(SP) ; SAVE LINE POINTER CLR R1 ; SHOW CHANGE BAR NOT WANTED MOV #$LSTBF,R5 ; POINT TO LIST BUFFER CALL $PRINT ; PRINT THE LINE MOV (SP)+,R1 ; GET LINE POINTER BACK 1$: BITB #LF.EOF,L.FB(R1) ; FIRST FILE AT EOF? BEQ LOOP ; LOOP IF NOT .IFT ;EQ STRIP$ BITB #LF.EOF,L.FB(R0) ; SECOND FILE AT EOF? BEQ LOOP ; LOOP IF NOT .ENDC ;EQ STRIP$ ;CG01- RETURN ; ELSE GO AWAY .SBTTL MISMCH - Look for a match after a mismatch .IF EQ STRIP$ ;CG01+ ;+ ; ; MISMCH ; WE COME HERE WHEN THE MAIN LOOP ABOVE FINDS A MISMATCH. FOR ; EACH FILE, WE READ ONE LINE AND COMPARE IT WITH EVERY LINE ; READ SO FAR OF THE OTHER LINE; IF WE FIND NO MATCH, WE DO ; THE SAME FOR THE OTHER FILE. (THIS MAY BE MODIFIED IF THE ; USER HAS INDICATED THAT ONE FILE IS MUCH LONGER THAN THE ; OTHER, TO CUT DOWN THE RISK OF RUNNING OUT OF SPACE). ; WHEN WE DO FIND A MATCH (WHICH WE MUST BECAUSE THE NEXT-LINE ; READER ENSURES THAT EVERY FILE IS EFFECTIVELY TERMINATED BY ; AN INFINITE NUMBER OF BLANK LINES), WE MUST EXAMINE THE ; NUMBER OF FOLLOWING LINES SPECIFIED BY THE USER TO MAKE ; SURE THAT IT IS A REAL MATCH; IF IT IS NOT, WE JUST CARRY ; ON WHERE WE LEFT OFF, BUT OTHERWISE WE GO TO 'FOUND' ; TO CLEAN UP ; ;- .ENABL LSB MISMCH:: MOV #$SDB1,R1 ;Point to the SDB for file #1 MOV #$SDB2,R0 ;Point to the SDB for file #2 MOV S.CUR(R0),S.POS(R0) ; REMEMBER HOW FAR WE'D GOT 1$: MOVB S.CNT(R1),R4 ; GET NUMBER OF LINES TO READ FROM THIS FILE 2$: CALL $GNLIN ; GET THE NEXT LINE MOV S.CUR(R1),S.POS(R1) ; REMEMBER HOW FAR WE'D GOT HERE TOO MOV S.ALT(R1),R2 ; GET THE OTHER SDB MOV R1,R3 ; REMEMBER FOR CURRENT FILE MOV S.TOP(R2),R1 ; GET FIRST LINE OF OTHER FILE MOV R1,S.CUR(R2) ; MAKE IT THE CURRENT LINE 3$: CALL $CMPAR ; COMPARE THE TWO LINES BCC MATCH ; J IF A MATCH SEEN 4$: CMP R1,S.POS(R2) ; AT THE END OF THE OTHER FILE? BEQ 5$ ; J IF SO MOV R0,-(SP) ; SAVE R0 MOV R2,R1 ; COPY SDB ADDRESS CALL $GNLIN ; GET NEXT LINE TO COMPARE MOV R0,R1 ; COPY ITS ADDRESS MOV (SP)+,R0 ; AND RESTORE R0 BR 3$ ; LOOP 5$: MOV R3,R1 ; GET SDB POINTER BACK SOB R4,2$ ; LOOP FOR THIS FILE MOV R2,R1 ; NO MATCH WITH THIS LINE, SWITCH TO OTHER BR 1$ ; AND LOOP MATCH:: TSTB L.LEN(R0) ; MATCH OF BLANK LINES? ;001 BEQ 4$ ; YES, DON'T USE THAT TO RESYNCH ;001 MOV S.CUR(R3),S.MAT(R3) ; REMEMBER START OF MATCH MOV R1,S.MAT(R2) ; FOR BOTH FILES MOV R2,MATCHR ; AND REMEMBER WHICH WAS 'MASTER' FILE MOVB $LTMCH,R5 ; GET NUMBER TO MATCH (-1, SO 0=>1) BEQ 8$ ; MATCH, SKIP ;013 6$: MOV #$SDB1,R1 ; GET FILE 1 SDB CALL $GNLIN ; GET NEXT LINE FOR EACH FILE MOV R0,-(SP) ; REMEMBER LINE ADR MOV #$SDB2,R1 ; GET SDB FOR OTHER FILE CALL $GNLIN ; AND GET NEXT LINE FOR THAT TOO MOV R0,R1 ; COPY LINE ADR FOR COMPARISON MOV (SP)+,R0 ; AND GET OTHER FILE'S LINE CALL $CMPAR ; COMPARE THEM BCC 7$ ; J IF MATCHED MOV MATCHR,R2 ; ELSE SET UP TO CARRY ON WHERE WE LEFT OFF MOV S.MAT(R2),R1 ; RESTORE CURRENT LINE TO MATCH MOV R1,S.CUR(R2) ; AND MAKE IT CURRENT MOV S.ALT(R2),R3 ; GET OTHER SDB MOV S.MAT(R3),R0 ; SELECT LINE MOV R0,S.CUR(R3) ; AND MAKE IT CURRENT BR 4$ ; GO BACK TO WHERE WE LEFT OFF 7$: TSTB L.LEN(R0) ; IS THIS A BLANK LINE? ;001 BEQ 6$ ; YES, DON'T COUNT IT DOWN IN MATCHING ;001 SOB R5,6$ ; LOOP FOR COUNT ;001 8$: CALL FOUND ; PRINT LIST FILE ;013 BIT #FL.SLP,$FLAGS ; PATCH FILE WANTED? ;013 BEQ 9$ ; IF NO, BRANCH ;013 CALL PATFND ; PRINT PATCH FILE ;013 9$: JMP LOOP ; GET OUT ;013 .DSABL LSB ;**-1 .SBTTL FOUND - Found a complete match ;+ ; ; FOUND ; COME HERE WHEN WE HAVE MATCHED THE REQUIRED NUMBER OF LINES. ; ALL WE HAVE TO DO IS PRINT THE MISMATCH IN ANY REQUIRED ; FORM, THEN GO BACK TO THE MAIN LOOP TO CARRY ON. NOTE THAT ; THE LINES OF THE MISMATCH WILL BE RETURNED TO THE SPACE ; ALLOCATOR (BY A CALL TO $DISMS) THERE, SO WE HAVE NO NEED TO ; DO SO. ; ;- FOUND:: INC $DIFCT ; BUMP THE NUMBER OF DIFFERENCES BIT #FL.CB,$FLAGS ; CHANGE BAR PRINTING? BEQ 7$ ; J IF NOT MOV #$SDB2,R2 ; ELSE SDB FOR NEW FILE CLR R1 ;Need a MOVB BISB CBICHR,R1 ;Show change bar wanted MOV S.TOP(R2),R0 ; PRINT FROM THE TOP CMP R0,S.MAT(R2) ;Doing an insertion? BNE 2$ ;Branch if so 1$: MOVB CBDCHR,R1 ;Else indicate deletion 2$: MOV #$LSTBF,R5 ;Point to output file for $PRINT CALL $PRINT ; ELSE PRINT WITH CHANGE BARS CMP R0,S.MAT(R2) ; REACHED THE MATCHING LINES YET? BEQ 4$ ; J IF SO MOV L.NL(R0),R0 ; GET NEXT LINE TO PRINT CMP R0,S.MAT(R2) ;Reached matching lines yet? BNE 2$ ;Branch if not MOV #$SDB1,R3 ;Point to "old" file SDB MOV S.TOP(R3),R1 ;Point to start of mismatch CMP R1,S.MAT(R3) ;Any deletions? BEQ 3$ ;Branch if not MOV L.LNO(R1),R1 ;Get line number MOV S.MAT(R3),R5 ;Point to start of new match MOV L.LNO(R5),R5 ;Get it's line number DEC R5 ;Down by one BEQ 3$ ;Branch if insertion at beginning CMP R1,R5 ;Really just a changed line? BNE 1$ ;Branch if not. Put in "bullet" 3$: CLR R1 ;No more change bars BR 2$ ;Go print the line 4$: CLR R1 ; SHOW NO MORE CHANGE BARS 5$: CMP R0,S.CUR(R2) ; DONE YET? BNE 6$ ; IF NE NO JMP 12$ ; ELSE GET OUT 6$: MOV L.NL(R0),R0 ; NO--GET NEXT LINE MOV #$LSTBF,R5 ;Point to output file for $PRINT CALL $PRINT ; AND PRINT IT BR 5$ ; LOOP FOR MORE 7$: BIT #FL.DIF,$FLAGS ;Differences wanted? BEQ 12$ ;Branch if not. Done. MOV #$SDB1,R2 ; GET FIRST FILE MOV #$LSTFD,SAVFDB ;Get print FDB PUTLIN #STAR,#STARL ; PRINT A LONG LINE OF STARS INCB S.PGFL(R2) ;Flag that we want the page number printed 8$: MOV S.TOP(R2),R0 ; GET START OF MISMATCH CLR R1 ; SHOW NO CHANGE BARS 9$: MOV #$LSTBF,R5 ;Point to output file for $PRINT CALL $PRINT ; NO, SO PRINT CLRB S.PGFL(R2) ;Turn off page number printing CMP R0,S.MAT(R2) ; JUST PRINTED FIRST MATCHING LINE? BEQ 11$ ; J IF SO, DONE PRINTING MOV L.NL(R0),R3 ;Get the next printable line CMP L.PAG(R0),L.PAG(R3) ;Are they on different pages? BEQ 10$ ;Branch if not INCB S.PGFL(R2) ;Turn on page number printing 10$: MOV R3,R0 ;Copy pointer to next printable line BR 9$ ; AND LOOP 11$: MOV S.ALT(R2),R2 ; GET THE OTHER SDB CMP R2,#$SDB1 ; BACK WHERE WE CAME IN? BEQ 12$ ; J IF SO MOV #$LSTFD,SAVFDB ;Point to print buf for $PRINT PUTLIN #STAR,#STARS ; PRINT A SHORT LINE OF STARS INCB S.PGFL(R2) ;Say that we want the page number printed BR 8$ ; LOOP 12$: RETURN PATFND:: MOV #$SDB1,R2 ; GET 'OLD' FILE MOV S.TOP(R2),R1 ; GET FIRST LINE OF MISMATCH MOV #$PATBF,R0 ; GET PATCH BUFFER MOVB #'-,(R0)+ ; FIRST A SLIPR WARNING CHARACTER CLR -(SP) ; FLAG THAT WE ARE NOT DELETING CMP R1,S.MAT(R2) ; ANY LINES TO DELETE? BEQ 13$ ; J IF NOT INC (SP) ; FLAG WE ARE DELETING LINES MOV L.LNO(R1),R1 ; GET THE FIRST LINE NUMBER CLR R2 ; SHOW LEAD ZERO SUPPRESSION WANTED CALL $CBDMG ; OUTPUT THE LINE NUMBER MOV #$SDB1,R2 ; GET SDB BACK AGAIN MOVB #',,(R0)+ ; PUT A SEPARATOR MOV S.MAT(R2),R1 ; GET FIRST MATCHING LINE 13$: MOV L.LNO(R1),R1 ; GET ITS LINE NUMBER DEC R1 ; TAKE ONE OFF BEQ 17$ ; J IF ZERO - MUST BE INSERTION AT BEGINNING CLR R2 ; SHOW ZERO SUPPRESSION REQUIRED CALL $CBDMG ; OUTPUT THE SECOND NUMBER MOV #$AUDMG,R3 ; POINT AT AUDIT TRAIL MESSAGE TST @R3 ;Was one specified? BEQ 16$ ;Branch if none specified or null MOVB #',,(R0)+ ; YES--MOVE A COMMA INTO BUFFER TST (SP) ; ARE WE DELETING? BNE 14$ ; IF NE YES MOVB #',,(R0)+ ; NO--INSERT--WE NEED ANOTHER COMMA 14$: MOVB #'/,(R0)+ ; START THE AUDIT TRAIL MOVB #SEMI,(R0)+ ; ...LEADING SEMI-COLON 15$: MOVB (R3)+,(R0)+ ; MOVE IT INTO THE BUFFER BNE 15$ ; WATCH FOR THE NULL BYTE MOVB #'/,-1(R0) ; OVERWRITE THE NULL WITH THE FINAL SLASH 16$: MOV #$PATBF,R1 ; GET PATCH BUFFER ADDRESS SUB R1,R0 ; COMPUTE LINE LENGTH MOV R0,R2 ; SAVE LENGTH FROM FCS... MOV #$PATFD,SAVFDB ; POINT TO PATCH FDB PUTLIN R1,R2 ; OUTPUT THE SLIPR COMMAND LINE 17$: TST (SP)+ ; KEEP THE STACK HONEST MOV #$SDB2,R2 ; GET 'NEW' FILE CLR R1 ; SHOW CHANGE BARS NOT WANTED MOV S.TOP(R2),R0 ; GET FIRST LINE TO INSERT 18$: CMP R0,S.MAT(R2) ; ANY MORE MISMATCH TO OUTPUT? BEQ 19$ ; J IF NOT INC PRSLP ; SAY TO PRINT THE SLP FILE MOV #$PATBF,R5 ; POINT TO PATCH BUF FOR $PRINT CALL $PRINT ; ELSE OUTPUT IT CLR PRSLP ; FINISHED PRINTING SLP FILE MOV L.NL(R0),R0 ; GET NEXT LINE BR 18$ ; AND LOOP 19$: RETURN .ENDC ;EQ STRIP$ ;CG01- .SBTTL $GNLIN - Get next line to compare ;+ ; ; $GNLIN ; THIS ROUTINE IS CALLED TO FIND THE NEXT LINE TO USE IN A ; COMPARISON. IF THERE IS ALREADY A NEXT LINE, IT SIMPLY ; ADVANCES S.CUR AND RETURNS A POINTER TO IT, OTHERWISE ; IT READS A LINE, ALLOCATES CORE FOR IT THEN SETS UP ; THE POINTERS ACCORDINGLY. IF A LINE IS NOT ELIGIBLE ; FOR COMPARISON (LF.IGN SET), IT IS IGNORED AND ANOTHER ; LINE IS SOUGHT. ; ; INPUTS: ; ; R1 FILE CONTROL BLOCK FOR FILE ; S.CUR(R1) POINTER TO CURRENT LINE ; ; OUTPUTS: ; ; R0 POINTER TO NEXT LINE ; S.CUR(R1) ALSO RESET AS POINTER TO NEXT LINE ; ;- $GNLIN:: SAVREG ; KEEP TIDY MOV S.CUR(R1),R0 ; GET CURRENT LINE BEQ 2$ ;Branch if no current line 1$: MOV L.NL(R0),R0 ; ANY NEXT LINE? BNE 3$ ; J IF SO 2$: CALL $RDLIN ; ELSE READ A LINE AND PREPROCESS IT 3$: BITB #LF.IGN,L.FB(R0) ; IS THIS AN IGNORABLE LINE? BNE 1$ ; J IF SO, GET ANOTHER MOV R0,S$R0(SP) ; SET UP CALLER'S R0 MOV R0,S.CUR(R1) ; MAKE NEW LINE THE CURRENT ONE RETURN ; AND GO AWAY .SBTTL $RDLIN - Read a line and store it ;+ ; ; $RDLIN ; THIS ROUTINE IS CALLED TO GET THE NEXT LINE FROM AN INPUT ; FILE, PRE-PROCESS IT AND STORE IT, LINKED IN TO THE NEW ; DATA STRUCTURES. ; ; IF EOF IS SEEN ON THE FILE, A LINKAGE IS CREATED TO THE ; 'END-OF-FILE' RECORD, WHICH HAS A CIRCULAR NEXT-LINE POINTER ; SO THAT EVERY FILE IS EFFECTIVELY TERMINATED BY AN INFINITE ; NUMBER OF BLANK LINES ; ; INPUTS: ; ; R1 SDB FOR THE FILE TO HAVE A LINE READ ; ; OUTPUTS: ; ; R0 POINTER TO LINE HEADER ; ;- .ENABL LSB $RDLIN:: SAVREG ; KEEP IT CLEAN CLR R4 ; CLEAR LINE NUMBER INCREMENT 1$: GET$S S.FDBP(R1) ; GET A RECORD BCC 5$ ; J IF NO ERROR CMPB #FE.EOF,F.ERR(R0) ;Error. Was it EOF? BEQ 2$ ;Branch if so MOV R0,R2 ;Copy the pointer to the FDB ;+ ;ERROR .ERR #ERAREA,F.ERR(R2),LEVEL=FATAL,RETURN=NO,FILE=F.OPNM(R2) ;- 2$: MOV S.EOF(R1),R0 ;GET ADDRESS OF EOF RECORD MOV S.NEW(R1),R2 ; GET ADDRESS OF LAST LINE BEQ 3$ ;J IF NO PREVIOUS LINE (MUST BE NULL FILE) MOV R0,L.NL(R2) ; SET UP NEXT LINE POINTER BR 4$ ;SKIP EOF STUFF 3$: MOV R0,S.TOP(R1) ;MARK THIS AS OLDEST (ONLY) LINE 4$: INC R4 ;BUMP LINE NUMBER INCREMENT ADD R4,S.LNO(R1) ;UPDATE IN SDB MOV S.LNO(R1),L.LNO(R0) ;AND COPY INTO EOF RECORD MOV R0,S.NEW(R1) ;REMEMBER THAT THIS IS NEWEST RECORD MOV R0,S$R0(SP) ; TELL THE CALLER BR 18$ ; AND GO AWAY 5$: INC R4 ; BUMP THE LINE NUMBER MOV F.NRBD+2(R0),R2 ; GET BUFFER ADDRESS MOV F.NRBD(R0),R1 ; GET LENGTH OF RECORD .IF EQ STRIP$ 6$: CMP #1,R1 ;Only one character? .IFF ;EQ STRIP$ 6$: MOV S$R1(SP),R0 ;Get pointer to SDB CMP #1,R1 ;Only one character? .IFTF ;EQ STRIP$ BNE 7$ ;Branch if not CMPB #FF,@R2 ;Is it a form feed? BNE 7$ ;Branch if not .IFT ;EQ STRIP$ MOV S$R1(SP),R0 ;Get pointer to SDB .IFTF ;EQ STRIP$ INC S.PAG(R0) ;Bump the page count 7$: MOV R2,BUFADR ; SAVE BUFFER ADDRESS .IFT ;EQ STRIP$ BIT #FL.COM!FL.MBS!FL.TBS,$FLAGS ;Need to preprocess the line? BEQ 8$ ;Branch if not... Save time .IFF ;EQ STRIP$ CMP #1,S.PAG(R0) ;Is this the first page? BEQ 8$ ;Branch if so. Don't strip anything .IFTF ;EQ STRIP$ MOV #EDTBUF,R0 ; ELSE GET ADDRESS OF MODIFICATION BUFFER CALL $PREPR ; PRE-PROCESS THE LINE SUB BUFADR,R2 ; FIND LENGTH OF NEW LINE MOV R2,R1 ; AND MOVE TO RIGHT REGISTER FOR LATER SUB #EDTBUF,R0 ; FIND LENGTH OF MODIFICATIONS BR 9$ ; AND SKIP 8$: MOVB #255.,EDTBUF ; TERMINATE MODIFICATION BUFFER MOV #1,R0 ; AND SET LENGTH TO ONE BYTE 9$: MOV R1,LENGTH ; REMEMBER THE LENGTH ADD #L.HDSZ,R1 ; ADD HEADER LENGTH ADD R0,R1 ; ADD ALLOWANCE FOR MODIFICATIONS CALL $GTCOR ; ALLOCATE SPACE BCC 10$ ; J IF GOT SOME ;+ ;ERROR .IFT ;EQ STRIP$ .ERR #ERAREA,#TMD,LEVEL=FATAL,RETURN=NO .IFF ;EQ STRIP$ .ERR #ERAREA,#FE.SYS,LEVEL=FATAL,RETURN=NO .IFTF ;EQ STRIP$ ;- 10$: MOV S$R1(SP),R3 ; GET SDB BACK ADD R4,S.LNO(R3) ; INCREMENT THE LINE NUMBER MOV S.LNO(R3),L.LNO(R5) ; SET UP IN NEW RECORD MOV R1,L.SIZ(R5) ; REMEMBER LENGTH OF BLOCK MOV S.NEW(R3),R1 ; GET ADDRESS OF PREVIOUS LINE BEQ 11$ ; J IF NO LAST LINE MOV R5,L.NL(R1) ; AND SET UP NEXT LINE POINTER BR 12$ ; SKIP 11$: MOV R5,S.TOP(R3) ; SET UP FIRST LINE IF NOT ONE ALREADY 12$: MOV R5,S.NEW(R3) ; SET UP NEW LAST LINE MOV S.PAG(R3),L.PAG(R5) ;Copy the page # 13$: CLR R4 ; READY FOR BYTE MOVE BISB LENGTH,R4 ; REMEMBER RECORD LENGTH CLR R3 ; WILL BE FLAGS BYTE - ZERO INITIALLY MOVB R4,L.LEN(R5) ; SAVE IN RECORD BNE 14$ ; J IF SOMETHING LEFT .IFT ;EQ STRIP$ BIT #FL.BL,$FLAGS ; BLANK LINES WANTED? BNE 14$ ; J IF SO, DON'T IGNORE THIS .IFF ;EQ STRIP$ CMP #1,L.PAG(R5) ;On the first page? BEQ 14$ ;Branch if so. Don't strip it. .IFTF ;EQ STRIP$ MOV #LF.IGN,R3 ; ELSE SET TO IGNORE .ENDC ;EQ STRIP$ ;CG01- 14$: MOVB R3,L.FB(R5) ; SET UP FLAGS BYTE CLR L.NL(R5) ; NO NEXT LINE MOV R5,S$R0(SP) ; TELL THE CALLER ADD #L.TXT,R5 ; POINT TO TEXT PART OF RECORD MOV BUFADR,R2 ; GET ADR OF BUFFER TST R4 ; ANY BYTES TO MOVE? BEQ 16$ ; J IF NOT 15$: MOVB (R2)+,(R5)+ ; COPY A BYTE SOB R4,15$ ; LOOP 16$: MOV #EDTBUF,R2 ; GET ADDRESS OF EDIT BUFFER 17$: MOVB (R2)+,(R5)+ ; COPY THE CHANGES SOB R0,17$ ; UNTIL DONE 18$: RETURN ; GO AWAY .DSABL LSB .SBTTL $IDLIN - Print the file identification line ;+ ; ; $IDLIN ; This routine is used to convert the file ID's to ASCII so that they can be ; printed at the top of the listing. ; ; Inputs: ; R2 -> The SDB for the file ; Outputs: ; R0 Modified ; R1 Length of string ; R3 -> String ; $LSTBF contains string ; ;- $IDLIN:: MOV #$LSTBF,R1 ;Point to the listing buffer MOV R1,R3 ;Save it MOV S.FNUM(R2),(R1)+ ;Put in the stream number MOVB #SPACE,(R1)+ ; and a space MOV S.FDBP(R2),R0 ;Point at the FDB MOV F.OPNM(R0),R0 ;Point to the file name CALL $FNASC ;Convert it to ASCII SUB R3,R1 ;Get the length of the line RETURN .SBTTL $PRINT - Print a line with trimmings ;+ ; ; $PRINT ; GIVEN A POINTER TO A LINE DESCRIPTOR, PRINT THE LINE. ; THE EXACT FORMAT DEPENDS ON VARIOUS FLAGS: ; ; FL.LN PRINT A LINE NUMBER IN THE LEFT MARGIN ; FL.CB PRINT CHANGE BARS IF REQUIRED ; FL.SLP CHECK FOR LINE BEGINNING WITH SLIPR WARNING CHARACTER, ; PREFIX WITH '<' IF SO ; ; INPUTS: ; ; R0 POINTER TO LINE DESCRIPTOR ; R1 =0 IF CHANGE BARS NOT WANTED, <>0 IF THEY ARE ; R2 POINTER TO STREAM DESCRIPTOR ; R5 OUTPUT BUFFER TO USE ($LSTBF OR $PATBF) ; ;- .ENABL LSB $PRINT:: SAVREG ; KEEP TIDY BITB #LF.EOF,L.FB(R0) ; IS IT THE EOF LINE? BNE 15$ ;IGNORE IF SO .IF NE SRCPT$!STRIP$ BITB #LF.IGN,L.FB(R0) ;Should we ignore this line? BNE 15$ ;Branch if so .ENDC ;NE SRCPT$!STRIP$ 1$: MOV R5,SAVBUF ; SAVE BUFFER START MOV #$LSTFD,SAVFDB ;Default to list FDB .IF EQ STRIP$ ;CG01+ TST PRSLP ;Printing the SLP file? BNE 3$ ;If yes, branch BIT #FL.LN,$FLAGS ; LINE NUMBER? BEQ 2$ ; J IF NOT MOV S.FNUM(R2),(R5)+ ;Put in the stream id number TSTB S.PGFL(R2) ;Should we print the page number? BEQ 2$ ;Branch if not MOV L.PAG(R0),R1 ;Get the page number to print MOV R5,R0 ;Copy buffer address CLR R2 ;Flag zero suppression CALL $CBDMG ;Print the number MOV R0,R5 ;Restore the updated buffer pointer MOV S$R0(SP),R0 ; GET LINE POINTER BACK 2$: BIT #FL.CB,$FLAGS ; CHANGE BARS-TYPE COMPARISON? BEQ 3$ ; J IF NOT MOV #SPACE*400+SPACE,(R5)+ ;Put in some spaces MOV #SPACE*400+SPACE,(R5)+ ; MOVB S$R1(SP),(R5)+ ;Pick up the change bar character BNE 3$ ;Branch if it's there to print TSTB -(R5) ;If not, fix buffer pointer .IFTF ;EQ STRIP$ 3$: MOV S$R0(SP),R0 ; GET LINE POINTER AGAIN CLR R1 ; PREPARE TO PICK UP LENGTH BISB L.LEN(R0),R1 ; GET LENGTH IN BYTES ADD #L.TXT,R0 ; POINT PAST HEADER .IFT ;EQ STRIP$ BIT #FL.FF,$FLAGS ;Should we output form feeds? BNE 5$ ;Branch if yes DEC R1 ;One character? BNE 4$ ;Branch if not. Can't be a form feed CMPB #FF,@R0 ;Is it? BEQ 5$ ;Branch if so. Leave character count at 0 4$: INC R1 ;Fix the character count 5$: CMP R5,SAVBUF ;Do we need to space over? BEQ 6$ ;Branch if not MOVB #HT,(R5)+ ;Go to the next tab stop .IFTF ;EQ STRIP$ 6$: MOV R0,R2 ; COPY RECORD ADDRESS ADD R1,R2 ; AND POINT PAST TEXT TO MODIFICATION LIST CLR R3 ; SET START POSITION IN LINE 7$: CMPB R3,(R2) ; READY FOR NEXT CHANTGE YET? BEQ 8$ ; J IF SO TST R1 ; ANY BYTES LEFT BEQ 10$ ; J IF NOT MOVB (R0)+,(R5)+ ; ELSE COPY A BYTE OF TEXT INC R3 ; BUMP POSITION DEC R1 ; REDUCE COUNT BR 7$ ; LOOP 8$: INC R2 ; SKIP POSITION INDICATOR CLR -(SP) ; MAKE ROOM FOR # BYTES TO SKIP MOVB (R2)+,(SP) ; GET ONTO STACK ADD (SP),R0 ; ADD TO TEXT POINTER ADD (SP),R3 ; AND TO POSITION COUNTER CLR R4 ; READY FOR BYTE MOVE... BISB (R2)+,R4 ; GET LENGTH OF MODIFICATION STRING .IFT ;EQ STRIP$ 9$: MOVB (R2)+,(R5)+ ; COPY A BYTE OF THE MODIFICATION .IFF ;EQ STRIP$ 9$: TSTB (R2)+ ;Skip a byte of the modification .IFTF ;EQ STRIP$ SOB R4,9$ ; LOOP SUB (SP)+,R1 ; SUBTRACT SKIP LENGTH FROM COUNT BR 7$ ; LOOP .IFT ;EQ STRIP$ 10$: TST PRSLP ; PRINTING THE SLP FILE? BEQ 14$ ; J IF NOT MOV #$PATFD,SAVFDB ; POINT TO PATCH FDB MOV #SLPTBL,R0 ; GET TABLE OF WARNING CHARACTERS 11$: TSTB @R0 ;Anything left? BEQ 14$ ;Branch if not. Not a SLP command CMPB $PATBF,(R0)+ ;Is it this character? BNE 11$ ;Branch if not. Try again 12$: MOV R5,R0 ;COPY END OF BUFFER ADR INC R5 ;WILL BE ADDING A BYTE... MOV R5,R1 ;NOW COPY NEW END 13$: MOVB -(R0),-(R1) ;COPY A BYTE CMP R0,#$PATBF ;AT START OF LINE YET? BHI 13$ ;LOOP IF NOT MOVB #'<,-(R1) ;PUT IN THE MARKER .IFF ;EQ STRIP$ 10$: .IFTF ;EQ STRIP$ 14$: SUB SAVBUF,R5 ; GET LINE LENGTH PUTLIN SAVBUF,R5 ; PRINT THE LINE 15$: RETURN ; GO AWAY .DSABL LSB .ENDC ;EQ STRIP$ ;CG01- .SBTTL $DISMS - Dismiss stored lines ;+ ; ; $DISMS ; THIS ROUTINE IS CALLED WHEN A MATCH HAS BEEN FOUND OR WHILE ; COMPARING MATCHING LINES TO DISMISS ALL THE STORED LINES ; WHICH ARE NO LONGER NECESSARY. IT SIMPLY PASSES DOWN THE ; CHAIN RETURNING ALL THE BLOCKS TO THE FREE-LIST. ; EXCEPTIONALLY, A BLOCK MAY BE MARKED 'PERMANENT' (LF.PRM SET), ; IN WHICH CASE IT IS NOT RETURNED. THIS WILL HAPPEN IS THE ; BLOCK IS ONE OF THE STATIC ONES SUCH AS HEADER BLOCKS AND THE ; END OF FILE RECORD. ; ; INPUTS: ; ; R0 POINTER TO FIRST LINE NOT TO RETURN ; R1 SDB FOR THIS FILE ; ;- $DISMS:: SAVREG ; KEEP CLEAN MOV R1,R3 ; SAVE SDB 1$: MOV S.TOP(R3),R2 ; GET ADDRESS OF FIRST RECORD CMP R2,S$R0(SP) ; STOP HERE? BEQ 3$ ; J IF SO MOV L.SIZ(R2),R1 ; GET SIZE IN BYTES MOV L.NL(R2),R4 ; GET NEXT LINE ADDRESS BITB #LF.PRM,L.FB(R2) ; PERMANENT RECORD? BNE 2$ ; J IF SO MOV #$FRHD,R0 ; GET ADDRESS OF FREELIST CALL $RLCB ; ELSE RELEASE THE MEMORY 2$: MOV R4,S.TOP(R3) ; RESET TOP POINTER BR 1$ ; AND LOOP 3$: RETURN ; GO AWAY .SBTTL $CMPAR - Compare two lines .IF EQ STRIP$ ;CG01+ ;+ ; ; $CMPAR ; THIS ROUTINE IS CALLED TO COMPARE TWO LINES. ANY BLANK ; COMPRESSION, ETC, WILL ALREADY HAVE BEEN DONE, SO ALL THIS ; ROUTINE NEEDS TO DO IS CHECK THAT THE LINES ARE THE SAME ; LENGTH (IF THEY ARE NOT, THEY CLEARLY CANNOT BE THE SAME), ; THEN COMPARE EACH BYTE IN TURN. ; ; INPUTS: ; ; R0 POINTER TO FIRST LINE ; R1 POINTER TO SECOND LINE ; ; OUPUTS: ; ; C SET IF THE LINES ARE NOT IDENTICAL ; ;- $CMPAR:: SAVREG ; KEEP CLEAN CMPB L.LEN(R0),L.LEN(R1) ; SAME LENGTH? BNE 3$ ; NO, SO CAN'T BE THE SAME CLR R2 ; READY FOR BYTE MOVE BISB L.LEN(R0),R2 ; GET THEIR LENGTH AS A COUNTER BEQ 2$ ; J IF NO BYTES THERE ADD #L.TXT,R0 ; POINT TO TEXT OF LINE ADD #L.TXT,R1 ; AND THE OTHER BIT #FL.ICA,$FLAGS ; IGNORE CHARACTER CASE? ;IHZ BEQ 1$ ; B IF YES ;IHZ 10$: MOVB (R0)+,TMPCH1 ; TEMPORARY SAVE FIRST CHARACTER ;IHZ CMPB TMPCH1,#ACGRAV ; IN LOWER CASE, TOP RANGE? ;IHZ BLE 20$ ; B IF NOT ;IHZ CMPB TMPCH1,#LBRACE ; IN LOWER CASE, BOTTOM RANGE? ;IHZ BGE 20$ ; B IF NOT ;IHZ BICB #LOWCAS,TMPCH1 ; CLEAR LOWER CASE BIT ;IHZ 20$: MOVB (R1)+,TMPCH2 ; TEMPORARY SAVE SECOND CHARACTER ;IHZ CMPB TMPCH2,#140 ; IN LOWER CASE, TOP RANGE? ;IHZ BLE 30$ ; B IF NOT ;IHZ CMPB TMPCH2,#173 ; IN LOWER CASE, BOTTOM RANGE? ;IHZ BGE 30$ ; B IF NOT ;IHZ BICB #40,TMPCH2 ; CLEAR LOWER CASE BIT ;IHZ 30$: CMPB TMPCH1,TMPCH2 ; COMPARE A BYTE ;IHZ BNE 3$ ; B IF NOT SAME ;IHZ SOB R2,10$ ; LOOP IF NOT DONE ;IHZ BR 2$ ; SUCCESS ;IHZ 1$: CMPB (R0)+,(R1)+ ; COMPARE A BYTE BNE 3$ ; J IF NOT THE SAME, LINES AREN'T EITHER SOB R2,1$ ; LOOP IF NOT DONE 2$: TST (PC)+ ;Indicate success 3$: SEC ;Indicate failure RETURN .ENDC ;EQ STRIP$ ;CG01- .SBTTL $PREPR - Preprocess a line ;+ ; ; $PREPR ; THIS ROUTINE IS CALLED TO PROCESS A LINE WHEN IT HAS JUST BEEN READ ; IN TO DELETE FROM THE LINE WHICH WILL BE COMPARED THOSE THINGS ; WHICH THE USER HAS ASKED TO IGNORE, I.E. TRAILING BLANKS, MULTIPLE ; BLANKS, AND COMMENTS. IT IS NOT CALLED IF NO INTRA-RECORD CHANGES ; (I.E. ONE OR MORE OF THE ABOVE) ARE REQUIRED. THE SECTIONS WHICH ARE ; DELETED FROM THE COMPARISON LINE ARE PLACED IN A BUFFER SUPPLIED ; BY THE CALLER IN THE FORM: ; ; BYTE 1 BYTE NUMBER IN LINE (STARTING AT 0) AT WHICH CHANGE TAKES ; PLACE ; BYTE 2 LENGTH OF SECTION TO BE REPLACED IN COMPARE-LINE ; BYTE 3 LENGTH OF TEXT WHICH IS TO REPLACE IT ; BYTES 4... REPLACMENT TEXT ; ; THIS LIST IS TERMINATED BY A BYTE WITH VALUE 255., WHICH CAN NEVER ; BE A VALID CHARACTER POSITION SINCE THE INPUT LINE LENGTH IS LIMITED ; TO 132. BY THE BUFFER SIZES. ; ; INPUTS: ; R0 POINTER TO BUFFER TO HOLD MODIFICATION STRINGS ; R1 LENGTH OF LINE ; R2 POINTER TO LINE ; ; OUTPUTS: ; R0 FIRST FREE BYTE IN MODIFICATION BUFFER ; R2 FIRST FREE BYTE IN REDUCED LINE ; ; NOTE THAT THE LINE IS REDUCED IN SITU, NOT COPIED, BUT IT WILL ; NEVER BECOME LONGER IN THE PROCESS. ; ;- $PREPR:: SAVREG ; KEEP CLEAN MOV R2,R3 ; COPY STRING ADDRESS TO 'PUT' POINTER MOV R2,PREBUF ; AND STORE ADDRESS OF STRING TST R1 ; ANY CHARACTERS IN LINE? BEQ 3$ ;Branch if not. Get out. 1$: CMPB (R2),#HT ; IS THE CHAR A TAB? BEQ 7$ ; J IF SO CMPB (R2),#SPACE ; SPACE? BEQ 7$ ; J IF SO .IF EQ STRIP$ ;CG01+ BIT #FL.COM,$FLAGS ; IGNORING COMMENTS? BEQ 2$ ; J IF NOT .ENDC ;EQ STRIP$ ;CG01- CMPB (R2),#SEMI ; SITTING AT A SEMICOLON BEQ 4$ ; J IF SO 2$: MOVB (R2)+,(R3)+ ; ELSE NOTHING SPECIAL, SO JUST COPY SOB R1,1$ ; LOOP UNTIL DONE 3$: BR 15$ ; J IF DONE ; HERE WE DEAL WITH A COMMENT WHEN WE HAVE BEEN ASKED TO IGNORE ; THEM. THE REST OF THE LINE IS COPIED INTO THE MODIFICATION BUFFER, ; WITH A SUITABLE HEADER, AND THEN WE ARE FINISHED. NOTE THAT THERE ; IS NO NEED TO LOOK FOR SPACES OR TABS IN THE COMMENT SINCE WE ; ARE IGNORING IT ANYWAY. 4$: CMP R3,PREBUF ;At the beginning of the line? BEQ 5$ ;If so, it's a comment... CMPB #SPACE,-1(R2) ;Was the previous character a space? BEQ 5$ ;Branch if so CMPB #HT,-1(R2) ;How about a tab? BNE 2$ ;Branch if not. Don't call it a comment 5$: MOV R3,-(SP) ; SAVE OUTPUT BUFFER POINTER SUB PREBUF,R3 ; CONVERT TO OFFSET IN LINE MOVB R3,(R0)+ ; PUT INTO MOD LIST MOV (SP)+,R3 ; GET POINTER BACK CLRB (R0)+ ;Nothing is replacing string in the comparison MOVB R1,(R0)+ ; LENGTH OF MOD IS LENGTH OF REST OF STRING 6$: MOVB (R2)+,(R0)+ ; COPY REST OF LINE TO MOD BUFFER SOB R1,6$ ; LOOP UNTIL DONE BR 15$ ; J WHEN DONE ; HERE WE HAVE SEEN A BLANK (SPACE OR TAB). CONTINUE SCANNING THE LINE ; UNTIL EITHER THE END OF THE LINE OR A NON-BLANK IS SEEN. WE CANNOT ; KNOW UNTIL WE STOP SCANNING WHETHER THESE ARE TRAILING BLANKS OR ; JUST MULTIPLE BLANKS, SO WE CANNOT TEST UNTIL THEN WHETHER WE ; SHOULD BE IGNORING THEM. IF WE SHOULDN'T, WE COPY THE CHARACTERS ; WE IGNORED INTO THE OUTPUT BUFFER AND CARRY ON, OTHERWISE WE ; PLANT A SINGLE SPACE, FOR MULTIPLE BLANKS ONLY, THEN MAKE AN ; APPROPRIATE ENTRY IN THE MODIFICATION LIST. NOTE THAT AS ; A SPECIAL CASE, MULTIPLE BLANKS WHICH ARE TERMINATED BY A ; SEMICOLON IN 'IGNORE COMMENTS' (FL.COM SET) MODE ARE TREATED ; AS TRAILING BLANKS. 7$: MOV R2,-(SP) ; SAVE 'GET' POINTER MOV R3,-(SP) ; PUSH 'PUT' POINTER SUB PREBUF,R3 ; CONVERT TO POSITION IN LINE MOVB R3,(R0)+ ; STORE IN MOD LIST MOV (SP)+,R3 ; GET ABS POINTER BACK MOV R0,-(SP) ; SAVE MOD LIST POINTER FOR PLUGGING LATER ADD #2,R0 ; AND SKIP LENGTH BYTES 8$: MOVB (R2)+,(R0)+ ; COPY A BYTE INTO MOD LIST DEC R1 ; DONE YET? BEQ 10$ ; J IF SO, MUST BE TRAILING BLANKS CMPB (R2),#HT ; TAB? BEQ 8$ ; J IF SO CMPB (R2),#SPACE ; SPACE? BEQ 8$ ; J IF SO .IF EQ STRIP$ ;CG01+ BIT #FL.COM,$FLAGS ; IGNORING COMMENTS? BEQ 9$ ; J IF NOT .IFTF ;EQ STRIP$ CMPB (R2),#SEMI ; COMMENT? .IFT ;EQ STRIP$ BEQ 10$ ; J IF SO, TREAT AS TRAILING BLANK 9$: BIT #FL.MBS,$FLAGS ; MULTIPLE BLANK SUPPRESSION WANTED? BEQ 12$ ; J IF NOT, DON'T MAKE MODIFICATION CMP R3,PREBUF ;Are we at the beginning of the line? ;CG07 BEQ 105$ ;Branch if so. Remove all leading spaces ;CG07 MOVB #SPACE,(R3)+ ; MOVE A SPACE INTO OUTPUT BUFFER MOV #1,-(SP) ; AND SHOW ONE CHARACTER REPLACEMENT BR 11$ ; SKIP 10$: BIT #FL.TBS,$FLAGS ; TRAILING BLANK SUPPRESSION WANTED? BEQ 12$ ; J IF NOT .IFF ;EQ STRIP$ BNE 12$ ;Branch if not 10$: .ENDC ;EQ STRIP$ ;CG01- 105$: CLR -(SP) ; ELSE SHOW ZERO CHARACTER REPLACEMENT 11$: MOVB (SP)+,@(SP) ; STORE LENGTH OF REPLACMENT IN MOD LIST ENTRY INC (SP) ; POINT TO LENGTH OF ORIGINAL TEXT MOV R0,R4 ; COPY MOD LIST POINTER SUB (SP),R4 ; SUBTRACT START OF MOD ENTRY DEC R4 ; AND ACCOUNT FOR HEADER MOVB R4,@(SP)+ ; AND STORE, POP POINTER TST (SP)+ ; CLEAN UP STACK BR 14$ ; J TO CARRY ON ; HERE WE HAVE GOT TO THE END OF A SEQUENCE OF BLANKS AND DISCOVERED ; THAT WE DIDN'T WANT TO IGNORE THEM AFTER ALL. WE MUST COPY THEM ; BACK INTO THE OUTPUT BUFFER AND DELETE THE ENTRY WE HAVE STARTED ; IN THE MODIFICATION LIST. 12$: MOV R2,R4 ; COPY CURRENT BUFFER ADDRESS MOV (SP)+,R0 ; MOVE BACK POINTER TO MOD LIST DEC R0 ; ACCOUNT FOR HEADER MOV (SP)+,R2 ; GET ORIGINAL INPUT BUFF POINTER 13$: MOVB (R2)+,(R3)+ ; COPY ONE OF THE BYTES WE TRIED TO IGNORE CMP R2,R4 ; UNTIL WE REACH WHERE WE STOPPED IGNORING BLO 13$ ; LOOP IF NOT DONE 14$: TST R1 ; ANYTHING LEFT IN INPUT LINE? BNE 1$ ; LOOP IF SO TO LOOK AT IT 15$: MOVB #255.,(R0)+ ; STORE TERMINATOR IN MOD LIST MOV R0,S$R0(SP) ; SET CALLER'S R0 TO MOD LIST POINTER MOV R3,S$R2(SP) ; AND HIS R2 TO OUTPUT BUFF POINTER RETURN ; AND GO AWAY .SBTTL $GTCOR - Get a block of core ;+ ; ; $GTCOR ; THIS ROUTINE IS CALLED TO OBTAIN A CORE AREA TO HOLD A LINE ; IT HAS BEEN MADE A SEPARATE ROUTINE TO FACILITATE THE POSSIBLE ; ADDITION IN THE DISTANT FUTURE OF A RESHUFFLER WHICH WOULD ; COMPACT FREE CORE IF IT COULD NOT SATISFY THE REQUEST. ; ; INPUTS: ; R1 SIZE IN BYTES OF REQUIRED AREA ; ; OUTPUTS: ; R1 ACTUAL SIZE OF ALLOCATED AREA (CURRENTLY JUST INPUT ; VALUE ROUNDED TO AN EXACT NUMBER OF WORDS) ; R5 ADDRESS OF AREA ALLOCATED ; ;- $GTCOR:: MOV R0,-(SP) ;Preserve R0 MOV #$FRHD,R0 ; GET FREE HEAD CALL $RQCB ; REQUEST THE BLOCK MOV R0,R5 ; ELSE TELL THE CALLER MOV (SP)+,R0 ;Restore R0 RETURN .SBTTL $PUTLIN - Output a line to the output file ;+ ; ; $PUTLIN ; THIS ROUTINE CHECKS IF AN OUTPUT FILE IS BEING GENERATED. ; IF NOT, IT RETURNS DIRECTLY. OTHERWISE, IT OUTPUTS THE LINE ; AND CHECKS FOR ERRORS. IF SUCCESS, IT RETURNS TO THE CALLER, ; ELSE AN ERROR MESSAGE IS GENERATED AND CONTROL GOES TO $ABERR. ; ; INPUTS: ; 0(SP) RECORD BUFFER ADDRESS ; 2(SP) RECORD LENGTH ; ; THE MACRO 'PUTLIN BUFADRS,LENGTH' MAY BE USED TO ; CONVENIENTLY CALL THE ROUTINE. ; ;- .ENABL LSB $PUTLIN:: MOV R1,-(SP) ;Save R1 MOV SP,R1 PUT$S SAVFDB,4(R1),6(R1) ; OUTPUT THE LINE BCC 1$ ;Branch if no error MOV SAVFDB,R2 ;Get FDB address ;+ ;ERROR ADD #F.ERR,R2 ;Point to the error location .ERR #ERAREA,@R2,LEVEL=FATAL,RETURN=NO ;Output file full ; or output error ;- 1$: MOV (SP)+,R1 ; RESTORE R1 2$: MOV (SP)+,@SP ; CLEAN STACK MOV (SP)+,@SP RETURN .DSABL LSB ;+ ; BUFDMP will dump the contents of the list file at the end of a ; comparison when $CLOSE is not called. ; ; R0 -> File Descriptor Block (FDB) ; ; CALL BUFDMP ; ; F.ERR(R0) = error code ;- .ENABL LSB BUFDMP:: MOV R0,R1 ;Copy the FDB pointer MOV F.IOBF(R1),R5 ;Point to the I/O buffer MOV F.BPTR(R1),R4 ;Get the buffer pointer CMP R4,R5 ;Anything in the buffer? BEQ 6$ ;Branch if no 1$: ADD F.BFSZ(R1),R5 ;Get the hi limit of the buffer SUB R4,R5 ;Get the size of the area left BEQ 3$ ;Branch if buffer already full. 2$: CLRB (R4)+ ;Clear a byte DEC R5 ;Done? BNE 2$ ;Branch if not 3$: ADD #F.IO.,R0 ;Point to the I/O block .WRITW ;And write BCC 6$ ;Branch if no error JMP $OERR ;Output error 6$: RETURN .DSABL LSB .END SRCCOM