/ Check-in [3d6fba62]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Experiments with the regexp.c extension, trying to get it to report the exact substring that matches the RE.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | regexp-span
Files: files | file ages | folders
SHA3-256:3d6fba623af9356f6b02c7ef5f29c4bdeb2f8f0359bc0a3194951846afa336da
User & Date: drh 2018-01-01 16:59:08
Context
2018-01-01
16:59
Experiments with the regexp.c extension, trying to get it to report the exact substring that matches the RE. Leaf check-in: 3d6fba62 user: drh tags: regexp-span
2017-12-29
17:21
Add support for the sqlite_unsupported_offset() SQL function if and only if compiled using -DSQLITE_ENABLE_OFFSET_SQL_FUNC. Use that definition when compiling the command-line shell. check-in: 4f1f1f52 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/misc/regexp.c.

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95



96
97
98
99
100
101
102
...
114
115
116
117
118
119
120







121
122
123
124
125
126
127

128
129
130





131
132

133
134






































































135
136
137
138
139
140














141
142
143
144
145
146
147
...
186
187
188
189
190
191
192







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
...
314
315
316
317
318
319
320
321
322
323



324



325






326
327
328








329
330
331


















332
333
334
335
336
337
338
...
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
...
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
...
610
611
612
613
614
615
616


617
618
619
620
621
622
623
...
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
...
660
661
662
663
664
665
666






667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
...
735
736
737
738
739
740
741






























































742
743
744
745
746
747
748
...
752
753
754
755
756
757
758




759
760

/* The end-of-input character */
#define RE_EOF            0    /* End of input */

/* The NFA is implemented as sequence of opcodes taken from the following
** set.  Each opcode has a single integer argument.
*/
#define RE_OP_MATCH       1    /* Match the one character in the argument */
#define RE_OP_ANY         2    /* Match any one character.  (Implements ".") */
#define RE_OP_ANYSTAR     3    /* Special optimized version of .* */
#define RE_OP_FORK        4    /* Continue to both next and opcode at iArg */
#define RE_OP_GOTO        5    /* Jump to opcode at iArg */
#define RE_OP_ACCEPT      6    /* Halt and indicate a successful match */
#define RE_OP_CC_INC      7    /* Beginning of a [...] character class */
#define RE_OP_CC_EXC      8    /* Beginning of a [^...] character class */
#define RE_OP_CC_VALUE    9    /* Single value in a character class */
#define RE_OP_CC_RANGE   10    /* Range of values in a character class */
#define RE_OP_WORD       11    /* Perl word character [A-Za-z0-9_] */
#define RE_OP_NOTWORD    12    /* Not a perl word character */
#define RE_OP_DIGIT      13    /* digit:  [0-9] */
#define RE_OP_NOTDIGIT   14    /* Not a digit */
#define RE_OP_SPACE      15    /* space:  [ \t\n\r\v\f] */
#define RE_OP_NOTSPACE   16    /* Not a digit */

#define RE_OP_BOUNDARY   17    /* Boundary between word and non-word */




/* Each opcode is a "state" in the NFA */
typedef unsigned short ReStateNumber;

/* Because this is an NFA and not a DFA, multiple states can be active at
** once.  An instance of the following object records all active states in
** the NFA.  The implementation is optimized for the common case where the
................................................................................
  const unsigned char *z;  /* All text */
  int i;                   /* Next byte to read */
  int mx;                  /* EOF when i>=mx */
};

/* A compiled NFA (or an NFA that is in the process of being compiled) is
** an instance of the following object.







*/
typedef struct ReCompiled ReCompiled;
struct ReCompiled {
  ReInput sIn;                /* Regular expression text */
  const char *zErr;           /* Error message to return */
  char *aOp;                  /* Operators for the virtual machine */
  int *aArg;                  /* Arguments to each operator */

  unsigned (*xNextChar)(ReInput*);  /* Next character function */
  unsigned char zInit[12];    /* Initial text to match */
  int nInit;                  /* Number of characters in zInit */





