FSearch is a simple, skeletal, program to demonstrate the use of the XSEARCH and FMUL2MEMT% functions. It is also supposed to be useful, namely in order to let you search files for the presence of some word or byte sequence. The main thing, however, is that the main routine, FSearch, can be extracted and made use of for some project of your own, to save you from having to reinvent the fiddly bits, and concentrate on the bigger picture of what you want to do.
This program can be RUN under SuperBASIC or EXECuted as an SBASIC program (SMSQ/E only (and perhaps MultiBASIC with a wee bit of twiddling)). The compiled version can, of course, be EXECuted on most QL platforms. In its SBASIC form it requires that the FINDNAME% command is present. This could be loaded with your boot program.
For Super- and Minerva BASIC you should LRESPR the two mentioned toolkits first, or edit the program accordingly. The compiled version only needs Qlib_run or equivalent preloaded.
FSearch uses a medium sized buffer to load a file, or part file, into memory, where it can be quickly searched, using a slightly modified version of Simon Goodwin's very nice Msearch V0.8 routine from his DIY toolkit volume X.
The buffering thing is done like this: If the whole file fits into the buffer, then it is loaded with LBYTES. If it doesn't fit, then a buffer load at a time is fetched using FMUL2MEMT%. The partial file is scanned, and if the item searched for is not found, the routine backtracks the length of the search item and then loads the next portion into the buffer. This is repeated until the first instance of the looked for item is found or the end of the file reached.
As I said before, this program is only a simple demonstration of the core facilities of both XSEARCH and FMUL2MEMT%. One could expand on this to make it a more versatile program - or use it as part of some other project. (Or forget about the whole thing and go and sniff some more soldering flux.. ;o)
1 rem $$asmb=dev4_mem_search_XSEARCH_BIN,0,10 2 rem $$asmb=dev4_io_iob_IOB2MEMT_BIN,0,10 3 : 4 EXT_FN 'XSEARCH', 'FMUL2MEMT%' 5 : 10 rem + ************************************************************************ + 11 rem *< File Search >* 12 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 13 rem * FSearch function and harness to test * 14 rem * * 15 rem + ------------------------------------------------------------------------ + 16 rem * V0.01, pjw, 2025 Dec 12 * 17 rem + ************************************************************************ + 18 : 19 rem $$off 20 IF PEEK$(\\-4, 4) = 'SBAS' THEN 21 CLOSE: CLCHP: rem Tidy after any (failed) previous run 22 IF NOT FINDNAME%("XSEARCH"): LRESPR 'dev4_mem_search_XSEARCH_BIN' 23 IF NOT FINDNAME%("FMUL2MEMT%"): LRESPR 'dev4_io_iob_IOB2MEMT_BIN' 24 END IF 25 rem $$on 26 : 27 buffer = 4096: rem Buffer, max 32766b 28 t% = -1: rem Timeout (only needed if using IOB2MEMT%) 29 addr = ALCHP(buffer): rem Use same buffer for repeated runs 30 : 31 dc = FOPEN("con_252x62a128x96"): rem For Qdos 32 REPeat main 33 CLS#dc 34 INPUT#dc; 'Full name of file to search'\, ifn$ 35 IF LEN(ifn$) = 0: EXIT main 36 REPeat sloop 37 INPUT#dc; 'Enter string to search for'\, ss$ 38 l% = LEN(ss$) 39 IF l% = 0: EXIT sloop 40 DIM rtv$(l%): rtv$(0) = l%: rem Used to check for correct return value 41 : 42 fnd = FSearch(ifn$, ss$) 43 IF fnd >= 0 THEN 44 ch = FOP_IN(ifn$): BGET#ch\ (fnd), rtv$(1 TO l%): CLOSE#ch 45 PRINT#dc; 'Found "'; rtv$; '" at file position'! fnd 46 ELSE 47 PRINT#dc; '"'; ss$; '" not found', fnd 48 END IF 49 PRINT#dc 50 END REPeat sloop 51 END REPeat main 52 PRINT#dc; 'Finished': PAUSE 50 53 : 54 CLOSE#dc 55 RECHP addr 56 : 57 : 100 rem + ------------------------------------------------------------------------ + 102 rem |< FSearch >| 104 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 106 rem | Search a file for a given string | 108 rem | | 110 rem | A suitable buffer of min string length and max 32k must have been | 112 rem | reserved in advance. If file larger than buffer one buffer length is | 114 rem | processed at the time. | 116 rem | | 118 rem | GLOBal buffer = buffer size, addr = buffer address, (t% = timeout) | 120 rem | Dependencies: Either FMUL2MEM% or FMUL2MEMT%, and XSEARCH | 122 rem + ------------------------------------------------------------------------ + 124 rem | V0.01, pjw, 2023 Jun 01 | 126 rem | V0.02, pjw, 2025 Dec 11, returns position in file and not only in buffer | 128 rem + ------------------------------------------------------------------------ + 130 : 132 DEFine FuNction FSearch(fnm$, str$) 134 LOCal loop, ch, l, fleng, er 136 LOCal part, remain, fps 138 : 140 l = LEN(str$): IF l = 0: RETurn 0 142 : 144 ch = FOP_IN(fnm$): IF ch < 0: RETurn ch 146 fleng = FLEN(#ch): IF l > fleng: CLOSE#ch: RETurn -7 148 : 150 IF fleng <= buffer THEN 152 CLOSE#ch 154 LBYTES fnm$, addr 156 er = XSEARCH(addr, fleng, str$) 158 IF er > 0: RETurn er - addr 160 RETurn -7 162 END IF 164 : 166 part = buffer: fps = 0 168 remain = fleng 170 : 172 REPeat loop 174 IF remain < part THEN 176 part = remain 178 remain = 0 180 ELSE 182 remain = remain - part 184 END IF 186 : 188 er = FMUL2MEMT%(#ch; t%, part, addr) 190 IF er <= 0 THEN 192 IF er = 0: er = -10 194 EXIT loop 196 END IF 198 : 200 er = XSEARCH(addr, part, str$) 202 IF er OR remain = 0 THEN 204 IF er = 0 THEN 206 er = -7 208 ELSE 210 er = er + fps - addr 212 END IF 214 EXIT loop 216 END IF 218 : 220 remain = remain + l 222 fps = fps + part - l 224 : 226 GET#ch\ FPOS(#ch) - l 228 END REPeat loop 230 : 232 CLOSE#ch 234 RETurn er 236 END DEFine FSearch 238 : 240 :