texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[5638] garbage collection


From: Gavin D. Smith
Subject: [5638] garbage collection
Date: Wed, 04 Jun 2014 23:55:31 +0000

Revision: 5638
          http://svn.sv.gnu.org/viewvc/?view=rev&root=texinfo&revision=5638
Author:   gavin
Date:     2014-06-04 23:55:29 +0000 (Wed, 04 Jun 2014)
Log Message:
-----------
garbage collection

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/info/Makefile.am
    trunk/info/footnotes.c
    trunk/info/info.h
    trunk/info/nodes.c
    trunk/info/nodes.h
    trunk/info/session.c
    trunk/info/session.h

Removed Paths:
-------------
    trunk/info/gc.c
    trunk/info/gc.h

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog     2014-06-03 19:38:11 UTC (rev 5637)
+++ trunk/ChangeLog     2014-06-04 23:55:29 UTC (rev 5638)
@@ -1,3 +1,26 @@
+2014-06-05  Gavin Smith  <address@hidden>
+
+       * info/session.c (free_history_node): New function.  Free references
+       for internal nodes.
+       (forget_node, forget_window_and_nodes): Call free_history_node.
+       (info_split_window): Copy references if node in window is an internal
+       one.
+       (info_delete_window): Formatting.
+       (info_delete_window_internal): Remove out-of-date comment.
+
+       * info/session.c (gc_file_buffers_and_nodes): New function to
+       replace info_gc_file_buffers and gc_pointers.  All callers updated.
+       (add_gcable_pointer, gcable_pointers, gcable_pointers_index)
+       (gcable_pointers_slots): Moved from info/gc.c.
+       * info/gc.c, info/gc.h: Files removed.  (Copyright years were a
+       subset of those in session.c.)
+
+       * info/nodes.c (info_loaded_files_index): New variable.
+       (remember_info_file): Merged into info_load_file.
+       (forget_info_file): Declared as static.
+
+       * info/nodes.h: Changes to comments and formatting.
+
 2014-06-03  Gavin Smith  <address@hidden>
 
        * info/session.c (remember_window_and_node, info_set_node_of_window):

Modified: trunk/info/Makefile.am
===================================================================
--- trunk/info/Makefile.am      2014-06-03 19:38:11 UTC (rev 5637)
+++ trunk/info/Makefile.am      2014-06-04 23:55:29 UTC (rev 5638)
@@ -34,7 +34,7 @@
 
 ginfo_SOURCES = dir.c display.c display.h doc.h dribble.c dribble.h \
   echo-area.c echo-area.h \
-  filesys.c filesys.h footnotes.c footnotes.h gc.c gc.h \
+  filesys.c filesys.h footnotes.c footnotes.h \
   indices.c indices.h info-utils.c info-utils.h info.c info.h infodoc.c \
   infomap.c infomap.h infopath.c m-x.c man.c man.h nodemenu.c nodes.c nodes.h \
   search.c search.h session.c session.h signals.c signals.h \

Modified: trunk/info/footnotes.c
===================================================================
--- trunk/info/footnotes.c      2014-06-03 19:38:11 UTC (rev 5637)
+++ trunk/info/footnotes.c      2014-06-04 23:55:29 UTC (rev 5638)
@@ -247,7 +247,6 @@
      because we check if we are in the footnote window above. */
   info_set_node_of_window (fn_win, new_footnotes);
   add_gcable_pointer (new_footnotes->contents);
-  /* TODO: Make sure new_footnotes->references are freed properly. */
   fn_win->flags |= W_TempWindow;
 
   /* Make the height be the number of lines appearing in the footnotes. */

