obstack.c revision 53451
153451Speter/* obstack.c - subroutines used implicitly by object stack macros 253451Speter Copyright (C) 1988, 1993 Free Software Foundation, Inc. 353451Speter 453451SpeterThis program is free software; you can redistribute it and/or modify it 553451Speterunder the terms of the GNU General Public License as published by the 653451SpeterFree Software Foundation; either version 2, or (at your option) any 753451Speterlater version. 853451Speter 953451SpeterThis program is distributed in the hope that it will be useful, 1053451Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1153451SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1253451SpeterGNU General Public License for more details. 1353451Speter 1453451SpeterYou should have received a copy of the GNU General Public License 1553451Speteralong with this program; if not, write to the Free Software 1653451SpeterFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 1753451Speter 1853451Speter#include "obstack.h" 1953451Speter 2053451Speter/* This is just to get __GNU_LIBRARY__ defined. */ 2153451Speter#include <stdio.h> 2253451Speter 2353451Speter/* Comment out all this code if we are using the GNU C Library, and are not 2453451Speter actually compiling the library itself. This code is part of the GNU C 2553451Speter Library, but also included in many other GNU distributions. Compiling 2653451Speter and linking in this code is a waste when using the GNU C library 2753451Speter (especially if it is a shared library). Rather than having every GNU 2853451Speter program understand `configure --with-gnu-libc' and omit the object files, 2953451Speter it is simpler to just do this in the source for each such file. */ 3053451Speter 3153451Speter#if defined (_LIBC) || !defined (__GNU_LIBRARY__) 3253451Speter 3353451Speter 3453451Speter#ifdef __STDC__ 3553451Speter#define POINTER void * 3653451Speter#else 3753451Speter#define POINTER char * 3853451Speter#endif 3953451Speter 4053451Speter/* Determine default alignment. */ 4153451Speterstruct fooalign {char x; double d;}; 4253451Speter#define DEFAULT_ALIGNMENT \ 4353451Speter ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0)) 4453451Speter/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. 4553451Speter But in fact it might be less smart and round addresses to as much as 4653451Speter DEFAULT_ROUNDING. So we prepare for it to do that. */ 4753451Speterunion fooround {long x; double d;}; 4853451Speter#define DEFAULT_ROUNDING (sizeof (union fooround)) 4953451Speter 5053451Speter/* When we copy a long block of data, this is the unit to do it with. 5153451Speter On some machines, copying successive ints does not work; 5253451Speter in such a case, redefine COPYING_UNIT to `long' (if that works) 5353451Speter or `char' as a last resort. */ 5453451Speter#ifndef COPYING_UNIT 5553451Speter#define COPYING_UNIT int 5653451Speter#endif 5753451Speter 5853451Speter/* The non-GNU-C macros copy the obstack into this global variable 5953451Speter to avoid multiple evaluation. */ 6053451Speter 6153451Speterstruct obstack *_obstack; 6253451Speter 6353451Speter/* Define a macro that either calls functions with the traditional malloc/free 6453451Speter calling interface, or calls functions with the mmalloc/mfree interface 6553451Speter (that adds an extra first argument), based on the state of use_extra_arg. 6653451Speter For free, do not use ?:, since some compilers, like the MIPS compilers, 6753451Speter do not allow (expr) ? void : void. */ 6853451Speter 6953451Speter#define CALL_CHUNKFUN(h, size) \ 7053451Speter (((h) -> use_extra_arg) \ 7153451Speter ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ 7253451Speter : (*(h)->chunkfun) ((size))) 7353451Speter 7453451Speter#define CALL_FREEFUN(h, old_chunk) \ 7553451Speter do { \ 7653451Speter if ((h) -> use_extra_arg) \ 7753451Speter (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ 7853451Speter else \ 7953451Speter (*(h)->freefun) ((old_chunk)); \ 8053451Speter } while (0) 8153451Speter 8253451Speter 8353451Speter/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). 8453451Speter Objects start on multiples of ALIGNMENT (0 means use default). 8553451Speter CHUNKFUN is the function to use to allocate chunks, 8653451Speter and FREEFUN the function to free them. */ 8753451Speter 8853451Spetervoid 8953451Speter_obstack_begin (h, size, alignment, chunkfun, freefun) 9053451Speter struct obstack *h; 9153451Speter int size; 9253451Speter int alignment; 9353451Speter POINTER (*chunkfun) (); 9453451Speter void (*freefun) (); 9553451Speter{ 9653451Speter register struct _obstack_chunk* chunk; /* points to new chunk */ 9753451Speter 9853451Speter if (alignment == 0) 9953451Speter alignment = DEFAULT_ALIGNMENT; 10053451Speter if (size == 0) 10153451Speter /* Default size is what GNU malloc can fit in a 4096-byte block. */ 10253451Speter { 10353451Speter /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. 10453451Speter Use the values for range checking, because if range checking is off, 10553451Speter the extra bytes won't be missed terribly, but if range checking is on 10653451Speter and we used a larger request, a whole extra 4096 bytes would be 10753451Speter allocated. 10853451Speter 10953451Speter These number are irrelevant to the new GNU malloc. I suspect it is 11053451Speter less sensitive to the size of the request. */ 11153451Speter int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) 11253451Speter + 4 + DEFAULT_ROUNDING - 1) 11353451Speter & ~(DEFAULT_ROUNDING - 1)); 11453451Speter size = 4096 - extra; 11553451Speter } 11653451Speter 11753451Speter h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; 11853451Speter h->freefun = freefun; 11953451Speter h->chunk_size = size; 12053451Speter h->alignment_mask = alignment - 1; 12153451Speter h->use_extra_arg = 0; 12253451Speter 12353451Speter chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); 12453451Speter h->next_free = h->object_base = chunk->contents; 12553451Speter h->chunk_limit = chunk->limit 12653451Speter = (char *) chunk + h->chunk_size; 12753451Speter chunk->prev = 0; 12853451Speter /* The initial chunk now contains no empty object. */ 12953451Speter h->maybe_empty_object = 0; 13053451Speter} 13153451Speter 13253451Spetervoid 13353451Speter_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) 13453451Speter struct obstack *h; 13553451Speter int size; 13653451Speter int alignment; 13753451Speter POINTER (*chunkfun) (); 13853451Speter void (*freefun) (); 13953451Speter POINTER arg; 14053451Speter{ 14153451Speter register struct _obstack_chunk* chunk; /* points to new chunk */ 14253451Speter 14353451Speter if (alignment == 0) 14453451Speter alignment = DEFAULT_ALIGNMENT; 14553451Speter if (size == 0) 14653451Speter /* Default size is what GNU malloc can fit in a 4096-byte block. */ 14753451Speter { 14853451Speter /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. 14953451Speter Use the values for range checking, because if range checking is off, 15053451Speter the extra bytes won't be missed terribly, but if range checking is on 15153451Speter and we used a larger request, a whole extra 4096 bytes would be 15253451Speter allocated. 15353451Speter 15453451Speter These number are irrelevant to the new GNU malloc. I suspect it is 15553451Speter less sensitive to the size of the request. */ 15653451Speter int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) 15753451Speter + 4 + DEFAULT_ROUNDING - 1) 15853451Speter & ~(DEFAULT_ROUNDING - 1)); 15953451Speter size = 4096 - extra; 16053451Speter } 16153451Speter 16253451Speter h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; 16353451Speter h->freefun = freefun; 16453451Speter h->chunk_size = size; 16553451Speter h->alignment_mask = alignment - 1; 16653451Speter h->extra_arg = arg; 16753451Speter h->use_extra_arg = 1; 16853451Speter 16953451Speter chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); 17053451Speter h->next_free = h->object_base = chunk->contents; 17153451Speter h->chunk_limit = chunk->limit 17253451Speter = (char *) chunk + h->chunk_size; 17353451Speter chunk->prev = 0; 17453451Speter /* The initial chunk now contains no empty object. */ 17553451Speter h->maybe_empty_object = 0; 17653451Speter} 17753451Speter 17853451Speter/* Allocate a new current chunk for the obstack *H 17953451Speter on the assumption that LENGTH bytes need to be added 18053451Speter to the current object, or a new object of length LENGTH allocated. 18153451Speter Copies any partial object from the end of the old chunk 18253451Speter to the beginning of the new one. */ 18353451Speter 18453451Spetervoid 18553451Speter_obstack_newchunk (h, length) 18653451Speter struct obstack *h; 18753451Speter int length; 18853451Speter{ 18953451Speter register struct _obstack_chunk* old_chunk = h->chunk; 19053451Speter register struct _obstack_chunk* new_chunk; 19153451Speter register long new_size; 19253451Speter register int obj_size = h->next_free - h->object_base; 19353451Speter register int i; 19453451Speter int already; 19553451Speter 19653451Speter /* Compute size for new chunk. */ 19753451Speter new_size = (obj_size + length) + (obj_size >> 3) + 100; 19853451Speter if (new_size < h->chunk_size) 19953451Speter new_size = h->chunk_size; 20053451Speter 20153451Speter /* Allocate and initialize the new chunk. */ 20253451Speter new_chunk = h->chunk = CALL_CHUNKFUN (h, new_size); 20353451Speter new_chunk->prev = old_chunk; 20453451Speter new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; 20553451Speter 20653451Speter /* Move the existing object to the new chunk. 20753451Speter Word at a time is fast and is safe if the object 20853451Speter is sufficiently aligned. */ 20953451Speter if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) 21053451Speter { 21153451Speter for (i = obj_size / sizeof (COPYING_UNIT) - 1; 21253451Speter i >= 0; i--) 21353451Speter ((COPYING_UNIT *)new_chunk->contents)[i] 21453451Speter = ((COPYING_UNIT *)h->object_base)[i]; 21553451Speter /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, 21653451Speter but that can cross a page boundary on a machine 21753451Speter which does not do strict alignment for COPYING_UNITS. */ 21853451Speter already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); 21953451Speter } 22053451Speter else 22153451Speter already = 0; 22253451Speter /* Copy remaining bytes one by one. */ 22353451Speter for (i = already; i < obj_size; i++) 22453451Speter new_chunk->contents[i] = h->object_base[i]; 22553451Speter 22653451Speter /* If the object just copied was the only data in OLD_CHUNK, 22753451Speter free that chunk and remove it from the chain. 22853451Speter But not if that chunk might contain an empty object. */ 22953451Speter if (h->object_base == old_chunk->contents && ! h->maybe_empty_object) 23053451Speter { 23153451Speter new_chunk->prev = old_chunk->prev; 23253451Speter CALL_FREEFUN (h, old_chunk); 23353451Speter } 23453451Speter 23553451Speter h->object_base = new_chunk->contents; 23653451Speter h->next_free = h->object_base + obj_size; 23753451Speter /* The new chunk certainly contains no empty object yet. */ 23853451Speter h->maybe_empty_object = 0; 23953451Speter} 24053451Speter 24153451Speter/* Return nonzero if object OBJ has been allocated from obstack H. 24253451Speter This is here for debugging. 24353451Speter If you use it in a program, you are probably losing. */ 24453451Speter 24553451Speterint 24653451Speter_obstack_allocated_p (h, obj) 24753451Speter struct obstack *h; 24853451Speter POINTER obj; 24953451Speter{ 25053451Speter register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ 25153451Speter register struct _obstack_chunk* plp; /* point to previous chunk if any */ 25253451Speter 25353451Speter lp = (h)->chunk; 25453451Speter /* We use >= rather than > since the object cannot be exactly at 25553451Speter the beginning of the chunk but might be an empty object exactly 25653451Speter at the end of an adjacent chunk. */ 25753451Speter while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) 25853451Speter { 25953451Speter plp = lp->prev; 26053451Speter lp = plp; 26153451Speter } 26253451Speter return lp != 0; 26353451Speter} 26453451Speter 26553451Speter/* Free objects in obstack H, including OBJ and everything allocate 26653451Speter more recently than OBJ. If OBJ is zero, free everything in H. */ 26753451Speter 26853451Speter#undef obstack_free 26953451Speter 27053451Speter/* This function has two names with identical definitions. 27153451Speter This is the first one, called from non-ANSI code. */ 27253451Speter 27353451Spetervoid 27453451Speter_obstack_free (h, obj) 27553451Speter struct obstack *h; 27653451Speter POINTER obj; 27753451Speter{ 27853451Speter register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ 27953451Speter register struct _obstack_chunk* plp; /* point to previous chunk if any */ 28053451Speter 28153451Speter lp = h->chunk; 28253451Speter /* We use >= because there cannot be an object at the beginning of a chunk. 28353451Speter But there can be an empty object at that address 28453451Speter at the end of another chunk. */ 28553451Speter while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) 28653451Speter { 28753451Speter plp = lp->prev; 28853451Speter CALL_FREEFUN (h, lp); 28953451Speter lp = plp; 29053451Speter /* If we switch chunks, we can't tell whether the new current 29153451Speter chunk contains an empty object, so assume that it may. */ 29253451Speter h->maybe_empty_object = 1; 29353451Speter } 29453451Speter if (lp) 29553451Speter { 29653451Speter h->object_base = h->next_free = (char *)(obj); 29753451Speter h->chunk_limit = lp->limit; 29853451Speter h->chunk = lp; 29953451Speter } 30053451Speter else if (obj != 0) 30153451Speter /* obj is not in any of the chunks! */ 30253451Speter abort (); 30353451Speter} 30453451Speter 30553451Speter/* This function is used from ANSI code. */ 30653451Speter 30753451Spetervoid 30853451Speterobstack_free (h, obj) 30953451Speter struct obstack *h; 31053451Speter POINTER obj; 31153451Speter{ 31253451Speter register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ 31353451Speter register struct _obstack_chunk* plp; /* point to previous chunk if any */ 31453451Speter 31553451Speter lp = h->chunk; 31653451Speter /* We use >= because there cannot be an object at the beginning of a chunk. 31753451Speter But there can be an empty object at that address 31853451Speter at the end of another chunk. */ 31953451Speter while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) 32053451Speter { 32153451Speter plp = lp->prev; 32253451Speter CALL_FREEFUN (h, lp); 32353451Speter lp = plp; 32453451Speter /* If we switch chunks, we can't tell whether the new current 32553451Speter chunk contains an empty object, so assume that it may. */ 32653451Speter h->maybe_empty_object = 1; 32753451Speter } 32853451Speter if (lp) 32953451Speter { 33053451Speter h->object_base = h->next_free = (char *)(obj); 33153451Speter h->chunk_limit = lp->limit; 33253451Speter h->chunk = lp; 33353451Speter } 33453451Speter else if (obj != 0) 33553451Speter /* obj is not in any of the chunks! */ 33653451Speter abort (); 33753451Speter} 33853451Speter 33953451Speter#if 0 34053451Speter/* These are now turned off because the applications do not use it 34153451Speter and it uses bcopy via obstack_grow, which causes trouble on sysV. */ 34253451Speter 34353451Speter/* Now define the functional versions of the obstack macros. 34453451Speter Define them to simply use the corresponding macros to do the job. */ 34553451Speter 34653451Speter#ifdef __STDC__ 34753451Speter/* These function definitions do not work with non-ANSI preprocessors; 34853451Speter they won't pass through the macro names in parentheses. */ 34953451Speter 35053451Speter/* The function names appear in parentheses in order to prevent 35153451Speter the macro-definitions of the names from being expanded there. */ 35253451Speter 35353451SpeterPOINTER (obstack_base) (obstack) 35453451Speter struct obstack *obstack; 35553451Speter{ 35653451Speter return obstack_base (obstack); 35753451Speter} 35853451Speter 35953451SpeterPOINTER (obstack_next_free) (obstack) 36053451Speter struct obstack *obstack; 36153451Speter{ 36253451Speter return obstack_next_free (obstack); 36353451Speter} 36453451Speter 36553451Speterint (obstack_object_size) (obstack) 36653451Speter struct obstack *obstack; 36753451Speter{ 36853451Speter return obstack_object_size (obstack); 36953451Speter} 37053451Speter 37153451Speterint (obstack_room) (obstack) 37253451Speter struct obstack *obstack; 37353451Speter{ 37453451Speter return obstack_room (obstack); 37553451Speter} 37653451Speter 37753451Spetervoid (obstack_grow) (obstack, pointer, length) 37853451Speter struct obstack *obstack; 37953451Speter POINTER pointer; 38053451Speter int length; 38153451Speter{ 38253451Speter obstack_grow (obstack, pointer, length); 38353451Speter} 38453451Speter 38553451Spetervoid (obstack_grow0) (obstack, pointer, length) 38653451Speter struct obstack *obstack; 38753451Speter POINTER pointer; 38853451Speter int length; 38953451Speter{ 39053451Speter obstack_grow0 (obstack, pointer, length); 39153451Speter} 39253451Speter 39353451Spetervoid (obstack_1grow) (obstack, character) 39453451Speter struct obstack *obstack; 39553451Speter int character; 39653451Speter{ 39753451Speter obstack_1grow (obstack, character); 39853451Speter} 39953451Speter 40053451Spetervoid (obstack_blank) (obstack, length) 40153451Speter struct obstack *obstack; 40253451Speter int length; 40353451Speter{ 40453451Speter obstack_blank (obstack, length); 40553451Speter} 40653451Speter 40753451Spetervoid (obstack_1grow_fast) (obstack, character) 40853451Speter struct obstack *obstack; 40953451Speter int character; 41053451Speter{ 41153451Speter obstack_1grow_fast (obstack, character); 41253451Speter} 41353451Speter 41453451Spetervoid (obstack_blank_fast) (obstack, length) 41553451Speter struct obstack *obstack; 41653451Speter int length; 41753451Speter{ 41853451Speter obstack_blank_fast (obstack, length); 41953451Speter} 42053451Speter 42153451SpeterPOINTER (obstack_finish) (obstack) 42253451Speter struct obstack *obstack; 42353451Speter{ 42453451Speter return obstack_finish (obstack); 42553451Speter} 42653451Speter 42753451SpeterPOINTER (obstack_alloc) (obstack, length) 42853451Speter struct obstack *obstack; 42953451Speter int length; 43053451Speter{ 43153451Speter return obstack_alloc (obstack, length); 43253451Speter} 43353451Speter 43453451SpeterPOINTER (obstack_copy) (obstack, pointer, length) 43553451Speter struct obstack *obstack; 43653451Speter POINTER pointer; 43753451Speter int length; 43853451Speter{ 43953451Speter return obstack_copy (obstack, pointer, length); 44053451Speter} 44153451Speter 44253451SpeterPOINTER (obstack_copy0) (obstack, pointer, length) 44353451Speter struct obstack *obstack; 44453451Speter POINTER pointer; 44553451Speter int length; 44653451Speter{ 44753451Speter return obstack_copy0 (obstack, pointer, length); 44853451Speter} 44953451Speter 45053451Speter#endif /* __STDC__ */ 45153451Speter 45253451Speter#endif /* 0 */ 45353451Speter 45453451Speter#endif /* _LIBC or not __GNU_LIBRARY__. */ 455