/[pcre]/code/trunk/pcre_jit_compile.c
ViewVC logotype

Diff of /code/trunk/pcre_jit_compile.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1300 by zherczeg, Mon Mar 25 12:34:26 2013 UTC revision 1310 by zherczeg, Sat Apr 6 06:51:09 2013 UTC
# Line 313  typedef struct compiler_common { Line 313  typedef struct compiler_common {
313    /* First byte code. */    /* First byte code. */
314    pcre_uchar *start;    pcre_uchar *start;
315    /* Maps private data offset to each opcode. */    /* Maps private data offset to each opcode. */
316    int *private_data_ptrs;    sljit_si *private_data_ptrs;
317    /* Tells whether the capturing bracket is optimized. */    /* Tells whether the capturing bracket is optimized. */
318    pcre_uint8 *optimized_cbracket;    pcre_uint8 *optimized_cbracket;
319    /* Tells whether the starting offset is a target of then. */    /* Tells whether the starting offset is a target of then. */
# Line 356  typedef struct compiler_common { Line 356  typedef struct compiler_common {
356    BOOL has_then;    BOOL has_then;
357    /* Needs to know the start position anytime. */    /* Needs to know the start position anytime. */
358    BOOL needs_start_ptr;    BOOL needs_start_ptr;
359    /* Currently in recurse. */    /* Currently in recurse or negative assert. */
360    BOOL local_exit;    BOOL local_exit;
361    /* Currently in assert. */    /* Currently in a positive assert. */
362    int then_local_exit;    BOOL positive_assert;
363    /* Newline control. */    /* Newline control. */
364    int nltype;    int nltype;
365    int newline;    int newline;
# Line 384  typedef struct compiler_common { Line 384  typedef struct compiler_common {
384    recurse_entry *currententry;    recurse_entry *currententry;
385    jump_list *partialmatch;    jump_list *partialmatch;
386    jump_list *quit;    jump_list *quit;
387    jump_list *then_quit;    jump_list *positive_assert_quit;
388    jump_list *forced_quit;    jump_list *forced_quit;
389    jump_list *accept;    jump_list *accept;
390    jump_list *calllimit;    jump_list *calllimit;
# Line 534  return cc; Line 534  return cc;
534    
535  /* Functions whose might need modification for all new supported opcodes:  /* Functions whose might need modification for all new supported opcodes:
536   next_opcode   next_opcode
537   get_private_data_length   check_opcode_types
538   set_private_data_ptrs   set_private_data_ptrs
539   get_framesize   get_framesize
540   init_frame   init_frame
# Line 733  switch(*cc) Line 733  switch(*cc)
733    }    }
734  }  }
735    
736  #define CASE_ITERATOR_PRIVATE_DATA_1 \  static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
     case OP_MINSTAR: \  
     case OP_MINPLUS: \  
     case OP_QUERY: \  
     case OP_MINQUERY: \  
     case OP_MINSTARI: \  
     case OP_MINPLUSI: \  
     case OP_QUERYI: \  
     case OP_MINQUERYI: \  
     case OP_NOTMINSTAR: \  
     case OP_NOTMINPLUS: \  
     case OP_NOTQUERY: \  
     case OP_NOTMINQUERY: \  
     case OP_NOTMINSTARI: \  
     case OP_NOTMINPLUSI: \  
     case OP_NOTQUERYI: \  
     case OP_NOTMINQUERYI:  
   
 #define CASE_ITERATOR_PRIVATE_DATA_2A \  
     case OP_STAR: \  
     case OP_PLUS: \  
     case OP_STARI: \  
     case OP_PLUSI: \  
     case OP_NOTSTAR: \  
     case OP_NOTPLUS: \  
     case OP_NOTSTARI: \  
     case OP_NOTPLUSI:  
   
 #define CASE_ITERATOR_PRIVATE_DATA_2B \  
     case OP_UPTO: \  
     case OP_MINUPTO: \  
     case OP_UPTOI: \  
     case OP_MINUPTOI: \  
     case OP_NOTUPTO: \  
     case OP_NOTMINUPTO: \  
     case OP_NOTUPTOI: \  
     case OP_NOTMINUPTOI:  
   
 #define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \  
     case OP_TYPEMINSTAR: \  
     case OP_TYPEMINPLUS: \  
     case OP_TYPEQUERY: \  
     case OP_TYPEMINQUERY:  
   
 #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \  
     case OP_TYPESTAR: \  
     case OP_TYPEPLUS:  
   
 #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \  
     case OP_TYPEUPTO: \  
     case OP_TYPEMINUPTO:  
   
 static int get_class_iterator_size(pcre_uchar *cc)  
 {  
 switch(*cc)  
   {  
   case OP_CRSTAR:  
   case OP_CRPLUS:  
   return 2;  
   
   case OP_CRMINSTAR:  
   case OP_CRMINPLUS:  
   case OP_CRQUERY:  
   case OP_CRMINQUERY:  
   return 1;  
   
   case OP_CRRANGE:  
   case OP_CRMINRANGE:  
   if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE))  
     return 0;  
   return 2;  
   
   default:  
   return 0;  
   }  
 }  
   
 static int get_private_data_length(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)  
737  {  {
 int private_data_length = 0;  
 pcre_uchar *alternative;  
738  pcre_uchar *name;  pcre_uchar *name;
739  pcre_uchar *end = NULL;  pcre_uchar *name2;
740  int space, size, i;  unsigned int cbra_index;
741  pcre_uint32 bracketlen;  int i;
742    
743  /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */  /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
744  while (cc < ccend)  while (cc < ccend)
745    {    {
   space = 0;  
   size = 0;  
   bracketlen = 0;  
746    switch(*cc)    switch(*cc)
747      {      {
748      case OP_SET_SOM:      case OP_SET_SOM:
# Line 838  while (cc < ccend) Line 756  while (cc < ccend)
756      cc += 1 + IMM2_SIZE;      cc += 1 + IMM2_SIZE;
757      break;      break;
758    
     case OP_ASSERT:  
     case OP_ASSERT_NOT:  
     case OP_ASSERTBACK:  
     case OP_ASSERTBACK_NOT:  
     case OP_ONCE:  
     case OP_ONCE_NC:  
     case OP_BRAPOS:  
     case OP_SBRA:  
     case OP_SBRAPOS:  
     private_data_length += sizeof(sljit_sw);  
     bracketlen = 1 + LINK_SIZE;  
     break;  
   
759      case OP_CBRAPOS:      case OP_CBRAPOS:
760      case OP_SCBRAPOS:      case OP_SCBRAPOS:
     private_data_length += sizeof(sljit_sw);  
761      common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;      common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;
762      bracketlen = 1 + LINK_SIZE + IMM2_SIZE;      cc += 1 + LINK_SIZE + IMM2_SIZE;
763      break;      break;
764    
765      case OP_COND:      case OP_COND:
# Line 863  while (cc < ccend) Line 767  while (cc < ccend)
767      /* Only AUTO_CALLOUT can insert this opcode. We do      /* Only AUTO_CALLOUT can insert this opcode. We do
768         not intend to support this case. */         not intend to support this case. */
769      if (cc[1 + LINK_SIZE] == OP_CALLOUT)      if (cc[1 + LINK_SIZE] == OP_CALLOUT)
770        return -1;        return FALSE;
771        cc += 1 + LINK_SIZE;
     if (*cc == OP_COND)  
       {  
       /* Might be a hidden SCOND. */  
       alternative = cc + GET(cc, 1);  
       if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)  
         private_data_length += sizeof(sljit_sw);  
       }  
     else  
       private_data_length += sizeof(sljit_sw);  
     bracketlen = 1 + LINK_SIZE;  
772      break;      break;
773    
774      case OP_CREF:      case OP_CREF:
# Line 884  while (cc < ccend) Line 778  while (cc < ccend)
778      break;      break;
779    
780      case OP_NCREF:      case OP_NCREF:
781      bracketlen = GET2(cc, 1);      cbra_index = GET2(cc, 1);
782      name = (pcre_uchar *)common->name_table;      name = (pcre_uchar *)common->name_table;
783      alternative = name;      name2 = name;
784      for (i = 0; i < common->name_count; i++)      for (i = 0; i < common->name_count; i++)
785        {        {
786        if (GET2(name, 0) == bracketlen) break;        if (GET2(name, 0) == cbra_index) break;
787        name += common->name_entry_size;        name += common->name_entry_size;
788        }        }
789      SLJIT_ASSERT(i != common->name_count);      SLJIT_ASSERT(i != common->name_count);
790    
791      for (i = 0; i < common->name_count; i++)      for (i = 0; i < common->name_count; i++)
792        {        {
793        if (STRCMP_UC_UC(alternative + IMM2_SIZE, name + IMM2_SIZE) == 0)        if (STRCMP_UC_UC(name2 + IMM2_SIZE, name + IMM2_SIZE) == 0)
794          common->optimized_cbracket[GET2(alternative, 0)] = 0;          common->optimized_cbracket[GET2(name2, 0)] = 0;
795        alternative += common->name_entry_size;        name2 += common->name_entry_size;
796        }        }
     bracketlen = 0;  
797      cc += 1 + IMM2_SIZE;      cc += 1 + IMM2_SIZE;
798      break;      break;
799    
     case OP_BRA:  
     bracketlen = 1 + LINK_SIZE;  
     break;  
   
     case OP_CBRA:  
     case OP_SCBRA:  
     bracketlen = 1 + LINK_SIZE + IMM2_SIZE;  
     break;  
   
     CASE_ITERATOR_PRIVATE_DATA_1  
     space = 1;  
     size = -2;  
     break;  
   
     CASE_ITERATOR_PRIVATE_DATA_2A  
     space = 2;  
     size = -2;  
     break;  
   
     CASE_ITERATOR_PRIVATE_DATA_2B  
     space = 2;  
     size = -(2 + IMM2_SIZE);  
     break;  
   
     CASE_ITERATOR_TYPE_PRIVATE_DATA_1  
     space = 1;  
     size = 1;  
     break;  
   
     CASE_ITERATOR_TYPE_PRIVATE_DATA_2A  
     if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI)  
       space = 2;  
     size = 1;  
     break;  
   
     CASE_ITERATOR_TYPE_PRIVATE_DATA_2B  
     if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI)  
       space = 2;  
     size = 1 + IMM2_SIZE;  
     break;  
   
     case OP_CLASS:  
     case OP_NCLASS:  
     size += 1 + 32 / sizeof(pcre_uchar);  
     space = get_class_iterator_size(cc + size);  
     break;  
   
 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8  
     case OP_XCLASS:  
     size = GET(cc, 1);  
     space = get_class_iterator_size(cc + size);  
     break;  
 #endif  
   
800      case OP_RECURSE:      case OP_RECURSE:
801      /* Set its value only once. */      /* Set its value only once. */
802      if (common->recursive_head_ptr == 0)      if (common->recursive_head_ptr == 0)
# Line 1015  while (cc < ccend) Line 854  while (cc < ccend)
854      default:      default:
855      cc = next_opcode(common, cc);      cc = next_opcode(common, cc);
856      if (cc == NULL)      if (cc == NULL)
857        return -1;        return FALSE;
858      break;      break;
859      }      }
860      }
861    return TRUE;
862    }
863    
864    if (space > 0 && cc >= end)  static int get_class_iterator_size(pcre_uchar *cc)
865      private_data_length += sizeof(sljit_sw) * space;  {
866    switch(*cc)
867      {
868      case OP_CRSTAR:
869      case OP_CRPLUS:
870      return 2;
871    
872    if (size != 0)    case OP_CRMINSTAR:
873      case OP_CRMINPLUS:
874      case OP_CRQUERY:
875      case OP_CRMINQUERY:
876      return 1;
877    
878      case OP_CRRANGE:
879      case OP_CRMINRANGE:
880      if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE))
881        return 0;
882      return 2;
883    
884      default:
885      return 0;
886      }
887    }
888    
889    static BOOL detect_repeat(compiler_common *common, pcre_uchar *begin)
890    {
891    pcre_uchar *end = bracketend(begin);
892    pcre_uchar *next;
893    pcre_uchar *next_end;
894    pcre_uchar *max_end;
895    pcre_uchar type;
896    sljit_sw length = end - begin;
897    int min, max, i;
898    
899    /* Detect fixed iterations first. */
900    if (end[-(1 + LINK_SIZE)] != OP_KET)
901      return FALSE;
902    
903    /* Already detected repeat. */
904    if (common->private_data_ptrs[end - common->start - LINK_SIZE] != 0)
905      return TRUE;
906    
907    next = end;
908    min = 1;
909    while (1)
910      {
911      if (*next != *begin)
912        break;
913      next_end = bracketend(next);
914      if (next_end - next != length || memcmp(begin, next, IN_UCHARS(length)) != 0)
915        break;
916      next = next_end;
917      min++;
918      }
919    
920    if (min == 2)
921      return FALSE;
922    
923    max = 0;
924    max_end = next;
925    if (*next == OP_BRAZERO || *next == OP_BRAMINZERO)
926      {
927      type = *next;
928      while (1)
929      {      {
930      if (size < 0)      if (next[0] != type || next[1] != OP_BRA || next[2 + LINK_SIZE] != *begin)
931        {        break;
932        cc += -size;      next_end = bracketend(next + 2 + LINK_SIZE);
933  #ifdef SUPPORT_UTF      if (next_end - next != (length + 2 + LINK_SIZE) || memcmp(begin, next + 2 + LINK_SIZE, IN_UCHARS(length)) != 0)
934        if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);        break;
935  #endif      next = next_end;
936        }      max++;
     else  
       cc += size;  
937      }      }
938    
939    if (bracketlen != 0)    if (next[0] == type && next[1] == *begin && max >= 1)
940      {      {
941      if (cc >= end)      next_end = bracketend(next + 1);
942        if (next_end - next == (length + 1) && memcmp(begin, next + 1, IN_UCHARS(length)) == 0)
943        {        {
944        end = bracketend(cc);        for (i = 0; i < max; i++, next_end += 1 + LINK_SIZE)
945        if (end[-1 - LINK_SIZE] == OP_KET)          if (*next_end != OP_KET)
946          end = NULL;            break;
947    
948          if (i == max)
949            {
950            common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end;
951            common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO;
952            /* +2 the original and the last. */
953            common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2;
954            if (min == 1)
955              return TRUE;
956            min--;
957            max_end -= (1 + LINK_SIZE) + GET(max_end, -LINK_SIZE);
958            }
959        }        }
     cc += bracketlen;  
960      }      }
961    }    }
962  return private_data_length;  
963    if (min >= 3)
964      {
965      common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end;
966      common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT;
967      common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min;
968      return TRUE;
969      }
970    
971    return FALSE;
972  }  }
973    
974  static void set_private_data_ptrs(compiler_common *common, int private_data_ptr, pcre_uchar *ccend)  #define CASE_ITERATOR_PRIVATE_DATA_1 \
975        case OP_MINSTAR: \
976        case OP_MINPLUS: \
977        case OP_QUERY: \
978        case OP_MINQUERY: \
979        case OP_MINSTARI: \
980        case OP_MINPLUSI: \
981        case OP_QUERYI: \
982        case OP_MINQUERYI: \
983        case OP_NOTMINSTAR: \
984        case OP_NOTMINPLUS: \
985        case OP_NOTQUERY: \
986        case OP_NOTMINQUERY: \
987        case OP_NOTMINSTARI: \
988        case OP_NOTMINPLUSI: \
989        case OP_NOTQUERYI: \
990        case OP_NOTMINQUERYI:
991    
992    #define CASE_ITERATOR_PRIVATE_DATA_2A \
993        case OP_STAR: \
994        case OP_PLUS: \
995        case OP_STARI: \
996        case OP_PLUSI: \
997        case OP_NOTSTAR: \
998        case OP_NOTPLUS: \
999        case OP_NOTSTARI: \
1000        case OP_NOTPLUSI:
1001    
1002    #define CASE_ITERATOR_PRIVATE_DATA_2B \
1003        case OP_UPTO: \
1004        case OP_MINUPTO: \
1005        case OP_UPTOI: \
1006        case OP_MINUPTOI: \
1007        case OP_NOTUPTO: \
1008        case OP_NOTMINUPTO: \
1009        case OP_NOTUPTOI: \
1010        case OP_NOTMINUPTOI:
1011    
1012    #define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \
1013        case OP_TYPEMINSTAR: \
1014        case OP_TYPEMINPLUS: \
1015        case OP_TYPEQUERY: \
1016        case OP_TYPEMINQUERY:
1017    
1018    #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \
1019        case OP_TYPESTAR: \
1020        case OP_TYPEPLUS:
1021    
1022    #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \
1023        case OP_TYPEUPTO: \
1024        case OP_TYPEMINUPTO:
1025    
1026    static void set_private_data_ptrs(compiler_common *common, int *private_data_start, pcre_uchar *ccend)
1027  {  {
1028  pcre_uchar *cc = common->start;  pcre_uchar *cc = common->start;
1029  pcre_uchar *alternative;  pcre_uchar *alternative;
1030  pcre_uchar *end = NULL;  pcre_uchar *end = NULL;
1031    int private_data_ptr = *private_data_start;
1032  int space, size, bracketlen;  int space, size, bracketlen;
1033    
1034  while (cc < ccend)  while (cc < ccend)
# Line 1061  while (cc < ccend) Line 1036  while (cc < ccend)
1036    space = 0;    space = 0;
1037    size = 0;    size = 0;
1038    bracketlen = 0;    bracketlen = 0;
1039      if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE)
1040        return;
1041    
1042      if (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)
1043        if (detect_repeat(common, cc))
1044          {
1045          /* These brackets are converted to repeats, so no global
1046          based single character repeat is allowed. */
1047          if (cc >= end)
1048            end = bracketend(cc);
1049          }
1050    
1051    switch(*cc)    switch(*cc)
1052      {      {
1053        case OP_KET:
1054        if (common->private_data_ptrs[cc + 1 - common->start] != 0)
1055          {
1056          common->private_data_ptrs[cc - common->start] = private_data_ptr;
1057          private_data_ptr += sizeof(sljit_sw);
1058          cc += common->private_data_ptrs[cc + 1 - common->start];
1059          }
1060        cc += 1 + LINK_SIZE;
1061        break;
1062    
1063      case OP_ASSERT:      case OP_ASSERT:
1064      case OP_ASSERT_NOT:      case OP_ASSERT_NOT:
1065      case OP_ASSERTBACK:      case OP_ASSERTBACK:
# Line 1156  while (cc < ccend) Line 1153  while (cc < ccend)
1153      break;      break;
1154      }      }
1155    
1156      /* Character iterators, which are not inside a repeated bracket,
1157         gets a private slot instead of allocating it on the stack. */
1158    if (space > 0 && cc >= end)    if (space > 0 && cc >= end)
1159      {      {
1160      common->private_data_ptrs[cc - common->start] = private_data_ptr;      common->private_data_ptrs[cc - common->start] = private_data_ptr;
# Line 1186  while (cc < ccend) Line 1185  while (cc < ccend)
1185      cc += bracketlen;      cc += bracketlen;
1186      }      }
1187    }    }
1188    *private_data_start = private_data_ptr;
1189  }  }
1190    
1191  /* Returns with a frame_types (always < 0) if no need for frame. */  /* Returns with a frame_types (always < 0) if no need for frame. */
# Line 1497  while (cc < ccend) Line 1497  while (cc < ccend)
1497    size = 0;    size = 0;
1498    switch(*cc)    switch(*cc)
1499      {      {
1500        case OP_KET:
1501        if (PRIVATE_DATA(cc) != 0)
1502          private_data_length++;
1503        cc += 1 + LINK_SIZE;
1504        break;
1505    
1506      case OP_ASSERT:      case OP_ASSERT:
1507      case OP_ASSERT_NOT:      case OP_ASSERT_NOT:
1508      case OP_ASSERTBACK:      case OP_ASSERTBACK:
# Line 1665  do Line 1671  do
1671    
1672      switch(*cc)      switch(*cc)
1673        {        {
1674          case OP_KET:
1675          if (PRIVATE_DATA(cc) != 0)
1676            {
1677            count = 1;
1678            srcw[0] = PRIVATE_DATA(cc);
1679            }
1680          cc += 1 + LINK_SIZE;
1681          break;
1682    
1683        case OP_ASSERT:        case OP_ASSERT:
1684        case OP_ASSERT_NOT:        case OP_ASSERT_NOT:
1685        case OP_ASSERTBACK:        case OP_ASSERTBACK:
# Line 5503  jump_list *tmp = NULL; Line 5518  jump_list *tmp = NULL;
5518  jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;  jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;
5519  jump_list **found;  jump_list **found;
5520  /* Saving previous accept variables. */  /* Saving previous accept variables. */
5521  int save_then_local_exit = common->then_local_exit;  BOOL save_local_exit = common->local_exit;
5522    BOOL save_positive_assert = common->positive_assert;
5523  then_trap_backtrack *save_then_trap = common->then_trap;  then_trap_backtrack *save_then_trap = common->then_trap;
5524    struct sljit_label *save_quit_label = common->quit_label;
5525  struct sljit_label *save_accept_label = common->accept_label;  struct sljit_label *save_accept_label = common->accept_label;
5526  jump_list *save_then_quit = common->then_quit;  jump_list *save_quit = common->quit;
5527    jump_list *save_positive_assert_quit = common->positive_assert_quit;
5528  jump_list *save_accept = common->accept;  jump_list *save_accept = common->accept;
5529  struct sljit_jump *jump;  struct sljit_jump *jump;
5530  struct sljit_jump *brajump = NULL;  struct sljit_jump *brajump = NULL;
# Line 5576  else Line 5594  else
5594    }    }
5595    
5596  memset(&altbacktrack, 0, sizeof(backtrack_common));  memset(&altbacktrack, 0, sizeof(backtrack_common));
5597  common->then_local_exit = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? 1 : -1;  if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
5598  common->then_quit = NULL;    {
5599      /* Negative assert is stronger than positive assert. */
5600      common->local_exit = TRUE;
5601      common->quit_label = NULL;
5602      common->quit = NULL;
5603      common->positive_assert = FALSE;
5604      }
5605    else
5606      common->positive_assert = TRUE;
5607    common->positive_assert_quit = NULL;
5608    
5609  while (1)  while (1)
5610    {    {
5611    common->accept_label = NULL;    common->accept_label = NULL;
# Line 5592  while (1) Line 5620  while (1)
5620    compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);    compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);
5621    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
5622      {      {
5623      common->then_local_exit = save_then_local_exit;      if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
5624          {
5625          common->local_exit = save_local_exit;
5626          common->quit_label = save_quit_label;
5627          common->quit = save_quit;
5628          }
5629        common->positive_assert = save_positive_assert;
5630      common->then_trap = save_then_trap;      common->then_trap = save_then_trap;
5631      common->accept_label = save_accept_label;      common->accept_label = save_accept_label;
5632      common->then_quit = save_then_quit;      common->positive_assert_quit = save_positive_assert_quit;
5633      common->accept = save_accept;      common->accept = save_accept;
5634      return NULL;      return NULL;
5635      }      }
# Line 5660  while (1) Line 5694  while (1)
5694    compile_backtrackingpath(common, altbacktrack.top);    compile_backtrackingpath(common, altbacktrack.top);
5695    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
5696      {      {
5697      common->then_local_exit = save_then_local_exit;      if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
5698          {
5699          common->local_exit = save_local_exit;
5700          common->quit_label = save_quit_label;
5701          common->quit = save_quit;
5702          }
5703        common->positive_assert = save_positive_assert;
5704      common->then_trap = save_then_trap;      common->then_trap = save_then_trap;
5705      common->accept_label = save_accept_label;      common->accept_label = save_accept_label;
5706      common->then_quit = save_then_quit;      common->positive_assert_quit = save_positive_assert_quit;
5707      common->accept = save_accept;      common->accept = save_accept;
5708      return NULL;      return NULL;
5709      }      }
# Line 5676  while (1) Line 5716  while (1)
5716    cc += GET(cc, 1);    cc += GET(cc, 1);
5717    }    }
5718    
5719    if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
5720      {
5721      SLJIT_ASSERT(common->positive_assert_quit == NULL);
5722      /* Makes the check less complicated below. */
5723      common->positive_assert_quit = common->quit;
5724      }
5725    
5726  /* None of them matched. */  /* None of them matched. */
5727  if (common->then_quit != NULL)  if (common->positive_assert_quit != NULL)
5728    {    {
5729    jump = JUMP(SLJIT_JUMP);    jump = JUMP(SLJIT_JUMP);
5730    set_jumps(common->then_quit, LABEL());    set_jumps(common->positive_assert_quit, LABEL());
5731    SLJIT_ASSERT(framesize != no_stack);    SLJIT_ASSERT(framesize != no_stack);
5732    if (framesize < 0)    if (framesize < 0)
5733      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));
# Line 5840  else Line 5887  else
5887      }      }
5888    }    }
5889    
5890  common->then_local_exit = save_then_local_exit;  if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
5891      {
5892      common->local_exit = save_local_exit;
5893      common->quit_label = save_quit_label;
5894      common->quit = save_quit;
5895      }
5896    common->positive_assert = save_positive_assert;
5897  common->then_trap = save_then_trap;  common->then_trap = save_then_trap;
5898  common->accept_label = save_accept_label;  common->accept_label = save_accept_label;
5899  common->then_quit = save_then_quit;  common->positive_assert_quit = save_positive_assert_quit;
5900  common->accept = save_accept;  common->accept = save_accept;
5901  return cc + 1 + LINK_SIZE;  return cc + 1 + LINK_SIZE;
5902  }  }
# Line 6091  pcre_uchar opcode; Line 6144  pcre_uchar opcode;
6144  int private_data_ptr = 0;  int private_data_ptr = 0;
6145  int offset = 0;  int offset = 0;
6146  int stacksize;  int stacksize;
6147    int repeat_ptr = 0, repeat_length = 0;
6148    int repeat_type = 0, repeat_count = 0;
6149  pcre_uchar *ccbegin;  pcre_uchar *ccbegin;
6150  pcre_uchar *matchingpath;  pcre_uchar *matchingpath;
6151  pcre_uchar bra = OP_BRA;  pcre_uchar bra = OP_BRA;
# Line 6100  BOOL has_alternatives; Line 6155  BOOL has_alternatives;
6155  BOOL needs_control_head = FALSE;  BOOL needs_control_head = FALSE;
6156  struct sljit_jump *jump;  struct sljit_jump *jump;
6157  struct sljit_jump *skip;  struct sljit_jump *skip;
6158  struct sljit_label *rmaxlabel = NULL;  struct sljit_label *rmax_label = NULL;
6159  struct sljit_jump *braminzerojump = NULL;  struct sljit_jump *braminzero = NULL;
6160    
6161  PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);  PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);
6162    
# Line 6114  if (*cc == OP_BRAZERO || *cc == OP_BRAMI Line 6169  if (*cc == OP_BRAZERO || *cc == OP_BRAMI
6169    
6170  opcode = *cc;  opcode = *cc;
6171  ccbegin = cc;  ccbegin = cc;
6172  matchingpath = ccbegin + 1 + LINK_SIZE;  matchingpath = bracketend(cc) - 1 - LINK_SIZE;
6173    ket = *matchingpath;
6174    if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0)
6175      {
6176      repeat_ptr = PRIVATE_DATA(matchingpath);
6177      repeat_length = PRIVATE_DATA(matchingpath + 1);
6178      repeat_type = PRIVATE_DATA(matchingpath + 2);
6179      repeat_count = PRIVATE_DATA(matchingpath + 3);
6180      SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0);
6181      if (repeat_type == OP_UPTO)
6182        ket = OP_KETRMAX;
6183      if (repeat_type == OP_MINUPTO)
6184        ket = OP_KETRMIN;
6185      }
6186    
6187  if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)  if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
6188    {    {
6189    /* Drop this bracket_backtrack. */    /* Drop this bracket_backtrack. */
6190    parent->top = backtrack->prev;    parent->top = backtrack->prev;
6191    return bracketend(cc);    return matchingpath + 1 + LINK_SIZE + repeat_length;
6192    }    }
6193    
6194  ket = *(bracketend(cc) - 1 - LINK_SIZE);  matchingpath = ccbegin + 1 + LINK_SIZE;
6195  SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);  SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
6196  SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));  SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
6197  cc += GET(cc, 1);  cc += GET(cc, 1);
# Line 6203  if (bra == OP_BRAMINZERO) Line 6271  if (bra == OP_BRAMINZERO)
6271    if (ket != OP_KETRMIN)    if (ket != OP_KETRMIN)
6272      {      {
6273      free_stack(common, 1);      free_stack(common, 1);
6274      braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);      braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
6275      }      }
6276    else    else
6277      {      {
# Line 6218  if (bra == OP_BRAMINZERO) Line 6286  if (bra == OP_BRAMINZERO)
6286        if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)        if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
6287          {          {
6288          /* When we come from outside, private_data_ptr contains the previous STR_PTR. */          /* When we come from outside, private_data_ptr contains the previous STR_PTR. */
6289          braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);          braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
6290          }          }
6291        else        else
6292          {          {
6293          /* Except when the whole stack frame must be saved. */          /* Except when the whole stack frame must be saved. */
6294          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
6295          braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw));          braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw));
6296          }          }
6297        JUMPHERE(skip);        JUMPHERE(skip);
6298        }        }
# Line 6237  if (bra == OP_BRAMINZERO) Line 6305  if (bra == OP_BRAMINZERO)
6305      }      }
6306    }    }
6307    
6308    if (repeat_type != 0)
6309      {
6310      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, repeat_count);
6311      if (repeat_type == OP_EXACT)
6312        rmax_label = LABEL();
6313      }
6314    
6315  if (ket == OP_KETRMIN)  if (ket == OP_KETRMIN)
6316    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();
6317    
6318  if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
6319    {    {
6320    rmaxlabel = LABEL();    rmax_label = LABEL();
6321    if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)    if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA && repeat_type == 0)
6322      BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmaxlabel;      BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmax_label;
6323    }    }
6324    
6325  /* Handling capturing brackets and alternatives. */  /* Handling capturing brackets and alternatives. */
# Line 6462  if (opcode == OP_ONCE) Line 6537  if (opcode == OP_ONCE)
6537    match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);    match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);
6538    
6539  stacksize = 0;  stacksize = 0;
6540    if (repeat_type == OP_MINUPTO)
6541      {
6542      /* We need to preserve the counter. TMP2 will be used below. */
6543      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
6544      stacksize++;
6545      }
6546  if (ket != OP_KET || bra != OP_BRA)  if (ket != OP_KET || bra != OP_BRA)
6547    stacksize++;    stacksize++;
6548  if (offset != 0)  if (offset != 0)
# Line 6478  if (stacksize > 0) Line 6559  if (stacksize > 0)
6559    allocate_stack(common, stacksize);    allocate_stack(common, stacksize);
6560    
6561  stacksize = 0;  stacksize = 0;
6562    if (repeat_type == OP_MINUPTO)
6563      {
6564      /* TMP2 was set above. */
6565      OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);
6566      stacksize++;
6567      }
6568    
6569  if (ket != OP_KET || bra != OP_BRA)  if (ket != OP_KET || bra != OP_BRA)
6570    {    {
6571    if (ket != OP_KET)    if (ket != OP_KET)
# Line 6507  if (offset != 0 && common->optimized_cbr Line 6595  if (offset != 0 && common->optimized_cbr
6595    
6596  if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
6597    {    {
6598    if (opcode == OP_ONCE || opcode >= OP_SBRA)    if (repeat_type != 0)
6599        {
6600        if (has_alternatives)
6601          BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
6602        OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
6603        JUMPTO(SLJIT_C_NOT_ZERO, rmax_label);
6604        /* Drop STR_PTR for greedy plus quantifier. */
6605        if (opcode != OP_ONCE)
6606          free_stack(common, 1);
6607        }
6608      else if (opcode == OP_ONCE || opcode >= OP_SBRA)
6609      {      {
6610      if (has_alternatives)      if (has_alternatives)
6611        BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();        BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
6612      /* Checking zero-length iteration. */      /* Checking zero-length iteration. */
6613      if (opcode != OP_ONCE)      if (opcode != OP_ONCE)
6614        {        {
6615        CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0, rmaxlabel);        CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0, rmax_label);
6616        /* Drop STR_PTR for greedy plus quantifier. */        /* Drop STR_PTR for greedy plus quantifier. */
6617        if (bra != OP_BRAZERO)        if (bra != OP_BRAZERO)
6618          free_stack(common, 1);          free_stack(common, 1);
6619        }        }
6620      else      else
6621        /* TMP2 must contain the starting STR_PTR. */        /* TMP2 must contain the starting STR_PTR. */
6622        CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);        CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label);
6623      }      }
6624    else    else
6625      JUMPTO(SLJIT_JUMP, rmaxlabel);      JUMPTO(SLJIT_JUMP, rmax_label);
6626    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();    BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();
6627    }    }
6628    
6629    if (repeat_type == OP_EXACT)
6630      {
6631      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
6632      JUMPTO(SLJIT_C_NOT_ZERO, rmax_label);
6633      }
6634    else if (repeat_type == OP_UPTO)
6635      {
6636      /* We need to preserve the counter. */
6637      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
6638      allocate_stack(common, 1);
6639      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
6640      }
6641    
6642  if (bra == OP_BRAZERO)  if (bra == OP_BRAZERO)
6643    BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();    BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();
6644    
# Line 6535  if (bra == OP_BRAMINZERO) Line 6646  if (bra == OP_BRAMINZERO)
6646    {    {
6647    /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */    /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */
6648    JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath);    JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath);
6649    if (braminzerojump != NULL)    if (braminzero != NULL)
6650      {      {
6651      JUMPHERE(braminzerojump);      JUMPHERE(braminzero);
6652      /* We need to release the end pointer to perform the      /* We need to release the end pointer to perform the
6653      backtrack for the zero-length iteration. When      backtrack for the zero-length iteration. When
6654      framesize is < 0, OP_ONCE will do the release itself. */      framesize is < 0, OP_ONCE will do the release itself. */
# Line 6563  cc += 1 + LINK_SIZE; Line 6674  cc += 1 + LINK_SIZE;
6674  /* Temporarily encoding the needs_control_head in framesize. */  /* Temporarily encoding the needs_control_head in framesize. */
6675  if (opcode == OP_ONCE)  if (opcode == OP_ONCE)
6676    BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);    BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
6677  return cc;  return cc + repeat_length;
6678  }  }
6679    
6680  static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)  static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
# Line 7850  if (bra == OP_BRAZERO) Line 7961  if (bra == OP_BRAZERO)
7961  static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)  static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)
7962  {  {
7963  DEFINE_COMPILER;  DEFINE_COMPILER;
7964  int opcode;  int opcode, stacksize, count;
7965  int offset = 0;  int offset = 0;
7966  int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;  int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;
7967  int stacksize;  int repeat_ptr = 0, repeat_type = 0, repeat_count = 0;
 int count;  
7968  pcre_uchar *cc = current->cc;  pcre_uchar *cc = current->cc;
7969  pcre_uchar *ccbegin;  pcre_uchar *ccbegin;
7970  pcre_uchar *ccprev;  pcre_uchar *ccprev;
# Line 7868  BOOL needs_control_head = FALSE; Line 7978  BOOL needs_control_head = FALSE;
7978  struct sljit_jump *brazero = NULL;  struct sljit_jump *brazero = NULL;
7979  struct sljit_jump *once = NULL;  struct sljit_jump *once = NULL;
7980  struct sljit_jump *cond = NULL;  struct sljit_jump *cond = NULL;
7981  struct sljit_label *rminlabel = NULL;  struct sljit_label *rmin_label = NULL;
7982    struct sljit_label *exact_label = NULL;
7983    
7984  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)  if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
7985    {    {
# Line 7877  if (*cc == OP_BRAZERO || *cc == OP_BRAMI Line 7988  if (*cc == OP_BRAZERO || *cc == OP_BRAMI
7988    }    }
7989    
7990  opcode = *cc;  opcode = *cc;
7991    ccbegin = bracketend(cc) - 1 - LINK_SIZE;
7992    ket = *ccbegin;
7993    if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0)
7994      {
7995      repeat_ptr = PRIVATE_DATA(ccbegin);
7996      repeat_type = PRIVATE_DATA(ccbegin + 2);
7997      repeat_count = PRIVATE_DATA(ccbegin + 3);
7998      SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0);
7999      if (repeat_type == OP_UPTO)
8000        ket = OP_KETRMAX;
8001      if (repeat_type == OP_MINUPTO)
8002        ket = OP_KETRMIN;
8003      }
8004  ccbegin = cc;  ccbegin = cc;
 ket = *(bracketend(ccbegin) - 1 - LINK_SIZE);  
