FSearch

Blurb

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.

Prerequisites

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.

What FSearch does

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 :
  
Generated with sb2htm on 2025 Dec 12