Fixed buglet in file open action.
[pspp] / src / libpspp / pool.c
index 105937b99885262c2e8d0ec609f61bc471f09087..141d8ab40323b94fea587ce801369bde6938b7aa 100644 (file)
@@ -1,6 +1,5 @@
 /* PSPP - computes sample statistics.
    Copyright (C) 2000 Free Software Foundation, Inc.
 /* PSPP - computes sample statistics.
    Copyright (C) 2000 Free Software Foundation, Inc.
-   Written by Ben Pfaff <blp@gnu.org>.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -21,6 +20,7 @@
 #include "pool.h"
 #include <stdlib.h>
 #include "alloc.h"
 #include "pool.h"
 #include <stdlib.h>
 #include "alloc.h"
+#include <libpspp/assertion.h>
 #include "message.h"
 #include "size_max.h"
 #include "str.h"
 #include "message.h"
 #include "size_max.h"
 #include "str.h"
@@ -100,8 +100,8 @@ union align
 
 /* DISCRETE_BLOCKS may be declared as nonzero to prevent
    suballocation of blocks.  This is useful under memory
 
 /* DISCRETE_BLOCKS may be declared as nonzero to prevent
    suballocation of blocks.  This is useful under memory
-   debuggers like Checker or valgrind because it allows the
-   source location of bugs to be more accurately pinpointed.
+   debuggers like valgrind because it allows the source location
+   of bugs to be more accurately pinpointed.
 
    On the other hand, if we're testing the library, then we want to
    test the library's real functionality, not its crippled, slow,
 
    On the other hand, if we're testing the library, then we want to
    test the library's real functionality, not its crippled, slow,
@@ -364,6 +364,72 @@ pool_strdup (struct pool *pool, const char *string)
 {
   return pool_clone_unaligned (pool, string, strlen (string) + 1);
 }
 {
   return pool_clone_unaligned (pool, string, strlen (string) + 1);
 }
+
+/* Formats FORMAT with the given ARGS in memory allocated from
+   POOL and returns the formatted string. */
+char *
+pool_vasprintf (struct pool *pool, const char *format, va_list args_)
+{
+  struct pool_block *b;
+  va_list args;
+  int needed, avail;
+  char *s;
+
+  va_copy (args, args_);
+  b = pool->blocks;
+  avail = BLOCK_SIZE - b->ofs;
+  s = ((char *) b) + b->ofs;
+  needed = vsnprintf (s, avail, format, args);
+  va_end (args);
+
+  if (needed >= 0) 
+    {
+      if (needed < avail) 
+        {
+          /* Success.  Reserve the space that was actually used. */
+          b->ofs += needed + 1;
+        }
+      else
+        {
+          /* Failure, but now we know how much space is needed.
+             Allocate that much and reformat. */
+          s = pool_alloc (pool, needed + 1);
+
+          va_copy (args, args_);
+          vsprintf (s, format, args);
+          va_end (args);
+        }
+    }
+  else 
+    {
+      /* Some old libc's returned -1 when the destination string
+         was too short.  This should be uncommon these days and
+         it's a rare case anyhow.  Use the easiest solution: punt
+         to dynamic allocation. */
+      va_copy (args, args_);
+      s = xvasprintf (format, args);
+      va_end (args);
+
+      pool_register (pool, free, s);
+    }
+
+  return s;
+}
+
+/* Formats FORMAT in memory allocated from POOL
+   and returns the formatted string. */
+char *
+pool_asprintf (struct pool *pool, const char *format, ...)
+{
+  va_list args;
+  char *string;
+  
+  va_start (args, format);
+  string = pool_vasprintf (pool, format, args);
+  va_end (args);
+
+  return string;
+}
 \f
 /* Standard allocation routines. */
 
 \f
 /* Standard allocation routines. */
 
@@ -621,20 +687,20 @@ pool_add_subpool (struct pool *pool, struct pool *subpool)
   subpool->parent = pool;
 }
 
   subpool->parent = pool;
 }
 
-/* Opens file FILENAME with mode MODE and returns a handle to it
+/* Opens file FILE_NAME with mode MODE and returns a handle to it
    if successful or a null pointer if not.
    The file will be closed automatically when POOL is destroyed, or it
    may be closed explicitly in advance using pool_fclose(), or
    detached from the pool with pool_detach_file(). */
 FILE *
    if successful or a null pointer if not.
    The file will be closed automatically when POOL is destroyed, or it
    may be closed explicitly in advance using pool_fclose(), or
    detached from the pool with pool_detach_file(). */
 FILE *
-pool_fopen (struct pool *pool, const char *filename, const char *mode)
+pool_fopen (struct pool *pool, const char *file_name, const char *mode)
 {
   FILE *f;
 
 {
   FILE *f;
 
-  assert (pool && filename && mode);
-  f = fopen (filename, mode);
-  if (f == NULL)
-    return NULL;
+  assert (pool && file_name && mode);
+  f = fopen (file_name, mode);
+  if (f != NULL)
+    pool_attach_file (pool, f);
 
   return f;
 }
 
   return f;
 }
@@ -710,8 +776,8 @@ pool_register (struct pool *pool, void (*free) (void *), void *p)
 }
 
 /* Unregisters previously registered P from POOL.
 }
 
 /* Unregisters previously registered P from POOL.
-   Returns nonzero only if P was found to be registered in POOL. */
-int
+   Returns true only if P was found to be registered in POOL. */
+bool
 pool_unregister (struct pool *pool, void *p)
 {
   assert (pool && p);
 pool_unregister (struct pool *pool, void *p)
 {
   assert (pool && p);
@@ -723,11 +789,11 @@ pool_unregister (struct pool *pool, void *p)
       if (g->type == POOL_GIZMO_REGISTERED && g->p.registered.p == p)
        {
          delete_gizmo (pool, g);
       if (g->type == POOL_GIZMO_REGISTERED && g->p.registered.p == p)
        {
          delete_gizmo (pool, g);
-         return 1;
+         return true;
        }
   }
   
        }
   }
   
-  return 0;
+  return false;
 }
 \f
 /* Partial freeing. */
 }
 \f
 /* Partial freeing. */
@@ -849,7 +915,7 @@ free_gizmo (struct pool_gizmo *gizmo)
       gizmo->p.registered.free (gizmo->p.registered.p);
       break;
     default:
       gizmo->p.registered.free (gizmo->p.registered.p);
       break;
     default:
-      assert (0);
+      NOT_REACHED ();
     }
 }
 
     }
 }