Ticket #1186: obstack.c

File obstack.c, 18.1 KB (added by bchesneau@…, 20 years ago)

files/obstrack?c

Line 
1/* obstack.c - subroutines used implicitly by object stack macros
2   Copyright (C) 1988-1994,96,97,98,99,2000,2001 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.  Its master source is NOT part of
4   the C library, however.  The master source lives in /gd/gnu/lib.
5
6   The GNU C Library is free software; you can redistribute it and/or
7   modify it under the terms of the GNU Lesser General Public
8   License as published by the Free Software Foundation; either
9   version 2.1 of the License, or (at your option) any later version.
10
11   The GNU C Library is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with the GNU C Library; if not, write to the Free
18   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19   02111-1307 USA.  */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25#include "obstack.h"
26
27/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
28   incremented whenever callers compiled using an old obstack.h can no
29   longer properly call the functions in this obstack.c.  */
30#define OBSTACK_INTERFACE_VERSION 1
31
32/* Comment out all this code if we are using the GNU C Library, and are not
33   actually compiling the library itself, and the installed library
34   supports the same library interface we do.  This code is part of the GNU
35   C Library, but also included in many other GNU distributions.  Compiling
36   and linking in this code is a waste when using the GNU C library
37   (especially if it is a shared library).  Rather than having every GNU
38   program understand `configure --with-gnu-libc' and omit the object
39   files, it is simpler to just do this in the source for each such file.  */
40
41#include <stdio.h>              /* Random thing to get __GNU_LIBRARY__.  */
42#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
43#include <gnu-versions.h>
44#if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
45#define ELIDE_CODE
46#endif
47#endif
48
49
50#ifndef ELIDE_CODE
51
52
53#if defined (__STDC__) && __STDC__
54#define POINTER void *
55#else
56#define POINTER char *
57#endif
58
59/* Determine default alignment.  */
60struct fooalign {char x; double d;};
61#define DEFAULT_ALIGNMENT  \
62  ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
63/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
64   But in fact it might be less smart and round addresses to as much as
65   DEFAULT_ROUNDING.  So we prepare for it to do that.  */
66union fooround {long x; double d;};
67#define DEFAULT_ROUNDING (sizeof (union fooround))
68
69/* When we copy a long block of data, this is the unit to do it with.
70   On some machines, copying successive ints does not work;
71   in such a case, redefine COPYING_UNIT to `long' (if that works)
72   or `char' as a last resort.  */
73#ifndef COPYING_UNIT
74#define COPYING_UNIT int
75#endif
76
77
78/* The functions allocating more room by calling `obstack_chunk_alloc'
79   jump to the handler pointed to by `obstack_alloc_failed_handler'.
80   This can be set to a user defined function which should either
81   abort gracefully or use longjump - but shouldn't return.  This
82   variable by default points to the internal function
83   `print_and_abort'.  */
84#if defined (__STDC__) && __STDC__
85static void print_and_abort (void);
86void (*obstack_alloc_failed_handler) (void) = print_and_abort;
87#else
88static void print_and_abort ();
89void (*obstack_alloc_failed_handler) () = print_and_abort;
90#endif
91
92/* Exit value used when `print_and_abort' is used.  */
93#if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H
94#include <stdlib.h>
95#endif
96#ifndef EXIT_FAILURE
97#define EXIT_FAILURE 1
98#endif
99int obstack_exit_failure = EXIT_FAILURE;
100
101/* The non-GNU-C macros copy the obstack into this global variable
102   to avoid multiple evaluation.  */
103
104struct obstack *_obstack;
105
106/* Define a macro that either calls functions with the traditional malloc/free
107   calling interface, or calls functions with the mmalloc/mfree interface
108   (that adds an extra first argument), based on the state of use_extra_arg.
109   For free, do not use ?:, since some compilers, like the MIPS compilers,
110   do not allow (expr) ? void : void.  */
111
112#if defined (__STDC__) && __STDC__
113#define CALL_CHUNKFUN(h, size) \
114  (((h) -> use_extra_arg) \
115   ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
116   : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
117
118#define CALL_FREEFUN(h, old_chunk) \
119  do { \
120    if ((h) -> use_extra_arg) \
121      (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
122    else \
123      (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
124  } while (0)
125#else
126#define CALL_CHUNKFUN(h, size) \
127  (((h) -> use_extra_arg) \
128   ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
129   : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size)))
130
131#define CALL_FREEFUN(h, old_chunk) \
132  do { \
133    if ((h) -> use_extra_arg) \
134      (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
135    else \
136      (*(void (*) ()) (h)->freefun) ((old_chunk)); \
137  } while (0)
138#endif
139
140
141/* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
142   Objects start on multiples of ALIGNMENT (0 means use default).
143   CHUNKFUN is the function to use to allocate chunks,
144   and FREEFUN the function to free them.
145
146   Return nonzero if successful, calls obstack_alloc_failed_handler if
147   allocation fails.  */
148
149int
150_obstack_begin (h, size, alignment, chunkfun, freefun)
151     struct obstack *h;
152     int size;
153     int alignment;
154#if defined (__STDC__) && __STDC__
155     POINTER (*chunkfun) (long);
156     void (*freefun) (void *);
157#else
158     POINTER (*chunkfun) ();
159     void (*freefun) ();
160#endif
161{
162  register struct _obstack_chunk *chunk; /* points to new chunk */
163
164  if (alignment == 0)
165    alignment = (int) DEFAULT_ALIGNMENT;
166  if (size == 0)
167    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
168    {
169      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
170         Use the values for range checking, because if range checking is off,
171         the extra bytes won't be missed terribly, but if range checking is on
172         and we used a larger request, a whole extra 4096 bytes would be
173         allocated.
174
175         These number are irrelevant to the new GNU malloc.  I suspect it is
176         less sensitive to the size of the request.  */
177      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
178                    + 4 + DEFAULT_ROUNDING - 1)
179                   & ~(DEFAULT_ROUNDING - 1));
180      size = 4096 - extra;
181    }
182
183#if defined (__STDC__) && __STDC__
184  h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
185  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
186#else
187  h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
188  h->freefun = freefun;
189#endif
190  h->chunk_size = size;
191  h->alignment_mask = alignment - 1;
192  h->use_extra_arg = 0;
193
194  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
195  if (!chunk)
196    (*obstack_alloc_failed_handler) ();
197  h->next_free = h->object_base = chunk->contents;
198  h->chunk_limit = chunk->limit
199    = (char *) chunk + h->chunk_size;
200  chunk->prev = 0;
201  /* The initial chunk now contains no empty object.  */
202  h->maybe_empty_object = 0;
203  h->alloc_failed = 0;
204  return 1;
205}
206
207int
208_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
209     struct obstack *h;
210     int size;
211     int alignment;
212#if defined (__STDC__) && __STDC__
213     POINTER (*chunkfun) (POINTER, long);
214     void (*freefun) (POINTER, POINTER);
215#else
216     POINTER (*chunkfun) ();
217     void (*freefun) ();
218#endif
219     POINTER arg;
220{
221  register struct _obstack_chunk *chunk; /* points to new chunk */
222
223  if (alignment == 0)
224    alignment = (int) DEFAULT_ALIGNMENT;
225  if (size == 0)
226    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
227    {
228      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
229         Use the values for range checking, because if range checking is off,
230         the extra bytes won't be missed terribly, but if range checking is on
231         and we used a larger request, a whole extra 4096 bytes would be
232         allocated.
233
234         These number are irrelevant to the new GNU malloc.  I suspect it is
235         less sensitive to the size of the request.  */
236      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
237                    + 4 + DEFAULT_ROUNDING - 1)
238                   & ~(DEFAULT_ROUNDING - 1));
239      size = 4096 - extra;
240    }
241
242#if defined(__STDC__) && __STDC__
243  h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
244  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
245#else
246  h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
247  h->freefun = freefun;
248#endif
249  h->chunk_size = size;
250  h->alignment_mask = alignment - 1;
251  h->extra_arg = arg;
252  h->use_extra_arg = 1;
253
254  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
255  if (!chunk)
256    (*obstack_alloc_failed_handler) ();
257  h->next_free = h->object_base = chunk->contents;
258  h->chunk_limit = chunk->limit
259    = (char *) chunk + h->chunk_size;
260  chunk->prev = 0;
261  /* The initial chunk now contains no empty object.  */
262  h->maybe_empty_object = 0;
263  h->alloc_failed = 0;
264  return 1;
265}
266
267/* Allocate a new current chunk for the obstack *H
268   on the assumption that LENGTH bytes need to be added
269   to the current object, or a new object of length LENGTH allocated.
270   Copies any partial object from the end of the old chunk
271   to the beginning of the new one.  */
272
273void
274_obstack_newchunk (h, length)
275     struct obstack *h;
276     int length;
277{
278  register struct _obstack_chunk *old_chunk = h->chunk;
279  register struct _obstack_chunk *new_chunk;
280  register long new_size;
281  register long obj_size = h->next_free - h->object_base;
282  register long i;
283  long already;
284  char *object_base;
285
286  /* Compute size for new chunk.  */
287  new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
288  if (new_size < h->chunk_size)
289    new_size = h->chunk_size;
290
291  /* Allocate and initialize the new chunk.  */
292  new_chunk = CALL_CHUNKFUN (h, new_size);
293  if (!new_chunk)
294    (*obstack_alloc_failed_handler) ();
295  h->chunk = new_chunk;
296  new_chunk->prev = old_chunk;
297  new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
298
299  /* Compute an aligned object_base in the new chunk */
300  object_base =
301    __INT_TO_PTR ((__PTR_TO_INT (new_chunk->contents) + h->alignment_mask)
302                  & ~ (h->alignment_mask));
303
304  /* Move the existing object to the new chunk.
305     Word at a time is fast and is safe if the object
306     is sufficiently aligned.  */
307  if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
308    {
309      for (i = obj_size / sizeof (COPYING_UNIT) - 1;
310           i >= 0; i--)
311        ((COPYING_UNIT *)object_base)[i]
312          = ((COPYING_UNIT *)h->object_base)[i];
313      /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
314         but that can cross a page boundary on a machine
315         which does not do strict alignment for COPYING_UNITS.  */
316      already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
317    }
318  else
319    already = 0;
320  /* Copy remaining bytes one by one.  */
321  for (i = already; i < obj_size; i++)
322    object_base[i] = h->object_base[i];
323
324  /* If the object just copied was the only data in OLD_CHUNK,
325     free that chunk and remove it from the chain.
326     But not if that chunk might contain an empty object.  */
327  if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
328    {
329      new_chunk->prev = old_chunk->prev;
330      CALL_FREEFUN (h, old_chunk);
331    }
332
333  h->object_base = object_base;
334  h->next_free = h->object_base + obj_size;
335  /* The new chunk certainly contains no empty object yet.  */
336  h->maybe_empty_object = 0;
337}
338
339/* Return nonzero if object OBJ has been allocated from obstack H.
340   This is here for debugging.
341   If you use it in a program, you are probably losing.  */
342
343#if defined (__STDC__) && __STDC__
344/* Suppress -Wmissing-prototypes warning.  We don't want to declare this in
345   obstack.h because it is just for debugging.  */
346int _obstack_allocated_p (struct obstack *h, POINTER obj);
347#endif
348
349int
350_obstack_allocated_p (h, obj)
351     struct obstack *h;
352     POINTER obj;
353{
354  register struct _obstack_chunk *lp;   /* below addr of any objects in this chunk */
355  register struct _obstack_chunk *plp;  /* point to previous chunk if any */
356
357  lp = (h)->chunk;
358  /* We use >= rather than > since the object cannot be exactly at
359     the beginning of the chunk but might be an empty object exactly
360     at the end of an adjacent chunk.  */
361  while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
362    {
363      plp = lp->prev;
364      lp = plp;
365    }
366  return lp != 0;
367}
368
369/* Free objects in obstack H, including OBJ and everything allocate
370   more recently than OBJ.  If OBJ is zero, free everything in H.  */
371
372#undef obstack_free
373
374/* This function has two names with identical definitions.
375   This is the first one, called from non-ANSI code.  */
376
377void
378_obstack_free (h, obj)
379     struct obstack *h;
380     POINTER obj;
381{
382  register struct _obstack_chunk *lp;   /* below addr of any objects in this chunk */
383  register struct _obstack_chunk *plp;  /* point to previous chunk if any */
384
385  lp = h->chunk;
386  /* We use >= because there cannot be an object at the beginning of a chunk.
387     But there can be an empty object at that address
388     at the end of another chunk.  */
389  while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
390    {
391      plp = lp->prev;
392      CALL_FREEFUN (h, lp);
393      lp = plp;
394      /* If we switch chunks, we can't tell whether the new current
395         chunk contains an empty object, so assume that it may.  */
396      h->maybe_empty_object = 1;
397    }
398  if (lp)
399    {
400      h->object_base = h->next_free = (char *) (obj);
401      h->chunk_limit = lp->limit;
402      h->chunk = lp;
403    }
404  else if (obj != 0)
405    /* obj is not in any of the chunks! */
406    abort ();
407}
408
409/* This function is used from ANSI code.  */
410
411void
412obstack_free (h, obj)
413     struct obstack *h;
414     POINTER obj;
415{
416  register struct _obstack_chunk *lp;   /* below addr of any objects in this chunk */
417  register struct _obstack_chunk *plp;  /* point to previous chunk if any */
418
419  lp = h->chunk;
420  /* We use >= because there cannot be an object at the beginning of a chunk.
421     But there can be an empty object at that address
422     at the end of another chunk.  */
423  while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
424    {
425      plp = lp->prev;
426      CALL_FREEFUN (h, lp);
427      lp = plp;
428      /* If we switch chunks, we can't tell whether the new current
429         chunk contains an empty object, so assume that it may.  */
430      h->maybe_empty_object = 1;
431    }
432  if (lp)
433    {
434      h->object_base = h->next_free = (char *) (obj);
435      h->chunk_limit = lp->limit;
436      h->chunk = lp;
437    }
438  else if (obj != 0)
439    /* obj is not in any of the chunks! */
440    abort ();
441}
442
443int
444_obstack_memory_used (h)
445     struct obstack *h;
446{
447  register struct _obstack_chunk* lp;
448  register int nbytes = 0;
449
450  for (lp = h->chunk; lp != 0; lp = lp->prev)
451    {
452      nbytes += lp->limit - (char *) lp;
453    }
454  return nbytes;
455}
456
457/* Define the error handler.  */
458#ifndef _
459# if defined HAVE_LIBINTL_H || defined _LIBC
460#  include <libintl.h>
461#  ifndef _
462#   define _(Str) gettext (Str)
463#  endif
464# else
465#  define _(Str) (Str)
466# endif
467#endif
468#if defined _LIBC && defined USE_IN_LIBIO
469# include <libio/iolibio.h>
470# define fputs(s, f) _IO_fputs (s, f)
471#endif
472
473#ifndef __attribute__
474/* This feature is available in gcc versions 2.5 and later.  */
475# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
476#  define __attribute__(Spec) /* empty */
477# endif
478#endif
479
480static void
481__attribute__ ((noreturn))
482print_and_abort ()
483{
484  fputs (_("memory exhausted"), stderr);
485  fputc ('\n', stderr);
486  exit (obstack_exit_failure);
487}
488
489#if 0
490/* These are now turned off because the applications do not use it
491   and it uses bcopy via obstack_grow, which causes trouble on sysV.  */
492
493/* Now define the functional versions of the obstack macros.
494   Define them to simply use the corresponding macros to do the job.  */
495
496#if defined (__STDC__) && __STDC__
497/* These function definitions do not work with non-ANSI preprocessors;
498   they won't pass through the macro names in parentheses.  */
499
500/* The function names appear in parentheses in order to prevent
501   the macro-definitions of the names from being expanded there.  */
502
503POINTER (obstack_base) (obstack)
504     struct obstack *obstack;
505{
506  return obstack_base (obstack);
507}
508
509POINTER (obstack_next_free) (obstack)
510     struct obstack *obstack;
511{
512  return obstack_next_free (obstack);
513}
514
515int (obstack_object_size) (obstack)
516     struct obstack *obstack;
517{
518  return obstack_object_size (obstack);
519}
520
521int (obstack_room) (obstack)
522     struct obstack *obstack;
523{
524  return obstack_room (obstack);
525}
526
527int (obstack_make_room) (obstack, length)
528     struct obstack *obstack;
529     int length;
530{
531  return obstack_make_room (obstack, length);
532}
533
534void (obstack_grow) (obstack, data, length)
535     struct obstack *obstack;
536     const POINTER data;
537     int length;
538{
539  obstack_grow (obstack, data, length);
540}
541
542void (obstack_grow0) (obstack, data, length)
543     struct obstack *obstack;
544     const POINTER data;
545     int length;
546{
547  obstack_grow0 (obstack, data, length);
548}
549
550void (obstack_1grow) (obstack, character)
551     struct obstack *obstack;
552     int character;
553{
554  obstack_1grow (obstack, character);
555}
556
557void (obstack_blank) (obstack, length)
558     struct obstack *obstack;
559     int length;
560{
561  obstack_blank (obstack, length);
562}
563
564void (obstack_1grow_fast) (obstack, character)
565     struct obstack *obstack;
566     int character;
567{
568  obstack_1grow_fast (obstack, character);
569}
570
571void (obstack_blank_fast) (obstack, length)
572     struct obstack *obstack;
573     int length;
574{
575  obstack_blank_fast (obstack, length);
576}
577
578POINTER (obstack_finish) (obstack)
579     struct obstack *obstack;
580{
581  return obstack_finish (obstack);
582}
583
584POINTER (obstack_alloc) (obstack, length)
585     struct obstack *obstack;
586     int length;
587{
588  return obstack_alloc (obstack, length);
589}
590
591POINTER (obstack_copy) (obstack, address, length)
592     struct obstack *obstack;
593     const POINTER address;
594     int length;
595{
596  return obstack_copy (obstack, address, length);
597}
598
599POINTER (obstack_copy0) (obstack, address, length)
600     struct obstack *obstack;
601     const POINTER address;
602     int length;
603{
604  return obstack_copy0 (obstack, address, length);
605}
606
607#endif /* __STDC__ */
608
609#endif /* 0 */
610
611#endif  /* !ELIDE_CODE */