Deleted: trunk/info/gc.c
===================================================================
--- trunk/info/gc.c     2014-06-03 19:38:11 UTC (rev 5637)
+++ trunk/info/gc.c     2014-06-04 23:55:29 UTC (rev 5638)
@@ -1,92 +0,0 @@
-/* gc.c -- Functions to remember and garbage collect unused node contents.
-   $Id$
-
-   Copyright 1993, 2004, 2007, 2008, 2013
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or (at
-   your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-   Originally written by Brian Fox. */
-
-#include "info.h"
-
-/* Array of pointers to the contents of gc-able nodes.  A pointer on this
-   list can be garbage collected when no info window contains a node whose
-   contents member match the pointer. */
-static char **gcable_pointers = NULL;
-static size_t gcable_pointers_index = 0;
-static size_t gcable_pointers_slots = 0;
-
-/* Add POINTER to the list of garbage collectible pointers.  A pointer
-   is not actually garbage collected until no info window contains a node
-   whose contents member is equal to the pointer. */
-void
-add_gcable_pointer (char *pointer)
-{
-  gc_pointers ();
-  add_pointer_to_array (pointer, gcable_pointers_index, gcable_pointers,
-                       gcable_pointers_slots, 10);
-}
-
-/* Grovel the list of info windows and gc-able pointers finding those
-   node->contents which are collectible, and free them. */
-void
-gc_pointers (void)
-{
-  size_t i, j, k;
-  WINDOW *iw;
-  char **new = NULL;
-  size_t new_index = 0;
-  size_t new_slots = 0;
-
-  if (!gcable_pointers_index)
-    return;
-
-  for (iw = windows; iw; iw = iw->next)
-    {
-      for (j = 0; j < iw->hist_index; j++)
-       {
-         NODE *node = iw->hist[j]->node;
-
-         /* If this node->contents appears in our list of gcable_pointers,
-            it is not gc-able, so save it. */
-         for (k = 0; k < gcable_pointers_index; k++)
-           if (gcable_pointers[k] == node->contents)
-             {
-               add_pointer_to_array (node->contents, new_index, new, 
-                                      new_slots, 10);
-               break;
-             }
-       }
-    }
-
-  /* We have gathered all of the pointers which need to be saved.  Free any
-     of the original pointers which do not appear in the new list. */
-  for (i = 0; i < gcable_pointers_index; i++)
-    {
-      for (j = 0; j < new_index; j++)
-       if (gcable_pointers[i] == new[j])
-         break;
-
-      /* If we got all the way through the new list, then the old pointer
-        can be garbage collected. */
-      if (new && !new[j])
-       free (gcable_pointers[i]);
-    }
-
-  free (gcable_pointers);
-  gcable_pointers = new;
-  gcable_pointers_slots = new_slots;
-  gcable_pointers_index = new_index;
-}

Deleted: trunk/info/gc.h
===================================================================
--- trunk/info/gc.h     2014-06-03 19:38:11 UTC (rev 5637)
+++ trunk/info/gc.h     2014-06-04 23:55:29 UTC (rev 5638)
@@ -1,34 +0,0 @@
-/* gc.h -- Functions for garbage collecting unused node contents.
-   $Id$
-
-   Copyright 1993, 1997, 2004, 2007, 2013
-   Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-   Originally written by Brian Fox. */
-
-#ifndef INFO_GC_H
-#define INFO_GC_H
-
-/* Add POINTER to the list of garbage collectible pointers.  A pointer
-   is not actually garbage collected until no info window contains a node
-   whose contents member is equal to the pointer. */
-extern void add_gcable_pointer (char *pointer);
-
-/* Grovel the list of info windows and gc-able pointers finding those
-   node->contents which are collectible, and free them. */
-extern void gc_pointers (void);
-
-#endif /* not INFO_GC_H */

Modified: trunk/info/info.h
===================================================================
--- trunk/info/info.h   2014-06-03 19:38:11 UTC (rev 5637)
+++ trunk/info/info.h   2014-06-04 23:55:29 UTC (rev 5638)
@@ -40,7 +40,6 @@
 #include "session.h"
 #include "echo-area.h"
 #include "footnotes.h"
-#include "gc.h"
 
 #include "string.h"
 #include "mbiter.h"

Modified: trunk/info/nodes.c
===================================================================
--- trunk/info/nodes.c  2014-06-03 19:38:11 UTC (rev 5637)
+++ trunk/info/nodes.c  2014-06-04 23:55:29 UTC (rev 5638)
@@ -34,9 +34,12 @@
 /* When non-zero, this is a string describing the recent file error. */
 char *info_recent_file_error = NULL;
 
