BBS:      TELESC.NET.BR
Assunto:  docs/boolsrch.md src/sbbs3/boolsrch.c boolsrch.h boolsrch_test.cctrl/t
De:       Rob Swindell (on Windows 11)
Data:     Sun, 17 May 2026 18:45:24 -0700
-----------------------------------------------------------
https://gitlab.synchro.net/main/sbbs/-/commit/64cf7e3d7f7a26349f1e009a
Added Files:
	docs/boolsrch.md src/sbbs3/boolsrch.c boolsrch.h boolsrch_test.c
Modified Files:
	ctrl/text.dat exec/load/text.js src/sbbs3/listfile.cpp objects.mk prntfile.cpp readmail.cpp readmsgs.cpp sbbs.jsdocs.vcxproj sbbs.vcxproj scandirs.cpp scansubs.cpp text.h text_defaults.c text_id.c
Log Message:
boolsrch: add boolean text-search engine (issue #1139)

PCBoard/Wildcat-compatible boolean search syntax (AND/OR/NOT with parens,
quoted phrases for whole-word match) for the four "Text to search for"
prompts: message-base scan/F-find, private mail / search, file-listing
search, and the less-style file pager. Bare-word queries keep their
current case-insensitive substring semantics, so existing usage is
unchanged; the new operators unlock multi-term searches that the old
strcasestr-only code couldn't express.

New engine (src/sbbs3/boolsrch.[ch], one TU):

  bool_expr_compile()      parses query into AST, malloc'd errmsg on fail
  bool_expr_match()        evaluate against a single haystack
  bool_expr_match_fields() evaluate against N fields (term hits doc if it
                           appears in ANY field) - the shape callers want
                           for scanning subj/body/tags or name/desc/tags/
                           author
  bool_expr_free()         frees the compiled expression tree

Recursive-descent parser, precedence NOT > AND > OR, supports both
symbol (& | !) and keyword (AND OR NOT, case-insens, whole-word) forms.
Quoted "..." phrases apply a word-boundary check at each side that
contains no whitespace inside the quotes - so "TEST" won't match
TESTING/BACKTEST while " TEST " is pure substring (escape hatch).
Implicit AND is inserted before ! / NOT (Wildcat's
"(windows|DOS) & (modem|comm) !OS/2" idiom).

Wired through:
  readmsgs.cpp   scanposts, searchposts (F find at scan and read-loop)
  listfile.cpp   listfiles (FL_FIND across name/desc/extdesc/tags/author)
  prntfile.cpp   printfile() P_SEEK / and n search
  readmail.cpp   searchmail / at the mail read prompt
  scansubs.cpp   getstr buffer raised from 40 to 120 for boolean queries
  scandirs.cpp   same

Engine compiles the expression once per scan and reuses it across every
document - no per-record parsing cost. Malformed queries print the new
text.dat string InvalidSearchExpression (#948) and return cleanly to the
prompt; pre-existing stale defaults for SeekPrompt (#944) and SeekHelp
(#947) were re-emitted by textgen at the same time.

Standalone unit test (src/sbbs3/boolsrch_test.c, TU-include of
boolsrch.c) covers 95 cases: precedence, parens, quoting + whitespace-
boundary suppression, keyword-vs-substring discrimination (BANDIT not
split on AND), implicit AND, syntax errors, multi-field matching.
Public API is exactly the four entry points above; diagnostic helpers
(describe/is_simple/simple_text) stay file-local.

User-facing docs at docs/boolsrch.md for later wiki import.

Co-Authored-By: Claude Opus 4.7 (1M context) 
n
---
  mSynchronetn  hgVertrauen n hHome of Synchronet n gh[vert/cvs/bbs].synchro.net

-----------------------------------------------------------
[Voltar]