From 64454cfb5749adbe20e030628c169a04a6890d46 Mon Sep 17 00:00:00 2001 From: michael Date: Sun, 23 Aug 2020 09:07:00 +0000 Subject: [PATCH] * Merging revisions r45585,r45628,r45629 from trunk: ------------------------------------------------------------------------ r45585 | michael | 2020-06-04 15:32:47 +0200 (Thu, 04 Jun 2020) | 1 line * Fix bug ID #37159: upstream patches ------------------------------------------------------------------------ r45628 | michael | 2020-06-08 23:41:39 +0200 (Mon, 08 Jun 2020) | 1 line * Fix 0037159 (again) ------------------------------------------------------------------------ r45629 | michael | 2020-06-09 16:19:47 +0200 (Tue, 09 Jun 2020) | 1 line * Fix bug ID #0037189, backwards search ------------------------------------------------------------------------ git-svn-id: branches/fixes_3_2@46566 - --- packages/regexpr/src/regexpr.pas | 103 ++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 24 deletions(-) diff --git a/packages/regexpr/src/regexpr.pas b/packages/regexpr/src/regexpr.pas index 5b02e7f693..438fddd07b 100644 --- a/packages/regexpr/src/regexpr.pas +++ b/packages/regexpr/src/regexpr.pas @@ -412,7 +412,7 @@ type function MatchAtOnePos(APos: PRegExprChar): boolean; {$IFDEF InlineFuncs}inline;{$ENDIF} // Exec for stored InputString - function ExecPrim(AOffset: integer; ATryOnce, ASlowChecks: boolean): boolean; + function ExecPrim(AOffset: integer; ATryOnce, ASlowChecks, ABackward: boolean): boolean; {$IFDEF RegExpPCodeDump} function DumpOp(op: TREOp): RegExprString; @@ -454,12 +454,14 @@ type // Raises exception if used without preceeding SUCCESSFUL call to // Exec* (Exec, ExecPos, ExecNext). So You always must use something like // if Exec (InputString) then repeat { proceed results} until not ExecNext; - function ExecNext: boolean; + function ExecNext: boolean; overload; + function ExecNext(ABackward: boolean): boolean; overload; // find match for InputString starting from AOffset position // (AOffset=1 - first char of InputString) function ExecPos(AOffset: integer = 1): boolean; overload; function ExecPos(AOffset: integer; ATryOnce: boolean): boolean; overload; + function ExecPos(AOffset: integer; ATryOnce, ABackward: boolean): boolean; overload; // Returns ATemplate with '$&' or '$0' replaced by whole r.e. // occurence and '$1'...'$nn' replaced by subexpression with given index. @@ -2950,6 +2952,7 @@ var Len: integer; SavedPtr: PRegExprChar; EnderChar, TempChar: REChar; + DashForRange: Boolean; begin Result := nil; flags := 0; @@ -3007,8 +3010,18 @@ begin while (regparse < fRegexEnd) and (regparse^ <> ']') do begin - if (regparse^ = '-') and ((regparse + 1) < fRegexEnd) and - ((regparse + 1)^ <> ']') and CanBeRange then + // last '-' inside [] treated as simple dash + if (regparse^ = '-') and + ((regparse + 1) < fRegexEnd) and + ((regparse + 1)^ = ']') then + begin + EmitRangeChar('-', False); + Inc(regparse); + Break; + end; + + // char '-' which (maybe) makes a range + if (regparse^ = '-') and ((regparse + 1) < fRegexEnd) and CanBeRange then begin Inc(regparse); RangeEnd := regparse^; @@ -3084,12 +3097,22 @@ begin else begin TempChar := UnQuoteChar(regparse); - EmitRangeChar(TempChar, (regparse + 1)^ = '-'); + // False if '-' is last char in [] + DashForRange := + (regparse + 2 < fRegexEnd) and + ((regparse + 1)^ = '-') and + ((regparse + 2)^ <> ']'); + EmitRangeChar(TempChar, DashForRange); end; end else begin - EmitRangeChar(regparse^, (regparse + 1)^ = '-'); + // False if '-' is last char in [] + DashForRange := + (regparse + 2 < fRegexEnd) and + ((regparse + 1)^ = '-') and + ((regparse + 2)^ <> ']'); + EmitRangeChar(regparse^, DashForRange); end; Inc(regparse); end; @@ -4102,7 +4125,7 @@ end; { of function TRegExpr.MatchPrim function TRegExpr.Exec(const AInputString: RegExprString): boolean; begin InputString := AInputString; - Result := ExecPrim(1, False, False); + Result := ExecPrim(1, False, False, False); end; { of function TRegExpr.Exec -------------------------------------------------------------- } @@ -4112,27 +4135,33 @@ var SlowChecks: boolean; begin SlowChecks := Length(fInputString) < fSlowChecksSizeMax; - Result := ExecPrim(1, False, SlowChecks); + Result := ExecPrim(1, False, SlowChecks, False); end; { of function TRegExpr.Exec -------------------------------------------------------------- } function TRegExpr.Exec(AOffset: integer): boolean; begin - Result := ExecPrim(AOffset, False, False); + Result := ExecPrim(AOffset, False, False, False); end; { of function TRegExpr.Exec -------------------------------------------------------------- } function TRegExpr.ExecPos(AOffset: integer = 1): boolean; begin - Result := ExecPrim(AOffset, False, False); + Result := ExecPrim(AOffset, False, False, False); end; { of function TRegExpr.ExecPos -------------------------------------------------------------- } function TRegExpr.ExecPos(AOffset: integer; ATryOnce: boolean): boolean; begin - Result := ExecPrim(AOffset, ATryOnce, False); + Result := ExecPrim(AOffset, ATryOnce, False, False); +end; + + +function TRegExpr.ExecPos(AOffset: integer; ATryOnce, aBackward: boolean): boolean; +begin + Result := ExecPrim(AOffset, ATryOnce, False, ABackward); end; @@ -4165,7 +4194,8 @@ begin GrpCount := 0; end; -function TRegExpr.ExecPrim(AOffset: integer; ATryOnce, ASlowChecks: boolean): boolean; +function TRegExpr.ExecPrim(AOffset: integer; + ATryOnce, ASlowChecks, ABackward: boolean): boolean; var Ptr: PRegExprChar; begin @@ -4233,11 +4263,23 @@ begin end; // Messy cases: unanchored match. - Dec(Ptr); + if ABackward then + Inc(Ptr, 2) + else + Dec(Ptr); repeat - Inc(Ptr); - if Ptr > fInputEnd then - Exit; + if ABackward then + begin + Dec(Ptr); + if Ptr < fInputStart then + Exit; + end + else + begin + Inc(Ptr); + if Ptr > fInputEnd then + Exit; + end; {$IFDEF UseFirstCharSet} {$IFDEF UniCode} @@ -4255,7 +4297,13 @@ begin end; { of function TRegExpr.ExecPrim -------------------------------------------------------------- } + function TRegExpr.ExecNext: boolean; +begin + Result:=ExecNext(False); +end; + +function TRegExpr.ExecNext(ABackward: boolean): boolean; var PtrBegin, PtrEnd: PRegExprChar; Offset: PtrInt; @@ -4274,8 +4322,9 @@ begin if PtrBegin = PtrEnd then Inc(Offset); - Result := ExecPrim(Offset, False, False); + Result := ExecPrim(Offset, False, False, ABackward); end; { of function TRegExpr.ExecNext + -------------------------------------------------------------- } procedure TRegExpr.SetInputString(const AInputString: RegExprString); @@ -4420,10 +4469,13 @@ begin begin Ch := p^; Inc(p); + n := -1; if Ch = '$' then - n := GrpIndexes[ParseVarName(p)] - else - n := -1; + begin + n := ParseVarName(p); + if (n >= 0) and (n <= High(GrpIndexes)) then + n := GrpIndexes[n]; + end; if n >= 0 then begin Inc(ResultLen, endp[n] - startp[n]); @@ -4467,7 +4519,7 @@ begin end; SetLength(Result, ResultLen); // Fill Result - ResultPtr := Pointer(Result); + ResultPtr := PRegExprChar(Result); p := TemplateBeg; Mode := smodeNormal; while p < TemplateEnd do @@ -4476,10 +4528,13 @@ begin p0 := p; Inc(p); p1 := p; + n := -1; if Ch = '$' then - n := GrpIndexes[ParseVarName(p)] - else - n := -1; + begin + n := ParseVarName(p); + if (n >= 0) and (n <= High(GrpIndexes)) then + n := GrpIndexes[n]; + end; if (n >= 0) then begin p0 := startp[n];