comparison src/regexp_nfa.c @ 6328:adfbffe1e642 v7.4.497

updated for version 7.4.497 Problem: With some regexp patterns the NFA engine uses many states and becomes very slow. To the user it looks like Vim freezes. Solution: When the number of states reaches a limit fall back to the old engine. (Christian Brabandt)
author Bram Moolenaar <bram@vim.org>
date Wed, 05 Nov 2014 14:27:36 +0100
parents 7f2472960aa1
children 2bb019eb60ca
comparison
equal deleted inserted replaced
6327:896d12bf73c1 6328:adfbffe1e642
5520 thislist = &list[flag]; 5520 thislist = &list[flag];
5521 nextlist = &list[flag ^= 1]; 5521 nextlist = &list[flag ^= 1];
5522 nextlist->n = 0; /* clear nextlist */ 5522 nextlist->n = 0; /* clear nextlist */
5523 nextlist->has_pim = FALSE; 5523 nextlist->has_pim = FALSE;
5524 ++nfa_listid; 5524 ++nfa_listid;
5525 if (prog->re_engine == AUTOMATIC_ENGINE && nfa_listid >= NFA_MAX_STATES)
5526 {
5527 /* too many states, retry with old engine */
5528 nfa_match = NFA_TOO_EXPENSIVE;
5529 goto theend;
5530 }
5531
5525 thislist->id = nfa_listid; 5532 thislist->id = nfa_listid;
5526 nextlist->id = nfa_listid + 1; 5533 nextlist->id = nfa_listid + 1;
5527 5534
5528 #ifdef ENABLE_LOG 5535 #ifdef ENABLE_LOG
5529 fprintf(log_fd, "------------------------------------------\n"); 5536 fprintf(log_fd, "------------------------------------------\n");
5702 * First try matching the invisible match, then what 5709 * First try matching the invisible match, then what
5703 * follows. 5710 * follows.
5704 */ 5711 */
5705 result = recursive_regmatch(t->state, NULL, prog, 5712 result = recursive_regmatch(t->state, NULL, prog,
5706 submatch, m, &listids); 5713 submatch, m, &listids);
5714 if (result == NFA_TOO_EXPENSIVE)
5715 {
5716 nfa_match = result;
5717 goto theend;
5718 }
5707 5719
5708 /* for \@! and \@<! it is a match when the result is 5720 /* for \@! and \@<! it is a match when the result is
5709 * FALSE */ 5721 * FALSE */
5710 if (result != (t->state->c == NFA_START_INVISIBLE_NEG 5722 if (result != (t->state->c == NFA_START_INVISIBLE_NEG
5711 || t->state->c == NFA_START_INVISIBLE_NEG_FIRST 5723 || t->state->c == NFA_START_INVISIBLE_NEG_FIRST
5815 #endif 5827 #endif
5816 5828
5817 /* First try matching the pattern. */ 5829 /* First try matching the pattern. */
5818 result = recursive_regmatch(t->state, NULL, prog, 5830 result = recursive_regmatch(t->state, NULL, prog,
5819 submatch, m, &listids); 5831 submatch, m, &listids);
5832 if (result == NFA_TOO_EXPENSIVE)
5833 {
5834 nfa_match = result;
5835 goto theend;
5836 }
5820 if (result) 5837 if (result)
5821 { 5838 {
5822 int bytelen; 5839 int bytelen;
5823 5840
5824 #ifdef ENABLE_LOG 5841 #ifdef ENABLE_LOG
6758 colnr_T col; 6775 colnr_T col;
6759 { 6776 {
6760 int i; 6777 int i;
6761 regsubs_T subs, m; 6778 regsubs_T subs, m;
6762 nfa_state_T *start = prog->start; 6779 nfa_state_T *start = prog->start;
6780 int result;
6763 #ifdef ENABLE_LOG 6781 #ifdef ENABLE_LOG
6764 FILE *f; 6782 FILE *f;
6765 #endif 6783 #endif
6766 6784
6767 reginput = regline + col; 6785 reginput = regline + col;
6789 #ifdef FEAT_SYN_HL 6807 #ifdef FEAT_SYN_HL
6790 clear_sub(&subs.synt); 6808 clear_sub(&subs.synt);
6791 clear_sub(&m.synt); 6809 clear_sub(&m.synt);
6792 #endif 6810 #endif
6793 6811
6794 if (nfa_regmatch(prog, start, &subs, &m) == FALSE) 6812 result = nfa_regmatch(prog, start, &subs, &m);
6813 if (result == FALSE)
6795 return 0; 6814 return 0;
6815 else if (result == NFA_TOO_EXPENSIVE)
6816 return result;
6796 6817
6797 cleanup_subexpr(); 6818 cleanup_subexpr();
6798 if (REG_MULTI) 6819 if (REG_MULTI)
6799 { 6820 {
6800 for (i = 0; i < subs.norm.in_use; i++) 6821 for (i = 0; i < subs.norm.in_use; i++)
6927 nfa_has_zend = prog->has_zend; 6948 nfa_has_zend = prog->has_zend;
6928 nfa_has_backref = prog->has_backref; 6949 nfa_has_backref = prog->has_backref;
6929 nfa_nsubexpr = prog->nsubexp; 6950 nfa_nsubexpr = prog->nsubexp;
6930 nfa_listid = 1; 6951 nfa_listid = 1;
6931 nfa_alt_listid = 2; 6952 nfa_alt_listid = 2;
6932 #ifdef DEBUG
6933 nfa_regengine.expr = prog->pattern; 6953 nfa_regengine.expr = prog->pattern;
6934 #endif
6935 6954
6936 if (prog->reganch && col > 0) 6955 if (prog->reganch && col > 0)
6937 return 0L; 6956 return 0L;
6938 6957
6939 need_clear_subexpr = TRUE; 6958 need_clear_subexpr = TRUE;
6977 prog->state[i].lastlist[1] = 0; 6996 prog->state[i].lastlist[1] = 0;
6978 } 6997 }
6979 6998
6980 retval = nfa_regtry(prog, col); 6999 retval = nfa_regtry(prog, col);
6981 7000
6982 #ifdef DEBUG
6983 nfa_regengine.expr = NULL; 7001 nfa_regengine.expr = NULL;
6984 #endif
6985 7002
6986 theend: 7003 theend:
6987 return retval; 7004 return retval;
6988 } 7005 }
6989 7006
7001 int *postfix; 7018 int *postfix;
7002 7019
7003 if (expr == NULL) 7020 if (expr == NULL)
7004 return NULL; 7021 return NULL;
7005 7022
7006 #ifdef DEBUG
7007 nfa_regengine.expr = expr; 7023 nfa_regengine.expr = expr;
7008 #endif
7009 7024
7010 init_class_tab(); 7025 init_class_tab();
7011 7026
7012 if (nfa_regcomp_start(expr, re_flags) == FAIL) 7027 if (nfa_regcomp_start(expr, re_flags) == FAIL)
7013 return NULL; 7028 return NULL;
7080 #endif 7095 #endif
7081 #ifdef FEAT_SYN_HL 7096 #ifdef FEAT_SYN_HL
7082 /* Remember whether this pattern has any \z specials in it. */ 7097 /* Remember whether this pattern has any \z specials in it. */
7083 prog->reghasz = re_has_z; 7098 prog->reghasz = re_has_z;
7084 #endif 7099 #endif
7085 #ifdef DEBUG
7086 prog->pattern = vim_strsave(expr); 7100 prog->pattern = vim_strsave(expr);
7087 nfa_regengine.expr = NULL; 7101 nfa_regengine.expr = NULL;
7088 #endif
7089 7102
7090 out: 7103 out:
7091 vim_free(post_start); 7104 vim_free(post_start);
7092 post_start = post_ptr = post_end = NULL; 7105 post_start = post_ptr = post_end = NULL;
7093 state_ptr = NULL; 7106 state_ptr = NULL;
7097 vim_free(prog); 7110 vim_free(prog);
7098 prog = NULL; 7111 prog = NULL;
7099 #ifdef ENABLE_LOG 7112 #ifdef ENABLE_LOG
7100 nfa_postfix_dump(expr, FAIL); 7113 nfa_postfix_dump(expr, FAIL);
7101 #endif 7114 #endif
7102 #ifdef DEBUG
7103 nfa_regengine.expr = NULL; 7115 nfa_regengine.expr = NULL;
7104 #endif
7105 goto out; 7116 goto out;
7106 } 7117 }
7107 7118
7108 /* 7119 /*
7109 * Free a compiled regexp program, returned by nfa_regcomp(). 7120 * Free a compiled regexp program, returned by nfa_regcomp().
7113 regprog_T *prog; 7124 regprog_T *prog;
7114 { 7125 {
7115 if (prog != NULL) 7126 if (prog != NULL)
7116 { 7127 {
7117 vim_free(((nfa_regprog_T *)prog)->match_text); 7128 vim_free(((nfa_regprog_T *)prog)->match_text);
7118 #ifdef DEBUG
7119 vim_free(((nfa_regprog_T *)prog)->pattern); 7129 vim_free(((nfa_regprog_T *)prog)->pattern);
7120 #endif
7121 vim_free(prog); 7130 vim_free(prog);
7122 } 7131 }
7123 } 7132 }
7124 7133
7125 /* 7134 /*