8005  cc += GET(cc, 1);  cc += GET(cc, 1);
8006  has_alternatives = *cc == OP_ALT;  has_alternatives = *cc == OP_ALT;
8007  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))  if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
# Line 7897  if (opcode == OP_ONCE) Line 8020  if (opcode == OP_ONCE)
8020    CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;    CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;
8021    }    }
8022    
8023    if (ket != OP_KET && repeat_type != 0)
8024      {
8025      /* TMP1 is used in OP_KETRMIN below. */
8026      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
8027      free_stack(common, 1);
8028      if (repeat_type == OP_UPTO)
8029        OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0, SLJIT_IMM, 1);
8030      else
8031        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0);
8032      }
8033    
8034  if (ket == OP_KETRMAX)  if (ket == OP_KETRMAX)
8035    {    {
8036    if (bra == OP_BRAZERO)    if (bra == OP_BRAZERO)
# Line 7911  else if (ket == OP_KETRMIN) Line 8045  else if (ket == OP_KETRMIN)
8045    if (bra != OP_BRAMINZERO)    if (bra != OP_BRAMINZERO)
8046      {      {
8047      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
8048      if (opcode >= OP_SBRA || opcode == OP_ONCE)      if (repeat_type != 0)
8049          {
8050          /* TMP1 was set a few lines above. */
8051          CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
8052          /* Drop STR_PTR for non-greedy plus quantifier. */
8053          if (opcode != OP_ONCE)
8054            free_stack(common, 1);
8055          }
8056        else if (opcode >= OP_SBRA || opcode == OP_ONCE)
8057        {        {
8058        /* Checking zero-length iteration. */        /* Checking zero-length iteration. */
8059        if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)        if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)
# Line 7921  else if (ket == OP_KETRMIN) Line 8063  else if (ket == OP_KETRMIN)
8063          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);          OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
8064          CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);          CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
8065          }          }
8066          /* Drop STR_PTR for non-greedy plus quantifier. */
8067        if (opcode != OP_ONCE)        if (opcode != OP_ONCE)
8068          free_stack(common, 1);          free_stack(common, 1);
8069        }        }
8070      else      else
8071        JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);        JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
8072      }      }
8073    rminlabel = LABEL();    rmin_label = LABEL();
8074      if (repeat_type != 0)
8075        OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
8076    }    }
8077  else if (bra == OP_BRAZERO)  else if (bra == OP_BRAZERO)
8078    {    {
# Line 7935  else if (bra == OP_BRAZERO) Line 8080  else if (bra == OP_BRAZERO)
8080    free_stack(common, 1);    free_stack(common, 1);
8081    brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);    brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
8082    }    }
8083    else if (repeat_type == OP_EXACT)
8084      {
8085      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
8086      exact_label = LABEL();
8087      }
8088    
8089  if (offset != 0)  if (offset != 0)
8090    {    {
# Line 8082  if (has_alternatives) Line 8232  if (has_alternatives)
8232        match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);        match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);
8233    
8234      stacksize = 0;      stacksize = 0;
8235        if (repeat_type == OP_MINUPTO)
8236          {
8237          /* We need to preserve the counter. TMP2 will be used below. */
8238          OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
8239          stacksize++;
8240          }
8241      if (ket != OP_KET || bra != OP_BRA)      if (ket != OP_KET || bra != OP_BRA)
8242        stacksize++;        stacksize++;
8243      if (offset != 0)      if (offset != 0)
# Line 8095  if (has_alternatives) Line 8251  if (has_alternatives)
8251        stacksize++;        stacksize++;
8252    
8253      if (stacksize > 0)      if (stacksize > 0)
8254          allocate_stack(common, stacksize);
8255    
8256        stacksize = 0;
8257        if (repeat_type == OP_MINUPTO)
8258        {        {
8259        if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0)        /* TMP2 was set above. */
8260          allocate_stack(common, stacksize);        OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);
8261        else        stacksize++;
         {  
         /* We know we have place at least for one item on the top of the stack. */  
         SLJIT_ASSERT(stacksize == 1);  
         OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));  
         }  
