Trailing-Edge
-
PDP-10 Archives
-
steco_19840320_1er_E35
-
10,5676/teco/source/tecsrh.mac
There are 3 other files named tecsrh.mac in the archive. Click here to see a list.
SUBTTL Introduction
; Copyright (c) 1980 Stevens Institute of Technology,
; Hoboken, New Jersey, 07030
; This software may be used and copied provided that this copyright notice
;is included, and provided that copies of all modifications are sent to:
;
; TECO Project
; Computer Center
; Stevens Institute of Technology
; Castle Point Station
; Hoboken, New Jersey 07030
;
;
; The information in this software is subject to change without notice
; and should not be construed as a commitment by the authors or their
; employers.
; Search needed universals
SEARCH TECUNV ; TECO universal file
; Generate the prologue
TECVER==200 ; Major version number
TECMIN==1 ; Minor version number
TECEDT==1156 ; Edit level
TECWHO==0 ; Last editor
PROLOGUE(SRH,<TECO Pattern matching and searches>) ; Generate the TITLE and other stuff
SUBTTL Table of Contents
;+
;.pag.lit
; Table of Contents for TECSRH - Search and Pattern processing
;
;
; Section Page
; 1. Introduction . . . . . . . . . . . . . . . . . . . . . 1
; 2. Table of Contents. . . . . . . . . . . . . . . . . . . 2
; 3. Revision History . . . . . . . . . . . . . . . . . . . 3
; 4. Searches
; 4.1. Commands
; 4.1.1. FS, FN, FD, and FK . . . . . . . . . 4
; 4.1.2. _, N, and S. . . . . . . . . . . . . 5
; 4.2. pattern source setup. . . . . . . . . . . . . 6
; 4.3. Set up search matrix. . . . . . . . . . . . . 9
; 4.4. New fast search routine . . . . . . . . . . . 28
; 4.5. Old slow but sure routine . . . . . . . . . . 32
; 4.6. pattern found . . . . . . . . . . . . . . . . 35
; 4.7. Autotype after succesful searches . . . . . . 35
; 4.8. Pattern not found in this buffer. . . . . . . 36
; 5. Data segment . . . . . . . . . . . . . . . . . . . . . 38
; 6. End of TECSRH. . . . . . . . . . . . . . . . . . . . . 39
;.end lit.pag
;-
SUBTTL Revision History
COMMENT |
1000 Start of this version
1012 By: Nick Bush On: 6-August-1980
Fix the fast search algorithm. Under certain circumstances, it was looking
one character too far in the buffer. If this character happened to match,
it could claim that the string was found when in fact it did not exist
in the buffer. This would also end up with PT set at Z+1 leading to
all sorts of problems (including PTD stopcodes in video mode).
Also make REE (reenter) save all of the Tx ac's before calling lower
level routines which use them. There are numerous places where not
doing this can cause random errors.
Modules: TECPRS,TECSRH
1013 By: Nick Bush On: 6-August-1980
Make UPDLIN use SC$WLN to write out a line if the line on the screen is
blank, and we didn't have a function block for the replacement.
Make FS and FN searches only move the text in the text buffer once, not
do a delete and an insert. It will now only delete characters if the
new string is shorter, and only insert space if the new string is longer.
Modules: TECVID,TECSRH
1057 By: Nick Bush On: 3-December-1980
Fix search failure code to check for an iteration correctly. Previous
edits had changed the contents of the XS stack, but had not fixed
TECSRH.
Modules: TECSRH
1061 By: Nick Bush On: 18-December-1980
1) Finish and debug Tektronix 4025 support.
2) Add FW command.
3) Add capability of logging screen update info in log file.
Modules: TECUNV,TECTEK,TECSRH,TECTBL,TECECM,TECVID,TECERR
1063 By: Nick Bush On: 19-December-1980
Fix FW command to clear current ^D column so we will remember a new one.
Fix ] command to respect the settings of the QR$xxx flags and not
store text into a value only Q-reg or a value into a text only Q-reg.
Modules: TECCMD,TECSRH
1103 By: Nick Bush On: 1-March-1981
Fix SLOS.Z to handle -S^EL correctly. It was always succeeding.
Modules: TECSRH
1104 By: Nick Bush On: 12-March-1981
Fix FW command when going backwards from the end of the buffer. It was
looking at the character after the end of the buffer.
Fix FK/FS to work correctly with ^ES in the search argument.
Modules: TECSRH
Start of Version 200A(1126)
1127 By: Nick Bush@SIT, Robert C. McQueen@SIT On: 15-October-1981
Add the following new features:
- String arguments. {...} is a string argument.
- Make I take them, = and == return them.
- Implement the FC command to define immediate command tables
- Implement the E? command to return various items.
- Start doing some work so that TECO will work on TOPS-20
- Start doing some work so that TECO some day may run in a section
besides zero.
Modules: TECUNV,TECERR,TECPRS,TECCMD,TECSRH,TECMEM,TECUUO,TECECM,TECMVM,TECCOM,TECINI
1155 By: Robert C. McQueen On: 12-April-1982
Minus search didn't work if you started at the end of the buffer.
Modules: TECSRH
1156 By: Robert C. McQueen On: 14-April-1982
- Fix bug in the last edit.
- Fix problem with screen updating if /MODE:ASCI and P command.
Modules: TECSRH,TECCMD
|
SUBTTL SR$INI - Search initializtion
;+
;.hl1 SR$INI
; This routine will initialze the lowsegment data for TECSRH.
;-
$CODE ; This is in the code section
SR$INI: MOVEI T1,SRHBLK ; Get the BLK address
MOVEI T2,SRHTPT ; And the TPT address
PJRST M$USEB ; Set up the pointer
SUBTTL Searches -- Commands -- FW - Find word
;+
;.hl2 FW - Find word
;This search routine will find the nth word. It works a little differently
;than the normal search processing in TECO. It will position to the beginning
;of the word always.
; For example, 1FW$ will find the beginning of the next word, -FW$ will find
;the beginning of the current word (if we are in the middle of it) or find
;the beginning of the previous word if we are not in the middle of a word.
;-
; Character mask for characters which may be in words
BRINI$(WRD) ; First character position
BRKCH$(WRD,"A","Z") ; Include uppercase
BRKCH$(WRD,"a","z") ; And lowercase alphabetics
BRKCH$(WRD,"0","9") ; Also numerics
WRDMSK: BRGEN$(WRD) ; Generate the mask
FW$CMD: LOAD. P1,TPTADR,+$QRTPT+TXTBUF ; Get the current buffer address
LOAD. P2,BLKPT,(P1) ; Get the current address of PT
MOVE T1,P2 ; Get the pointer address
IDIVI T1,5 ; Get the word/byte offset
ADDI T1,.BKTLN(P1) ; Plus the base address
HLL T1,BTAB-1(T2) ; Get the byte pointer
MOVE P4,T1 ; Into a safe place
JUMPLE A1,FWCM.3 ; Backwards search?
LOAD. P3,BLKEND,(P1) ; No, get the number of chars to search
SUB P3,P2 ; . . .
FWCM.0: JUMPE P3,FWERR ; If nothing, give the error
PUSHJ P,FWCHR ; Get a character
TDNN T3,WRDMSK(T1) ; We want this char?
SOJA P3,FWCM.0 ; End of buffer yet?
; Here after we have found the first character that is part of a word.
;Now look for the first character not part of the word.
FWCM.1: SOJLE P3,FWCM.A ; If nothing left, check where we should be
FWCM.B: PUSHJ P,FWCHR ; Get a character
TDNN T3,WRDMSK(T1) ; Is this character allowed in a word?
JRST FWCM.2 ; No, all done with this word
SOJG P3,FWCM.B ; Yes, continue on
FWCM.A: SOJG A1,FWERR ; If this isn't the last pass, don't move PT
FWCM.2: SOJG A1,[SOJA P3,FWCM.0] ; Loop for the next word
LOAD. P2,BLKEND,(P1) ; Get the end position
SUB P2,P3 ; And back up the correct number of chars
STOR. P2,BLKPT,(P1) ; Store it
ZERO. T1,BLKCOL,(P1) ; Flag we have changed columns
POPJ P, ; And return
; Here to search backwards for the n+1 word boundary. Note that
;a 0FW command will move to the start of the current word if it is within
;one. If it is currently in a word boundary, it will move to the
;start of the previous word.
FWCM.3: CFMN. ,BLKEND,(P1),P2 ; At end of buffer?
SOJA P2,FWCM.4 ; Yes, don't bother with the IBP
IBP P4 ; Change the pointer to the correct place
FWCM.4: JUMPL P2,FWERR ; Error if nothing left
PUSHJ P,FWCHRB ; Get a character going backwards
TDNN T3,WRDMSK(T1) ; Is this a valid word character?
SOJA P2,FWCM.4 ; No, try the next
; Here when we found the tail end (or middle) of a word. Now we must
;search backwards for the start.
JUMPE P2,FWCM.9 ; If at start of buffer, we are done
SOJL P2,FWERR ; If we hit the start of the buffer first, give up
FWCM.6: PUSHJ P,FWCHRB ; Get a character
TDNN T3,WRDMSK(T1) ; Valid in a word?
JRST FWCM.7 ; No, this is the start of the previous word
SOJGE P2,FWCM.6 ; Yes, try the next
JUMPN A1,FWERR ; If we need more, don't bother moving pointer
ZERO. ,BLKPT,(P1) ; Otherwise, clear the pointer
ZERO. T1,BLKCOL,(P1) ; Flag no remembered column
POPJ P, ; And return
FWCM.7: AOJLE A1,[SOJA P2,FWCM.4] ; If we need to search more, continue on
AOJA P2,FWCM.8 ; Bump back up one char
FWCM.9: AOJLE A1,FWERR ; If we need more, punt
FWCM.8: STOR. P2,BLKPT,(P1) ; Otherwise, store the position
ZERO. T1,BLKCOL,(P1) ; Flag no remembered column
POPJ P, ; And return
; Here if we can't find enough word boundaries.
FWERR: ERROR E.WNF ; Give the error
; Routine to get characters for FW
FWCHRB: LDB T1,P4 ; Get a character
ADDX P4,<INSVL.(7,BP.POS)> ; Back up the pointer
JUMPGE P4,FWCH.1 ; Do we need to back up a word?
HRLI P4,(POINT 7,,34) ; Yes, do it
SOJA P4,FWCH.1 ; And enter common routine
FWCHR: ILDB T1,P4 ; Forward is easy
FWCH.1: IDIVI T1,^D32 ; Break character into word/bit offsets
MOVN T2,T2 ; Make it the amount to shift
MOVX T3,1B0 ; Get a bit
LSH T3,(T2) ; And shift it
POPJ P, ; All done
SUBTTL Searches -- Commands -- FS - Find string and replace it
;+
;.hl1 FS Command
;This routine will handle the FS command processing. It will search
;for the nth occurance of the string and change it. If the string is
;not found in the current editing buffer an error will be given.
;-
FSSRCH: PUSHJ P,S$SETUP ; Do the initial set up
; and bounds defaulting
JRST FSUP.E ; Error, go handle it
PUSHJ P,S$BUILD ; Build the search matrices
; Now deterine the length of the second string that was given
TXZ S,S.NCCT ; Refresh ^T flag
MOVE CH,ARGTRM ; Get delimiter
TXO F,F.SRCH ; Flag so insert knows we are a search
PUSHJ P,INSE.0 ; Call the insert argument scanning
MOVEM T1,INSLEN ; Store the length
; Do the searching
PUSHJ P,S$SEARCH ; Do the search processing in the
; current buffer
JRST S$FRETURN ; Failed, Clean up and error
; Here if the string was found. Determine if the new string will fit
; over the old one, or if the space must be expanded or crunched.
PUSHJ P,FSNSUB ; Do the FS/FN subroutine
PJRST S$TRETURN ; Give a good return
; Here if an error occured during setup. We should try to eat the search string
;since otherwise a : modified search may not recover properly.
FSUP.E: PUSH P,T1 ; Save the error code
PUSHJ P,S$BUILD ; Build the string
TXZ S,S.NCCT ; Fix the ^T flag
MOVE CH,ARGTRM ; Get the delimeter
TXO F,F.SRCH ; Flag from a searh
PUSHJ P,INSE.0 ; Get the insert string portion
POP P,T1 ; Get the error code back
.ERR (T1) ; And give the error code
SUBTTL Searches -- Commands -- FSNSUB - FS/FN subroutine
;+
;.hl2 FSNSUB
;This routine will do the general fix up for the inserting of the second
;string.
;-
FSNSUB: LOAD. T1,TPTADR,+TXTBUF ; Get the text buffer address
SUB P2,P4 ; Put us back at the start of the string
STOR. P2,BLKPT,(T1) ; And store the correct position
ZERO. A1,BLKCOL,(T1) ; Clear current column
MOVE A1,P4 ; Get the length of the string
SUB A1,INSLEN ; Minus the length of the insert string
SKIPLE A1 ; Really have to delete anything?
PUSHJ P,DELETE ; Delete the items
MOVE CH,ARGTRM ; Get the argument terminator
MOVE T1,INSLEN ; Get the insert string length
SUB T1,P4 ; And get the amount that still needs to be expanded
JUMPGE T1,.+2 ; Is all the space there?
SETZ T1, ; Yes, don't need to expand any
MOVEI T2,TXTBUF+$QRTPT ; Get the address of the pointer to the text
SKIPE INSLEN ; If no insert string, don't need to insert anything
PUSHJ P,INSE.I ; Insert the string
MOVE CH,ARGTRM
TXNE S,S.NRAD ; Null insert?
CAXE CH,.CHESC ; Terminator an altmode (Escape) ?
SKIPA ; Skip over
TXO F,F.DONE ; Flag done
POPJ P, ; Return to the caller
SUBTTL Searches -- Commands -- FN - Find string and replace it
;+
;.hl1 FN Command
;This routine will handle the FN command. This command will cause the
;string specfied to be searched for and then replaced with the second
;string specified. If the string is not found in the current editing
;buffer the next buffer will be read until the string is found or until
;an end of file is reached.
;-
FNSRCH: TXO F,F.NSRH!F.SRCH ; Flag that this is an N search
PUSHJ P,S$SETUP ; Do the initial set up
; and bounds defaulting
JRST FSUP.E ; Error
PUSHJ P,S$BUILD ; Build the search matrices
; Now deterine the length of the second string that was given
TXZ S,S.NCCT ; Refresh ^T flag
MOVE CH,ARGTRM ; Get delimiter
PUSHJ P,INSE.0 ; Call the insert argument scanning
MOVEM T1,INSLEN ; Store the length
; Do the searching
FNSH.1: PUSHJ P,S$SEARCH ; Do the search processing in the
; current buffer
JRST FNSH.0 ; Failed, read the next buffer
; if that is needed
; Here if we found the string
PUSHJ P,FSNSUB ; Call the subroutine to do the work
PJRST S$TRETURN ; Give a true return
; Here if the FN search has failed. Check the negative search flag and give
; up if it is on. Why it is on in the first place I don't know.
FNSH.0: TXNE S,S.MINS ; Negative search ?
JRST FNSH.2 ; Yes, give a fail return
MOVEM A1,SRHCNT ; Store the search cound
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the current text buffer
PUSHJ P,GETFDI ; Get the input file descriptor
JRST FNSH.2 ; Common failure exit
LOAD T2,.FDFLG(T1),FD.EOF ; Check to see if at end of file
JMPT T2,FNSH.2 ; We are, just get out
PUSH P,P1 ; Save P1
MOVEI P1,1 ; Punch one buffer full
PUSHJ P,PUNSCH ; Dump it
POP P,P1 ; Restore P1
MOVE A1,SRHCNT ; Restore the count
SETZM LOWERB ; Clear the lower bound (new buffer)
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the text buffer address
LOAD. T1,BLKEND,(T1) ; Get the new upper bounds
MOVEM T1,UPPERB ; Set it
JRST FNSH.1 ; Loop back
FNSH.2: MOVE CH,ARGTRM ; Get the argument terminator
CAXE CH,.CHESC ; Escape ?
TXZ S,S.NRAD ; Yes, Flag so second altmode gets
; put in *(q-reg)
JRST S$FRETURN ; Do the failure return processing
SUBTTL Searches -- Commands -- FD - Find string and delete it
;+
;.hl1 FD command
;This routing will handle the FD command. This command will delete from
;the current pointer to the end of the string that was found.
;-
FDSRCH: PUSHJ P,S$SETUP ; Do the initial set up
; and bounds defaulting
JRST SRUP.E ; Error, go skip the string
PUSHJ P,S$BUILD ; Build the search matrices
PUSHJ P,S$SEARCH ; Do the search processing in the
; current buffer
JRST S$FRETURN ; Give a failure return
MOVE A1,SAVEPT ; Get the old PT
SUB A1,P2 ; Determine the amount to delete
PUSHJ P,DELETE ; Do the delete
PJRST S$TRETURN ; Return the correct value
; and do the auto type out
SUBTTL Searches -- Commands -- FK - Find and kill the specified string
;+
;.hl1 FK Command
; The FK search command will search for the specified string and delete
;it.
;-
FKSRCH: PUSHJ P,S$SETUP ; Do the initial set up
; and bounds defaulting
JRST SRUP.E ; Error, go skip the string
PUSHJ P,S$BUILD ; Build the search matrices
PUSHJ P,S$SEARCH ; Do the search processing in the
; current buffer
JRST S$FRETURN ; Give a failure return
LOAD. T1,TPTADR,+TXTBUF ; Get the text buffer address
SUB P2,P4 ; Put us back at the start of the string
STOR. P2,BLKPT,(T1) ; And store the correct position
ZERO. A1,BLKCOL,(T1) ; Clear current column
MOVE A1,P4 ; Get the length of the string
PUSHJ P,DELETE ; Delete the items
PJRST S$TRETURN ; Do the normal return processing
SUBTTL Searches -- Commands -- _
;+
;.HL1 Backarrow search
;The underscore search processing search for the specified string discarding
;all buffers that do not contain the string.
;-
LARR: PUSHJ P,S$SETUP ; Do the initial set up
; and bounds defaulting
JRST SRUP.E ; Error, go skip the string
PUSHJ P,S$BUILD ; Build the search matrices
LARR.0: PUSHJ P,S$SEARCH ; Do the search processing in the
; current buffer
JRST LARR.1 ; Here if the search has failed
PJRST S$TRETURN ; Give a good return
; Here if the string was not found in the buffer. Yank in the next buffer
;from the input file if there is one.
LARR.1: TXNE S,S.MINS ; Minus search (-_?!?!?!)
JRST S$FRETURN ; Yes, just fail
MOVEM A1,SRHCNT ; Store the count
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the current text buffer
PUSHJ P,GETFDI ; Get the input FD
JRST S$FRETURN ; No input FD, just fail
LOAD T1,.FDFLG(T1),FD.EOF ; Get the end of file flag
JMPT T1,S$FRETURN ; Just return if an EOF already
PUSHJ P,YANK ; Get the next buffer
MOVE A1,SRHCNT ; Restore the search counter
SETZM LOWERB ; Clear the lower bounds
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the text buffer address
LOAD. T1,BLKEND,(T1) ; Get the end of it
MOVEM T1,UPPERB ; Store as the upper bounds
JRST LARR.0 ; Loop back for more
SUBTTL Searches Commands -- N - Non-stop search
;+
;.HL2 N search
;The N search processing will search for the specified string reading
;and writting buffers until the string is found.
;-
N$CMD: TXO F,F.NSRH ; Flag N type search
PUSHJ P,S$SETUP ; Do the initial set up
; and bounds defaulting
JRST SRUP.E ; Error, go skip the string
PUSHJ P,S$BUILD ; Build the search matrices
N$CM.0: PUSHJ P,S$SEARCH ; Do the search processing in the
; current buffer
JRST N$CM.1 ; Do the common failure processing
PJRST S$TRETURN ; Give a good return
; Here to do the failure processing. This means we call the common code
; in the FN/N subroutine and loop back.
N$CM.1: TXNE S,S.MINS ; Negative search ?
JRST S$FRETURN ; Yes, give a fail return
MOVEM A1,SRHCNT ; Store the search cound
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the current text buffer
PUSHJ P,GETFDI ; Get the input file descriptor
JRST S$FRETURN ; Common failure exit
LOAD T2,.FDFLG(T1),FD.EOF ; Check to see if at end of file
JMPT T2,S$FRETURN ; We are, just get out
PUSH P,P1 ; Save P1
MOVEI P1,1 ; Punch one buffer full
PUSHJ P,PUNSCH ; Dump it
POP P,P1 ; Restore P1
MOVE A1,SRHCNT ; Restore the count
SETZM LOWERB ; Clear the lower bound (new buffer)
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the text buffer address
LOAD. T1,BLKEND,(T1) ; Get the new upper bounds
MOVEM T1,UPPERB ; Set it
JRST N$CM.0 ; Loop back
SUBTTL Searches -- Commands -- S - General search
;+
;.HL2 S search
;This command will search for the specfied string and stop when it is
;found. If the string specified is not found it will give an error and
;leave the pointer untouched.
;-
SERCH: PUSHJ P,S$SETUP ; Do the initial set up
; and bounds defaulting
JRST SRUP.E ; Error, go skip the string
PUSHJ P,S$BUILD ; Build the search matrices
PUSHJ P,S$SEARCH ; Do the search processing in the
; current buffer
JRST S$FRETURN ; Do the failure return processing
JRST S$TRETURN ; Do the true return processing
; Here if S$SETUP failed
SRUP.E: PUSH P,T1 ; Save T1
PUSHJ P,S$BUILD ; Build the search string
POP P,T1 ; restore the error code
.ERR (T1) ; And tell the user
SUBTTL Searches -- S$SETUP - Set up for a search
;+
;.hl1 S$SETUP
;This routine will setup the search processing to do a search. It will
;default the bounds according to the information that was given to it.
;It will save the pointer so that it can be restored later.
;-
S$SETUP:
TXZ S,S.MINS ; Flag not negative search (yet)
LOAD. T4,TPTADR,+$QRTPT+TXTBUF ; Get the buffer address
LOAD. T4,BLKPT,(T4) ; Get the character address of PT
MOVEM T4,SAVEPT ; Save in case the search fails
MOVEM T4,UPPERB ; PT is upper bound on backward searches
TXZE F,F.ARG2 ; If two arguments then bounded search
JRST BOUNDS ; Bounded search
SETZM LOWERB ; Save as default lower bound
SKIPE A1 ; Zero ?
JRST SERC33 ; No - Skip this
TXNN F,F.ARG ; There must be no argument
JRST SERC33 ; There isn't, keep going
ISAERR: MOVEI T1,E.ISA## ; Get the error code
POPJ P, ; And return
SERC33: SKIPGE A1 ; Get the argument where it is wanted
TXOA S,S.MINS ; Negative search
SETZM UPPERB ; No upperbound on forward searches
MOVMS A1 ; Correct in case of minus searching
JRST SERCHA ; Start the search
;Here if bounded search, set up bounds
BOUNDS: JUMPL A2,.+2 ; Negative bounds are illegal
JUMPGE A1,.+2 ; . . .
JRST ISAERR ; Go return the error
TXZ F,F.NSRH!F.LARW!F.ARG ; FN and N go to FS and S
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the address of the text buffer
CFMG. ,BLKEND,(T1),A2 ; Too big ?
LOAD. A2,BLKEND,(T1) ; Yes - Make it the end
STOR. A2,BLKPT,(T1) ; Store the new pointer
CAML A1,A2 ; Minus implied ?
JRST SAVESH ; No - Save te mounds
EXCH A2,A1 ; Yes - Exchage the arguments
TXO S,S.MINS ; Flag that it is now a minus search
SAVESH: MOVEM A2,LOWERB ; Save the lower bound
MOVEM A1,UPPERB ; Save the upper bound
SETZ A1, ; Assume first occurance in case bounded
;Adjust upper and lower bounds
SERCHA: SETZ T1, ; Good lower bound
LOAD. T2,TPTADR,+$QRTPT+TXTBUF ; Get the buffer address
LOAD. T2,BLKEND,(T2) ; Get the end
CAMLE T1,LOWERB ; Is the lower bound too low ?
MOVEM T1,LOWERB ; Yes - Adjust it
CAMGE T2,LOWERB ; Is the upper bound too low ?
MOVEM T2,LOWERB ; Yes - Adjust it
SKIPE UPPERB ; Fix zero upper bound
CAMGE T2,UPPERB ; Greater that the upper bound ?
MOVEM T2,UPPERB ; Save the new upper bound
CAMLE T1,UPPERB ; Is the lower bound .LE. the upper ?
MOVEM T1,UPPERB ; No - Fix it
PJRST .POPJ1 ; Give a good return
SUBTTL Searches -- S$BUILD - Build the search matrix
;+
;.hl1 S$BUILD
;This routine will build the search matrices if needed. It will only rebuild
;the search matrix if the previous search matrix used a ^G(q-reg) in the
;search.
;-
S$BUILD:
MOVX CH,.CHESC ; Use Escape as the delimiter if @ not seen
TXZN F,F.SLSL ; Atsign seen ?
JRST SERCHB ; No - Terminator altmode
PUSHJ P,SKRCH ; Yes - Get the user specified delimiter
ERROR E.USR ; ++ Unterminated search command
; Determine whether we can use the previous pattern
SERCHB: MOVEM CH,T2 ; T2:=Pattern source string delimiter
MOVEM CH,ARGTRM ; Save delimiter for FS insertion
SETZM SCNEST ; Search nest level is zero
PUSHJ P,SKRCH ; Look ahead 1 character
ERROR E.USR
CAIE CH,(T2) ; Is it the delimiter?
JRST SERCHT ; No, an argument is given
SKIPL SRHCTR ; Yes, use previous pattern string
; unless there was none or last had error
ERROR E.SNA ; ++ Initial search with no argument
SKIPN SCTLGA ; but not if remembered pattern source used ^Gi
POPJ P, ; Ok, Use the previous matrices
; Move a new pattern source to storage
SERCHT: TXZ S,S.XMAT ; Clear exact match flag
STORE T1,SMATRX,SMATRX+SCLRLN-1,0 ; Clear previous matrices
SETZM SRHCTR ; Clear source pattern length counter
SETZM SCTLGA ; Assume pattern source doesn't use ^Gi
MOVE P4,[POINT 7,SRHARG] ; Point to start of storage area
JRST SERCHD ; 1st character already in
SERCHC: PUSHJ P,SKRCH ; Get next character of pattern source
ERROR E.USR
SERCHD: CHKEO EO21,SERCHE ; If EO=1, ^R is just text
CAXE CH,$CHQOT ; Quoting character?
SERCHE: CAXN CH,.CHCNQ ; ^Q?
JRST SERCHG ; Yes, next character is text
CAIN CH,(T2) ; The delimiter?
JRST SERCH0 ; Yes
CAXN CH,.CHCNT ; ^T?
JRST SERCHU ; Yes
TXNE S,S.NCCT ; ^T flag on?
JRST SERCHF ; Yes, ^V and ^W are just text
CAXE CH,.CHCNV ; ^V?
CAXN CH,.CHCNW ; ^W?
TXO S,S.XMAT ; Yes, set exact match flag
CHKEO EO200,SERCHF ; Don't check for ^A/^B if old mode
CAXE CH,.CHCNA ; Control-A
CAXN CH,.CHCNB ; Or control-B?
TXO S,S.XMAT ; Yes, flag exact match
SERCHF: AOS T1,SRHCTR ; Bump string counter
CAILE T1,^D80 ; Still fit in store?
ERROR E.STC
IDPB CH,P4 ; Yes, store character
JRST SERCHC ; and go back for more
SERCHG: AOS T1,SRHCTR ; Count the ^R (^Q)
CAILE T1,^D80 ; Will it fit?
ERROR E.STC
IDPB CH,P4 ; Yes, store it
PUSHJ P,SKRCH ; Get next character
ERROR E.USR
JRST SERCHF ; and store it as text
SERCHU: TXC S,S.NCCT ; ^T, complement control command switch
JRST SERCHF
SUBTTL Searches -- Set up search matrix
SERCH0: TXZ S,S.NCCT ; Refresh ^T flag
MOVEI P1,0 ; Start at beginning of pattern
IDPB P1,P4 ; Store as a null for error typeout
MOVE T1,SRHCTR ; Get the number of characters
STOR. T1,BLKEND,+SRHBLK ; Store it
MOVEI T1,SRHBLK ; Get the block address
SETZ T2, ; And set up to read from first
PUSHJ P,SETINC ; character
JFCL ; Will never happen
MOVEI P4,SRHTPT ; Get the address of the pointer
PUSHJ P,SCH.0 ; Set up the matrix
LSH P1,-2 ; Change index to pattern length
MOVEM P1,PATLEN ; Save it
MOVNS SRHCTR ; Flag pattern is legal
JRST ROTATE ; And go rotate it
; Set up a 131 by 36 bit table based on the pattern source.
; The table is implemented as a four word by 36 table, with the first
; 32 bits of the words used for the four portions of the ASCII character
; set (i.e. 0-37, 40-77, 100-137, 140-177) and three of the bits left over
; in the last word used for the "bogus" characters BEGPAG, ENDPAG, and
; SPCTAB. This is a little harder to set up for single letters in the
; pattern source, but is much easier for ranges and makes the fast search
; algorithm setup much faster. The table is then rotated into the old
; TECO 36 by 131 bit table for the actual search matrix.
SCH.0: LOAD. T1,TPTADR,(P4) ; Get the address of the text
PUSHJ P,GETINC ; And get a character
POPJ P, ; Return if we hit the end of the buffer
PUSHJ P,SCH.1 ; Process the character
JRST SCH.0 ; Get the next character, this one didn't count
ADDI P1,4 ; End of a pattern position, on to next
CAILE P1,^D36*4 ; and error if more than 36 positions in pattern
ERROR E.STL ; ++ Search too long
JRST SCH.0 ; Otherwise, loop for the next character
; Here to build a single character entry
SCH.1: MOVEI T1,S2TABL ; Check for control character in string
SKIPE SCNEST ; Control-G allowed?
MOVEI T1,S1TABL ; No, avoid it
TXNE S,S.NCCT ; ^T flag on?
MOVEI T1,S3TABL ; Yes, use restricted table
PUSHJ P,NDISP1 ; Go search table, don't return if found
SCH.9: CHKEO EO21,SCH.4 ; Not control, if EO=1, force exact mode
TXNN S,S.NCCT ; If ^T flag on, all control characters are legal
PUSHJ P,CKNCC ; OF, all other control characters are illegal
; (Don't return if any)
SCH.2: TXNE S,S.EMAT ; Forced either match on?
JRST SCH.3 ; Yes, match either
TXNN S,S.XMAT ; No, want an exact match?
TXNE F,F.PMAT ; No, want global exact match?
JRST SCH.4 ; Asked for exact match
SCH.3: CAXL CH,"a" ; Match either, is it lower case?
CAXLE CH,"z"
JRST .+2 ; No
SUBI CH,"a"-"A" ; Yes, make it upper case
CAIL CH,"A" ; Is it upper case?
CAILE CH,"Z"
JRST SCH.5 ; No
MOVSI T3,400000 ; Yes, convert character to bit of 131
MOVNI T2,-"@"(CH) ; want - (<ch>-100) for LSH
LSH T3,0(T2) ; Position bit to letter range
IORM T3,BITMAT+2(P1) ; Set match on upper case
IORM T3,BITMAT+3(P1) ; and lower case characters
JRST SCH.6
SCH.4: PUSHJ P,CASE ; Exact mode, adjust pattern character case
SCH.5: MOVSI T1,400000 ; Convert character to bit of 131
MOVE T2,CH ; Copy of character
IDIVI T2,^D32 ; Using 32 bits per word, figure word and bit
ADDI T2,0(P1) ; Word plus current pattern position
MOVNS T3 ; Negative of remainder for bit shift
LSH T1,0(T3) ; Position bit within 32 bit range for each word
IORM T1,BITMAT(T2) ; and include it in appropriate word
SCH.6: AOS (P) ; Increment the return address
POPJ P, ; Yes, return to caller
; Control character dispatch table for second scan of pattern source
S2TABL: XWD CNTLG,.CHBEL ; ^G
S1TABL: XWD CNTLE,.CHCNE ; ^E
XWD CNTLX,.CHCNX ; ^X
XWD CNTLN,.CHCNN ; ^N
XWD CNTLS,.CHCNS ; ^S
XWD CNTLA,.CHCNA ; ^A
XWD CNTLB,.CHCNB ; ^B
XWD CNTLV,.CHCNV ; ^V
XWD CNTLW,.CHCNW ; ^W
XWD CNTLBS,.CHCBS ; ^\
XWD CNTLCF,.CHCCF ; ^^
; Shorter table used for ^T on mode starts here
S3TABL: XWD CNTLT,.CHCNT ; ^T
XWD CNTLQ,.CHCNQ ; ^Q
XWD CNTLR,$CHQOT ; Quoting character?
XWD CNTLLB,.CHESC ; ESCape
XWD 0,0 ; End of list
; Macro to set bits in bit table. The three arguments are:
; AC - AC to use for doing the sets
; NAME - Name of break set
; ADDRESS - Address of four word entry
DEFINE SETBRK(AC,NAME,ADDRESS)<
$$$CUR==0 ;; Current ac contents are zero
IFN <BRWRD$(NAME,0)>,< ;; Any bits set in first word?
$$$CUR==BRWRD$(NAME,0) ;; Yes, get the first word
MOVX T1,<BRWRD$(NAME,0)> ;; Get the first word
IORM T1,0+ADDRESS ;; Turn on the bits in the first word
> ;; End of IFN <BRWRD$(NAME,0)>
IFN <BRWRD$(NAME,1)>,< ;; Anything in second word?
IFN $$$CUR^!<BRWRD$(NAME,1)>,< ;; Yes, is this the same as the previous?
$$$CUR==BRWRD$(NAME,1) ;; Remember what we have
MOVX T1,<BRWRD$(NAME,1)> ;; And get it into the ac
> ;; End of IFN $$$CUR^!<BRWRD$(NAME,1)>
IORM T1,1+ADDRESS ;; Turn on the bits
> ;; End of IFN <BRWRD$(NAME,1)>
IFN <BRWRD$(NAME,2)>,< ;; Anything in second word?
IFN $$$CUR^!<BRWRD$(NAME,2)>,< ;; Yes, is this the same as the previous?
$$$CUR==BRWRD$(NAME,2) ;; Remember what we have
MOVX T1,<BRWRD$(NAME,2)> ;; And get it into the ac
> ;; End of IFN $$$CUR^!<BRWRD$(NAME,2)>
IORM T1,2+ADDRESS ;; Turn on the bits
> ;; End of IFN <BRWRD$(NAME,2)>
IFN <BRWRD$(NAME,3)>,< ;; Anything in second word?
IFN $$$CUR^!<BRWRD$(NAME,3)>,< ;; Yes, is this the same as the previous?
$$$CUR==BRWRD$(NAME,3) ;; Remember what we have
MOVX T1,<BRWRD$(NAME,3)> ;; And get it into the ac
> ;; End of IFN $$$CUR^!<BRWRD$(NAME,3)>
IORM T1,3+ADDRESS ;; Turn on the bits
> ;; End of IFN <BRWRD$(NAME,3)>
> ; End of DEFINE SETBRK
; Control S matches any separator character (i.e., any character not
; a letter, number, period, dollar, or percent)
BRINI$(CTS,ALL) ; Initialize to all chars
UNBRK$(CTS,.CHNUL) ; Don't allow nulls to match
UNBRK$(CTS,"%") ; Except %
UNBRK$(CTS,"$") ; Or dollar sign
UNBRK$(CTS,".") ; Or dot
UNBRK$(CTS,"0","9") ; Or a number
UNBRK$(CTS,"A","Z") ; Or upper case letter
UNBRK$(CTS,"a","z") ; Or lower case letter
BRKCH$(CTS,BEGPAG) ; Or start of page
BRKCH$(CTS,ENDPAG) ; Or end of page
CNTLS: SETBRK T1,CTS,BITMAT(P1) ; Set the break set
JRST SCH.6 ; Go return
; Control X matches any single character
BRINI$(CTX,ALL) ; Control-X matches all chars
UNBRK$(CTX,.CHNUL) ; Except a null
CNTLX: SETBRK T1,CTX,BITMAT(P1) ; Set the correct bits
JRST SCH.6 ; Go return
; Control R is the same as Control Q (Provided EO > 1)
; except it doesn't cause rubout problems
CNTLR: CHKEO EO21,SCH.5 ; If EO=1, ^R is just text
; Control Q causes the next character to be taken as text, even if it is
; a control character or the delimiter
CNTLQ: LOAD. T1,TPTADR,(P4) ; Get the next character
PUSHJ P,GETINC ; . . .
POPJ P, ; Done
JRST SCH.2 ; Process with special checks
; Control V causes the next character to be made lower case
; Two Control V's set lower case mode until further notice
CNTLA: CHKEO EO200,SCH.9 ; If before version 200
CNTLV: CHKEO EO21,SCH.5 ; If EO=1, ^V is just text
PUSHJ P,C.V ; Set ^V flags
POPJ P, ; All done
; Control W causes the next character to be taken without case conversion
; Two Control W's set standard case mode until further notice
CNTLB: CHKEO EO200,SCH.9 ; Only version 200 and on
CNTLW: CHKEO EO21,SCH.5 ; If EO=1, ^W is just text
PUSHJ P,C.W ; Set ^W flags
POPJ P, ; Done
; Control \ inverts case match mode, starting at accept either
CNTLBS: CHKEO EO21,SCH.5 ; If EO=1, ^\ is just text
TXC S,S.EMAT ; Complement accept either flag
POPJ P, ; All done
; When searching for ALTmode under EO=1, both ESCape and ALTmode match
CNTLLB: CHKEO EO21,.+2 ; EO=1?
JRST SCH.5 ; No, accept ESCape only
MOVEI T1,000040 ; Yes, mark ALTmode as an acceptable character
IORM T1,BITMAT+3(P1)
JRST SCH.5 ; and ESCape
; Control circumflex causes immediately following @[\]^_ to be converted to
; the appropriate character in the lower case range
CNTLCF: CHKEO EO21,SCH.5 ; If EO=1, ^^ is just text
LOAD. T1,TPTADR,(P4) ; Get the address
PUSHJ P,GETINC ; Get the next character
POPJ P, ; All done
PUSHJ P,CVTSPC ; Convert it to lower case if appropriate
JRST SCH.2 ; Go store this character
; Control T inverts the control character interpretation switch
; The initial setting is that all control character commands are active
; With the switch on, only ^Q, ^R, and ^T commands exist, but all other
; control characters are legal
CNTLT: CHKEO EO21,SCH.5 ; If EO=1, ^T is just text
TXC S,S.NCCT ; Complement current setting
POPJ P, ; Return
; Control N - invert the sense of the following "character", i.e. accept
; anything but the specified character
CNTLN: MOVSI T1,-4 ; Set AOBJN count for the 4 words of this position
HRR T1,P1 ; of the pattern
CTLN.0: PUSH P,BITMAT(T1) ; Save the current status of the pattern (in case
; of ^E[A,^N^EW] for example)
SETZM BITMAT(T1) ; Start over again
AOBJN T1,CTLN.0 ; Loop through this position
CTLN.3: LOAD. T1,TPTADR,(P4) ; Get the buffer address
PUSHJ P,GETINC ; And get a character
JRST CTLN.2 ; None left, go restore entries
PUSHJ P,SCH.1 ; Build the table for the character
JRST CTLN.3 ; Try again
CTLN.2: MOVEI T1,4 ; Now go back through the 4 words
MOVEI T2,BITMAT+3(P1) ; starting at the high end 'cause of stack
CTLN.1: SETCM T3,0(T2) ; complementing the resulting setting
TRZ T3,17 ; (remembering only using 32 bits per word)
POP P,0(T2) ; Get back the original bits
IORM T3,0(T2) ; Include the new bits wanted
SUBI T2,1 ; Back up to previous word (need a ASOBJN)
SOJG T1,CTLN.1 ; and loop through all 4 words
PJRST .POPJ1 ; Return
; Control Gi causes the text in Q register i to be substituted into
; the search string at this point
CNTLG: CHKEO EO21,SCH.5 ; If EO=1, ^G is just text
SETZB T1,CTGSVE ; No default name
MOVEI T2,CTGCHR ; Get the character routine
MOVEI T3,CTGREA ; And the re-eat routine
MOVEI T4,(P4) ; Get the TPT address
PUSHJ P,REDQRG ; And get the Q-reg name (with parens)
JRST [PUSHJ P,CTGCHR ; If not, try normal one
ERROR E.ICG ; Bad
PUSHJ P,QREGV2 ; Get the block address
JRST .+1] ; And continue
PUSH P,P4 ; Save source pointer
MOVEI P4,$QRTPT(T1) ; Get the TPT address
LOAD. T1,TPTADR,(P4) ; Get the Q-register
JUMPE T1,[ERROR E.NTQ] ; No text in Q-reg
SETZ T2, ; Start from start of buffer
PUSHJ P,SETINC ; . . .
JFCL ; Ignore error
PUSHJ P,SCH.0 ; Go process the string as pattern source
POP P,P4
POPJ P, ; And return
; Routines to fetch chars for REDQRG
CTGCHR: SETZ CH, ; Clear CH
EXCH CH,CTGSVE ; Get the saved character
JUMPN CH,.POPJ1 ; Got one, return
$SAVE <T1,T2> ; Save some ac's
LOAD. T1,TPTADR,(P4) ; get the buffer address
PJRST GETINC ; get a character
CTGREA: MOVEM CH,CTGSVE ; Save the character
POPJ P, ; And return
; Control E commands all go through here
CNTLE: CHKEO EO21,SCH.5 ; If EO=1, ^E is just text
LOAD. T1,TPTADR,(P4) ; Get the address
PUSHJ P,GETINC ; And get the character
JRST CNTLER ; Give the error
MOVEI T1,S4TABL ; Set to search for ^E command characters
PUSHJ P,NDISPT ; and look for legal commands (no return if good)
CNTLER: ERROR E.ICE
; Dispatch table for ^E commands
S4TABL: XWD CNTLEA,"A" ; ^EA accept any alpha
XWD CNTLEV,"V" ; ^EV accept any lower case alpha
XWD CNTLEW,"W" ; ^EW accept any upper case alpha
XWD CNTLED,"D" ; ^ED accept any digit
XWD CNTLEL,"L" ; ^EL accept any end of line character
XWD CNTLES,"S" ; ^ES accept a string of spaces and/or TABs
XWD CNTLEN,74 ; ^E<NNN> accept the ACSII character represented by <nnn>
XWD CNTLEB,133 ; ^E[A,B,C] accept A or B or C or ...
XWD 0,0 ; End of list
; Control EA - accept any alphabetic character
CNTLEA: SETBRK T1,ALPH,BITMAT(P1) ; Flag all alphabetics
JRST SCH.6 ; And advance to next char pos
; Control EV - accept any lower case alphabetic character
BRINI$(LOW) ; Make mask for lower case
BRKCH$(LOW,"a","z") ; . . .
CNTLEV: SETBRK T1,LOW,BITMAT(P1) ; Flag lower case letters accepted
PJRST SCH.6 ; Return
; Control EW - accept any upper case alphabetic character
BRINI$(UPP) ; Make uppercase mask
BRKCH$(UPP,"A","Z") ; . . .
CNTLEW: SETBRK T1,UPP,BITMAT(P1) ; Flag uppercase valid
PJRST SCH.6 ; Return
; Control ED - accept any digit
BRINI$(DIG) ; Make digit mask
BRKCH$(DIG,"0","9") ; . . .
CNTLED: SETBRK T1,DIG,BITMAT(P1) ; Flag the digits valid
PJRST SCH.6 ; Return
; Control EL - accept any end of line character (including buffer end)
BRINI$(EOL) ; Make end of line mask
BRKCH$(EOL,.CHLFD,.CHFFD) ; Flag the normal break chars
BRKCH$(EOL,ENDPAG) ; And include the end of page character
CNTLEL: SETBRK T1,EOL,BITMAT(P1) ; Flag the end of line chars
PJRST SCH.6 ; Return
; Control ES - accept any string of spaces and/or TABs
BRINI$(SPC) ; Mask for spaces/tabs
BRKCH$(SPC,.CHTAB) ; Flag the tab
BRKCH$(SPC," ") ; And the space
BRKCH$(SPC,SPCTAB) ; And the special bit
CNTLES: SETBRK T1,SPC,BITMAT(P1) ; Flag the space characters
PJRST SCH.6 ; Return
; Control E[a,b,c,...] - accept any of "characters" a or b or c
CNTLEB: AOS SCNEST ; Remember our nesting level
CTLE.0: LOAD. T1,TPTADR,(P4) ; Get the buffer address
PUSHJ P,GETINC ; get next character
PJRST CNTLER ; Error
PUSHJ P,SCH.1 ; Process the next "character"
JRST CTLE.0 ; Wasn't anything we could store, try again
LOAD. T1,TPTADR,(P4) ; Get the buffer address
PUSHJ P,GETINC ; Get the next character
JRST CNTLER ; Error
SOJL P2,CNTLER ; Error if off end of string
CAIN CH,"," ; Another "character" to come?
JRST CTLE.0 ; Yes, go include it too
CAIE CH,"]" ; No, correct ending to ^E command?
ERROR E.ICE
PJRST SCH.6 ; Return
; Control E<nnn> - accept the ASCII character whose octal representation is nnn
CNTLEN: MOVEI P2,0 ; Clear number accumulator
CTEN.1: LOAD. T1,TPTADR,(P4) ; Get a character
PUSHJ P,GETINC ; . . .
JRST CNTLER ; None there
CAIN CH,">" ; The other end of the number?
JRST CTEN.2 ; Yes, done
CAIL CH,"0" ; Is it an digit?
CAILE CH,"7"
ERROR E.ICE
LSH P2,3 ; Yes, scale up the previous value
ADDI P2,-60(CH) ; and add in the new oit
JRST CTEN.1 ; then go try for more
CTEN.2: CAILE P2,177 ; Make sure it's legitimate
ERROR E.ICE
MOVE CH,P2 ; Copy the result as the character
JRST SCH.5 ; and go set the appropriate bit
; Now we need to build up TECO's standard search table, a 36 bit by 131. word
; table with each pattern position being a slice of the 131 words, with all of
; the acceptable characters for each position marked by a bit on in the word
; reached by using the character directly as an index into the table (the extra
; 3 words are for "beginning of page", "end of page", and "this position matches
; strings of spaces and/or TABs"). At the same time we will set up the two
; simple tables for the fast search algorithm (DELTA0), since it is
; much quicker to do this now if we use the fast one.
; The conversion is done by rotating the 131. bit by 36 word table 90 degrees.
; Since that table was built first (instead of the normal TECO table as in
; standard TECO), the loop is only needed for as many times as there were
; pattern characters (doing it in the other order requires a loop through all
; 131 characters with no possibility for less).
; AC usage:
; P1 AOBJN pointer with "virtual" index into 131 by 36 table (word index/4)
; P2 actual word index into 131 by 36 table
; P3 bit mask specifying pattern position we're currently doing
; P4 AOBJN pointer into the 131 bits of an entry of the 131 by 36 table
; A1 First arg
; T2+T3 current words worth of the 131 bits and the JFFO result
SLARGE==10777777 ; A special large number for DELTA0 used for
; the characters defining the rightmost pattern
; position
ROTATE: MOVN P1,PATLEN ; Get the number of pattern positions used
HRLZS P1 ; as an AOBJN pointer
MOVEI P2,0 ; Clear the actual index
MOVE P3,PATLEN ; Initialize DELTA0 to the number
MOVEM P3,DELTA0 ; of positions in the pattern
MOVE P4,[XWD DELTA0,DELTA0+1]
BLT P4,DELTA0+SPCTAB
SUBI P3,1 ; Pattern length - 1 is the distance we are from
MOVEM P3,ROTLEN ; the end of the pattern at the moment
MOVSI P3,400000 ; Start mask at first pattern position
ROTA.1: MOVSI P4,-BITMLN ; Set AOBJN pointer into the 131 bits
ROTA.2: SKIPE T2,BITMAT(P2) ; Get 32 of those, seeing if any are on
ROTA.3: JFFO T2,[MOVSI T4,400000 ; and if any are, see which the first one is
MOVN T1,T3 ; Got one, make a mask to turn it off
LSH T4,0(T1)
ANDCM T2,T4 ; and do so
ADDI T3,0(P4) ; Add 0, 32, 64, or 96 to the bit number
IORM P3,SMATRX(T3) ; and turn on the position bit for the character
SKIPN T1,ROTLEN ; Get the current distance from the right end of the pattern
MOVX T1,SLARGE ; At the right, change to the special number
MOVEM T1,DELTA0(T3) ; Set that in fast loop table
JRST ROTA.3] ; On to next bit
ADDI P2,1 ; Finished a word of the 131 bit string
ADDI P4,^D31 ; Next word is 32 farther into the 36 by 131 table
AOBJN P4,ROTA.2 ; Loop until all 131 bits done
LSH P3,-1 ; On to the next pattern mask position
SOS ROTLEN ; and distance from the end
AOBJN P1,ROTA.1 ; and loop through all used pattern position
; Now determine which search method we will use. If ^ES appeared we have to use
; the old slow method. Initially if we need to match BEGPAG or ENDPAG, we will
; use the old method. Also we will arbitrarily select 3 as the shortest string
; which will benefit from using the new search. As an aid, turn off the BEGPAG
; and ENDPAG bits which don't appear at the appropriate end of the pattern,
; since they obviously won't match except there.
FIGSCH: SETZB P3,SCHTYP ; Assume an old style search
MOVN P1,PATLEN ; Generate a bit mask for the last pattern
MOVSI P4,400000 ; position used in this search
ANDM P4,SMATRX+BEGPAG; (with a side effect of clearing extra begin page bits)
LSH P4,1(P1)
MOVE P1,PATLEN ; Now see how long the pattern is
CAILE P1,2 ; If it is fewer than 3 positions long,
SKIPE SMATRX+SPCTAB ; or if there were any ^ES positions,
POPJ P, ; just go return and user old search
ANDM P4,SMATRX+ENDPAG; We know pattern is longer than 1, so clear extra end page bits
SKIPN SMATRX+BEGPAG ; If either end of buffer will match,
SKIPE SMATRX+ENDPAG ; ...
POPJ P, ; Just return and use the old method
SETOM SCHTYP ; We win with the new one, remember that in case
; this was an nSFOO$ type
; We are going to use the new search, set up the more costly DELTA2 table.
; This table is based on the arrangement of characters in the pattern.
; It uses the existence (or non-existance) of matching substrings in the
; pattern to be able to shift the pattern farther than would be indicated by
; DELTA1, e.g. if the pattern is ACACACACACAABC and the part of the searched
; string being examined is CABC, DELTA1 will only shift the pattern right 3
; positions, while "looking" at the pattern will tell a human observer that
; the pattern can be shifted its whole length without missing any possible
; matches.
; A few bits in P2 for use during the DELTA2 setup
NEDSET==1B35 ; This position of DELTA2 still needs setting up
WNTOFF==1B34 ; We shifted off the end of the pattern this pass
FSTIME==1B33 ; This is the first pass - use a special value instead of
; having to initialize the index matrix (INDMAT)
; AC usage (see comment at ROTATE)
; T4 the highest entry currently being used in INDMAT
; P4 a number used to indicate how far the pattern can be shifted when we
; find a mismatch between sub-pattern strings
; P2 used for the above flag bits
; A2 index into INDMAT for updates to it as matches occur in sub-patterns
; CH index into INDMAT for loop
; P3 index into pattern (*4 since 4 words per pattern position)
; J temporary index into pattern (also *4)
; P1 AOBJN pointer
; A1 1st argument for search
; We want to look for sub-strings in the pattern matching rightmost sub-strings
; of the pattern. If none are found, then as in the above example when more than
; one pattern position has been matched we know we can shift farther than to
; the next occurance of single pattern characters. If some matches are found
; then we can try them next immediately.
; The examination is implemented by using an array of pointers (indices into
; the pattern) (INDMAT), stored in decreasing order and overwritten each pass
; by the pointers for the next pass. When I points to the beginning of the
; rightmost n characters of the pattern, then each pointer in INDMAT points
; to the beginning of a sub-string which matches those n characters. When
; INDMAT has been emptied, all of these sub-strings have been matched and the
; rest of DELTA2 can be set to shift the pattern its entire length. The
; initial setting of INDMAT (implemented by FSTIME) is such that every pattern
; position is examined on the first pass.
MOVEI T4,-1(P1) ; Start the top of INDMAT at pattern length - 1
MOVEI P4,-1(P1) ; Start the non-match shift at pattern length
; (adjusted because a 0-index is subtracted from it)
MOVX P2,NEDSET!FSTIME ; The first setting is needs setting, first pass,
; and haven't gone off the end
MOVEI P3,-1(P1) ; Start at right end of pattern (0-indexed)
LSH P3,2 ; adjusted for being 4 word bit strings
MOVEI P1,0(P3) ; Set initial INDMAT value to shift all less 1
; remembering the first SUBI 4
SET2.2: MOVEI A2,0 ; Start used INDMAT entry index off at none
MOVN CH,T4 ; Make an AOBJN pointer for loop through INDMAT
HRLZS CH
SET2.3: TXNN P2,FSTIME ; Get the appropriate INDMAT entry
SKIPA P1,INDMAT(CH) ; Not the first time, use the real array
SUBI P1,4 ; The first pass, use our fake value
MOVE T2,BITMAT(P3) ; Figure out if any of the characters matched
AND T2,BITMAT(P1) ; by the position we are looking at at highest
MOVE T3,BITMAT+1(P3) ; level (P3) also match at the position indicated
AND T3,BITMAT+1(P1) ; by the substring table (INDMAT - D)
OR T2,T3
MOVE T3,BITMAT+2(P3) ; (AND the strings together, if result is zero
AND T3,BITMAT+2(P1) ; then no characters match)
OR T2,T3
MOVE T3,BITMAT+3(P3)
AND T3,BITMAT+3(P1)
OR T2,T3
JUMPE T2,SET2.5 ; If zero, no matches here
JUMPE P1,SET2.4 ; Did we just match with the leftmost position?
MOVEI T1,-4(P1) ; No, update the index matrix to check the position
MOVEM T1,INDMAT(A2) ; in front of this for finding substrings
AOSA A2 ; Remember we used another element of INDMAT
SET2.4: TXO P2,WNTOFF ; We matched at the left end, that goes off the end
SET2.5: TXNN P2,NEDSET ; Do we still need to set up this position?
JRST SET2.6 ; No, skip all the logical stuff
MOVE T2,BITMAT(P1) ; Yes, then we need to figure out if the substring
ANDCM T2,BITMAT(P3) ; indicated position (P1) character set is a
MOVE T3,BITMAT+1(P1) ; subset of the high level (P3) character set
ANDCM T3,BITMAT+1(P3) ; (Done by D .AND. .NOT. I .NE. 0)
OR T2,T3
MOVE T3,BITMAT+2(P1)
ANDCM T3,BITMAT+2(P3)
OR T2,T3
MOVE T3,BITMAT+3(P1)
ANDCM T3,BITMAT+3(P3)
OR T2,T3
JUMPE T2,SET2.6 ; Skip out if it's not
TXZ P2,NEDSET ; It is, don't do this again
MOVNI T1,4(P1) ; We now know that we can shift at least as much
ASH T1,-2 ; as the distance from here to the right end
ADD T1,PATLEN ; since no substrings matched from here to there
MOVE T3,P3 ; Figure out where to put it with
LSH T3,-2 ; a word table
MOVEM T1,DELTA2(T3) ; Put it there
SET2.6: AOBJN CH,SET2.3 ; Loop through current index matrix
TXZ P2,FSTIME ; Finished the first pass
MOVE T4,A2 ; Remember the highest index matrix element used
TXOE P2,NEDSET ; Do we still need to set this position?
JRST [MOVE T1,P4 ; Yes, then we can shift it based on how
MOVE T2,P3 ; far the highest level loop is from
LSH T2,-2 ; the right end of the pattern
SUB T1,T2
ADD T1,PATLEN
MOVEM T1,DELTA2(T2)
JRST .+1]
TXZE P2,WNTOFF ; Did this pass go off the end of the pattern
JRST [MOVEI P4,-4(P3) ; Yes, need to adjust the amount we
LSH P4,-2 ; can shift when NEDSET is used
JRST .+1] ; immediately above
SUBI P3,4 ; Now look a position to the left of last loop
SKIPE T4 ; unless there is no need to cause no matches
JUMPGE P3,SET2.2 ; or because we looked at all of them
JUMPL P3,SET2.E ; Did we look at all of them?
ADD P4,PATLEN ; No, need to fill in the rest with the largest
LSH P3,-2 ; possible number based on how far we are from
SUB P4,P3 ; the right end of the pattern and how far the
; setup got
MOVEM P4,DELTA2(P3)
ADDI P4,1 ; Each position to the left can shift one farther
SOJGE P3,.-2
SET2.E: POPJ P, ; Return with matrix set up
SUBTTL Searches -- S$SEARCH -- Execute the matrix
;+
;.hl1 S$SEARCH
;This routine will do the searching. It will determine if the slow or the
;fast algorithm is to be used. It will then dispatch to the correct routine
;to do the searching.
;-
S$SEARCH:
SCHLOP: TXNN S,S.MINS ; If this time is minus search, force old search
SKIPN SCHTYP ; Which one are we using?
JRST SLOSCH ; The old one
; JRST FSTSCH ; The new one, fall into it
SUBTTL Searches -- S$SEARCH -- Fast search
; This is an implementation of the algorithm of Boyer and Moore, published
; in the Communications of the ACM, October 1977, Vol. 20 Number 10, page 762.
; This article serves as the primary documentation for this routine (and the
; DELTA? table setup routines).
; This is the actual search, which uses the numbers in DELTA0, DELTA1, and
; DELTA2 for determining where in the searched string to look. The actual
; character comparisons are done in the tried and true TECO way, with TECO's
; original bit map (there can't be a better way).
; AC usage (ditto)
; A1 Updates first arg for nSFOO$$ search
; A2 A negative index into the byte pointer table
;
; P1 The length of the string to be searched
; P2 The base register into the byte pointer table, including
; P3 The current character address within the buffer.
; P4 Contains the bit mask for the last pattern position
;
; T1 During the slow loop, shifts the bit mask through the pattern
; T2 The word address of the first byte of the portion of the searched
; string currently being examined
; T3 The value of A2 (negative character index) at the start of the current
; FAST and SLOW loop execution
; T4 During the slow loop, counts down through the pattern
; The bytes in the searched string are obtained through a window by a table of
; constant byte pointers indexed into by P2, T2, and A2.
FSTSCH: MOVN T1,PATLEN ; Generate the bit mask for the rightmost
MOVMM T1,CSRLEN ; Save the current length in case of success
MOVX P4,1B0 ; pattern position
LSH P4,1(T1)
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the address of the buffer
LOAD. P3,BLKPT,(T1) ; Get the character address of PT
MOVE P1,UPPERB ; Figure out how many characters are to be searched
SUB P1,P3 ; i.e. the length of the searched string
;[1012]; Fix calculation of "searched string" length to be correct. This
;[1012];avoids having the final character of the search string match the
;[1012];character after the end of the string.
;[1012]; ADDI P1,1
TXNE F,F.ARG ; Is this an nSFOO$$?
JUMPLE A1,SCHFND ; Yes, done if we've found that many
MOVX P2,<0(A2)> ; Start the byte pointer base at 0(C)
FSTS.1: MOVE T2,P3 ; Convert I into a word and byte address
IDIVI T2,5
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the address of the current text buffer
ADDI T2,.BKTLN(T1) ; Update it
MOVE T1,P1 ; Figure the current byte pointer window length
CAILE T1,SCHBPL ; the length of string left
MOVEI T1,SCHBPL ; or the window size, whichever is less
; Fall through to next page...
MOVN A2,T1 ; Copy that as negative index into table
ADD T1,T3 ; Add the byte in word offset
ADDI T1,SCHBPT-1 ; plus the address of the start of the table
HRR P2,T1 ; equals the base address to be negatively
; indexed from
ADD A2,PATLEN ; This search starts at the right end of the pattern
JUMPG A2,SCHNFD ; If that is to the right of the last character
; of the string, then we didn't find it
MOVE T3,A2 ; Save C at the start of the loop, so we can
; tell how many characters we've skipped
; FAST: ; The fast loop in the ACM article
FSTS.3: LDB CH,@P2 ; Get a character from the searched string
ADD A2,DELTA0(CH) ; Shift down based on its existance in the pattern
JUMPLE A2,FSTS.3 ; and loop unless it is in the rightmost position
; i.e. if we just had a match (see LARGE)
TLON A2,-1 ; Did it match (SLARGE makes the left half 7)
JRST FSTS.5 ; No, we used up our window (left half is zero)
MOVE T1,P4 ; Start at right end of pattern bit mask
MOVE T4,PATLEN ; for that many characters
; SLOW: ; SLOW loop in ACM article
FSTS.4: SOJLE T4,FSTS.6 ; If we run out of pattern characters, it matched
LSH T1,1 ; Set bit mask to previous pattern position
LDB CH,@P2 ; Get the next searched string character
TDNE T1,SMATRX(CH) ; Does it match?
SOJA A2,FSTS.4 ; Yes, back up byte pointer index one and loop
MOVE T1,DELTA0(CH) ; No, figure which table shift us the most
TLNN T1,-1 ; If we just got SLARGE, use DELTA2 always
CAMGE T1,DELTA2-1(T4)
MOVE T1,DELTA2-1(T4)
ADD A2,T1 ; Update our current position by that much
JUMPL A2,FSTS.3 ; and go back to FAST unless we exceeded window
; Search failed in this window, see what to do
FSTS.5: JUMPLE P1,SCHNFD ; Not found if there is no searched string left
SUB A2,T3 ; See how many characters we skipped
ADDI P3,0(A2) ; Update current position by that much
SUBI P1,0(A2) ; and amount left by that much
JRST FSTS.1 ; and try again
; Here when string found, decide where the right end of the pattern is
FSTS.6: SUB A2,T3 ; How much we moved
ADD P3,A2 ; Adjust pointer by that much
ADD P3,PATLEN ; but we scanned back by that much too
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the address of the text buffer
STOR. P3,BLKPT,(T1) ; Store the new address
ADD P3,PATLEN ; Now get to right end of pattern
JRST SCHFND ; We did it
; Build the fixed byte pointer table. The following code is done again
; under an XLIST
SCHBPL==^D200 ; Length of window of byte pointers
$A==0 ; Start the base address at zero
; SCHBPT:REPEAT SCHBPL/5+1,< ; Build 5 for each word of bytes, plus extra for
; ; the fact that the first byte may be one of 5
; $M==177B6 ; A mask for the current character of the word
; REPEAT 5,< ; For each word of bytes
; POINTR $A(T2),$M ; Build 5 pointers
; $M==$M_-7 ; Moving mask each time
; >
; $A==$A+1 ; To next word
; >
XLIST
SCHBPT:
IF1,<
BLOCK SCHBPL+5
>
IF2,<
REPEAT SCHBPL/5+1,<
$M==177B6
REPEAT 5,<
POINTR $A(T2),$M
$M==$M_-7
>
$A==$A+1
>
>
LIST
SUBTTL Searches -- S$SEARCH -- Slow algorithm
;+
;.HL1 SLOSCH
;This routine will do the slow search through the text buffer. It does the
;search as a character by character match.
;-
SLOSCH: LOAD. P2,TPTADR,+$QRTPT+TXTBUF ; Get the address of the text buffer
MOVN T1,PATLEN ; Figure old end of search comparator
MOVX P4,1B0 ; Get a bit to shift (1st character)
LSH P4,0(T1) ; Which is bit one past end of pattern
LOAD. P3,BLKPT,(P2) ; Get the character address of PT
S1: TXNE F,F.ARG ; Is there an argument ?
JUMPLE A1,SCHFND ; Yes - Seen string N times yet ?
MOVE T2,P3 ; No - Form the byte pointer which will be used
SUBI T2,1 ; It will be incremented before use
IDIVI T2,5 ; Determine the byte offset
ADDI T2,.BKTLN(P2) ; Add in the offset to the text
HLL T2,BTAB(T3) ; Fill in the rest of the byte pointer
MOVX P1,1B0 ; Start seeking match for first character
MOVE T3,T2 ; Set the dynamic pointer to the static
CAML P3,UPPERB ; Any room left to search?
JRST SLOS.X ; No, all done (unless backwards)
JUMPG P3,S4A ; At the beginning of the buffer ?
SKIPL SMATRX+BEGPAG ; And 1st search character
; is the beginning of buffer character ?
JRST S4A ; No
MOVX P1,1B1 ; Yes - Start the search at the second character
MOVE T3,T2 ; Set the dynamic pointer to be the static
SETOM BCOUNT ; Flag first is the beginning of the page
JRST S4B ; Enter the search loop
S3: MOVX P1,1B0 ; Start seeking match for first character
MOVE T3,T2 ; Set the dynamic pointer to the static
JRST S4A
S4: TDNE P1,SMATRX+SPCTAB ; IS SPACE/TAB STRING BIT SET?
JRST SPTB ; YES
S4E: CAML P3,UPPERB ; DON'T ALLOW I OUTSIDE BOUNDS
JRST S4D ; ...
ADDI P3,1 ; LOOK AT NEXT LOC, XCEPT 1ST TIME THRU
S4C: LSH P1,-1 ; ADVANCE TO NEXT CHAR POSITION
S4B: CAMN P1,P4 ; END OF SEARCH TABLE?
JRST SCHFND ; YES.
S4A: ILDB CH,T3 ; NO, GET NEXT CHAR
TDNE P1,SMATRX(CH) ; IS IT A MATCH?
JRST S4 ; YES, GO TO NEXT TABLE ENTRY.
S4D: AOSN BCOUNT ; IF WE FAILED WITH BEGPAG
JRST S3 ; THEN TRY AGAIN WITH 1ST CHAR
TXNE S,S.MINS ; BACKWARDS SEARCH
JRST SR4A
CAML P3,UPPERB ; TOO FAR?
JRST SLOS.Z ; Check the boundary condition
INCR. P3,BLKPT,(P2) ; Increment the pointer
IBP T2 ; Move the static byte pointer
JRST S3 ; And keep looking
SR4A: DECR. P3,BLKPT,(P2) ; Decrement the pointer
CAMGE P3,LOWERB ; Done ?
JRST SLOS.Z ; Check the boundary condition
ADD T2,[7B5] ; Decrement the byte pointer
JUMPGE T2,S3 ; Jump it needs no fix it up
HRLI T2,(POINT 7,,34); Fix it up
SOJA T2,S3 ; Decrement the address and go
; Skip over a string of spaces and/or TABs while searching
SPTB: CAIE CH," " ; But was the character we matched a
CAXN CH,.CHTAB ; space or a TAB?
JRST SPTB.1 ; Yes, then accept more
JRST S4E ; No, look at next pattern position
SPTB.1: ADDI P3,1 ; Advance to next buffer location
CAML P3,UPPERB ; End of buffer?
JRST S4C ; Yes, no more then
MOVE T4,T3 ; Save current byte pointer
ILDB CH,T3 ; Look at next character
CAIE CH," " ; Is it a space?
CAXN CH,.CHTAB ; or a TAB?
JRST SPTB.1 ; Yes, keep on trucking
MOVE T3,T4 ; No, End of string, restore
; the pointer to last space or tab
JRST S4C ; and continue search
; Here to check to see if we have a minus search and are starting at the
; end of the buffer. It we are then we just check to see if the end of
; page is a valid match and continue backwards.
SLOS.X: TXNN S,S.MINS ; Minus search?
JRST SLOS.Z ; No, try for matching Z in foward
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the address of the text buffer
TDNN P1,SMATRX+ENDPAG ; End of page allowed?
JRST SR4A ; No, continue on
CFME. ,BLKEND,(T1),P3 ; Yes, but only if we are at Z
JRST SR4A ; No, continue on
JRST SCHFND ; Found
; Here to do a boundary check for the end of the buffer and the end
;being allowed.
SLOS.Z: LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the address of the text buffer
TDNN P1,SMATRX+ENDPAG ; End of page good match for a match here ?
JRST SCHNFD ; It is not, just fail
CFME. ,BLKEND,(T1),P3 ; Yes, but only if we're at Z
JRST SCHNFD ; Not found, give up
FALL SCHFND ; Found it, do end of search bookkeeping
SUBTTL Searches -- S$SEARCH -- Found string and loop
SCHFND: SETOM SFINDF ; Flag we found at least one
LOAD. P1,TPTADR,+$QRTPT+TXTBUF ; Get the address of the current text buffer
LOAD. P4,BLKPT,(P1) ; Get the address of PT
SUBM P3,P4 ; Determine the length
MOVE P2,P3 ; Save the current pointer
TXNE S,S.MINS ; Is this a minus search ?
DECR. P3,BLKPT,(P1) ; Decrement PT
STOR. P3,BLKPT,(P1) ; Store the new PT
SOJG A1,SCHLOP ; Loop if more to look for
MOVEM P4,CSRLEN ; Save the length of the search string
ZERO. T1,BLKCOL,(P1) ; Clear the column
TXNE S,S.MINS ; Minus search?
TXNN S,S.RVRS ; Yes, want to leave at start?
JRST SFND.1 ; Either not minus, or want to stay at end
INCR. ,BLKPT,(P1) ; Minus search, leave pointer at start
PJRST .POPJ1 ; And return
SFND.1: STOR. P2,BLKPT,(P1) ; Update it otherwise
JRST .POPJ1 ; Just return if we found them all
SUBTTL Searches -- Here for the true return for a search
;+
;.hl1 S$TRETURN
;This routine is called to do the normal found routine for a search.
;It will do the auto type out processing and return the correct value
;if the search is in a loop and depending on the EO level.
;-
S$TRETURN:
PUSHJ P,S$AUTOTYPE ; Do the auto type out
MOVE T1,CSRLEN ; Get the length of the string we found
MOVEM T1,SRHLEN ; Save it
TXZE F,F.COLN ; Colon search ?
JRST RTONES ; Yes - Return a minus one
CHKEO EODEC,S$TR.0 ; If old TECO, must check for < ... >
POPJ P, ; Just return
S$TR.0: CFXE. T1,XSBTYP,(XS),$XELOP ; In an interaction ?
POPJ P, ; Just return
JRST RTONES ; Return a minus one
SUBTTL Searches -- Autotype after succesful searches
;+
;.hl1 S$AUTOTYPE
;This routine will do the auto type out after a successful search.
;-
S$AUTOTYPE:
TXNE F,F.COLN ; Auto type out on colon searches ?
POPJ P, ; No - Just return
CFXE. T1,XSBTYP,(XS),$XELOP ; In an interaction ?
SKIPN AUTOF ; Auto type out wanted ?
POPJ P, ; No - Return
TXO F,F.ARG ; Flag we have an argument
MOVX A1,0 ; It is a zero
PUSHJ P,TYPE ; Go type it
HRRZ CH,AUTOF ; Get the flag character
SKIPL AUTOF ; Do we want it ?
PUSHJ P,T$OCHR ; Yes - Type it
MOVX A1,1 ; Get the 1T command
PUSHJ P,TYPE ; Type it
TXZ F,F.ARG ; Clear the flag
POPJ P, ; Return to the caller
SUBTTL Searches -- S$SEARCH -- Not found, clear the pointer
SCHNFD: MOVE T1,PATLEN ; Get the length of the string
MOVMM T1,CSRLEN ; Save the length
LOAD. T1,TPTADR,+$QRTPT+TXTBUF ; Get the address of the current text buffer
ZERO. ,BLKPT,(T1) ; Make the pointer be at the begining of the buffer
ZERO. T2,BLKCOL,(T1) ; Clear current column
SETZM SFINDF ; SFINDF=0
POPJ P, ; Return to the caller
SUBTTL Searches -- S$FRETURN - Common failure return
;+
;.HL1 S$FRETURN
;This is the common failure return exit routine. This routine will restore
;the pointer if needed.
;-
S$FRETURN:
CHKEO EODEC,S$FR.1 ; Leave pointer at top for EO of 2 or less
MOVE T4,SAVEPT ; Get the old PT
STOR. T4,BLKPT,(T1) ; Restore it
S$FR.1: TXZE F,F.COLN ; Colon modified?
JRST S$FR.0 ; Yes, return a 0
CFXE. T1,XSBTYP,(XS),$XELOP ; Is the last thing stacked an iteration?
ERROR E.SRH ; No, give error message
CHKEO EODEC,S$FR.0 ; Must return value in iteration?
TXNE S,S.NRAD ; Null insert ?
TXO F,F.DONE ; Flag done
POPJ P, ; Return to the caller
S$FR.0: TXNE S,S.NRAD ; Null insert?
TXO F,F.DONE ; Yes, flag we are done
PJRST RETZER ; And return a zero
SRHMOD: EXP SRCHSW ; DEFAULT SEARCH MODE
SUBTTL Data segment
; The following is the impure storage for TECSRH
$IMPURE ; Go to the IMPURE PSECT
LOWVER(SRH,4) ; Low segment version number
; Info for ^G q-register name scanning
CTGSVE: BLOCK 1 ; Saved character
SRHTPT: BLOCK 1 ; TPT for current part of search string
SRHBLK: BLOCK .BKTLN+^D36 ; Header for search string
SRHARG==SRHBLK+.BKTLN ; Address of text portion of buffer
; Search bounds
UPPERB: BLOCK 1 ; Upper bound
LOWERB: BLOCK 1 ; Lower bounds
SAVEPT: BLOCK 1 ; Saved value of PT
; Misc
SRHLEN: BLOCK 1 ; Length of last search string found
CSRLEN: BLOCK 1 ; Length of current search string
; (including possible ^Es items)
SRHSTA: BLOCK 1 ; Start of the search area
SFINDF: BLOCK 1 ; Search flag
INSLEN: BLOCK 1 ; Length of the string
BCOUNT: BLOCK 1 ; Flag for checking BEGPAG in slow search
SRHCTR: BLOCK 1 ; Number of characters in search argument
; (Must precded SRHARG)
ARGTRM: BLOCK 1 ; FS, FN 2nd argument terminator
SRHCNT: BLOCK 1 ; Search count store
PNT.P2: BLOCK 1 ; Pointer store (I)
; Search table stuff
; *** DO NOT SEPERATE ***
; VVVVVVV
SMATRX: BLOCK SMATLN ; The old search bit table
BITMAT: BLOCK BITMLN*^D36 ; The new rotated search bit table
DELTA2: BLOCK ^D36 ; The table which knows what the pattern looks like
SCLRLN==.-SMATRX ; Length
; ^^^^^^^
; *** DO NOT SEPERATE ***
DELTA0: BLOCK SMATLN ; The tables which known shere character are in the pattern
INDMAT: BLOCK ^D36 ; A table of indicies into the pattern
PATLEN: BLOCK 1 ; Number of positions in the pattern
ROTLEN: BLOCK 1 ; Current distance from the right end
; of the pattern
SCNEST: BLOCK 1 ; Nest level counter during searches, 0 if none
SCHTYP: BLOCK 1 ; 0 if old TECO search, -1 if new search
SCTLGA: BLOCK 1 ; 0 If pattern has no ^G, -1 if it does
SUBTTL End of TECSRH
END ; End of TECSRH