  unsigned nState;            /* Number of entries in aOp[] and aArg[] */
  unsigned nAlloc;            /* Slots allocated for aOp[] and aArg[] */

};







































































/* Add a state to the given state set if it is not already there */
static void re_add_state(ReStateSet *pSet, int newState){
  unsigned i;
  for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
  pSet->aState[pSet->nState++] = (ReStateNumber)newState;
}















/* Extract the next unicode character from *pzIn and return it.  Advance
** *pzIn to the first byte past the end of the character returned.  To
** be clear:  this routine converts utf8 to unicode.  This routine is 
** optimized for the common case where the next character is a single byte.
*/
static unsigned re_next_char(ReInput *p){
................................................................................
  return (c>='0' && c<='9');
}

/* Return true if c is a perl "space" character:  [ \t\r\n\v\f] */
static int re_space_char(int c){
  return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
}








/* Run a compiled regular expression on the zero-terminated input
** string zIn[].  Return true on a match and false if there is no match.
*/
static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
  ReStateSet aStateSet[2], *pThis, *pNext;
  ReStateNumber aSpace[100];
  ReStateNumber *pToFree;
  unsigned int i = 0;
  unsigned int iSwap = 0;
  int c = RE_EOF+1;
  int cPrev = 0;
  int rc = 0;
  ReInput in;

  in.z = zIn;
  in.i = 0;
  in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);

  /* Look for the initial prefix match, if there is one. */
  if( pRe->nInit ){
    unsigned char x = pRe->zInit[0];
    while( in.i+pRe->nInit<=in.mx 
     && (zIn[in.i]!=x ||
         strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
    ){
      in.i++;
    }
    if( in.i+pRe->nInit>in.mx ) return 0;
  }

  if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
    pToFree = 0;
    aStateSet[0].aState = aSpace;
  }else{
    pToFree = sqlite3_malloc( sizeof(ReStateNumber)*2*pRe->nState );
    if( pToFree==0 ) return -1;
    aStateSet[0].aState = pToFree;
  }
  aStateSet[1].aState = &aStateSet[0].aState[pRe->nState];
  pNext = &aStateSet[1];
  pNext->nState = 0;
  re_add_state(pNext, 0);
  while( c!=RE_EOF && pNext->nState>0 ){
    cPrev = c;
    c = pRe->xNextChar(&in);
    pThis = pNext;
    pNext = &aStateSet[iSwap];
    iSwap = 1 - iSwap;
    pNext->nState = 0;
    for(i=0; i<pThis->nState; i++){
      int x = pThis->aState[i];
      switch( pRe->aOp[x] ){
        case RE_OP_MATCH: {
          if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_ANY: {
          re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_WORD: {
          if( re_word_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_NOTWORD: {
          if( !re_word_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_DIGIT: {
          if( re_digit_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_NOTDIGIT: {
          if( !re_digit_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_SPACE: {
          if( re_space_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_NOTSPACE: {
          if( !re_space_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_BOUNDARY: {



          if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1);
          break;
        }
        case RE_OP_ANYSTAR: {
          re_add_state(pNext, x);
          re_add_state(pThis, x+1);
          break;
        }
        case RE_OP_FORK: {
          re_add_state(pThis, x+pRe->aArg[x]);
          re_add_state(pThis, x+1);
          break;
        }
        case RE_OP_GOTO: {
          re_add_state(pThis, x+pRe->aArg[x]);
          break;
        }
        case RE_OP_ACCEPT: {
          rc = 1;
          goto re_match_end;
        }
        case RE_OP_CC_INC:
        case RE_OP_CC_EXC: {
          int j = 1;
          int n = pRe->aArg[x];
          int hit = 0;
          for(j=1; j>0 && j<n; j++){
            if( pRe->aOp[x+j]==RE_OP_CC_VALUE ){
................................................................................
                j = -1;
              }else{
                j++;
              }
            }
          }
          if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
          if( hit ) re_add_state(pNext, x+n);
          break;            
        }



      }



    }






  }
  for(i=0; i<pNext->nState; i++){
    if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; }








  }
re_match_end:
  sqlite3_free(pToFree);


















  return rc;
}

/* Resize the opcode and argument arrays for an RE under construction.
*/
static int re_resize(ReCompiled *p, int N){
  char *aOp;
................................................................................
        zErr = re_subcompile_re(p);
        if( zErr ) return zErr;
        if( rePeek(p)!=')' ) return "unmatched '('";
        p->sIn.i++;
        break;
      }
      case '.': {
        if( rePeek(p)=='*' ){
          re_append(p, RE_OP_ANYSTAR, 0);
          p->sIn.i++;
        }else{ 
          re_append(p, RE_OP_ANY, 0);
        }
        break;
      }
      case '*': {
        if( iPrev<0 ) return "'*' without operand";
        re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1);
        re_append(p, RE_OP_FORK, iPrev - p->nState + 1);
        break;
................................................................................
        re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
        break;
      }
      case '{': {
        int m = 0, n = 0;
        int sz, j;
        if( iPrev<0 ) return "'{m,n}' without operand";
        while( (c=rePeek(p))>='0' && c<='9' ){ m = m*10 + c - '0'; p->sIn.i++; }
        n = m;
        if( c==',' ){
          p->sIn.i++;
          n = 0;
          while( (c=rePeek(p))>='0' && c<='9' ){ n = n*10 + c-'0'; p->sIn.i++; }
        }
        if( c!='}' ) return "unmatched '{'";
        if( n>0 && n<m ) return "n less than m in '{m,n}'";
        p->sIn.i++;
        sz = p->nState - iPrev;
        if( m==0 ){
          if( n==0 ) return "both m and n are zero in '{m,n}'";
................................................................................
** regular expression.  Applications should invoke this routine once
** for every call to re_compile() to avoid memory leaks.
*/
void re_free(ReCompiled *pRe){
  if( pRe ){
    sqlite3_free(pRe->aOp);
    sqlite3_free(pRe->aArg);


    sqlite3_free(pRe);
  }
}

/*
** Compile a textual regular expression in zIn[] into a compiled regular
** expression suitable for us by re_match() and return a pointer to the
................................................................................
  if( re_resize(pRe, 30) ){
    re_free(pRe);
    return "out of memory";
  }
  if( zIn[0]=='^' ){
    zIn++;
  }else{
    re_append(pRe, RE_OP_ANYSTAR, 0);
  }
  pRe->sIn.z = (unsigned char*)zIn;
  pRe->sIn.i = 0;
  pRe->sIn.mx = (int)strlen(zIn);
  zErr = re_subcompile_re(pRe);
  if( zErr ){
    re_free(pRe);
................................................................................
  }else if( pRe->sIn.i>=pRe->sIn.mx ){
    re_append(pRe, RE_OP_ACCEPT, 0);
    *ppRe = pRe;
  }else{
    re_free(pRe);
    return "unrecognized character";
  }







  /* The following is a performance optimization.  If the regex begins with
  ** ".*" (if the input regex lacks an initial "^") and afterwards there are
  ** one or more matching characters, enter those matching characters into
  ** zInit[].  The re_match() routine can then search ahead in the input 
  ** string looking for the initial match without having to run the whole
  ** regex engine over the string.  Do not worry able trying to match
  ** unicode characters beyond plane 0 - those are very rare and this is
  ** just an optimization. */
  if( pRe->aOp[0]==RE_OP_ANYSTAR ){
    for(j=0, i=1; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
      unsigned x = pRe->aArg[i];
      if( x<=127 ){
        pRe->zInit[j++] = (unsigned char)x;
      }else if( x<=0xfff ){
        pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
        pRe->zInit[j++] = 0x80 | (x&0x3f);
      }else if( x<=0xffff ){
................................................................................
  if( zStr!=0 ){
    sqlite3_result_int(context, re_match(pRe, zStr, -1));
  }
  if( setAux ){
    sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
  }
}































































/*
** Invoke this routine to register the regexp() function with the
** SQLite database connection.
*/
#ifdef _WIN32
__declspec(dllexport)
................................................................................
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
                                 re_sql_func, 0, 0);




  return rc;
}







|
|
<
<
<
<
|
|
|
|
|
|
|
|
|
|
>
|
>
>
>







 







>
>
>
>
>
>
>



|



>

<
|
>
>
>
>
>
|
|
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|




>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>





|
|
|
|
|
|
|
|
|
|
|
|
<




|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<



|



|



|



|



|



|



>
>
>
|
<
<
<
|
|
<
|
<
<
<


<
<
<
<
<
<
<
<







 







|


>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
<
<
>
>
>
>
>
>
>
>
|
<
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
|
<







 







|




|







 







>
>







 







|







 







>
>
>
>
>
>









|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>


72
73
74
75
76
77
78
79
80




81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350




351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381



382
383

384



385
386








387
388
389
390
391
392
393
...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425


426
427
428
429
430
431
432
433
434


435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
...
610
611
612
613
614
615
616




617

618
619
620
621
622
623
624
...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
...
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
...
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
...
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
...
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
...
938
939
940
941
942
943
944
945
946
947
948
949
950

/* The end-of-input character */
#define RE_EOF            0    /* End of input */

/* The NFA is implemented as sequence of opcodes taken from the following
** set.  Each opcode has a single integer argument.
*/
#define RE_OP_MATCH       0    /* Match the one character in the argument */
#define RE_OP_ANY         1    /* Match any one character.  (Implements ".") */




#define RE_OP_CC_INC      2    /* Beginning of a [...] character class */
#define RE_OP_CC_EXC      3    /* Beginning of a [^...] character class */
#define RE_OP_CC_VALUE    4    /* Single value in a character class */
#define RE_OP_CC_RANGE    5    /* Range of values in a character class */
#define RE_OP_WORD        6    /* Perl word character [A-Za-z0-9_] */
#define RE_OP_NOTWORD     7    /* Not a perl word character */
#define RE_OP_DIGIT       8    /* digit:  [0-9] */
#define RE_OP_NOTDIGIT    9    /* Not a digit */
#define RE_OP_SPACE      10    /* space:  [ \t\n\r\v\f] */
#define RE_OP_NOTSPACE   11    /* Not a digit */
#define RE_IMMEDIATE     12    /* OPs >= this evaluate immediately */
#define RE_OP_BOUNDARY   12    /* Boundary between word and non-word */
#define RE_OP_FORK       13    /* Continue to both next and opcode at iArg */
#define RE_OP_GOTO       14    /* Jump to opcode at iArg */
#define RE_OP_ACCEPT     15    /* Halt and indicate a successful match */

/* Each opcode is a "state" in the NFA */
typedef unsigned short ReStateNumber;

/* Because this is an NFA and not a DFA, multiple states can be active at
** once.  An instance of the following object records all active states in
** the NFA.  The implementation is optimized for the common case where the
................................................................................
  const unsigned char *z;  /* All text */
  int i;                   /* Next byte to read */
  int mx;                  /* EOF when i>=mx */
};

/* A compiled NFA (or an NFA that is in the process of being compiled) is
** an instance of the following object.
**
** The application must serialize access to this object.  The code here
** is threadsafe, as long as each thread is using its own ReCompiled object.
** But a single ReCompiled object is neither threadsafe nor reentrant.
**
** The iBegin value is the earliest possible start of the match.  The
** true start of the match might be later.
*/
typedef struct ReCompiled ReCompiled;
struct ReCompiled {
  ReInput sIn;                /* Regexp text, or match string text */
  const char *zErr;           /* Error message to return */
  char *aOp;                  /* Operators for the virtual machine */
  int *aArg;                  /* Arguments to each operator */
  ReStateSet a, b;                  /* Used by re_match() */
  unsigned (*xNextChar)(ReInput*);  /* Next character function */

  unsigned char nInit;              /* Number of characters in zInit */
  unsigned char bFlexStart;   /* Input regexp omits the initial "^" */
  unsigned char bKeepSpan;    /* When matching, remember start and end */
  unsigned char bMultiBegin;  /* iBegin might not be accurate */
  unsigned int iBegin;        /* Offset to first character in the match */
  unsigned int iEnd;          /* Offset past the end of last match char */
  unsigned int nState;        /* Number of entries in aOp[] and aArg[] */
  unsigned int nAlloc;        /* Slots allocated for aOp[] and aArg[] */
  unsigned char zInit[12];    /* Initial text to match */
};

#if SQLITE_REGEXP_DEBUG
/************************************************************************
** The following interfaces are used for development and debugging only
** and are commented out for deployment.
*/
#include <stdio.h>
#include <ctype.h>

/* Render one character. */
static char *re_char(int c){
  static char zBuf[20];
  if( isprint(c) && (c==' ' || !isspace(c)) ){
    sqlite3_snprintf(sizeof(zBuf),zBuf,"'%c'",c);
  }else{
    sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",c);
  }
  return zBuf;
}

/*
** Print out a regexp program.
*/
static void re_print(ReCompiled *pRe){
  int i;
  for(i=0; i<pRe->nState; i++){
    printf("%3d ", i);
    switch( pRe->aOp[i] ){
      case RE_OP_MATCH:    printf("MATCH     %s\n", re_char(pRe->aArg[i]));
                           break;
      case RE_OP_ANY:      printf("ANY\n"); break;
      case RE_OP_WORD:     printf("WORD\n"); break;
      case RE_OP_NOTWORD:  printf("NOTWORD\n"); break;
      case RE_OP_DIGIT:    printf("DIGIT\n"); break;
      case RE_OP_NOTDIGIT: printf("NOTDIGIT\n"); break;
      case RE_OP_SPACE:    printf("SPACE\n"); break;
      case RE_OP_NOTSPACE: printf("NOTSPACE\n"); break;
      case RE_OP_BOUNDARY: printf("BOUNDARY\n"); break;
      case RE_OP_FORK:     printf("FORK      %d\n", i+pRe->aArg[i]); break;
      case RE_OP_GOTO:     printf("GOTO      %d\n", i+pRe->aArg[i]); break;
      case RE_OP_ACCEPT:   printf("ACCEPT\n"); break;
      case RE_OP_CC_INC: 
      case RE_OP_CC_EXC: {
        printf("%s\n", pRe->aOp[i]==RE_OP_CC_INC ? "CC_INC" : "CC_EXC");
        int j;
        int n = pRe->aArg[i];
        for(j=1; j>0 && j<n; j++){
          printf("%3d ... %s %s\n", i+j,
           pRe->aOp[i+j]==RE_OP_CC_VALUE ? "VALUE" : "RANGE",
           re_char(pRe->aArg[i+j]));
        }
        i += n-1;
        break;
      }
    }
  }
}
/*
** Print out a ReStateSet
*/
static void restateset_print(ReStateSet *pSet){
  int i;
  for(i=0; i<pSet->nState; i++){
    if( i ) printf(" ");
    printf(" %2d", pSet->aState[i]);
  }
}
/* End of debugging utilities
*****************************************************************************/
#endif /* SQLITE_REGEXP_DEBUG */

/* Add a state to the given state set if it is not already there */
static void re_add_state_to_set(ReStateSet *pSet, int newState){
  unsigned i;
  for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
  pSet->aState[pSet->nState++] = (ReStateNumber)newState;
}

/* Add a state to the appropriate state set.  States for immediate
** evaluation are added into pRe->a.  If another input token is required
** before the state can be evaluated, then it is added to pRe->b.
*/
static void re_add_state(ReCompiled *pRe, int newState){
  ReStateSet *pSet;
  if( pRe->aOp[newState]>=RE_IMMEDIATE ){
    pSet = &pRe->a;
  }else{
    pSet = &pRe->b;
  }
  re_add_state_to_set(pSet, newState);
}

/* Extract the next unicode character from *pzIn and return it.  Advance
** *pzIn to the first byte past the end of the character returned.  To
** be clear:  this routine converts utf8 to unicode.  This routine is 
** optimized for the common case where the next character is a single byte.
*/
static unsigned re_next_char(ReInput *p){
................................................................................
  return (c>='0' && c<='9');
}

/* Return true if c is a perl "space" character:  [ \t\r\n\v\f] */
static int re_space_char(int c){
  return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
}

/* Interchange pRe->a and pRe->b */
static void re_swap(ReCompiled *pRe){
  ReStateSet t = pRe->a;
  pRe->a = pRe->b;
  pRe->b = t;
}

/* Run a compiled regular expression on the zero-terminated input
** string zIn[].  Return true on a match and false if there is no match.
*/
static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
  unsigned int i = 0;
  int c = RE_EOF+1;
  int rc = 0;
  int iIdx = -1;
  int iBegin = -1;
  int iReset = -1;
  ReInput *pIn = &pRe->sIn;

  pIn->z = zIn;
  pIn->i = 0;
  pIn->mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);
  pRe->bMultiBegin = 0;


  /* Look for the initial prefix match, if there is one. */
  if( pRe->nInit ){
    unsigned char x = pRe->zInit[0];
    while( pIn->i+pRe->nInit<=pIn->mx 
     && (zIn[pIn->i]!=x ||
         strncmp((const char*)zIn+pIn->i,
                 (const char*)pRe->zInit,pRe->nInit)!=0)
    ){
      pIn->i++;
    }
    if( pIn->i+pRe->nInit>pIn->mx ) return 0;
  }

re_print(pRe);
printf("INPUT: [%.*s]\n", nIn, zIn);
  pRe->b.nState = 0;
  pRe->a.nState = 0;
  re_add_state(pRe, 0);
  iReset = -1;
  c = 0;
  while(1){
    for(i=0; i<pRe->a.nState; i++){
      int x = pRe->a.aState[i];
printf("%2d,%-5s %d.%d = ", pRe->sIn.i, re_char(c), i, x);
restateset_print(&pRe->a);
printf("  => ");
restateset_print(&pRe->b);
printf("\n");
      switch( pRe->aOp[x] ){
        case RE_OP_MATCH: {
          if( pRe->aArg[x]!=c ) break;
          /* Fall thru */
        }
        case RE_OP_ANY: {
        add_next:
          re_add_state(pRe, x+1);




          break;
        }
        case RE_OP_WORD: {
          if( re_word_char(c) ) goto add_next;
          break;
        }
        case RE_OP_NOTWORD: {
          if( !re_word_char(c) ) goto add_next;
          break;
        }
        case RE_OP_DIGIT: {
          if( re_digit_char(c) ) goto add_next;
          break;
        }
        case RE_OP_NOTDIGIT: {
          if( !re_digit_char(c) ) goto add_next;
          break;
        }
        case RE_OP_SPACE: {
          if( re_space_char(c) ) goto add_next;
          break;
        }
        case RE_OP_NOTSPACE: {
          if( !re_space_char(c) ) goto add_next;
          break;
        }
        case RE_OP_BOUNDARY: {
          int iCur = pIn->i;
          int cNext = pRe->xNextChar(pIn);
          pIn->i = iCur;
          if( re_word_char(c)!=re_word_char(cNext) ){



            if( iReset>=0 ) goto add_next;
            re_add_state_to_set(&pRe->b, x);

          }



          break;
        }








        case RE_OP_CC_INC:
        case RE_OP_CC_EXC: {
          int j = 1;
          int n = pRe->aArg[x];
          int hit = 0;
          for(j=1; j>0 && j<n; j++){
            if( pRe->aOp[x+j]==RE_OP_CC_VALUE ){
................................................................................
                j = -1;
              }else{
                j++;
              }
            }
          }
          if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
          if( hit ) re_add_state(pRe, x+n);
          break;            
        }
        case RE_OP_FORK: {
          re_add_state(pRe, x+1);
          /* Fall thru */
        }
        case RE_OP_GOTO: {
          re_add_state(pRe, x+pRe->aArg[x]);
          break;
        }
        case RE_OP_ACCEPT: {
          if( !pRe->bKeepSpan ) return 1;
          pRe->iEnd = pIn->i;
printf("ACCEPT %d\n", pIn->i);
          rc = 1;
          break;
        }


      } /* End of switch( pRe->aOp[x] ) */
    } /* End of loop over states in pRe->a.aState[] */
    if( iReset<0 ){
      if( pRe->bFlexStart ){
        iReset = pRe->b.nState;
        memcpy(pRe->a.aState, pRe->b.aState, iReset*sizeof(ReStateNumber));
      }else{
        iReset = 0;
      }


printf("iReset=%d\n", iReset);
    }else if( c==RE_EOF || pRe->b.nState==0 ){
      break;
    }else if( pRe->b.nState>iReset ){
      if( iBegin<0 ){
        iBegin = iIdx;
printf("Begin at %d\n", iIdx);
      }else{
        pRe->bMultiBegin = 1;
printf("Another possible beginning: %d\n", iIdx);
      }
    }
    re_swap(pRe);
    pRe->b.nState = iReset;
    iIdx = pIn->i;
    c = pRe->xNextChar(pIn);
  }
  pRe->iBegin = iBegin;
  return rc;
}

/* Resize the opcode and argument arrays for an RE under construction.
*/
static int re_resize(ReCompiled *p, int N){
  char *aOp;
................................................................................
        zErr = re_subcompile_re(p);
        if( zErr ) return zErr;
        if( rePeek(p)!=')' ) return "unmatched '('";
        p->sIn.i++;
        break;
      }
      case '.': {




        re_append(p, RE_OP_ANY, 0);

        break;
      }
      case '*': {
        if( iPrev<0 ) return "'*' without operand";
        re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1);
        re_append(p, RE_OP_FORK, iPrev - p->nState + 1);
        break;
................................................................................
        re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
        break;
      }
      case '{': {
        int m = 0, n = 0;
        int sz, j;
        if( iPrev<0 ) return "'{m,n}' without operand";
        while( (c=rePeek(p))>='0' && c<='9' ){ m = m*10 + c - '0';p->sIn.i++; }
        n = m;
        if( c==',' ){
          p->sIn.i++;
          n = 0;
          while( (c=rePeek(p))>='0' && c<='9' ){ n = n*10 + c-'0';p->sIn.i++; }
        }
        if( c!='}' ) return "unmatched '{'";
        if( n>0 && n<m ) return "n less than m in '{m,n}'";
        p->sIn.i++;
        sz = p->nState - iPrev;
        if( m==0 ){
          if( n==0 ) return "both m and n are zero in '{m,n}'";
................................................................................
** regular expression.  Applications should invoke this routine once
** for every call to re_compile() to avoid memory leaks.
*/
void re_free(ReCompiled *pRe){
  if( pRe ){
    sqlite3_free(pRe->aOp);
    sqlite3_free(pRe->aArg);
    sqlite3_free(pRe->a.aState);
    sqlite3_free(pRe->b.aState);
    sqlite3_free(pRe);
  }
}

/*
** Compile a textual regular expression in zIn[] into a compiled regular
** expression suitable for us by re_match() and return a pointer to the
................................................................................
  if( re_resize(pRe, 30) ){
    re_free(pRe);
    return "out of memory";
  }
  if( zIn[0]=='^' ){
    zIn++;
  }else{
    pRe->bFlexStart = 1;
  }
  pRe->sIn.z = (unsigned char*)zIn;
  pRe->sIn.i = 0;
  pRe->sIn.mx = (int)strlen(zIn);
  zErr = re_subcompile_re(pRe);
  if( zErr ){
    re_free(pRe);
................................................................................
  }else if( pRe->sIn.i>=pRe->sIn.mx ){
    re_append(pRe, RE_OP_ACCEPT, 0);
    *ppRe = pRe;
  }else{
    re_free(pRe);
    return "unrecognized character";
  }
  pRe->a.aState = sqlite3_malloc64( sizeof(pRe->a.aState[0])*pRe->nState );
  pRe->b.aState = sqlite3_malloc64( sizeof(pRe->b.aState[0])*pRe->nState );
  if( pRe->a.aState==0 || pRe->b.aState==0 ){
    re_free(pRe);
    return "out of memory";
  }

  /* The following is a performance optimization.  If the regex begins with
  ** ".*" (if the input regex lacks an initial "^") and afterwards there are
  ** one or more matching characters, enter those matching characters into
  ** zInit[].  The re_match() routine can then search ahead in the input 
  ** string looking for the initial match without having to run the whole
  ** regex engine over the string.  Do not worry able trying to match
  ** unicode characters beyond plane 0 - those are very rare and this is
  ** just an optimization. */
  if( pRe->bFlexStart && !noCase ){
    for(j=0, i=0; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
      unsigned x = pRe->aArg[i];
      if( x<=127 ){
        pRe->zInit[j++] = (unsigned char)x;
      }else if( x<=0xfff ){
        pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
        pRe->zInit[j++] = 0x80 | (x&0x3f);
      }else if( x<=0xffff ){
................................................................................
  if( zStr!=0 ){
    sqlite3_result_int(context, re_match(pRe, zStr, -1));
  }
  if( setAux ){
    sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
  }
}

/*
** Implementation of the regexp_test1() SQL function.
**
**         regexp_test1(PATTERN, STRING)
**
** Return the part of STRING that matches PATTERN.  Or return NULL
** if there is no match.
*/
static void re_test1_func(
  sqlite3_context *context, 
  int argc, 
  sqlite3_value **argv
){
  ReCompiled *pRe;          /* Compiled regular expression */
  const char *zPattern;     /* The regular expression */
  const unsigned char *zStr;/* String being searched */
  const char *zErr;         /* Compile error message */
  int setAux = 0;           /* True to invoke sqlite3_set_auxdata() */
  int rc;

  pRe = sqlite3_get_auxdata(context, 0);
  if( pRe==0 ){
    zPattern = (const char*)sqlite3_value_text(argv[0]);
    if( zPattern==0 ) return;
    zErr = re_compile(&pRe, zPattern, 0);
    if( zErr ){
      re_free(pRe);
      sqlite3_result_error(context, zErr, -1);
      return;
    }
    if( pRe==0 ){
      sqlite3_result_error_nomem(context);
      return;
    }
    setAux = 1;
  }
  zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
  if( zStr!=0 ){
    int iBegin, iEnd;
    pRe->bKeepSpan = 1;
    rc = re_match(pRe, zStr, -1);
    if( !rc ) goto re_test1_end;
    iBegin = pRe->iBegin;
    iEnd = pRe->iEnd;
    if( pRe->bMultiBegin ){
      pRe->bKeepSpan = 0;
      while( re_match(pRe, zStr+iBegin, iEnd-iBegin)==0 ){
        if( zStr[++iBegin]>=0xc0 ){
          while( (zStr[iBegin]&0xc0)==0x80 ) iBegin++;
        }
        if( iBegin>=iEnd ) goto re_test1_end;
      }
    }
    sqlite3_result_text(context, (const char*)zStr+iBegin,
                        iEnd - iBegin, SQLITE_TRANSIENT);
  }
re_test1_end:
  if( setAux ){
    sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
  }
}

/*
** Invoke this routine to register the regexp() function with the
** SQLite database connection.
*/
#ifdef _WIN32
__declspec(dllexport)
................................................................................
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
                                 re_sql_func, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "re_test1", 2, SQLITE_UTF8, 0,
                                 re_test1_func, 0, 0);
  }
  return rc;
}