8262        }        }
8263    
     stacksize = 0;  
8264      if (ket != OP_KET || bra != OP_BRA)      if (ket != OP_KET || bra != OP_BRA)
8265        {        {
8266        if (ket != OP_KET)        if (ket != OP_KET)
# Line 8217  else if (opcode == OP_ONCE) Line 8371  else if (opcode == OP_ONCE)
8371      }      }
8372    }    }
8373    
8374  if (ket == OP_KETRMAX)  if (repeat_type == OP_EXACT)
8375      {
8376      OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
8377      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0);
8378      CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label);
8379      }
8380    else if (ket == OP_KETRMAX)
8381    {    {
8382    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
8383    if (bra != OP_BRAZERO)    if (bra != OP_BRAZERO)
8384      free_stack(common, 1);      free_stack(common, 1);
8385    
8386    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);    CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
8387    if (bra == OP_BRAZERO)    if (bra == OP_BRAZERO)
8388      {      {
# Line 8240  else if (ket == OP_KETRMIN) Line 8401  else if (ket == OP_KETRMIN)
8401    affect badly the free_stack(2) above. */    affect badly the free_stack(2) above. */
8402    if (opcode != OP_ONCE)    if (opcode != OP_ONCE)
8403      free_stack(common, 1);      free_stack(common, 1);
8404    CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rminlabel);    CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label);
8405    if (opcode == OP_ONCE)    if (opcode == OP_ONCE)
8406      free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);      free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);
8407    else if (bra == OP_BRAMINZERO)    else if (bra == OP_BRAMINZERO)
# Line 8343  if (opcode == OP_THEN || opcode == OP_TH Line 8504  if (opcode == OP_THEN || opcode == OP_TH
8504      add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));      add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));
8505      return;      return;
8506      }      }
8507    else if (common->then_local_exit != 0)    else if (common->positive_assert)
8508      {      {
8509      if (common->then_local_exit > 0)      add_jump(compiler, &common->positive_assert_quit, JUMP(SLJIT_JUMP));
       add_jump(compiler, &common->then_quit, JUMP(SLJIT_JUMP));  
     else if (common->accept_label == NULL)  
       add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));  
     else  
       JUMPTO(SLJIT_JUMP, common->accept_label);  
