about summary refs log tree commit diff
path: root/posix/regex_internal.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-02-28 07:43:13 +0000
committerUlrich Drepper <drepper@redhat.com>2002-02-28 07:43:13 +0000
commita9388965cca987526247e93b96dc65f4ec63cc9e (patch)
tree807a7b691419ddd73dc8e99fc495fcf8cf599b56 /posix/regex_internal.c
parent51f38e87b13f233bdf76bd6d3edaabf4fd9eb126 (diff)
downloadglibc-a9388965cca987526247e93b96dc65f4ec63cc9e.tar.gz
glibc-a9388965cca987526247e93b96dc65f4ec63cc9e.tar.xz
glibc-a9388965cca987526247e93b96dc65f4ec63cc9e.zip
Update.
2002-02-28  Isamu Hasegawa  <isamu@yamato.ibm.com>

	* posix/regcomp.c (regcomp): Remove a redundant condition.
	(init_word_char): Add a check on malloc failure.
	(create_initial_state): Likewise.
	(duplicate_node): Likewise.
	(calc_eclosure): Likewise.
	(calc_eclosure_iter): Likewise.
	(parse_expression): Likewise.
	(parse_bracket_exp): Remove unnecessary malloc invocations.
	(build_equiv_class): Likewise.
	(build_charclass): Likewise.
	* posix/regex_internal.c (re_node_set_intersect): Add a check
	on malloc failure.
	(re_node_set_add_intersect): Likewise.
	(re_node_set_merge): Likewise.
	(re_acquire_state): Likewise.
	(re_acquire_state_context): Likewise.
	(create_newstate_common): Likewise.
	(register_state): Likewise.
	(create_ci_newstate): Likewise.
	(create_cd_newstate): Likewise.
	* posix/regex_internal.h: Fix prototypes of re_acquire_state
	and re_acquire_state_context.
	* posix/regexec.c (regexec): Suit it to the error handling of
	re_search_internal.
	(re_match): Likewise.
	(re_search): Likewise.
	(re_search_internal): Add a check on malloc failure.
	(acquire_init_state_context): Likewise.
	(check_matching): Likewise.
	(proceed_next_node): Likewise.
	(set_regs): Likewise.
	(sift_states_backward): Likewise.
	(sift_states_iter_bkref): Likewise.
	(add_epsilon_backreference): Likewise.
	(transit_state): Likewise.
	(transit_state_sb): Likewise.
	(transit_state_mb): Likewise.
	(transit_state_bkref_loop): Likewise.
	(build_trtable): Likewise.
	(group_nodes_into_DFAstates): Likewise.
	(match_ctx_init): Likewise.
	(match_ctx_add_entry): Likewise.
Diffstat (limited to 'posix/regex_internal.c')
-rw-r--r--posix/regex_internal.c139
1 files changed, 101 insertions, 38 deletions
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
index 63bed420cd..11726b340d 100644
--- a/posix/regex_internal.c
+++ b/posix/regex_internal.c
@@ -68,6 +68,8 @@ static reg_errcode_t re_string_translate_buffer (re_string_t *pstr,
 static re_dfastate_t *create_newstate_common (re_dfa_t *dfa,
                                               const re_node_set *nodes,
                                               unsigned int hash);
+static reg_errcode_t register_state (re_dfa_t *dfa, re_dfastate_t *newstate,
+                                     unsigned int hash);
 static re_dfastate_t *create_ci_newstate (re_dfa_t *dfa,
                                           const re_node_set *nodes,
                                           unsigned int hash);
@@ -473,6 +475,10 @@ re_node_set_init_copy (dest, src)
   return REG_NOERROR;
 }
 
+/* Calculate the intersection of the sets SRC1 and SRC2. And store it in
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.
+   Note: We assume dest->elems is NULL, when dest->alloc is 0.  */
+
 static reg_errcode_t
 re_node_set_intersect (dest, src1, src2)
      re_node_set *dest;
@@ -483,31 +489,28 @@ re_node_set_intersect (dest, src1, src2)
     {
       if (src1->nelem + src2->nelem > dest->alloc)
         {
-          int *new_array;
-          if (dest->alloc == 0)
-            new_array = re_malloc (int, src1->nelem + src2->nelem);
-          else
-            new_array = re_realloc (dest->elems, int,
-                                    src1->nelem + src2->nelem);
           dest->alloc = src1->nelem + src2->nelem;
-          if (new_array == NULL)
+          dest->elems = re_realloc (dest->elems, int, dest->alloc);
+          if (dest->elems == NULL)
             return REG_ESPACE;
-          dest->elems = new_array;
         }
     }
   else
     {
+      /* The intersection of empty sets is also empty set.  */
       dest->nelem = 0;
       return REG_NOERROR;
     }
 
