File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pcre / pcregexp.pas
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 08:25:56 2013 UTC (10 years, 10 months ago) by misho
Branches: pcre, MAIN
CVS tags: v8_34, v8_33, v8_31, v8_30, v8_21, HEAD
8.33

    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>