8510      return;      return;
8511      }      }
8512    }    }
# Line 8830  SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA Line 8986  SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA
8986  common->capture_last_ptr = common->ovector_start;  common->capture_last_ptr = common->ovector_start;
8987  common->ovector_start += sizeof(sljit_sw);  common->ovector_start += sizeof(sljit_sw);
8988  #endif  #endif
8989  private_data_size = get_private_data_length(common, rootbacktrack.cc, ccend);  if (!check_opcode_types(common, rootbacktrack.cc, ccend))
 if (private_data_size < 0)  
8990    {    {
8991    SLJIT_FREE(common->optimized_cbracket);    SLJIT_FREE(common->optimized_cbracket);
8992    return;    return;
# Line 8893  if (common->capture_last_ptr != 0) Line 9048  if (common->capture_last_ptr != 0)
9048    
9049  SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));  SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
9050  common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);  common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);
9051  private_data_size += common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);  
9052  if (private_data_size > SLJIT_MAX_LOCAL_SIZE)  common->private_data_ptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(sljit_si));
9053    if (!common->private_data_ptrs)
9054    {    {
9055    SLJIT_FREE(common->optimized_cbracket);    SLJIT_FREE(common->optimized_cbracket);
9056    return;    return;
9057    }    }
9058    memset(common->private_data_ptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int));
9059    
9060  common->private_data_ptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(int));  private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);
9061  if (!common->private_data_ptrs)  set_private_data_ptrs(common, &private_data_size, ccend);
9062    if (private_data_size > SLJIT_MAX_LOCAL_SIZE)
9063    {    {
9064      SLJIT_FREE(common->private_data_ptrs);
9065    SLJIT_FREE(common->optimized_cbracket);    SLJIT_FREE(common->optimized_cbracket);
9066    return;    return;
9067    }    }
 memset(common->private_data_ptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int));  
 set_private_data_ptrs(common, common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw), ccend);  
9068    
9069  if (common->has_then)  if (common->has_then)
9070    {    {

Legend:
Removed from v.1300  
changed lines
  Added in v.1310

  ViewVC Help
Powered by ViewVC 1.1.5