Renamed from strtoxmax.c, removing the old strtoimax.c.
[gnulib.git] / lib / obstack.c
index a8a4500..7b1206c 100644 (file)
 /* obstack.c - subroutines used implicitly by object stack macros
-   Copyright (C) 1988, 89, 90, 91, 92, 93, 94 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 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, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   Copyright (C) 1988-1994,96,97,98,99,2000,2001 Free Software Foundation, Inc.
+   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.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
 
 #include "obstack.h"
 
-/* This is just to get __GNU_LIBRARY__ defined.  */
-#include <stdio.h>
+/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
+   incremented whenever callers compiled using an old obstack.h can no
+   longer properly call the functions in this obstack.c.  */
+#define OBSTACK_INTERFACE_VERSION 1
 
 /* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself.  This code is part of the GNU C
-   Library, but also included in many other GNU distributions.  Compiling
+   actually compiling the library itself, and the installed library
+   supports the same library interface we do.  This code is part of the GNU
+   C Library, but also included in many other GNU distributions.  Compiling
    and linking in this code is a waste when using the GNU C library
    (especially if it is a shared library).  Rather than having every GNU
-   program understand `configure --with-gnu-libc' and omit the object files,
-   it is simpler to just do this in the source for each such file.  */
+   program understand `configure --with-gnu-libc' and omit the object
+   files, it is simpler to just do this in the source for each such file.  */
+
+#include <stdio.h>             /* Random thing to get __GNU_LIBRARY__.  */
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
+#endif
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+#endif
 
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+#ifndef ELIDE_CODE
 
 
-#ifdef __STDC__
-#define POINTER void *
-#else
-#define POINTER char *
-#endif
+# if defined __STDC__ && __STDC__
+#  define POINTER void *
+# else
+#  define POINTER char *
+# endif
 
 /* Determine default alignment.  */
 struct fooalign {char x; double d;};
-#define DEFAULT_ALIGNMENT  \
-  ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0))
+# define DEFAULT_ALIGNMENT  \
+  ((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.  */
 union fooround {long x; double d;};
-#define DEFAULT_ROUNDING (sizeof (union fooround))
+# define DEFAULT_ROUNDING (sizeof (union fooround))
 
 /* When we copy a long block of data, this is the unit to do it with.
    On some machines, copying successive ints does not work;
    in such a case, redefine COPYING_UNIT to `long' (if that works)
    or `char' as a last resort.  */
-#ifndef COPYING_UNIT
-#define COPYING_UNIT int
-#endif
+# ifndef COPYING_UNIT
+#  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 can be set to a user defined function which should either
+   abort gracefully or use longjump - but shouldn't return.  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 __GNU_LIBRARY__ || defined HAVE_STDLIB_H
+#  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.  */
@@ -66,18 +112,33 @@ struct obstack *_obstack;
    For free, do not use ?:, since some compilers, like the MIPS compilers,
    do not allow (expr) ? void : void.  */
 
-#define CALL_CHUNKFUN(h, size) \
+# 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)) \
-   : (*(h)->chunkfun) ((size)))
+   : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size)))
 
-#define CALL_FREEFUN(h, old_chunk) \
+#  define CALL_FREEFUN(h, old_chunk) \
   do { \
     if ((h) -> use_extra_arg) \
       (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
     else \
-      (*(h)->freefun) ((old_chunk)); \
+      (*(void (*) ()) (h)->freefun) ((old_chunk)); \
   } while (0)
+# endif
 
 \f
 /* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
@@ -85,22 +146,26 @@ struct obstack *_obstack;
    CHUNKFUN is the function to use to allocate chunks,
    and FREEFUN the function to free them.
 
-   Return nonzero if successful, zero if out of memory.
-   To recover from an out of memory error,
-   free up some memory, then call this again.  */
+   Return nonzero if successful, calls obstack_alloc_failed_handler if
+   allocation fails.  */
 
 int
 _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_chunkchunk; /* points to new chunk */
+  register struct _obstack_chunk *chunk; /* points to new chunk */
 
   if (alignment == 0)
-    alignment = DEFAULT_ALIGNMENT;
+    alignment = (int) DEFAULT_ALIGNMENT;
   if (size == 0)
     /* Default size is what GNU malloc can fit in a 4096-byte block.  */
     {
@@ -118,25 +183,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;
 }
 
@@ -145,14 +212,19 @@ _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_chunkchunk; /* points to new chunk */
+  register struct _obstack_chunk *chunk; /* points to new chunk */
 
   if (alignment == 0)
-    alignment = DEFAULT_ALIGNMENT;
+    alignment = (int) DEFAULT_ALIGNMENT;
   if (size == 0)
     /* Default size is what GNU malloc can fit in a 4096-byte block.  */
     {
@@ -170,8 +242,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;
@@ -179,17 +256,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;
 }
 
@@ -204,30 +278,32 @@ _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;
-  int already;
+  register long obj_size = h->next_free - h->object_base;
+  register long i;
+  long already;
+  char *object_base;
 
   /* Compute size for new chunk.  */
-  new_size = (obj_size + length) + (obj_size >> 3) + 100;
+  new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
   if (new_size < h->chunk_size)
     new_size = h->chunk_size;
 
   /* 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;
 
+  /* Compute an aligned object_base in the new chunk */
+  object_base =
+    __INT_TO_PTR ((__PTR_TO_INT (new_chunk->contents) + h->alignment_mask)
+                 & ~ (h->alignment_mask));
+
   /* Move the existing object to the new chunk.
      Word at a time is fast and is safe if the object
      is sufficiently aligned.  */
@@ -235,7 +311,7 @@ _obstack_newchunk (h, length)
     {
       for (i = obj_size / sizeof (COPYING_UNIT) - 1;
           i >= 0; i--)
-       ((COPYING_UNIT *)new_chunk->contents)[i]
+       ((COPYING_UNIT *)object_base)[i]
          = ((COPYING_UNIT *)h->object_base)[i];
       /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
         but that can cross a page boundary on a machine
@@ -246,7 +322,7 @@ _obstack_newchunk (h, length)
     already = 0;
   /* Copy remaining bytes one by one.  */
   for (i = already; i < obj_size; i++)
-    new_chunk->contents[i] = h->object_base[i];
+    object_base[i] = h->object_base[i];
 
   /* If the object just copied was the only data in OLD_CHUNK,
      free that chunk and remove it from the chain.
@@ -257,7 +333,7 @@ _obstack_newchunk (h, length)
       CALL_FREEFUN (h, old_chunk);
     }
 
-  h->object_base = new_chunk->contents;
+  h->object_base = object_base;
   h->next_free = h->object_base + obj_size;
   /* The new chunk certainly contains no empty object yet.  */
   h->maybe_empty_object = 0;
@@ -267,25 +343,25 @@ _obstack_newchunk (h, length)
    This is here for debugging.
    If you use it in a program, you are probably losing.  */
 
-#ifdef __STDC__
+# if defined __STDC__ && __STDC__
 /* Suppress -Wmissing-prototypes warning.  We don't want to declare this in
    obstack.h because it is just for debugging.  */
 int _obstack_allocated_p (struct obstack *h, POINTER obj);
-#endif
+# endif
 
 int
 _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;
@@ -296,7 +372,7 @@ _obstack_allocated_p (h, obj)
 /* Free objects in obstack H, including OBJ and everything allocate
    more recently than OBJ.  If OBJ is zero, free everything in H.  */
 
-#undef obstack_free
+# undef obstack_free
 
 /* This function has two names with identical definitions.
    This is the first one, called from non-ANSI code.  */
@@ -306,14 +382,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);
@@ -324,7 +400,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;
     }
@@ -340,14 +416,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);
@@ -358,7 +434,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;
     }
@@ -367,14 +443,69 @@ obstack_free (h, obj)
     abort ();
 }
 \f
-#if 0
+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;
+}
+\f
+/* Define the error handler.  */
+# ifndef _
+#  if defined HAVE_LIBINTL_H || defined _LIBC
+#   include <libintl.h>
+#   ifndef _
+#    define _(Str) gettext (Str)
+#   endif
+#  else
+#   define _(Str) (Str)
+#  endif
+# endif
+# if defined _LIBC && defined USE_IN_LIBIO
+#  include <libio/iolibio.h>
+#  define fputs(s, f) _IO_fputs (s, f)
+# endif
+
+# ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+#  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#   define __attribute__(Spec) /* empty */
+#  endif
+# endif
+
+static void
+__attribute__ ((noreturn))
+print_and_abort ()
+{
+  /* Don't change any of these strings.  Yes, it would be possible to add
+     the newline to the string and use fputs or so.  But this must not
+     happen because the "memory exhausted" message appears in other places
+     like this and the translation should be reused instead of creating
+     a very similar string which requires a separate translation.  */
+# if defined _LIBC && defined USE_IN_LIBIO
+  if (_IO_fwide (stderr, 0) > 0)
+    __fwprintf (stderr, L"%s\n", _("memory exhausted"));
+  else
+# endif
+    fprintf (stderr, "%s\n", _("memory exhausted"));
+  exit (obstack_exit_failure);
+}
+\f
+# 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.  */
 
 /* Now define the functional versions of the obstack macros.
    Define them to simply use the corresponding macros to do the job.  */
 
-#ifdef __STDC__
+#  if defined __STDC__ && __STDC__
 /* These function definitions do not work with non-ANSI preprocessors;
    they won't pass through the macro names in parentheses.  */
 
@@ -405,20 +536,27 @@ int (obstack_room) (obstack)
   return obstack_room (obstack);
 }
 
-void (obstack_grow) (obstack, pointer, length)
+int (obstack_make_room) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  return obstack_make_room (obstack, length);
+}
+
+void (obstack_grow) (obstack, data, length)
      struct obstack *obstack;
-     POINTER pointer;
+     const POINTER data;
      int length;
 {
-  obstack_grow (obstack, pointer, length);
+  obstack_grow (obstack, data, length);
 }
 
-void (obstack_grow0) (obstack, pointer, length)
+void (obstack_grow0) (obstack, data, length)
      struct obstack *obstack;
-     POINTER pointer;
+     const POINTER data;
      int length;
 {
-  obstack_grow0 (obstack, pointer, length);
+  obstack_grow0 (obstack, data, length);
 }
 
 void (obstack_1grow) (obstack, character)
@@ -462,24 +600,24 @@ POINTER (obstack_alloc) (obstack, length)
   return obstack_alloc (obstack, length);
 }
 
-POINTER (obstack_copy) (obstack, pointer, length)
+POINTER (obstack_copy) (obstack, address, length)
      struct obstack *obstack;
-     POINTER pointer;
+     const POINTER address;
      int length;
 {
-  return obstack_copy (obstack, pointer, length);
+  return obstack_copy (obstack, address, length);
 }
 
-POINTER (obstack_copy0) (obstack, pointer, length)
+POINTER (obstack_copy0) (obstack, address, length)
      struct obstack *obstack;
-     POINTER pointer;
+     const POINTER address;
      int length;
 {
-  return obstack_copy0 (obstack, pointer, length);
+  return obstack_copy0 (obstack, address, length);
 }
 
-#endif /* __STDC__ */
+#  endif /* __STDC__ */
 
-#endif /* 0 */
+# endif /* 0 */
 
-#endif /* _LIBC or not __GNU_LIBRARY__.  */
+#endif /* !ELIDE_CODE */