xref: /386bsd/usr/src/usr.bin/gas/obstack.c (revision a2142627)
1 /* obstack.c - subroutines used implicitly by object stack macros
2    Copyright (C) 1988 Free Software Foundation, Inc.
3 
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 1, or (at your option) any
7 later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
17 
18 #include "obstack.h"
19 
20 #ifdef __STDC__
21 #define POINTER void *
22 #else
23 #define POINTER char *
24 #endif
25 
26 /* Determine default alignment.  */
27 struct fooalign {char x; double d;};
28 #define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
29 /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
30    But in fact it might be less smart and round addresses to as much as
31    DEFAULT_ROUNDING.  So we prepare for it to do that.  */
32 union fooround {long x; double d;};
33 #define DEFAULT_ROUNDING (sizeof (union fooround))
34 
35 /* When we copy a long block of data, this is the unit to do it with.
36    On some machines, copying successive ints does not work;
37    in such a case, redefine COPYING_UNIT to `long' (if that works)
38    or `char' as a last resort.  */
39 #ifndef COPYING_UNIT
40 #define COPYING_UNIT int
41 #endif
42 
43 /* The non-GNU-C macros copy the obstack into this global variable
44    to avoid multiple evaluation.  */
45 
46 struct obstack *_obstack;
47 
48 /* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
49    Objects start on multiples of ALIGNMENT (0 means use default).
50    CHUNKFUN is the function to use to allocate chunks,
51    and FREEFUN the function to free them.  */
52 
53 void
_obstack_begin(h,size,alignment,chunkfun,freefun)54 _obstack_begin (h, size, alignment, chunkfun, freefun)
55      struct obstack *h;
56      int size;
57      int alignment;
58      POINTER (*chunkfun) ();
59      void (*freefun) ();
60 {
61   register struct _obstack_chunk* chunk; /* points to new chunk */
62 
63   if (alignment == 0)
64     alignment = DEFAULT_ALIGNMENT;
65   if (size == 0)
66     /* Default size is what GNU malloc can fit in a 4096-byte block.  */
67     {
68       /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
69 	 Use the values for range checking, because if range checking is off,
70 	 the extra bytes won't be missed terribly, but if range checking is on
71 	 and we used a larger request, a whole extra 4096 bytes would be
72 	 allocated.
73 
74 	 These number are irrelevant to the new GNU malloc.  I suspect it is
75 	 less sensitive to the size of the request.  */
76       int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
77 		    + 4 + DEFAULT_ROUNDING - 1)
78 		   & ~(DEFAULT_ROUNDING - 1));
79       size = 4096 - extra;
80     }
81 
82   h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
83   h->freefun = freefun;
84   h->chunk_size = size;
85   h->alignment_mask = alignment - 1;
86 
87   chunk	= h->chunk = (*h->chunkfun) (h->chunk_size);
88   h->next_free = h->object_base = chunk->contents;
89   h->chunk_limit = chunk->limit
90    = (char *) chunk + h->chunk_size;
91   chunk->prev = 0;
92 }
93 
94 /* Allocate a new current chunk for the obstack *H
95    on the assumption that LENGTH bytes need to be added
96    to the current object, or a new object of length LENGTH allocated.
97    Copies any partial object from the end of the old chunk
98    to the beginning of the new one.  */
99 
100 void
_obstack_newchunk(h,length)101 _obstack_newchunk (h, length)
102      struct obstack *h;
103      int length;
104 {
105   register struct _obstack_chunk*	old_chunk = h->chunk;
106   register struct _obstack_chunk*	new_chunk;
107   register long	new_size;
108   register int obj_size = h->next_free - h->object_base;
109   register int i;
110   int already;
111 
112   /* Compute size for new chunk.  */
113   new_size = (obj_size + length) + (obj_size >> 3) + 100;
114   if (new_size < h->chunk_size)
115     new_size = h->chunk_size;
116 
117   /* Allocate and initialize the new chunk.  */
118   new_chunk = h->chunk = (*h->chunkfun) (new_size);
119   new_chunk->prev = old_chunk;
120   new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
121 
122   /* Move the existing object to the new chunk.
123      Word at a time is fast and is safe if the object
124      is sufficiently aligned.  */
125   if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
126     {
127       for (i = obj_size / sizeof (COPYING_UNIT) - 1;
128 	   i >= 0; i--)
129 	((COPYING_UNIT *)new_chunk->contents)[i]
130 	  = ((COPYING_UNIT *)h->object_base)[i];
131       /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
132 	 but that can cross a page boundary on a machine
133 	 which does not do strict alignment for COPYING_UNITS.  */
134       already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
135     }
136   else
137     already = 0;
138   /* Copy remaining bytes one by one.  */
139   for (i = already; i < obj_size; i++)
140     new_chunk->contents[i] = h->object_base[i];
141 
142   /* If the object just copied was the only data in OLD_CHUNK,
143      free that chunk and remove it from the chain.  */
144   if (h->object_base == old_chunk->contents)
145     {
146       new_chunk->prev = old_chunk->prev;
147       (*h->freefun) (old_chunk);
148     }
149 
150   h->object_base = new_chunk->contents;
151   h->next_free = h->object_base + obj_size;
152 }
153 
154 /* Return nonzero if object OBJ has been allocated from obstack H.
155    This is here for debugging.
156    If you use it in a program, you are probably losing.  */
157 
158 int
_obstack_allocated_p(h,obj)159 _obstack_allocated_p (h, obj)
160      struct obstack *h;
161      POINTER obj;
162 {
163   register struct _obstack_chunk*  lp;	/* below addr of any objects in this chunk */
164   register struct _obstack_chunk*  plp;	/* point to previous chunk if any */
165 
166   lp = (h)->chunk;
167   while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
168     {
169       plp = lp -> prev;
170       lp = plp;
171     }
172   return lp != 0;
173 }
174 
175 /* Free objects in obstack H, including OBJ and everything allocate
176    more recently than OBJ.  If OBJ is zero, free everything in H.  */
177 
178 void
179 #ifdef __STDC__
180 #undef obstack_free
obstack_free(struct obstack * h,POINTER obj)181 obstack_free (struct obstack *h, POINTER obj)
182 #else
183 _obstack_free (h, obj)
184      struct obstack *h;
185      POINTER obj;
186 #endif
187 {
188   register struct _obstack_chunk*  lp;	/* below addr of any objects in this chunk */
189   register struct _obstack_chunk*  plp;	/* point to previous chunk if any */
190 
191   lp = (h)->chunk;
192   /* We use >= because there cannot be an object at the beginning of a chunk.
193      But there can be an empty object at that address
194      at the end of another chunk.  */
195   while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
196     {
197       plp = lp -> prev;
198       (*h->freefun) (lp);
199       lp = plp;
200     }
201   if (lp)
202     {
203       (h)->object_base = (h)->next_free = (char *)(obj);
204       (h)->chunk_limit = lp->limit;
205       (h)->chunk = lp;
206     }
207   else if (obj != 0)
208     /* obj is not in any of the chunks! */
209     abort ();
210 }
211 
212 /* Let same .o link with output of gcc and other compilers.  */
213 
214 #ifdef __STDC__
215 void
_obstack_free(h,obj)216 _obstack_free (h, obj)
217      struct obstack *h;
218      POINTER obj;
219 {
220   obstack_free (h, obj);
221 }
222 #endif
223 
224 #if 0
225 /* These are now turned off because the applications do not use it
226    and it uses bcopy via obstack_grow, which causes trouble on sysV.  */
227 
228 /* Now define the functional versions of the obstack macros.
229    Define them to simply use the corresponding macros to do the job.  */
230 
231 #ifdef __STDC__
232 /* These function definitions do not work with non-ANSI preprocessors;
233    they won't pass through the macro names in parentheses.  */
234 
235 /* The function names appear in parentheses in order to prevent
236    the macro-definitions of the names from being expanded there.  */
237 
238 POINTER (obstack_base) (obstack)
239      struct obstack *obstack;
240 {
241   return obstack_base (obstack);
242 }
243 
244 POINTER (obstack_next_free) (obstack)
245      struct obstack *obstack;
246 {
247   return obstack_next_free (obstack);
248 }
249 
250 int (obstack_object_size) (obstack)
251      struct obstack *obstack;
252 {
253   return obstack_object_size (obstack);
254 }
255 
256 int (obstack_room) (obstack)
257      struct obstack *obstack;
258 {
259   return obstack_room (obstack);
260 }
261 
262 void (obstack_grow) (obstack, pointer, length)
263      struct obstack *obstack;
264      POINTER pointer;
265      int length;
266 {
267   obstack_grow (obstack, pointer, length);
268 }
269 
270 void (obstack_grow0) (obstack, pointer, length)
271      struct obstack *obstack;
272      POINTER pointer;
273      int length;
274 {
275   obstack_grow0 (obstack, pointer, length);
276 }
277 
278 void (obstack_1grow) (obstack, character)
279      struct obstack *obstack;
280      int character;
281 {
282   obstack_1grow (obstack, character);
283 }
284 
285 void (obstack_blank) (obstack, length)
286      struct obstack *obstack;
287      int length;
288 {
289   obstack_blank (obstack, length);
290 }
291 
292 void (obstack_1grow_fast) (obstack, character)
293      struct obstack *obstack;
294      int character;
295 {
296   obstack_1grow_fast (obstack, character);
297 }
298 
299 void (obstack_blank_fast) (obstack, length)
300      struct obstack *obstack;
301      int length;
302 {
303   obstack_blank_fast (obstack, length);
304 }
305 
306 POINTER (obstack_finish) (obstack)
307      struct obstack *obstack;
308 {
309   return obstack_finish (obstack);
310 }
311 
312 POINTER (obstack_alloc) (obstack, length)
313      struct obstack *obstack;
314      int length;
315 {
316   return obstack_alloc (obstack, length);
317 }
318 
319 POINTER (obstack_copy) (obstack, pointer, length)
320      struct obstack *obstack;
321      POINTER pointer;
322      int length;
323 {
324   return obstack_copy (obstack, pointer, length);
325 }
326 
327 POINTER (obstack_copy0) (obstack, pointer, length)
328      struct obstack *obstack;
329      POINTER pointer;
330      int length;
331 {
332   return obstack_copy0 (obstack, pointer, length);
333 }
334 
335 #endif /* __STDC__ */
336 
337 #endif /* 0 */
338