Annotation of embedaddon/pcre/pcregexp.pas, revision 1.1.1.1

1.1       misho       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.

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>