1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #ifdef HAVE_CONFIG_H
23: # include <config.h>
24: #endif
25:
26: #ifdef _LIBC
27: # include <obstack.h>
28: # include <shlib-compat.h>
29: #else
30: # include "obstack.h"
31: #endif
32:
33:
34:
35:
36: #define OBSTACK_INTERFACE_VERSION 1
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47: #include <stdio.h>
48: #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
49: # include <gnu-versions.h>
50: # if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
51: # define ELIDE_CODE
52: # endif
53: #endif
54:
55: #include <stddef.h>
56:
57: #ifndef ELIDE_CODE
58:
59:
60: # if HAVE_INTTYPES_H
61: # include <inttypes.h>
62: # endif
63: # if HAVE_STDINT_H || defined _LIBC
64: # include <stdint.h>
65: # endif
66:
67:
68: union fooround
69: {
70: uintmax_t i;
71: long double d;
72: void *p;
73: };
74: struct fooalign
75: {
76: char c;
77: union fooround u;
78: };
79:
80:
81:
82: enum
83: {
84: DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
85: DEFAULT_ROUNDING = sizeof (union fooround)
86: };
87:
88:
89:
90:
91:
92: # ifndef COPYING_UNIT
93: # define COPYING_UNIT int
94: # endif
95:
96:
97:
98:
99:
100:
101:
102:
103: static void print_and_abort (void);
104: void (*obstack_alloc_failed_handler) (void) = print_and_abort;
105:
106:
107: # include <stdlib.h>
108: # ifdef _LIBC
109: int obstack_exit_failure = EXIT_FAILURE;
110: # else
111: # include "exitfail.h"
112: # define obstack_exit_failure exit_failure
113: # endif
114:
115: # ifdef _LIBC
116: # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
117:
118:
119:
120: struct obstack *_obstack_compat;
121: compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
122: # endif
123: # endif
124:
125:
126:
127:
128:
129:
130:
131: # define CALL_CHUNKFUN(h, size) \
132: (((h) -> use_extra_arg) \
133: ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
134: : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
135:
136: # define CALL_FREEFUN(h, old_chunk) \
137: do { \
138: if ((h) -> use_extra_arg) \
139: (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
140: else \
141: (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
142: } while (0)
143:
144: ^L
145:
146:
147:
148:
149:
150:
151:
152:
153: int
154: _obstack_begin (struct obstack *h,
155: int size, int alignment,
156: void *(*chunkfun) (long),
157: void (*freefun) (void *))
158: {
159: register struct _obstack_chunk *chunk;
160:
161: if (alignment == 0)
162: alignment = DEFAULT_ALIGNMENT;
163: if (size == 0)
164:
165: {
166:
167:
168:
169:
170:
171:
172:
173:
174: int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
175: + 4 + DEFAULT_ROUNDING - 1)
176: & ~(DEFAULT_ROUNDING - 1));
177: size = 4096 - extra;
178: }
179:
180: h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
181: h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
182: h->chunk_size = size;
183: h->alignment_mask = alignment - 1;
184: h->use_extra_arg = 0;
185:
186: chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
187: if (!chunk)
188: (*obstack_alloc_failed_handler) ();
189: h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
190: alignment - 1);
191: h->chunk_limit = chunk->limit
192: = (char *) chunk + h->chunk_size;
193: chunk->prev = 0;
194:
195: h->maybe_empty_object = 0;
196: h->alloc_failed = 0;
197: return 1;
198: }
199:
200: int
201: _obstack_begin_1 (struct obstack *h, int size, int alignment,
202: void *(*chunkfun) (void *, long),
203: void (*freefun) (void *, void *),
204: void *arg)
205: {
206: register struct _obstack_chunk *chunk;
207:
208: if (alignment == 0)
209: alignment = DEFAULT_ALIGNMENT;
210: if (size == 0)
211:
212: {
213:
214:
215:
216:
217:
218:
219:
220:
221: int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
222: + 4 + DEFAULT_ROUNDING - 1)
223: & ~(DEFAULT_ROUNDING - 1));
224: size = 4096 - extra;
225: }
226:
227: h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
228: h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
229: h->chunk_size = size;
230: h->alignment_mask = alignment - 1;
231: h->extra_arg = arg;
232: h->use_extra_arg = 1;
233:
234: chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
235: if (!chunk)
236: (*obstack_alloc_failed_handler) ();
237: h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
238: alignment - 1);
239: h->chunk_limit = chunk->limit
240: = (char *) chunk + h->chunk_size;
241: chunk->prev = 0;
242:
243: h->maybe_empty_object = 0;
244: h->alloc_failed = 0;
245: return 1;
246: }
247:
248:
249:
250:
251:
252:
253:
254: void
255: _obstack_newchunk (struct obstack *h, int length)
256: {
257: register struct _obstack_chunk *old_chunk = h->chunk;
258: register struct _obstack_chunk *new_chunk;
259: register long new_size;
260: register long obj_size = h->next_free - h->object_base;
261: register long i;
262: long already;
263: char *object_base;
264:
265:
266: new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
267: if (new_size < h->chunk_size)
268: new_size = h->chunk_size;
269:
270:
271: new_chunk = CALL_CHUNKFUN (h, new_size);
272: if (!new_chunk)
273: (*obstack_alloc_failed_handler) ();
274: h->chunk = new_chunk;
275: new_chunk->prev = old_chunk;
276: new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
277:
278:
279: object_base =
280: __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
281:
282:
283:
284:
285: if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
286: {
287: for (i = obj_size / sizeof (COPYING_UNIT) - 1;
288: i >= 0; i--)
289: ((COPYING_UNIT *)object_base)[i]
290: = ((COPYING_UNIT *)h->object_base)[i];
291:
292:
293:
294: already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
295: }
296: else
297: already = 0;
298:
299: for (i = already; i < obj_size; i++)
300: object_base[i] = h->object_base[i];
301:
302:
303:
304:
305: if (! h->maybe_empty_object
306: && (h->object_base
307: == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
308: h->alignment_mask)))
309: {
310: new_chunk->prev = old_chunk->prev;
311: CALL_FREEFUN (h, old_chunk);
312: }
313:
314: h->object_base = object_base;
315: h->next_free = h->object_base + obj_size;
316:
317: h->maybe_empty_object = 0;
318: }
319: # ifdef _LIBC
320: libc_hidden_def (_obstack_newchunk)
321: # endif
322:
323:
324:
325:
326:
327:
328:
329: int _obstack_allocated_p (struct obstack *h, void *obj);
330:
331: int
332: _obstack_allocated_p (struct obstack *h, void *obj)
333: {
334: register struct _obstack_chunk *lp;
335: register struct _obstack_chunk *plp;
336:
337: lp = (h)->chunk;
338:
339:
340:
341: while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
342: {
343: plp = lp->prev;
344: lp = plp;
345: }
346: return lp != 0;
347: }
348: ^L
349:
350:
351:
352: # undef obstack_free
353:
354: void
355: obstack_free (struct obstack *h, void *obj)
356: {
357: register struct _obstack_chunk *lp;
358: register struct _obstack_chunk *plp;
359:
360: lp = h->chunk;
361:
362:
363:
364: while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
365: {
366: plp = lp->prev;
367: CALL_FREEFUN (h, lp);
368: lp = plp;
369:
370:
371: h->maybe_empty_object = 1;
372: }
373: if (lp)
374: {
375: h->object_base = h->next_free = (char *) (obj);
376: h->chunk_limit = lp->limit;
377: h->chunk = lp;
378: }
379: else if (obj != 0)
380:
381: abort ();
382: }
383:
384: # ifdef _LIBC
385:
386:
387: strong_alias (obstack_free, _obstack_free)
388: # endif
389: ^L
390: int
391: _obstack_memory_used (struct obstack *h)
392: {
393: register struct _obstack_chunk* lp;
394: register int nbytes = 0;
395:
396: for (lp = h->chunk; lp != 0; lp = lp->prev)
397: {
398: nbytes += lp->limit - (char *) lp;
399: }
400: return nbytes;
401: }
402: ^L
403:
404: # ifdef _LIBC
405: # include <libintl.h>
406: # else
407: # include "gettext.h"
408: # endif
409: # ifndef _
410: # define _(msgid) gettext (msgid)
411: # endif
412:
413: # ifdef _LIBC
414: # include <libio/iolibio.h>
415: # endif
416:
417: # ifndef __attribute__
418:
419: # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
420: # define __attribute__(Spec)
421: # endif
422: # endif
423:
424: static void
425: __attribute__ ((noreturn))
426: print_and_abort (void)
427: {
428:
429:
430:
431:
432:
433: # ifdef _LIBC
434: (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
435: # else
436: fprintf (stderr, "%s\n", _("memory exhausted"));
437: # endif
438: exit (obstack_exit_failure);
439: }
440:
441: #endif