changeset 44735:98b894d1d3ad

(last_node): Make it a global variable. (process_file): Print the tags from the nodes as soon as possible, and delete the nodes. This brings down the memory occupancy as etags to almost the same level as when the #line directives were not parsed. (free_fdesc): New function. (find_entries): Use it. (invalidate_nodes): In etags mode, do not just mark the nodes as invalid, do delete them.
author Francesco Potortì <pot@gnu.org>
date Mon, 22 Apr 2002 14:11:26 +0000
parents 712ef4d4683e
children 2ae99744dc81
files lib-src/etags.c
diffstat 1 files changed, 87 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/lib-src/etags.c	Mon Apr 22 07:58:15 2002 +0000
+++ b/lib-src/etags.c	Mon Apr 22 14:11:26 2002 +0000
@@ -33,7 +33,7 @@
  *	Francesco Potort́ <pot@gnu.org> has maintained it since 1993.
  */
 
-char pot_etags_version[] = "@(#) pot revision number is 15.15";
+char pot_etags_version[] = "@(#) pot revision number is 15.16";
 
 #define	TRUE	1
 #define	FALSE	0
@@ -368,9 +368,10 @@
 static void process_file __P((char *, language *));
 static void find_entries __P((FILE *));
 static void free_tree __P((node *));
+static void free_fdesc __P((fdesc *));
 static void pfnote __P((char *, bool, char *, int, int, long));
 static void new_pfnote __P((char *, int, bool, char *, int, int, long));
-static void invalidate_nodes __P((fdesc *, node *));
+static void invalidate_nodes __P((fdesc *, node **));
 static void put_entries __P((node *));
 
 static char *concat __P((char *, char *, char *));
@@ -410,6 +411,7 @@
 static const int invalidcharno = -1;
 
 static node *nodehead;		/* the head of the binary tree of tags */
+static node *last_node;		/* the last node created */
 
 static linebuffer lb;		/* the current line */
 
@@ -1531,19 +1533,44 @@
     pfatal (file);
 
   /* If not Ctags, and if this is not metasource and if it contained no #line
-     directives, we can write the tags and free curfdp an all nodes pointing to
-     it. */
+     directives, we can write the tags and free all nodes pointing to
+     curfdp. */
   if (!CTAGS
-      && curfdp == fdhead	/* no #line directives in this file */
+      && curfdp->usecharno	/* no #line directives in this file */
       && !curfdp->lang->metasource)
     {
-      /* Write tags for file curfdp->taggedfname. */
-      ;
+      node *np, *prev;
+
+      /* Look for the head of the sublist relative to this file.  See add_node
+	 for the structure of the node tree. */
+      prev = NULL;
+      for (np = nodehead; np != NULL; prev = np, np = np->left)
+	if (np->fdp == curfdp)
+	  break;
+
+      /* If we generated tags for this file, write and delete them. */
+      if (np != NULL)
+	{
+	  /* This is the head of the last sublist, if any.  The following
+	     instructions depend on this being true. */
+	  assert (np->left == NULL);
+
+	  assert (fdhead == curfdp);
+	  assert (last_node->fdp == curfdp);
+	  put_entries (np);	/* write tags for file curfdp->taggedfname */
+	  free_tree (np);	/* remove the written nodes */
+	  if (prev == NULL)
+	    nodehead = NULL;	/* no nodes left */
+	  else
+	    prev->left = NULL;	/* delete the pointer to the sublist */
+	}
     }
 
  cleanup:
   if (compressed_name) free (compressed_name);
   if (uncompressed_name) free (uncompressed_name);
+  last_node = NULL;
+  curfdp = NULL;
   return;
 }
 
@@ -1578,8 +1605,6 @@
  * This routine opens the specified file and calls the function
  * which finds the function and type definitions.
  */
-static node *last_node = NULL;
-
 static void
 find_entries (inf)
      FILE *inf;
@@ -1677,17 +1702,10 @@
 		       badfdp->taggedfname, badfdp->infname);
 
 	    /* Delete the tags referring to badfdp. */
-	    invalidate_nodes (badfdp, nodehead);
+	    invalidate_nodes (badfdp, &nodehead);
 
 	    *fdpp = badfdp->next; /* remove the bad description from the list */
