"Fossies" - the Fresh Open Source Software Archive

Member "pcre-8.42/pcregexp.pas" (31 Jan 2014, 26071 Bytes) of package /linux/misc/pcre-8.42.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Pascal source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 {
    2   pcRegExp - Perl compatible regular expressions for Virtual Pascal
    3   (c) 2001 Peter S. Voronov aka Chem O'Dun <petervrn@yahoo.com>
    4 
    5   Based on PCRE library interface unit for Virtual Pascal.
    6   (c) 2001 Alexander Tokarev <dwalin@dwalin.ru>
    7 
    8   The current PCRE version is: 3.7
    9 
   10   This software may be distributed under the terms of the modified BSD license
   11   Copyright (c) 2001, Alexander Tokarev
   12   All rights reserved.
   13 
   14   Redistribution and use in source and binary forms, with or without
   15   modification, are permitted provided that the following conditions are met:
   16 
   17     * Redistributions of source code must retain the above copyright notice,
   18       this list of conditions and the following disclaimer.
   19     * Redistributions in binary form must reproduce the above copyright notice,
   20       this list of conditions and the following disclaimer in the documentation
   21       and/or other materials provided with the distribution.
   22     * Neither the name of the <ORGANIZATION> nor the names of its contributors
   23       may be used to endorse or promote products derived from this software without
   24       specific prior written permission.
   25 
   26   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   27   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   28   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   29   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
   30   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   32   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   33   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   34   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   35   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   36 
   37   The PCRE library is written by: Philip Hazel <ph10@cam.ac.uk>
   38   Copyright (c) 1997-2004 University of Cambridge
   39 
   40   AngelsHolocaust 4-11-04 updated to use version v5.0
   41   (INFO: this is regex-directed, NFA)
   42   AH:  9-11-04 - pcre_free: removed var, pcre already gives the ptr, now
   43                 everything works as it should (no more crashes)
   44          -> removed CheckRegExp because pcre handles errors perfectly
   45       10-11-04 - added pcError (errorhandling), pcInit
   46       13-11-04 - removed the ErrorPos = 0 check -> always print erroroffset
   47       17-10-05 - support for \1-\9 backreferences in TpcRegExp.GetReplStr
   48       17-02-06 - added RunTimeOptions: caller can set options while searching
   49       19-02-06 - added SearchOfs(): let PCRE use the complete string and offset
   50          into the string itself
   51       20-12-06 - support for version 7.0
   52       27.08.08 - support for v7.7
   53 }
   54 
   55 {$H+} {$DEFINE PCRE_3_7} {$DEFINE PCRE_5_0} {$DEFINE PCRE_7_0} {$DEFINE PCRE_7_7}
   56 
   57 Unit pcregexp;
   58 
   59 Interface
   60 
   61 uses objects;
   62 
   63 Type
   64  PpcRegExp = ^TpcRegExp;
   65 // TpcRegExp = object
   66  TpcRegExp = object(TObject)
   67   MatchesCount: integer;
   68   RegExpC, RegExpExt : Pointer;
   69   Matches:Pointer;
   70   RegExp: shortstring;
   71   SourceLen: integer;
   72   PartialMatch : boolean;
   73   Error : boolean;
   74   ErrorMsg : Pchar;
   75   ErrorPos : integer;
   76   RunTimeOptions: Integer; // options which can be set by the caller
   77   constructor Init(const ARegExp : shortstring; AOptions : integer; ALocale : Pointer);
   78   function Search(AStr: Pchar; ALen : longint) : boolean; virtual;
   79   function SearchNext( AStr: Pchar; ALen : longint) : boolean; virtual;
   80   function SearchOfs ( AStr: Pchar; ALen, AOfs : longint) : boolean; virtual;
   81   function MatchSub(ANom: integer; var Pos, Len : longint) : boolean; virtual;
   82   function MatchFull(var Pos, Len : longint) : boolean; virtual;
   83   function GetSubStr(ANom: integer; AStr: Pchar) : string; virtual;
   84   function GetFullStr(AStr: Pchar) : string; virtual;
   85   function GetReplStr(AStr: Pchar; const ARepl: string) : string; virtual;
   86   function GetPreSubStr(AStr: Pchar) : string; virtual;
   87   function GetPostSubStr(AStr: Pchar) : string; virtual;
   88   function ErrorStr : string; virtual;
   89   destructor Done; virtual;
   90  end;
   91 
   92  function pcGrepMatch(WildCard, aStr: string; AOptions:integer; ALocale : Pointer): Boolean;
   93  function pcGrepSub(WildCard, aStr, aRepl: string; AOptions:integer; ALocale : Pointer): string;
   94 
   95  function pcFastGrepMatch(WildCard, aStr: string): Boolean;
   96  function pcFastGrepSub(WildCard, aStr, aRepl: string): string;
   97 
   98 {$IFDEF PCRE_5_0}
   99  function pcGetVersion : pchar;
  100 {$ENDIF}
  101 
  102  function pcError (var pRegExp : Pointer) : Boolean;
  103  function pcInit  (const Pattern: Shortstring; CaseSens: Boolean) : Pointer;
  104 
  105 Const { Options }
  106  PCRE_CASELESS         = $0001;
  107  PCRE_MULTILINE        = $0002;
  108  PCRE_DOTALL           = $0004;
  109  PCRE_EXTENDED         = $0008;
  110  PCRE_ANCHORED         = $0010;
  111  PCRE_DOLLAR_ENDONLY   = $0020;
  112  PCRE_EXTRA            = $0040;
  113  PCRE_NOTBOL           = $0080;
  114  PCRE_NOTEOL           = $0100;
  115  PCRE_UNGREEDY         = $0200;
  116  PCRE_NOTEMPTY         = $0400;
  117 {$IFDEF PCRE_5_0}
  118  PCRE_UTF8             = $0800;
  119  PCRE_NO_AUTO_CAPTURE  = $1000;
  120  PCRE_NO_UTF8_CHECK    = $2000;
  121  PCRE_AUTO_CALLOUT     = $4000;
  122  PCRE_PARTIAL          = $8000;
  123 {$ENDIF}
  124 {$IFDEF PCRE_7_0}
  125  PCRE_DFA_SHORTEST     = $00010000;
  126  PCRE_DFA_RESTART      = $00020000;
  127  PCRE_FIRSTLINE        = $00040000;
  128  PCRE_DUPNAMES         = $00080000;
  129  PCRE_NEWLINE_CR       = $00100000;
  130  PCRE_NEWLINE_LF       = $00200000;
  131  PCRE_NEWLINE_CRLF     = $00300000;
  132  PCRE_NEWLINE_ANY      = $00400000;
  133  PCRE_NEWLINE_ANYCRLF  = $00500000;
  134 
  135  PCRE_NEWLINE_BITS     = PCRE_NEWLINE_CR or PCRE_NEWLINE_LF or PCRE_NEWLINE_ANY;
  136 
  137 {$ENDIF}
  138 {$IFDEF PCRE_7_7}
  139  PCRE_BSR_ANYCRLF      = $00800000;
  140  PCRE_BSR_UNICODE      = $01000000;
  141  PCRE_JAVASCRIPT_COMPAT= $02000000;
  142 {$ENDIF}
  143 
  144  PCRE_COMPILE_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_AUTO_CALLOUT + PCRE_CASELESS  +
  145                 PCRE_DOLLAR_ENDONLY + PCRE_DOTALL + PCRE_EXTENDED  +
  146                 PCRE_EXTRA + PCRE_MULTILINE + PCRE_NO_AUTO_CAPTURE +
  147                 PCRE_UNGREEDY + PCRE_UTF8 + PCRE_NO_UTF8_CHECK
  148                 {$IFDEF PCRE_7_0}
  149                 + PCRE_DUPNAMES + PCRE_FIRSTLINE + PCRE_NEWLINE_BITS
  150                 {$ENDIF}
  151                 {$IFDEF PCRE_7_7}
  152                 + PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE + PCRE_JAVASCRIPT_COMPAT
  153                 {$ENDIF}
  154                 ;
  155 
  156  PCRE_EXEC_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_NOTBOL + PCRE_NOTEOL +
  157                  PCRE_NOTEMPTY + PCRE_NO_UTF8_CHECK + PCRE_PARTIAL
  158                  {$IFDEF PCRE_7_0}
  159                  + PCRE_NEWLINE_BITS
  160                  {$ENDIF}
  161                  {$IFDEF PCRE_7_7}
  162                  + PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE
  163                  {$ENDIF}
  164                  ;
  165 
  166 {$IFDEF PCRE_7_0}
  167  PCRE_DFA_EXEC_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_NOTBOL + PCRE_NOTEOL +
  168                  PCRE_NOTEMPTY + PCRE_NO_UTF8_CHECK + PCRE_PARTIAL +
  169                  PCRE_DFA_SHORTEST + PCRE_DFA_RESTART +
  170                  PCRE_NEWLINE_BITS
  171                  {$IFDEF PCRE_7_7}
  172                  + PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE
  173                  {$ENDIF}
  174                  ;
  175 {$ENDIF}
  176 
  177 { Exec-time and get/set-time error codes }
  178  PCRE_ERROR_NOMATCH        =  -1;
  179  PCRE_ERROR_NULL       =  -2;
  180  PCRE_ERROR_BADOPTION      =  -3;
  181  PCRE_ERROR_BADMAGIC       =  -4;
  182  PCRE_ERROR_UNKNOWN_MODE   =  -5;
  183  PCRE_ERROR_NOMEMORY       =  -6;
  184  PCRE_ERROR_NOSUBSTRING    =  -7;
  185 {$IFDEF PCRE_5_0}
  186  PCRE_ERROR_MATCHLIMIT     =  -8;
  187  PCRE_ERROR_CALLOUT        =  -9;  { Never used by PCRE itself }
  188  PCRE_ERROR_BADUTF8        = -10;
  189  PCRE_ERROR_BADUTF8_OFFSET = -11;
  190  PCRE_ERROR_PARTIAL        = -12;
  191  PCRE_ERROR_BADPARTIAL     = -13;
  192  PCRE_ERROR_INTERNAL       = -14;
  193  PCRE_ERROR_BADCOUNT       = -15;
  194 {$ENDIF}
  195 {$IFDEF PCRE_7_0}
  196  PCRE_ERROR_DFA_UITEM      = -16;
  197  PCRE_ERROR_DFA_UCOND      = -17;
  198  PCRE_ERROR_DFA_UMLIMIT    = -18;
  199  PCRE_ERROR_DFA_WSSIZE     = -19;
  200  PCRE_ERROR_DFA_RECURSE    = -20;
  201  PCRE_ERROR_RECURSIONLIMIT = -21;
  202  PCRE_ERROR_NULLWSLIMIT    = -22;
  203  PCRE_ERROR_BADNEWLINE     = -23;
  204 {$ENDIF}
  205 
  206 { Request types for pcre_fullinfo() }
  207 
  208  PCRE_INFO_OPTIONS         =  0;
  209  PCRE_INFO_SIZE        =  1;
  210  PCRE_INFO_CAPTURECOUNT    =  2;
  211  PCRE_INFO_BACKREFMAX      =  3;
  212  PCRE_INFO_FIRSTBYTE       =  4;
  213  PCRE_INFO_FIRSTCHAR       =  4; { For backwards compatibility }
  214  PCRE_INFO_FIRSTTABLE      =  5;
  215 {$IFDEF PCRE_5_0}
  216  PCRE_INFO_LASTLITERAL     =  6;
  217  PCRE_INFO_NAMEENTRYSIZE   =  7;
  218  PCRE_INFO_NAMECOUNT       =  8;
  219  PCRE_INFO_NAMETABLE       =  9;
  220  PCRE_INFO_STUDYSIZE       = 10;
  221  PCRE_INFO_DEFAULT_TABLES  = 11;
  222 {$ENDIF PCRE_5_0}
  223 {$IFDEF PCRE_7_7}
  224  PCRE_INFO_OKPARTIAL       = 12;
  225  PCRE_INFO_JCHANGED        = 13;
  226  PCRE_INFO_HASCRORLF       = 14;
  227 {$ENDIF}
  228 
  229 { Request types for pcre_config() }
  230 {$IFDEF PCRE_5_0}
  231  PCRE_CONFIG_UTF8               = 0;
  232  PCRE_CONFIG_NEWLINE            = 1;
  233  PCRE_CONFIG_LINK_SIZE          = 2;
  234  PCRE_CONFIG_POSIX_MALLOC_THRESHOLD = 3;
  235  PCRE_CONFIG_MATCH_LIMIT        = 4;
  236  PCRE_CONFIG_STACKRECURSE           = 5;
  237  PCRE_CONFIG_UNICODE_PROPERTIES     = 6;
  238 {$ENDIF PCRE_5_0}
  239 {$IFDEF PCRE_7_0}
  240  PCRE_CONFIG_MATCH_LIMIT_RECURSION  = 7;
  241 {$ENDIF}
  242 {$IFDEF PCRE_7_7}
  243  PCRE_CONFIG_BSR            = 8;
  244 {$ENDIF}
  245 
  246 { Bit flags for the pcre_extra structure }
  247 {$IFDEF PCRE_5_0}
  248  PCRE_EXTRA_STUDY_DATA        = $0001;
  249  PCRE_EXTRA_MATCH_LIMIT       = $0002;
  250  PCRE_EXTRA_CALLOUT_DATA      = $0004;
  251  PCRE_EXTRA_TABLES            = $0008;
  252 {$ENDIF PCRE_5_0}
  253 {$IFDEF PCRE_7_0}
  254  PCRE_EXTRA_MATCH_LIMIT_RECURSION = $0010;
  255 {$ENDIF}
  256 
  257 Const
  258 // DefaultOptions : integer = 0;
  259  DefaultLocaleTable : pointer = nil;
  260 
  261 {$IFDEF PCRE_5_0}
  262 { The structure for passing additional data to pcre_exec(). This is defined in
  263 such as way as to be extensible. Always add new fields at the end, in order to
  264 remain compatible. }
  265 
  266 type ppcre_extra = ^tpcre_extra;
  267      tpcre_extra = record
  268        flags : longint;            { Bits for which fields are set }
  269        study_data : pointer;           { Opaque data from pcre_study() }
  270        match_limit : longint;          { Maximum number of calls to match() }
  271        callout_data : pointer;         { Data passed back in callouts }
  272        tables : pointer;           { Pointer to character tables }
  273        match_limit_recursion: longint; { Max recursive calls to match() }
  274      end;
  275 
  276 type ppcre_callout_block = ^pcre_callout_block;
  277      pcre_callout_block = record
  278        version,
  279   (* ------------------------ Version 0 ------------------------------- *)
  280        callout_number : integer;
  281        offset_vector : pointer;
  282        subject : pchar;
  283        subject_length, start_match, current_position, capture_top,
  284        capture_last : integer;
  285        callout_data : pointer;
  286   (* ------------------- Added for Version 1 -------------------------- *)
  287        pattern_position, next_item_length : integer;
  288      end;
  289 {$ENDIF PCRE_5_0}
  290 
  291 {$OrgName+}
  292 {$IFDEF VIRTUALPASCAL} {&Cdecl+} {$ENDIF VIRTUALPASCAL}
  293 
  294  { local replacement of external pcre memory management functions }
  295  function pcre_malloc( size : integer ) : pointer;
  296  procedure pcre_free( {var} p : pointer );
  297 {$IFDEF PCRE_5_0}
  298  const pcre_stack_malloc: function ( size : integer ): pointer = pcre_malloc;
  299        pcre_stack_free: procedure ( {var} p : pointer ) = pcre_free;
  300  function pcre_callout(var p : ppcre_callout_block) : integer;
  301 {$ENDIF PCRE_5_0}
  302 {$IFDEF VIRTUALPASCAL} {&Cdecl-} {$ENDIF VIRTUALPASCAL}
  303 
  304 Implementation
  305 
  306 Uses strings, collect, messages, dnapp, commands, advance0, stringsx
  307     {$IFDEF VIRTUALPASCAL} ,vpsyslow {$ENDIF VIRTUALPASCAL};
  308 
  309 Const
  310  MAGIC_NUMBER = $50435245; { 'PCRE' }
  311  MAX_MATCHES = 90; { changed in 3.5 version; should be divisible by 3, was 64}
  312 
  313 Type
  314  PMatchArray = ^TMatchArray;
  315  TMatchArray = array[0..( MAX_MATCHES * 3 )] of integer;
  316 
  317  PRegExpCollection = ^TRegExpCollection;
  318  TRegExpCollection =  object(TSortedCollection)
  319    MaxRegExp : integer;
  320    SearchRegExp : shortstring;
  321    CompareModeInsert : boolean;
  322    constructor Init(AMaxRegExp:integer);
  323    procedure FreeItem(P: Pointer); virtual;
  324    function  Compare(P1, P2: Pointer): Integer; virtual;
  325    function  Find(ARegExp:shortstring;var P: PpcRegExp):boolean; virtual;
  326    function CheckNew(ARegExp:shortstring):PpcRegExp;virtual;
  327  end;
  328 
  329 Var
  330  PRegExpCache : PRegExpCollection;
  331 
  332 
  333 {$IFDEF VIRTUALPASCAL} {&Cdecl+} {$ENDIF VIRTUALPASCAL}
  334 
  335  { imported original pcre functions }
  336 
  337  function pcre_compile( const pattern : PChar; options : integer;
  338             var errorptr : PChar; var erroroffset : integer;
  339             const tables : PChar ) : pointer {pcre}; external;
  340 {$IFDEF PCRE_7_0}
  341  function pcre_compile2( const pattern : PChar; options : integer;
  342              var errorcodeptr : Integer;
  343              var errorptr : PChar; var erroroffset : integer;
  344              const tables : PChar ) : pointer {pcre}; external;
  345 {$ENDIF}
  346 {$IFDEF PCRE_5_0}
  347  function pcre_config( what : integer; where : pointer) : integer; external;
  348  function pcre_copy_named_substring( const code : pointer {pcre};
  349                      const subject : pchar;
  350                      var ovector : integer;
  351                      stringcount : integer;
  352                      const stringname : pchar;
  353                      var buffer : pchar;
  354                      size : integer) : integer; external;
  355  function pcre_copy_substring( const subject : pchar; var ovector : integer;
  356                    stringcount, stringnumber : integer;
  357                    var buffer : pchar; size : integer )
  358                    : integer; external;
  359  function pcre_exec( const argument_re : pointer {pcre};
  360              const extra_data : pointer {pcre_extra};
  361 {$ELSE}
  362  function pcre_exec( const external_re : pointer;
  363              const external_extra : pointer;
  364 {$ENDIF}
  365              const subject : PChar;
  366              length, start_offset, options : integer;
  367              offsets : pointer;
  368              offsetcount : integer ) : integer; external;
  369 {$IFDEF PCRE_7_0}
  370  function pcre_dfa_exec( const argument_re : pointer {pcre};
  371              const extra_data : pointer {pcre_extra};
  372              const subject : pchar;
  373              length, start_offset, options : integer;
  374              offsets : pointer;
  375              offsetcount : integer;
  376              workspace : pointer;
  377              wscount : integer ) : integer; external;
  378 {$ENDIF}
  379 {$IFDEF PCRE_5_0}
  380  procedure pcre_free_substring( const p : pchar ); external;
  381  procedure pcre_free_substring_list( var p : pchar ); external;
  382  function pcre_fullinfo( const argument_re : pointer {pcre};
  383              const extra_data : pointer {pcre_extra};
  384              what : integer;
  385              where : pointer ) : integer; external;
  386  function pcre_get_named_substring( const code : pointer {pcre};
  387                     const subject : pchar;
  388                     var ovector : integer;
  389                     stringcount : integer;
  390                     const stringname : pchar;
  391                     var stringptr : pchar ) : integer; external;
  392  function pcre_get_stringnumber( const code : pointer {pcre};
  393                  const stringname : pchar ) : integer; external;
  394  function pcre_get_stringtable_entries( const code : pointer {pcre};
  395                     const stringname : pchar;
  396                     var firstptr,
  397                         lastptr : pchar ) : integer; external;
  398  function pcre_get_substring( const subject : pchar; var ovector : integer;
  399                   stringcount, stringnumber : integer;
  400                   var stringptr : pchar ) : integer; external;
  401  function pcre_get_substring_list( const subject : pchar; var ovector : integer;
  402                    stringcount : integer;
  403                    listptr : pointer {const char ***listptr}) : integer; external;
  404  function pcre_info( const argument_re : pointer {pcre};
  405              var optptr : integer;
  406              var first_byte : integer ) : integer; external;
  407  function pcre_maketables : pchar; external;
  408 {$ENDIF}
  409 {$IFDEF PCRE_7_0}
  410  function pcre_refcount( const argument_re : pointer {pcre};
  411              adjust : integer ) : pchar; external;
  412 {$ENDIF}
  413  function pcre_study( const external_re : pointer {pcre};
  414               options : integer;
  415               var errorptr : PChar ) : pointer {pcre_extra}; external;
  416 {$IFDEF PCRE_5_0}
  417  function pcre_version : pchar; external;
  418 {$ENDIF}
  419 
  420  function pcre_malloc( size : integer ) : pointer;
  421  begin
  422   GetMem( result, size );
  423  end;
  424 
  425  procedure pcre_free( {var} p : pointer );
  426  begin
  427   if (p <> nil) then
  428     FreeMem( p, 0 );
  429   {@p := nil;}
  430  end;
  431 
  432 {$IFDEF PCRE_5_0}
  433 (* Called from PCRE as a result of the (?C) item. We print out where we are in
  434 the match. Yield zero unless more callouts than the fail count, or the callout
  435 data is not zero. *)
  436 
  437  function pcre_callout;
  438  begin
  439  end;
  440 {$ENDIF}
  441 
  442 {$IFDEF VIRTUALPASCAL} {&Cdecl-} {$ENDIF VIRTUALPASCAL}
  443 
  444 // Always include the newest version of the library
  445 {$IFDEF PCRE_7_7}
  446   {$L pcre77.lib}
  447 {$ELSE}
  448   {$IFDEF PCRE_7_0}
  449     {$L pcre70.lib}
  450   {$ELSE}
  451     {$IFDEF PCRE_5_0}
  452       {$L pcre50.lib}
  453     {$ELSE}
  454       {$IFDEF PCRE_3_7}
  455     {$L pcre37.lib}
  456       {$ENDIF PCRE_3_7}
  457     {$ENDIF PCRE_5_0}
  458   {$ENDIF PCRE_7_0}
  459 {$ENDIF PCRE_7_7}
  460 
  461 {TpcRegExp}
  462 
  463  constructor TpcRegExp.Init(const ARegExp:shortstring; AOptions:integer; ALocale : Pointer);
  464  var
  465   pRegExp : PChar;
  466  begin
  467   RegExp:=ARegExp;
  468   RegExpC:=nil;
  469   RegExpExt:=nil;
  470   Matches:=nil;
  471   MatchesCount:=0;
  472   Error:=true;
  473   ErrorMsg:=nil;
  474   ErrorPos:=0;
  475   RunTimeOptions := 0;
  476   if length(RegExp) < 255 then
  477    begin
  478     RegExp[length(RegExp)+1]:=#0;
  479     pRegExp:=@RegExp[1];
  480    end
  481   else
  482    begin
  483     GetMem(pRegExp,length(RegExp)+1);
  484     pRegExp:=strpcopy(pRegExp,RegExp);
  485    end;
  486   RegExpC := pcre_compile( pRegExp,
  487                AOptions and PCRE_COMPILE_ALLOWED_OPTIONS,
  488                ErrorMsg, ErrorPos, ALocale);
  489   if length(RegExp) = 255 then
  490    StrDispose(pRegExp);
  491   if RegExpC = nil then
  492    exit;
  493   ErrorMsg:=nil;
  494   RegExpExt := pcre_study( RegExpC, 0, ErrorMsg );
  495   if (RegExpExt = nil) and (ErrorMsg <> nil) then
  496    begin
  497     pcre_free(RegExpC);
  498     exit;
  499    end;
  500   GetMem(Matches,SizeOf(TMatchArray));
  501   Error:=false;
  502  end;
  503 
  504  destructor TpcRegExp.Done;
  505  begin
  506   if RegExpC <> nil then
  507     pcre_free(RegExpC);
  508   if RegExpExt <> nil then
  509     pcre_free(RegExpExt);
  510   if Matches <> nil then
  511     FreeMem(Matches,SizeOf(TMatchArray));
  512  end;
  513 
  514  function TpcRegExp.SearchNext( AStr: Pchar; ALen : longint ) : boolean;
  515  var Options: Integer;
  516  begin // must handle PCRE_ERROR_PARTIAL here
  517   Options := (RunTimeOptions or startup.MiscMultiData.cfgRegEx.DefaultOptions) and
  518          PCRE_EXEC_ALLOWED_OPTIONS;
  519   if MatchesCount > 0 then
  520     MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, PMatchArray(Matches)^[1],
  521                  Options, Matches, MAX_MATCHES ) else
  522     MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, 0,
  523                  Options, Matches, MAX_MATCHES );
  524 {  if MatchesCount = 0 then
  525     MatchesCount := MatchesCount div 3;}
  526   PartialMatch := MatchesCount = PCRE_ERROR_PARTIAL;
  527   SearchNext := MatchesCount > 0;
  528  end;
  529 
  530  function TpcRegExp.Search( AStr: Pchar; ALen : longint):boolean;
  531  begin
  532   MatchesCount:=0;
  533   Search:=SearchNext(AStr,ALen);
  534   SourceLen:=ALen;
  535  end;
  536 
  537  function TpcRegExp.SearchOfs( AStr: Pchar; ALen, AOfs: longint ) : boolean;
  538  var Options: Integer;
  539  begin
  540   MatchesCount:=0;
  541   Options := (RunTimeOptions or startup.MiscMultiData.cfgRegEx.DefaultOptions) and
  542          PCRE_EXEC_ALLOWED_OPTIONS;
  543   MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, AOfs,
  544                Options, Matches, MAX_MATCHES );
  545   PartialMatch := MatchesCount = PCRE_ERROR_PARTIAL;
  546   SearchOfs := MatchesCount > 0;
  547   SourceLen := ALen-AOfs;
  548  end;
  549 
  550  function TpcRegExp.MatchSub(ANom:integer; var Pos,Len:longint):boolean;
  551  begin
  552   if (MatchesCount > 0) and (ANom <= (MatchesCount-1)) then
  553    begin
  554     ANom:=ANom*2;
  555     Pos:=PMatchArray(Matches)^[ANom];
  556     Len:=PMatchArray(Matches)^[ANom+1]-Pos;
  557     MatchSub:=true;
  558    end
  559   else
  560    MatchSub:=false;
  561  end;
  562 
  563  function TpcRegExp.MatchFull(var Pos,Len:longint):boolean;
  564  begin
  565   MatchFull:=MatchSub(0,Pos,Len);
  566  end;
  567 
  568  function TpcRegExp.GetSubStr(ANom: integer; AStr: Pchar):string;
  569  var
  570   s: ansistring;
  571   pos,len: longint;
  572  begin
  573   s:='';
  574   if MatchSub(ANom, pos, len) then
  575    begin
  576     setlength(s, len);
  577     Move(AStr[pos], s[1], len);
  578    end;
  579   GetSubStr:=s;
  580  end;
  581 
  582  function TpcRegExp.GetPreSubStr(AStr: Pchar):string;
  583  var
  584   s: ansistring;
  585   l: longint;
  586  begin
  587   s:='';
  588   if (MatchesCount > 0) then
  589    begin
  590     l:=PMatchArray(Matches)^[0]-1;
  591     if l > 0 then
  592      begin
  593       setlength(s,l);
  594       Move(AStr[1],s[1],l);
  595      end;
  596    end;
  597   GetPreSubStr:=s;
  598  end;
  599 
  600  function TpcRegExp.GetPostSubStr(AStr: Pchar):string;
  601  var
  602   s: ansistring;
  603   l: longint;
  604   ANom: integer;
  605  begin
  606   s:='';
  607   if (MatchesCount > 0) then
  608    begin
  609     ANom:=(MatchesCount-1){*2} shl 1;
  610     l:=SourceLen-PMatchArray(Matches)^[ANom+1]+1;
  611     if l > 0 then
  612      begin
  613       setlength(s,l);
  614       Move(AStr[PMatchArray(Matches)^[ANom+1]],s[1],l);
  615      end;
  616    end;
  617   GetPostSubStr:=s;
  618  end;
  619 
  620 
  621  function TpcRegExp.GetFullStr(AStr: Pchar):string;
  622  var
  623   s: ansistring;
  624   l: longint;
  625  begin
  626   GetFullStr:=GetSubStr(0,AStr);
  627  end;
  628 
  629  function TpcRegExp.GetReplStr(AStr: Pchar; const ARepl: string):string;
  630  var
  631   s: ansistring;
  632   l,i,lasti: longint;
  633  begin
  634   l:=length(ARepl);
  635   i:=1;
  636   lasti:=1;
  637   s:='';
  638   while i <= l do
  639    begin
  640     case ARepl[i] of
  641      '\' :
  642       begin
  643        if i < l then
  644     begin
  645      s:=s+copy(ARepl,lasti,i-lasti){+ARepl[i+1]};
  646      {AH 17-10-05 support for POSIX \1-\9 backreferences}
  647      case ARepl[i+1] of
  648       '0' : s:=s+GetFullStr(AStr);
  649       '1'..'9' : s:=s+GetSubStr(ord(ARepl[i+1])-ord('0'),AStr);
  650       else s:=s+ARepl[i+1]; // copy the escaped character
  651      end;
  652     end;
  653        inc(i);
  654        lasti:=i+1;
  655       end;
  656      '$' :
  657       begin
  658        if i < l then
  659     begin
  660      s:=s+copy(ARepl,lasti,i-lasti);
  661      case ARepl[i+1] of
  662       '&' : s:=s+GetFullStr(AStr);
  663       '1'..'9' : s:=s+GetSubStr(ord(ARepl[i+1])-ord('0'),AStr);
  664       '`' : s:=s+GetPreSubStr(AStr);
  665       #39 : s:=s+GetPostSubStr(AStr);
  666      end;
  667     end;
  668        inc(i);
  669        lasti:=i+1;
  670       end;
  671     end;
  672     inc(i);
  673    end;
  674   if lasti <= {AH 25-10-2004 added =, else l==1 won't work} l then
  675     s:=s+copy(ARepl,lasti,l-lasti+1);
  676   GetReplStr:=s;
  677  end;
  678 
  679  function TpcRegExp.ErrorStr:string;
  680   begin
  681    ErrorStr:=StrPas(ErrorMsg);
  682   end;
  683 
  684 {TRegExpCollection}
  685 
  686 constructor TRegExpCollection.Init(AMaxRegExp: integer);
  687 begin
  688  Inherited Init(1,1);
  689  MaxRegExp:=AMaxRegExp;
  690  CompareModeInsert:=true;
  691 end;
  692 
  693 procedure TRegExpCollection.FreeItem(P: Pointer);
  694 begin
  695  if P <> nil then
  696   begin
  697    Dispose(PpcRegExp(P),Done);
  698   end;
  699 end;
  700 
  701 function  TRegExpCollection.Compare(P1, P2: Pointer): Integer;
  702 //var
  703 // l,l1,l2,i : byte;
  704 //// wPos: pchar;
  705 begin
  706  if CompareModeInsert then
  707   begin
  708 //   l1:=length(PpcRegExp(P1)^.RegExp);
  709 //   l2:=length(PpcRegExp(P2)^.RegExp);
  710 //   if l1 > l2 then l:=l2 else
  711 //               l:=l1;
  712 //   for i:=1 to l do
  713 //     if PpcRegExp(P1).RegExp[i] <> PpcRegExp(P2).RegExp[i] then break;
  714 //   if i <=l then
  715 //     Compare:=ord(PpcRegExp(P1).RegExp[i])-ord(PpcRegExp(P2).RegExp[i]) else
  716 //     Compare:=l1-l2;
  717     Compare := stringsx.PasStrCmp(PpcRegExp(P1).RegExp, PpcRegExp(P2).RegExp, False);
  718   end
  719  else
  720   begin
  721 //   l1:=length(PpcRegExp(P1)^.RegExp);
  722 //   l2:=length(SearchRegExp);
  723 //   if l1 > l2 then l:=l2 else
  724 //               l:=l1;
  725 //   for i:=1 to l do
  726 //     if PpcRegExp(P1).RegExp[i] <> SearchRegExp[i] then
  727 //     begin
  728 //       Compare:=ord(PpcRegExp(P1).RegExp[i])-ord(SearchRegExp[i]);
  729 //       break;
  730 //     end;
  731 //   if i > l then Compare:=l1-l2;
  732     Compare := stringsx.PasStrCmp(PpcRegExp(P1).RegExp, SearchRegExp, False);
  733   end;
  734 end;
  735 
  736 function  TRegExpCollection.Find(ARegExp:shortstring;var P: PpcRegExp):boolean;
  737 var I : integer;
  738 begin
  739  CompareModeInsert:=false;
  740  SearchRegExp:=ARegExp;
  741  if Search(nil,I) then
  742   begin
  743    P:=PpcRegExp(At(I));
  744    Find:=true;
  745   end
  746  else
  747   begin
  748    P:=nil;
  749    Find:=false;
  750   end;
  751  CompareModeInsert:=true;
  752 end;
  753 
  754 function TRegExpCollection.CheckNew(ARegExp:shortstring):PpcRegExp;
  755 var
  756  P : PpcRegExp;
  757 begin
  758  if not Find(ARegExp,P) then
  759   begin
  760    if Count = MaxRegExp then
  761     AtFree(0);
  762    P:=New(ppcRegExp,Init(ARegExp,PCRE_CASELESS,nil));
  763    Insert(P);
  764   end;
  765  CheckNew:=P;
  766 end;
  767 
  768 function pcGrepMatch(WildCard, aStr: string; AOptions:integer; ALocale : Pointer): Boolean;
  769 var
  770  PpcRE:PpcRegExp;
  771 begin
  772  PpcRE:=New(ppcRegExp,Init(WildCard,AOptions,Alocale));
  773  pcGrepMatch:=PpcRE^.Search(pchar(AStr),Length(AStr));
  774  Dispose(PpcRE,Done);
  775 end;
  776 
  777 function pcGrepSub(WildCard, aStr, aRepl: string; AOptions:integer; ALocale : Pointer): string;
  778 var
  779  PpcRE:PpcRegExp;
  780 begin
  781  PpcRE:=New(ppcRegExp,Init(WildCard,AOptions,Alocale));
  782  if PpcRE^.Search(pchar(AStr),Length(AStr)) then
  783   pcGrepSub:=PpcRE^.GetReplStr(pchar(AStr),ARepl)
  784  else
  785   pcGrepSub:='';
  786  Dispose(PpcRE,Done);
  787 end;
  788 
  789 function pcFastGrepMatch(WildCard, aStr: string): Boolean;
  790 var
  791  PpcRE:PpcRegExp;
  792 begin
  793  PpcRE:=PRegExpCache^.CheckNew(WildCard);
  794  pcFastGrepMatch:=PpcRE^.Search(pchar(AStr),Length(AStr));
  795 end;
  796 
  797 function pcFastGrepSub(WildCard, aStr, aRepl: string): string;
  798 var
  799  PpcRE:PpcRegExp;
  800 begin
  801  PpcRE:=PRegExpCache^.CheckNew(WildCard);
  802  if PpcRE^.Search(pchar(AStr),Length(AStr)) then
  803   pcFastGrepSub:=PpcRE^.GetReplStr(pchar(AStr),ARepl)
  804  else
  805   pcFastGrepSub:='';
  806 end;
  807 
  808 {$IFDEF PCRE_5_0}
  809 function pcGetVersion : pchar; assembler; {$FRAME-}{$USES none}
  810 asm
  811   call pcre_version
  812 end;
  813 {$ENDIF PCRE_5_0}
  814 
  815 function pcError;
  816 var P: ppcRegExp absolute pRegExp;
  817 begin
  818   Result := (P = nil) or P^.Error;
  819   If Result and (P <> nil) then
  820   begin
  821 {     if P^.ErrorPos = 0 then
  822       MessageBox(GetString(erRegExpCompile)+'"'+P^.ErrorStr+'"', nil,mfConfirmation+mfOkButton)
  823     else}
  824       MessageBox(GetString(erRegExpCompile)+'"'+P^.ErrorStr+'"'+GetString(erRegExpCompPos),
  825          @P^.ErrorPos,mfConfirmation+mfOkButton);
  826     Dispose(P, Done);
  827     P:=nil;
  828   end;
  829 end;
  830 
  831 function pcInit;
  832 var Options : Integer;
  833 begin
  834   If CaseSens then Options := 0 else Options := PCRE_CASELESS;
  835   Result := New( PpcRegExp, Init( Pattern,
  836                   {DefaultOptions}
  837                   startup.MiscMultiData.cfgRegEx.DefaultOptions or Options,
  838                   DefaultLocaleTable) );
  839 end;
  840 
  841 Initialization
  842  PRegExpCache:=New(PRegExpCollection,Init(64));
  843 Finalization
  844  Dispose(PRegExpCache,Done);
  845 End.