-/* The list of already loaded nodes. */
+/* The list of already loaded files. */
 FILE_BUFFER **info_loaded_files = NULL;
 
+/* Number of loaded files. */
+size_t info_loaded_files_index = 0;
+
 /* The number of slots currently allocated to LOADED_FILES. */
 size_t info_loaded_files_slots = 0;
 
@@ -566,7 +569,7 @@
 static FILE_BUFFER *info_load_file (char *fullpath, int get_tags);
 static FILE_BUFFER *info_find_subfile (char *filename);
 static void get_file_character_encoding (FILE_BUFFER *fb);
-static void remember_info_file (FILE_BUFFER *file_buffer);
+static void forget_info_file (char *filename);
 static void info_reload_file_buffer_contents (FILE_BUFFER *fb);
 
 /* Locate the file named by FILENAME, and return the information structure
@@ -755,7 +758,8 @@
 
   /* If the file was loaded, remember the name under which it was found. */
   if (file_buffer)
-    remember_info_file (file_buffer);
+    add_pointer_to_array (file_buffer, info_loaded_files_index,
+                          info_loaded_files, info_loaded_files_slots, 10);
 
   return file_buffer;
 }
@@ -822,21 +826,8 @@
   return file_buffer;
 }
 
-/* Add FILE_BUFFER to our list of already loaded info files. */
-static void
-remember_info_file (FILE_BUFFER *file_buffer)
-{
-  int i;
-
-  for (i = 0; info_loaded_files && info_loaded_files[i]; i++)
-    ;
-
-  add_pointer_to_array (file_buffer, i, info_loaded_files,
-                        info_loaded_files_slots, 10);
-}
-
 /* Forget the contents, tags table, nodes list, and names of FILENAME. */