-
-	    /* Delete badfdp. */
-	    if (badfdp->infname != NULL) free (badfdp->infname);
-	    if (badfdp->infabsname != NULL) free (badfdp->infabsname);
-	    if (badfdp->infabsdir != NULL) free (badfdp->infabsdir);
-	    if (badfdp->taggedfname != NULL) free (badfdp->taggedfname);
-	    if (badfdp->prop != NULL) free (badfdp->prop);
-	    free (badfdp);
+	    free_fdesc (badfdp);
 	  }
 	else
 	  fdpp = &(*fdpp)->next; /* advance the list pointer */
@@ -1850,6 +1868,22 @@
 }
 
 /*
+ * free_fdesc ()
+ *	delete a file description
+ */
+static void
+free_fdesc (fdp)
+     register fdesc *fdp;
+{
+  if (fdp->infname != NULL) free (fdp->infname);
+  if (fdp->infabsname != NULL) free (fdp->infabsname);
+  if (fdp->infabsdir != NULL) free (fdp->infabsdir);
+  if (fdp->taggedfname != NULL) free (fdp->taggedfname);
+  if (fdp->prop != NULL) free (fdp->prop);
+  free (fdp);
+}
+
+/*
  * add_node ()
  *	Adds a node to the tree of nodes.  In etags mode, sort by file
  *  	name.  In ctags mode, sort by tag name.  Make no attempt at
@@ -1873,16 +1907,16 @@
     }
 
   if (!CTAGS)
+    /* Etags Mode */
     {
-      /* Etags Mode */
-      assert (last_node != NULL);
       /* For each file name, tags are in a linked sublist on the right
 	 pointer.  The first tags of different files are a linked list
 	 on the left pointer.  last_node points to the end of the last
 	 used sublist. */
-      if (last_node->fdp == np->fdp)
+      if (last_node != NULL && last_node->fdp == np->fdp)
 	{
 	  /* Let's use the same sublist as the last added node. */
+	  assert (last_node->right == NULL);
 	  last_node->right = np;
 	  last_node = np;
 	}
@@ -1896,7 +1930,8 @@
 	/* The head of this sublist is not good for us.  Let's try the
 	   next one. */
 	add_node (np, &cur_node->left);
-    }
+    } /* if ETAGS mode */
+
   else
     {
       /* Ctags Mode */
@@ -1930,28 +1965,44 @@
 
       /* Actually add the node */
       add_node (np, dif < 0 ? &cur_node->left : &cur_node->right);
-    }
+    } /* if CTAGS mode */
 }
 
 /*
  * invalidate_nodes ()
  *	Scan the node tree and invalidate all nodes pointing to the
- *	given file description.
+ *	given file description (CTAGS case) or free them (ETAGS case).
  */
 static void
-invalidate_nodes (badfdp, np)
+invalidate_nodes (badfdp, npp)
      fdesc *badfdp;
-     node *np;
+     node **npp;
 {
-  if (np->left != NULL)
-    invalidate_nodes (badfdp, np->left);
-  /* Memory leak here: if not CTAGS, in which case it would be quite
-     difficult, the node could be freed.  If CTAGS the node is part of a
-     binary tree, if not it is part of a list of lists. */
-  if (np->fdp == badfdp)
-    np-> valid = FALSE;
-  if (np->right != NULL)
-    invalidate_nodes (badfdp, np->right);
+  node *np = *npp;
+
+  if (np == NULL)
+    return;
+
+  if (CTAGS)
+    {
+      if (np->left != NULL)
+	invalidate_nodes (badfdp, &np->left);
+      if (np->fdp == badfdp)
+	np-> valid = FALSE;
+      if (np->right != NULL)
+	invalidate_nodes (badfdp, &np->right);
+    }
+  else
+    {
+      node **next = &np->left;
+      if (np->fdp == badfdp)
+	{
+	  *npp = *next;		/* detach the sublist from the list */
+	  np->left = NULL;	/* isolate it */
+	  free_tree (np);	/* free it */
+	}
+      invalidate_nodes (badfdp, next);
+    }
 }
 
 
@@ -6138,6 +6189,6 @@
  * indent-tabs-mode: t
  * tab-width: 8
  * fill-column: 79
- * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc")
+ * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node")
  * End:
  */