-  for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
+  for (i1 = i2 = id = 0; i1 < src1->nelem && i2 < src2->nelem; )
     {
       if (src1->elems[i1] > src2->elems[i2])
         {
           ++i2;
           continue;
         }
+      /* The intersection must have the elements which are in both of
+         SRC1 and SRC2.  */
       if (src1->elems[i1] == src2->elems[i2])
         dest->elems[id++] = src2->elems[i2++];
       ++i1;
@@ -516,6 +519,10 @@ re_node_set_intersect (dest, src1, src2)
   return REG_NOERROR;
 }
 
+/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.
+   Note: We assume dest->elems is NULL, when dest->alloc is 0.  */
+
 static reg_errcode_t
 re_node_set_add_intersect (dest, src1, src2)
      re_node_set *dest;
@@ -526,16 +533,10 @@ re_node_set_add_intersect (dest, src1, src2)
     {
       if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
         {
-          int *new_array;
-          if (dest->alloc == 0)
-            new_array = re_malloc (int, src1->nelem + src2->nelem);
-          else
-            new_array = re_realloc (dest->elems, int,
-                                    src1->nelem + src2->nelem + dest->nelem);
           dest->alloc = src1->nelem + src2->nelem + dest->nelem;
-          if (new_array == NULL)
+          dest->elems = re_realloc (dest->elems, int, dest->alloc);
+          if (dest->elems == NULL)
             return REG_ESPACE;
-          dest->elems = new_array;
         }
     }
   else
@@ -567,6 +568,9 @@ re_node_set_add_intersect (dest, src1, src2)
   return REG_NOERROR;
 }
 
+/* Calculate the union set of the sets SRC1 and SRC2. And store it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
+
 static reg_errcode_t
 re_node_set_init_union (dest, src1, src2)
      re_node_set *dest;
@@ -617,6 +621,9 @@ re_node_set_init_union (dest, src1, src2)
   return REG_NOERROR;
 }
 
+/* Calculate the union set of the sets DEST and SRC. And store it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
+
 static reg_errcode_t
 re_node_set_merge (dest, src)
      re_node_set *dest;
@@ -628,12 +635,16 @@ re_node_set_merge (dest, src)
   else if (dest == NULL)
     {
       dest = re_malloc (re_node_set, 1);
+      if (dest == NULL)
+        return REG_ESPACE;
       return re_node_set_init_copy (dest, src);
     }
   if (dest->alloc < src->nelem + dest->nelem)
     {
       dest->alloc = 2 * (src->nelem + dest->alloc);
       dest->elems = re_realloc (dest->elems, int, dest->alloc);
+      if (dest->elems == NULL)
+        return REG_ESPACE;
     }
 
   for (si = 0, di = 0 ; si < src->nelem && di < dest->nelem ;)
@@ -860,18 +871,28 @@ calc_state_hash (nodes, context)
 
 /* Search for the state whose node_set is equivalent to NODES.
    Return the pointer to the state, if we found it in the DFA.
-   Otherwise create the new one and return it.  */
-
-static re_dfastate_t *
-re_acquire_state (dfa, nodes)
+   Otherwise create the new one and return it.  In case of an error
+   return NULL and set the error code in ERR.
+   Note: - We assume NULL as the invalid state, then it is possible that
+           return value is NULL and ERR is REG_NOERROR.
+         - We never return non-NULL value in case of any errors, it is for
+           optimization.  */
+
+static re_dfastate_t*
+re_acquire_state (err, dfa, nodes)
+     reg_errcode_t *err;
      re_dfa_t *dfa;
      const re_node_set *nodes;
 {
   unsigned int hash;
+  re_dfastate_t *new_state;
   struct re_state_table_entry *spot;
   int i;
   if (nodes->nelem == 0)
-    return NULL;
+    {
+      *err = REG_NOERROR;
+      return NULL;
+    }
   hash = calc_state_hash (nodes, 0);
   spot = dfa->state_table + (hash & dfa->state_hash_mask);
 
@@ -893,25 +914,42 @@ re_acquire_state (dfa, nodes)
       }
 
   /* There are no appropriate state in the dfa, create the new one.  */
-  return create_ci_newstate (dfa, nodes, hash);
+  new_state = create_ci_newstate (dfa, nodes, hash);
+  if (new_state != NULL)
+    return new_state;
+  else
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
 }
 
 /* Search for the state whose node_set is equivalent to NODES and
    whose context is equivalent to CONTEXT.
    Return the pointer to the state, if we found it in the DFA.
-   Otherwise create the new one and return it.  */
-
-static re_dfastate_t *
-re_acquire_state_context (dfa, nodes, context)
+   Otherwise create the new one and return it.  In case of an error
+   return NULL and set the error code in ERR.
+   Note: - We assume NULL as the invalid state, then it is possible that
+           return value is NULL and ERR is REG_NOERROR.
+         - We never return non-NULL value in case of any errors, it is for
+           optimization.  */
+
+static re_dfastate_t*
+re_acquire_state_context (err, dfa, nodes, context)
+     reg_errcode_t *err;
      re_dfa_t *dfa;
      const re_node_set *nodes;
      unsigned int context;
 {
   unsigned int hash;
+  re_dfastate_t *new_state;
   struct re_state_table_entry *spot;
   int i;
   if (nodes->nelem == 0)
-    return NULL;
+    {
+      *err = REG_NOERROR;
+      return NULL;
+    }
   hash = calc_state_hash (nodes, context);
   spot = dfa->state_table + (hash & dfa->state_hash_mask);
 
@@ -934,9 +972,19 @@ re_acquire_state_context (dfa, nodes, context)
           return state;
       }
   /* There are no appropriate state in `dfa', create the new one.  */
