PageRenderTime 11ms CodeModel.GetById 10ms app.highlight 165ms RepoModel.GetById 1ms app.codeStats 1ms

/unicode_far/RegExp.cpp

https://bitbucket.org/regent/farmanager
C++ | 5054 lines | 4201 code | 724 blank | 129 comment | 755 complexity | f22272cb582641abcd3d3fd99c498d1c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2  Copyright Š 2000 Konstantin Stupnik
   3  Copyright Š 2008 Far Group
   4  All rights reserved.
   5
   6  Redistribution and use in source and binary forms, with or without
   7  modification, are permitted provided that the following conditions
   8  are met:
   9  1. Redistributions of source code must retain the above copyright
  10     notice, this list of conditions and the following disclaimer.
  11  2. Redistributions in binary form must reproduce the above copyright
  12     notice, this list of conditions and the following disclaimer in the
  13     documentation and/or other materials provided with the distribution.
  14  3. The name of the authors may not be used to endorse or promote products
  15     derived from this software without specific prior written permission.
  16
  17  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27
  28  Regular expressions support library.
  29  Syntax and semantics of regexps very close to
  30  syntax and semantics of perl regexps.
  31*/
  32
  33#include "headers.hpp"
  34#pragma hdrstop
  35
  36#include "RegExp.hpp"
  37
  38#ifndef RE_FAR_MODE
  39
  40#ifndef UNICODE
  41#ifndef RE_EXTERNAL_CTYPE
  42#include <ctype.h>
  43#endif
  44#else
  45#ifndef __LINUX
  46#include <windows.h>
  47#endif
  48#endif
  49#ifndef RE_NO_STRING_H
  50#include <string.h>
  51#endif
  52
  53#else
  54
  55#define malloc xf_malloc
  56#define free xf_free
  57
  58#endif
  59
  60#ifdef RE_DEBUG
  61#include <stdio.h>
  62#ifdef dpf
  63#undef dpf
  64#endif
  65#define dpf(x) printf x
  66
  67char *ops[]=
  68{
  69	"opNone",
  70	"opLineStart",
  71	"opLineEnd",
  72	"opDataStart",
  73	"opDataEnd",
  74	"opWordBound",
  75	"opNotWordBound",
  76	"opType",
  77	"opNotType",
  78	"opCharAny",
  79	"opCharAnyAll",
  80	"opSymbol",
  81	"opNotSymbol",
  82	"opSymbolIgnoreCase",
  83	"opNotSymbolIgnoreCase",
  84	"opSymbolClass",
  85	"opOpenBracket",
  86	"opClosingBracket",
  87	"opAlternative",
  88	"opBackRef",
  89#ifdef NAMEDBRACKETS
  90	"opNamedBracket",
  91	"opNamedBackRef",
  92#endif
  93	"opRangesBegin",
  94	"opRange",
  95	"opMinRange",
  96	"opSymbolRange",
  97	"opSymbolMinRange",
  98	"opNotSymbolRange",
  99	"opNotSymbolMinRange",
 100	"opAnyRange",
 101	"opAnyMinRange",
 102	"opTypeRange",
 103	"opTypeMinRange",
 104	"opNotTypeRange",
 105	"opNotTypeMinRange",
 106	"opClassRange",
 107	"opClassMinRange",
 108	"opBracketRange",
 109	"opBracketMinRange",
 110	"opBackRefRange",
 111	"opBackRefMinRange",
 112#ifdef NAMEDBRACKETS
 113	"opNamedRefRange",
 114	"opNamedRefMinRange",
 115#endif
 116	"opRangesEnd",
 117	"opAssertionsBegin",
 118	"opLookAhead",
 119	"opNotLookAhead",
 120	"opLookBehind",
 121	"opNotLookBehind",
 122	"opAsserionsEnd",
 123	"opNoReturn",
 124#ifdef RELIB
 125	"opLibCall",
 126#endif
 127	"opRegExpEnd",
 128};
 129
 130#else
 131#define dpf(x)
 132#endif
 133
 134#ifndef UNICODE
 135#ifdef RE_STATIC_LOCALE
 136#ifdef RE_EXTERNAL_CTYPE
 137prechar RegExp::lc;
 138prechar RegExp::uc;
 139prechar RegExp::chartypes;
 140#else
 141int RegExp::ilc[256/sizeof(int)];
 142int RegExp::iuc[256/sizeof(int)];
 143int RegExp::ichartypes[256/sizeof(int)];
 144rechar* RegExp::lc=(rechar*)RegExp::ilc;
 145rechar* RegExp::uc=(rechar*)RegExp::iuc;
 146rechar* RegExp::chartypes=(rechar*)RegExp::ichartypes;
 147#endif
 148int RegExp::icharbits[256/sizeof(int)];
 149rechar* RegExp::charbits=(rechar*)RegExp::icharbits;
 150#endif
 151#endif
 152
 153#ifdef UNICODE
 154#ifndef __LINUX
 155
 156#define ISDIGIT(c) iswdigit(c)
 157#define ISSPACE(c) iswspace(c)
 158#define ISWORD(c)  (IsCharAlphaNumeric(c) || c=='_')
 159#define ISLOWER(c) IsCharLower(c)
 160#define ISUPPER(c) IsCharUpper(c)
 161#define ISALPHA(c) IsCharAlpha(c)
 162#define TOUPPER(c) ((rechar)(DWORD_PTR)CharUpper((LPTSTR)(DWORD_PTR)c))
 163#define TOLOWER(c) ((rechar)(DWORD_PTR)CharLower((LPTSTR)(DWORD_PTR)c))
 164
 165#else
 166
 167#define ISDIGIT(c) iswdigit(c)
 168#define ISSPACE(c) iswspace(c)
 169#define ISWORD(c)  (iswalnum(c) || c=='_')
 170#define ISLOWER(c) iswlower(c)
 171#define ISUPPER(c) iswupper(c)
 172#define ISALPHA(c) iswalpha(c)
 173#define TOUPPER(c) towupper(c)
 174#define TOLOWER(c) towlower(c)
 175
 176#endif
 177
 178#define ISTYPE(c,t) isType(c,t)
 179
 180int isType(rechar chr,int type)
 181{
 182	switch (type)
 183	{
 184		case TYPE_DIGITCHAR:return ISDIGIT(chr);
 185		case TYPE_SPACECHAR:return ISSPACE(chr);
 186		case TYPE_WORDCHAR: return ISWORD(chr);
 187		case TYPE_LOWCASE:  return ISLOWER(chr);
 188		case TYPE_UPCASE:   return ISUPPER(chr);
 189		case TYPE_ALPHACHAR:return ISALPHA(chr);
 190	}
 191
 192	return false;
 193}
 194
 195int ushlen(const rechar* str)
 196{
 197	rechar ch;
 198	int len = -1;
 199
 200	do
 201	{
 202		ch = str[len+1];
 203		len++;
 204	}
 205	while (ch);
 206
 207	return len;
 208}
 209
 210#define strlen ushlen
 211
 212struct UniSet
 213{
 214	unsigned char* high[256];
 215	char types;
 216	char nottypes;
 217	char negative;
 218	UniSet()
 219	{
 220		ClearArray(high);
 221		types=0;
 222		nottypes=0;
 223		negative=0;
 224	}
 225	UniSet(const UniSet& src)
 226	{
 227		for (int i=0; i<256; i++)
 228		{
 229			if (src.high[i])
 230			{
 231				high[i]=new unsigned char[32];
 232				memcpy(high[i],src.high[i],32);
 233			}
 234			else
 235			{
 236				high[i]=nullptr;
 237			}
 238		}
 239
 240		types=src.types;
 241		nottypes=src.nottypes;
 242		negative=src.negative;
 243	}
 244	UniSet& operator=(const UniSet& src)
 245	{
 246		if (this != &src)
 247		{
 248			for (int i=0; i<256; i++)
 249			{
 250				if (src.high[i])
 251				{
 252					if (!high[i])high[i]=new unsigned char[32];
 253
 254					memcpy(high[i],src.high[i],32);
 255				}
 256				else
 257				{
 258					if (high[i])delete [] high[i];
 259
 260					high[i]=nullptr;
 261				}
 262			}
 263
 264			types=src.types;
 265			nottypes=src.nottypes;
 266			negative=src.negative;
 267		}
 268
 269		return (*this);
 270	}
 271
 272	void Reset()
 273	{
 274		for (int i=0; i<256; i++)
 275		{
 276			if (high[i])
 277			{
 278				delete [] high[i];
 279				high[i]=0;
 280			}
 281		}
 282
 283		types=0;
 284		nottypes=0;
 285		negative=0;
 286	}
 287
 288	struct Setter
 289	{
 290		UniSet& set;
 291		rechar idx;
 292		Setter(UniSet& s,rechar chr):set(s),idx(chr)
 293		{
 294		}
 295		void operator=(int val)
 296		{
 297			if (val)set.SetBit(idx);
 298			else set.ClearBit(idx);
 299		}
 300		bool operator!()const
 301		{
 302			return !set.GetBit(idx);
 303		}
 304	};
 305
 306	const bool operator[](rechar idx)const
 307	{
 308		return GetBit(idx);
 309	}
 310	Setter operator[](rechar idx)
 311	{
 312		return Setter(*this,idx);
 313	}
 314	~UniSet()
 315	{
 316		for (int i=0; i<256; i++)
 317		{
 318			if (high[i])delete [] high[i];
 319		}
 320	}
 321	bool CheckType(int t, rechar chr) const
 322	{
 323		switch (t)
 324		{
 325			case TYPE_DIGITCHAR:if (ISDIGIT(chr))return true; else break;
 326			case TYPE_SPACECHAR:if (ISSPACE(chr))return true; else break;
 327			case TYPE_WORDCHAR: if (ISWORD(chr)) return true; else break;
 328			case TYPE_LOWCASE:  if (ISLOWER(chr))return true; else break;
 329			case TYPE_UPCASE:   if (ISUPPER(chr))return true; else break;
 330			case TYPE_ALPHACHAR:if (ISALPHA(chr))return true; else break;
 331		}
 332
 333		return false;
 334	}
 335	bool GetBit(rechar chr) const
 336	{
 337		if (types)
 338		{
 339			int t=TYPE_ALPHACHAR;
 340
 341			while (t)
 342			{
 343				if (types&t)
 344				{
 345					if (CheckType(t,chr))
 346						return negative?false:true;
 347				}
 348
 349				t>>=1;
 350			}
 351		}
 352
 353		if (nottypes)
 354		{
 355			int t=TYPE_ALPHACHAR;
 356
 357			while (t)
 358			{
 359				if (nottypes&t)
 360				{
 361					if (!CheckType(t,chr))
 362						return negative?false:true;
 363				}
 364
 365				t>>=1;
 366			}
 367		}
 368
 369		unsigned char h=(chr&0xff00)>>8;
 370
 371		if (!high[h]) return negative?true:false;
 372
 373		if (((high[h][(chr&0xff)>>3]&(1<<(chr&7)))?1:0))
 374		{
 375			return negative?false:true;
 376		}
 377
 378		return negative?true:false;
 379	}
 380	void SetBit(rechar  chr)
 381	{
 382		unsigned char h=(chr&0xff00)>>8;
 383
 384		if (!high[h])
 385		{
 386			high[h]=new unsigned char[32];
 387			memset(high[h],0,32);
 388		}
 389
 390		high[h][(chr&0xff)>>3]|=1<<(chr&7);
 391	}
 392	void ClearBit(rechar  chr)
 393	{
 394		unsigned char h=(chr&0xff00)>>8;
 395
 396		if (!high[h])
 397		{
 398			high[h]=new unsigned char[32];
 399			memset(high[h],0,32);
 400		}
 401
 402		high[h][(chr&0xff)>>3]&=~(1<<(chr&7));
 403	}
 404
 405};
 406
 407#define GetBit(cls,chr) cls->GetBit(chr)
 408#define SetBit(cls,chr) cls->SetBit(chr)
 409
 410#else
 411#define ISDIGIT(c) ((chartypes[c]&TYPE_DIGITCHAR))
 412#define ISSPACE(c) ((chartypes[c]&TYPE_SPACECHAR))
 413#define ISWORD(c)  ((chartypes[c]&TYPE_WORDCHAR))
 414#define ISLOWER(c) ((chartypes[c]&TYPE_LOWCASE))
 415#define ISUPPER(c) ((chartypes[c]&TYPE_UPCASE))
 416#define ISALPHA(c) ((chartypes[c]&TYPE_ALPHACHAR))
 417#define TOUPPER(c) uc[c]
 418#define TOLOWER(c) lc[c]
 419
 420#define ISTYPE(c,t) (chartypes[c]&t)
 421
 422#endif //UNICODE
 423
 424
 425
 426enum REOp
 427{
 428	opLineStart=0x1,        // ^
 429	opLineEnd,              // $
 430	opDataStart,            // \A and ^ in single line mode
 431	opDataEnd,              // \Z and $ in signle line mode
 432
 433	opWordBound,            // \b
 434	opNotWordBound,         // \B
 435
 436	opType,                 // \d\s\w\l\u\e
 437	opNotType,              // \D\S\W\L\U\E
 438
 439	opCharAny,              // .
 440	opCharAnyAll,           // . in single line mode
 441
 442	opSymbol,               // single char
 443	opNotSymbol,            // [^c] negative charclass with one char
 444	opSymbolIgnoreCase,     // symbol with IGNORE_CASE turned on
 445	opNotSymbolIgnoreCase,  // [^c] with ignore case set.
 446
 447	opSymbolClass,          // [chars]
 448
 449	opOpenBracket,          // (
 450
 451	opClosingBracket,       // )
 452
 453	opAlternative,          // |
 454
 455	opBackRef,              // \1
 456
 457#ifdef NAMEDBRACKETS
 458	opNamedBracket,         // (?{name}
 459	opNamedBackRef,         // \p{name}
 460#endif
 461
 462
 463	opRangesBegin,          // for op type check
 464
 465	opRange,                // generic range
 466	opMinRange,             // generic minimizing range
 467
 468	opSymbolRange,          // quantifier applied to single char
 469	opSymbolMinRange,       // minimizing quantifier
 470
 471	opNotSymbolRange,       // [^x]
 472	opNotSymbolMinRange,
 473
 474	opAnyRange,             // .
 475	opAnyMinRange,
 476
 477	opTypeRange,            // \w, \d, \s
 478	opTypeMinRange,
 479
 480	opNotTypeRange,         // \W, \D, \S
 481	opNotTypeMinRange,
 482
 483	opClassRange,           // for char classes
 484	opClassMinRange,
 485
 486	opBracketRange,         // for brackets
 487	opBracketMinRange,
 488
 489	opBackRefRange,         // for backrefs
 490	opBackRefMinRange,
 491
 492#ifdef NAMEDBRACKETS
 493	opNamedRefRange,
 494	opNamedRefMinRange,
 495#endif
 496
 497	opRangesEnd,            // end of ranges
 498
 499	opAssertionsBegin,
 500
 501	opLookAhead,
 502	opNotLookAhead,
 503
 504	opLookBehind,
 505	opNotLookBehind,
 506
 507	opAsserionsEnd,
 508
 509	opNoReturn,
 510
 511#ifdef RELIB
 512	opLibCall,
 513#endif
 514	opRegExpEnd
 515};
 516
 517struct REOpCode
 518{
 519	int op;
 520	REOpCode *next,*prev;
 521#ifdef RE_DEBUG
 522	int    srcpos;
 523#endif
 524#ifdef RE_NO_NEWARRAY
 525	static void OnCreate(void *ptr);
 526	static void OnDelete(void *ptr);
 527#else
 528	REOpCode()
 529	{
 530		ClearStruct(*this);
 531	}
 532	~REOpCode();
 533#endif
 534
 535	struct SBracket
 536	{
 537		REOpCode* nextalt;
 538		int index;
 539		REOpCode* pairindex;
 540	};
 541
 542	struct SRange
 543	{
 544		union
 545		{
 546			SBracket bracket;
 547			int op;
 548			rechar symbol;
 549#ifdef UNICODE
 550			UniSet *symbolclass;
 551#else
 552			prechar symbolclass;
 553#endif
 554			REOpCode* nextalt;
 555			int refindex;
 556#ifdef NAMEDBRACKETS
 557			prechar refname;
 558#endif
 559			int type;
 560		};
 561		int min,max;
 562	};
 563
 564	struct SNamedBracket
 565	{
 566		REOpCode* nextalt;
 567		prechar name;
 568		REOpCode* pairindex;
 569	};
 570
 571	struct SAssert
 572	{
 573		REOpCode* nextalt;
 574		int length;
 575		REOpCode* pairindex;
 576	};
 577
 578	struct SAlternative
 579	{
 580		REOpCode* nextalt;
 581		REOpCode* endindex;
 582	};
 583
 584
 585	union
 586	{
 587		SRange range;
 588		SBracket bracket;
 589#ifdef NAMEDBRACKETS
 590		SNamedBracket nbracket;
 591#endif
 592		SAssert assert;
 593		SAlternative alternative;
 594		rechar symbol;
 595#ifdef UNICODE
 596		UniSet *symbolclass;
 597#else
 598		prechar symbolclass;
 599#endif
 600		int refindex;
 601#ifdef NAMEDBRACKETS
 602		prechar refname;
 603#endif
 604#ifdef RELIB
 605		prechar rename;
 606#endif
 607
 608		int type;
 609	};
 610};
 611
 612#ifdef RE_NO_NEWARRAY
 613void StateStackItem::OnCreate(void *ptr)
 614{
 615	memset(ptr,0,sizeof(StateStackItem));
 616}
 617
 618void REOpCode::OnCreate(void *ptr)
 619{
 620	memset(ptr,0,sizeof(REOpCode));
 621}
 622
 623void REOpCode::OnDelete(void *ptr)
 624{
 625	REOpCode &o=*static_cast<REOpCode*>(ptr);
 626
 627	switch (o.op)
 628	{
 629		case opSymbolClass:
 630
 631			if (o.symbolclass)
 632				free(o.symbolclass);
 633
 634			break;
 635		case opClassRange:
 636		case opClassMinRange:
 637
 638			if (o.range.symbolclass)
 639				free(o.range.symbolclass);
 640
 641			break;
 642#ifdef NAMEDBRACKETS
 643		case opNamedBracket:
 644
 645			if (o.nbracket.name)
 646				free(o.nbracket.name);
 647
 648			break;
 649		case opNamedBackRef:
 650
 651			if (o.refname)
 652				free(o.refname);
 653
 654			break;
 655#endif
 656#ifdef RELIB
 657		case opLibCall:
 658
 659			if (o.rename)
 660				free(o.rename);
 661
 662			break;
 663#endif
 664	}
 665}
 666
 667void *RegExp::CreateArray(const unsigned int size, const unsigned int total,
 668                          ON_CREATE_FUNC Create)
 669{
 670	if (total && size)
 671	{
 672		/* record[0] - sizeof
 673		   record[1] - total
 674		   record[2] - array
 675		*/
 676		unsigned char *record=static_cast<unsigned char*>
 677		                      (malloc(sizeof(unsigned int)*2+size*total));
 678
 679		if (record)
 680		{
 681			unsigned char *array=record+2*sizeof(unsigned int);
 682			*reinterpret_cast<int*>(record)=size;
 683			*reinterpret_cast<int*>(record+sizeof(unsigned int))=total;
 684
 685			if (Create)
 686				for (unsigned int f=0; f<total; ++f)
 687					Create(array+size*f);
 688
 689			return array;
 690		}
 691	}
 692
 693	return nullptr;
 694}
 695
 696void RegExp::DeleteArray(void **array, ON_DELETE_FUNC Delete)
 697{
 698	if (array && *array)
 699	{
 700		unsigned char *record=reinterpret_cast<unsigned char*>(*array)-
 701		                      2*sizeof(unsigned int);
 702
 703		if (Delete)
 704		{
 705			unsigned char *m=static_cast<unsigned char*>(*array);
 706			unsigned int size=*reinterpret_cast<int*>(record),
 707			                  total=*reinterpret_cast<int*>(record+sizeof(unsigned int));
 708
 709			for (unsigned int f=0; f<total; ++f)
 710				Delete(m+size*f);
 711		}
 712
 713		free(record);
 714		*array=nullptr;
 715	}
 716}
 717#else  // RE_NO_NEWARRAY
 718REOpCode::~REOpCode()
 719{
 720	switch (op)
 721	{
 722#ifdef UNICODE
 723		case opSymbolClass:delete symbolclass; break;
 724#else
 725case opSymbolClass:delete [] symbolclass; break;
 726#endif
 727#ifdef UNICODE
 728		case opClassRange:
 729		case opClassMinRange:delete range.symbolclass; break;
 730#else
 731case opClassRange:
 732case opClassMinRange:delete [] range.symbolclass; break;
 733#endif
 734#ifdef NAMEDBRACKETS
 735		case opNamedBracket:delete [] nbracket.name; break;
 736		case opNamedBackRef:delete [] refname; break;
 737#endif
 738#ifdef RELIB
 739		case opLibCall:delete [] rename; break;
 740#endif
 741	}
 742}
 743#endif // RE_NO_NEWARRAY
 744
 745
 746
 747void RegExp::Init(const prechar expr,int options)
 748{
 749	//ClearStruct(*this);
 750	code=nullptr;
 751	brhandler=nullptr;
 752	brhdata=nullptr;
 753#ifndef UNICODE
 754#ifndef RE_STATIC_LOCALE
 755#ifndef RE_EXTERNAL_CTYPE
 756	InitLocale();
 757#endif //RE_EXTERNAL_CTYPE
 758#endif//RE_STATIC_LOCALE
 759#endif //UNICODE
 760#ifdef NAMEDBRACKETS
 761	havenamedbrackets=0;
 762#endif
 763	stack=&initstack[0];
 764	st=&stack[0];
 765	initstackpage.stack=stack;
 766	firstpage=lastpage=&initstackpage;
 767	firstpage->next=nullptr;
 768	firstpage->prev=nullptr;
 769#ifdef UNICODE
 770	firstptr=new UniSet();
 771#define first (*firstptr)
 772#endif
 773	start=nullptr;
 774	end=nullptr;
 775	trimend=nullptr;
 776	Compile((const RECHAR*)expr,options);
 777}
 778
 779RegExp::RegExp():
 780	code(nullptr),
 781#ifdef NAMEDBRACKETS
 782	havenamedbrackets(0),
 783#endif
 784	stack(&initstack[0]),
 785	st(&stack[0]),
 786	slashChar('/'),
 787	backslashChar('\\'),
 788	firstpage(&initstackpage),
 789	lastpage(&initstackpage),
 790#ifdef UNICODE
 791	firstptr(new UniSet()),
 792#endif
 793	errorcode(errNotCompiled),
 794	start(nullptr),
 795	end(nullptr),
 796	trimend(nullptr),
 797#ifdef RE_DEBUG
 798	resrc(nullptr),
 799#endif
 800	brhandler(nullptr),
 801	brhdata(nullptr)
 802{
 803#ifndef UNICODE
 804#ifndef RE_STATIC_LOCALE
 805#ifndef RE_EXTERNAL_CTYPE
 806	InitLocale();
 807#endif
 808#endif
 809#endif//UNICODE
 810	initstackpage.stack=stack;
 811	firstpage->next=nullptr;
 812	firstpage->prev=nullptr;
 813}
 814
 815RegExp::RegExp(const RECHAR* expr,int options)
 816{
 817	slashChar='/';
 818	backslashChar='\\';
 819#ifdef RE_DEBUG
 820	resrc=nullptr;
 821#endif
 822	Init((const prechar)expr,options);
 823}
 824
 825RegExp::~RegExp()
 826{
 827#ifdef RE_DEBUG
 828#ifdef RE_NO_NEWARRAY
 829
 830	if (resrc)
 831		free(resrc);
 832
 833#else
 834	delete [] resrc;
 835#endif // RE_NO_NEWARRAY
 836#endif
 837
 838	if (code)
 839	{
 840#ifdef RE_NO_NEWARRAY
 841		DeleteArray(reinterpret_cast<void**>(&code),REOpCode::OnDelete);
 842#else
 843		delete [] code;
 844		code=nullptr;
 845#endif
 846	}
 847
 848	CleanStack();
 849#ifdef UNICODE
 850	delete firstptr;
 851#endif
 852}
 853
 854#ifndef UNICODE
 855#ifndef RE_EXTERNAL_CTYPE
 856void RegExp::InitLocale()
 857{
 858	for (int i=0; i<256; i++)
 859	{
 860		lc[i]=tolower(i);
 861		uc[i]=toupper(i);
 862	}
 863
 864	for (int i=0; i<256; i++)
 865	{
 866		char res=0;
 867
 868		if (isalnum(i) || i=='_')res|=TYPE_WORDCHAR;
 869
 870		if (isalpha(i))res|=TYPE_ALPHACHAR;
 871
 872		if (isdigit(i))res|=TYPE_DIGITCHAR;
 873
 874		if (isspace(i))res|=TYPE_SPACECHAR;
 875
 876		if (lc[i]==i && uc[i]!=i)res|=TYPE_LOWCASE;
 877
 878		if (uc[i]==i && lc[i]!=i)res|=TYPE_UPCASE;
 879
 880		chartypes[i]=res;
 881	}
 882
 883	memset(charbits,0,sizeof(charbits));
 884
 885	for (int i=0,j=0,k=1; i<256; i++)
 886	{
 887		if (chartypes[i]&TYPE_DIGITCHAR) {charbits[j]|=k;}
 888
 889		if (chartypes[i]&TYPE_SPACECHAR) {charbits[32+j]|=k;}
 890
 891		if (chartypes[i]&TYPE_WORDCHAR) {charbits[64+j]|=k;}
 892
 893		if (chartypes[i]&TYPE_LOWCASE) {charbits[96+j]|=k;}
 894
 895		if (chartypes[i]&TYPE_UPCASE) {charbits[128+j]|=k;}
 896
 897		if (chartypes[i]&TYPE_ALPHACHAR) {charbits[160+j]|=k;}
 898
 899		k<<=1;
 900
 901		if (k==256) {k=1; j++;}
 902	}
 903}
 904#endif
 905#endif
 906
 907
 908
 909int RegExp::CalcLength(const prechar src,int srclength)
 910{
 911	int length=3;//global brackets
 912	int brackets[MAXDEPTH];
 913	int count=0;
 914	int i,save;
 915	bracketscount=1;
 916	int inquote=0;
 917
 918	for (i=0; i<srclength; i++,length++)
 919	{
 920		if (inquote && src[i]!=backslashChar && src[i+1]!='E')
 921		{
 922			continue;
 923		}
 924
 925		if (src[i]==backslashChar)
 926		{
 927			i++;
 928
 929			if (src[i]=='Q')inquote=1;
 930
 931			if (src[i]=='E')inquote=0;
 932
 933			if (src[i]=='x')
 934			{
 935				i++;
 936				if(isxdigit(src[i]))
 937				{
 938					for(int j=1,k=i;j<4;j++)
 939					{
 940						if(isxdigit(src[k+j]))
 941						{
 942							i++;
 943						}
 944						else
 945						{
 946							break;
 947						}
 948					}
 949				}
 950				else return SetError(errSyntax,i);
 951			}
 952
 953#ifdef NAMEDBRACKETS
 954
 955			if (src[i]=='p')
 956			{
 957				i++;
 958
 959				if (src[i]!='{')
 960					return SetError(errSyntax,i);
 961
 962				i++;
 963				int save2=i;
 964
 965				while (i<srclength && (ISWORD(src[i]) || ISSPACE(src[i])) && src[i]!='}')
 966					i++;
 967
 968				if (i>=srclength)
 969					return SetError(errBrackets,save2);
 970
 971				if (src[i]!='}' && !(ISWORD(src[i]) || ISSPACE(src[i])))
 972					return SetError(errSyntax,i);
 973			}
 974
 975#endif
 976			continue;
 977		}
 978
 979		switch (src[i])
 980		{
 981			case '(':
 982			{
 983				brackets[count]=i;
 984				count++;
 985
 986				if (count==MAXDEPTH)return SetError(errMaxDepth,i);
 987
 988				if (src[i+1]=='?')
 989				{
 990					i+=2;
 991#ifdef NAMEDBRACKETS
 992
 993					if (src[i]=='{')
 994					{
 995						save=i;
 996						i++;
 997
 998						while (i<srclength && (ISWORD(src[i]) || ISSPACE(src[i])) && src[i]!='}')
 999							i++;
1000
1001						if (i>=srclength)
1002							return SetError(errBrackets,save);
1003
1004						if (src[i]!='}' && !(ISWORD(src[i]) || ISSPACE(src[i])))
1005							return SetError(errSyntax,i);
1006					}
1007
1008#endif
1009				}
1010				else
1011				{
1012					bracketscount++;
1013				}
1014
1015				break;
1016			}
1017			case ')':
1018			{
1019				count--;
1020
1021				if (count<0)return SetError(errBrackets,i);
1022
1023				break;
1024			}
1025			case '{':
1026			case '*':
1027			case '+':
1028			case '?':
1029			{
1030				length--;
1031
1032				if (src[i]=='{')
1033				{
1034					save=i;
1035
1036					while (i<srclength && src[i]!='}')i++;
1037
1038					if (i>=srclength)return SetError(errBrackets,save);
1039				}
1040
1041				if (src[i+1]=='?')i++;
1042
1043				break;
1044			}
1045			case '[':
1046			{
1047				save=i;
1048
1049				while (i<srclength && src[i]!=']')i++;
1050
1051				if (i>=srclength)return SetError(errBrackets,save);
1052
1053				break;
1054			}
1055#ifdef RELIB
1056			case '%':
1057			{
1058				i++;
1059				save=i;
1060
1061				while (i<srclength && src[i]!='%')i++;
1062
1063				if (i>=srclength)return SetError(errBrackets,save-1);
1064
1065				if (save==i)return SetError(errSyntax,save);
1066			} break;
1067#endif
1068		}
1069	}
1070
1071	if (count)
1072	{
1073		errorpos=brackets[0];
1074		errorcode=errBrackets;
1075		return 0;
1076	}
1077
1078	return length;
1079}
1080
1081int RegExp::Compile(const RECHAR* src,int options)
1082{
1083	int srcstart=0,srclength/*=0*/,relength;
1084
1085	if (options&OP_CPPMODE)
1086	{
1087		slashChar='\\';
1088		backslashChar='/';
1089	}
1090	else
1091	{
1092		slashChar='/';
1093		backslashChar='\\';
1094	}
1095
1096	havefirst=0;
1097#ifdef RE_NO_NEWARRAY
1098	DeleteArray(reinterpret_cast<void**>(&code),REOpCode::OnDelete);
1099#else
1100
1101	if (code)delete [] code;
1102
1103	code=nullptr;
1104#endif
1105
1106	if (options&OP_PERLSTYLE)
1107	{
1108		if (src[0]!=slashChar)return SetError(errSyntax,0);
1109
1110		srcstart=1;
1111		srclength=1;
1112
1113		while (src[srclength] && src[srclength]!=slashChar)
1114		{
1115			if (src[srclength]==backslashChar && src[srclength+1])
1116			{
1117				srclength++;
1118			}
1119
1120			srclength++;
1121		}
1122
1123		if (!src[srclength])
1124		{
1125			return SetError(errSyntax,srclength-1);
1126		}
1127
1128		int i=srclength+1;
1129		srclength--;
1130
1131		while (src[i])
1132		{
1133			switch (src[i])
1134			{
1135				case 'i':options|=OP_IGNORECASE; break;
1136				case 's':options|=OP_SINGLELINE; break;
1137				case 'm':options|=OP_MULTILINE; break;
1138				case 'x':options|=OP_XTENDEDSYNTAX; break;
1139				case 'o':options|=OP_OPTIMIZE; break;
1140				default:return SetError(errOptions,i);
1141			}
1142
1143			i++;
1144		}
1145	}
1146	else
1147	{
1148		srclength=(int)strlen(src);
1149	}
1150
1151	ignorecase=options&OP_IGNORECASE?1:0;
1152	relength=CalcLength((const prechar)src+srcstart,srclength);
1153
1154	if (!relength)
1155	{
1156		return 0;
1157	}
1158
1159#ifdef RE_NO_NEWARRAY
1160	code=static_cast<REOpCode*>
1161	     (CreateArray(sizeof(REOpCode), relength, REOpCode::OnCreate));
1162#else
1163	code=new REOpCode[relength];
1164	memset(code,0,sizeof(REOpCode)*relength);
1165#endif
1166
1167	for (int i=0; i<relength; i++)
1168	{
1169		code[i].next=i<relength-1?code+i+1:0;
1170		code[i].prev=i>0?code+i-1:0;
1171	}
1172
1173	int result=InnerCompile((const prechar)src+srcstart,srclength,options);
1174
1175	if (!result)
1176	{
1177#ifdef RE_NO_NEWARRAY
1178		DeleteArray(reinterpret_cast<void**>(&code),REOpCode::OnDelete);
1179#else
1180		delete [] code;
1181		code=nullptr;
1182#endif
1183	}
1184	else
1185	{
1186		errorcode=errNone;
1187		minlength=0;
1188
1189		if (options&OP_OPTIMIZE)Optimize();
1190	}
1191
1192	return result;
1193}
1194
1195int RegExp::GetNum(const prechar src,int& i)
1196{
1197	int res=0;//atoi((const char*)src+i);
1198
1199	while (ISDIGIT(src[i]))
1200	{
1201		res*=10;
1202		res+=src[i]-'0';
1203		i++;
1204	}
1205
1206	return res;
1207}
1208
1209static int CalcPatternLength(PREOpCode from,PREOpCode to)
1210{
1211	int len=0;
1212	int altcnt=0;
1213	int altlen=-1;
1214
1215	for (; from->prev!=to; from=from->next)
1216	{
1217		switch (from->op)
1218		{
1219				//zero width
1220			case opLineStart:
1221			case opLineEnd:
1222			case opDataStart:
1223			case opDataEnd:
1224			case opWordBound:
1225			case opNotWordBound:continue;
1226			case opType:
1227			case opNotType:
1228			case opCharAny:
1229			case opCharAnyAll:
1230			case opSymbol:
1231			case opNotSymbol:
1232			case opSymbolIgnoreCase:
1233			case opNotSymbolIgnoreCase:
1234			case opSymbolClass:
1235				len++;
1236				altcnt++;
1237				continue;
1238#ifdef NAMEDBRACKETS
1239			case opNamedBracket:
1240#endif
1241			case opOpenBracket:
1242			{
1243				int l=CalcPatternLength(from->next,from->bracket.pairindex->prev);
1244
1245				if (l==-1)return -1;
1246
1247				len+=l;
1248				altcnt+=l;
1249				from=from->bracket.pairindex;
1250				continue;
1251			}
1252			case opClosingBracket:
1253				break;
1254			case opAlternative:
1255
1256				if (altlen!=-1 && altcnt!=altlen)return -1;
1257
1258				altlen=altcnt;
1259				altcnt=0;
1260				continue;
1261			case opBackRef:
1262#ifdef NAMEDBRACKETS
1263			case opNamedBackRef:
1264#endif
1265				return -1;
1266			case opRangesBegin:
1267			case opRange:
1268			case opMinRange:
1269			case opSymbolRange:
1270			case opSymbolMinRange:
1271			case opNotSymbolRange:
1272			case opNotSymbolMinRange:
1273			case opAnyRange:
1274			case opAnyMinRange:
1275			case opTypeRange:
1276			case opTypeMinRange:
1277			case opNotTypeRange:
1278			case opNotTypeMinRange:
1279			case opClassRange:
1280			case opClassMinRange:
1281
1282				if (from->range.min!=from->range.max)return -1;
1283
1284				len+=from->range.min;
1285				altcnt+=from->range.min;
1286				continue;
1287			case opBracketRange:
1288			case opBracketMinRange:
1289			{
1290				if (from->range.min!=from->range.max)return -1;
1291
1292				int l=CalcPatternLength(from->next,from->bracket.pairindex->prev);
1293
1294				if (l==-1)return -1;
1295
1296				len+=from->range.min*l;
1297				altcnt+=from->range.min*l;
1298				from=from->bracket.pairindex;
1299				continue;
1300			}
1301			case opBackRefRange:
1302			case opBackRefMinRange:
1303#ifdef NAMEDBRACKETS
1304			case opNamedRefRange:
1305			case opNamedRefMinRange:
1306#endif
1307				return -1;
1308			case opRangesEnd:
1309			case opAssertionsBegin:
1310			case opLookAhead:
1311			case opNotLookAhead:
1312			case opLookBehind:
1313			case opNotLookBehind:
1314				from=from->assert.pairindex;
1315				continue;
1316			case opAsserionsEnd:
1317			case opNoReturn:
1318				continue;
1319#ifdef RELIB
1320			case opLibCall:
1321				return -1;
1322#endif
1323		}
1324	}
1325
1326	if (altlen!=-1 && altlen!=altcnt)return -1;
1327
1328	return altlen==-1?len:altlen;
1329}
1330
1331int RegExp::InnerCompile(const prechar src,int srclength,int options)
1332{
1333	int i,j;
1334	PREOpCode brackets[MAXDEPTH];
1335	// current brackets depth
1336	// one place reserved for surrounding 'main' brackets
1337	int brdepth=1;
1338	// compiling interior of lookbehind
1339	// used to apply restrictions of lookbehind
1340	int lookbehind=0;
1341	// counter of normal brackets
1342	int brcount=0;
1343	// counter of closed brackets
1344	// used to check correctness of backreferences
1345	bool closedbrackets[MAXDEPTH];
1346	// quoting is active
1347	int inquote=0;
1348	maxbackref=0;
1349#ifdef UNICODE
1350	UniSet *tmpclass;
1351#else
1352	rechar tmpclass[32];
1353	int *itmpclass=(int*)tmpclass;
1354#endif
1355	code->op=opOpenBracket;
1356	code->bracket.index=0;
1357#ifdef NAMEDBRACKETS
1358	MatchHash h;
1359	SMatch m;
1360#endif
1361	int pos=1;
1362	register PREOpCode op;//=code;
1363	brackets[0]=code;
1364#ifdef RE_DEBUG
1365#ifdef RE_NO_NEWARRAY
1366	resrc=static_cast<rechar*>(malloc(sizeof(rechar)*(srclength+4)));
1367#else
1368	resrc=new rechar[srclength+4];
1369#endif // RE_NO_NEWARRAY
1370	resrc[0]='(';
1371	resrc[1]=0;
1372	memcpy(resrc+1,src,srclength*sizeof(rechar));
1373	resrc[srclength+1]=')';
1374	resrc[srclength+2]=27;
1375	resrc[srclength+3]=0;
1376#endif
1377	havelookahead=0;
1378
1379	for (i=0; i<srclength; i++)
1380	{
1381		op=code+pos;
1382		pos++;
1383#ifdef RE_DEBUG
1384		op->srcpos=i+1;
1385#endif
1386
1387		if (inquote && src[i]!=backslashChar)
1388		{
1389			op->op=ignorecase?opSymbolIgnoreCase:opSymbol;
1390			op->symbol=ignorecase?TOLOWER(src[i]):src[i];
1391
1392			if (ignorecase && TOUPPER(op->symbol)==op->symbol)op->op=opSymbol;
1393
1394			continue;
1395		}
1396
1397		if (src[i]==backslashChar)
1398		{
1399			i++;
1400
1401			if (inquote && src[i]!='E')
1402			{
1403				op->op=opSymbol;
1404				op->symbol=backslashChar;
1405				op=code+pos;
1406				pos++;
1407				op->op=ignorecase?opSymbolIgnoreCase:opSymbol;
1408				op->symbol=ignorecase?TOLOWER(src[i]):src[i];
1409
1410				if (ignorecase && TOUPPER(op->symbol)==op->symbol)op->op=opSymbol;
1411
1412				continue;
1413			}
1414
1415			op->op=opType;
1416
1417			switch (src[i])
1418			{
1419				case 'Q':inquote=1; pos--; continue;
1420				case 'E':inquote=0; pos--; continue;
1421				case 'b':op->op=opWordBound; continue;
1422				case 'B':op->op=opNotWordBound; continue;
1423				case 'D':op->op=opNotType;
1424				case 'd':op->type=TYPE_DIGITCHAR; continue;
1425				case 'S':op->op=opNotType;
1426				case 's':op->type=TYPE_SPACECHAR; continue;
1427				case 'W':op->op=opNotType;
1428				case 'w':op->type=TYPE_WORDCHAR; continue;
1429				case 'U':op->op=opNotType;
1430				case 'u':op->type=TYPE_UPCASE; continue;
1431				case 'L':op->op=opNotType;
1432				case 'l':op->type=TYPE_LOWCASE; continue;
1433				case 'I':op->op=opNotType;
1434				case 'i':op->type=TYPE_ALPHACHAR; continue;
1435				case 'A':op->op=opDataStart; continue;
1436				case 'Z':op->op=opDataEnd; continue;
1437				case 'n':op->op=opSymbol; op->symbol='\n'; continue;
1438				case 'r':op->op=opSymbol; op->symbol='\r'; continue;
1439				case 't':op->op=opSymbol; op->symbol='\t'; continue;
1440				case 'f':op->op=opSymbol; op->symbol='\f'; continue;
1441				case 'e':op->op=opSymbol; op->symbol=27; continue;
1442				case 'O':op->op=opNoReturn; continue;
1443#ifdef NAMEDBRACKETS
1444				case 'p':
1445				{
1446					op->op=opNamedBackRef;
1447					i++;
1448
1449					if (src[i]!='{')return SetError(errSyntax,i);
1450
1451					int len=0; i++;
1452
1453					while (src[i+len]!='}')len++;
1454
1455					if (len>0)
1456					{
1457#ifdef RE_NO_NEWARRAY
1458						op->refname=static_cast<rechar*>(malloc(sizeof(rechar)*(len+1)));
1459#else
1460						op->refname=new rechar[len+1];
1461#endif
1462						memcpy(op->refname,src+i,len*sizeof(rechar));
1463						op->refname[len]=0;
1464
1465						if (!h.Exists((char*)op->refname))
1466						{
1467							return SetError(errReferenceToUndefinedNamedBracket,i);
1468						}
1469
1470						i+=len;
1471					}
1472					else
1473					{
1474						return SetError(errSyntax,i);
1475					}
1476				} continue;
1477#endif
1478				case 'x':
1479				{
1480					i++;
1481
1482					if (i>=srclength)return SetError(errSyntax,i-1);
1483
1484					if(isxdigit(src[i]))
1485					{
1486						int c=TOLOWER(src[i])-'0';
1487
1488						if (c>9)c-='a'-'0'-10;
1489
1490						op->op=ignorecase?opSymbolIgnoreCase:opSymbol;
1491						op->symbol=c;
1492						for(int j=1,k=i;j<4 && k+j<srclength;j++)
1493						{
1494							if(isxdigit(src[k+j]))
1495							{
1496								i++;
1497								c=TOLOWER(src[k+j])-'0';
1498								if (c>9)c-='a'-'0'-10;
1499								op->symbol<<=4;
1500								op->symbol|=c;
1501							}
1502							else
1503							{
1504								break;
1505							}
1506						}
1507						if (ignorecase)
1508						{
1509							op->symbol=TOLOWER(op->symbol);
1510							if (TOUPPER(op->symbol)==TOLOWER(op->symbol))
1511							{
1512								op->op=opSymbol;
1513							}
1514						}
1515					}
1516					else return SetError(errSyntax,i);
1517
1518					continue;
1519				}
1520				default:
1521				{
1522					if (ISDIGIT(src[i]))
1523					{
1524						int save=i;
1525						op->op=opBackRef;
1526						op->refindex=GetNum(src,i); i--;
1527
1528						if (op->refindex<=0 || op->refindex>brcount || !closedbrackets[op->refindex])
1529						{
1530							return SetError(errInvalidBackRef,save-1);
1531						}
1532
1533						if (op->refindex>maxbackref)maxbackref=op->refindex;
1534					}
1535					else
1536					{
1537						if (options&OP_STRICT && ISALPHA(src[i]))
1538						{
1539							return SetError(errInvalidEscape,i-1);
1540						}
1541
1542						op->op=ignorecase?opSymbolIgnoreCase:opSymbol;
1543						op->symbol=ignorecase?TOLOWER(src[i]):src[i];
1544
1545						if (TOLOWER(op->symbol)==TOUPPER(op->symbol))
1546						{
1547							op->op=opSymbol;
1548						}
1549					}
1550				}
1551			}
1552
1553			continue;
1554		}
1555
1556		switch (src[i])
1557		{
1558			case '.':
1559			{
1560				if (options&OP_SINGLELINE)
1561				{
1562					op->op=opCharAnyAll;
1563				}
1564				else
1565				{
1566					op->op=opCharAny;
1567				}
1568
1569				continue;
1570			}
1571			case '^':
1572			{
1573				if (options&OP_MULTILINE)
1574				{
1575					op->op=opLineStart;
1576				}
1577				else
1578				{
1579					op->op=opDataStart;
1580				}
1581
1582				continue;
1583			}
1584			case '$':
1585			{
1586				if (options&OP_MULTILINE)
1587				{
1588					op->op=opLineEnd;
1589				}
1590				else
1591				{
1592					op->op=opDataEnd;
1593				}
1594
1595				continue;
1596			}
1597			case '|':
1598			{
1599				if (brackets[brdepth-1]->op==opAlternative)
1600				{
1601					brackets[brdepth-1]->alternative.nextalt=op;
1602				}
1603				else
1604				{
1605					if (brackets[brdepth-1]->op==opOpenBracket)
1606					{
1607						brackets[brdepth-1]->bracket.nextalt=op;
1608					}
1609					else
1610					{
1611						brackets[brdepth-1]->assert.nextalt=op;
1612					}
1613				}
1614
1615				if (brdepth==MAXDEPTH)return SetError(errMaxDepth,i);
1616
1617				brackets[brdepth++]=op;
1618				op->op=opAlternative;
1619				continue;
1620			}
1621			case '(':
1622			{
1623				op->op=opOpenBracket;
1624
1625				if (src[i+1]=='?')
1626				{
1627					i+=2;
1628
1629					switch (src[i])
1630					{
1631						case ':':op->bracket.index=-1; break;
1632						case '=':op->op=opLookAhead; havelookahead=1; break;
1633						case '!':op->op=opNotLookAhead; havelookahead=1; break;
1634						case '<':
1635						{
1636							i++;
1637
1638							if (src[i]=='=')
1639							{
1640								op->op=opLookBehind;
1641							}
1642							else if (src[i]=='!')
1643							{
1644								op->op=opNotLookBehind;
1645							}
1646							else return SetError(errSyntax,i);
1647
1648							lookbehind++;
1649						} break;
1650#ifdef NAMEDBRACKETS
1651						case '{':
1652						{
1653							op->op=opNamedBracket;
1654							havenamedbrackets=1;
1655							int len=0;
1656							i++;
1657
1658							while (src[i+len]!='}')len++;
1659
1660							if (len>0)
1661							{
1662#ifdef RE_NO_NEWARRAY
1663								op->nbracket.name=static_cast<rechar*>(malloc(sizeof(rechar)*(len+1)));
1664#else
1665								op->nbracket.name=new rechar[len+1];
1666#endif
1667								memcpy(op->nbracket.name,src+i,len*sizeof(rechar));
1668								op->nbracket.name[len]=0;
1669								//h.SetItem((char*)op->nbracket.name,m);
1670							}
1671							else
1672							{
1673								op->op=opOpenBracket;
1674								op->bracket.index=-1;
1675							}
1676
1677							i+=len;
1678						} break;
1679#endif
1680						default:
1681						{
1682							return SetError(errSyntax,i);
1683						}
1684					}
1685				}
1686				else
1687				{
1688					brcount++;
1689					closedbrackets[brcount]=false;
1690					op->bracket.index=brcount;
1691				}
1692
1693				brackets[brdepth]=op;
1694				brdepth++;
1695				continue;
1696			}
1697			case ')':
1698			{
1699				op->op=opClosingBracket;
1700				brdepth--;
1701
1702				while (brackets[brdepth]->op==opAlternative)
1703				{
1704					brackets[brdepth]->alternative.endindex=op;
1705					brdepth--;
1706				}
1707
1708				switch (brackets[brdepth]->op)
1709				{
1710					case opOpenBracket:
1711					{
1712						op->bracket.pairindex=brackets[brdepth];
1713						brackets[brdepth]->bracket.pairindex=op;
1714						op->bracket.index=brackets[brdepth]->bracket.index;
1715
1716						if (op->bracket.index!=-1)
1717						{
1718							closedbrackets[op->bracket.index]=true;
1719						}
1720
1721						break;
1722					}
1723#ifdef NAMEDBRACKETS
1724					case opNamedBracket:
1725					{
1726						op->nbracket.pairindex=brackets[brdepth];
1727						brackets[brdepth]->nbracket.pairindex=op;
1728						op->nbracket.name=brackets[brdepth]->nbracket.name;
1729						h.SetItem((char*)op->nbracket.name,m);
1730						break;
1731					}
1732#endif
1733					case opLookBehind:
1734					case opNotLookBehind:
1735					{
1736						lookbehind--;
1737						int l=CalcPatternLength(brackets[brdepth]->next,op->prev);
1738
1739						if (l==-1)return SetError(errVariableLengthLookBehind,i);
1740
1741						brackets[brdepth]->assert.length=l;
1742					}// there is no break and this is correct!
1743					case opLookAhead:
1744					case opNotLookAhead:
1745					{
1746						op->assert.pairindex=brackets[brdepth];
1747						brackets[brdepth]->assert.pairindex=op;
1748						break;
1749					}
1750				}
1751
1752				continue;
1753			}
1754			case '[':
1755			{
1756				i++;
1757				int negative=0;
1758
1759				if (src[i]=='^')
1760				{
1761					negative=1;
1762					i++;
1763				}
1764
1765				int lastchar=0;
1766				int classsize=0;
1767				op->op=opSymbolClass;
1768				//op->symbolclass=new rechar[32];
1769				//memset(op->symbolclass,0,32);
1770#ifdef UNICODE
1771				op->symbolclass=new UniSet();
1772				tmpclass=op->symbolclass;
1773           #define IF_U(t)
1774#else
1775
1776				for (j=0; j<8; j++)itmpclass[j]=0;
1777				int classindex=0;
1778           #define IF_U(t) t
1779#endif
1780
1781				for (; src[i]!=']'; i++)
1782				{
1783					if (src[i]==backslashChar)
1784					{
1785						i++;
1786						int isnottype=0;
1787						int type=0;
1788						lastchar=0;
1789
1790						switch (src[i])
1791						{
1792							case 'D':isnottype=1;
1793							case 'd':type=TYPE_DIGITCHAR; IF_U(classindex=0); break;
1794							case 'W':isnottype=1;
1795							case 'w':type=TYPE_WORDCHAR; IF_U(classindex=64); break;
1796							case 'S':isnottype=1;
1797							case 's':type=TYPE_SPACECHAR; IF_U(classindex=32); break;
1798							case 'L':isnottype=1;
1799							case 'l':type=TYPE_LOWCASE; IF_U(lassindex=96); break;
1800							case 'U':isnottype=1;
1801							case 'u':type=TYPE_UPCASE; IF_U(classindex=128); break;
1802							case 'I':isnottype=1;
1803							case 'i':type=TYPE_ALPHACHAR; IF_U(classindex=160); break;
1804							case 'n':lastchar='\n'; break;
1805							case 'r':lastchar='\r'; break;
1806							case 't':lastchar='\t'; break;
1807							case 'f':lastchar='\f'; break;
1808							case 'e':lastchar=27; break;
1809							case 'x':
1810							{
1811								i++;
1812
1813								if (i>=srclength)return SetError(errSyntax,i-1);
1814
1815								if (isxdigit(src[i]))
1816								{
1817									int c=TOLOWER(src[i])-'0';
1818
1819									if (c>9)c-='a'-'0'-10;
1820
1821									lastchar=c;
1822
1823									for(int j=1,k=i;j<4 && k+j<srclength;j++)
1824									{
1825										if (isxdigit(src[k+j]))
1826										{
1827											i++;
1828											c=TOLOWER(src[k+j])-'0';
1829
1830											if (c>9)c-='a'-'0'-10;
1831
1832											lastchar<<=4;
1833											lastchar|=c;
1834										}
1835										else
1836										{
1837											break;
1838										}
1839									}
1840									dpf(("Last char=%c(%02x)\n",lastchar,lastchar));
1841								}
1842								else return SetError(errSyntax,i);
1843
1844								break;
1845							}
1846							default:
1847							{
1848								if (options&OP_STRICT && ISALPHA(src[i]))
1849								{
1850									return SetError(errInvalidEscape,i-1);
1851								}
1852
1853								lastchar=src[i];
1854							}
1855						}
1856
1857						if (type)
1858						{
1859#ifdef UNICODE
1860
1861							if (isnottype)
1862							{
1863								tmpclass->nottypes|=type;
1864							}
1865							else
1866							{
1867								tmpclass->types|=type;
1868							}
1869
1870#else
1871							isnottype=isnottype?0xffffffff:0;
1872							int *b=(int*)(charbits+classindex);
1873
1874							for (j=0; j<8; j++)
1875							{
1876								itmpclass[j]|=b[j]^isnottype;
1877							}
1878
1879#endif
1880							classsize=257;
1881							//for(int j=0;j<32;j++)op->symbolclass[j]|=charbits[classindex+j]^isnottype;
1882							//classsize+=charsizes[classindex>>5];
1883							//int setbit;
1884							/*for(int j=0;j<256;j++)
1885							{
1886							  setbit=(chartypes[j]^isnottype)&type;
1887							  if(setbit)
1888							  {
1889							    if(ignorecase)
1890							    {
1891							      SetBit(op->symbolclass,lc[j]);
1892							      SetBit(op->symbolclass,uc[j]);
1893							    }else
1894							    {
1895							      SetBit(op->symbolclass,j);
1896							    }
1897							    classsize++;
1898							  }
1899							}*/
1900						}
1901						else
1902						{
1903							if (options&OP_IGNORECASE)
1904							{
1905								SetBit(tmpclass,TOLOWER(lastchar));
1906								SetBit(tmpclass,TOUPPER(lastchar));
1907							}
1908							else
1909							{
1910								SetBit(tmpclass,lastchar);
1911							}
1912
1913							classsize++;
1914						}
1915
1916						continue;
1917					}
1918
1919					if (src[i]=='-')
1920					{
1921						if (lastchar && src[i+1]!=']')
1922						{
1923							int to=src[i+1];
1924
1925							if (to==backslashChar)
1926							{
1927								to=src[i+2];
1928
1929								if (to=='x')
1930								{
1931									i+=2;
1932									to=TOLOWER(src[i+1]);
1933
1934									if(isxdigit(to))
1935									{
1936										to-='0';
1937
1938										if (to>9)to-='a'-'0'-10;
1939
1940										for(int j=1,k=(i+1);j<4 && k+j<srclength;j++)
1941										{
1942											int c=TOLOWER(src[k+j]);
1943											if(isxdigit(c))
1944											{
1945												i++;
1946												c-='0';
1947
1948												if (c>9)c-='a'-'0'-10;
1949
1950												to<<=4;
1951												to|=c;
1952											}
1953											else
1954											{
1955												break;
1956											}
1957										}
1958									}
1959									else return SetError(errSyntax,i);
1960								}
1961								else
1962								{
1963									SetBit(tmpclass,'-');
1964									classsize++;
1965									continue;
1966								}
1967							}
1968
1969							i++;
1970							dpf(("from %d to %d\n",lastchar,to));
1971
1972							for (j=lastchar; j<=to; j++)
1973							{
1974								if (ignorecase)
1975								{
1976									SetBit(tmpclass,TOLOWER(j));
1977									SetBit(tmpclass,TOUPPER(j));
1978								}
1979								else
1980								{
1981									SetBit(tmpclass,j);
1982								}
1983
1984								classsize++;
1985							}
1986
1987							continue;
1988						}
1989					}
1990
1991					lastchar=src[i];
1992
1993					if (ignorecase)
1994					{
1995						SetBit(tmpclass,TOLOWER(lastchar));
1996						SetBit(tmpclass,TOUPPER(lastchar));
1997					}
1998					else
1999					{
2000						SetBit(tmpclass,lastchar);
2001					}
2002
2003					classsize++;
2004				}
2005
2006				if (negative && classsize>1)
2007				{
2008#ifdef UNICODE
2009					tmpclass->negative=negative;
2010#else
2011
2012					for (int jj=0; jj<8; jj++)itmpclass[jj]^=0xffffffff;
2013
2014#endif
2015					//for(int j=0;j<32;j++)op->symbolclass[j]^=0xff;
2016				}
2017
2018				if (classsize==1)
2019				{
2020#ifdef UNICODE
2021					delete op->symbolclass;
2022					op->symbolclass=0;
2023					tmpclass=0;
2024#endif
2025					op->op=negative?opNotSymbol:opSymbol;
2026
2027					if (ignorecase)
2028					{
2029						op->op+=2;
2030						op->symbol=TOLOWER(lastchar);
2031					}
2032					else
2033					{
2034						op->symbol=lastchar;
2035					}
2036				}
2037
2038#ifdef UNICODE
2039
2040				if (tmpclass)tmpclass->negative=negative;
2041
2042#else
2043				else if (classsize==256 && !negative)
2044				{
2045					op->op=options&OP_SINGLELINE?opCharAnyAll:opCharAny;
2046				}
2047				else
2048				{
2049#ifdef RE_NO_NEWARRAY
2050					op->symbolclass=static_cast<rechar*>(malloc(sizeof(rechar)*32));
2051#else
2052				op->symbolclass=new rechar[32];
2053#endif
2054
2055					for (j=0; j<8; j++)((int*)op->symbolclass)[j]=itmpclass[j];
2056				}
2057
2058#endif
2059				continue;
2060			}
2061			case '+':
2062			case '*':
2063			case '?':
2064			case '{':
2065			{
2066				int min=0,max=0;
2067
2068				switch (src[i])
2069				{
2070					case '+':min=1; max=-2; break;
2071					case '*':min=0; max=-2; break;
2072					case '?':
2073					{
2074						//if(src[i+1]=='?') return SetError(errInvalidQuantifiersCombination,i);
2075						min=0; max=1;
2076						break;
2077					}
2078					case '{':
2079					{
2080						i++;
2081						int save=i;
2082						min=GetNum(src,i);
2083						max=min;
2084
2085						if (min<0)return SetError(errInvalidRange,save);
2086
2087//            i++;
2088						if (src[i]==',')
2089						{
2090							if (src[i+1]=='}')
2091							{
2092								i++;
2093								max=-2;
2094							}
2095							else
2096							{
2097								i++;
2098								max=GetNum(src,i);
2099
2100//                i++;
2101								if (max<min)return SetError(errInvalidRange,save);
2102							}
2103						}
2104
2105						if (src[i]!='}')return SetError(errInvalidRange,save);
2106					}
2107				}
2108
2109				pos--;
2110				op=code+pos-1;
2111
2112				if (min==1 && max==1)continue;
2113
2114				op->range.min=min;
2115				op->range.max=max;
2116
2117				switch (op->op)
2118				{
2119					case opLineStart:
2120					case opLineEnd:
2121					case opDataStart:
2122					case opDataEnd:
2123					case opWordBound:
2124					case opNotWordBound:
2125					{
2126						return SetError(errInvalidQuantifiersCombination,i);
2127//            op->range.op=op->op;
2128//            op->op=opRange;
2129//            continue;
2130					}
2131					case opCharAny:
2132					case opCharAnyAll:
2133					{
2134						op->range.op=op->op;
2135						op->op=opAnyRange;
2136						break;
2137					}
2138					case opType:
2139					{
2140						op->op=opTypeRange;
2141						break;
2142					}
2143					case opNotType:
2144					{
2145						op->op=opNotTypeRange;
2146						break;
2147					}
2148					case opSymbolIgnoreCase:
2149					case opSymbol:
2150					{
2151						op->op=opSymbolRange;
2152						break;
2153					}
2154					case opNotSymbol:
2155					case opNotSymbolIgnoreCase:
2156					{
2157						op->op=opNotSymbolRange;
2158						break;
2159					}
2160					case opSymbolClass:
2161					{
2162						op->op=opClassRange;
2163						break;
2164					}
2165					case opBackRef:
2166					{
2167						op->op=opBackRefRange;
2168						break;
2169					}
2170#ifdef NAMEDBRACKETS
2171					case opNamedBackRef:
2172					{
2173						op->op=opNamedRefRange;
2174					} break;
2175#endif
2176					case opClosingBracket:
2177					{
2178						op=op->bracket.pairindex;
2179
2180						if (op->op!=opOpenBracket)return SetError(errInvalidQuantifiersCombination,i);
2181
2182						op->range.min=min;
2183						op->range.max=max;
2184						op->op=opBracketRange;
2185						break;
2186					}
2187					default:
2188					{
2189						dpf(("OP=%d\n",op->op));
2190						return SetError(errInvalidQuantifiersCombination,i);
2191					}
2192				}//switch(code.op)
2193
2194				if (src[i+1]=='?')
2195				{
2196					op->op++;
2197					i++;
2198				}
2199
2200				continue;
2201			}// case +*?{
2202			case ' ':
2203			case '\t':
2204			case '\n':
2205			case '\r':
2206			{
2207				if (options&OP_XTENDEDSYNTAX)
2208				{
2209					pos--;
2210					continue;
2211				}
2212			}
2213#ifdef RELIB
2214			case '%':
2215			{
2216				i++;
2217				int len=0;
2218
2219				while (src[i+len]!='%')len++;
2220
2221				op->op=opLibCall;
2222#ifdef RE_NO_NEWARRAY
2223				op->rename=static_cast<rechar*>(malloc(sizeof(rechar)*(len+1)));
2224#else
2225				op->rename=new rechar[len+1];
2226#endif
2227				memcpy(op->rename,src+i,len*sizeof(rechar));
2228				op->rename[len]=0;
2229				i+=len;
2230				continue;
2231			}
2232#endif
2233			default:
2234			{
2235				op->op=options&OP_IGNORECASE?opSymbolIgnoreCase:opSymbol;
2236
2237				if (ignorecase)
2238				{
2239					op->symbol=TOLOWER(src[i]);
2240				}
2241				else
2242				{
2243					op->symbol=src[i];
2244				}
2245			}
2246		}//switch(src[i])
2247	}//for()
2248
2249	op=code+pos;
2250	pos++;
2251	brdepth--;
2252
2253	while (brdepth>=0 && brackets[brdepth]->op==opAlternative)
2254	{
2255		brackets[brdepth]->alternative.endindex=op;
2256		brdepth--;
2257	}
2258
2259	op->op=opClosingBracket;
2260	op->bracket.pairindex=code;
2261	code->bracket.pairindex=op;
2262#ifdef RE_DEBUG
2263	op->srcpos=i;
2264#endif
2265	op=code+pos;
2266	//pos++;
2267	op->op=opRegExpEnd;
2268#ifdef RE_DEBUG
2269	op->srcpos=i+1;
2270#endif
2271	return 1;
2272}
2273
2274inline void RegExp::PushState()
2275{
2276	stackcount++;
2277#ifdef RELIB
2278	stackusage++;
2279#endif
2280
2281	if (stackcount==STACK_PAGE_SIZE)
2282	{
2283		if (lastpage->next)
2284		{
2285			lastpage=lastpage->next;
2286			stack=lastpage->stack;
2287		}
2288		else
2289		{
2290			lastpage->next=new StateStackPage;
2291			lastpage->next->prev=lastpage;
2292			lastpage=lastpage->next;
2293			lastpage->next=nullptr;
2294#ifdef RE_NO_NEWARRAY
2295			lastpage->stack=static_cast<StateStackItem*>
2296			                (CreateArray(sizeof(StateStackItem), STACK_PAGE_SIZE,
2297			                             StateStackItem::OnCreate));
2298#else
2299			lastpage->stack=new StateStackItem[STACK_PAGE_SIZE];
2300#endif // RE_NO_NEWARRAY
2301			stack=lastpage->stack;
2302		}
2303
2304		stackcount=0;
2305	}
2306
2307	st=&stack[stackcount];
2308}
2309inline int RegExp::PopState()
2310{
2311	stackcount--;
2312#ifdef RELIB
2313	stackusage--;
2314
2315	if (stackusage<0)return 0;
2316
2317#endif
2318
2319	if (stackcount<0)
2320	{
2321		if (!lastpage->prev)
2322			return 0;
2323
2324		lastpage=lastpage->prev;
2325		stack=lastpage->stack;
2326		stackcount=STACK_PAGE_SIZE-1;
2327	}
2328
2329	st=&stack[stackcount];
2330	return 1;
2331}
2332
2333
2334inline StateStackItem *RegExp::GetState()
2335{
2336	int tempcount=stackcount;
2337#ifdef RELIB
2338
2339	if (!stackusage)return 0;
2340
2341#endif
2342	StateStackPage* temppage=lastpage;
2343	StateStackItem* tempstack=lastpage->stack;
2344	tempcount--;
2345
2346	if (tempcount<0)
2347	{
2348		if (!temppage->prev)
2349			return 0;
2350
2351		temppage=temppage->prev;
2352		tempstack=temppage->stack;
2353		tempcount=STACK_PAGE_SIZE-1;
2354	}
2355
2356	return &tempstack[tempcount];
2357}
2358
2359inline StateStackItem *RegExp::FindStateByPos(PREOpCode pos,int op)
2360{
2361#ifdef RELIB
2362	int tempusage=stackusage;
2363#endif
2364	int tempcount=stackcount;
2365	StateStackPage* temppage=lastpage;
2366	StateStackItem* tempstack=lastpage->stack;
2367
2368	do
2369	{
2370		tempcount--;
2371#ifdef RELIB
2372		tempusage--;
2373
2374		if (tempusage<0)return 0;
2375
2376#endif
2377
2378		if (tempcount<0)
2379		{
2380			if (!temppage->prev)
2381				return 0;
2382
2383			temppage=temppage->prev;
2384			tempstack=temppage->stack;
2385			tempcount=STACK_PAGE_SIZE-1;
2386		}
2387	}
2388	while (tempstack[tempcount].pos!=pos || tempstack[tempcount].op!=op);
2389
2390	return &tempstack[tempcount];
2391}
2392
2393
2394inline int RegExp::StrCmp(const prechar& str,const prechar _st,const prechar ed)
2395{
2396	const prechar save=str;
2397
2398	if (ignorecase)
2399	{
2400		while (_st<ed)
2401		{
2402			if (TOLOWER(*str)!=TOLOWER(*_st)) {str=save; return 0;}
2403
2404			str++;
2405			_st++;
2406		}
2407	}
2408	else
2409	{
2410		while (_st<ed)
2411		{
2412			if (*str!=*_st) {str=save; return 0;}
2413
2414			str++;
2415			_st++;
2416		}
2417	}
2418
2419	return 1;
2420}
2421
2422#define OP (*op)
2423
2424
2425#define MINSKIP(cmp) \
2426	{ int jj; \
2427		switch(op->next->op) \
2428		{ \
2429			case opSymbol: \
2430			{ \
2431				jj=op->next->symbol; \
2432				if(*str!=jj) \
2433					while(str<strend && cmp && st->max--)\
2434					{\
2435						str++;\
2436						if(str[1]!=jj)break;\
2437					} \
2438				break; \
2439			} \
2440			case opNotSymbol: \
2441			{ \
2442				jj=op->next->symbol; \
2443				if(*str==jj) \
2444					while(str<strend && cmp && st->max--)\
2445					{\
2446						str++;\
2447						if(str[1]==jj)break;\
2448					} \
2449				break; \
2450			} \
2451			case opSymbolIgnoreCase: \
2452			{ \
2453				jj=op->next->symbol; \
2454				if(TOLOWER(*str)!=jj) \
2455					while(str<strend && cmp && st->max--)\
2456					{\
2457						str++;\
2458						if(TOLOWER(str[1])!=jj)break;\
2459					} \
2460				break; \
2461			} \
2462			case opNotSymbolIgnoreCase: \
2463			{ \
2464				jj=op->next->symbol; \
2465				if(TOLOWER(*str)==jj) \
2466					while(str<strend && cmp && st->max--)\
2467					{\
2468						str++;\
2469						if(TOLOWER(str[1])==jj)break;\
2470					} \
2471				break; \
2472			} \
2473			case opType: \
2474			{ \
2475				jj=op->next->type; \
2476				if(!(ISTYPE(*str,jj))) \
2477					while(str<strend && cmp && st->max--)\
2478					{\
2479						str++;\
2480						if(!(ISTYPE(str[1],jj)))break;\
2481					} \
2482				break; \
2483			} \
2484			case opNotType: \
2485			{ \
2486				jj=op->next->type; \
2487				if((ISTYPE(*str,jj))) \
2488					while(str<strend && cmp && st->max--)\
2489					{\
2490						str++;\
2491						if((ISTYPE(str[1],jj)))break;\
2492					} \
2493				break; \
2494			} \
2495			case opSymbolClass: \
2496			{ \
2497				cl=op->next->symbolclass; \
2498				if(!GetBit(cl,*str)) \
2499					while(str<strend && cmp && st->max--)\
2500					{\
2501						str++;\
2502						if(!GetBit(cl,str[1]))break;\
2503					} \
2504				break; \
2505			} \
2506		} \
2507	}
2508
2509#ifdef RELIB
2510static void KillMatchList(MatchList *ml)
2511{
2512	for (int i=0; i<ml->Count(); i++)
2513	{
2514		KillMatchList((*ml)[i].sublist);
2515		(*ml)[i].sublist=nullptr;
2516	}
2517
2518	ml->Clean();
2519}
2520
2521#endif
2522
2523
2524int RegExp::InnerMatch(const prechar str,const prechar strend,PMatch match,int& matchcount
2525#ifdef NAMEDBRACKETS
2526                       ,PMatchHash hmatch
2527#endif
2528                      )
2529{
2530//  register prechar str=start;
2531	int i,j;
2532	int minimizing;
2533	PREOpCode op,tmp=nullptr;
2534	PMatch m;
2535#ifdef UNICODE
2536	UniSet *cl;
2537#else
2538	prechar cl;
2539#endif
2540#ifdef RELIB
2541	SMatchListItem ml;
2542#endif
2543	int inrangebracket=0;
2544
2545	if (errorcode==errNotCompiled)return 0;
2546
2547	if (matchcount<maxbackref)return SetError(errNotEnoughMatches,maxbackref);
2548
2549#ifdef NAMEDBRACKETS
2550
2551	if (havenamedbrackets && !hmatch)return SetError(errNoStorageForNB,0);
2552
2553#endif
2554#ifdef RELIB
2555
2556	if (reclevel<=1)
2557	{
2558#endif
2559		stackcount=0;
2560		lastpage=firstpage;
2561		stack=lastpage->stack;
2562		st=&stack[0];
2563#ifdef RELIB
2564	}
2565
2566#endif
2567	StateStackItem *ps;
2568	errorcode=errNone;
2569
2570	/*for(i=0;i<matchcount;i++)
2571	{
2572	  match[i].start=-1;
2573	  match[i].end=-1;
2574	}*/
2575	if (bracketscount<matchcount)matchcount=bracketscount;
2576
2577	memset(match,-1,sizeof(*match)*matchcount);
2578
2579	for (op=code; op; op=op->next)
2580	{
2581		//dpf(("op:%s,\tpos:%d,\tstr:%d\n",ops[OP.op],pos,str-start));
2582		dpf(("=================\n"));
2583		dpf(("S:%s\n%*s\n",start,str-start+3,"^"));
2584		dpf(("R:%s\n%*s\n",resrc,OP.srcpos+3,"^"));
2585
2586		if (str<=strend)
2587			switch (OP.op)
2588			{
2589				case opLineStart:
2590				{
2591					if (str==start || str[-1]==0x0d || str[-1]==0x0a)continue;
2592
2593					break;
2594				}
2595				case opLineEnd:
2596				{
2597					if (str==strend)continue;
2598
2599					if (str[0]==0x0d || str[0]==0x0a)
2600					{
2601						if (str[0]==0x0d)str++;
2602
2603						if (str[0]==0x0a)str++;
2604
2605						continue;
2606					}
2607
2608					break;
2609				}
2610				case opDataStart:
2611				{
2612					if (str==start)continue;
2613
2614					break;
2615				}
2616				case opDataEnd:
2617				{
2618					if (str==strend)continue;
2619
2620					break;
2621				}
2622				case opWordBound:
2623				{
2624					if ((str==start && ISWORD(*str))||
2625					        (!(ISWORD(str[-1])) && ISWORD(*str)) ||
2626					        (!(ISWORD(*str)) && ISWORD(str[-1])) ||
2627					        (str==strend && ISWORD(str[-1])))continue;
2628
2629					break;
2630				}
2631				case opNotWordBound:
2632				{
2633					if (!((str==start && ISWORD(*str))||
2634					        (!(ISWORD(str[-1])) && ISWORD(*str)) ||
2635					        (!(ISWORD(*str)) && ISWORD(str[-1])) ||
2636					        (str==strend && ISWORD(str[-1]))))continue;
2637
2638					break;
2639				}
2640				case opType:
2641				{
2642					if (ISTYPE(*str,OP.type))
2643					{
2644						str++;
2645						continue;
2646					}
2647
2648					break;
2649				}
2650				case opNotType:
2651				{
2652					if (!(ISTYPE(*str,OP.type)))
2653					{
2654						str++;
2655						continue;
2656					}
2657
2658					break;
2659				}
2660				case opCharAny:
2661				{
2662					if (*str!=0x0d && *str!=0x0a)
2663					{
2664						str++;
2665						continue;
2666					}
2667
2668					break;
2669				}
2670				case opCharAnyAll:
2671				{
2672					str++;
2673					continue;
2674				}
2675				case opSymbol:
2676				{
2677					if (*str==OP.symbol)
2678					{
2679						str++;
2680						continue;
2681					}
2682
2683					break;
2684				}
2685				case opNotSymbol:
2686				{
2687					if (*str!=OP.symbol)
2688					{
2689						str++;
2690						continue;
2691					}
2692
2693					break;
2694				}
2695				case opSymbolIgnoreCase:
2696				{
2697					if (TOLOWER(*str)==OP.symbol)
2698					{
2699						str++;
2700						continue;
2701					}
2702
2703					break;
2704				}
2705				case opNotSymbolIgnoreCase:
2706				{
2707					if (TOLOWER(*str)!=OP.symbol)
2708					{
2709						str++;
2710						continue;
2711					}
2712
2713					break;
2714				}
2715				case opSymbolClass:
2716				{
2717					if (GetBit(OP.symbolclass,*str))
2718					{
2719						str++;
2720						continue;
2721					}
2722
2723					break;
2724				}
2725				case opOpenBracket:
2726				{
2727					if (OP.bracket.index>=0 && OP.bracket.index<matchcount)
2728					{
2729						//if (inrangebracket) Mantis#1388
2730						{
2731							st->op=opOpenBracket;
2732							st->pos=op;
2733							st->min=match[OP.bracket.index].start;
2734							st->max=match[OP.bracket.index].end;
2735							PushState();
2736						}
2737
2738						match[OP.bracket.index].start=(int)(str-start);
2739					}
2740
2741					if (OP.bracket.nextalt)
2742					{
2743						st->op=opAlternative;
2744						st->pos=OP.bracket.nextalt;
2745						st->savestr=str;
2746						PushState();
2747					}
2748
2749					continue;
2750				}
2751#ifdef NAMEDBRACKETS
2752				case opNamedBracket:
2753				{
2754					if (hmatch)
2755					{
2756						PMatch m2;
2757
2758						if (!hmatch->Exists((char*)OP.nbracket.name))
2759						{
2760							tag_Match sm;
2761							sm.start=-1;
2762							sm.end=-1;
2763							m2=hmatch->SetItem((char*)OP.nbracket.name,sm);
2764						}
2765						else
2766						{
2767							m2=hmatch->GetPtr((char*)OP.nbracket.name);
2768			

Large files files are truncated, but you can click here to view the full file