-void
+static void
 forget_info_file (char *filename)
 {
   int i;

Modified: trunk/info/nodes.h
===================================================================
--- trunk/info/nodes.h  2014-06-03 19:38:11 UTC (rev 5637)
+++ trunk/info/nodes.h  2014-06-04 23:55:29 UTC (rev 5638)
@@ -25,8 +25,6 @@
 #include "info.h"
 #include "search.h"
 
-/* User code interface.  */
-
 /* Structure which describes a node reference, such as a menu entry or
    cross reference. */
 typedef struct {
@@ -79,8 +77,6 @@
 #define N_IsManPage    0x40     /* This node is a manpage. */
 #define N_FromAnchor   0x80     /* Synthesized for an anchor reference. */
 #define N_WasRewritten 0x100    /* NODE->contents can be passed to free(). */ 
-
-/* Internal data structures.  */
 
 /* String constants. */
 #define INFO_FILE_LABEL                 "File:"
@@ -100,7 +96,6 @@
 #define LOCAL_VARIABLES_LABEL           "Local Variables"
 #define CHARACTER_ENCODING_LABEL        "coding:"
 
-
 /* Character constants. */
 #define INFO_COOKIE '\037'
 #define INFO_FF     '\014'
@@ -132,13 +127,10 @@
   int flags;                    /* Various flags.  Mimics of N_* flags. */
   char *encoding;               /* Name of character encoding of file. */
 } FILE_BUFFER;
-
-/* Externally visible functions.  */
 
 /* Array of FILE_BUFFER * which represents the currently loaded info files. */
 extern FILE_BUFFER **info_loaded_files;
-
-/* The number of slots currently allocated to INFO_LOADED_FILES. */
+extern size_t info_loaded_files_index;
 extern size_t info_loaded_files_slots;
 
 /* Locate the file named by FILENAME, and return the information structure
@@ -188,8 +180,6 @@
 
 /* Create a new, empty file buffer. */
 extern FILE_BUFFER *make_file_buffer (void);
-
-void forget_info_file (char *filename);
 
 /* Found in dir.c */
 extern NODE *get_dir_node (void);

Modified: trunk/info/session.c
===================================================================
--- trunk/info/session.c        2014-06-03 19:38:11 UTC (rev 5637)
+++ trunk/info/session.c        2014-06-04 23:55:29 UTC (rev 5638)
@@ -37,8 +37,6 @@
 #  define HAVE_STRUCT_TIMEVAL
 #endif /* HAVE_SYS_TIME_H */
 
-static void info_gc_file_buffers (void);
-
 static void info_clear_pending_input (void);
 static void info_set_pending_input (unsigned char key);
 static void info_handle_pointer (char *label, WINDOW *window);
@@ -46,6 +44,7 @@
 char *node_printed_rep (NODE *node);
 
 static REFERENCE *select_menu_digit (WINDOW *window, unsigned char key);
+static void gc_file_buffers_and_nodes (void);
 
 /* Warning!  Any change to the order of the commands defined with
    DECLARE_INFO_COMMAND in this file results in an incompatible .info
@@ -307,6 +306,17 @@
 /*                                                                  */
 /* **************************************************************** */
 
+static void
+free_history_node (NODE *n)
+{
+  /* References of internal nodes are not stored anywhere else.  The
+     contents fields were recorded with add_gcable_pointer. */
+  if (n->flags & N_IsInternal)
+    info_free_references (n->references);
+
+  free (n);
+}
+
 /* Go back one in the node history. */
 void
 forget_node (WINDOW *win)
@@ -315,7 +325,7 @@
   if (i == 0)
     return;
 
-  free (win->hist[i - 1]->node);
+  free_history_node (win->hist[i - 1]->node);
   free (win->hist[i - 1]);
   win->hist[i - 1] = 0;
   i = --win->hist_index;
@@ -333,7 +343,7 @@
   int i;
   for (i = 0; i < win->hist_index; i++)
     {
-      free (win->hist[i]->node);
+      free_history_node (win->hist[i]->node);
       free (win->hist[i]);
     }
   free (win->hist);
@@ -1266,18 +1276,21 @@
    are automatically tiling windows, re-tile after the split. */
 DECLARE_INFO_COMMAND (info_split_window, _("Split the current window"))
 {
-  WINDOW *split;
-  NODE *copy;
-  
-  copy = xmalloc (sizeof (NODE));
-  *copy = *window->node; /* Field-by-field copy of structure. */
-  /* Make the new window. */
-  split = window_make_window ();
+  WINDOW *split = window_make_window ();
 
   if (!split)
     info_error ("%s", msg_win_too_small);
   else
     {
+      NODE *copy = xmalloc (sizeof (NODE));
+      *copy = *window->node; /* Field-by-field copy of structure. */
+
+      /* References in internal nodes are not stored in a tag table.  This
+         allows us to free internal nodes without checking if their
+         references are shared by other NODE objects. */
+      if (copy->flags & N_IsInternal)
+        copy->references = info_copy_references (copy->references);
+
       info_set_node_of_window (split, copy);
       /* Make sure point still appears in the active window. */
       info_show_point (window);
@@ -1298,13 +1311,9 @@
 DECLARE_INFO_COMMAND (info_delete_window, _("Delete the current window"))
 {
   if (!windows->next)
-    {
-      info_error ("%s", msg_cant_kill_last);
-    }
+    info_error ("%s", msg_cant_kill_last);
   else if (window->flags & W_WindowIsPerm)
-    {
-      info_error ("%s", _("Cannot delete a permanent window"));
-    }
+    info_error ("%s", _("Cannot delete a permanent window"));
   else
     {
       info_delete_window_internal (window);
@@ -1315,7 +1324,7 @@
       if (auto_tiling_p)
         window_tile_windows (DONT_TILE_INTERNALS);
 
-      info_gc_file_buffers ();
+      gc_file_buffers_and_nodes ();
     }
 }
 
@@ -1326,8 +1335,6 @@
 {
   if (windows->next && ((window->flags & W_WindowIsPerm) == 0))
     {
-      /* We not only delete the window from the display, we forget it from
-         our list of remembered windows. */
       forget_window_and_nodes (window);
       window_delete_window (window);
 
@@ -3198,7 +3205,6 @@
    to gc even those file buffer contents which had to be uncompressed. */
 int gc_compressed_files = 0;
 
-static void info_gc_file_buffers (void);
 static void info_search_1 (WINDOW *window, int count,
                           unsigned char key, int case_sensitive,
                           int ask_for_string, long start);
@@ -3701,7 +3707,7 @@
 
   /* Perhaps free the unreferenced file buffers that were searched, but
      not retained. */
-  info_gc_file_buffers ();
+  gc_file_buffers_and_nodes ();
 }
 
 int search_skip_screen_p = 0;
@@ -4171,15 +4177,38 @@
   free_isearch_states ();
 
   /* Perhaps GC some file buffers. */
-  info_gc_file_buffers ();
+  gc_file_buffers_and_nodes ();
 
   /* After searching, leave the window in the correct state. */
   if (!echo_area_is_active)
     window_clear_echo_area ();
 }
 
-/* Find tag table entries for nodes which have been rewritten, and free
-   their contents. */
+
+/* **************************************************************** */
+/*                                                                  */
+/*                      Garbage collection                          */
+/*                                                                  */
+/* **************************************************************** */
+
+
+/* Contents of displayed nodes with no corresponding file buffer. */
+static char **gcable_pointers = NULL;
+static size_t gcable_pointers_index = 0;
+static size_t gcable_pointers_slots = 0;
+
+/* Add POINTER to the list of garbage collectible pointers.  A pointer
+   is not garbage collected until no window contains a node whose contents
+   member is equal to the pointer. */
+void
+add_gcable_pointer (char *pointer)
+{
+  add_pointer_to_array (pointer, gcable_pointers_index, gcable_pointers,
+                       gcable_pointers_slots, 10);
+}
+
+/* Free contents of rewritten nodes in the file's tag table.  This will
+   do nothing for a subfile of a split file. */
 static void
 free_node_contents (FILE_BUFFER *fb)
 {
@@ -4197,75 +4226,119 @@
       }
 }
 
-
-/* GC some file buffers.  A file buffer can be gc-ed if there we have
-   no nodes in INFO_WINDOWS that reference this file buffer's contents.
-   Garbage collecting a file buffer means to free the file buffers
-   contents. */
 static void
-info_gc_file_buffers (void)
+gc_file_buffers_and_nodes (void)
 {
-  register int fb_index, iw_index, i;
-  register FILE_BUFFER *fb;
-  register WINDOW *iw;
+  /* Array to record whether each file buffer was referenced or not. */
+  int *fb_referenced = xcalloc (info_loaded_files_index, sizeof (int));
+  WINDOW *win;
+  int i, j;
+  int fb_index, nc_index;
 
-  if (!info_loaded_files)
-    return;
+  /* New value of gcable_pointers. */
+  char **new = NULL;
+  size_t new_index = 0;
+  size_t new_slots = 0;
 
-  for (fb_index = 0; (fb = info_loaded_files[fb_index]); fb_index++)
+  /* Loop over nodes in the history of displayed windows recording which
+     nodes and file buffers were referenced. */
+  for (win = windows; win; win = win->next)
     {
-      int fb_referenced_p = 0, parent_referenced_p = 0;
-
-      /* If already gc-ed, do nothing. */
-      if (!fb->contents)
+      if (!win->hist)
         continue;
+      for (i = 0; win->hist[i]; i++)
+        {
+          NODE *n = win->hist[i]->node;
 
-      /* If this file had to be uncompressed, check to see if we should
-         gc it.  This means that the user-variable "gc-compressed-files"
-         is non-zero. */
-      if ((fb->flags & N_IsCompressed) && !gc_compressed_files)
-        continue;
+          /* Loop over file buffers. */
+          for (fb_index = 0; fb_index < info_loaded_files_index; fb_index++)
+            {
+              FILE_BUFFER *fb = info_loaded_files[fb_index];
 
-      /* If this file's contents are not gc-able, move on. */
-      if (fb->flags & N_CannotGC)
-        continue;
-
-      /* Check each window to see if it has any nodes which reference
-         this file. */
-      for (iw = windows; iw; iw = iw->next)
-        {
-          for (i = 0; iw->hist && iw->hist[i]; i++)
-            {
-              NODE *n = iw->hist[i]->node;
-              if (n->filename
-                  && ((FILENAME_CMP (fb->fullpath, n->filename) == 0)
-                      || (FILENAME_CMP (fb->filename, n->filename) == 0)))
+              if (fb->flags & N_TagsIndirect)
                 {
-                  fb_referenced_p = 1;
-                  break;
+                  if (n->parent
+                      && (FILENAME_CMP (fb->fullpath, n->parent) == 0))
+                    {
+                      fb_referenced[fb_index] = 1;
+                      break;
+                    }
                 }
-
-              /* If any subfile of a split file is referenced, none of
-                 the rewritten nodes in the split file is freed. */
-              if (n->parent
-                 && ((FILENAME_CMP (fb->fullpath, n->parent) == 0)
-                      || (FILENAME_CMP (fb->filename, n->parent) == 0)))
+              else
                 {
-                  parent_referenced_p = 1;
-                  break;
+                  if (n->filename
+                      && (FILENAME_CMP (fb->fullpath, n->filename) == 0))
+                    {
+                      fb_referenced[fb_index] = 1;
+                      break;
+                    }
                 }
+
             }
+
+          /* Loop over gcable_pointers. */
+          for (nc_index = 0; nc_index < gcable_pointers_index; nc_index++)
+            if (n->contents == gcable_pointers[nc_index])
+              {
+                add_pointer_to_array (n->contents, new_index, new, 
+                                      new_slots, 10);
+                break;
+              }
         }
+    }
 
-      /* If this file buffer wasn't referenced, free its contents. */
-      if (!fb_referenced_p)
+  /* Free unreferenced file buffers. */
+  for (i = 0; i < info_loaded_files_index; i++)
+    {
+      if (!fb_referenced[i])
         {
-          if (!parent_referenced_p)
-            free_node_contents (fb);
+          FILE_BUFFER *fb = info_loaded_files[i];
+
+          if (fb->flags & N_TagsIndirect)
+            {
+              free_node_contents (fb);
+              continue;
+            }
+
+          /* If already gc-ed, do nothing. */
+          if (!fb->contents)
+            continue;
+
+          /* If this file had to be uncompressed, check to see if we should
+             gc it.  This means that the user-variable "gc-compressed-files"
+             is non-zero. */
+          if ((fb->flags & N_IsCompressed) && !gc_compressed_files)
+            continue;
+
+          /* If this file's contents are not gc-able, move on. */
+          if (fb->flags & N_CannotGC)
+            continue;
+
+          free_node_contents (fb);
           free (fb->contents);
-          fb->contents = NULL;
+          fb->contents = 0;
         }
     }
+
+  /* Free unreferenced node contents and update gcable_pointers. */
+  for (i = 0; i < gcable_pointers_index; i++)
+    {
+      for (j = 0; j < new_index; j++)
+       if (gcable_pointers[i] == new[j])
+         break;
+
+      /* If we got all the way through the new list, then the old pointer
+        can be garbage collected. */
+      if (!new || j == new_index)
+       free (gcable_pointers[i]);
+    }
+
+  free (gcable_pointers);
+  gcable_pointers = new;
+  gcable_pointers_slots = new_slots;
+  gcable_pointers_index = new_index;
+
+  free (fb_referenced);
 }
 
 

Modified: trunk/info/session.h
===================================================================
--- trunk/info/session.h        2014-06-03 19:38:11 UTC (rev 5637)
+++ trunk/info/session.h        2014-06-04 23:55:29 UTC (rev 5638)
@@ -43,6 +43,11 @@
    to gc even those file buffer contents which had to be uncompressed. */
 extern int gc_compressed_files;
 
+/* Add POINTER to the list of garbage collectible pointers.  A pointer
+   is not actually garbage collected until no info window contains a node
+   whose contents member is equal to the pointer. */
+extern void add_gcable_pointer (char *pointer);
+
 /* When non-zero, tiling takes place automatically when info_split_window
    is called. */
 extern int auto_tiling_p;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]