File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -829,6 +829,16 @@ namespace MultiReplaceEngine {
829829 onInvalid (result, seg.text );
830830 return result;
831831 }
832+ // get_string() evaluates the whole expression, so a
833+ // loadlib() called inside a string-producing segment can
834+ // latch here too. Same structural abort as the numeric path.
835+ if (_loadlibFailed) {
836+ reportError (ILuaEngineHost::ErrorCategory::CompileError,
837+ _loadlibError);
838+ result.success = false ;
839+ result.errorMessage = _loadlibError;
840+ return result;
841+ }
832842 // Record for history. txtout/txtprev readers will see
833843 // this slot in subsequent matches; numout/numprev get a
834844 // type-mismatch fallback because the slot is String.
Original file line number Diff line number Diff line change @@ -125,11 +125,27 @@ namespace MultiReplaceEngine {
125125
126126 // Depth-counting scan to the matching ')'. Inside the
127127 // expression we deliberately do NOT honour escape
128- // sequences - the formula engine sees the raw text.
128+ // sequences - the formula engine sees the raw text. A
129+ // single-quoted string literal is skipped whole so its
130+ // parentheses are not counted (ExprTk uses '' for an
131+ // embedded quote).
129132 int depth = 1 ;
130133 while (i < n && depth > 0 ) {
131134 const char c = templ[i];
132- if (c == ' (' ) {
135+ if (c == ' \' ' ) {
136+ ++i;
137+ while (i < n) {
138+ if (templ[i] == ' \' ' ) {
139+ if (i + 1 < n && templ[i + 1 ] == ' \' ' ) {
140+ i += 2 ; // escaped quote, stay in string
141+ continue ;
142+ }
143+ break ; // closing quote
144+ }
145+ ++i;
146+ }
147+ }
148+ else if (c == ' (' ) {
133149 ++depth;
134150 }
135151 else if (c == ' )' ) {
You can’t perform that action at this time.
0 commit comments