1 |
/* obstack.c - subroutines used implicitly by object stack macros |
/* obstack.c - subroutines used implicitly by object stack macros |
2 |
Copyright (C) 1988-1994, 1996-1999, 2000-2002 Free Software Foundation, Inc. |
|
3 |
|
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, |
4 |
|
1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. |
5 |
|
|
6 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
7 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
8 |
the Free Software Foundation; either version 2, or (at your option) |
the Free Software Foundation; either version 2, or (at your option) |
52 |
#ifndef ELIDE_CODE |
#ifndef ELIDE_CODE |
53 |
|
|
54 |
|
|
|
# if defined __STDC__ && __STDC__ |
|
|
# define POINTER void * |
|
|
# else |
|
|
# define POINTER char * |
|
|
# endif |
|
|
|
|
55 |
/* Determine default alignment. */ |
/* Determine default alignment. */ |
56 |
struct fooalign {char x; double d;}; |
struct fooalign {char x; double d;}; |
57 |
# define DEFAULT_ALIGNMENT \ |
# define DEFAULT_ALIGNMENT \ |
77 |
abort gracefully or use longjump - but shouldn't return. This |
abort gracefully or use longjump - but shouldn't return. This |
78 |
variable by default points to the internal function |
variable by default points to the internal function |
79 |
`print_and_abort'. */ |
`print_and_abort'. */ |
|
# if defined __STDC__ && __STDC__ |
|
80 |
static void print_and_abort (void); |
static void print_and_abort (void); |
81 |
void (*obstack_alloc_failed_handler) (void) = print_and_abort; |
void (*obstack_alloc_failed_handler) (void) = print_and_abort; |
|
# else |
|
|
static void print_and_abort (); |
|
|
void (*obstack_alloc_failed_handler) () = print_and_abort; |
|
|
# endif |
|
82 |
|
|
83 |
/* Exit value used when `print_and_abort' is used. */ |
/* Exit value used when `print_and_abort' is used. */ |
84 |
# if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H |
# include <stdlib.h> |
85 |
# include <stdlib.h> |
# ifndef _LIBC |
86 |
# endif |
# include "exit.h" |
|
# ifndef EXIT_FAILURE |
|
|
# define EXIT_FAILURE 1 |
|
87 |
# endif |
# endif |
88 |
int obstack_exit_failure = EXIT_FAILURE; |
int obstack_exit_failure = EXIT_FAILURE; |
89 |
|
|
98 |
For free, do not use ?:, since some compilers, like the MIPS compilers, |
For free, do not use ?:, since some compilers, like the MIPS compilers, |
99 |
do not allow (expr) ? void : void. */ |
do not allow (expr) ? void : void. */ |
100 |
|
|
101 |
# if defined __STDC__ && __STDC__ |
# define CALL_CHUNKFUN(h, size) \ |
|
# define CALL_CHUNKFUN(h, size) \ |
|
102 |
(((h) -> use_extra_arg) \ |
(((h) -> use_extra_arg) \ |
103 |
? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ |
? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ |
104 |
: (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) |
: (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) |
105 |
|
|
106 |
# define CALL_FREEFUN(h, old_chunk) \ |
# define CALL_FREEFUN(h, old_chunk) \ |
107 |
do { \ |
do { \ |
108 |
if ((h) -> use_extra_arg) \ |
if ((h) -> use_extra_arg) \ |
109 |
(*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ |
(*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ |
110 |
else \ |
else \ |
111 |
(*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ |
(*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ |
112 |
} while (0) |
} while (0) |
|
# else |
|
|
# define CALL_CHUNKFUN(h, size) \ |
|
|
(((h) -> use_extra_arg) \ |
|
|
? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ |
|
|
: (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size))) |
|
|
|
|
|
# define CALL_FREEFUN(h, old_chunk) \ |
|
|
do { \ |
|
|
if ((h) -> use_extra_arg) \ |
|
|
(*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ |
|
|
else \ |
|
|
(*(void (*) ()) (h)->freefun) ((old_chunk)); \ |
|
|
} while (0) |
|
|
# endif |
|
113 |
|
|
114 |
|
|
115 |
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). |
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). |
121 |
allocation fails. */ |
allocation fails. */ |
122 |
|
|
123 |
int |
int |
124 |
_obstack_begin (h, size, alignment, chunkfun, freefun) |
_obstack_begin (struct obstack *h, |
125 |
struct obstack *h; |
int size, int alignment, |
126 |
int size; |
void *(*chunkfun) (long), |
127 |
int alignment; |
void (*freefun) (void *)) |
|
# if defined __STDC__ && __STDC__ |
|
|
POINTER (*chunkfun) (long); |
|
|
void (*freefun) (void *); |
|
|
# else |
|
|
POINTER (*chunkfun) (); |
|
|
void (*freefun) (); |
|
|
# endif |
|
128 |
{ |
{ |
129 |
register struct _obstack_chunk *chunk; /* points to new chunk */ |
register struct _obstack_chunk *chunk; /* points to new chunk */ |
130 |
|
|
147 |
size = 4096 - extra; |
size = 4096 - extra; |
148 |
} |
} |
149 |
|
|
|
# if defined __STDC__ && __STDC__ |
|
150 |
h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; |
h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; |
151 |
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; |
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; |
|
# else |
|
|
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; |
|
|
h->freefun = freefun; |
|
|
# endif |
|
152 |
h->chunk_size = size; |
h->chunk_size = size; |
153 |
h->alignment_mask = alignment - 1; |
h->alignment_mask = alignment - 1; |
154 |
h->use_extra_arg = 0; |
h->use_extra_arg = 0; |
167 |
} |
} |
168 |
|
|
169 |
int |
int |
170 |
_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) |
_obstack_begin_1 (struct obstack *h, int size, int alignment, |
171 |
struct obstack *h; |
void *(*chunkfun) (void *, long), |
172 |
int size; |
void (*freefun) (void *, void *), |
173 |
int alignment; |
void *arg) |
|
# if defined __STDC__ && __STDC__ |
|
|
POINTER (*chunkfun) (POINTER, long); |
|
|
void (*freefun) (POINTER, POINTER); |
|
|
# else |
|
|
POINTER (*chunkfun) (); |
|
|
void (*freefun) (); |
|
|
# endif |
|
|
POINTER arg; |
|
174 |
{ |
{ |
175 |
register struct _obstack_chunk *chunk; /* points to new chunk */ |
register struct _obstack_chunk *chunk; /* points to new chunk */ |
176 |
|
|
193 |
size = 4096 - extra; |
size = 4096 - extra; |
194 |
} |
} |
195 |
|
|
|
# if defined __STDC__ && __STDC__ |
|
196 |
h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; |
h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; |
197 |
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; |
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; |
|
# else |
|
|
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; |
|
|
h->freefun = freefun; |
|
|
# endif |
|
198 |
h->chunk_size = size; |
h->chunk_size = size; |
199 |
h->alignment_mask = alignment - 1; |
h->alignment_mask = alignment - 1; |
200 |
h->extra_arg = arg; |
h->extra_arg = arg; |
220 |
to the beginning of the new one. */ |
to the beginning of the new one. */ |
221 |
|
|
222 |
void |
void |
223 |
_obstack_newchunk (h, length) |
_obstack_newchunk (struct obstack *h, int length) |
|
struct obstack *h; |
|
|
int length; |
|
224 |
{ |
{ |
225 |
register struct _obstack_chunk *old_chunk = h->chunk; |
register struct _obstack_chunk *old_chunk = h->chunk; |
226 |
register struct _obstack_chunk *new_chunk; |
register struct _obstack_chunk *new_chunk; |
287 |
This is here for debugging. |
This is here for debugging. |
288 |
If you use it in a program, you are probably losing. */ |
If you use it in a program, you are probably losing. */ |
289 |
|
|
|
# if defined __STDC__ && __STDC__ |
|
290 |
/* Suppress -Wmissing-prototypes warning. We don't want to declare this in |
/* Suppress -Wmissing-prototypes warning. We don't want to declare this in |
291 |
obstack.h because it is just for debugging. */ |
obstack.h because it is just for debugging. */ |
292 |
int _obstack_allocated_p (struct obstack *h, POINTER obj); |
int _obstack_allocated_p (struct obstack *h, void *obj); |
|
# endif |
|
293 |
|
|
294 |
int |
int |
295 |
_obstack_allocated_p (h, obj) |
_obstack_allocated_p (struct obstack *h, void *obj) |
|
struct obstack *h; |
|
|
POINTER obj; |
|
296 |
{ |
{ |
297 |
register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ |
register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ |
298 |
register struct _obstack_chunk *plp; /* point to previous chunk if any */ |
register struct _obstack_chunk *plp; /* point to previous chunk if any */ |
301 |
/* We use >= rather than > since the object cannot be exactly at |
/* We use >= rather than > since the object cannot be exactly at |
302 |
the beginning of the chunk but might be an empty object exactly |
the beginning of the chunk but might be an empty object exactly |
303 |
at the end of an adjacent chunk. */ |
at the end of an adjacent chunk. */ |
304 |
while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) |
while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) |
305 |
{ |
{ |
306 |
plp = lp->prev; |
plp = lp->prev; |
307 |
lp = plp; |
lp = plp; |
318 |
This is the first one, called from non-ANSI code. */ |
This is the first one, called from non-ANSI code. */ |
319 |
|
|
320 |
void |
void |
321 |
_obstack_free (h, obj) |
_obstack_free (struct obstack *h, void *obj) |
|
struct obstack *h; |
|
|
POINTER obj; |
|
322 |
{ |
{ |
323 |
register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ |
register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ |
324 |
register struct _obstack_chunk *plp; /* point to previous chunk if any */ |
register struct _obstack_chunk *plp; /* point to previous chunk if any */ |
327 |
/* We use >= because there cannot be an object at the beginning of a chunk. |
/* We use >= because there cannot be an object at the beginning of a chunk. |
328 |
But there can be an empty object at that address |
But there can be an empty object at that address |
329 |
at the end of another chunk. */ |
at the end of another chunk. */ |
330 |
while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) |
while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) |
331 |
{ |
{ |
332 |
plp = lp->prev; |
plp = lp->prev; |
333 |
CALL_FREEFUN (h, lp); |
CALL_FREEFUN (h, lp); |
350 |
/* This function is used from ANSI code. */ |
/* This function is used from ANSI code. */ |
351 |
|
|
352 |
void |
void |
353 |
obstack_free (h, obj) |
obstack_free (struct obstack *h, void *obj) |
|
struct obstack *h; |
|
|
POINTER obj; |
|
354 |
{ |
{ |
355 |
register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ |
register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ |
356 |
register struct _obstack_chunk *plp; /* point to previous chunk if any */ |
register struct _obstack_chunk *plp; /* point to previous chunk if any */ |
359 |
/* We use >= because there cannot be an object at the beginning of a chunk. |
/* We use >= because there cannot be an object at the beginning of a chunk. |
360 |
But there can be an empty object at that address |
But there can be an empty object at that address |
361 |
at the end of another chunk. */ |
at the end of another chunk. */ |
362 |
while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) |
while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) |
363 |
{ |
{ |
364 |
plp = lp->prev; |
plp = lp->prev; |
365 |
CALL_FREEFUN (h, lp); |
CALL_FREEFUN (h, lp); |
380 |
} |
} |
381 |
|
|
382 |
int |
int |
383 |
_obstack_memory_used (h) |
_obstack_memory_used (struct obstack *h) |
|
struct obstack *h; |
|
384 |
{ |
{ |
385 |
register struct _obstack_chunk* lp; |
register struct _obstack_chunk* lp; |
386 |
register int nbytes = 0; |
register int nbytes = 0; |
414 |
|
|
415 |
static void |
static void |
416 |
__attribute__ ((noreturn)) |
__attribute__ ((noreturn)) |
417 |
print_and_abort () |
print_and_abort (void) |
418 |
{ |
{ |
419 |
/* Don't change any of these strings. Yes, it would be possible to add |
/* Don't change any of these strings. Yes, it would be possible to add |
420 |
the newline to the string and use fputs or so. But this must not |
the newline to the string and use fputs or so. But this must not |
429 |
fprintf (stderr, "%s\n", _("memory exhausted")); |
fprintf (stderr, "%s\n", _("memory exhausted")); |
430 |
exit (obstack_exit_failure); |
exit (obstack_exit_failure); |
431 |
} |
} |
|
|
|
|
# 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. */ |
|
|
|
|
|
# if defined __STDC__ && __STDC__ |
|
|
/* These function definitions do not work with non-ANSI preprocessors; |
|
|
they won't pass through the macro names in parentheses. */ |
|
|
|
|
|
/* The function names appear in parentheses in order to prevent |
|
|
the macro-definitions of the names from being expanded there. */ |
|
|
|
|
|
POINTER (obstack_base) (obstack) |
|
|
struct obstack *obstack; |
|
|
{ |
|
|
return obstack_base (obstack); |
|
|
} |
|
|
|
|
|
POINTER (obstack_next_free) (obstack) |
|
|
struct obstack *obstack; |
|
|
{ |
|
|
return obstack_next_free (obstack); |
|
|
} |
|
|
|
|
|
int (obstack_object_size) (obstack) |
|
|
struct obstack *obstack; |
|
|
{ |
|
|
return obstack_object_size (obstack); |
|
|
} |
|
|
|
|
|
int (obstack_room) (obstack) |
|
|
struct obstack *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, data, length) |
|
|
struct obstack *obstack; |
|
|
const POINTER data; |
|
|
int length; |
|
|
{ |
|
|
obstack_grow (obstack, data, length); |
|
|
} |
|
|
|
|
|
void (obstack_grow0) (obstack, data, length) |
|
|
struct obstack *obstack; |
|
|
const POINTER data; |
|
|
int length; |
|
|
{ |
|
|
obstack_grow0 (obstack, data, length); |
|
|
} |
|
|
|
|
|
void (obstack_1grow) (obstack, character) |
|
|
struct obstack *obstack; |
|
|
int character; |
|
|
{ |
|
|
obstack_1grow (obstack, character); |
|
|
} |
|
|
|
|
|
void (obstack_blank) (obstack, length) |
|
|
struct obstack *obstack; |
|
|
int length; |
|
|
{ |
|
|
obstack_blank (obstack, length); |
|
|
} |
|
|
|
|
|
void (obstack_1grow_fast) (obstack, character) |
|
|
struct obstack *obstack; |
|
|
int character; |
|
|
{ |
|
|
obstack_1grow_fast (obstack, character); |
|
|
} |
|
|
|
|
|
void (obstack_blank_fast) (obstack, length) |
|
|
struct obstack *obstack; |
|
|
int length; |
|
|
{ |
|
|
obstack_blank_fast (obstack, length); |
|
|
} |
|
|
|
|
|
POINTER (obstack_finish) (obstack) |
|
|
struct obstack *obstack; |
|
|
{ |
|
|
return obstack_finish (obstack); |
|
|
} |
|
|
|
|
|
POINTER (obstack_alloc) (obstack, length) |
|
|
struct obstack *obstack; |
|
|
int length; |
|
|
{ |
|
|
return obstack_alloc (obstack, length); |
|
|
} |
|
|
|
|
|
POINTER (obstack_copy) (obstack, address, length) |
|
|
struct obstack *obstack; |
|
|
const POINTER address; |
|
|
int length; |
|
|
{ |
|
|
return obstack_copy (obstack, address, length); |
|
|
} |
|
|
|
|
|
POINTER (obstack_copy0) (obstack, address, length) |
|
|
struct obstack *obstack; |
|
|
const POINTER address; |
|
|
int length; |
|
|
{ |
|
|
return obstack_copy0 (obstack, address, length); |
|
|
} |
|
|
|
|
|
# endif /* __STDC__ */ |
|
|
|
|
|
# endif /* 0 */ |
|
432 |
|
|
433 |
#endif /* !ELIDE_CODE */ |
#endif /* !ELIDE_CODE */ |