2 pcRegExp - Perl compatible regular expressions for Virtual Pascal
\r
3 (c) 2001 Peter S. Voronov aka Chem O'Dun <petervrn@yahoo.com>
\r
5 Based on PCRE library interface unit for Virtual Pascal.
\r
6 (c) 2001 Alexander Tokarev <dwalin@dwalin.ru>
\r
8 The current PCRE version is: 3.7
\r
10 This software may be distributed under the terms of the modified BSD license
\r
11 Copyright (c) 2001, Alexander Tokarev
\r
12 All rights reserved.
\r
14 Redistribution and use in source and binary forms, with or without
\r
15 modification, are permitted provided that the following conditions are met:
\r
17 * Redistributions of source code must retain the above copyright notice,
\r
18 this list of conditions and the following disclaimer.
\r
19 * Redistributions in binary form must reproduce the above copyright notice,
\r
20 this list of conditions and the following disclaimer in the documentation
\r
21 and/or other materials provided with the distribution.
\r
22 * Neither the name of the <ORGANIZATION> nor the names of its contributors
\r
23 may be used to endorse or promote products derived from this software without
\r
24 specific prior written permission.
\r
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
\r
27 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
\r
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
\r
29 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
\r
30 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\r
31 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
\r
32 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
\r
33 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
\r
34 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
\r
35 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
37 The PCRE library is written by: Philip Hazel <ph10@cam.ac.uk>
\r
38 Copyright (c) 1997-2004 University of Cambridge
\r
40 AngelsHolocaust 4-11-04 updated to use version v5.0
\r
41 (INFO: this is regex-directed, NFA)
\r
42 AH: 9-11-04 - pcre_free: removed var, pcre already gives the ptr, now
\r
43 everything works as it should (no more crashes)
\r
44 -> removed CheckRegExp because pcre handles errors perfectly
\r
45 10-11-04 - added pcError (errorhandling), pcInit
\r
46 13-11-04 - removed the ErrorPos = 0 check -> always print erroroffset
\r
47 17-10-05 - support for \1-\9 backreferences in TpcRegExp.GetReplStr
\r
48 17-02-06 - added RunTimeOptions: caller can set options while searching
\r
49 19-02-06 - added SearchOfs(): let PCRE use the complete string and offset
\r
50 into the string itself
\r
51 20-12-06 - support for version 7.0
\r
52 27.08.08 - support for v7.7
\r
55 {$H+} {$DEFINE PCRE_3_7} {$DEFINE PCRE_5_0} {$DEFINE PCRE_7_0} {$DEFINE PCRE_7_7}
\r
64 PpcRegExp = ^TpcRegExp;
\r
65 // TpcRegExp = object
\r
66 TpcRegExp = object(TObject)
\r
67 MatchesCount: integer;
\r
68 RegExpC, RegExpExt : Pointer;
\r
70 RegExp: shortstring;
\r
72 PartialMatch : boolean;
\r
76 RunTimeOptions: Integer; // options which can be set by the caller
\r
77 constructor Init(const ARegExp : shortstring; AOptions : integer; ALocale : Pointer);
\r
78 function Search(AStr: Pchar; ALen : longint) : boolean; virtual;
\r
79 function SearchNext( AStr: Pchar; ALen : longint) : boolean; virtual;
\r
80 function SearchOfs ( AStr: Pchar; ALen, AOfs : longint) : boolean; virtual;
\r
81 function MatchSub(ANom: integer; var Pos, Len : longint) : boolean; virtual;
\r
82 function MatchFull(var Pos, Len : longint) : boolean; virtual;
\r
83 function GetSubStr(ANom: integer; AStr: Pchar) : string; virtual;
\r
84 function GetFullStr(AStr: Pchar) : string; virtual;
\r
85 function GetReplStr(AStr: Pchar; const ARepl: string) : string; virtual;
\r
86 function GetPreSubStr(AStr: Pchar) : string; virtual;
\r
87 function GetPostSubStr(AStr: Pchar) : string; virtual;
\r
88 function ErrorStr : string; virtual;
\r
89 destructor Done; virtual;
\r
92 function pcGrepMatch(WildCard, aStr: string; AOptions:integer; ALocale : Pointer): Boolean;
\r
93 function pcGrepSub(WildCard, aStr, aRepl: string; AOptions:integer; ALocale : Pointer): string;
\r
95 function pcFastGrepMatch(WildCard, aStr: string): Boolean;
\r
96 function pcFastGrepSub(WildCard, aStr, aRepl: string): string;
\r
99 function pcGetVersion : pchar;
\r
102 function pcError (var pRegExp : Pointer) : Boolean;
\r
103 function pcInit (const Pattern: Shortstring; CaseSens: Boolean) : Pointer;
\r
106 PCRE_CASELESS = $0001;
\r
107 PCRE_MULTILINE = $0002;
\r
108 PCRE_DOTALL = $0004;
\r
109 PCRE_EXTENDED = $0008;
\r
110 PCRE_ANCHORED = $0010;
\r
111 PCRE_DOLLAR_ENDONLY = $0020;
\r
112 PCRE_EXTRA = $0040;
\r
113 PCRE_NOTBOL = $0080;
\r
114 PCRE_NOTEOL = $0100;
\r
115 PCRE_UNGREEDY = $0200;
\r
116 PCRE_NOTEMPTY = $0400;
\r
119 PCRE_NO_AUTO_CAPTURE = $1000;
\r
120 PCRE_NO_UTF8_CHECK = $2000;
\r
121 PCRE_AUTO_CALLOUT = $4000;
\r
122 PCRE_PARTIAL = $8000;
\r
125 PCRE_DFA_SHORTEST = $00010000;
\r
126 PCRE_DFA_RESTART = $00020000;
\r
127 PCRE_FIRSTLINE = $00040000;
\r
128 PCRE_DUPNAMES = $00080000;
\r
129 PCRE_NEWLINE_CR = $00100000;
\r
130 PCRE_NEWLINE_LF = $00200000;
\r
131 PCRE_NEWLINE_CRLF = $00300000;
\r
132 PCRE_NEWLINE_ANY = $00400000;
\r
133 PCRE_NEWLINE_ANYCRLF = $00500000;
\r
135 PCRE_NEWLINE_BITS = PCRE_NEWLINE_CR or PCRE_NEWLINE_LF or PCRE_NEWLINE_ANY;
\r
139 PCRE_BSR_ANYCRLF = $00800000;
\r
140 PCRE_BSR_UNICODE = $01000000;
\r
141 PCRE_JAVASCRIPT_COMPAT= $02000000;
\r
144 PCRE_COMPILE_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_AUTO_CALLOUT + PCRE_CASELESS +
\r
145 PCRE_DOLLAR_ENDONLY + PCRE_DOTALL + PCRE_EXTENDED +
\r
146 PCRE_EXTRA + PCRE_MULTILINE + PCRE_NO_AUTO_CAPTURE +
\r
147 PCRE_UNGREEDY + PCRE_UTF8 + PCRE_NO_UTF8_CHECK
\r
149 + PCRE_DUPNAMES + PCRE_FIRSTLINE + PCRE_NEWLINE_BITS
\r
152 + PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE + PCRE_JAVASCRIPT_COMPAT
\r
156 PCRE_EXEC_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_NOTBOL + PCRE_NOTEOL +
\r
157 PCRE_NOTEMPTY + PCRE_NO_UTF8_CHECK + PCRE_PARTIAL
\r
159 + PCRE_NEWLINE_BITS
\r
162 + PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE
\r
167 PCRE_DFA_EXEC_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_NOTBOL + PCRE_NOTEOL +
\r
168 PCRE_NOTEMPTY + PCRE_NO_UTF8_CHECK + PCRE_PARTIAL +
\r
169 PCRE_DFA_SHORTEST + PCRE_DFA_RESTART +
\r
172 + PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE
\r
177 { Exec-time and get/set-time error codes }
\r
178 PCRE_ERROR_NOMATCH = -1;
\r
179 PCRE_ERROR_NULL = -2;
\r
180 PCRE_ERROR_BADOPTION = -3;
\r
181 PCRE_ERROR_BADMAGIC = -4;
\r
182 PCRE_ERROR_UNKNOWN_MODE = -5;
\r
183 PCRE_ERROR_NOMEMORY = -6;
\r
184 PCRE_ERROR_NOSUBSTRING = -7;
\r
186 PCRE_ERROR_MATCHLIMIT = -8;
\r
187 PCRE_ERROR_CALLOUT = -9; { Never used by PCRE itself }
\r
188 PCRE_ERROR_BADUTF8 = -10;
\r
189 PCRE_ERROR_BADUTF8_OFFSET = -11;
\r
190 PCRE_ERROR_PARTIAL = -12;
\r
191 PCRE_ERROR_BADPARTIAL = -13;
\r
192 PCRE_ERROR_INTERNAL = -14;
\r
193 PCRE_ERROR_BADCOUNT = -15;
\r
196 PCRE_ERROR_DFA_UITEM = -16;
\r
197 PCRE_ERROR_DFA_UCOND = -17;
\r
198 PCRE_ERROR_DFA_UMLIMIT = -18;
\r
199 PCRE_ERROR_DFA_WSSIZE = -19;
\r
200 PCRE_ERROR_DFA_RECURSE = -20;
\r
201 PCRE_ERROR_RECURSIONLIMIT = -21;
\r
202 PCRE_ERROR_NULLWSLIMIT = -22;
\r
203 PCRE_ERROR_BADNEWLINE = -23;
\r
206 { Request types for pcre_fullinfo() }
\r
208 PCRE_INFO_OPTIONS = 0;
\r
209 PCRE_INFO_SIZE = 1;
\r
210 PCRE_INFO_CAPTURECOUNT = 2;
\r
211 PCRE_INFO_BACKREFMAX = 3;
\r
212 PCRE_INFO_FIRSTBYTE = 4;
\r
213 PCRE_INFO_FIRSTCHAR = 4; { For backwards compatibility }
\r
214 PCRE_INFO_FIRSTTABLE = 5;
\r
216 PCRE_INFO_LASTLITERAL = 6;
\r
217 PCRE_INFO_NAMEENTRYSIZE = 7;
\r
218 PCRE_INFO_NAMECOUNT = 8;
\r
219 PCRE_INFO_NAMETABLE = 9;
\r
220 PCRE_INFO_STUDYSIZE = 10;
\r
221 PCRE_INFO_DEFAULT_TABLES = 11;
\r
224 PCRE_INFO_OKPARTIAL = 12;
\r
225 PCRE_INFO_JCHANGED = 13;
\r
226 PCRE_INFO_HASCRORLF = 14;
\r
229 { Request types for pcre_config() }
\r
231 PCRE_CONFIG_UTF8 = 0;
\r
232 PCRE_CONFIG_NEWLINE = 1;
\r
233 PCRE_CONFIG_LINK_SIZE = 2;
\r
234 PCRE_CONFIG_POSIX_MALLOC_THRESHOLD = 3;
\r
235 PCRE_CONFIG_MATCH_LIMIT = 4;
\r
236 PCRE_CONFIG_STACKRECURSE = 5;
\r
237 PCRE_CONFIG_UNICODE_PROPERTIES = 6;
\r
240 PCRE_CONFIG_MATCH_LIMIT_RECURSION = 7;
\r
243 PCRE_CONFIG_BSR = 8;
\r
246 { Bit flags for the pcre_extra structure }
\r
248 PCRE_EXTRA_STUDY_DATA = $0001;
\r
249 PCRE_EXTRA_MATCH_LIMIT = $0002;
\r
250 PCRE_EXTRA_CALLOUT_DATA = $0004;
\r
251 PCRE_EXTRA_TABLES = $0008;
\r
254 PCRE_EXTRA_MATCH_LIMIT_RECURSION = $0010;
\r
258 // DefaultOptions : integer = 0;
\r
259 DefaultLocaleTable : pointer = nil;
\r
262 { The structure for passing additional data to pcre_exec(). This is defined in
\r
263 such as way as to be extensible. Always add new fields at the end, in order to
\r
264 remain compatible. }
\r
266 type ppcre_extra = ^tpcre_extra;
\r
267 tpcre_extra = record
\r
268 flags : longint; { Bits for which fields are set }
\r
269 study_data : pointer; { Opaque data from pcre_study() }
\r
270 match_limit : longint; { Maximum number of calls to match() }
\r
271 callout_data : pointer; { Data passed back in callouts }
\r
272 tables : pointer; { Pointer to character tables }
\r
273 match_limit_recursion: longint; { Max recursive calls to match() }
\r
276 type ppcre_callout_block = ^pcre_callout_block;
\r
277 pcre_callout_block = record
\r
279 (* ------------------------ Version 0 ------------------------------- *)
\r
280 callout_number : integer;
\r
281 offset_vector : pointer;
\r
283 subject_length, start_match, current_position, capture_top,
\r
284 capture_last : integer;
\r
285 callout_data : pointer;
\r
286 (* ------------------- Added for Version 1 -------------------------- *)
\r
287 pattern_position, next_item_length : integer;
\r
292 {$IFDEF VIRTUALPASCAL} {&Cdecl+} {$ENDIF VIRTUALPASCAL}
\r
294 { local replacement of external pcre memory management functions }
\r
295 function pcre_malloc( size : integer ) : pointer;
\r
296 procedure pcre_free( {var} p : pointer );
\r
298 const pcre_stack_malloc: function ( size : integer ): pointer = pcre_malloc;
\r
299 pcre_stack_free: procedure ( {var} p : pointer ) = pcre_free;
\r
300 function pcre_callout(var p : ppcre_callout_block) : integer;
\r
302 {$IFDEF VIRTUALPASCAL} {&Cdecl-} {$ENDIF VIRTUALPASCAL}
\r
306 Uses strings, collect, messages, dnapp, commands, advance0, stringsx
\r
307 {$IFDEF VIRTUALPASCAL} ,vpsyslow {$ENDIF VIRTUALPASCAL};
\r
310 MAGIC_NUMBER = $50435245; { 'PCRE' }
\r
311 MAX_MATCHES = 90; { changed in 3.5 version; should be divisible by 3, was 64}
\r
314 PMatchArray = ^TMatchArray;
\r
315 TMatchArray = array[0..( MAX_MATCHES * 3 )] of integer;
\r
317 PRegExpCollection = ^TRegExpCollection;
\r
318 TRegExpCollection = object(TSortedCollection)
\r
319 MaxRegExp : integer;
\r
320 SearchRegExp : shortstring;
\r
321 CompareModeInsert : boolean;
\r
322 constructor Init(AMaxRegExp:integer);
\r
323 procedure FreeItem(P: Pointer); virtual;
\r
324 function Compare(P1, P2: Pointer): Integer; virtual;
\r
325 function Find(ARegExp:shortstring;var P: PpcRegExp):boolean; virtual;
\r
326 function CheckNew(ARegExp:shortstring):PpcRegExp;virtual;
\r
330 PRegExpCache : PRegExpCollection;
\r
333 {$IFDEF VIRTUALPASCAL} {&Cdecl+} {$ENDIF VIRTUALPASCAL}
\r
335 { imported original pcre functions }
\r
337 function pcre_compile( const pattern : PChar; options : integer;
\r
338 var errorptr : PChar; var erroroffset : integer;
\r
339 const tables : PChar ) : pointer {pcre}; external;
\r
341 function pcre_compile2( const pattern : PChar; options : integer;
\r
342 var errorcodeptr : Integer;
\r
343 var errorptr : PChar; var erroroffset : integer;
\r
344 const tables : PChar ) : pointer {pcre}; external;
\r
347 function pcre_config( what : integer; where : pointer) : integer; external;
\r
348 function pcre_copy_named_substring( const code : pointer {pcre};
\r
349 const subject : pchar;
\r
350 var ovector : integer;
\r
351 stringcount : integer;
\r
352 const stringname : pchar;
\r
353 var buffer : pchar;
\r
354 size : integer) : integer; external;
\r
355 function pcre_copy_substring( const subject : pchar; var ovector : integer;
\r
356 stringcount, stringnumber : integer;
\r
357 var buffer : pchar; size : integer )
\r
358 : integer; external;
\r
359 function pcre_exec( const argument_re : pointer {pcre};
\r
360 const extra_data : pointer {pcre_extra};
\r
362 function pcre_exec( const external_re : pointer;
\r
363 const external_extra : pointer;
\r
365 const subject : PChar;
\r
366 length, start_offset, options : integer;
\r
368 offsetcount : integer ) : integer; external;
\r
370 function pcre_dfa_exec( const argument_re : pointer {pcre};
\r
371 const extra_data : pointer {pcre_extra};
\r
372 const subject : pchar;
\r
373 length, start_offset, options : integer;
\r
375 offsetcount : integer;
\r
376 workspace : pointer;
\r
377 wscount : integer ) : integer; external;
\r
380 procedure pcre_free_substring( const p : pchar ); external;
\r
381 procedure pcre_free_substring_list( var p : pchar ); external;
\r
382 function pcre_fullinfo( const argument_re : pointer {pcre};
\r
383 const extra_data : pointer {pcre_extra};
\r
385 where : pointer ) : integer; external;
\r
386 function pcre_get_named_substring( const code : pointer {pcre};
\r
387 const subject : pchar;
\r
388 var ovector : integer;
\r
389 stringcount : integer;
\r
390 const stringname : pchar;
\r
391 var stringptr : pchar ) : integer; external;
\r
392 function pcre_get_stringnumber( const code : pointer {pcre};
\r
393 const stringname : pchar ) : integer; external;
\r
394 function pcre_get_stringtable_entries( const code : pointer {pcre};
\r
395 const stringname : pchar;
\r
397 lastptr : pchar ) : integer; external;
\r
398 function pcre_get_substring( const subject : pchar; var ovector : integer;
\r
399 stringcount, stringnumber : integer;
\r
400 var stringptr : pchar ) : integer; external;
\r
401 function pcre_get_substring_list( const subject : pchar; var ovector : integer;
\r
402 stringcount : integer;
\r
403 listptr : pointer {const char ***listptr}) : integer; external;
\r
404 function pcre_info( const argument_re : pointer {pcre};
\r
405 var optptr : integer;
\r
406 var first_byte : integer ) : integer; external;
\r
407 function pcre_maketables : pchar; external;
\r
410 function pcre_refcount( const argument_re : pointer {pcre};
\r
411 adjust : integer ) : pchar; external;
\r
413 function pcre_study( const external_re : pointer {pcre};
\r
415 var errorptr : PChar ) : pointer {pcre_extra}; external;
\r
417 function pcre_version : pchar; external;
\r
420 function pcre_malloc( size : integer ) : pointer;
\r
422 GetMem( result, size );
\r
425 procedure pcre_free( {var} p : pointer );
\r
433 (* Called from PCRE as a result of the (?C) item. We print out where we are in
\r
434 the match. Yield zero unless more callouts than the fail count, or the callout
\r
435 data is not zero. *)
\r
437 function pcre_callout;
\r
442 {$IFDEF VIRTUALPASCAL} {&Cdecl-} {$ENDIF VIRTUALPASCAL}
\r
444 // Always include the newest version of the library
\r
463 constructor TpcRegExp.Init(const ARegExp:shortstring; AOptions:integer; ALocale : Pointer);
\r
475 RunTimeOptions := 0;
\r
476 if length(RegExp) < 255 then
\r
478 RegExp[length(RegExp)+1]:=#0;
\r
479 pRegExp:=@RegExp[1];
\r
483 GetMem(pRegExp,length(RegExp)+1);
\r
484 pRegExp:=strpcopy(pRegExp,RegExp);
\r
486 RegExpC := pcre_compile( pRegExp,
\r
487 AOptions and PCRE_COMPILE_ALLOWED_OPTIONS,
\r
488 ErrorMsg, ErrorPos, ALocale);
\r
489 if length(RegExp) = 255 then
\r
490 StrDispose(pRegExp);
\r
491 if RegExpC = nil then
\r
494 RegExpExt := pcre_study( RegExpC, 0, ErrorMsg );
\r
495 if (RegExpExt = nil) and (ErrorMsg <> nil) then
\r
497 pcre_free(RegExpC);
\r
500 GetMem(Matches,SizeOf(TMatchArray));
\r
504 destructor TpcRegExp.Done;
\r
506 if RegExpC <> nil then
\r
507 pcre_free(RegExpC);
\r
508 if RegExpExt <> nil then
\r
509 pcre_free(RegExpExt);
\r
510 if Matches <> nil then
\r
511 FreeMem(Matches,SizeOf(TMatchArray));
\r
514 function TpcRegExp.SearchNext( AStr: Pchar; ALen : longint ) : boolean;
\r
515 var Options: Integer;
\r
516 begin // must handle PCRE_ERROR_PARTIAL here
\r
517 Options := (RunTimeOptions or startup.MiscMultiData.cfgRegEx.DefaultOptions) and
\r
518 PCRE_EXEC_ALLOWED_OPTIONS;
\r
519 if MatchesCount > 0 then
\r
520 MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, PMatchArray(Matches)^[1],
\r
521 Options, Matches, MAX_MATCHES ) else
\r
522 MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, 0,
\r
523 Options, Matches, MAX_MATCHES );
\r
524 { if MatchesCount = 0 then
\r
525 MatchesCount := MatchesCount div 3;}
\r
526 PartialMatch := MatchesCount = PCRE_ERROR_PARTIAL;
\r
527 SearchNext := MatchesCount > 0;
\r
530 function TpcRegExp.Search( AStr: Pchar; ALen : longint):boolean;
\r
533 Search:=SearchNext(AStr,ALen);
\r
537 function TpcRegExp.SearchOfs( AStr: Pchar; ALen, AOfs: longint ) : boolean;
\r
538 var Options: Integer;
\r
541 Options := (RunTimeOptions or startup.MiscMultiData.cfgRegEx.DefaultOptions) and
\r
542 PCRE_EXEC_ALLOWED_OPTIONS;
\r
543 MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, AOfs,
\r
544 Options, Matches, MAX_MATCHES );
\r
545 PartialMatch := MatchesCount = PCRE_ERROR_PARTIAL;
\r
546 SearchOfs := MatchesCount > 0;
\r
547 SourceLen := ALen-AOfs;
\r
550 function TpcRegExp.MatchSub(ANom:integer; var Pos,Len:longint):boolean;
\r
552 if (MatchesCount > 0) and (ANom <= (MatchesCount-1)) then
\r
555 Pos:=PMatchArray(Matches)^[ANom];
\r
556 Len:=PMatchArray(Matches)^[ANom+1]-Pos;
\r
563 function TpcRegExp.MatchFull(var Pos,Len:longint):boolean;
\r
565 MatchFull:=MatchSub(0,Pos,Len);
\r
568 function TpcRegExp.GetSubStr(ANom: integer; AStr: Pchar):string;
\r
574 if MatchSub(ANom, pos, len) then
\r
577 Move(AStr[pos], s[1], len);
\r
582 function TpcRegExp.GetPreSubStr(AStr: Pchar):string;
\r
588 if (MatchesCount > 0) then
\r
590 l:=PMatchArray(Matches)^[0]-1;
\r
594 Move(AStr[1],s[1],l);
\r
600 function TpcRegExp.GetPostSubStr(AStr: Pchar):string;
\r
607 if (MatchesCount > 0) then
\r
609 ANom:=(MatchesCount-1){*2} shl 1;
\r
610 l:=SourceLen-PMatchArray(Matches)^[ANom+1]+1;
\r
614 Move(AStr[PMatchArray(Matches)^[ANom+1]],s[1],l);
\r
621 function TpcRegExp.GetFullStr(AStr: Pchar):string;
\r
626 GetFullStr:=GetSubStr(0,AStr);
\r
629 function TpcRegExp.GetReplStr(AStr: Pchar; const ARepl: string):string;
\r
632 l,i,lasti: longint;
\r
645 s:=s+copy(ARepl,lasti,i-lasti){+ARepl[i+1]};
\r
646 {AH 17-10-05 support for POSIX \1-\9 backreferences}
\r
648 '0' : s:=s+GetFullStr(AStr);
\r
649 '1'..'9' : s:=s+GetSubStr(ord(ARepl[i+1])-ord('0'),AStr);
\r
650 else s:=s+ARepl[i+1]; // copy the escaped character
\r
660 s:=s+copy(ARepl,lasti,i-lasti);
\r
662 '&' : s:=s+GetFullStr(AStr);
\r
663 '1'..'9' : s:=s+GetSubStr(ord(ARepl[i+1])-ord('0'),AStr);
\r
664 '`' : s:=s+GetPreSubStr(AStr);
\r
665 #39 : s:=s+GetPostSubStr(AStr);
\r
674 if lasti <= {AH 25-10-2004 added =, else l==1 won't work} l then
\r
675 s:=s+copy(ARepl,lasti,l-lasti+1);
\r
679 function TpcRegExp.ErrorStr:string;
\r
681 ErrorStr:=StrPas(ErrorMsg);
\r
684 {TRegExpCollection}
\r
686 constructor TRegExpCollection.Init(AMaxRegExp: integer);
\r
688 Inherited Init(1,1);
\r
689 MaxRegExp:=AMaxRegExp;
\r
690 CompareModeInsert:=true;
\r
693 procedure TRegExpCollection.FreeItem(P: Pointer);
\r
697 Dispose(PpcRegExp(P),Done);
\r
701 function TRegExpCollection.Compare(P1, P2: Pointer): Integer;
\r
703 // l,l1,l2,i : byte;
\r
706 if CompareModeInsert then
\r
708 // l1:=length(PpcRegExp(P1)^.RegExp);
\r
709 // l2:=length(PpcRegExp(P2)^.RegExp);
\r
710 // if l1 > l2 then l:=l2 else
\r
712 // for i:=1 to l do
\r
713 // if PpcRegExp(P1).RegExp[i] <> PpcRegExp(P2).RegExp[i] then break;
\r
715 // Compare:=ord(PpcRegExp(P1).RegExp[i])-ord(PpcRegExp(P2).RegExp[i]) else
\r
717 Compare := stringsx.PasStrCmp(PpcRegExp(P1).RegExp, PpcRegExp(P2).RegExp, False);
\r
721 // l1:=length(PpcRegExp(P1)^.RegExp);
\r
722 // l2:=length(SearchRegExp);
\r
723 // if l1 > l2 then l:=l2 else
\r
725 // for i:=1 to l do
\r
726 // if PpcRegExp(P1).RegExp[i] <> SearchRegExp[i] then
\r
728 // Compare:=ord(PpcRegExp(P1).RegExp[i])-ord(SearchRegExp[i]);
\r
731 // if i > l then Compare:=l1-l2;
\r
732 Compare := stringsx.PasStrCmp(PpcRegExp(P1).RegExp, SearchRegExp, False);
\r
736 function TRegExpCollection.Find(ARegExp:shortstring;var P: PpcRegExp):boolean;
\r
739 CompareModeInsert:=false;
\r
740 SearchRegExp:=ARegExp;
\r
741 if Search(nil,I) then
\r
743 P:=PpcRegExp(At(I));
\r
751 CompareModeInsert:=true;
\r
754 function TRegExpCollection.CheckNew(ARegExp:shortstring):PpcRegExp;
\r
758 if not Find(ARegExp,P) then
\r
760 if Count = MaxRegExp then
\r
762 P:=New(ppcRegExp,Init(ARegExp,PCRE_CASELESS,nil));
\r
768 function pcGrepMatch(WildCard, aStr: string; AOptions:integer; ALocale : Pointer): Boolean;
\r
772 PpcRE:=New(ppcRegExp,Init(WildCard,AOptions,Alocale));
\r
773 pcGrepMatch:=PpcRE^.Search(pchar(AStr),Length(AStr));
\r
774 Dispose(PpcRE,Done);
\r
777 function pcGrepSub(WildCard, aStr, aRepl: string; AOptions:integer; ALocale : Pointer): string;
\r
781 PpcRE:=New(ppcRegExp,Init(WildCard,AOptions,Alocale));
\r
782 if PpcRE^.Search(pchar(AStr),Length(AStr)) then
\r
783 pcGrepSub:=PpcRE^.GetReplStr(pchar(AStr),ARepl)
\r
786 Dispose(PpcRE,Done);
\r
789 function pcFastGrepMatch(WildCard, aStr: string): Boolean;
\r
793 PpcRE:=PRegExpCache^.CheckNew(WildCard);
\r
794 pcFastGrepMatch:=PpcRE^.Search(pchar(AStr),Length(AStr));
\r
797 function pcFastGrepSub(WildCard, aStr, aRepl: string): string;
\r
801 PpcRE:=PRegExpCache^.CheckNew(WildCard);
\r
802 if PpcRE^.Search(pchar(AStr),Length(AStr)) then
\r
803 pcFastGrepSub:=PpcRE^.GetReplStr(pchar(AStr),ARepl)
\r
809 function pcGetVersion : pchar; assembler; {$FRAME-}{$USES none}
\r
816 var P: ppcRegExp absolute pRegExp;
\r
818 Result := (P = nil) or P^.Error;
\r
819 If Result and (P <> nil) then
\r
821 { if P^.ErrorPos = 0 then
\r
822 MessageBox(GetString(erRegExpCompile)+'"'+P^.ErrorStr+'"', nil,mfConfirmation+mfOkButton)
\r
824 MessageBox(GetString(erRegExpCompile)+'"'+P^.ErrorStr+'"'+GetString(erRegExpCompPos),
\r
825 @P^.ErrorPos,mfConfirmation+mfOkButton);
\r
832 var Options : Integer;
\r
834 If CaseSens then Options := 0 else Options := PCRE_CASELESS;
\r
835 Result := New( PpcRegExp, Init( Pattern,
\r
837 startup.MiscMultiData.cfgRegEx.DefaultOptions or Options,
\r
838 DefaultLocaleTable) );
\r
842 PRegExpCache:=New(PRegExpCollection,Init(64));
\r
844 Dispose(PRegExpCache,Done);
\r