(psppire_var_store_item_editable): Use var_is_alpha.
[pspp] / src / libpspp / pool.c
index 105937b99885262c2e8d0ec609f61bc471f09087..c39852dcc7a2977becee7d8c0b970c11d52471d4 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. */
 
@@ -406,6 +472,34 @@ pool_nmalloc (struct pool *pool, size_t n, size_t s)
   return pool_malloc (pool, n * s);
 }
 
   return pool_malloc (pool, n * s);
 }
 
+/* Allocates AMT bytes using malloc(), to be managed by POOL,
+   zeros the block, and returns a pointer to the beginning of the
+   block.
+   If POOL is a null pointer, then allocates a normal memory block
+   with xmalloc().  */
+void *
+pool_zalloc (struct pool *pool, size_t amt)
+{
+  void *p = pool_malloc (pool, amt);
+  memset (p, 0, amt);
+  return p;
+}
+
+/* Allocates and returns N elements of S bytes each, to be
+   managed by POOL, and zeros the block.
+   If POOL is a null pointer, then allocates a normal memory block
+   with malloc().
+   N must be nonnegative, S must be positive.
+   Terminates the program if the memory cannot be obtained,
+   including the case where N * S overflows the range of size_t. */
+void *
+pool_calloc (struct pool *pool, size_t n, size_t s) 
+{
+  void *p = pool_nmalloc (pool, n, s);
+  memset (p, 0, n * s);
+  return p;
+}
+
 /* Changes the allocation size of the specified memory block P managed
    by POOL to AMT bytes and returns a pointer to the beginning of the
    block.
 /* Changes the allocation size of the specified memory block P managed
    by POOL to AMT bytes and returns a pointer to the beginning of the
    block.
@@ -621,20 +715,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 +804,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 +817,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 +943,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 ();
     }
 }
 
     }
 }