Code::Blocks  SVN r11506
sqstdrex.cpp
Go to the documentation of this file.
1 /* see copyright notice in squirrel.h */
2 #include <squirrel.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <setjmp.h>
6 #include "sqstdstring.h"
7 
8 // C::B patch: Fix wrong spelling of UNICODE
9 #ifdef _UNICODE
10 #define scisprint iswprint
11 #else
12 #define scisprint isprint
13 #endif
14 
15 #ifdef _DEBUG
16 #include <stdio.h>
17 
18 static const SQChar *g_nnames[] =
19 {
20  _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"),
21  _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"),
22  _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),
23  _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB")
24 };
25 
26 #endif
27 
28 #define OP_GREEDY (MAX_CHAR+1) // * + ? {n}
29 #define OP_OR (MAX_CHAR+2)
30 #define OP_EXPR (MAX_CHAR+3) //parentesis ()
31 #define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:)
32 #define OP_DOT (MAX_CHAR+5)
33 #define OP_CLASS (MAX_CHAR+6)
34 #define OP_CCLASS (MAX_CHAR+7)
35 #define OP_NCLASS (MAX_CHAR+8) //negates class the [^
36 #define OP_RANGE (MAX_CHAR+9)
37 #define OP_CHAR (MAX_CHAR+10)
38 #define OP_EOL (MAX_CHAR+11)
39 #define OP_BOL (MAX_CHAR+12)
40 #define OP_WB (MAX_CHAR+13)
41 
42 #define SQREX_SYMBOL_ANY_CHAR ('.')
43 #define SQREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
44 #define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
45 #define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
46 #define SQREX_SYMBOL_BRANCH ('|')
47 #define SQREX_SYMBOL_END_OF_STRING ('$')
48 #define SQREX_SYMBOL_BEGINNING_OF_STRING ('^')
49 #define SQREX_SYMBOL_ESCAPE_CHAR ('\\')
50 
51 
52 typedef int SQRexNodeType;
53 
54 typedef struct tagSQRexNode{
56  SQInteger left;
57  SQInteger right;
58  SQInteger next;
59 }SQRexNode;
60 
61 struct SQRex{
62  const SQChar *_eol;
63  const SQChar *_bol;
64  const SQChar *_p;
65  SQInteger _first;
66  SQInteger _op;
68  SQInteger _nallocated;
69  SQInteger _nsize;
70  SQInteger _nsubexpr;
71  SQRexMatch *_matches;
72  SQInteger _currsubexp;
73  void *_jmpbuf;
74  const SQChar **_error;
75 };
76 
77 static SQInteger sqstd_rex_list(SQRex *exp);
78 
79 static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)
80 {
81  SQRexNode n;
82  n.type = type;
83  n.next = n.right = n.left = -1;
84  if(type == OP_EXPR)
85  n.right = exp->_nsubexpr++;
86  if(exp->_nallocated < (exp->_nsize + 1)) {
87  SQInteger oldsize = exp->_nallocated;
88  exp->_nallocated *= 2;
89  exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));
90  }
91  exp->_nodes[exp->_nsize++] = n;
92  SQInteger newid = exp->_nsize - 1;
93  return (SQInteger)newid;
94 }
95 
96 static void sqstd_rex_error(SQRex *exp,const SQChar *error)
97 {
98  if(exp->_error) *exp->_error = error;
99  longjmp(*((jmp_buf*)exp->_jmpbuf),-1);
100 }
101 
102 static void sqstd_rex_expect(SQRex *exp, SQInteger n){
103  if((*exp->_p) != n)
104  sqstd_rex_error(exp, _SC("expected paren"));
105  exp->_p++;
106 }
107 
109 {
110  if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){
111  exp->_p++;
112  switch(*exp->_p) {
113  case 'v': exp->_p++; return '\v';
114  case 'n': exp->_p++; return '\n';
115  case 't': exp->_p++; return '\t';
116  case 'r': exp->_p++; return '\r';
117  case 'f': exp->_p++; return '\f';
118  default: return (*exp->_p++);
119  }
120  } else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));
121  return (*exp->_p++);
122 }
123 
124 static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid)
125 {
126  SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS);
127  exp->_nodes[n].left = classid;
128  return n;
129 }
130 
131 static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass)
132 {
133  SQChar t;
134  if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {
135  exp->_p++;
136  switch(*exp->_p) {
137  case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n');
138  case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t');
139  case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r');
140  case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f');
141  case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v');
142  case 'a': case 'A': case 'w': case 'W': case 's': case 'S':
143  case 'd': case 'D': case 'x': case 'X': case 'c': case 'C':
144  case 'p': case 'P': case 'l': case 'u':
145  {
146  t = *exp->_p; exp->_p++;
147  return sqstd_rex_charclass(exp,t);
148  }
149  case 'b':
150  case 'B':
151  if(!isclass) {
152  SQInteger node = sqstd_rex_newnode(exp,OP_WB);
153  exp->_nodes[node].left = *exp->_p;
154  exp->_p++;
155  return node;
156  } //else default
157  default:
158  t = *exp->_p; exp->_p++;
159  return sqstd_rex_newnode(exp,t);
160  }
161  }
162  else if(!scisprint(*exp->_p)) {
163 
164  sqstd_rex_error(exp,_SC("letter expected"));
165  }
166  t = *exp->_p; exp->_p++;
167  return sqstd_rex_newnode(exp,t);
168 }
169 static SQInteger sqstd_rex_class(SQRex *exp)
170 {
171  SQInteger ret = -1;
172  SQInteger first = -1,chain;
174  ret = sqstd_rex_newnode(exp,OP_NCLASS);
175  exp->_p++;
176  }else ret = sqstd_rex_newnode(exp,OP_CLASS);
177 
178  if(*exp->_p == ']') sqstd_rex_error(exp,_SC("empty class"));
179  chain = ret;
180  while(*exp->_p != ']' && exp->_p != exp->_eol) {
181  if(*exp->_p == '-' && first != -1){
182  SQInteger r;
183  if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range"));
184  r = sqstd_rex_newnode(exp,OP_RANGE);
185  if(exp->_nodes[first].type>*exp->_p) sqstd_rex_error(exp,_SC("invalid range"));
186  if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges"));
187  exp->_nodes[r].left = exp->_nodes[first].type;
188  SQInteger t = sqstd_rex_escapechar(exp);
189  exp->_nodes[r].right = t;
190  exp->_nodes[chain].next = r;
191  chain = r;
192  first = -1;
193  }
194  else{
195  if(first!=-1){
196  SQInteger c = first;
197  exp->_nodes[chain].next = c;
198  chain = c;
199  first = sqstd_rex_charnode(exp,SQTrue);
200  }
201  else{
202  first = sqstd_rex_charnode(exp,SQTrue);
203  }
204  }
205  }
206  if(first!=-1){
207  SQInteger c = first;
208  exp->_nodes[chain].next = c;
209  chain = c;
210  first = -1;
211  }
212  /* hack? */
213  exp->_nodes[ret].left = exp->_nodes[ret].next;
214  exp->_nodes[ret].next = -1;
215  return ret;
216 }
217 
218 static SQInteger sqstd_rex_parsenumber(SQRex *exp)
219 {
220  SQInteger ret = *exp->_p-'0';
221  SQInteger positions = 10;
222  exp->_p++;
223  while(isdigit(*exp->_p)) {
224  ret = ret*10+(*exp->_p++-'0');
225  if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant"));
226  positions *= 10;
227  };
228  return ret;
229 }
230 
231 static SQInteger sqstd_rex_element(SQRex *exp)
232 {
233  SQInteger ret = -1;
234  switch(*exp->_p)
235  {
236  case '(': {
237  SQInteger expr;
238  exp->_p++;
239 
240 
241  if(*exp->_p =='?') {
242  exp->_p++;
243  sqstd_rex_expect(exp,':');
244  expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR);
245  }
246  else
247  expr = sqstd_rex_newnode(exp,OP_EXPR);
248  SQInteger newn = sqstd_rex_list(exp);
249  exp->_nodes[expr].left = newn;
250  ret = expr;
251  sqstd_rex_expect(exp,')');
252  }
253  break;
254  case '[':
255  exp->_p++;
256  ret = sqstd_rex_class(exp);
257  sqstd_rex_expect(exp,']');
258  break;
259  case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break;
260  case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break;
261  default:
262  ret = sqstd_rex_charnode(exp,SQFalse);
263  break;
264  }
265 
266 
267  // C::B patch: Avoid compiler warnings (1) (and below)
268 // SQInteger op;
269  SQBool isgreedy = SQFalse;
270  unsigned short p0 = 0, p1 = 0;
271  switch(*exp->_p){
272  case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
273  case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
274  case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break;
275  case '{':
276  exp->_p++;
277  if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));
278  p0 = (unsigned short)sqstd_rex_parsenumber(exp);
279  /*******************************/
280  switch(*exp->_p) {
281  case '}':
282  p1 = p0; exp->_p++;
283  break;
284  case ',':
285  exp->_p++;
286  p1 = 0xFFFF;
287  if(isdigit(*exp->_p)){
288  p1 = (unsigned short)sqstd_rex_parsenumber(exp);
289  }
290  sqstd_rex_expect(exp,'}');
291  break;
292  default:
293  sqstd_rex_error(exp,_SC(", or } expected"));
294  }
295  /*******************************/
296  isgreedy = SQTrue;
297  break;
298 
299  }
300  if(isgreedy) {
301  SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY);
302  // C::B patch: Avoid compiler warnings (2) (and above)
303 // op = OP_GREEDY;
304  exp->_nodes[nnode].left = ret;
305  exp->_nodes[nnode].right = ((p0)<<16)|p1;
306  ret = nnode;
307  }
308 
309  if((*exp->_p != SQREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) {
310  SQInteger nnode = sqstd_rex_element(exp);
311  exp->_nodes[ret].next = nnode;
312  }
313 
314  return ret;
315 }
316 
317 static SQInteger sqstd_rex_list(SQRex *exp)
318 {
319  SQInteger ret=-1,e;
320  if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) {
321  exp->_p++;
322  ret = sqstd_rex_newnode(exp,OP_BOL);
323  }
324  e = sqstd_rex_element(exp);
325  if(ret != -1) {
326  exp->_nodes[ret].next = e;
327  }
328  else ret = e;
329 
330  if(*exp->_p == SQREX_SYMBOL_BRANCH) {
331  SQInteger temp,tright;
332  exp->_p++;
333  temp = sqstd_rex_newnode(exp,OP_OR);
334  exp->_nodes[temp].left = ret;
335  tright = sqstd_rex_list(exp);
336  exp->_nodes[temp].right = tright;
337  ret = temp;
338  }
339  return ret;
340 }
341 
342 static SQBool sqstd_rex_matchcclass(SQInteger cclass,SQChar c)
343 {
344  switch(cclass) {
345  case 'a': return isalpha(c)?SQTrue:SQFalse;
346  case 'A': return !isalpha(c)?SQTrue:SQFalse;
347  case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse;
348  case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse;
349  case 's': return isspace(c)?SQTrue:SQFalse;
350  case 'S': return !isspace(c)?SQTrue:SQFalse;
351  case 'd': return isdigit(c)?SQTrue:SQFalse;
352  case 'D': return !isdigit(c)?SQTrue:SQFalse;
353  case 'x': return isxdigit(c)?SQTrue:SQFalse;
354  case 'X': return !isxdigit(c)?SQTrue:SQFalse;
355  case 'c': return iscntrl(c)?SQTrue:SQFalse;
356  case 'C': return !iscntrl(c)?SQTrue:SQFalse;
357  case 'p': return ispunct(c)?SQTrue:SQFalse;
358  case 'P': return !ispunct(c)?SQTrue:SQFalse;
359  case 'l': return islower(c)?SQTrue:SQFalse;
360  case 'u': return isupper(c)?SQTrue:SQFalse;
361  }
362  return SQFalse; /*cannot happen*/
363 }
364 
365 static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c)
366 {
367  do {
368  switch(node->type) {
369  case OP_RANGE:
370  if(c >= node->left && c <= node->right) return SQTrue;
371  break;
372  case OP_CCLASS:
373  if(sqstd_rex_matchcclass(node->left,c)) return SQTrue;
374  break;
375  default:
376  if(c == node->type)return SQTrue;
377  }
378  } while((node->next != -1) && (node = &exp->_nodes[node->next]));
379  return SQFalse;
380 }
381 
382 static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next)
383 {
384 
385  SQRexNodeType type = node->type;
386  switch(type) {
387  case OP_GREEDY: {
388  //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;
389  SQRexNode *greedystop = NULL;
390  SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
391  const SQChar *s=str, *good = str;
392 
393  if(node->next != -1) {
394  greedystop = &exp->_nodes[node->next];
395  }
396  else {
397  greedystop = next;
398  }
399 
400  while((nmaches == 0xFFFF || nmaches < p1)) {
401 
402  const SQChar *stop;
403  if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))
404  break;
405  nmaches++;
406  good=s;
407  if(greedystop) {
408  //checks that 0 matches satisfy the expression(if so skips)
409  //if not would always stop(for instance if is a '?')
410  if(greedystop->type != OP_GREEDY ||
411  (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
412  {
413  SQRexNode *gnext = NULL;
414  if(greedystop->next != -1) {
415  gnext = &exp->_nodes[greedystop->next];
416  }else if(next && next->next != -1){
417  gnext = &exp->_nodes[next->next];
418  }
419  stop = sqstd_rex_matchnode(exp,greedystop,s,gnext);
420  if(stop) {
421  //if satisfied stop it
422  if(p0 == p1 && p0 == nmaches) break;
423  else if(nmaches >= p0 && p1 == 0xFFFF) break;
424  else if(nmaches >= p0 && nmaches <= p1) break;
425  }
426  }
427  }
428 
429  if(s >= exp->_eol)
430  break;
431  }
432  if(p0 == p1 && p0 == nmaches) return good;
433  else if(nmaches >= p0 && p1 == 0xFFFF) return good;
434  else if(nmaches >= p0 && nmaches <= p1) return good;
435  return NULL;
436  }
437  case OP_OR: {
438  const SQChar *asd = str;
439  SQRexNode *temp=&exp->_nodes[node->left];
440  while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
441  if(temp->next != -1)
442  temp = &exp->_nodes[temp->next];
443  else
444  return asd;
445  }
446  asd = str;
447  temp = &exp->_nodes[node->right];
448  while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
449  if(temp->next != -1)
450  temp = &exp->_nodes[temp->next];
451  else
452  return asd;
453  }
454  return NULL;
455  break;
456  }
457  case OP_EXPR:
458  case OP_NOCAPEXPR:{
459  SQRexNode *n = &exp->_nodes[node->left];
460  const SQChar *cur = str;
461  SQInteger capture = -1;
462  if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
463  capture = exp->_currsubexp;
464  exp->_matches[capture].begin = cur;
465  exp->_currsubexp++;
466  }
467 
468  do {
469  SQRexNode *subnext = NULL;
470  if(n->next != -1) {
471  subnext = &exp->_nodes[n->next];
472  }else {
473  subnext = next;
474  }
475  if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) {
476  if(capture != -1){
477  exp->_matches[capture].begin = 0;
478  exp->_matches[capture].len = 0;
479  }
480  return NULL;
481  }
482  } while((n->next != -1) && (n = &exp->_nodes[n->next]));
483 
484  if(capture != -1)
485  exp->_matches[capture].len = cur - exp->_matches[capture].begin;
486  return cur;
487  }
488  case OP_WB:
489  // C::B patch: Eliminate compiler warnings
490  if( (str == exp->_bol && !isspace(*str))
491  || ((str == exp->_eol && !isspace(*(str-1))))
492  || ((!isspace(*str) && isspace(*(str+1))))
493  || ((isspace(*str) && !isspace(*(str+1)))) ) {
494  return (node->left == 'b')?str:NULL;
495  }
496  return (node->left == 'b')?NULL:str;
497  case OP_BOL:
498  if(str == exp->_bol) return str;
499  return NULL;
500  case OP_EOL:
501  if(str == exp->_eol) return str;
502  return NULL;
503  case OP_DOT:{
504  // C::B patch: Avoid compiler warnings (1) (and below)
505  ++str;
506  }
507  return str;
508  case OP_NCLASS:
509  case OP_CLASS:
510  if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) {
511  // C::B patch: Avoid compiler warnings (2) (and above/below)
512  ++str;
513  return str;
514  }
515  return NULL;
516  case OP_CCLASS:
517  if(sqstd_rex_matchcclass(node->left,*str)) {
518  // C::B patch: Avoid compiler warnings (3) (and above/below)
519  ++str;
520  return str;
521  }
522  return NULL;
523  default: /* char */
524  if(*str != node->type) return NULL;
525  // C::B patch: Avoid compiler warnings (4) (and above)
526  ++str;
527  return str;
528  }
529  return NULL;
530 }
531 
532 /* public api */
533 SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)
534 {
535  SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));
536  exp->_eol = exp->_bol = NULL;
537  exp->_p = pattern;
538  exp->_nallocated = (SQInteger)scstrlen(pattern) * sizeof(SQChar);
539  exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));
540  exp->_nsize = 0;
541  exp->_matches = 0;
542  exp->_nsubexpr = 0;
543  exp->_first = sqstd_rex_newnode(exp,OP_EXPR);
544  exp->_error = error;
545  exp->_jmpbuf = sq_malloc(sizeof(jmp_buf));
546  if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {
547  SQInteger res = sqstd_rex_list(exp);
548  exp->_nodes[exp->_first].left = res;
549  if(*exp->_p!='\0')
550  sqstd_rex_error(exp,_SC("unexpected character"));
551 #ifdef _DEBUG
552  {
553  SQInteger nsize,i;
554  SQRexNode *t;
555  nsize = exp->_nsize;
556  t = &exp->_nodes[0];
557  scprintf(_SC("\n"));
558  for(i = 0;i < nsize; i++) {
559  if(exp->_nodes[i].type>MAX_CHAR)
560  scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);
561  else
562  scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);
563  scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);
564  }
565  scprintf(_SC("\n"));
566  }
567 #endif
568  exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch));
569  memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch));
570  }
571  else{
572  sqstd_rex_free(exp);
573  return NULL;
574  }
575  return exp;
576 }
577 
579 {
580  if(exp) {
581  if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode));
582  if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf));
583  if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch));
584  sq_free(exp,sizeof(SQRex));
585  }
586 }
587 
588 SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)
589 {
590  const SQChar* res = NULL;
591  exp->_bol = text;
592  exp->_eol = text + scstrlen(text);
593  exp->_currsubexp = 0;
594  res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL);
595  if(res == NULL || res != exp->_eol)
596  return SQFalse;
597  return SQTrue;
598 }
599 
600 SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)
601 {
602  const SQChar *cur = NULL;
603  SQInteger node = exp->_first;
604  if(text_begin >= text_end) return SQFalse;
605  exp->_bol = text_begin;
606  exp->_eol = text_end;
607  do {
608  cur = text_begin;
609  while(node != -1) {
610  exp->_currsubexp = 0;
611  cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL);
612  if(!cur)
613  break;
614  node = exp->_nodes[node].next;
615  }
616  // C::B patch: Avoid compiler warnings
617  ++text_begin;
618  } while(cur == NULL && text_begin != text_end);
619 
620  if(cur == NULL)
621  return SQFalse;
622 
623  --text_begin;
624 
625  if(out_begin) *out_begin = text_begin;
626  if(out_end) *out_end = cur;
627  return SQTrue;
628 }
629 
630 SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end)
631 {
632  return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);
633 }
634 
636 {
637  return exp->_nsubexpr;
638 }
639 
640 SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp)
641 {
642  if( n<0 || n >= exp->_nsubexpr) return SQFalse;
643  *subexp = exp->_matches[n];
644  return SQTrue;
645 }
646 
SQInteger right
Definition: sqstdrex.cpp:57
#define OP_RANGE
Definition: sqstdrex.cpp:36
SQBool sqstd_rex_searchrange(SQRex *exp, const SQChar *text_begin, const SQChar *text_end, const SQChar **out_begin, const SQChar **out_end)
Definition: sqstdrex.cpp:600
#define OP_DOT
Definition: sqstdrex.cpp:32
#define OP_EOL
Definition: sqstdrex.cpp:38
static SQInteger sqstd_rex_list(SQRex *exp)
Definition: sqstdrex.cpp:317
const SQChar ** _error
Definition: sqstdrex.cpp:74
void * sq_malloc(SQUnsignedInteger size)
Definition: sqapi.cpp:1259
static SQInteger sqstd_rex_charnode(SQRex *exp, SQBool isclass)
Definition: sqstdrex.cpp:131
#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE
Definition: sqstdrex.cpp:44
#define OP_WB
Definition: sqstdrex.cpp:40
void sqstd_rex_free(SQRex *exp)
Definition: sqstdrex.cpp:578
SQInteger _nallocated
Definition: sqstdrex.cpp:68
#define scisprint
Definition: sqstdrex.cpp:12
#define OP_BOL
Definition: sqstdrex.cpp:39
static SQInteger sqstd_rex_parsenumber(SQRex *exp)
Definition: sqstdrex.cpp:218
static SQBool sqstd_rex_matchclass(SQRex *exp, SQRexNode *node, SQChar c)
Definition: sqstdrex.cpp:365
static void sqstd_rex_expect(SQRex *exp, SQInteger n)
Definition: sqstdrex.cpp:102
SQInteger _nsubexpr
Definition: sqstdrex.cpp:70
const SQChar * _p
Definition: sqstdrex.cpp:64
#define SQREX_SYMBOL_BEGINNING_OF_STRING
Definition: sqstdrex.cpp:48
static SQInteger sqstd_rex_charclass(SQRex *exp, SQInteger classid)
Definition: sqstdrex.cpp:124
#define OP_EXPR
Definition: sqstdrex.cpp:30
static SQInteger sqstd_rex_class(SQRex *exp)
Definition: sqstdrex.cpp:169
SQInteger left
Definition: sqstdrex.cpp:56
SQRexNodeType type
Definition: sqstdrex.cpp:55
const SQChar * _bol
Definition: sqstdrex.cpp:63
SQBool sqstd_rex_getsubexp(SQRex *exp, SQInteger n, SQRexMatch *subexp)
Definition: sqstdrex.cpp:640
SQInteger _op
Definition: sqstdrex.cpp:66
static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)
Definition: sqstdrex.cpp:79
#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE
Definition: sqstdrex.cpp:45
int SQRexNodeType
Definition: sqstdrex.cpp:52
SQInteger _nsize
Definition: sqstdrex.cpp:69
#define SQREX_SYMBOL_END_OF_STRING
Definition: sqstdrex.cpp:47
#define OP_CCLASS
Definition: sqstdrex.cpp:34
static wxString capture
void * sq_realloc(void *p, SQUnsignedInteger oldsize, SQUnsignedInteger newsize)
Definition: sqapi.cpp:1264
#define OP_GREEDY
Definition: sqstdrex.cpp:28
void * _jmpbuf
Definition: sqstdrex.cpp:73
#define SQREX_SYMBOL_BRANCH
Definition: sqstdrex.cpp:46
#define OP_NCLASS
Definition: sqstdrex.cpp:35
SQRex * sqstd_rex_compile(const SQChar *pattern, const SQChar **error)
Definition: sqstdrex.cpp:533
struct tagSQRexNode SQRexNode
const SQChar * _eol
Definition: sqstdrex.cpp:62
static SQChar sqstd_rex_escapechar(SQRex *exp)
Definition: sqstdrex.cpp:108
#define OP_CLASS
Definition: sqstdrex.cpp:33
static void sqstd_rex_error(SQRex *exp, const SQChar *error)
Definition: sqstdrex.cpp:96
SQRexNode * _nodes
Definition: sqstdrex.cpp:67
char SQChar
void sq_free(void *p, SQUnsignedInteger size)
Definition: sqapi.cpp:1269
#define OP_OR
Definition: sqstdrex.cpp:29
SQBool sqstd_rex_match(SQRex *exp, const SQChar *text)
Definition: sqstdrex.cpp:588
SQInteger next
Definition: sqstdrex.cpp:58
SQInteger _first
Definition: sqstdrex.cpp:65
SQInteger sqstd_rex_getsubexpcount(SQRex *exp)
Definition: sqstdrex.cpp:635
SQInteger _currsubexp
Definition: sqstdrex.cpp:72
static SQBool sqstd_rex_matchcclass(SQInteger cclass, SQChar c)
Definition: sqstdrex.cpp:342
static const SQChar * sqstd_rex_matchnode(SQRex *exp, SQRexNode *node, const SQChar *str, SQRexNode *next)
Definition: sqstdrex.cpp:382
#define SQREX_SYMBOL_ANY_CHAR
Definition: sqstdrex.cpp:42
SQRexMatch * _matches
Definition: sqstdrex.cpp:71
#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE
Definition: sqstdrex.cpp:43
#define NULL
Definition: prefix.cpp:59
static SQInteger sqstd_rex_element(SQRex *exp)
Definition: sqstdrex.cpp:231
#define OP_NOCAPEXPR
Definition: sqstdrex.cpp:31
#define SQREX_SYMBOL_ESCAPE_CHAR
Definition: sqstdrex.cpp:49