EXTERNAL INTEGER FN MATCH ADDR (INTEGER PATTERN ADDRESS, PATTERN LENGTH, C RANGE ADDRESS, RANGE LENGTH) ! Scans a row of RANGE LENGTH bytes at RANGE ADDRESS to find the first ! slice which matches the pattern of PATTERN LENGTH bytes at PATTERN ADDRESS. ! Returns the address of the first byte of the slice, if found: otherwise ! returns zero. The pattern may overlap the range at either end. A zero ! length pattern will produce a match and return a copy of RANGE ADDRESS ! as the result. Otherwise zero or negative lengths, or lengths not less ! than 2**24, will produce a result of zero. If the pattern is longer than ! the range then a zero result will also be returned. LONG INTEGER SD INTEGER D UNLESS 0<RANGE LENGTH<=X'00FFFFFF' C AND 0<=PATTERN LENGTH<=X'00FFFFFF' C THEN RESULT = 0 IF PATTERN LENGTH=0 THEN RESULT = RANGE ADDRESS D = RANGE LENGTH - PATTERN LENGTH + 1; ! A match may start at any offset from 0 ! to D-1 within the range, so this is ! the number of bytes that can usefully ! be scanned for instances of the first ! byte of the pattern. IF D<=0 THEN RESULT = 0 *LDTB_X'18000000'; ! Byte vector descriptor. *LDB_PATTERN LENGTH *LDA_PATTERN ADDRESS *LB_(DR ); ! Pick up first byte of pattern. *STD_SD; ! Save descriptor to pattern. *LDB_D; ! Construct descriptor to range (only ! the bytes which need to be checked ! against the leading byte of pattern). *LDA_RANGE ADDRESS SCAN: *SWNE_L =DR ; ! Mask=0, Ref=1st. byte of pattern ! (in B register). *JCC_8,<NOT FOUND>; ! -> if no match found. ! ! DR points to byte in range which matches first byte in pattern. *STD_TOS ; ! Save the pointer to it. *LDTB_SD; ! Pick up length of pattern. *LSD_SD; ! Acc points to pattern. *CPS_L =DR ; ! Try to match pattern. *JCC_8,<FOUND>; ! -> if match found. *LD_TOS ; ! If no match found, recover ! descriptor to residue of range, *MODD_1; ! skip past the last byte tested, *J_<SCAN>; ! and try again. FOUND: *LSS_TOS ; ! Match found: pick up address where *EXIT_-64; ! it was found, and return that. NOT FOUND: RESULT = 0 END END OF FILE