summaryrefslogtreecommitdiff
path: root/lib/obstack.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1997-02-04 03:20:29 +0000
committerJim Meyering <jim@meyering.net>1997-02-04 03:20:29 +0000
commite4ccac4d27caeef527ef24982b9873837bd17d60 (patch)
treead000abbff60cb505072a5e962effa34bd2b0e19 /lib/obstack.c
parentb3ffd1523ba97e06d9d5620e9cdbb1e4baf9c58c (diff)
downloadgnulib-e4ccac4d27caeef527ef24982b9873837bd17d60.tar.gz
new obstack from libc
Diffstat (limited to 'lib/obstack.c')
-rw-r--r--lib/obstack.c177
1 files changed, 134 insertions, 43 deletions
diff --git a/lib/obstack.c b/lib/obstack.c
index a5ffe9f65c..1e36c4a0a5 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -1,19 +1,23 @@
/* obstack.c - subroutines used implicitly by object stack macros
Copyright (C) 1988,89,90,91,92,93,94,96 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 2, or (at your option)
-any later version.
+ This file is part of the GNU C Library. Its master source is NOT part of
+ the C library, however. The master source lives in /gd/gnu/lib.
-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.
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
#include "obstack.h"
@@ -52,7 +56,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Determine default alignment. */
struct fooalign {char x; double d;};
#define DEFAULT_ALIGNMENT \
- ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0))
+ ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
But in fact it might be less smart and round addresses to as much as
DEFAULT_ROUNDING. So we prepare for it to do that. */
@@ -67,6 +71,28 @@ union fooround {long x; double d;};
#define COPYING_UNIT int
#endif
+
+/* The functions allocating more room by calling `obstack_chunk_alloc'
+ jump to the handler pointed to by `obstack_alloc_failed_handler'.
+ This variable by default points to the internal function
+ `print_and_abort'. */
+#if defined (__STDC__) && __STDC__
+static void print_and_abort (void);
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+#else
+static void print_and_abort ();
+void (*obstack_alloc_failed_handler) () = print_and_abort;
+#endif
+
+/* Exit value used when `print_and_abort' is used. */
+#if defined (__STDC__) && __STDC__
+#include <stdlib.h>
+#endif
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+int obstack_exit_failure = EXIT_FAILURE;
+
/* The non-GNU-C macros copy the obstack into this global variable
to avoid multiple evaluation. */
@@ -78,6 +104,20 @@ struct obstack *_obstack;
For free, do not use ?:, since some compilers, like the MIPS compilers,
do not allow (expr) ? void : void. */
+#if defined (__STDC__) && __STDC__
+#define CALL_CHUNKFUN(h, size) \
+ (((h) -> use_extra_arg) \
+ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+ : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
+
+#define CALL_FREEFUN(h, old_chunk) \
+ do { \
+ if ((h) -> use_extra_arg) \
+ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+ else \
+ (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
+ } while (0)
+#else
#define CALL_CHUNKFUN(h, size) \
(((h) -> use_extra_arg) \
? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
@@ -90,6 +130,7 @@ struct obstack *_obstack;
else \
(*(void (*) ()) (h)->freefun) ((old_chunk)); \
} while (0)
+#endif
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
@@ -106,10 +147,15 @@ _obstack_begin (h, size, alignment, chunkfun, freefun)
struct obstack *h;
int size;
int alignment;
+#if defined (__STDC__) && __STDC__
+ POINTER (*chunkfun) (long);
+ void (*freefun) (void *);
+#else
POINTER (*chunkfun) ();
void (*freefun) ();
+#endif
{
- register struct _obstack_chunk* chunk; /* points to new chunk */
+ register struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0)
alignment = DEFAULT_ALIGNMENT;
@@ -130,25 +176,27 @@ _obstack_begin (h, size, alignment, chunkfun, freefun)
size = 4096 - extra;
}
+#if defined (__STDC__) && __STDC__
+ h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
+ h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+#else
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
h->freefun = freefun;
+#endif
h->chunk_size = size;
h->alignment_mask = alignment - 1;
h->use_extra_arg = 0;
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
if (!chunk)
- {
- h->alloc_failed = 1;
- return 0;
- }
- h->alloc_failed = 0;
+ (*obstack_alloc_failed_handler) ();
h->next_free = h->object_base = chunk->contents;
h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size;
chunk->prev = 0;
/* The initial chunk now contains no empty object. */
h->maybe_empty_object = 0;
+ h->alloc_failed = 0;
return 1;
}
@@ -157,11 +205,16 @@ _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
struct obstack *h;
int size;
int alignment;
+#if defined (__STDC__) && __STDC__
+ POINTER (*chunkfun) (POINTER, long);
+ void (*freefun) (POINTER, POINTER);
+#else
POINTER (*chunkfun) ();
void (*freefun) ();
+#endif
POINTER arg;
{
- register struct _obstack_chunk* chunk; /* points to new chunk */
+ register struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0)
alignment = DEFAULT_ALIGNMENT;
@@ -182,8 +235,13 @@ _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
size = 4096 - extra;
}
+#if defined(__STDC__) && __STDC__
+ h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
+ h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+#else
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
h->freefun = freefun;
+#endif
h->chunk_size = size;
h->alignment_mask = alignment - 1;
h->extra_arg = arg;
@@ -191,17 +249,14 @@ _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
if (!chunk)
- {
- h->alloc_failed = 1;
- return 0;
- }
- h->alloc_failed = 0;
+ (*obstack_alloc_failed_handler) ();
h->next_free = h->object_base = chunk->contents;
h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size;
chunk->prev = 0;
/* The initial chunk now contains no empty object. */
h->maybe_empty_object = 0;
+ h->alloc_failed = 0;
return 1;
}
@@ -216,8 +271,8 @@ _obstack_newchunk (h, length)
struct obstack *h;
int length;
{
- register struct _obstack_chunk* old_chunk = h->chunk;
- register struct _obstack_chunk* new_chunk;
+ register struct _obstack_chunk *old_chunk = h->chunk;
+ register struct _obstack_chunk *new_chunk;
register long new_size;
register int obj_size = h->next_free - h->object_base;
register int i;
@@ -231,11 +286,7 @@ _obstack_newchunk (h, length)
/* Allocate and initialize the new chunk. */
new_chunk = CALL_CHUNKFUN (h, new_size);
if (!new_chunk)
- {
- h->alloc_failed = 1;
- return;
- }
- h->alloc_failed = 0;
+ (*obstack_alloc_failed_handler) ();
h->chunk = new_chunk;
new_chunk->prev = old_chunk;
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
@@ -290,14 +341,14 @@ _obstack_allocated_p (h, obj)
struct obstack *h;
POINTER obj;
{
- register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
- register struct _obstack_chunk* plp; /* point to previous chunk if any */
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = (h)->chunk;
/* We use >= rather than > since the object cannot be exactly at
the beginning of the chunk but might be an empty object exactly
- at the end of an adjacent chunk. */
- while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ at the end of an adjacent chunk. */
+ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
{
plp = lp->prev;
lp = plp;
@@ -318,14 +369,14 @@ _obstack_free (h, obj)
struct obstack *h;
POINTER obj;
{
- register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
- register struct _obstack_chunk* plp; /* point to previous chunk if any */
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = h->chunk;
/* We use >= because there cannot be an object at the beginning of a chunk.
But there can be an empty object at that address
at the end of another chunk. */
- while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
{
plp = lp->prev;
CALL_FREEFUN (h, lp);
@@ -336,7 +387,7 @@ _obstack_free (h, obj)
}
if (lp)
{
- h->object_base = h->next_free = (char *)(obj);
+ h->object_base = h->next_free = (char *) (obj);
h->chunk_limit = lp->limit;
h->chunk = lp;
}
@@ -352,14 +403,14 @@ obstack_free (h, obj)
struct obstack *h;
POINTER obj;
{
- register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
- register struct _obstack_chunk* plp; /* point to previous chunk if any */
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = h->chunk;
/* We use >= because there cannot be an object at the beginning of a chunk.
But there can be an empty object at that address
at the end of another chunk. */
- while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
{
plp = lp->prev;
CALL_FREEFUN (h, lp);
@@ -370,7 +421,7 @@ obstack_free (h, obj)
}
if (lp)
{
- h->object_base = h->next_free = (char *)(obj);
+ h->object_base = h->next_free = (char *) (obj);
h->chunk_limit = lp->limit;
h->chunk = lp;
}
@@ -379,6 +430,39 @@ obstack_free (h, obj)
abort ();
}
+int
+_obstack_memory_used (h)
+ struct obstack *h;
+{
+ register struct _obstack_chunk* lp;
+ register int nbytes = 0;
+
+ for (lp = h->chunk; lp != 0; lp = lp->prev)
+ {
+ nbytes += lp->limit - (char *) lp;
+ }
+ return nbytes;
+}
+
+/* Define the error handler. */
+#ifndef _
+# ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# ifndef _
+# define _(Str) gettext (Str)
+# endif
+# else
+# define _(Str) (Str)
+# endif
+#endif
+
+static void
+print_and_abort ()
+{
+ fputs (_("memory exhausted\n"), stderr);
+ exit (obstack_exit_failure);
+}
+
#if 0
/* These are now turned off because the applications do not use it
and it uses bcopy via obstack_grow, which causes trouble on sysV. */
@@ -417,6 +501,13 @@ int (obstack_room) (obstack)
return obstack_room (obstack);
}
+int (obstack_make_room) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ return obstack_make_room (obstack, length);
+}
+
void (obstack_grow) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;