Fixed memory leak that could occur for when large data1 node were
[idzebra-moved-to-github.git] / recctrl / regxread.c
index 2e51f67..a9cd6a2 100644 (file)
@@ -1,10 +1,27 @@
 /*
- * Copyright (C) 1994-1998, Index Data I/S 
+ * Copyright (C) 1994-1998, Index Data
  * All rights reserved.
  * Sebastian Hammer, Adam Dickmeiss
  *
  * $Log: regxread.c,v $
- * Revision 1.14  1998-03-05 08:41:00  adam
+ * Revision 1.19  1998-11-03 10:22:39  adam
+ * Fixed memory leak that could occur for when large data1 node were
+ * concatenated. Data-type data1_nodes may have multiple nodes.
+ *
+ * Revision 1.18  1998/10/15 13:11:47  adam
+ * Added support for option -record for "end element". When specified
+ * end element will mark end-of-record when at outer-level.
+ *
+ * Revision 1.17  1998/07/01 10:13:51  adam
+ * Minor fix.
+ *
+ * Revision 1.16  1998/06/30 15:15:09  adam
+ * Tags are trimmed: white space removed before- and after the tag.
+ *
+ * Revision 1.15  1998/06/30 12:55:45  adam
+ * Bug fix.
+ *
+ * Revision 1.14  1998/03/05 08:41:00  adam
  * Implemented rule contexts.
  *
  * Revision 1.13  1997/12/12 06:33:58  adam
 #include <stdio.h>
 #include <assert.h>
 #include <string.h>
+#include <ctype.h>
 
 #include <tpath.h>
 #include <zebrautl.h>
@@ -694,44 +712,26 @@ static void execData (struct lexSpec *spec,
 
     parent = d1_stack[*d1_level -1];
     assert (parent);
-    if ((res=d1_stack[*d1_level]) && res->which == DATA1N_data)
-    {
-        if (elen + res->u.data.len <= DATA1_LOCALDATA)
-            memcpy (res->u.data.data + res->u.data.len, ebuf, elen);
-        else
-        {
-            char *nb = xmalloc (elen + res->u.data.len);
-            memcpy (nb, res->u.data.data, res->u.data.len);
-            memcpy (nb + res->u.data.len, ebuf, elen);
-            if (res->u.data.len > DATA1_LOCALDATA)
-                xfree (res->u.data.data);
-            res->u.data.data = nb;
-            res->destroy = destroy_data;
-        }
-        res->u.data.len += elen;
-    }
+
+    res = data1_mk_node (spec->dh, spec->m);
+    res->parent = parent;
+    res->which = DATA1N_data;
+    res->u.data.what = DATA1I_text;
+    res->u.data.len = elen;
+    res->u.data.formatted_text = formatted_text;
+    if (elen > DATA1_LOCALDATA)
+       res->u.data.data = nmem_malloc (spec->m, elen);
     else
-    {
-        res = data1_mk_node (spec->dh, spec->m);
-        res->parent = parent;
-        res->which = DATA1N_data;
-        res->u.data.what = DATA1I_text;
-        res->u.data.len = elen;
-        res->u.data.formatted_text = formatted_text;
-        if (elen > DATA1_LOCALDATA)
-            res->u.data.data = nmem_malloc (spec->m, elen);
-        else
-            res->u.data.data = res->lbuf;
-        memcpy (res->u.data.data, ebuf, elen);
-        res->root = parent->root;
-        
-        parent->last_child = res;
-        if (d1_stack[*d1_level])
-            d1_stack[*d1_level]->next = res;
-        else
-            parent->child = res;
-        d1_stack[*d1_level] = res;
-    }
+       res->u.data.data = res->lbuf;
+    memcpy (res->u.data.data, ebuf, elen);
+    res->root = parent->root;
+    
+    parent->last_child = res;
+    if (d1_stack[*d1_level])
+       d1_stack[*d1_level]->next = res;
+    else
+       parent->child = res;
+    d1_stack[*d1_level] = res;
 }
 
 static void execDataP (struct lexSpec *spec,
@@ -827,6 +827,19 @@ static void variantBegin (struct lexSpec *spec,
     d1_stack[++(*d1_level)] = NULL;
 }
 
+static void tagStrip (const char **tag, int *len)
+{
+    int i;
+
+    for (i = *len; i > 0 && isspace((*tag)[i-1]); --i)
+        ;
+    *len = i;
+    for (i = 0; i < *len && isspace((*tag)[i]); i++)
+        ;
+    *tag += i;
+    *len -= i;
+}
+
 static void tagBegin (struct lexSpec *spec, 
                       data1_node **d1_stack, int *d1_level,
                       const char *tag, int len)
@@ -843,17 +856,20 @@ static void tagBegin (struct lexSpec *spec,
         logf (LOG_WARN, "in element begin. No record type defined");
         return ;
     }
-    
+    tagStrip (&tag, &len);
+   
     res = data1_mk_node (spec->dh, spec->m);
     res->parent = parent;
     res->which = DATA1N_tag;
     res->u.tag.get_bytes = -1;
 
     if (len >= DATA1_LOCALDATA)
-        len = DATA1_LOCALDATA-1;
-    memcpy (res->lbuf, tag, len);
-    res->lbuf[len] = '\0';
-    res->u.tag.tag = res->lbuf;
+       res->u.tag.tag = nmem_malloc (spec->m, len+1);
+    else
+       res->u.tag.tag = res->lbuf;
+
+    memcpy (res->u.tag.tag, tag, len);
+    res->u.tag.tag[len] = '\0';
    
 #if REGX_DEBUG 
     logf (LOG_DEBUG, "begin tag %s (%d)", res->u.tag.tag, *d1_level);
@@ -882,12 +898,15 @@ static void tagBegin (struct lexSpec *spec,
 }
 
 static void tagEnd (struct lexSpec *spec, 
-                    data1_node **d1_stack, int *d1_level,
+                    data1_node **d1_stack, int *d1_level, int min_level,
                     const char *tag, int len)
 {
-    while (*d1_level > 1)
+    tagStrip (&tag, &len);
+    while (*d1_level > min_level)
     {
         (*d1_level)--;
+        if (*d1_level == 0)
+           break;
         if ((d1_stack[*d1_level]->which == DATA1N_tag) &&
            (!tag ||
             (strlen(d1_stack[*d1_level]->u.tag.tag) == (size_t) len &&
@@ -1202,23 +1221,30 @@ static int execCode (struct lexSpec *spec,
            }
            else if (!strcmp (p, "element"))
            {
-               r = execTok (spec, &s, arg_no, arg_start, arg_end,
-                            &cmd_str, &cmd_len);
-#if 0
-               if (*d1_level == 1)
-               {
-                   *d1_level = 0;
-                   returnCode = 0;
-               }
-#endif
+                int min_level = 1;
+                while ((r = execTok (spec, &s, arg_no, arg_start, arg_end,
+                                     &cmd_str, &cmd_len)) == 3)
+                {
+                    if (cmd_len==7 && !memcmp ("-record", cmd_str, cmd_len))
+                        min_level = 0;
+                }
                if (r > 2)
                {
-                   tagEnd (spec, d1_stack, d1_level, cmd_str, cmd_len);
+                   tagEnd (spec, d1_stack, d1_level, min_level,
+                            cmd_str, cmd_len);
                    r = execTok (spec, &s, arg_no, arg_start, arg_end,
                                 &cmd_str, &cmd_len);
                }
                else
-                   tagEnd (spec, d1_stack, d1_level, NULL, 0);
+                   tagEnd (spec, d1_stack, d1_level, min_level, NULL, 0);
+                if (*d1_level == 0)
+                {
+#if REGX_DEBUG
+                   logf (LOG_DEBUG, "end element end records");
+#endif
+                   returnCode = 0;
+                }
+
            }
            else if (!strcmp (p, "context"))
            {
@@ -1270,7 +1296,7 @@ static int execCode (struct lexSpec *spec,
                          &cmd_str, &cmd_len);
             } while (r > 1);
             if (element_str)
-                tagEnd (spec, d1_stack, d1_level, NULL, 0);
+                tagEnd (spec, d1_stack, d1_level, 1, NULL, 0);
         }
         else if (!strcmp (p, "unread"))
         {
@@ -1605,6 +1631,7 @@ data1_node *grs_read_regx (struct grs_read_info *p)
             return NULL;
         }
     }
+    curLexSpec->dh = p->dh;
     if (!p->offset)
     {
         curLexSpec->f_win_start = 0;