source: branches/libc-0.6/src/emx/include/obstack.h

Last change on this file was 2155, checked in by bird, 20 years ago

Added obstack.h and it's implementation from GLIBC.

  • Property cvs2svn:cvs-rev set to 1.3
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 18.6 KB
Line 
1/* obstack.h - object stack macros
2 Copyright (C) 1988-1994,1996-1999,2003,2004 Free Software Foundation, Inc.
3 This file is part of the GNU C Library. Its master source is NOT part of
4 the C library, however. The master source lives in /gd/gnu/lib.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
20/** @file
21 * GLIBC 2.3.x CVS
22 */
23
24/* Summary:
25
26All the apparent functions defined here are macros. The idea
27is that you would use these pre-tested macros to solve a
28very specific set of problems, and they would run fast.
29Caution: no side-effects in arguments please!! They may be
30evaluated MANY times!!
31
32These macros operate a stack of objects. Each object starts life
33small, and may grow to maturity. (Consider building a word syllable
34by syllable.) An object can move while it is growing. Once it has
35been "finished" it never changes address again. So the "top of the
36stack" is typically an immature growing object, while the rest of the
37stack is of mature, fixed size and fixed address objects.
38
39These routines grab large chunks of memory, using a function you
40supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
41by calling `obstack_chunk_free'. You must define them and declare
42them before using any obstack macros.
43
44Each independent stack is represented by a `struct obstack'.
45Each of the obstack macros expects a pointer to such a structure
46as the first argument.
47
48One motivation for this package is the problem of growing char strings
49in symbol tables. Unless you are "fascist pig with a read-only mind"
50--Gosper's immortal quote from HAKMEM item 154, out of context--you
51would not like to put any arbitrary upper limit on the length of your
52symbols.
53
54In practice this often means you will build many short symbols and a
55few long symbols. At the time you are reading a symbol you don't know
56how long it is. One traditional method is to read a symbol into a
57buffer, realloc()ating the buffer every time you try to read a symbol
58that is longer than the buffer. This is beaut, but you still will
59want to copy the symbol from the buffer to a more permanent
60symbol-table entry say about half the time.
61
62With obstacks, you can work differently. Use one obstack for all symbol
63names. As you read a symbol, grow the name in the obstack gradually.
64When the name is complete, finalize it. Then, if the symbol exists already,
65free the newly read name.
66
67The way we do this is to take a large chunk, allocating memory from
68low addresses. When you want to build a symbol in the chunk you just
69add chars above the current "high water mark" in the chunk. When you
70have finished adding chars, because you got to the end of the symbol,
71you know how long the chars are, and you can create a new object.
72Mostly the chars will not burst over the highest address of the chunk,
73because you would typically expect a chunk to be (say) 100 times as
74long as an average object.
75
76In case that isn't clear, when we have enough chars to make up
77the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
78so we just point to it where it lies. No moving of chars is
79needed and this is the second win: potentially long strings need
80never be explicitly shuffled. Once an object is formed, it does not
81change its address during its lifetime.
82
83When the chars burst over a chunk boundary, we allocate a larger
84chunk, and then copy the partly formed object from the end of the old
85chunk to the beginning of the new larger chunk. We then carry on
86accreting characters to the end of the object as we normally would.
87
88A special macro is provided to add a single char at a time to a
89growing object. This allows the use of register variables, which
90break the ordinary 'growth' macro.
91
92Summary:
93 We allocate large chunks.
94 We carve out one object at a time from the current chunk.
95 Once carved, an object never moves.
96 We are free to append data of any size to the currently
97 growing object.
98 Exactly one object is growing in an obstack at any one time.
99 You can run one obstack per control block.
100 You may have as many control blocks as you dare.
101 Because of the way we do it, you can `unwind' an obstack
102 back to a previous state. (You may remove objects much
103 as you would with a stack.)
104*/
105
106
107/* Don't do the contents of this file more than once. */
108
109#ifndef _OBSTACK_H
110#define _OBSTACK_H 1
111
112#ifdef __cplusplus
113extern "C" {
114#endif
115
116
117/* We use subtraction of (char *) 0 instead of casting to int
118 because on word-addressable machines a simple cast to int
119 may ignore the byte-within-word field of the pointer. */
120
121#ifndef __PTR_TO_INT
122# define __PTR_TO_INT(P) ((P) - (char *) 0)
123#endif
124
125#ifndef __INT_TO_PTR
126# define __INT_TO_PTR(P) ((P) + (char *) 0)
127#endif
128
129/* We need the type of the resulting object. If __PTRDIFF_TYPE__ is
130 defined, as with GNU C, use that; that way we don't pollute the
131 namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h>
132 and use ptrdiff_t. */
133
134#ifdef __PTRDIFF_TYPE__
135# define PTR_INT_TYPE __PTRDIFF_TYPE__
136#else
137# include <stddef.h>
138# define PTR_INT_TYPE ptrdiff_t
139#endif
140
141#include <string.h>
142
143struct _obstack_chunk /* Lives at front of each chunk. */
144{
145 char *limit; /* 1 past end of this chunk */
146 struct _obstack_chunk *prev; /* address of prior chunk or NULL */
147 char contents[4]; /* objects begin here */
148};
149
150struct obstack /* control current object in current chunk */
151{
152 long chunk_size; /* preferred size to allocate chunks in */
153 struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
154 char *object_base; /* address of object we are building */
155 char *next_free; /* where to add next char to current object */
156 char *chunk_limit; /* address of char after current chunk */
157 PTR_INT_TYPE temp; /* Temporary for some macros. */
158 int alignment_mask; /* Mask of alignment for each object. */
159 /* These prototypes vary based on `use_extra_arg', and we use
160 casts to the prototypeless function type in all assignments,
161 but having prototypes here quiets -Wstrict-prototypes. */
162 struct _obstack_chunk *(*chunkfun) (void *, long);
163 void (*freefun) (void *, struct _obstack_chunk *);
164 void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
165 unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */
166 unsigned maybe_empty_object:1;/* There is a possibility that the current
167 chunk contains a zero-length object. This
168 prevents freeing the chunk if we allocate
169 a bigger chunk to replace it. */
170 unsigned alloc_failed:1; /* No longer used, as we now call the failed
171 handler on error, but retained for binary
172 compatibility. */
173};
174
175/* Declare the external functions we use; they are in obstack.c. */
176
177extern void _obstack_newchunk (struct obstack *, int);
178extern int _obstack_begin (struct obstack *, int, int,
179 void *(*) (long), void (*) (void *));
180extern int _obstack_begin_1 (struct obstack *, int, int,
181 void *(*) (void *, long),
182 void (*) (void *, void *), void *);
183extern int _obstack_memory_used (struct obstack *);
184
185void obstack_free (struct obstack *obstack, void *block);
186
187
188
189/* Error handler called when `obstack_chunk_alloc' failed to allocate
190 more memory. This can be set to a user defined function which
191 should either abort gracefully or use longjump - but shouldn't
192 return. The default action is to print a message and abort. */
193extern void (*obstack_alloc_failed_handler) (void);
194
195/* Exit value used when `print_and_abort' is used. */
196extern int obstack_exit_failure;
197
198
199/* Pointer to beginning of object being allocated or to be allocated next.
200 Note that this might not be the final address of the object
201 because a new chunk might be needed to hold the final size. */
202
203#define obstack_base(h) ((void *) (h)->object_base)
204
205/* Size for allocating ordinary chunks. */
206
207#define obstack_chunk_size(h) ((h)->chunk_size)
208
209/* Pointer to next byte not yet allocated in current chunk. */
210
211#define obstack_next_free(h) ((h)->next_free)
212
213/* Mask specifying low bits that should be clear in address of an object. */
214
215#define obstack_alignment_mask(h) ((h)->alignment_mask)
216
217/* To prevent prototype warnings provide complete argument list. */
218#define obstack_init(h) \
219 _obstack_begin ((h), 0, 0, \
220 (void *(*) (long)) obstack_chunk_alloc, \
221 (void (*) (void *)) obstack_chunk_free)
222
223#define obstack_begin(h, size) \
224 _obstack_begin ((h), (size), 0, \
225 (void *(*) (long)) obstack_chunk_alloc, \
226 (void (*) (void *)) obstack_chunk_free)
227
228#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
229 _obstack_begin ((h), (size), (alignment), \
230 (void *(*) (long)) (chunkfun), \
231 (void (*) (void *)) (freefun))
232
233#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
234 _obstack_begin_1 ((h), (size), (alignment), \
235 (void *(*) (void *, long)) (chunkfun), \
236 (void (*) (void *, void *)) (freefun), (arg))
237
238#define obstack_chunkfun(h, newchunkfun) \
239 ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
240
241#define obstack_freefun(h, newfreefun) \
242 ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
243
244#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar))
245
246#define obstack_blank_fast(h,n) ((h)->next_free += (n))
247
248#define obstack_memory_used(h) _obstack_memory_used (h)
249
250
251#if defined __GNUC__ && defined __STDC__ && __STDC__
252/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
253 does not implement __extension__. But that compiler doesn't define
254 __GNUC_MINOR__. */
255# if __GNUC__ < 2 || (defined __NeXT__ && __NeXT__ && !__GNUC_MINOR__)
256# define __extension__
257# endif
258
259/* For GNU C, if not -traditional,
260 we can define these macros to compute all args only once
261 without using a global variable.
262 Also, we can avoid using the `temp' slot, to make faster code. */
263
264# define obstack_object_size(OBSTACK) \
265 __extension__ \
266 ({ struct obstack const *__o = (OBSTACK); \
267 (unsigned) (__o->next_free - __o->object_base); })
268
269# define obstack_room(OBSTACK) \
270 __extension__ \
271 ({ struct obstack const *__o = (OBSTACK); \
272 (unsigned) (__o->chunk_limit - __o->next_free); })
273
274# define obstack_make_room(OBSTACK,length) \
275__extension__ \
276({ struct obstack *__o = (OBSTACK); \
277 int __len = (length); \
278 if (__o->chunk_limit - __o->next_free < __len) \
279 _obstack_newchunk (__o, __len); \
280 (void) 0; })
281
282# define obstack_empty_p(OBSTACK) \
283 __extension__ \
284 ({ struct obstack const *__o = (OBSTACK); \
285 (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); })
286
287# define obstack_grow(OBSTACK,where,length) \
288__extension__ \
289({ struct obstack *__o = (OBSTACK); \
290 int __len = (length); \
291 if (__o->next_free + __len > __o->chunk_limit) \
292 _obstack_newchunk (__o, __len); \
293 memcpy (__o->next_free, where, __len); \
294 __o->next_free += __len; \
295 (void) 0; })
296
297# define obstack_grow0(OBSTACK,where,length) \
298__extension__ \
299({ struct obstack *__o = (OBSTACK); \
300 int __len = (length); \
301 if (__o->next_free + __len + 1 > __o->chunk_limit) \
302 _obstack_newchunk (__o, __len + 1); \
303 memcpy (__o->next_free, where, __len); \
304 __o->next_free += __len; \
305 *(__o->next_free)++ = 0; \
306 (void) 0; })
307
308# define obstack_1grow(OBSTACK,datum) \
309__extension__ \
310({ struct obstack *__o = (OBSTACK); \
311 if (__o->next_free + 1 > __o->chunk_limit) \
312 _obstack_newchunk (__o, 1); \
313 obstack_1grow_fast (__o, datum); \
314 (void) 0; })
315
316/* These assume that the obstack alignment is good enough for pointers
317 or ints, and that the data added so far to the current object
318 shares that much alignment. */
319
320# define obstack_ptr_grow(OBSTACK,datum) \
321__extension__ \
322({ struct obstack *__o = (OBSTACK); \
323 if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
324 _obstack_newchunk (__o, sizeof (void *)); \
325 obstack_ptr_grow_fast (__o, datum); }) \
326
327# define obstack_int_grow(OBSTACK,datum) \
328__extension__ \
329({ struct obstack *__o = (OBSTACK); \
330 if (__o->next_free + sizeof (int) > __o->chunk_limit) \
331 _obstack_newchunk (__o, sizeof (int)); \
332 obstack_int_grow_fast (__o, datum); })
333
334# define obstack_ptr_grow_fast(OBSTACK,aptr) \
335__extension__ \
336({ struct obstack *__o1 = (OBSTACK); \
337 *(const void **) __o1->next_free = (aptr); \
338 __o1->next_free += sizeof (const void *); \
339 (void) 0; })
340
341# define obstack_int_grow_fast(OBSTACK,aint) \
342__extension__ \
343({ struct obstack *__o1 = (OBSTACK); \
344 *(int *) __o1->next_free = (aint); \
345 __o1->next_free += sizeof (int); \
346 (void) 0; })
347
348# define obstack_blank(OBSTACK,length) \
349__extension__ \
350({ struct obstack *__o = (OBSTACK); \
351 int __len = (length); \
352 if (__o->chunk_limit - __o->next_free < __len) \
353 _obstack_newchunk (__o, __len); \
354 obstack_blank_fast (__o, __len); \
355 (void) 0; })
356
357# define obstack_alloc(OBSTACK,length) \
358__extension__ \
359({ struct obstack *__h = (OBSTACK); \
360 obstack_blank (__h, (length)); \
361 obstack_finish (__h); })
362
363# define obstack_copy(OBSTACK,where,length) \
364__extension__ \
365({ struct obstack *__h = (OBSTACK); \
366 obstack_grow (__h, (where), (length)); \
367 obstack_finish (__h); })
368
369# define obstack_copy0(OBSTACK,where,length) \
370__extension__ \
371({ struct obstack *__h = (OBSTACK); \
372 obstack_grow0 (__h, (where), (length)); \
373 obstack_finish (__h); })
374
375/* The local variable is named __o1 to avoid a name conflict
376 when obstack_blank is called. */
377# define obstack_finish(OBSTACK) \
378__extension__ \
379({ struct obstack *__o1 = (OBSTACK); \
380 void *__value = (void *) __o1->object_base; \
381 if (__o1->next_free == __value) \
382 __o1->maybe_empty_object = 1; \
383 __o1->next_free \
384 = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
385 & ~ (__o1->alignment_mask)); \
386 if (__o1->next_free - (char *)__o1->chunk \
387 > __o1->chunk_limit - (char *)__o1->chunk) \
388 __o1->next_free = __o1->chunk_limit; \
389 __o1->object_base = __o1->next_free; \
390 __value; })
391
392# define obstack_free(OBSTACK, OBJ) \
393__extension__ \
394({ struct obstack *__o = (OBSTACK); \
395 void *__obj = (OBJ); \
396 if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
397 __o->next_free = __o->object_base = (char *)__obj; \
398 else (obstack_free) (__o, __obj); })
399
400
401#else /* not __GNUC__ or not __STDC__ */
402
403# define obstack_object_size(h) \
404 (unsigned) ((h)->next_free - (h)->object_base)
405
406# define obstack_room(h) \
407 (unsigned) ((h)->chunk_limit - (h)->next_free)
408
409# define obstack_empty_p(h) \
410 ((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0)
411
412/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
413 so that we can avoid having void expressions
414 in the arms of the conditional expression.
415 Casting the third operand to void was tried before,
416 but some compilers won't accept it. */
417
418# define obstack_make_room(h,length) \
419( (h)->temp = (length), \
420 (((h)->next_free + (h)->temp > (h)->chunk_limit) \
421 ? (_obstack_newchunk ((h), (h)->temp), 0) : 0))
422
423# define obstack_grow(h,where,length) \
424( (h)->temp = (length), \
425 (((h)->next_free + (h)->temp > (h)->chunk_limit) \
426 ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
427 memcpy ((h)->next_free, where, (h)->temp), \
428 (h)->next_free += (h)->temp)
429
430# define obstack_grow0(h,where,length) \
431( (h)->temp = (length), \
432 (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
433 ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \
434 memcpy ((h)->next_free, where, (h)->temp), \
435 (h)->next_free += (h)->temp, \
436 *((h)->next_free)++ = 0)
437
438# define obstack_1grow(h,datum) \
439( (((h)->next_free + 1 > (h)->chunk_limit) \
440 ? (_obstack_newchunk ((h), 1), 0) : 0), \
441 obstack_1grow_fast (h, datum))
442
443# define obstack_ptr_grow(h,datum) \
444( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
445 ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
446 obstack_ptr_grow_fast (h, datum))
447
448# define obstack_int_grow(h,datum) \
449( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
450 ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
451 obstack_int_grow_fast (h, datum))
452
453# define obstack_ptr_grow_fast(h,aptr) \
454 (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
455
456# define obstack_int_grow_fast(h,aint) \
457 (((int *) ((h)->next_free += sizeof (int)))[-1] = (aptr))
458
459# define obstack_blank(h,length) \
460( (h)->temp = (length), \
461 (((h)->chunk_limit - (h)->next_free < (h)->temp) \
462 ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
463 obstack_blank_fast (h, (h)->temp))
464
465# define obstack_alloc(h,length) \
466 (obstack_blank ((h), (length)), obstack_finish ((h)))
467
468# define obstack_copy(h,where,length) \
469 (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
470
471# define obstack_copy0(h,where,length) \
472 (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
473
474# define obstack_finish(h) \
475( ((h)->next_free == (h)->object_base \
476 ? (((h)->maybe_empty_object = 1), 0) \
477 : 0), \
478 (h)->temp = __PTR_TO_INT ((h)->object_base), \
479 (h)->next_free \
480 = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
481 & ~ ((h)->alignment_mask)), \
482 (((h)->next_free - (char *) (h)->chunk \
483 > (h)->chunk_limit - (char *) (h)->chunk) \
484 ? ((h)->next_free = (h)->chunk_limit) : 0), \
485 (h)->object_base = (h)->next_free, \
486 (void *) __INT_TO_PTR ((h)->temp))
487
488# define obstack_free(h,obj) \
489( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
490 (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
491 ? (int) ((h)->next_free = (h)->object_base \
492 = (h)->temp + (char *) (h)->chunk) \
493 : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
494
495#endif /* not __GNUC__ or not __STDC__ */
496
497#ifdef __cplusplus
498} /* C++ */
499#endif
500
501#endif /* obstack.h */
Note: See TracBrowser for help on using the repository browser.