Fix the preprocessor compiling bug in interpretor/Makefile.
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / architecture / osclib / faust / src / lib / deelx.h
1 // deelx.h
2 //
3 // DEELX Regular Expression Engine (v1.2)
4 //
5 // Copyright 2006 (c) RegExLab.com
6 // All Rights Reserved.
7 //
8 // http://www.regexlab.com/deelx/
9 //
10 // Author: Ê·ÊÙΰ (sswater shi)
11 // sswater@gmail.com
12 //
13 // $Revision: 1.1.2.26 $
14 //
15
16 #ifndef __DEELX_REGEXP__H__
17 #define __DEELX_REGEXP__H__
18
19 #include <memory.h>
20 #include <ctype.h>
21 #include <limits.h>
22 #include <string.h>
23 #include <stdio.h>
24
25 //
26 // Data Reference
27 //
28 template <class ELT> class CBufferRefT
29 {
30 public:
31 CBufferRefT(const ELT * pcsz, int length);
32 CBufferRefT(const ELT * pcsz);
33
34 public:
35 int nCompare (const ELT * pcsz) const;
36 int nCompareNoCase(const ELT * pcsz) const;
37 int Compare (const ELT * pcsz) const;
38 int CompareNoCase(const ELT * pcsz) const;
39 int Compare (const CBufferRefT <ELT> &) const;
40 int CompareNoCase(const CBufferRefT <ELT> &) const;
41
42 ELT At (int nIndex, ELT def = 0) const;
43 ELT operator [] (int nIndex) const;
44
45 const ELT * GetBuffer() const;
46 int GetSize() const;
47
48 public:
49 virtual ~CBufferRefT();
50
51 // Content
52 protected:
53 const ELT * m_pRef;
54 int m_nSize;
55 };
56
57 //
58 // Implemenation
59 //
60 template <class ELT> CBufferRefT <ELT> :: CBufferRefT(const ELT * pcsz, int length)
61 {
62 m_pRef = pcsz;
63 m_nSize = length;
64 }
65
66 template <class ELT> CBufferRefT <ELT> :: CBufferRefT(const ELT * pcsz)
67 {
68 m_pRef = pcsz;
69 m_nSize = 0;
70
71 if(pcsz != 0) while(m_pRef[m_nSize] != 0) m_nSize ++;
72 }
73
74 template <class ELT> int CBufferRefT <ELT> :: nCompare(const ELT * pcsz) const
75 {
76 for(int i=0; i<m_nSize; i++)
77 {
78 if(m_pRef[i] != pcsz[i])
79 return m_pRef[i] - pcsz[i];
80 }
81
82 return 0;
83 }
84
85 template <class ELT> int CBufferRefT <ELT> :: nCompareNoCase(const ELT * pcsz) const
86 {
87 for(int i=0; i<m_nSize; i++)
88 {
89 if(m_pRef[i] != pcsz[i])
90 {
91 if(toupper((int)m_pRef[i]) != toupper((int)pcsz[i]))
92 return m_pRef[i] - pcsz[i];
93 }
94 }
95
96 return 0;
97 }
98
99 template <class ELT> inline int CBufferRefT <ELT> :: Compare(const ELT * pcsz) const
100 {
101 return nCompare(pcsz) ? 1 : (int)pcsz[m_nSize];
102 }
103
104 template <class ELT> inline int CBufferRefT <ELT> :: CompareNoCase(const ELT * pcsz) const
105 {
106 return nCompareNoCase(pcsz) ? 1 : (int)pcsz[m_nSize];
107 }
108
109 template <class ELT> inline int CBufferRefT <ELT> :: Compare(const CBufferRefT <ELT> & cref) const
110 {
111 return m_nSize == cref.m_nSize ? nCompare(cref.GetBuffer()) : 1;
112 }
113
114 template <class ELT> inline int CBufferRefT <ELT> :: CompareNoCase(const CBufferRefT <ELT> & cref) const
115 {
116 return m_nSize == cref.m_nSize ? nCompareNoCase(cref.GetBuffer()) : 1;
117 }
118
119 template <class ELT> inline ELT CBufferRefT <ELT> :: At(int nIndex, ELT def) const
120 {
121 return nIndex >= m_nSize ? def : m_pRef[nIndex];
122 }
123
124 template <class ELT> inline ELT CBufferRefT <ELT> :: operator [] (int nIndex) const
125 {
126 return nIndex >= m_nSize ? 0 : m_pRef[nIndex];
127 }
128
129 template <class ELT> const ELT * CBufferRefT <ELT> :: GetBuffer() const
130 {
131 static const ELT _def[] = {0}; return m_pRef ? m_pRef : _def;
132 }
133
134 template <class ELT> inline int CBufferRefT <ELT> :: GetSize() const
135 {
136 return m_nSize;
137 }
138
139 template <class ELT> CBufferRefT <ELT> :: ~CBufferRefT()
140 {
141 }
142
143 //
144 // Data Buffer
145 //
146 template <class ELT> class CBufferT : public CBufferRefT <ELT>
147 {
148 public:
149 CBufferT(const ELT * pcsz, int length);
150 CBufferT(const ELT * pcsz);
151 CBufferT();
152
153 public:
154 ELT & operator [] (int nIndex);
155 const ELT & operator [] (int nIndex) const;
156 void Append(const ELT * pcsz, int length, int eol = 0);
157 void Append(ELT el, int eol = 0);
158
159 public:
160 void Push(ELT el);
161 int Pop (ELT & el);
162 int Peek(ELT & el) const;
163
164 public:
165 const ELT * GetBuffer() const;
166 ELT * GetBuffer();
167 ELT * Detach();
168 void Release();
169 void Prepare(int index, int fill = 0);
170 void Restore(int size);
171
172 public:
173 virtual ~CBufferT();
174
175 // Content
176 protected:
177 ELT * m_pBuffer;
178 int m_nMaxLength;
179 };
180
181 //
182 // Implemenation
183 //
184 template <class ELT> CBufferT <ELT> :: CBufferT(const ELT * pcsz, int length) : CBufferRefT <ELT> (0, length)
185 {
186 m_nMaxLength = CBufferRefT <ELT> :: m_nSize + 1;
187
188 CBufferRefT <ELT> :: m_pRef = m_pBuffer = new ELT[m_nMaxLength];
189 memcpy(m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT <ELT> :: m_nSize);
190 m_pBuffer[CBufferRefT <ELT> :: m_nSize] = 0;
191 }
192
193 template <class ELT> CBufferT <ELT> :: CBufferT(const ELT * pcsz) : CBufferRefT <ELT> (pcsz)
194 {
195 m_nMaxLength = CBufferRefT <ELT> :: m_nSize + 1;
196
197 CBufferRefT <ELT> :: m_pRef = m_pBuffer = new ELT[m_nMaxLength];
198 memcpy(m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT <ELT> :: m_nSize);
199 m_pBuffer[CBufferRefT <ELT> :: m_nSize] = 0;
200 }
201
202 template <class ELT> CBufferT <ELT> :: CBufferT() : CBufferRefT <ELT> (0, 0)
203 {
204 m_nMaxLength = 0;
205 m_pBuffer = 0;
206 }
207
208 template <class ELT> inline ELT & CBufferT <ELT> :: operator [] (int nIndex)
209 {
210 return m_pBuffer[nIndex];
211 }
212
213 template <class ELT> inline const ELT & CBufferT <ELT> :: operator [] (int nIndex) const
214 {
215 return m_pBuffer[nIndex];
216 }
217
218 template <class ELT> void CBufferT <ELT> :: Append(const ELT * pcsz, int length, int eol)
219 {
220 int nNewLength = m_nMaxLength;
221
222 // Check length
223 if(nNewLength < 8)
224 nNewLength = 8;
225
226 if(CBufferRefT <ELT> :: m_nSize + length + eol > nNewLength)
227 nNewLength *= 2;
228
229 if(CBufferRefT <ELT> :: m_nSize + length + eol > nNewLength)
230 {
231 nNewLength = CBufferRefT <ELT> :: m_nSize + length + eol + 11;
232 nNewLength -= nNewLength % 8;
233 }
234
235 // Realloc
236 if(nNewLength > m_nMaxLength)
237 {
238 ELT * pNewBuffer = new ELT[nNewLength];
239
240 if(m_pBuffer != 0)
241 {
242 memcpy(pNewBuffer, m_pBuffer, sizeof(ELT) * CBufferRefT <ELT> :: m_nSize);
243 delete [] m_pBuffer;
244 }
245
246 CBufferRefT <ELT> :: m_pRef = m_pBuffer = pNewBuffer;
247 m_nMaxLength = nNewLength;
248 }
249
250 // Append
251 memcpy(m_pBuffer + CBufferRefT <ELT> :: m_nSize, pcsz, sizeof(ELT) * length);
252 CBufferRefT <ELT> :: m_nSize += length;
253
254 if(eol > 0) m_pBuffer[CBufferRefT <ELT> :: m_nSize] = 0;
255 }
256
257 template <class ELT> inline void CBufferT <ELT> :: Append(ELT el, int eol)
258 {
259 Append(&el, 1, eol);
260 }
261
262 template <class ELT> void CBufferT <ELT> :: Push(ELT el)
263 {
264 // Realloc
265 if(CBufferRefT <ELT> :: m_nSize >= m_nMaxLength)
266 {
267 int nNewLength = m_nMaxLength * 2;
268 if( nNewLength < 8 ) nNewLength = 8;
269
270 ELT * pNewBuffer = new ELT[nNewLength];
271
272 if(m_pBuffer != 0)
273 {
274 memcpy(pNewBuffer, m_pBuffer, sizeof(ELT) * CBufferRefT <ELT> :: m_nSize);
275 delete [] m_pBuffer;
276 }
277
278 CBufferRefT <ELT> :: m_pRef = m_pBuffer = pNewBuffer;
279 m_nMaxLength = nNewLength;
280 }
281
282 // Append
283 m_pBuffer[CBufferRefT <ELT> :: m_nSize++] = el;
284 }
285
286 template <class ELT> inline int CBufferT <ELT> :: Pop(ELT & el)
287 {
288 if(CBufferRefT <ELT> :: m_nSize > 0)
289 {
290 el = m_pBuffer[--CBufferRefT <ELT> :: m_nSize];
291 return 1;
292 }
293 else
294 {
295 return 0;
296 }
297 }
298
299 template <class ELT> inline int CBufferT <ELT> :: Peek(ELT & el) const
300 {
301 if(CBufferRefT <ELT> :: m_nSize > 0)
302 {
303 el = m_pBuffer[CBufferRefT <ELT> :: m_nSize - 1];
304 return 1;
305 }
306 else
307 {
308 return 0;
309 }
310 }
311
312 template <class ELT> const ELT * CBufferT <ELT> :: GetBuffer() const
313 {
314 static const ELT _def[] = {0}; return m_pBuffer ? m_pBuffer : _def;
315 }
316
317 template <class ELT> ELT * CBufferT <ELT> :: GetBuffer()
318 {
319 static const ELT _def[] = {0}; return m_pBuffer ? m_pBuffer : (ELT *)_def;
320 }
321
322 template <class ELT> ELT * CBufferT <ELT> :: Detach()
323 {
324 ELT * pBuffer = m_pBuffer;
325
326 CBufferRefT <ELT> :: m_pRef = m_pBuffer = 0;
327 CBufferRefT <ELT> :: m_nSize = m_nMaxLength = 0;
328
329 return pBuffer;
330 }
331
332 template <class ELT> void CBufferT <ELT> :: Release()
333 {
334 ELT * pBuffer = Detach();
335
336 if(pBuffer != 0) delete [] pBuffer;
337 }
338
339 template <class ELT> void CBufferT <ELT> :: Prepare(int index, int fill)
340 {
341 int nNewSize = index + 1;
342
343 // Realloc
344 if(nNewSize > m_nMaxLength)
345 {
346 int nNewLength = m_nMaxLength;
347
348 if( nNewLength < 8 )
349 nNewLength = 8;
350
351 if( nNewSize > nNewLength )
352 nNewLength *= 2;
353
354 if( nNewSize > nNewLength )
355 {
356 nNewLength = nNewSize + 11;
357 nNewLength -= nNewLength % 8;
358 }
359
360 ELT * pNewBuffer = new ELT[nNewLength];
361
362 if(m_pBuffer != 0)
363 {
364 memcpy(pNewBuffer, m_pBuffer, sizeof(ELT) * CBufferRefT <ELT> :: m_nSize);
365 delete [] m_pBuffer;
366 }
367
368 CBufferRefT <ELT> :: m_pRef = m_pBuffer = pNewBuffer;
369 m_nMaxLength = nNewLength;
370 }
371
372 // size
373 if( CBufferRefT <ELT> :: m_nSize < nNewSize )
374 {
375 memset(m_pBuffer + CBufferRefT <ELT> :: m_nSize, fill, sizeof(ELT) * (nNewSize - CBufferRefT <ELT> :: m_nSize));
376 CBufferRefT <ELT> :: m_nSize = nNewSize;
377 }
378 }
379
380 template <class ELT> inline void CBufferT <ELT> :: Restore(int size)
381 {
382 CBufferRefT <ELT> :: m_nSize = size;
383 }
384
385 template <class ELT> CBufferT <ELT> :: ~CBufferT()
386 {
387 if(m_pBuffer != 0) delete [] m_pBuffer;
388 }
389
390 //
391 // Context
392 //
393 class CContext
394 {
395 public:
396 CBufferT <int> m_stack;
397 CBufferT <int> m_capturestack, m_captureindex;
398
399 public:
400 int m_nCurrentPos;
401 int m_nBeginPos;
402 int m_nLastBeginPos;
403 int m_nParenZindex;
404
405 void * m_pMatchString;
406 int m_pMatchStringLength;
407 };
408
409 //
410 // Interface
411 //
412 class ElxInterface
413 {
414 public:
415 virtual int Match (CContext * pContext) const = 0;
416 virtual int MatchNext(CContext * pContext) const = 0;
417
418 public:
419 virtual ~ElxInterface() {};
420 };
421
422 //
423 // Alternative
424 //
425 template <int x> class CAlternativeElxT : public ElxInterface
426 {
427 public:
428 int Match (CContext * pContext) const;
429 int MatchNext(CContext * pContext) const;
430
431 public:
432 CAlternativeElxT();
433
434 public:
435 CBufferT <ElxInterface *> m_elxlist;
436 };
437
438 typedef CAlternativeElxT <0> CAlternativeElx;
439
440 //
441 // Assert
442 //
443 template <int x> class CAssertElxT : public ElxInterface
444 {
445 public:
446 int Match (CContext * pContext) const;
447 int MatchNext(CContext * pContext) const;
448
449 public:
450 CAssertElxT(ElxInterface * pelx, int byes = 1);
451
452 public:
453 ElxInterface * m_pelx;
454 int m_byes;
455 };
456
457 typedef CAssertElxT <0> CAssertElx;
458
459 //
460 // Back reference elx
461 //
462 template <class CHART> class CBackrefElxT : public ElxInterface
463 {
464 public:
465 int Match (CContext * pContext) const;
466 int MatchNext(CContext * pContext) const;
467
468 public:
469 CBackrefElxT(int nnumber, int brightleft, int bignorecase);
470
471 public:
472 int m_nnumber;
473 int m_brightleft;
474 int m_bignorecase;
475
476 CBufferT <CHART> m_szNamed;
477 };
478
479 //
480 // Implementation
481 //
482 template <class CHART> CBackrefElxT <CHART> :: CBackrefElxT(int nnumber, int brightleft, int bignorecase)
483 {
484 m_nnumber = nnumber;
485 m_brightleft = brightleft;
486 m_bignorecase = bignorecase;
487 }
488
489 template <class CHART> int CBackrefElxT <CHART> :: Match(CContext * pContext) const
490 {
491 // check number, for named
492 if( m_nnumber < 0 || m_nnumber >= pContext->m_captureindex.GetSize() ) return 0;
493
494 int index = pContext->m_captureindex[m_nnumber];
495 if( index < 0 ) return 0;
496
497 // check enclosed
498 int pos1 = pContext->m_capturestack[index + 1];
499 int pos2 = pContext->m_capturestack[index + 2];
500
501 if( pos2 < 0 ) pos2 = pContext->m_nCurrentPos;
502
503 // info
504 int lpos = pos1 < pos2 ? pos1 : pos2;
505 int rpos = pos1 < pos2 ? pos2 : pos1;
506 int slen = rpos - lpos;
507
508 const CHART * pcsz = (const CHART *)pContext->m_pMatchString;
509 int npos = pContext->m_nCurrentPos;
510 int tlen = pContext->m_pMatchStringLength;
511
512 // compare
513 int bsucc;
514 CBufferRefT <CHART> refstr(pcsz + lpos, slen);
515
516 if( m_brightleft )
517 {
518 if(npos < slen)
519 return 0;
520
521 if(m_bignorecase)
522 bsucc = ! refstr.nCompareNoCase(pcsz + (npos - slen));
523 else
524 bsucc = ! refstr.nCompare (pcsz + (npos - slen));
525
526 if( bsucc )
527 {
528 pContext->m_stack.Push(npos);
529 pContext->m_nCurrentPos -= slen;
530 }
531 }
532 else
533 {
534 if(npos + slen > tlen)
535 return 0;
536
537 if(m_bignorecase)
538 bsucc = ! refstr.nCompareNoCase(pcsz + npos);
539 else
540 bsucc = ! refstr.nCompare (pcsz + npos);
541
542 if( bsucc )
543 {
544 pContext->m_stack.Push(npos);
545 pContext->m_nCurrentPos += slen;
546 }
547 }
548
549 return bsucc;
550 }
551
552 template <class CHART> int CBackrefElxT <CHART> :: MatchNext(CContext * pContext) const
553 {
554 int npos = 0;
555
556 pContext->m_stack.Pop(npos);
557 pContext->m_nCurrentPos = npos;
558
559 return 0;
560 }
561
562 // RCHART
563 #ifndef RCHART
564 #define RCHART(ch) ((CHART)ch)
565 #endif
566
567 // BOUNDARY_TYPE
568 enum BOUNDARY_TYPE
569 {
570 BOUNDARY_FILE_BEGIN, // begin of whole text
571 BOUNDARY_FILE_END , // end of whole text
572 BOUNDARY_LINE_BEGIN, // begin of line
573 BOUNDARY_LINE_END , // end of line
574 BOUNDARY_WORD_BEGIN, // begin of word
575 BOUNDARY_WORD_END , // end of word
576 BOUNDARY_WORD_EDGE ,
577 };
578
579 //
580 // Boundary Elx
581 //
582 template <class CHART> class CBoundaryElxT : public ElxInterface
583 {
584 public:
585 int Match (CContext * pContext) const;
586 int MatchNext(CContext * pContext) const;
587
588 public:
589 CBoundaryElxT(int ntype, int byes = 1);
590
591 protected:
592 static int IsWordChar(CHART ch);
593
594 public:
595 int m_ntype;
596 int m_byes;
597 };
598
599 //
600 // Implementation
601 //
602 template <class CHART> CBoundaryElxT <CHART> :: CBoundaryElxT(int ntype, int byes)
603 {
604 m_ntype = ntype;
605 m_byes = byes;
606 }
607
608 template <class CHART> int CBoundaryElxT <CHART> :: Match(CContext * pContext) const
609 {
610 const CHART * pcsz = (const CHART *)pContext->m_pMatchString;
611 int npos = pContext->m_nCurrentPos;
612 int tlen = pContext->m_pMatchStringLength;
613
614 CHART chL = npos > 0 ? pcsz[npos - 1] : 0;
615 CHART chR = npos < tlen ? pcsz[npos ] : 0;
616
617 int bsucc = 0;
618
619 switch(m_ntype)
620 {
621 case BOUNDARY_FILE_BEGIN:
622 bsucc = (npos <= 0);
623 break;
624
625 case BOUNDARY_FILE_END:
626 bsucc = (npos >= tlen);
627 break;
628
629 case BOUNDARY_LINE_BEGIN:
630 bsucc = (npos <= 0 ) || (chL == RCHART('\n')) || ((chL == RCHART('\r')) && (chR != RCHART('\n')));
631 break;
632
633 case BOUNDARY_LINE_END:
634 bsucc = (npos >= tlen) || (chR == RCHART('\r')) || ((chR == RCHART('\n')) && (chL != RCHART('\r')));
635 break;
636
637 case BOUNDARY_WORD_BEGIN:
638 bsucc = ! IsWordChar(chL) && IsWordChar(chR);
639 break;
640
641 case BOUNDARY_WORD_END:
642 bsucc = IsWordChar(chL) && ! IsWordChar(chR);
643 break;
644
645 case BOUNDARY_WORD_EDGE:
646 bsucc = IsWordChar(chL) ? ! IsWordChar(chR) : IsWordChar(chR);
647 break;
648 }
649
650 return bsucc;
651 }
652
653 template <class CHART> int CBoundaryElxT <CHART> :: MatchNext(CContext *) const
654 {
655 return 0;
656 }
657
658 template <class CHART> inline int CBoundaryElxT <CHART> :: IsWordChar(CHART ch)
659 {
660 return (ch >= RCHART('A') && ch <= RCHART('Z')) || (ch >= RCHART('a') && ch <= RCHART('z')) || (ch >= RCHART('0') && ch <= RCHART('9')) || (ch == RCHART('_'));
661 }
662
663 //
664 // Bracket
665 //
666 template <class CHART> class CBracketElxT : public ElxInterface
667 {
668 public:
669 int Match (CContext * pContext) const;
670 int MatchNext(CContext * pContext) const;
671
672 public:
673 CBracketElxT(int nnumber, int bright);
674
675 public:
676 int m_nnumber;
677 int m_bright;
678
679 CBufferT <CHART> m_szNamed;
680 };
681
682 template <class CHART> CBracketElxT <CHART> :: CBracketElxT(int nnumber, int bright)
683 {
684 m_nnumber = nnumber;
685 m_bright = bright;
686 }
687
688 template <class CHART> int CBracketElxT <CHART> :: Match(CContext * pContext) const
689 {
690 // check, for named
691 if(m_nnumber < 0) return 0;
692
693 if( ! m_bright )
694 {
695 pContext->m_captureindex.Prepare(m_nnumber, -1);
696 int index = pContext->m_captureindex[m_nnumber];
697
698 // check
699 if(index > 0 && index < pContext->m_capturestack.GetSize() && pContext->m_capturestack[index+2] < 0)
700 {
701 pContext->m_capturestack[index+3] --;
702 return 1;
703 }
704
705 // save
706 pContext->m_captureindex[m_nnumber] = pContext->m_capturestack.GetSize();
707
708 pContext->m_capturestack.Push(m_nnumber);
709 pContext->m_capturestack.Push(pContext->m_nCurrentPos);
710 pContext->m_capturestack.Push(-1);
711 pContext->m_capturestack.Push( 0); // z-index
712 }
713 else
714 {
715 // check
716 int index = pContext->m_captureindex[m_nnumber];
717
718 if(pContext->m_capturestack[index + 3] < 0)
719 {
720 pContext->m_capturestack[index + 3] ++;
721 return 1;
722 }
723
724 // save
725 pContext->m_capturestack[index + 2] = pContext->m_nCurrentPos;
726 pContext->m_capturestack[index + 3] = pContext->m_nParenZindex ++;
727 }
728
729 return 1;
730 }
731
732 template <class CHART> int CBracketElxT <CHART> :: MatchNext(CContext * pContext) const
733 {
734 int index = pContext->m_captureindex[m_nnumber];
735
736 if( ! m_bright )
737 {
738 if(pContext->m_capturestack[index + 3] < 0)
739 {
740 pContext->m_capturestack[index + 3] ++;
741 return 0;
742 }
743
744 pContext->m_capturestack.Restore(pContext->m_capturestack.GetSize() - 4);
745
746 // to find
747 index = pContext->m_capturestack.GetSize() - 4;
748 while(index >= 0 && pContext->m_capturestack[index] != m_nnumber) index -= 4;
749
750 // new index
751 pContext->m_captureindex[m_nnumber] = index;
752 }
753 else
754 {
755 if(pContext->m_capturestack[index + 3] < 0)
756 {
757 pContext->m_capturestack[index + 3] --;
758 return 0;
759 }
760
761 pContext->m_capturestack[index + 2] = -1;
762 pContext->m_capturestack[index + 3] = 0;
763 }
764
765 return 0;
766 }
767
768 //
769 // Deletage
770 //
771 template <class CHART> class CDelegateElxT : public ElxInterface
772 {
773 public:
774 int Match (CContext * pContext) const;
775 int MatchNext(CContext * pContext) const;
776
777 public:
778 CDelegateElxT(int ndata = 0);
779
780 public:
781 ElxInterface * m_pelx;
782 int m_ndata; // +0 : recursive to
783 // -3 : named recursive
784
785 CBufferT <CHART> m_szNamed;
786 };
787
788 template <class CHART> CDelegateElxT <CHART> :: CDelegateElxT(int ndata)
789 {
790 m_pelx = 0;
791 m_ndata = ndata;
792 }
793
794 template <class CHART> int CDelegateElxT <CHART> :: Match(CContext * pContext) const
795 {
796 if(m_pelx != 0)
797 return m_pelx->Match(pContext);
798 else
799 return 1;
800 }
801
802 template <class CHART> int CDelegateElxT <CHART> :: MatchNext(CContext * pContext) const
803 {
804 if(m_pelx != 0)
805 return m_pelx->MatchNext(pContext);
806 else
807 return 0;
808 }
809
810 //
811 // Empty
812 //
813 template <int x> class CEmptyElxT : public ElxInterface
814 {
815 public:
816 int Match (CContext * pContext) const;
817 int MatchNext(CContext * pContext) const;
818
819 public:
820 CEmptyElxT();
821 };
822
823 typedef CEmptyElxT <0> CEmptyElx;
824
825 //
826 // Global
827 //
828 template <int x> class CGlobalElxT : public ElxInterface
829 {
830 public:
831 int Match (CContext * pContext) const;
832 int MatchNext(CContext * pContext) const;
833
834 public:
835 CGlobalElxT();
836 };
837
838 typedef CGlobalElxT <0> CGlobalElx;
839
840 //
841 // Repeat
842 //
843 template <int x> class CRepeatElxT : public ElxInterface
844 {
845 public:
846 int Match (CContext * pContext) const;
847 int MatchNext(CContext * pContext) const;
848
849 public:
850 CRepeatElxT(ElxInterface * pelx, int ntimes);
851
852 protected:
853 int MatchFixed (CContext * pContext) const;
854 int MatchNextFixed(CContext * pContext) const;
855
856 public:
857 ElxInterface * m_pelx;
858 int m_nfixed;
859 };
860
861 typedef CRepeatElxT <0> CRepeatElx;
862
863 //
864 // Greedy
865 //
866 template <int x> class CGreedyElxT : public CRepeatElxT <x>
867 {
868 public:
869 int Match (CContext * pContext) const;
870 int MatchNext(CContext * pContext) const;
871
872 public:
873 CGreedyElxT(ElxInterface * pelx, int nmin = 0, int nmax = INT_MAX);
874
875 protected:
876 int MatchVart (CContext * pContext) const;
877 int MatchNextVart(CContext * pContext) const;
878
879 public:
880 int m_nvart;
881 };
882
883 typedef CGreedyElxT <0> CGreedyElx;
884
885 //
886 // Independent
887 //
888 template <int x> class CIndependentElxT : public ElxInterface
889 {
890 public:
891 int Match (CContext * pContext) const;
892 int MatchNext(CContext * pContext) const;
893
894 public:
895 CIndependentElxT(ElxInterface * pelx);
896
897 public:
898 ElxInterface * m_pelx;
899 };
900
901 typedef CIndependentElxT <0> CIndependentElx;
902
903 //
904 // List
905 //
906 template <int x> class CListElxT : public ElxInterface
907 {
908 public:
909 int Match (CContext * pContext) const;
910 int MatchNext(CContext * pContext) const;
911
912 public:
913 CListElxT(int brightleft);
914
915 public:
916 CBufferT <ElxInterface *> m_elxlist;
917 int m_brightleft;
918 };
919
920 typedef CListElxT <0> CListElx;
921
922 //
923 // Posix Elx
924 //
925 template <class CHART> class CPosixElxT : public ElxInterface
926 {
927 public:
928 int Match (CContext * pContext) const;
929 int MatchNext(CContext * pContext) const;
930
931 public:
932 CPosixElxT(const char * posix, int brightleft);
933
934 protected:
935 static int misblank(int c);
936
937 public:
938 int (*m_posixfun)(int);
939 int m_brightleft;
940 int m_byes;
941 };
942
943 //
944 // Implementation
945 //
946 template <class CHART> CPosixElxT <CHART> :: CPosixElxT(const char * posix, int brightleft)
947 {
948 m_brightleft = brightleft;
949
950 if(posix[1] == '^')
951 {
952 m_byes = 0;
953 posix += 2;
954 }
955 else
956 {
957 m_byes = 1;
958 posix += 1;
959 }
960
961 if (!strncmp(posix, "alnum:", 6)) m_posixfun = isalnum ;
962 else if(!strncmp(posix, "alpha:", 6)) m_posixfun = isalpha ;
963 else if(!strncmp(posix, "ascii:", 6)) m_posixfun = isascii ;
964 else if(!strncmp(posix, "cntrl:", 6)) m_posixfun = iscntrl ;
965 else if(!strncmp(posix, "digit:", 6)) m_posixfun = isdigit ;
966 else if(!strncmp(posix, "graph:", 6)) m_posixfun = isgraph ;
967 else if(!strncmp(posix, "lower:", 6)) m_posixfun = islower ;
968 else if(!strncmp(posix, "print:", 6)) m_posixfun = isprint ;
969 else if(!strncmp(posix, "punct:", 6)) m_posixfun = ispunct ;
970 else if(!strncmp(posix, "space:", 6)) m_posixfun = isspace ;
971 else if(!strncmp(posix, "upper:", 6)) m_posixfun = isupper ;
972 else if(!strncmp(posix, "xdigit:",7)) m_posixfun = isxdigit;
973 else if(!strncmp(posix, "blank:", 6)) m_posixfun = misblank;
974 else m_posixfun = 0 ;
975 }
976
977 template <class CHART> int CPosixElxT <CHART> :: misblank(int c)
978 {
979 return c == 0x20 || c == '\t';
980 }
981
982 template <class CHART> int CPosixElxT <CHART> :: Match(CContext * pContext) const
983 {
984 if(m_posixfun == 0) return 0;
985
986 int tlen = pContext->m_pMatchStringLength;
987 int npos = pContext->m_nCurrentPos;
988
989 // check
990 int at = m_brightleft ? npos - 1 : npos;
991 if( at < 0 || at >= tlen )
992 return 0;
993
994 CHART ch = ((const CHART *)pContext->m_pMatchString)[at];
995
996 int bsucc = (*m_posixfun)(ch);
997
998 if( ! m_byes )
999 bsucc = ! bsucc;
1000
1001 if( bsucc )
1002 pContext->m_nCurrentPos += m_brightleft ? -1 : 1;
1003
1004 return bsucc;
1005 }
1006
1007 template <class CHART> int CPosixElxT <CHART> :: MatchNext(CContext * pContext) const
1008 {
1009 pContext->m_nCurrentPos -= m_brightleft ? -1 : 1;
1010 return 0;
1011 }
1012
1013 //
1014 // Possessive
1015 //
1016 template <int x> class CPossessiveElxT : public CGreedyElxT <x>
1017 {
1018 public:
1019 int Match (CContext * pContext) const;
1020 int MatchNext(CContext * pContext) const;
1021
1022 public:
1023 CPossessiveElxT(ElxInterface * pelx, int nmin = 0, int nmax = INT_MAX);
1024 };
1025
1026 typedef CPossessiveElxT <0> CPossessiveElx;
1027
1028 //
1029 // Range Elx
1030 //
1031 template <class CHART> class CRangeElxT : public ElxInterface
1032 {
1033 public:
1034 int Match (CContext * pContext) const;
1035 int MatchNext(CContext * pContext) const;
1036
1037 public:
1038 CRangeElxT(int brightleft, int byes);
1039
1040 public:
1041 CBufferT <CHART> m_ranges;
1042 CBufferT <CHART> m_chars;
1043 CBufferT <ElxInterface *> m_embeds;
1044
1045 public:
1046 int m_brightleft;
1047 int m_byes;
1048 };
1049
1050 //
1051 // Implementation
1052 //
1053 template <class CHART> CRangeElxT <CHART> :: CRangeElxT(int brightleft, int byes)
1054 {
1055 m_brightleft = brightleft;
1056 m_byes = byes;
1057 }
1058
1059 template <class CHART> int CRangeElxT <CHART> :: Match(CContext * pContext) const
1060 {
1061 int tlen = pContext->m_pMatchStringLength;
1062 int npos = pContext->m_nCurrentPos;
1063
1064 // check
1065 int at = m_brightleft ? npos - 1 : npos;
1066 if( at < 0 || at >= tlen )
1067 return 0;
1068
1069 CHART ch = ((const CHART *)pContext->m_pMatchString)[at];
1070 int bsucc = 0, i;
1071
1072 // compare
1073 for(i=0; !bsucc && i<m_ranges.GetSize(); i+=2)
1074 {
1075 if(m_ranges[i] <= ch && ch <= m_ranges[i+1]) bsucc = 1;
1076 }
1077
1078 for(i=0; !bsucc && i<m_chars.GetSize(); i++)
1079 {
1080 if(m_chars[i] == ch) bsucc = 1;
1081 }
1082
1083 for(i=0; !bsucc && i<m_embeds.GetSize(); i++)
1084 {
1085 if(m_embeds[i]->Match(pContext))
1086 {
1087 pContext->m_nCurrentPos = npos;
1088 bsucc = 1;
1089 }
1090 }
1091
1092 if( ! m_byes )
1093 bsucc = ! bsucc;
1094
1095 if( bsucc )
1096 pContext->m_nCurrentPos += m_brightleft ? -1 : 1;
1097
1098 return bsucc;
1099 }
1100
1101 template <class CHART> int CRangeElxT <CHART> :: MatchNext(CContext * pContext) const
1102 {
1103 pContext->m_nCurrentPos -= m_brightleft ? -1 : 1;
1104 return 0;
1105 }
1106
1107 //
1108 // Reluctant
1109 //
1110 template <int x> class CReluctantElxT : public CRepeatElxT <x>
1111 {
1112 public:
1113 int Match (CContext * pContext) const;
1114 int MatchNext(CContext * pContext) const;
1115
1116 public:
1117 CReluctantElxT(ElxInterface * pelx, int nmin = 0, int nmax = INT_MAX);
1118
1119 protected:
1120 int MatchVart (CContext * pContext) const;
1121 int MatchNextVart(CContext * pContext) const;
1122
1123 public:
1124 int m_nvart;
1125 };
1126
1127 typedef CReluctantElxT <0> CReluctantElx;
1128
1129 //
1130 // String Elx
1131 //
1132 template <class CHART> class CStringElxT : public ElxInterface
1133 {
1134 public:
1135 int Match (CContext * pContext) const;
1136 int MatchNext(CContext * pContext) const;
1137
1138 public:
1139 CStringElxT(const CHART * fixed, int nlength, int brightleft, int bignorecase);
1140
1141 public:
1142 CBufferT <CHART> m_szPattern;
1143 int m_brightleft;
1144 int m_bignorecase;
1145 };
1146
1147 //
1148 // Implementation
1149 //
1150 template <class CHART> CStringElxT <CHART> :: CStringElxT(const CHART * fixed, int nlength, int brightleft, int bignorecase) : m_szPattern(fixed, nlength)
1151 {
1152 m_brightleft = brightleft;
1153 m_bignorecase = bignorecase;
1154 }
1155
1156 template <class CHART> int CStringElxT <CHART> :: Match(CContext * pContext) const
1157 {
1158 const CHART * pcsz = (const CHART *)pContext->m_pMatchString;
1159 int npos = pContext->m_nCurrentPos;
1160 int tlen = pContext->m_pMatchStringLength;
1161 int slen = m_szPattern.GetSize();
1162
1163 int bsucc;
1164
1165 if(m_brightleft)
1166 {
1167 if(npos < slen)
1168 return 0;
1169
1170 if(m_bignorecase)
1171 bsucc = ! m_szPattern.nCompareNoCase(pcsz + (npos - slen));
1172 else
1173 bsucc = ! m_szPattern.nCompare (pcsz + (npos - slen));
1174
1175 if( bsucc )
1176 pContext->m_nCurrentPos -= slen;
1177 }
1178 else
1179 {
1180 if(npos + slen > tlen)
1181 return 0;
1182
1183 if(m_bignorecase)
1184 bsucc = ! m_szPattern.nCompareNoCase(pcsz + npos);
1185 else
1186 bsucc = ! m_szPattern.nCompare (pcsz + npos);
1187
1188 if( bsucc )
1189 pContext->m_nCurrentPos += slen;
1190 }
1191
1192 return bsucc;
1193 }
1194
1195 template <class CHART> int CStringElxT <CHART> :: MatchNext(CContext * pContext) const
1196 {
1197 int slen = m_szPattern.GetSize();
1198
1199 if(m_brightleft)
1200 pContext->m_nCurrentPos += slen;
1201 else
1202 pContext->m_nCurrentPos -= slen;
1203
1204 return 0;
1205 }
1206
1207 //
1208 // CConditionElx
1209 //
1210 template <class CHART> class CConditionElxT : public ElxInterface
1211 {
1212 public:
1213 int Match (CContext * pContext) const;
1214 int MatchNext(CContext * pContext) const;
1215
1216 public:
1217 CConditionElxT();
1218
1219 public:
1220 // backref condition
1221 int m_nnumber;
1222 CBufferT <CHART> m_szNamed;
1223
1224 // elx condition
1225 ElxInterface * m_pelxask;
1226
1227 // selection
1228 ElxInterface * m_pelxyes, * m_pelxno;
1229 };
1230
1231 template <class CHART> CConditionElxT <CHART> :: CConditionElxT()
1232 {
1233 m_nnumber = -1;
1234 }
1235
1236 template <class CHART> int CConditionElxT <CHART> :: Match(CContext * pContext) const
1237 {
1238 // status
1239 int nbegin = pContext->m_nCurrentPos;
1240 int nsize = pContext->m_stack.GetSize();
1241 int ncsize = pContext->m_capturestack.GetSize();
1242
1243 // condition result
1244 int condition_yes = 0;
1245
1246 // backref type
1247 if( m_nnumber >= 0 )
1248 {
1249 do
1250 {
1251 if(m_nnumber >= pContext->m_captureindex.GetSize()) break;
1252
1253 int index = pContext->m_captureindex[m_nnumber];
1254 if( index < 0) break;
1255
1256 // else valid
1257 condition_yes = 1;
1258 }
1259 while(0);
1260 }
1261 else
1262 {
1263 if( m_pelxask == 0 )
1264 condition_yes = 1;
1265 else
1266 condition_yes = m_pelxask->Match(pContext);
1267
1268 pContext->m_stack.Restore(nsize);
1269 pContext->m_nCurrentPos = nbegin;
1270 }
1271
1272 // elx result
1273 int bsucc;
1274 if( condition_yes )
1275 bsucc = m_pelxyes == 0 ? 1 : m_pelxyes->Match(pContext);
1276 else
1277 bsucc = m_pelxno == 0 ? 1 : m_pelxno ->Match(pContext);
1278
1279 if( bsucc )
1280 {
1281 pContext->m_stack.Push(ncsize);
1282 pContext->m_stack.Push(condition_yes);
1283 }
1284 else
1285 {
1286 pContext->m_capturestack.Restore(ncsize);
1287 }
1288
1289 return bsucc;
1290 }
1291
1292 template <class CHART> int CConditionElxT <CHART> :: MatchNext(CContext * pContext) const
1293 {
1294 // pop
1295 int ncsize, condition_yes;
1296
1297 pContext->m_stack.Pop(condition_yes);
1298 pContext->m_stack.Pop(ncsize);
1299
1300 // elx result
1301 int bsucc;
1302 if( condition_yes )
1303 bsucc = m_pelxyes == 0 ? 0 : m_pelxyes->MatchNext(pContext);
1304 else
1305 bsucc = m_pelxno == 0 ? 0 : m_pelxno ->MatchNext(pContext);
1306
1307 if( bsucc )
1308 {
1309 pContext->m_stack.Push(ncsize);
1310 pContext->m_stack.Push(condition_yes);
1311 }
1312 else
1313 {
1314 pContext->m_capturestack.Restore(ncsize);
1315 }
1316
1317 return bsucc;
1318 }
1319
1320 //
1321 // MatchResult
1322 //
1323 template <int x> class MatchResultT
1324 {
1325 public:
1326 int IsMatched() const;
1327
1328 public:
1329 int GetStart() const;
1330 int GetEnd () const;
1331
1332 public:
1333 int MaxGroupNumber() const;
1334 int GetGroupStart(int nGroupNumber) const;
1335 int GetGroupEnd (int nGroupNumber) const;
1336
1337 public:
1338 MatchResultT(CContext * pContext, int nMaxNumber = -1);
1339 MatchResultT <x> & operator = (const MatchResultT <x> &);
1340 inline operator int() const { return IsMatched(); }
1341
1342 public:
1343 CBufferT <int> m_result;
1344 };
1345
1346 typedef MatchResultT <0> MatchResult;
1347
1348 // Stocked Elx IDs
1349 enum STOCKELX_ID_DEFINES
1350 {
1351 STOCKELX_EMPTY = 0,
1352
1353 ///////////////////////
1354
1355 STOCKELX_DOT_ALL,
1356 STOCKELX_DOT_NOT_ALL,
1357
1358 STOCKELX_WORD,
1359 STOCKELX_WORD_NOT,
1360
1361 STOCKELX_SPACE,
1362 STOCKELX_SPACE_NOT,
1363
1364 STOCKELX_DIGITAL,
1365 STOCKELX_DIGITAL_NOT,
1366
1367 //////////////////////
1368
1369 STOCKELX_DOT_ALL_RIGHTLEFT,
1370 STOCKELX_DOT_NOT_ALL_RIGHTLEFT,
1371
1372 STOCKELX_WORD_RIGHTLEFT,
1373 STOCKELX_WORD_RIGHTLEFT_NOT,
1374
1375 STOCKELX_SPACE_RIGHTLEFT,
1376 STOCKELX_SPACE_RIGHTLEFT_NOT,
1377
1378 STOCKELX_DIGITAL_RIGHTLEFT,
1379 STOCKELX_DIGITAL_RIGHTLEFT_NOT,
1380
1381 /////////////////////
1382
1383 STOCKELX_COUNT
1384 };
1385
1386 // REGEX_FLAGS
1387 #ifndef _REGEX_FLAGS_DEFINED
1388 enum REGEX_FLAGS
1389 {
1390 NO_FLAG = 0,
1391 SINGLELINE = 0x01,
1392 MULTILINE = 0x02,
1393 GLOBAL = 0x04,
1394 IGNORECASE = 0x08,
1395 RIGHTTOLEFT = 0x10,
1396 EXTENDED = 0x20,
1397 };
1398 #define _REGEX_FLAGS_DEFINED
1399 #endif
1400
1401 //
1402 // Builder T
1403 //
1404 template <class CHART> class CBuilderT
1405 {
1406 public:
1407 typedef CDelegateElxT <CHART> CDelegateElx;
1408 typedef CBracketElxT <CHART> CBracketElx;
1409 typedef CBackrefElxT <CHART> CBackrefElx;
1410 typedef CConditionElxT <CHART> CConditionElx;
1411
1412 // Methods
1413 public:
1414 ElxInterface * Build(const CBufferRefT <CHART> & pattern, int flags);
1415 int GetNamedNumber(const CBufferRefT <CHART> & named) const;
1416 void Clear();
1417
1418 public:
1419 CBuilderT();
1420 ~CBuilderT();
1421
1422 // Public Attributes
1423 public:
1424 ElxInterface * m_pTopElx;
1425 int m_nFlags;
1426 int m_nMaxNumber;
1427 int m_nNextNamed;
1428 int m_nGroupCount;
1429
1430 CBufferT <ElxInterface *> m_objlist;
1431 CBufferT <ElxInterface *> m_grouplist;
1432 CBufferT <CDelegateElx *> m_recursivelist;
1433 CBufferT <CListElx *> m_namedlist;
1434 CBufferT <CBackrefElx *> m_namedbackreflist;
1435 CBufferT <CConditionElx *> m_namedconditionlist;
1436
1437 // CHART_INFO
1438 protected:
1439 struct CHART_INFO
1440 {
1441 public:
1442 CHART ch;
1443 int type;
1444 int pos;
1445 int len;
1446
1447 public:
1448 CHART_INFO(CHART c, int t, int p = 0, int l = 0) { ch = c; type = t; pos = p; len = l; }
1449 inline int operator == (const CHART_INFO & ci) { return ch == ci.ch && type == ci.type; }
1450 inline int operator != (const CHART_INFO & ci) { return ! operator == (ci); }
1451 };
1452
1453 protected:
1454 static unsigned int Hex2Int(const CHART * pcsz, int length, int & used);
1455 static int ReadDec(char * & str, unsigned int & dec);
1456 void MoveNext();
1457 int GetNext2();
1458
1459 ElxInterface * BuildAlternative(int vaflags);
1460 ElxInterface * BuildList (int & flags);
1461 ElxInterface * BuildRepeat (int & flags);
1462 ElxInterface * BuildSimple (int & flags);
1463 ElxInterface * BuildCharset (int & flags);
1464 ElxInterface * BuildRecursive (int & flags);
1465 ElxInterface * BuildBoundary (int & flags);
1466 ElxInterface * BuildBackref (int & flags);
1467
1468 ElxInterface * GetStockElx (int nStockId);
1469 ElxInterface * Keep(ElxInterface * pElx);
1470
1471 // Private Attributes
1472 protected:
1473 CBufferRefT <CHART> m_pattern;
1474 CHART_INFO prev, curr, next, nex2;
1475 int m_nNextPos;
1476 int m_nCharsetDepth;
1477 int m_bQuoted;
1478 int (*m_quote_fun)(int);
1479
1480 ElxInterface * m_pStockElxs[STOCKELX_COUNT];
1481 };
1482
1483 //
1484 // Implementation
1485 //
1486 template <class CHART> CBuilderT <CHART> :: CBuilderT() : m_pattern(0, 0), prev(0, 0), curr(0, 0), next(0, 0), nex2(0, 0)
1487 {
1488 Clear();
1489 }
1490
1491 template <class CHART> CBuilderT <CHART> :: ~CBuilderT()
1492 {
1493 Clear();
1494 }
1495
1496 template <class CHART> int CBuilderT <CHART> :: GetNamedNumber(const CBufferRefT <CHART> & named) const
1497 {
1498 for(int i=0; i<m_namedlist.GetSize(); i++)
1499 {
1500 if( ! ((CBracketElx *)m_namedlist[i]->m_elxlist[0])->m_szNamed.CompareNoCase(named) )
1501 return ((CBracketElx *)m_namedlist[i]->m_elxlist[0])->m_nnumber;
1502 }
1503
1504 return -3;
1505 }
1506
1507 template <class CHART> ElxInterface * CBuilderT <CHART> :: Build(const CBufferRefT <CHART> & pattern, int flags)
1508 {
1509 // init
1510 m_pattern = pattern;
1511 m_nNextPos = 0;
1512 m_nCharsetDepth = 0;
1513 m_nMaxNumber = 0;
1514 m_nNextNamed = 0;
1515 m_nFlags = flags;
1516 m_bQuoted = 0;
1517 m_quote_fun = 0;
1518
1519 m_grouplist .Restore(0);
1520 m_recursivelist .Restore(0);
1521 m_namedlist .Restore(0);
1522 m_namedbackreflist .Restore(0);
1523 m_namedconditionlist.Restore(0);
1524
1525 int i;
1526 for(i=0; i<3; i++) MoveNext();
1527
1528 // build
1529 m_pTopElx = BuildAlternative(flags);
1530
1531 // group 0
1532 m_grouplist.Prepare(0);
1533 m_grouplist[0] = m_pTopElx;
1534
1535 // append named to unnamed
1536 m_nGroupCount = m_grouplist.GetSize();
1537
1538 m_grouplist.Prepare(m_nMaxNumber + m_namedlist.GetSize());
1539
1540 for(i=0; i<m_namedlist.GetSize(); i++)
1541 {
1542 CBracketElx * pleft = (CBracketElx *)m_namedlist[i]->m_elxlist[0];
1543 CBracketElx * pright = (CBracketElx *)m_namedlist[i]->m_elxlist[2];
1544
1545 // append
1546 m_grouplist[m_nGroupCount ++] = m_namedlist[i];
1547
1548 if( pleft->m_nnumber > 0 )
1549 continue;
1550
1551 // same name
1552 int find_same_name = GetNamedNumber(pleft->m_szNamed);
1553 if( find_same_name >= 0 )
1554 {
1555 pleft ->m_nnumber = find_same_name;
1556 pright->m_nnumber = find_same_name;
1557 }
1558 else
1559 {
1560 m_nMaxNumber ++;
1561
1562 pleft ->m_nnumber = m_nMaxNumber;
1563 pright->m_nnumber = m_nMaxNumber;
1564 }
1565 }
1566
1567 for(i=1; i<m_nGroupCount; i++)
1568 {
1569 CBracketElx * pleft = (CBracketElx *)((CListElx*)m_grouplist[i])->m_elxlist[0];
1570
1571 if( pleft->m_nnumber > m_nMaxNumber )
1572 m_nMaxNumber = pleft->m_nnumber;
1573 }
1574
1575 // connect recursive
1576 for(i=0; i<m_recursivelist.GetSize(); i++)
1577 {
1578 if( m_recursivelist[i]->m_ndata == -3 )
1579 m_recursivelist[i]->m_ndata = GetNamedNumber(m_recursivelist[i]->m_szNamed);
1580
1581 if( m_recursivelist[i]->m_ndata >= 0 && m_recursivelist[i]->m_ndata < m_grouplist.GetSize() )
1582 m_recursivelist[i]->m_pelx = m_grouplist[m_recursivelist[i]->m_ndata];
1583 }
1584
1585 // named backref
1586 for(i=0; i<m_namedbackreflist.GetSize(); i++)
1587 {
1588 m_namedbackreflist[i]->m_nnumber = GetNamedNumber(m_namedbackreflist[i]->m_szNamed);
1589 }
1590
1591 // named condition
1592 for(i=0; i<m_namedconditionlist.GetSize(); i++)
1593 {
1594 int nn = GetNamedNumber(m_namedconditionlist[i]->m_szNamed);
1595 if( nn >= 0 )
1596 {
1597 m_namedconditionlist[i]->m_nnumber = nn;
1598 m_namedconditionlist[i]->m_pelxask = 0;
1599 }
1600 }
1601
1602 return m_pTopElx;
1603 }
1604
1605 template <class CHART> void CBuilderT <CHART> :: Clear()
1606 {
1607 for(int i=0; i<m_objlist.GetSize(); i++)
1608 {
1609 delete m_objlist[i];
1610 }
1611
1612 m_objlist.Restore(0);
1613 m_pTopElx = 0;
1614
1615 memset(m_pStockElxs, 0, sizeof(m_pStockElxs));
1616 }
1617
1618 //
1619 // hex to int
1620 //
1621 template <class CHART> unsigned int CBuilderT <CHART> :: Hex2Int(const CHART * pcsz, int length, int & used)
1622 {
1623 unsigned int result = 0;
1624 int & i = used;
1625
1626 for(i=0; i<length; i++)
1627 {
1628 if(pcsz[i] >= RCHART('0') && pcsz[i] <= RCHART('9'))
1629 result = (result << 4) + (pcsz[i] - RCHART('0'));
1630 else if(pcsz[i] >= RCHART('A') && pcsz[i] <= RCHART('F'))
1631 result = (result << 4) + (0x0A + (pcsz[i] - RCHART('A')));
1632 else if(pcsz[i] >= RCHART('a') && pcsz[i] <= RCHART('f'))
1633 result = (result << 4) + (0x0A + (pcsz[i] - RCHART('a')));
1634 else
1635 break;
1636 }
1637
1638 return result;
1639 }
1640
1641 template <class CHART> inline ElxInterface * CBuilderT <CHART> :: Keep(ElxInterface * pelx)
1642 {
1643 m_objlist.Push(pelx);
1644 return pelx;
1645 }
1646
1647 template <class CHART> void CBuilderT <CHART> :: MoveNext()
1648 {
1649 // forwards
1650 prev = curr;
1651 curr = next;
1652 next = nex2;
1653
1654 // get nex2
1655 while( ! GetNext2() ) {};
1656 }
1657
1658 template <class CHART> int CBuilderT <CHART> :: GetNext2()
1659 {
1660 // check length
1661 if(m_nNextPos >= m_pattern.GetSize())
1662 {
1663 nex2 = CHART_INFO(0, 1, m_nNextPos, 0);
1664 return 1;
1665 }
1666
1667 int delta = 1;
1668 CHART ch = m_pattern[m_nNextPos];
1669
1670 // if quoted
1671 if(m_bQuoted)
1672 {
1673 if(ch == RCHART('\\'))
1674 {
1675 if(m_pattern[m_nNextPos + 1] == RCHART('E'))
1676 {
1677 m_quote_fun = 0;
1678 m_bQuoted = 0;
1679 m_nNextPos += 2;
1680 return 0;
1681 }
1682 }
1683
1684 if(m_quote_fun != 0)
1685 nex2 = CHART_INFO((CHART)(*m_quote_fun)((int)ch), 0, m_nNextPos, delta);
1686 else
1687 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
1688
1689 m_nNextPos += delta;
1690
1691 return 1;
1692 }
1693
1694 // common
1695 switch(ch)
1696 {
1697 case RCHART('\\'):
1698 {
1699 CHART ch1 = m_pattern[m_nNextPos+1];
1700
1701 // backref
1702 if(ch1 >= RCHART('0') && ch1 <= RCHART('9'))
1703 {
1704 nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
1705 break;
1706 }
1707
1708 // escape
1709 delta = 2;
1710
1711 switch(ch1)
1712 {
1713 case RCHART('A'):
1714 case RCHART('Z'):
1715 case RCHART('w'):
1716 case RCHART('W'):
1717 case RCHART('s'):
1718 case RCHART('S'):
1719 case RCHART('B'):
1720 case RCHART('d'):
1721 case RCHART('D'):
1722 case RCHART('k'):
1723 case RCHART('g'):
1724 nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta);
1725 break;
1726
1727 case RCHART('b'):
1728 if(m_nCharsetDepth > 0)
1729 nex2 = CHART_INFO('\b', 0, m_nNextPos, delta);
1730 else
1731 nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta);
1732 break;
1733
1734 /*
1735 case RCHART('<'):
1736 case RCHART('>'):
1737 if(m_nCharsetDepth > 0)
1738 nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta);
1739 else
1740 nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta);
1741 break;
1742 */
1743
1744 case RCHART('x'):
1745 if(m_pattern[m_nNextPos+2] != '{')
1746 {
1747 int red = 0;
1748 unsigned int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 2, 2, red);
1749
1750 delta += red;
1751
1752 if(red > 0)
1753 nex2 = CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta);
1754 else
1755 nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta);
1756
1757 break;
1758 }
1759
1760 case RCHART('u'):
1761 if(m_pattern[m_nNextPos+2] != '{')
1762 {
1763 int red = 0;
1764 unsigned int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 2, 4, red);
1765
1766 delta += red;
1767
1768 if(red > 0)
1769 nex2 = CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta);
1770 else
1771 nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta);
1772 }
1773 else
1774 {
1775 int red = 0;
1776 unsigned int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 3, sizeof(int) * 2, red);
1777
1778 delta += red;
1779
1780 while(m_nNextPos + delta < m_pattern.GetSize() && m_pattern.At(m_nNextPos + delta) != RCHART('}'))
1781 delta ++;
1782
1783 delta ++; // skip '}'
1784
1785 nex2 = CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta);
1786 }
1787 break;
1788
1789 case RCHART('a'): nex2 = CHART_INFO(RCHART('\a'), 0, m_nNextPos, delta); break;
1790 case RCHART('f'): nex2 = CHART_INFO(RCHART('\f'), 0, m_nNextPos, delta); break;
1791 case RCHART('n'): nex2 = CHART_INFO(RCHART('\n'), 0, m_nNextPos, delta); break;
1792 case RCHART('r'): nex2 = CHART_INFO(RCHART('\r'), 0, m_nNextPos, delta); break;
1793 case RCHART('t'): nex2 = CHART_INFO(RCHART('\t'), 0, m_nNextPos, delta); break;
1794 case RCHART('v'): nex2 = CHART_INFO(RCHART('\v'), 0, m_nNextPos, delta); break;
1795 case RCHART('e'): nex2 = CHART_INFO(RCHART( 27 ), 0, m_nNextPos, delta); break;
1796
1797 case RCHART('G'): // skip '\G'
1798 if(m_nCharsetDepth > 0)
1799 {
1800 m_nNextPos += 2;
1801 return 0;
1802 }
1803 else
1804 {
1805 nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta);
1806 break;
1807 }
1808
1809 case RCHART('L'):
1810 if( ! m_quote_fun ) m_quote_fun = ::tolower;
1811
1812 case RCHART('U'):
1813 if( ! m_quote_fun ) m_quote_fun = ::toupper;
1814
1815 case RCHART('Q'):
1816 {
1817 m_bQuoted = 1;
1818 m_nNextPos += 2;
1819 return 0;
1820 }
1821
1822 case RCHART('E'):
1823 {
1824 m_quote_fun = 0;
1825 m_bQuoted = 0;
1826 m_nNextPos += 2;
1827 return 0;
1828 }
1829
1830 case 0:
1831 if(m_nNextPos+1 >= m_pattern.GetSize())
1832 {
1833 delta = 1;
1834 nex2 = CHART_INFO(ch , 0, m_nNextPos, delta);
1835 }
1836 else
1837 nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); // common '\0' char
1838 break;
1839
1840 default:
1841 nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta);
1842 break;
1843 }
1844 }
1845 break;
1846
1847 case RCHART('*'):
1848 case RCHART('+'):
1849 case RCHART('?'):
1850 case RCHART('.'):
1851 case RCHART('{'):
1852 case RCHART('}'):
1853 case RCHART(')'):
1854 case RCHART('|'):
1855 case RCHART('$'):
1856 if(m_nCharsetDepth > 0)
1857 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
1858 else
1859 nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
1860 break;
1861
1862 case RCHART('-'):
1863 if(m_nCharsetDepth > 0)
1864 nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
1865 else
1866 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
1867 break;
1868
1869 case RCHART('('):
1870 {
1871 CHART ch1 = m_pattern[m_nNextPos+1];
1872 CHART ch2 = m_pattern[m_nNextPos+2];
1873
1874 // skip remark
1875 if(ch1 == RCHART('?') && ch2 == RCHART('#'))
1876 {
1877 m_nNextPos += 2;
1878 while(m_nNextPos < m_pattern.GetSize())
1879 {
1880 if(m_pattern[m_nNextPos] == RCHART(')'))
1881 break;
1882
1883 m_nNextPos ++;
1884 }
1885
1886 if(m_pattern[m_nNextPos] == RCHART(')'))
1887 {
1888 m_nNextPos ++;
1889
1890 // get next nex2
1891 return 0;
1892 }
1893 }
1894 else
1895 {
1896 if(m_nCharsetDepth > 0)
1897 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
1898 else
1899 nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
1900 }
1901 }
1902 break;
1903
1904 case RCHART('#'):
1905 if(m_nFlags & EXTENDED)
1906 {
1907 // skip remark
1908 m_nNextPos ++;
1909
1910 while(m_nNextPos < m_pattern.GetSize())
1911 {
1912 if(m_pattern[m_nNextPos] == RCHART('\n') || m_pattern[m_nNextPos] == RCHART('\r'))
1913 break;
1914
1915 m_nNextPos ++;
1916 }
1917
1918 // get next nex2
1919 return 0;
1920 }
1921 else
1922 {
1923 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
1924 }
1925 break;
1926
1927 case RCHART(' '):
1928 case RCHART('\f'):
1929 case RCHART('\n'):
1930 case RCHART('\r'):
1931 case RCHART('\t'):
1932 case RCHART('\v'):
1933 if(m_nFlags & EXTENDED)
1934 {
1935 m_nNextPos ++;
1936
1937 // get next nex2
1938 return 0;
1939 }
1940 else
1941 {
1942 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
1943 }
1944 break;
1945
1946 case RCHART('['):
1947 m_nCharsetDepth ++;
1948 nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
1949 break;
1950
1951 case RCHART(']'):
1952 if(m_nCharsetDepth > 0)
1953 {
1954 m_nCharsetDepth --;
1955 nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
1956 }
1957 else
1958 {
1959 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
1960 }
1961 break;
1962
1963 case RCHART(':'):
1964 if(next == CHART_INFO(RCHART('['), 1))
1965 nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
1966 else
1967 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
1968 break;
1969
1970 case RCHART('^'):
1971 if(m_nCharsetDepth == 0 || next == CHART_INFO(RCHART('['), 1) || (curr == CHART_INFO(RCHART('['), 1) && next == CHART_INFO(RCHART(':'), 1)))
1972 nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
1973 else
1974 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
1975 break;
1976
1977 case 0:
1978 if(m_nNextPos >= m_pattern.GetSize())
1979 nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); // end of string
1980 else
1981 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); // common '\0' char
1982 break;
1983
1984 default:
1985 nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
1986 break;
1987 }
1988
1989 m_nNextPos += delta;
1990
1991 return 1;
1992 }
1993
1994 template <class CHART> ElxInterface * CBuilderT <CHART> :: GetStockElx(int nStockId)
1995 {
1996 ElxInterface ** pStockElxs = m_pStockElxs;
1997
1998 // check
1999 if(nStockId < 0 || nStockId >= STOCKELX_COUNT)
2000 return GetStockElx(0);
2001
2002 // create if no
2003 if(pStockElxs[nStockId] == 0)
2004 {
2005 switch(nStockId)
2006 {
2007 case STOCKELX_EMPTY:
2008 pStockElxs[nStockId] = Keep(new CEmptyElx());
2009 break;
2010
2011 case STOCKELX_WORD:
2012 {
2013 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 1));
2014
2015 pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z'));
2016 pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z'));
2017 pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
2018 pRange->m_chars .Push(RCHART('_'));
2019
2020 pStockElxs[nStockId] = pRange;
2021 }
2022 break;
2023
2024 case STOCKELX_WORD_NOT:
2025 {
2026 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 0));
2027
2028 pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z'));
2029 pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z'));
2030 pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
2031 pRange->m_chars .Push(RCHART('_'));
2032
2033 pStockElxs[nStockId] = pRange;
2034 }
2035 break;
2036
2037 case STOCKELX_DOT_ALL:
2038 pStockElxs[nStockId] = Keep(new CRangeElxT <CHART> (0, 0));
2039 break;
2040
2041 case STOCKELX_DOT_NOT_ALL:
2042 {
2043 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 0));
2044
2045 pRange->m_chars .Push(RCHART('\n'));
2046
2047 pStockElxs[nStockId] = pRange;
2048 }
2049 break;
2050
2051 case STOCKELX_SPACE:
2052 {
2053 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 1));
2054
2055 pRange->m_chars .Push(RCHART(' '));
2056 pRange->m_chars .Push(RCHART('\t'));
2057 pRange->m_chars .Push(RCHART('\r'));
2058 pRange->m_chars .Push(RCHART('\n'));
2059
2060 pStockElxs[nStockId] = pRange;
2061 }
2062 break;
2063
2064 case STOCKELX_SPACE_NOT:
2065 {
2066 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 0));
2067
2068 pRange->m_chars .Push(RCHART(' '));
2069 pRange->m_chars .Push(RCHART('\t'));
2070 pRange->m_chars .Push(RCHART('\r'));
2071 pRange->m_chars .Push(RCHART('\n'));
2072
2073 pStockElxs[nStockId] = pRange;
2074 }
2075 break;
2076
2077 case STOCKELX_DIGITAL:
2078 {
2079 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 1));
2080
2081 pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
2082
2083 pStockElxs[nStockId] = pRange;
2084 }
2085 break;
2086
2087 case STOCKELX_DIGITAL_NOT:
2088 {
2089 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 0));
2090
2091 pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
2092
2093 pStockElxs[nStockId] = pRange;
2094 }
2095 break;
2096
2097 case STOCKELX_WORD_RIGHTLEFT:
2098 {
2099 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 1));
2100
2101 pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z'));
2102 pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z'));
2103 pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
2104 pRange->m_chars .Push(RCHART('_'));
2105
2106 pStockElxs[nStockId] = pRange;
2107 }
2108 break;
2109
2110 case STOCKELX_WORD_RIGHTLEFT_NOT:
2111 {
2112 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 0));
2113
2114 pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z'));
2115 pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z'));
2116 pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
2117 pRange->m_chars .Push(RCHART('_'));
2118
2119 pStockElxs[nStockId] = pRange;
2120 }
2121 break;
2122
2123 case STOCKELX_DOT_ALL_RIGHTLEFT:
2124 pStockElxs[nStockId] = Keep(new CRangeElxT <CHART> (1, 0));
2125 break;
2126
2127 case STOCKELX_DOT_NOT_ALL_RIGHTLEFT:
2128 {
2129 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 0));
2130
2131 pRange->m_chars .Push(RCHART('\n'));
2132
2133 pStockElxs[nStockId] = pRange;
2134 }
2135 break;
2136
2137 case STOCKELX_SPACE_RIGHTLEFT:
2138 {
2139 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 1));
2140
2141 pRange->m_chars .Push(RCHART(' '));
2142 pRange->m_chars .Push(RCHART('\t'));
2143 pRange->m_chars .Push(RCHART('\r'));
2144 pRange->m_chars .Push(RCHART('\n'));
2145 pRange->m_chars .Push(RCHART('\f'));
2146 pRange->m_chars .Push(RCHART('\v'));
2147
2148 pStockElxs[nStockId] = pRange;
2149 }
2150 break;
2151
2152 case STOCKELX_SPACE_RIGHTLEFT_NOT:
2153 {
2154 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 0));
2155
2156 pRange->m_chars .Push(RCHART(' '));
2157 pRange->m_chars .Push(RCHART('\t'));
2158 pRange->m_chars .Push(RCHART('\r'));
2159 pRange->m_chars .Push(RCHART('\n'));
2160 pRange->m_chars .Push(RCHART('\f'));
2161 pRange->m_chars .Push(RCHART('\v'));
2162
2163 pStockElxs[nStockId] = pRange;
2164 }
2165 break;
2166
2167 case STOCKELX_DIGITAL_RIGHTLEFT:
2168 {
2169 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 1));
2170
2171 pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
2172
2173 pStockElxs[nStockId] = pRange;
2174 }
2175 break;
2176
2177 case STOCKELX_DIGITAL_RIGHTLEFT_NOT:
2178 {
2179 CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 0));
2180
2181 pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
2182
2183 pStockElxs[nStockId] = pRange;
2184 }
2185 break;
2186 }
2187 }
2188
2189 // return
2190 return pStockElxs[nStockId];
2191 }
2192
2193 template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildAlternative(int vaflags)
2194 {
2195 if(curr == CHART_INFO(0, 1))
2196 return GetStockElx(STOCKELX_EMPTY);
2197
2198 // flag instance
2199 int flags = vaflags;
2200
2201 // first part
2202 ElxInterface * pAlternativeOne = BuildList(flags);
2203
2204 // check alternative
2205 if(curr == CHART_INFO(RCHART('|'), 1))
2206 {
2207 CAlternativeElx * pAlternative = (CAlternativeElx *)Keep(new CAlternativeElx());
2208 pAlternative->m_elxlist.Push(pAlternativeOne);
2209
2210 // loop
2211 while(curr == CHART_INFO(RCHART('|'), 1))
2212 {
2213 // skip '|' itself
2214 MoveNext();
2215
2216 pAlternativeOne = BuildList(flags);
2217 pAlternative->m_elxlist.Push(pAlternativeOne);
2218 }
2219
2220 return pAlternative;
2221 }
2222
2223 return pAlternativeOne;
2224 }
2225
2226 template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildList(int & flags)
2227 {
2228 if(curr == CHART_INFO(0, 1) || curr == CHART_INFO(RCHART('|'), 1) || curr == CHART_INFO(RCHART(')'), 1))
2229 return GetStockElx(STOCKELX_EMPTY);
2230
2231 // first
2232 ElxInterface * pListOne = BuildRepeat(flags);
2233
2234 if(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('|'), 1) && curr != CHART_INFO(RCHART(')'), 1))
2235 {
2236 CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT));
2237 pList->m_elxlist.Push(pListOne);
2238
2239 while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('|'), 1) && curr != CHART_INFO(RCHART(')'), 1))
2240 {
2241 pListOne = BuildRepeat(flags);
2242
2243 // add
2244 pList->m_elxlist.Push(pListOne);
2245 }
2246
2247 return pList;
2248 }
2249
2250 return pListOne;
2251 }
2252
2253 template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildRepeat(int & flags)
2254 {
2255 // simple
2256 ElxInterface * pSimple = BuildSimple(flags);
2257
2258 if(curr.type == 0) return pSimple;
2259
2260 // is quantifier or not
2261 int bIsQuantifier = 1;
2262
2263 // quantifier range
2264 unsigned int nMin = 0, nMax = 0;
2265
2266 switch(curr.ch)
2267 {
2268 case RCHART('{'):
2269 {
2270 CBufferT <char> re;
2271
2272 // skip '{'
2273 MoveNext();
2274
2275 // copy
2276 while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('}'), 1))
2277 {
2278 re.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
2279 MoveNext();
2280 }
2281
2282 // skip '}'
2283 MoveNext();
2284
2285 // read
2286 int red;
2287 char * str = re.GetBuffer();
2288
2289 if( ! ReadDec(str, nMin) )
2290 red = 0;
2291 else if( *str != ',' )
2292 red = 1;
2293 else
2294 {
2295 str ++;
2296
2297 if( ! ReadDec(str, nMax) )
2298 red = 2;
2299 else
2300 red = 3;
2301 }
2302
2303 // check
2304 if(red <= 1 ) nMax = nMin;
2305 if(red == 2 ) nMax = INT_MAX;
2306 if(nMax < nMin) nMax = nMin;
2307 }
2308 break;
2309
2310 case RCHART('?'):
2311 nMin = 0;
2312 nMax = 1;
2313
2314 // skip '?'
2315 MoveNext();
2316 break;
2317
2318 case RCHART('*'):
2319 nMin = 0;
2320 nMax = INT_MAX;
2321
2322 // skip '*'
2323 MoveNext();
2324 break;
2325
2326 case RCHART('+'):
2327 nMin = 1;
2328 nMax = INT_MAX;
2329
2330 // skip '+'
2331 MoveNext();
2332 break;
2333
2334 default:
2335 bIsQuantifier = 0;
2336 break;
2337 }
2338
2339 // do quantify
2340 if(bIsQuantifier)
2341 {
2342 // 0 times
2343 if(nMax == 0)
2344 return GetStockElx(STOCKELX_EMPTY);
2345
2346 // fixed times
2347 if(nMin == nMax)
2348 {
2349 if(curr == CHART_INFO(RCHART('?'), 1) || curr == CHART_INFO(RCHART('+'), 1))
2350 MoveNext();
2351
2352 return Keep(new CRepeatElx(pSimple, nMin));
2353 }
2354
2355 // range times
2356 if(curr == CHART_INFO(RCHART('?'), 1))
2357 {
2358 MoveNext();
2359 return Keep(new CReluctantElx(pSimple, nMin, nMax));
2360 }
2361 else if(curr == CHART_INFO(RCHART('+'), 1))
2362 {
2363 MoveNext();
2364 return Keep(new CPossessiveElx(pSimple, nMin, nMax));
2365 }
2366 else
2367 {
2368 return Keep(new CGreedyElx(pSimple, nMin, nMax));
2369 }
2370 }
2371
2372 return pSimple;
2373 }
2374
2375 template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildSimple(int & flags)
2376 {
2377 CBufferT <CHART> fixed;
2378
2379 while(curr != CHART_INFO(0, 1))
2380 {
2381 if(curr.type == 0)
2382 {
2383 if(next == CHART_INFO(RCHART('{'), 1) || next == CHART_INFO(RCHART('?'), 1) || next == CHART_INFO(RCHART('*'), 1) || next == CHART_INFO(RCHART('+'), 1))
2384 {
2385 if(fixed.GetSize() == 0)
2386 {
2387 fixed.Append(curr.ch, 1);
2388 MoveNext();
2389 }
2390
2391 break;
2392 }
2393 else
2394 {
2395 fixed.Append(curr.ch, 1);
2396 MoveNext();
2397 }
2398 }
2399 else if(curr.type == 1)
2400 {
2401 CHART vch = curr.ch;
2402
2403 // end of simple
2404 if(vch == RCHART(')') || vch == RCHART('|'))
2405 break;
2406
2407 // has fixed already
2408 if(fixed.GetSize() > 0)
2409 break;
2410
2411 // left parentheses
2412 if(vch == RCHART('('))
2413 {
2414 return BuildRecursive(flags);
2415 }
2416
2417 // char set
2418 if( vch == RCHART('[') || vch == RCHART('.') || vch == RCHART('w') || vch == RCHART('W') ||
2419 vch == RCHART('s') || vch == RCHART('S') || vch == RCHART('d') || vch == RCHART('D')
2420 )
2421 {
2422 return BuildCharset(flags);
2423 }
2424
2425 // boundary
2426 if( vch == RCHART('^') || vch == RCHART('$') || vch == RCHART('A') || vch == RCHART('Z') ||
2427 vch == RCHART('b') || vch == RCHART('B') || vch == RCHART('G') // vch == RCHART('<') || vch == RCHART('>')
2428 )
2429 {
2430 return BuildBoundary(flags);
2431 }
2432
2433 // backref
2434 if(vch == RCHART('\\') || vch == RCHART('k') || vch == RCHART('g'))
2435 {
2436 return BuildBackref(flags);
2437 }
2438
2439 // treat vchar as char
2440 fixed.Append(curr.ch, 1);
2441 MoveNext();
2442 }
2443 }
2444
2445 if(fixed.GetSize() > 0)
2446 return Keep(new CStringElxT <CHART> (fixed.GetBuffer(), fixed.GetSize(), flags & RIGHTTOLEFT, flags & IGNORECASE));
2447 else
2448 return GetStockElx(STOCKELX_EMPTY);
2449 }
2450
2451 template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildCharset(int & flags)
2452 {
2453 // char
2454 CHART ch = curr.ch;
2455
2456 // skip
2457 MoveNext();
2458
2459 switch(ch)
2460 {
2461 case RCHART('.'):
2462 return GetStockElx(
2463 flags & RIGHTTOLEFT ?
2464 ((flags & SINGLELINE) ? STOCKELX_DOT_ALL_RIGHTLEFT : STOCKELX_DOT_NOT_ALL_RIGHTLEFT) :
2465 ((flags & SINGLELINE) ? STOCKELX_DOT_ALL : STOCKELX_DOT_NOT_ALL)
2466 );
2467
2468 case RCHART('w'):
2469 return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_WORD_RIGHTLEFT : STOCKELX_WORD);
2470
2471 case RCHART('W'):
2472 return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_WORD_RIGHTLEFT_NOT : STOCKELX_WORD_NOT);
2473
2474 case RCHART('s'):
2475 return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_SPACE_RIGHTLEFT : STOCKELX_SPACE);
2476
2477 case RCHART('S'):
2478 return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_SPACE_RIGHTLEFT_NOT : STOCKELX_SPACE_NOT);
2479
2480 case RCHART('d'):
2481 return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_DIGITAL_RIGHTLEFT : STOCKELX_DIGITAL);
2482
2483 case RCHART('D'):
2484 return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_DIGITAL_RIGHTLEFT_NOT : STOCKELX_DIGITAL_NOT);
2485
2486 case RCHART('['):
2487 {
2488 CRangeElxT <CHART> * pRange;
2489
2490 // create
2491 if(curr == CHART_INFO(RCHART(':'), 1))
2492 {
2493 CBufferT <char> posix;
2494
2495 do {
2496 posix.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
2497 MoveNext();
2498 }
2499 while(curr.ch != RCHART(0) && curr != CHART_INFO(RCHART(']'), 1));
2500
2501 MoveNext(); // skip ']'
2502
2503 // posix
2504 return Keep(new CPosixElxT <CHART> (posix.GetBuffer(), flags & RIGHTTOLEFT));
2505 }
2506 else if(curr == CHART_INFO(RCHART('^'), 1))
2507 {
2508 MoveNext(); // skip '^'
2509 pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (flags & RIGHTTOLEFT, 0));
2510 }
2511 else
2512 {
2513 pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (flags & RIGHTTOLEFT, 1));
2514 }
2515
2516 // parse
2517 while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART(']'), 1))
2518 {
2519 ch = curr.ch;
2520
2521 if(curr.type == 1 && (
2522 ch == RCHART('.') || ch == RCHART('w') || ch == RCHART('W') || ch == RCHART('s') || ch == RCHART('S') || ch == RCHART('d') || ch == RCHART('D') ||
2523 (ch == RCHART('[') && next == CHART_INFO(RCHART(':'), 1))
2524 ))
2525 {
2526 pRange->m_embeds.Push(BuildCharset(flags));
2527 }
2528 else if(next == CHART_INFO(RCHART('-'), 1) && nex2.type == 0)
2529 {
2530 pRange->m_ranges.Push(ch); pRange->m_ranges.Push(nex2.ch);
2531
2532 // next
2533 MoveNext();
2534 MoveNext();
2535 MoveNext();
2536 }
2537 else
2538 {
2539 pRange->m_chars.Push(ch);
2540
2541 // next
2542 MoveNext();
2543 }
2544 }
2545
2546 // skip ']'
2547 MoveNext();
2548
2549 return pRange;
2550 }
2551 }
2552
2553 return GetStockElx(STOCKELX_EMPTY);
2554 }
2555
2556 template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildRecursive(int & flags)
2557 {
2558 // skip '('
2559 MoveNext();
2560
2561 if(curr == CHART_INFO(RCHART('?'), 1))
2562 {
2563 ElxInterface * pElx = 0;
2564
2565 // skip '?'
2566 MoveNext();
2567
2568 int bNegative = 0;
2569 CHART named_end = RCHART('>');
2570
2571 switch(curr.ch)
2572 {
2573 case RCHART('!'):
2574 bNegative = 1;
2575
2576 case RCHART('='):
2577 {
2578 MoveNext(); // skip '!' or '='
2579 pElx = Keep(new CAssertElx(BuildAlternative(flags & ~RIGHTTOLEFT), !bNegative));
2580 }
2581 break;
2582
2583 case RCHART('<'):
2584 switch(next.ch)
2585 {
2586 case RCHART('!'):
2587 bNegative = 1;
2588
2589 case RCHART('='):
2590 MoveNext(); // skip '<'
2591 MoveNext(); // skip '!' or '='
2592 {
2593 pElx = Keep(new CAssertElx(BuildAlternative(flags | RIGHTTOLEFT), !bNegative));
2594 }
2595 break;
2596
2597 default: // named group
2598 break;
2599 }
2600 // break if assertion // else named
2601 if(pElx != 0) break;
2602
2603 case RCHART('P'):
2604 if(curr.ch == RCHART('P')) MoveNext(); // skip 'P'
2605
2606 case RCHART('\''):
2607 if (curr.ch == RCHART('<' )) named_end = RCHART('>' );
2608 else if(curr.ch == RCHART('\'')) named_end = RCHART('\'');
2609 MoveNext(); // skip '<' or '\''
2610 {
2611 // named number
2612 int nThisBackref = m_nNextNamed ++;
2613
2614 CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT));
2615 CBracketElx * pleft = (CBracketElx *)Keep(new CBracketElx(-1, flags & RIGHTTOLEFT ? 1 : 0));
2616 CBracketElx * pright = (CBracketElx *)Keep(new CBracketElx(-1, flags & RIGHTTOLEFT ? 0 : 1));
2617
2618 // save name
2619 CBufferT <CHART> & name = pleft->m_szNamed;
2620 CBufferT <char> num;
2621
2622 while(curr.ch != RCHART(0) && curr.ch != named_end)
2623 {
2624 name.Append(curr.ch, 1);
2625 num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
2626 MoveNext();
2627 }
2628 MoveNext(); // skip '>' or '\''
2629
2630 // check <num>
2631 unsigned int number;
2632 char * str = num.GetBuffer();
2633
2634 if( ReadDec(str, number) ? ( *str == '\0') : 0 )
2635 {
2636 pleft ->m_nnumber = number;
2637 pright->m_nnumber = number;
2638
2639 name.Release();
2640 }
2641
2642 // left, center, right
2643 pList->m_elxlist.Push(pleft);
2644 pList->m_elxlist.Push(BuildAlternative(flags));
2645 pList->m_elxlist.Push(pright);
2646
2647 // for recursive
2648 m_namedlist.Prepare(nThisBackref);
2649 m_namedlist[nThisBackref] = pList;
2650
2651 pElx = pList;
2652 }
2653 break;
2654
2655 case RCHART('>'):
2656 {
2657 MoveNext(); // skip '>'
2658 pElx = Keep(new CIndependentElx(BuildAlternative(flags)));
2659 }
2660 break;
2661
2662 case RCHART('R'):
2663 MoveNext(); // skip 'R'
2664 while(curr.ch != RCHART(0) && isspace(curr.ch)) MoveNext(); // skip space
2665
2666 if(curr.ch == RCHART('<') || curr.ch == RCHART('\''))
2667 {
2668 named_end = curr.ch == RCHART('<') ? RCHART('>') : RCHART('\'');
2669 CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(-3));
2670
2671 MoveNext(); // skip '<' or '\\'
2672
2673 // save name
2674 CBufferT <CHART> & name = pDelegate->m_szNamed;
2675 CBufferT <char> num;
2676
2677 while(curr.ch != RCHART(0) && curr.ch != named_end)
2678 {
2679 name.Append(curr.ch, 1);
2680 num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
2681 MoveNext();
2682 }
2683 MoveNext(); // skip '>' or '\''
2684
2685 // check <num>
2686 unsigned int number;
2687 char * str = num.GetBuffer();
2688
2689 if( ReadDec(str, number) ? ( *str == '\0') : 0 )
2690 {
2691 pDelegate->m_ndata = number;
2692 name.Release();
2693 }
2694
2695 m_recursivelist.Push(pDelegate);
2696 pElx = pDelegate;
2697 }
2698 else
2699 {
2700 CBufferT <char> rto;
2701 while(curr.ch != RCHART(0) && curr.ch != RCHART(')'))
2702 {
2703 rto.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
2704 MoveNext();
2705 }
2706
2707 unsigned int rtono = 0;
2708 char * str = rto.GetBuffer();
2709 ReadDec(str, rtono);
2710
2711 CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(rtono));
2712
2713 m_recursivelist.Push(pDelegate);
2714 pElx = pDelegate;
2715 }
2716 break;
2717
2718 case RCHART('('):
2719 {
2720 CConditionElx * pConditionElx = (CConditionElx *)Keep(new CConditionElx());
2721
2722 // condition
2723 ElxInterface * & pCondition = pConditionElx->m_pelxask;
2724
2725 if(next == CHART_INFO(RCHART('?'), 1))
2726 {
2727 pCondition = BuildRecursive(flags);
2728 }
2729 else // named, assert or number
2730 {
2731 MoveNext(); // skip '('
2732 int pos0 = curr.pos;
2733
2734 // save elx condition
2735 pCondition = Keep(new CAssertElx(BuildAlternative(flags), 1));
2736
2737 // save name
2738 pConditionElx->m_szNamed.Append(m_pattern.GetBuffer() + pos0, curr.pos - pos0, 1);
2739
2740 // save number
2741 CBufferT <char> numstr;
2742 while(pos0 < curr.pos)
2743 {
2744 CHART ch = m_pattern[pos0];
2745 numstr.Append(((ch & (CHART)0xff) == ch) ? (char)ch : 0, 1);
2746 pos0 ++;
2747 }
2748
2749 unsigned int number;
2750 char * str = numstr.GetBuffer();
2751
2752 // valid group number
2753 if( ReadDec(str, number) ? ( *str == '\0') : 0 )
2754 {
2755 pConditionElx->m_nnumber = number;
2756 pCondition = 0;
2757 }
2758 else // maybe elx, maybe named
2759 {
2760 pConditionElx->m_nnumber = -1;
2761 m_namedconditionlist.Push(pConditionElx);
2762 }
2763
2764 MoveNext(); // skip ')'
2765 }
2766
2767 // alternative
2768 {
2769 int newflags = flags;
2770
2771 pConditionElx->m_pelxyes = BuildList(newflags);
2772 }
2773
2774 if(curr.ch == RCHART('|'))
2775 {
2776 MoveNext(); // skip '|'
2777
2778 pConditionElx->m_pelxno = BuildAlternative(flags);
2779 }
2780 else
2781 {
2782 pConditionElx->m_pelxno = 0;
2783 }
2784
2785 pElx = pConditionElx;
2786 }
2787 break;
2788
2789 default:
2790 while(curr.ch != RCHART(0) && isspace(curr.ch)) MoveNext(); // skip space
2791
2792 if(curr.ch >= RCHART('0') && curr.ch <= RCHART('9')) // recursive (?1) => (?R1)
2793 {
2794 CBufferT <char> rto;
2795 while(curr.ch != RCHART(0) && curr.ch != RCHART(')'))
2796 {
2797 rto.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
2798 MoveNext();
2799 }
2800
2801 unsigned int rtono = 0;
2802 char * str = rto.GetBuffer();
2803 ReadDec(str, rtono);
2804
2805 CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(rtono));
2806
2807 m_recursivelist.Push(pDelegate);
2808 pElx = pDelegate;
2809 }
2810 else
2811 {
2812 // flag
2813 int newflags = flags;
2814 while(curr != CHART_INFO(0, 1) && curr.ch != RCHART(':') && curr.ch != RCHART(')') && curr != CHART_INFO(RCHART('('), 1))
2815 {
2816 int tochange = 0;
2817
2818 switch(curr.ch)
2819 {
2820 case RCHART('i'):
2821 case RCHART('I'):
2822 tochange = IGNORECASE;
2823 break;
2824
2825 case RCHART('s'):
2826 case RCHART('S'):
2827 tochange = SINGLELINE;
2828 break;
2829
2830 case RCHART('m'):
2831 case RCHART('M'):
2832 tochange = MULTILINE;
2833 break;
2834
2835 case RCHART('g'):
2836 case RCHART('G'):
2837 tochange = GLOBAL;
2838 break;
2839
2840 case RCHART('-'):
2841 bNegative = 1;
2842 break;
2843 }
2844
2845 if(bNegative)
2846 newflags &= ~tochange;
2847 else
2848 newflags |= tochange;
2849
2850 // move to next char
2851 MoveNext();
2852 }
2853
2854 if(curr.ch == RCHART(':') || curr == CHART_INFO(RCHART('('), 1))
2855 {
2856 // skip ':'
2857 if(curr.ch == RCHART(':')) MoveNext();
2858
2859 pElx = BuildAlternative(newflags);
2860 }
2861 else
2862 {
2863 // change parent flags
2864 flags = newflags;
2865
2866 pElx = GetStockElx(STOCKELX_EMPTY);
2867 }
2868 }
2869 break;
2870 }
2871
2872 MoveNext(); // skip ')'
2873
2874 return pElx;
2875 }
2876 else
2877 {
2878 // group and number
2879 CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT));
2880 int nThisBackref = ++ m_nMaxNumber;
2881
2882 // left, center, right
2883 pList->m_elxlist.Push(Keep(new CBracketElx(nThisBackref, flags & RIGHTTOLEFT ? 1 : 0)));
2884 pList->m_elxlist.Push(BuildAlternative(flags));
2885 pList->m_elxlist.Push(Keep(new CBracketElx(nThisBackref, flags & RIGHTTOLEFT ? 0 : 1)));
2886
2887 // for recursive
2888 m_grouplist.Prepare(nThisBackref);
2889 m_grouplist[nThisBackref] = pList;
2890
2891 // right
2892 MoveNext(); // skip ')'
2893
2894 return pList;
2895 }
2896 }
2897
2898 template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildBoundary(int & flags)
2899 {
2900 // char
2901 CHART ch = curr.ch;
2902
2903 // skip
2904 MoveNext();
2905
2906 switch(ch)
2907 {
2908 case RCHART('^'):
2909 return Keep(new CBoundaryElxT <CHART> ((flags & MULTILINE) ? BOUNDARY_LINE_BEGIN : BOUNDARY_FILE_BEGIN));
2910
2911 case RCHART('$'):
2912 return Keep(new CBoundaryElxT <CHART> ((flags & MULTILINE) ? BOUNDARY_LINE_END : BOUNDARY_FILE_END));
2913
2914 case RCHART('b'):
2915 return Keep(new CBoundaryElxT <CHART> (BOUNDARY_WORD_EDGE));
2916
2917 case RCHART('B'):
2918 return Keep(new CBoundaryElxT <CHART> (BOUNDARY_WORD_EDGE, 0));
2919
2920 case RCHART('A'):
2921 return Keep(new CBoundaryElxT <CHART> (BOUNDARY_FILE_BEGIN));
2922
2923 case RCHART('Z'):
2924 return Keep(new CBoundaryElxT <CHART> (BOUNDARY_FILE_END));
2925
2926 case RCHART('G'):
2927 if(flags & GLOBAL)
2928 return Keep(new CGlobalElx());
2929 else
2930 return GetStockElx(STOCKELX_EMPTY);
2931
2932 default:
2933 return GetStockElx(STOCKELX_EMPTY);
2934 }
2935 }
2936
2937 template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildBackref(int & flags)
2938 {
2939 // skip '\\' or '\k' or '\g'
2940 MoveNext();
2941
2942 if(curr.ch == RCHART('<') || curr.ch == RCHART('\''))
2943 {
2944 CHART named_end = curr.ch == RCHART('<') ? RCHART('>') : RCHART('\'');
2945 CBackrefElxT <CHART> * pbackref = (CBackrefElxT <CHART> *)Keep(new CBackrefElxT <CHART> (-1, flags & RIGHTTOLEFT, flags & IGNORECASE));
2946
2947 MoveNext(); // skip '<' or '\''
2948
2949 // save name
2950 CBufferT <CHART> & name = pbackref->m_szNamed;
2951 CBufferT <char> num;
2952
2953 while(curr.ch != RCHART(0) && curr.ch != named_end)
2954 {
2955 name.Append(curr.ch, 1);
2956 num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
2957 MoveNext();
2958 }
2959 MoveNext(); // skip '>' or '\''
2960
2961 // check <num>
2962 unsigned int number;
2963 char * str = num.GetBuffer();
2964
2965 if( ReadDec(str, number) ? ( *str == '\0') : 0 )
2966 {
2967 pbackref->m_nnumber = number;
2968 name.Release();
2969 }
2970 else
2971 {
2972 m_namedbackreflist.Push(pbackref);
2973 }
2974
2975 return pbackref;
2976 }
2977 else
2978 {
2979 unsigned int nbackref = 0;
2980
2981 for(int i=0; i<3; i++)
2982 {
2983 if(curr.ch >= RCHART('0') && curr.ch <= RCHART('9'))
2984 nbackref = nbackref * 10 + (curr.ch - <