X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flibpspp%2Fpool.c;h=c39852dcc7a2977becee7d8c0b970c11d52471d4;hb=a8915a78655ea9ff6242ba6ba4ed4d83253a323d;hp=105937b99885262c2e8d0ec609f61bc471f09087;hpb=dcf9b154cbcaa35c3d8459a201b77eec8bcb30bd;p=pspp diff --git a/src/libpspp/pool.c b/src/libpspp/pool.c index 105937b998..c39852dcc7 100644 --- a/src/libpspp/pool.c +++ b/src/libpspp/pool.c @@ -1,6 +1,5 @@ /* PSPP - computes sample statistics. Copyright (C) 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . 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 #include "alloc.h" +#include #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 - 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, @@ -364,6 +364,72 @@ pool_strdup (struct pool *pool, const char *string) { 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; +} /* Standard allocation routines. */ @@ -406,6 +472,34 @@ pool_nmalloc (struct pool *pool, size_t n, size_t 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. @@ -621,20 +715,20 @@ pool_add_subpool (struct pool *pool, struct pool *subpool) 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 * -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; - 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; } @@ -710,8 +804,8 @@ pool_register (struct pool *pool, void (*free) (void *), void *p) } /* 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); @@ -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); - return 1; + return true; } } - return 0; + return false; } /* Partial freeing. */ @@ -849,7 +943,7 @@ free_gizmo (struct pool_gizmo *gizmo) gizmo->p.registered.free (gizmo->p.registered.p); break; default: - assert (0); + NOT_REACHED (); } }