⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 regcomp.c

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Extended regular expression matching and search library.   Copyright (C) 2002, 2003 Free Software Foundation, Inc.   This file is part of the GNU C Library.   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307 USA.  */static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,					  int length, reg_syntax_t syntax);static void re_compile_fastmap_iter (regex_t *bufp,				     const re_dfastate_t *init_state,				     char *fastmap);static reg_errcode_t init_dfa (re_dfa_t *dfa, int pat_len);static reg_errcode_t init_word_char (re_dfa_t *dfa);#ifdef RE_ENABLE_I18Nstatic void free_charset (re_charset_t *cset);#endif /* RE_ENABLE_I18N */static void free_workarea_compile (regex_t *preg);static reg_errcode_t create_initial_state (re_dfa_t *dfa);static reg_errcode_t analyze (re_dfa_t *dfa);static reg_errcode_t analyze_tree (re_dfa_t *dfa, bin_tree_t *node);static void calc_first (re_dfa_t *dfa, bin_tree_t *node);static void calc_next (re_dfa_t *dfa, bin_tree_t *node);static void calc_epsdest (re_dfa_t *dfa, bin_tree_t *node);static reg_errcode_t duplicate_node_closure (re_dfa_t *dfa, int top_org_node,					     int top_clone_node, int root_node,					     unsigned int constraint);static reg_errcode_t duplicate_node (int *new_idx, re_dfa_t *dfa, int org_idx,				     unsigned int constraint);static int search_duplicated_node (re_dfa_t *dfa, int org_node,				   unsigned int constraint);static reg_errcode_t calc_eclosure (re_dfa_t *dfa);static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,					 int node, int root);static void calc_inveclosure (re_dfa_t *dfa);static int fetch_number (re_string_t *input, re_token_t *token,			 reg_syntax_t syntax);static re_token_t fetch_token (re_string_t *input, reg_syntax_t syntax);static int peek_token (re_token_t *token, re_string_t *input,			reg_syntax_t syntax);static int peek_token_bracket (re_token_t *token, re_string_t *input,			       reg_syntax_t syntax);static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,			  reg_syntax_t syntax, reg_errcode_t *err);static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,				  re_token_t *token, reg_syntax_t syntax,				  int nest, reg_errcode_t *err);static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,				 re_token_t *token, reg_syntax_t syntax,				 int nest, reg_errcode_t *err);static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,				     re_token_t *token, reg_syntax_t syntax,				     int nest, reg_errcode_t *err);static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,				  re_token_t *token, reg_syntax_t syntax,				  int nest, reg_errcode_t *err);static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,				 re_dfa_t *dfa, re_token_t *token,				 reg_syntax_t syntax, reg_errcode_t *err);static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,				      re_token_t *token, reg_syntax_t syntax,				      reg_errcode_t *err);static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,					    re_string_t *regexp,					    re_token_t *token, int token_len,					    re_dfa_t *dfa,					    reg_syntax_t syntax);static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,					  re_string_t *regexp,					  re_token_t *token);#ifndef _LIBC# ifdef RE_ENABLE_I18Nstatic reg_errcode_t build_range_exp (re_bitset_ptr_t sbcset,				      re_charset_t *mbcset, int *range_alloc,				      bracket_elem_t *start_elem,				      bracket_elem_t *end_elem);static reg_errcode_t build_collating_symbol (re_bitset_ptr_t sbcset,					     re_charset_t *mbcset,					     int *coll_sym_alloc,					     const unsigned char *name);# else /* not RE_ENABLE_I18N */static reg_errcode_t build_range_exp (re_bitset_ptr_t sbcset,				      bracket_elem_t *start_elem,				      bracket_elem_t *end_elem);static reg_errcode_t build_collating_symbol (re_bitset_ptr_t sbcset,					     const unsigned char *name);# endif /* not RE_ENABLE_I18N */#endif /* not _LIBC */#ifdef RE_ENABLE_I18Nstatic reg_errcode_t build_equiv_class (re_bitset_ptr_t sbcset,					re_charset_t *mbcset,					int *equiv_class_alloc,					const unsigned char *name);static reg_errcode_t build_charclass (re_bitset_ptr_t sbcset,				      re_charset_t *mbcset,				      int *char_class_alloc,				      const unsigned char *class_name,				      reg_syntax_t syntax);#else  /* not RE_ENABLE_I18N */static reg_errcode_t build_equiv_class (re_bitset_ptr_t sbcset,					const unsigned char *name);static reg_errcode_t build_charclass (re_bitset_ptr_t sbcset,				      const unsigned char *class_name,				      reg_syntax_t syntax);#endif /* not RE_ENABLE_I18N */static bin_tree_t *build_word_op (re_dfa_t *dfa, int not, reg_errcode_t *err);static void free_bin_tree (bin_tree_t *tree);static bin_tree_t *create_tree (bin_tree_t *left, bin_tree_t *right,				re_token_type_t type, int index);static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);/* This table gives an error message for each of the error codes listed   in regex.h.  Obviously the order here has to be same as there.   POSIX doesn't require that we do anything for REG_NOERROR,   but why not be nice?  */const char __re_error_msgid[] attribute_hidden =  {#define REG_NOERROR_IDX	0    gettext_noop ("Success")	/* REG_NOERROR */    "\0"#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")    gettext_noop ("No match")	/* REG_NOMATCH */    "\0"#define REG_BADPAT_IDX	(REG_NOMATCH_IDX + sizeof "No match")    gettext_noop ("Invalid regular expression") /* REG_BADPAT */    "\0"#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")    gettext_noop ("Invalid collation character") /* REG_ECOLLATE */    "\0"#define REG_ECTYPE_IDX	(REG_ECOLLATE_IDX + sizeof "Invalid collation character")    gettext_noop ("Invalid character class name") /* REG_ECTYPE */    "\0"#define REG_EESCAPE_IDX	(REG_ECTYPE_IDX + sizeof "Invalid character class name")    gettext_noop ("Trailing backslash") /* REG_EESCAPE */    "\0"#define REG_ESUBREG_IDX	(REG_EESCAPE_IDX + sizeof "Trailing backslash")    gettext_noop ("Invalid back reference") /* REG_ESUBREG */    "\0"#define REG_EBRACK_IDX	(REG_ESUBREG_IDX + sizeof "Invalid back reference")    gettext_noop ("Unmatched [ or [^")	/* REG_EBRACK */    "\0"#define REG_EPAREN_IDX	(REG_EBRACK_IDX + sizeof "Unmatched [ or [^")    gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */    "\0"#define REG_EBRACE_IDX	(REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")    gettext_noop ("Unmatched \\{") /* REG_EBRACE */    "\0"#define REG_BADBR_IDX	(REG_EBRACE_IDX + sizeof "Unmatched \\{")    gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */    "\0"#define REG_ERANGE_IDX	(REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")    gettext_noop ("Invalid range end")	/* REG_ERANGE */    "\0"#define REG_ESPACE_IDX	(REG_ERANGE_IDX + sizeof "Invalid range end")    gettext_noop ("Memory exhausted") /* REG_ESPACE */    "\0"#define REG_BADRPT_IDX	(REG_ESPACE_IDX + sizeof "Memory exhausted")    gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */    "\0"#define REG_EEND_IDX	(REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")    gettext_noop ("Premature end of regular expression") /* REG_EEND */    "\0"#define REG_ESIZE_IDX	(REG_EEND_IDX + sizeof "Premature end of regular expression")    gettext_noop ("Regular expression too big") /* REG_ESIZE */    "\0"#define REG_ERPAREN_IDX	(REG_ESIZE_IDX + sizeof "Regular expression too big")    gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */  };const size_t __re_error_msgid_idx[] attribute_hidden =  {    REG_NOERROR_IDX,    REG_NOMATCH_IDX,    REG_BADPAT_IDX,    REG_ECOLLATE_IDX,    REG_ECTYPE_IDX,    REG_EESCAPE_IDX,    REG_ESUBREG_IDX,    REG_EBRACK_IDX,    REG_EPAREN_IDX,    REG_EBRACE_IDX,    REG_BADBR_IDX,    REG_ERANGE_IDX,    REG_ESPACE_IDX,    REG_BADRPT_IDX,    REG_EEND_IDX,    REG_ESIZE_IDX,    REG_ERPAREN_IDX  };/* Entry points for GNU code.  *//* re_compile_pattern is the GNU regular expression compiler: it   compiles PATTERN (of length LENGTH) and puts the result in BUFP.   Returns 0 if the pattern was valid, otherwise an error string.   Assumes the `allocated' (and perhaps `buffer') and `translate' fields   are set in BUFP on entry.  */const char *re_compile_pattern (pattern, length, bufp)    const char *pattern;    size_t length;    struct re_pattern_buffer *bufp;{  reg_errcode_t ret;  /* And GNU code determines whether or not to get register information     by passing null for the REGS argument to re_match, etc., not by     setting no_sub.  */  bufp->no_sub = 0;  /* Match anchors at newline.  */  bufp->newline_anchor = 1;  ret = re_compile_internal (bufp, pattern, length, re_syntax_options);  if (!ret)    return NULL;  return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);}#ifdef _LIBCweak_alias (__re_compile_pattern, re_compile_pattern)#endif/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can   also be assigned to arbitrarily: each pattern buffer stores its own   syntax, so it can be changed between regex compilations.  *//* This has no initializer because initialized variables in Emacs   become read-only after dumping.  */reg_syntax_t re_syntax_options;/* Specify the precise syntax of regexps for compilation.  This provides   for compatibility for various utilities which historically have   different, incompatible syntaxes.   The argument SYNTAX is a bit mask comprised of the various bits   defined in regex.h.  We return the old syntax.  */reg_syntax_tre_set_syntax (syntax)    reg_syntax_t syntax;{  reg_syntax_t ret = re_syntax_options;  re_syntax_options = syntax;  return ret;}#ifdef _LIBCweak_alias (__re_set_syntax, re_set_syntax)#endifintre_compile_fastmap (bufp)    struct re_pattern_buffer *bufp;{  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;  char *fastmap = bufp->fastmap;  memset (fastmap, '\0', sizeof (char) * SBC_MAX);  re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);  if (dfa->init_state != dfa->init_state_word)    re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);  if (dfa->init_state != dfa->init_state_nl)    re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);  if (dfa->init_state != dfa->init_state_begbuf)    re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);  bufp->fastmap_accurate = 1;  return 0;}#ifdef _LIBCweak_alias (__re_compile_fastmap, re_compile_fastmap)#endifstatic inline voidre_set_fastmap (char *fastmap, int icase, int ch){  fastmap[ch] = 1;  if (icase)    fastmap[tolower (ch)] = 1;}/* Helper function for re_compile_fastmap.   Compile fastmap for the initial_state INIT_STATE.  */static voidre_compile_fastmap_iter (bufp, init_state, fastmap)     regex_t *bufp;     const re_dfastate_t *init_state;     char *fastmap;{  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;  int node_cnt;  int icase = (MB_CUR_MAX == 1 && (bufp->syntax & RE_ICASE));  for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)    {      int node = init_state->nodes.elems[node_cnt];      re_token_type_t type = dfa->nodes[node].type;      if (type == CHARACTER)	re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);      else if (type == SIMPLE_BRACKET)	{	  int i, j, ch;	  for (i = 0, ch = 0; i < BITSET_UINTS; ++i)	    for (j = 0; j < UINT_BITS; ++j, ++ch)	      if (dfa->nodes[node].opr.sbcset[i] & (1 << j))		re_set_fastmap (fastmap, icase, ch);	}#ifdef RE_ENABLE_I18N      else if (type == COMPLEX_BRACKET)	{	  int i;	  re_charset_t *cset = dfa->nodes[node].opr.mbcset;	  if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes	      || cset->nranges || cset->nchar_classes)	    {# ifdef _LIBC	      if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0)		{		  /* In this case we want to catch the bytes which are		     the first byte of any collation elements.		     e.g. In da_DK, we want to catch 'a' since "aa"			  is a valid collation element, and don't catch			  'b' since 'b' is the only collation element			  which starts from 'b'.  */		  int j, ch;		  const int32_t *table = (const int32_t *)		    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);		  for (i = 0, ch = 0; i < BITSET_UINTS; ++i)		    for (j = 0; j < UINT_BITS; ++j, ++ch)		      if (table[ch] < 0)			re_set_fastmap (fastmap, icase, ch);		}# else	      if (MB_CUR_MAX > 1)		for (i = 0; i < SBC_MAX; ++i)		  if (__btowc (i) == WEOF)		    re_set_fastmap (fastmap, icase, i);# endif /* not _LIBC */	    }	  for (i = 0; i < cset->nmbchars; ++i)	    {	      char buf[256];	      mbstate_t state;	      memset (&state, '\0', sizeof (state));	      __wcrtomb (buf, cset->mbchars[i], &state);	      re_set_fastmap (fastmap, icase, *(unsigned char *) buf);	    }	}#endif /* RE_ENABLE_I18N */      else if (type == END_OF_RE || type == OP_PERIOD)	{	  memset (fastmap, '\1', sizeof (char) * SBC_MAX);	  if (type == END_OF_RE)	    bufp->can_be_null = 1;	  return;	}    }}/* Entry point for POSIX code.  *//* regcomp takes a regular expression as a string and compiles it.   PREG is a regex_t *.  We do not expect any fields to be initialized,   since POSIX says we shouldn't.  Thus, we set     `buffer' to the compiled pattern;     `used' to the length of the compiled pattern;     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the       REG_EXTENDED bit in CFLAGS is set; otherwise, to       RE_SYNTAX_POSIX_BASIC;     `newline_anchor' to REG_NEWLINE being set in CFLAGS;     `fastmap' to an allocated space for the fastmap;     `fastmap_accurate' to zero;     `re_nsub' to the number of subexpressions in PATTERN.   PATTERN is the address of the pattern string.   CFLAGS is a series of bits which affect compilation.     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we     use POSIX basic syntax.     If REG_NEWLINE is set, then . and [^...] don't match newline.     Also, regexec will try a match beginning after every newline.     If REG_ICASE is set, then we considers upper- and lowercase     versions of letters to be equivalent when matching.     If REG_NOSUB is set, then when PREG is passed to regexec, that     routine will report only success or failure, and nothing about the     registers.   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for   the return codes and their meanings.)  */intregcomp (preg, pattern, cflags)    regex_t *__restrict preg;    const char *__restrict pattern;    int cflags;{  reg_errcode_t ret;  reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED			 : RE_SYNTAX_POSIX_BASIC);  preg->buffer = NULL;  preg->allocated = 0;  preg->used = 0;  /* Try to allocate space for the fastmap.  */  preg->fastmap = re_malloc (char, SBC_MAX);  if (BE (preg->fastmap == NULL, 0))    return REG_ESPACE;  syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;  /* If REG_NEWLINE is set, newlines are treated differently.  */  if (cflags & REG_NEWLINE)    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */      syntax &= ~RE_DOT_NEWLINE;      syntax |= RE_HAT_LISTS_NOT_NEWLINE;      /* It also changes the matching behavior.  */      preg->newline_anchor = 1;    }  else    preg->newline_anchor = 0;  preg->no_sub = !!(cflags & REG_NOSUB);  preg->translate = NULL;  ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);  /* POSIX doesn't distinguish between an unmatched open-group and an     unmatched close-group: both are REG_EPAREN.  */  if (ret == REG_ERPAREN)    ret = REG_EPAREN;  /* We have already checked preg->fastmap != NULL.  */  if (BE (ret == REG_NOERROR, 1))    /* Compute the fastmap now, since regexec cannot modify the pattern       buffer.  This function nevers fails in this implementation.  */    (void) re_compile_fastmap (preg);  else    {      /* Some error occurred while compiling the expression.  */      re_free (preg->fastmap);      preg->fastmap = NULL;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -