*** obstack.h~ Mon Aug 27 08:07:17 2007 --- obstack.h Mon Aug 27 08:48:16 2007 *************** *** 161,166 **** --- 161,175 ---- void *tempptr; } temp; /* Temporary for some macros. */ int alignment_mask; /* Mask of alignment for each object. */ + #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING + void (*alloc_failed_handler) (void *); + /* This is an obstack-specific error + handler that takes precedence over + the global one. */ + void *user_data; /* The user provided data is given to + either the obstack-specific error + handler or the global handler. */ + #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ /* These prototypes vary based on `use_extra_arg', and we use casts to the prototypeless function type in all assignments, but having prototypes here quiets -Wstrict-prototypes. */ *************** *** 180,190 **** --- 189,209 ---- /* Declare the external functions we use; they are in obstack.c. */ extern void _obstack_newchunk (struct obstack *, int); + #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING + extern int _obstack_begin (struct obstack *, int, int, + void *(*) (long), void (*) (void *), + void (*) (void *), void *); + extern int _obstack_begin_1 (struct obstack *, int, int, + void *(*) (void *, long), + void (*) (void *, void *), void *, + void (*) (void *), void *); + #else /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ extern int _obstack_begin (struct obstack *, int, int, void *(*) (long), void (*) (void *)); extern int _obstack_begin_1 (struct obstack *, int, int, void *(*) (void *, long), void (*) (void *, void *), void *); + #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ extern int _obstack_memory_used (struct obstack *); void obstack_free (struct obstack *obstack, void *block); *************** *** 194,200 **** --- 213,223 ---- more memory. This can be set to a user defined function which should either abort gracefully or use longjump - but shouldn't return. The default action is to print a message and abort. */ + #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING + extern void (*obstack_alloc_failed_handler) (void *); + #else /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ extern void (*obstack_alloc_failed_handler) (void); + #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ /* Exit value used when `print_and_abort' is used. */ extern int obstack_exit_failure; *************** *** 218,223 **** --- 241,282 ---- #define obstack_alignment_mask(h) ((h)->alignment_mask) /* To prevent prototype warnings provide complete argument list. */ + #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING + + #define obstack_alloc_failed_handler(h, new_handler) \ + ((h)->alloc_failed_handler = (void (*) (void *)) (new_handler)) + + #define obstack_user_data(h, new_user_data) \ + ((h)->user_data = (void *) (new_user_data)) + + #define obstack_init_sophisticatedly(h, handler, user_data) \ + _obstack_begin ((h), 0, 0, \ + (void *(*) (long)) obstack_chunk_alloc, \ + (void (*) (void *)) obstack_chunk_free, \ + (handler), (user_data)) + + #define obstack_init(h) obstack_init_sophisticatedly ((h), NULL, NULL) + + #define obstack_begin(h, size) \ + _obstack_begin ((h), (size), 0, \ + (void *(*) (long)) obstack_chunk_alloc, \ + (void (*) (void *)) obstack_chunk_free, \ + (h)->alloc_failed_handler, (h)->user_data) + + #define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ + _obstack_begin ((h), (size), (alignment), \ + (void *(*) (long)) (chunkfun), \ + (void (*) (void *)) (freefun) \ + (h)->alloc_failed_handler, (h)->user_data) + + #define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ + _obstack_begin_1 ((h), (size), (alignment), \ + (void *(*) (void *, long)) (chunkfun), \ + (void (*) (void *, void *)) (freefun), (arg), \ + (h)->alloc_failed_handler, (h)->user_data) + + #else /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ + #define obstack_init(h) \ _obstack_begin ((h), 0, 0, \ (void *(*) (long)) obstack_chunk_alloc, \ *************** *** 237,242 **** --- 296,303 ---- _obstack_begin_1 ((h), (size), (alignment), \ (void *(*) (void *, long)) (chunkfun), \ (void (*) (void *, void *)) (freefun), (arg)) + + #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ #define obstack_chunkfun(h, newchunkfun) \ ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun)) *** obstack.c~ Mon Aug 27 08:07:43 2007 --- obstack.c Mon Aug 27 09:00:08 2007 *************** *** 33,39 **** /* 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, and the installed library --- 33,39 ---- /* 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 2 /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself, and the installed library *************** *** 100,107 **** --- 100,112 ---- abort gracefully or use longjump - but shouldn't return. This variable by default points to the internal function `print_and_abort'. */ + #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING + static void print_and_abort (void *); + void (*obstack_alloc_failed_handler) (void *) = print_and_abort; + #else /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ static void print_and_abort (void); void (*obstack_alloc_failed_handler) (void) = print_and_abort; + #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ /* Exit value used when `print_and_abort' is used. */ # include *************** compat_symbol (libc, _obstack_compat, _o *** 147,160 **** CHUNKFUN is the function to use to allocate chunks, and FREEFUN the function to free them. ! Return nonzero if successful, calls obstack_alloc_failed_handler if ! allocation fails. */ int _obstack_begin (struct obstack *h, int size, int alignment, void *(*chunkfun) (long), ! void (*freefun) (void *)) { register struct _obstack_chunk *chunk; /* points to new chunk */ --- 152,174 ---- CHUNKFUN is the function to use to allocate chunks, and FREEFUN the function to free them. ! HANDLER is the obstack's local error handler instead of the global handler. ! USER_DATA is passed to the error handler, either the local one or the global ! one. ! ! Return nonzero if successful, calls obstack's local failed handler, ! or obstack_alloc_failed_handler if allocation fails. */ int _obstack_begin (struct obstack *h, int size, int alignment, void *(*chunkfun) (long), ! void (*freefun) (void *) ! #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING ! , void (*handler) (void *), ! void *user_data ! #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ ! ) { register struct _obstack_chunk *chunk; /* points to new chunk */ *************** _obstack_begin (struct obstack *h, *** 182,191 **** --- 196,218 ---- h->chunk_size = size; h->alignment_mask = alignment - 1; h->use_extra_arg = 0; + #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING + h->alloc_failed_handler = handler; + h->user_data = user_data; + #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); if (!chunk) + #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING + { + if (h->alloc_failed_handler) + (*h->alloc_failed_handler) (h->user_data); + else + (*obstack_alloc_failed_handler) (h->user_data); + } + #else /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ (*obstack_alloc_failed_handler) (); + #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, alignment - 1); h->chunk_limit = chunk->limit *************** _obstack_begin (struct obstack *h, *** 201,207 **** _obstack_begin_1 (struct obstack *h, int size, int alignment, void *(*chunkfun) (void *, long), void (*freefun) (void *, void *), ! void *arg) { register struct _obstack_chunk *chunk; /* points to new chunk */ --- 228,239 ---- _obstack_begin_1 (struct obstack *h, int size, int alignment, void *(*chunkfun) (void *, long), void (*freefun) (void *, void *), ! void *arg ! #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING ! , void (*handler) (void *), ! void *user_data ! #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ ! ) { register struct _obstack_chunk *chunk; /* points to new chunk */ *************** _obstack_begin_1 (struct obstack *h, int *** 230,239 **** --- 262,284 ---- h->alignment_mask = alignment - 1; h->extra_arg = arg; h->use_extra_arg = 1; + #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING + h->alloc_failed_handler = handler; + h->user_data = user_data; + #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); if (!chunk) + #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING + { + if (h->alloc_failed_handler) + (*h->alloc_failed_handler) (h->user_data); + else + (*obstack_alloc_failed_handler) (h->user_data); + } + #else /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ (*obstack_alloc_failed_handler) (); + #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, alignment - 1); h->chunk_limit = chunk->limit *************** _obstack_newchunk (struct obstack *h, in *** 270,276 **** --- 315,330 ---- /* Allocate and initialize the new chunk. */ new_chunk = CALL_CHUNKFUN (h, new_size); if (!new_chunk) + #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING + { + if (h->alloc_failed_handler) + (*h->alloc_failed_handler) (h->user_data); + else + (*obstack_alloc_failed_handler) (h->user_data); + } + #else /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ (*obstack_alloc_failed_handler) (); + #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ h->chunk = new_chunk; new_chunk->prev = old_chunk; new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; *************** _obstack_memory_used (struct obstack *h) *** 423,429 **** static void __attribute__ ((noreturn)) ! print_and_abort (void) { /* 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 --- 477,489 ---- static void __attribute__ ((noreturn)) ! print_and_abort ( ! #ifdef OBSTACK_SOPHISTICATED_FAILED_HANDLING ! void *user_data ! #else /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ ! void ! #endif /* OBSTACK_SOPHISTICATED_FAILED_HANDLING */ ! ) { /* 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