1 /* obstack.c - subroutines used implicitly by object stack macros
2 Copyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 96 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 Library General Public License as published by the
6 Free Software Foundation; either version 2, 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 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18 #include "obstack.h"
19
20 #ifndef __cplusplus
21 #ifdef __STDC__
22 void abort(void);
23 #endif
24 #endif
25
26 /* This is just to get __GNU_LIBRARY__ defined. */
27 #include <stdio.h>
28
29 /* Comment out all this code if we are using the GNU C Library, and are not
30 actually compiling the library itself. This code is part of the GNU C
31 Library, but also included in many other GNU distributions. Compiling
32 and linking in this code is a waste when using the GNU C library
33 (especially if it is a shared library). Rather than having every GNU
34 program understand `configure --with-gnu-libc' and omit the object files,
35 it is simpler to just do this in the source for each such file. */
36
37 /* CYGNUS LOCAL. No, don't comment the code out. We will be using
38 ../include/obstack.h, which was changed relatively recently in a
39 way that is not binary compatible. Until we feel confident that
40 nobody is using the old obstack.c code, force the use of this code.
41 This issue will arise anytime a change is made which is not binary
42 compatible.
43 #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
44 */
45 #if 1
46
47
48 #ifdef __STDC__
49 #define POINTER void *
50 #else
51 #define POINTER char *
52 #endif
53
54 /* Determine default alignment. */
55 struct fooalign {char x; double d;};
56 #define DEFAULT_ALIGNMENT \
57 ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0))
58 /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
59 But in fact it might be less smart and round addresses to as much as
60 DEFAULT_ROUNDING. So we prepare for it to do that. */
61 union fooround {long x; double d;};
62 #define DEFAULT_ROUNDING (sizeof (union fooround))
63
64 /* When we copy a long block of data, this is the unit to do it with.
65 On some machines, copying successive ints does not work;
66 in such a case, redefine COPYING_UNIT to `long' (if that works)
67 or `char' as a last resort. */
68 #ifndef COPYING_UNIT
69 #define COPYING_UNIT int
70 #endif
71
72 /* The non-GNU-C macros copy the obstack into this global variable
73 to avoid multiple evaluation. */
74
75 struct obstack *_obstack;
76
77 /* Define a macro that either calls functions with the traditional malloc/free
78 calling interface, or calls functions with the mmalloc/mfree interface
79 (that adds an extra first argument), based on the state of use_extra_arg.
80 For free, do not use ?:, since some compilers, like the MIPS compilers,
81 do not allow (expr) ? void : void. */
82
83 #define CALL_CHUNKFUN(h, size) \
84 (((h) -> use_extra_arg) \
85 ? (*(h)->chunkfun) (/*(h)->extra_arg,*/ (size)) \
86 : (*(h)->chunkfun) ((size)))
87
88 #define CALL_FREEFUN(h, old_chunk) \
89 do { \
90 if ((h) -> use_extra_arg) \
91 (*(h)->freefun) (/*(h)->extra_arg,*/ (old_chunk)); \
92 else \
93 (*(h)->freefun) ((old_chunk)); \
94 } while (0)
95
96
97 /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
98 Objects start on multiples of ALIGNMENT (0 means use default).
99 CHUNKFUN is the function to use to allocate chunks,
100 and FREEFUN the function to free them.
101
102 Return nonzero if successful, zero if out of memory.
103 To recover from an out of memory error,
104 free up some memory, then call this again. */
105
106 int
_obstack_begin(struct obstack * h,int size,int alignment,POINTER (* chunkfun)(int),void (* freefun)(void *))107 _obstack_begin (struct obstack *h, int size, int alignment, POINTER (*chunkfun) (int), void (*freefun) (void *)/*chunkfun, freefun*/)
108 {
109 register struct _obstack_chunk* chunk; /* points to new chunk */
110
111 if (alignment == 0)
112 alignment = DEFAULT_ALIGNMENT;
113 if (size == 0)
114 /* Default size is what GNU malloc can fit in a 4096-byte block. */
115 {
116 /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
117 Use the values for range checking, because if range checking is off,
118 the extra bytes won't be missed terribly, but if range checking is on
119 and we used a larger request, a whole extra 4096 bytes would be
120 allocated.
121
122 These number are irrelevant to the new GNU malloc. I suspect it is
123 less sensitive to the size of the request. */
124 int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
125 + 4 + DEFAULT_ROUNDING - 1)
126 & ~(DEFAULT_ROUNDING - 1));
127 size = 4096 - extra;
128 }
129
130 h->chunkfun = (struct _obstack_chunk * (*)(int)) chunkfun;
131 h->freefun = freefun;
132 h->chunk_size = size;
133 h->alignment_mask = alignment - 1;
134 h->use_extra_arg = 0;
135
136 chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
137 if (!chunk)
138 {
139 h->alloc_failed = 1;
140 return 0;
141 }
142 h->alloc_failed = 0;
143 h->next_free = h->object_base = chunk->contents;
144 h->chunk_limit = chunk->limit
145 = (char *) chunk + h->chunk_size;
146 chunk->prev = 0;
147 /* The initial chunk now contains no empty object. */
148 h->maybe_empty_object = 0;
149 return 1;
150 }
151
152 int
_obstack_begin_1(struct obstack * h,int size,int alignment,POINTER (* chunkfun)(int),void (* freefun)(void *),POINTER arg)153 _obstack_begin_1 (struct obstack *h, int size, int alignment, POINTER (*chunkfun) (int), void (*freefun) (void *), POINTER arg/*chunkfun, freefun, arg*/)
154 {
155 register struct _obstack_chunk* chunk; /* points to new chunk */
156
157 if (alignment == 0)
158 alignment = DEFAULT_ALIGNMENT;
159 if (size == 0)
160 /* Default size is what GNU malloc can fit in a 4096-byte block. */
161 {
162 /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
163 Use the values for range checking, because if range checking is off,
164 the extra bytes won't be missed terribly, but if range checking is on
165 and we used a larger request, a whole extra 4096 bytes would be
166 allocated.
167
168 These number are irrelevant to the new GNU malloc. I suspect it is
169 less sensitive to the size of the request. */
170 int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
171 + 4 + DEFAULT_ROUNDING - 1)
172 & ~(DEFAULT_ROUNDING - 1));
173 size = 4096 - extra;
174 }
175
176 h->chunkfun = (struct _obstack_chunk * (*)(int)) chunkfun;
177 h->freefun = freefun;
178 h->chunk_size = size;
179 h->alignment_mask = alignment - 1;
180 h->extra_arg = (char *)arg;
181 h->use_extra_arg = 1;
182
183 chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
184 if (!chunk)
185 {
186 h->alloc_failed = 1;
187 return 0;
188 }
189 h->alloc_failed = 0;
190 h->next_free = h->object_base = chunk->contents;
191 h->chunk_limit = chunk->limit
192 = (char *) chunk + h->chunk_size;
193 chunk->prev = 0;
194 /* The initial chunk now contains no empty object. */
195 h->maybe_empty_object = 0;
196 return 1;
197 }
198
199 /* Allocate a new current chunk for the obstack *H
200 on the assumption that LENGTH bytes need to be added
201 to the current object, or a new object of length LENGTH allocated.
202 Copies any partial object from the end of the old chunk
203 to the beginning of the new one. */
204
205 void
_obstack_newchunk(struct obstack * h,int length)206 _obstack_newchunk (struct obstack *h, int length)
207 {
208 register struct _obstack_chunk* old_chunk = h->chunk;
209 register struct _obstack_chunk* new_chunk;
210 register long new_size;
211 register int obj_size = h->next_free - h->object_base;
212 register int i;
213 int already;
214
215 /* Compute size for new chunk. */
216 new_size = (obj_size + length) + (obj_size >> 3) + 100;
217 if (new_size < h->chunk_size)
218 new_size = h->chunk_size;
219
220 /* Allocate and initialize the new chunk. */
221 new_chunk = CALL_CHUNKFUN (h, new_size);
222 if (!new_chunk)
223 {
224 h->alloc_failed = 1;
225 return;
226 }
227 h->alloc_failed = 0;
228 h->chunk = new_chunk;
229 new_chunk->prev = old_chunk;
230 new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
231
232 /* Move the existing object to the new chunk.
233 Word at a time is fast and is safe if the object
234 is sufficiently aligned. */
235 if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
236 {
237 for (i = obj_size / sizeof (COPYING_UNIT) - 1;
238 i >= 0; i--)
239 ((COPYING_UNIT *)new_chunk->contents)[i]
240 = ((COPYING_UNIT *)h->object_base)[i];
241 /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
242 but that can cross a page boundary on a machine
243 which does not do strict alignment for COPYING_UNITS. */
244 already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
245 }
246 else
247 already = 0;
248 /* Copy remaining bytes one by one. */
249 for (i = already; i < obj_size; i++)
250 new_chunk->contents[i] = h->object_base[i];
251
252 /* If the object just copied was the only data in OLD_CHUNK,
253 free that chunk and remove it from the chain.
254 But not if that chunk might contain an empty object. */
255 if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
256 {
257 new_chunk->prev = old_chunk->prev;
258 CALL_FREEFUN (h, old_chunk);
259 }
260
261 h->object_base = new_chunk->contents;
262 h->next_free = h->object_base + obj_size;
263 /* The new chunk certainly contains no empty object yet. */
264 h->maybe_empty_object = 0;
265 }
266
267 /* Return nonzero if object OBJ has been allocated from obstack H.
268 This is here for debugging.
269 If you use it in a program, you are probably losing. */
270
271 #ifdef __STDC__
272 /* Suppress -Wmissing-prototypes warning. We don't want to declare this in
273 obstack.h because it is just for debugging. */
274 int _obstack_allocated_p (struct obstack *h, POINTER obj);
275 #endif
276
277 int
_obstack_allocated_p(struct obstack * h,POINTER obj)278 _obstack_allocated_p (struct obstack *h, POINTER obj)
279 {
280 register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
281 register struct _obstack_chunk* plp; /* point to previous chunk if any */
282
283 lp = (h)->chunk;
284 /* We use >= rather than > since the object cannot be exactly at
285 the beginning of the chunk but might be an empty object exactly
286 at the end of an adjacent chunk. */
287 while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
288 {
289 plp = lp->prev;
290 lp = plp;
291 }
292 return lp != 0;
293 }
294
295 /* Free objects in obstack H, including OBJ and everything allocate
296 more recently than OBJ. If OBJ is zero, free everything in H. */
297
298 #undef obstack_free
299
300 /* This function has two names with identical definitions.
301 This is the first one, called from non-ANSI code. */
302
303 void
_obstack_free(struct obstack * h,POINTER obj)304 _obstack_free (struct obstack *h, POINTER obj)
305 {
306 register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
307 register struct _obstack_chunk* plp; /* point to previous chunk if any */
308
309 lp = h->chunk;
310 /* We use >= because there cannot be an object at the beginning of a chunk.
311 But there can be an empty object at that address
312 at the end of another chunk. */
313 while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
314 {
315 plp = lp->prev;
316 CALL_FREEFUN (h, lp);
317 lp = plp;
318 /* If we switch chunks, we can't tell whether the new current
319 chunk contains an empty object, so assume that it may. */
320 h->maybe_empty_object = 1;
321 }
322 if (lp)
323 {
324 h->object_base = h->next_free = (char *)(obj);
325 h->chunk_limit = lp->limit;
326 h->chunk = lp;
327 }
328 else if (obj != 0)
329 /* obj is not in any of the chunks! */
330 #ifdef __cplusplus
331 throw "snafu";
332 #else
333 abort();
334 #endif
335 }
336
337 /* This function is used from ANSI code. */
338
339 void
obstack_free(struct obstack * h,POINTER obj)340 obstack_free (struct obstack *h, POINTER obj)
341 {
342 register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
343 register struct _obstack_chunk* plp; /* point to previous chunk if any */
344
345 lp = h->chunk;
346 /* We use >= because there cannot be an object at the beginning of a chunk.
347 But there can be an empty object at that address
348 at the end of another chunk. */
349 while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
350 {
351 plp = lp->prev;
352 CALL_FREEFUN (h, lp);
353 lp = plp;
354 /* If we switch chunks, we can't tell whether the new current
355 chunk contains an empty object, so assume that it may. */
356 h->maybe_empty_object = 1;
357 }
358 if (lp)
359 {
360 h->object_base = h->next_free = (char *)(obj);
361 h->chunk_limit = lp->limit;
362 h->chunk = lp;
363 }
364 else if (obj != 0)
365 /* obj is not in any of the chunks! */
366 #ifdef __cplusplus
367 throw "snafu";
368 #else
369 abort();
370 #endif
371 }
372
373 int
_obstack_memory_used(struct obstack * h)374 _obstack_memory_used (struct obstack *h)
375 {
376 register struct _obstack_chunk* lp;
377 register int nbytes = 0;
378
379 for (lp = h->chunk; lp != 0; lp = lp->prev)
380 {
381 nbytes += lp->limit - (char *) lp;
382 }
383 return nbytes;
384 }
385
386 #if 0
387 /* These are now turned off because the applications do not use it
388 and it uses bcopy via obstack_grow, which causes trouble on sysV. */
389
390 /* Now define the functional versions of the obstack macros.
391 Define them to simply use the corresponding macros to do the job. */
392
393 #ifdef __STDC__
394 /* These function definitions do not work with non-ANSI preprocessors;
395 they won't pass through the macro names in parentheses. */
396
397 /* The function names appear in parentheses in order to prevent
398 the macro-definitions of the names from being expanded there. */
399
400 POINTER (obstack_base) (obstack)
401 struct obstack *obstack;
402 {
403 return obstack_base (obstack);
404 }
405
406 POINTER (obstack_next_free) (obstack)
407 struct obstack *obstack;
408 {
409 return obstack_next_free (obstack);
410 }
411
412 int (obstack_object_size) (obstack)
413 struct obstack *obstack;
414 {
415 return obstack_object_size (obstack);
416 }
417
418 int (obstack_room) (obstack)
419 struct obstack *obstack;
420 {
421 return obstack_room (obstack);
422 }
423
424 void (obstack_grow) (obstack, pointer, length)
425 struct obstack *obstack;
426 POINTER pointer;
427 int length;
428 {
429 obstack_grow (obstack, pointer, length);
430 }
431
432 void (obstack_grow0) (obstack, pointer, length)
433 struct obstack *obstack;
434 POINTER pointer;
435 int length;
436 {
437 obstack_grow0 (obstack, pointer, length);
438 }
439
440 void (obstack_1grow) (obstack, character)
441 struct obstack *obstack;
442 int character;
443 {
444 obstack_1grow (obstack, character);
445 }
446
447 void (obstack_blank) (obstack, length)
448 struct obstack *obstack;
449 int length;
450 {
451 obstack_blank (obstack, length);
452 }
453
454 void (obstack_1grow_fast) (obstack, character)
455 struct obstack *obstack;
456 int character;
457 {
458 obstack_1grow_fast (obstack, character);
459 }
460
461 void (obstack_blank_fast) (obstack, length)
462 struct obstack *obstack;
463 int length;
464 {
465 obstack_blank_fast (obstack, length);
466 }
467
468 POINTER (obstack_finish) (obstack)
469 struct obstack *obstack;
470 {
471 return obstack_finish (obstack);
472 }
473
474 POINTER (obstack_alloc) (obstack, length)
475 struct obstack *obstack;
476 int length;
477 {
478 return obstack_alloc (obstack, length);
479 }
480
481 POINTER (obstack_copy) (obstack, pointer, length)
482 struct obstack *obstack;
483 POINTER pointer;
484 int length;
485 {
486 return obstack_copy (obstack, pointer, length);
487 }
488
489 POINTER (obstack_copy0) (obstack, pointer, length)
490 struct obstack *obstack;
491 POINTER pointer;
492 int length;
493 {
494 return obstack_copy0 (obstack, pointer, length);
495 }
496
497 #endif /* __STDC__ */
498
499 #endif /* 0 */
500
501 #endif /* _LIBC or not __GNU_LIBRARY__. */
502