1a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* obstack.c - subroutines used implicitly by object stack macros
2a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
3a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997,
4a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
5a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   Foundation, Inc.
6a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
7a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   This program is free software: you can redistribute it and/or modify
8a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   it under the terms of the GNU General Public License as published by
9a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   the Free Software Foundation; either version 3 of the License, or
10a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   (at your option) any later version.
11a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
12a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   This program is distributed in the hope that it will be useful,
13a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   but WITHOUT ANY WARRANTY; without even the implied warranty of
14a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   GNU General Public License for more details.
16a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
17a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   You should have received a copy of the GNU General Public License
18a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
20a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#ifdef _LIBC
21a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# include <obstack.h>
22a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# include <shlib-compat.h>
23a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#else
24a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# include <config.h>
25a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# include "obstack.h"
26a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#endif
27a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
28a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
29a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   incremented whenever callers compiled using an old obstack.h can no
30a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   longer properly call the functions in this obstack.c.  */
31a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#define OBSTACK_INTERFACE_VERSION 1
32a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
33a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Comment out all this code if we are using the GNU C Library, and are not
34a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   actually compiling the library itself, and the installed library
35a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   supports the same library interface we do.  This code is part of the GNU
36a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   C Library, but also included in many other GNU distributions.  Compiling
37a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   and linking in this code is a waste when using the GNU C library
38a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   (especially if it is a shared library).  Rather than having every GNU
39a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   program understand `configure --with-gnu-libc' and omit the object
40a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   files, it is simpler to just do this in the source for each such file.  */
41a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
42a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#include <stdio.h>		/* Random thing to get __GNU_LIBRARY__.  */
43a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
44a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# include <gnu-versions.h>
45a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
46a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  define ELIDE_CODE
47a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
48a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#endif
49a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
50a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#include <stddef.h>
51a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
52a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#ifndef ELIDE_CODE
53a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
54a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# include <stdint.h>
55a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
56a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Determine default alignment.  */
57a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerunion fooround
58a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
59a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  uintmax_t i;
60a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  long double d;
61a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  void *p;
62a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner};
63a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerstruct fooalign
64a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
65a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  char c;
66a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  union fooround u;
67a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner};
68a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
69a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   But in fact it might be less smart and round addresses to as much as
70a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   DEFAULT_ROUNDING.  So we prepare for it to do that.  */
71a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerenum
72a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  {
73a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
74a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    DEFAULT_ROUNDING = sizeof (union fooround)
75a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  };
76a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
77a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* When we copy a long block of data, this is the unit to do it with.
78a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   On some machines, copying successive ints does not work;
79a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   in such a case, redefine COPYING_UNIT to `long' (if that works)
80a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   or `char' as a last resort.  */
81a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# ifndef COPYING_UNIT
82a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  define COPYING_UNIT int
83a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
84a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
85a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
86a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* The functions allocating more room by calling `obstack_chunk_alloc'
87a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   jump to the handler pointed to by `obstack_alloc_failed_handler'.
88a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   This can be set to a user defined function which should either
89a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   abort gracefully or use longjump - but shouldn't return.  This
90a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   variable by default points to the internal function
91a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   `print_and_abort'.  */
92a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerstatic void print_and_abort (void);
93a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnervoid (*obstack_alloc_failed_handler) (void) = print_and_abort;
94a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
95a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Exit value used when `print_and_abort' is used.  */
96a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# include <stdlib.h>
97a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# ifdef _LIBC
98a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerint obstack_exit_failure = EXIT_FAILURE;
99a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# else
100a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  include "exitfail.h"
101a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  define obstack_exit_failure exit_failure
102a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
103a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
104a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# ifdef _LIBC
105a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
106a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* A looong time ago (before 1994, anyway; we're not sure) this global variable
107a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   was used by non-GNU-C macros to avoid multiple evaluation.  The GNU C
108a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   library still exports it because somebody might use it.  */
109a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerstruct obstack *_obstack_compat;
110a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnercompat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
111a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  endif
112a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
113a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
114a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Define a macro that either calls functions with the traditional malloc/free
115a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   calling interface, or calls functions with the mmalloc/mfree interface
116a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   (that adds an extra first argument), based on the state of use_extra_arg.
117a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   For free, do not use ?:, since some compilers, like the MIPS compilers,
118a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   do not allow (expr) ? void : void.  */
119a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
120a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# define CALL_CHUNKFUN(h, size) \
121a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  (((h) -> use_extra_arg) \
122a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
123a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
124a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
125a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# define CALL_FREEFUN(h, old_chunk) \
126a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  do { \
127a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    if ((h) -> use_extra_arg) \
128a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
129a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    else \
130a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
131a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  } while (0)
132a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
133a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
134a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
135a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   Objects start on multiples of ALIGNMENT (0 means use default).
136a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   CHUNKFUN is the function to use to allocate chunks,
137a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   and FREEFUN the function to free them.
138a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
139a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   Return nonzero if successful, calls obstack_alloc_failed_handler if
140a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   allocation fails.  */
141a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
142a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerint
143a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner_obstack_begin (struct obstack *h,
144a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		int size, int alignment,
145a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		void *(*chunkfun) (long),
146a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		void (*freefun) (void *))
147a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
148a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register struct _obstack_chunk *chunk; /* points to new chunk */
149a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
150a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (alignment == 0)
151a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    alignment = DEFAULT_ALIGNMENT;
152a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (size == 0)
153a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
154a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
155a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
156a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 Use the values for range checking, because if range checking is off,
157a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 the extra bytes won't be missed terribly, but if range checking is on
158a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 and we used a larger request, a whole extra 4096 bytes would be
159a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 allocated.
160a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
161a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 These number are irrelevant to the new GNU malloc.  I suspect it is
162a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 less sensitive to the size of the request.  */
163a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
164a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		    + 4 + DEFAULT_ROUNDING - 1)
165a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		   & ~(DEFAULT_ROUNDING - 1));
166a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      size = 4096 - extra;
167a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
168a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
169a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
170a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
171a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->chunk_size = size;
172a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->alignment_mask = alignment - 1;
173a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->use_extra_arg = 0;
174a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
175a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
176a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (!chunk)
177a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    (*obstack_alloc_failed_handler) ();
178a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
179a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner					       alignment - 1);
180a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->chunk_limit = chunk->limit
181a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    = (char *) chunk + h->chunk_size;
182a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  chunk->prev = 0;
183a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* The initial chunk now contains no empty object.  */
184a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->maybe_empty_object = 0;
185a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->alloc_failed = 0;
186a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  return 1;
187a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
188a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
189a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerint
190a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner_obstack_begin_1 (struct obstack *h, int size, int alignment,
191a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		  void *(*chunkfun) (void *, long),
192a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		  void (*freefun) (void *, void *),
193a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		  void *arg)
194a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
195a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register struct _obstack_chunk *chunk; /* points to new chunk */
196a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
197a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (alignment == 0)
198a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    alignment = DEFAULT_ALIGNMENT;
199a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (size == 0)
200a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
201a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
202a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
203a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 Use the values for range checking, because if range checking is off,
204a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 the extra bytes won't be missed terribly, but if range checking is on
205a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 and we used a larger request, a whole extra 4096 bytes would be
206a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 allocated.
207a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
208a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 These number are irrelevant to the new GNU malloc.  I suspect it is
209a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 less sensitive to the size of the request.  */
210a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
211a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		    + 4 + DEFAULT_ROUNDING - 1)
212a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		   & ~(DEFAULT_ROUNDING - 1));
213a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      size = 4096 - extra;
214a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
215a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
216a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
217a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
218a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->chunk_size = size;
219a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->alignment_mask = alignment - 1;
220a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->extra_arg = arg;
221a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->use_extra_arg = 1;
222a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
223a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
224a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (!chunk)
225a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    (*obstack_alloc_failed_handler) ();
226a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
227a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner					       alignment - 1);
228a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->chunk_limit = chunk->limit
229a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    = (char *) chunk + h->chunk_size;
230a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  chunk->prev = 0;
231a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* The initial chunk now contains no empty object.  */
232a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->maybe_empty_object = 0;
233a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->alloc_failed = 0;
234a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  return 1;
235a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
236a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
237a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Allocate a new current chunk for the obstack *H
238a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   on the assumption that LENGTH bytes need to be added
239a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   to the current object, or a new object of length LENGTH allocated.
240a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   Copies any partial object from the end of the old chunk
241a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   to the beginning of the new one.  */
242a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
243a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnervoid
244a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner_obstack_newchunk (struct obstack *h, int length)
245a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
246a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register struct _obstack_chunk *old_chunk = h->chunk;
247a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register struct _obstack_chunk *new_chunk;
248a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register long	new_size;
249a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register long obj_size = h->next_free - h->object_base;
250a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register long i;
251a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  long already;
252a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  char *object_base;
253a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
254a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* Compute size for new chunk.  */
255a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
256a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (new_size < h->chunk_size)
257a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    new_size = h->chunk_size;
258a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
259a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* Allocate and initialize the new chunk.  */
260a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  new_chunk = CALL_CHUNKFUN (h, new_size);
261a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (!new_chunk)
262a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    (*obstack_alloc_failed_handler) ();
263a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->chunk = new_chunk;
264a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  new_chunk->prev = old_chunk;
265a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
266a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
267a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* Compute an aligned object_base in the new chunk */
268a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  object_base =
269a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
270a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
271a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* Move the existing object to the new chunk.
272a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     Word at a time is fast and is safe if the object
273a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     is sufficiently aligned.  */
274a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
275a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
276a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      for (i = obj_size / sizeof (COPYING_UNIT) - 1;
277a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	   i >= 0; i--)
278a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	((COPYING_UNIT *)object_base)[i]
279a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	  = ((COPYING_UNIT *)h->object_base)[i];
280a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
281a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 but that can cross a page boundary on a machine
282a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 which does not do strict alignment for COPYING_UNITS.  */
283a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
284a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
285a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  else
286a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    already = 0;
287a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* Copy remaining bytes one by one.  */
288a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  for (i = already; i < obj_size; i++)
289a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    object_base[i] = h->object_base[i];
290a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
291a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* If the object just copied was the only data in OLD_CHUNK,
292a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     free that chunk and remove it from the chain.
293a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     But not if that chunk might contain an empty object.  */
294a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (! h->maybe_empty_object
295a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      && (h->object_base
296a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	  == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
297a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner			  h->alignment_mask)))
298a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
299a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      new_chunk->prev = old_chunk->prev;
300a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      CALL_FREEFUN (h, old_chunk);
301a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
302a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
303a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->object_base = object_base;
304a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->next_free = h->object_base + obj_size;
305a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* The new chunk certainly contains no empty object yet.  */
306a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  h->maybe_empty_object = 0;
307a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
308a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# ifdef _LIBC
309a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerlibc_hidden_def (_obstack_newchunk)
310a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
311a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
312a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Return nonzero if object OBJ has been allocated from obstack H.
313a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   This is here for debugging.
314a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   If you use it in a program, you are probably losing.  */
315a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
316a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Suppress -Wmissing-prototypes warning.  We don't want to declare this in
317a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   obstack.h because it is just for debugging.  */
318a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerint _obstack_allocated_p (struct obstack *h, void *obj);
319a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
320a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerint
321a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner_obstack_allocated_p (struct obstack *h, void *obj)
322a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
323a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
324a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register struct _obstack_chunk *plp;	/* point to previous chunk if any */
325a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
326a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  lp = (h)->chunk;
327a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* We use >= rather than > since the object cannot be exactly at
328a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     the beginning of the chunk but might be an empty object exactly
329a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     at the end of an adjacent chunk.  */
330a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
331a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
332a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      plp = lp->prev;
333a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      lp = plp;
334a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
335a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  return lp != 0;
336a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
337a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
338a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Free objects in obstack H, including OBJ and everything allocate
339a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   more recently than OBJ.  If OBJ is zero, free everything in H.  */
340a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
341a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# undef obstack_free
342a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
343a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnervoid
344a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner__obstack_free (struct obstack *h, void *obj)
345a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
346a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
347a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register struct _obstack_chunk *plp;	/* point to previous chunk if any */
348a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
349a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  lp = h->chunk;
350a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* We use >= because there cannot be an object at the beginning of a chunk.
351a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     But there can be an empty object at that address
352a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     at the end of another chunk.  */
353a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
354a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
355a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      plp = lp->prev;
356a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      CALL_FREEFUN (h, lp);
357a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      lp = plp;
358a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      /* If we switch chunks, we can't tell whether the new current
359a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	 chunk contains an empty object, so assume that it may.  */
360a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      h->maybe_empty_object = 1;
361a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
362a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  if (lp)
363a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
364a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      h->object_base = h->next_free = (char *) (obj);
365a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      h->chunk_limit = lp->limit;
366a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      h->chunk = lp;
367a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
368a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  else if (obj != 0)
369a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    /* obj is not in any of the chunks! */
370a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    abort ();
371a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
372a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
373a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# ifdef _LIBC
374a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Older versions of libc used a function _obstack_free intended to be
375a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner   called by non-GCC compilers.  */
376a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerstrong_alias (obstack_free, _obstack_free)
377a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
378a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
379a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerint
380a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner_obstack_memory_used (struct obstack *h)
381a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
382a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register struct _obstack_chunk* lp;
383a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  register int nbytes = 0;
384a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
385a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  for (lp = h->chunk; lp != 0; lp = lp->prev)
386a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
387a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner      nbytes += lp->limit - (char *) lp;
388a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
389a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  return nbytes;
390a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
391a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
392a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* Define the error handler.  */
393a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# ifdef _LIBC
394a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  include <libintl.h>
395a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# else
396a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  include "gettext.h"
397a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
398a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# ifndef _
399a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  define _(msgid) gettext (msgid)
400a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
401a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
402a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# ifdef _LIBC
403a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  include <libio/iolibio.h>
404a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
405a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
406a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# ifndef __attribute__
407a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner/* This feature is available in gcc versions 2.5 and later.  */
408a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
409a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#   define __attribute__(Spec) /* empty */
410a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#  endif
411a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
412a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
413a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerstatic void
414a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner__attribute__ ((noreturn))
415a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerprint_and_abort (void)
416a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
417a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  /* Don't change any of these strings.  Yes, it would be possible to add
418a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     the newline to the string and use fputs or so.  But this must not
419a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     happen because the "memory exhausted" message appears in other places
420a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     like this and the translation should be reused instead of creating
421a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     a very similar string which requires a separate translation.  */
422a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# ifdef _LIBC
423a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
424a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# else
425a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  fprintf (stderr, "%s\n", _("memory exhausted"));
426a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# endif
427a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner  exit (obstack_exit_failure);
428a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
429a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
430a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#endif	/* !ELIDE_CODE */
431