-  return create_cd_newstate (dfa, nodes, context, hash);
+  new_state = create_cd_newstate (dfa, nodes, context, hash);
+  if (new_state != NULL)
+    return new_state;
+  else
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
 }
 
+/* Allocate memory for DFA state and initialize common properties.
+   Return the new state if succeeded, otherwise return NULL.  */
+
 static re_dfastate_t *
 create_newstate_common (dfa, nodes, hash)
      re_dfa_t *dfa;
@@ -945,6 +993,8 @@ create_newstate_common (dfa, nodes, hash)
 {
   re_dfastate_t *newstate;
   newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
+  if (newstate == NULL)
+    return NULL;
   re_node_set_init_copy (&newstate->nodes, nodes);
   newstate->trtable = NULL;
   newstate->trtable_search = NULL;
@@ -952,7 +1002,10 @@ create_newstate_common (dfa, nodes, hash)
   return newstate;
 }
 
-static void
+/* Store the new state NEWSTATE whose hash value is HASH in appropriate
+   position.  Return value indicate the error code if failed.  */
+
+static reg_errcode_t
 register_state (dfa, newstate, hash)
      re_dfa_t *dfa;
      re_dfastate_t *newstate;
@@ -972,8 +1025,7 @@ register_state (dfa, newstate, hash)
           spot->alloc = 4;
           new_array = re_malloc (re_dfastate_t *, spot->alloc);
 	  if (new_array == NULL)
-	    /* XXX return value */
-	    return;
+            return REG_ESPACE;
           new_array[0] = spot->entry.state;
         }
       else
@@ -985,8 +1037,12 @@ register_state (dfa, newstate, hash)
       spot->entry.array = new_array;
     }
   spot->entry.array[spot->num++] = newstate;
+  return REG_NOERROR;
 }
 
+/* Create the new state which is independ of contexts.
+   Return the new state if succeeded, otherwise return NULL.  */
+
 static re_dfastate_t *
 create_ci_newstate (dfa, nodes, hash)
      re_dfa_t *dfa;
@@ -994,8 +1050,11 @@ create_ci_newstate (dfa, nodes, hash)
      unsigned int hash;
 {
   int i;
+  reg_errcode_t err;
   re_dfastate_t *newstate;
   newstate = create_newstate_common (dfa, nodes, hash);
+  if (newstate == NULL)
+    return NULL;
   newstate->entrance_nodes = &newstate->nodes;
 
   for (i = 0 ; i < nodes->nelem ; i++)
@@ -1021,11 +1080,13 @@ create_ci_newstate (dfa, nodes, hash)
             newstate->halt = 1;
         }
     }
-
-  register_state (dfa, newstate, hash);
-  return newstate;
+  err = register_state (dfa, newstate, hash);
+  return (err != REG_NOERROR) ? NULL : newstate;
 }
 
+/* Create the new state which is depend on the context CONTEXT.
+   Return the new state if succeeded, otherwise return NULL.  */
+
 static re_dfastate_t *
 create_cd_newstate (dfa, nodes, context, hash)
      re_dfa_t *dfa;
@@ -1033,9 +1094,12 @@ create_cd_newstate (dfa, nodes, context, hash)
      unsigned int context, hash;
 {
   int i, nctx_nodes = 0;
+  reg_errcode_t err;
   re_dfastate_t *newstate;
 
   newstate = create_newstate_common (dfa, nodes, hash);
+  if (newstate == NULL)
+    return NULL;
   newstate->context = context;
   newstate->entrance_nodes = &newstate->nodes;
 
@@ -1076,7 +1140,6 @@ create_cd_newstate (dfa, nodes, context, hash)
             {
               newstate->entrance_nodes = re_malloc (re_node_set, 1);
 	      if (newstate->entrance_nodes == NULL)
-		/* XXX Return which value?  */
 		return NULL;
               re_node_set_init_copy (newstate->entrance_nodes, nodes);
               nctx_nodes = 0;
@@ -1090,6 +1153,6 @@ create_cd_newstate (dfa, nodes, context, hash)
             }
         }
     }
-  register_state (dfa, newstate, hash);
-  return newstate;
+  err = register_state (dfa, newstate, hash);
+  return (err != REG_NOERROR) ? NULL : newstate;
 }