libFirm 1.20
|
00001 /* obstack.h - object stack macros 00002 Copyright (C) 1988-1994,1996-1999,2003,2004,2005 00003 Free Software Foundation, Inc. 00004 This file is part of the GNU C Library. 00005 00006 The GNU C Library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Lesser General Public 00008 License as published by the Free Software Foundation; either 00009 version 2.1 of the License, or (at your option) any later version. 00010 00011 The GNU C Library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public 00017 License along with the GNU C Library; if not, write to the Free 00018 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. */ 00020 00033 /* Summary: 00034 00035 All the apparent functions defined here are macros. The idea 00036 is that you would use these pre-tested macros to solve a 00037 very specific set of problems, and they would run fast. 00038 Caution: no side-effects in arguments please!! They may be 00039 evaluated MANY times!! 00040 00041 These macros operate a stack of objects. Each object starts life 00042 small, and may grow to maturity. (Consider building a word syllable 00043 by syllable.) An object can move while it is growing. Once it has 00044 been "finished" it never changes address again. So the "top of the 00045 stack" is typically an immature growing object, while the rest of the 00046 stack is of mature, fixed size and fixed address objects. 00047 00048 These routines grab large chunks of memory, using a function you 00049 supply, called `obstack_chunk_alloc'. On occasion, they free chunks, 00050 by calling `obstack_chunk_free'. You must define them and declare 00051 them before using any obstack macros. 00052 00053 Each independent stack is represented by a `struct obstack'. 00054 Each of the obstack macros expects a pointer to such a structure 00055 as the first argument. 00056 00057 One motivation for this package is the problem of growing char strings 00058 in symbol tables. Unless you are "fascist pig with a read-only mind" 00059 --Gosper's immortal quote from HAKMEM item 154, out of context--you 00060 would not like to put any arbitrary upper limit on the length of your 00061 symbols. 00062 00063 In practice this often means you will build many short symbols and a 00064 few long symbols. At the time you are reading a symbol you don't know 00065 how long it is. One traditional method is to read a symbol into a 00066 buffer, realloc()ating the buffer every time you try to read a symbol 00067 that is longer than the buffer. This is beaut, but you still will 00068 want to copy the symbol from the buffer to a more permanent 00069 symbol-table entry say about half the time. 00070 00071 With obstacks, you can work differently. Use one obstack for all symbol 00072 names. As you read a symbol, grow the name in the obstack gradually. 00073 When the name is complete, finalize it. Then, if the symbol exists already, 00074 free the newly read name. 00075 00076 The way we do this is to take a large chunk, allocating memory from 00077 low addresses. When you want to build a symbol in the chunk you just 00078 add chars above the current "high water mark" in the chunk. When you 00079 have finished adding chars, because you got to the end of the symbol, 00080 you know how long the chars are, and you can create a new object. 00081 Mostly the chars will not burst over the highest address of the chunk, 00082 because you would typically expect a chunk to be (say) 100 times as 00083 long as an average object. 00084 00085 In case that isn't clear, when we have enough chars to make up 00086 the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) 00087 so we just point to it where it lies. No moving of chars is 00088 needed and this is the second win: potentially long strings need 00089 never be explicitly shuffled. Once an object is formed, it does not 00090 change its address during its lifetime. 00091 00092 When the chars burst over a chunk boundary, we allocate a larger 00093 chunk, and then copy the partly formed object from the end of the old 00094 chunk to the beginning of the new larger chunk. We then carry on 00095 accreting characters to the end of the object as we normally would. 00096 00097 A special macro is provided to add a single char at a time to a 00098 growing object. This allows the use of register variables, which 00099 break the ordinary 'growth' macro. 00100 00101 Summary: 00102 We allocate large chunks. 00103 We carve out one object at a time from the current chunk. 00104 Once carved, an object never moves. 00105 We are free to append data of any size to the currently 00106 growing object. 00107 Exactly one object is growing in an obstack at any one time. 00108 You can run one obstack per control block. 00109 You may have as many control blocks as you dare. 00110 Because of the way we do it, you can `unwind' an obstack 00111 back to a previous state. (You may remove objects much 00112 as you would with a stack.) 00113 */ 00114 00115 00116 /* Don't do the contents of this file more than once. */ 00117 00118 #ifndef _OBSTACK_H 00119 #define _OBSTACK_H 1 00120 00121 #include "../begin.h" 00122 00125 /* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is 00126 defined, as with GNU C, use that; that way we don't pollute the 00127 namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h> 00128 and use ptrdiff_t. */ 00129 00130 #ifdef __PTRDIFF_TYPE__ 00131 # define PTR_INT_TYPE __PTRDIFF_TYPE__ 00132 #else 00133 # include <stddef.h> 00134 # define PTR_INT_TYPE ptrdiff_t 00135 #endif 00136 00137 /* If B is the base of an object addressed by P, return the result of 00138 aligning P to the next multiple of A + 1. B and P must be of type 00139 char *. A + 1 must be a power of 2. */ 00140 00141 #define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) 00142 00143 /* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case 00144 where pointers can be converted to integers, aligned as integers, 00145 and converted back again. If PTR_INT_TYPE is narrower than a 00146 pointer (e.g., the AS/400), play it safe and compute the alignment 00147 relative to B. Otherwise, use the faster strategy of computing the 00148 alignment relative to 0. */ 00149 00150 #define __PTR_ALIGN(B, P, A) \ 00151 __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \ 00152 P, A) 00153 00154 #include <string.h> 00155 #include <stdarg.h> 00156 00157 struct _obstack_chunk /* Lives at front of each chunk. */ 00158 { 00159 char *limit; /* 1 past end of this chunk */ 00160 struct _obstack_chunk *prev; /* address of prior chunk or NULL */ 00161 char contents[4]; /* objects begin here */ 00162 }; 00163 00164 struct obstack /* control current object in current chunk */ 00165 { 00166 PTR_INT_TYPE chunk_size; /* preferred size to allocate chunks in */ 00167 struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ 00168 char *object_base; /* address of object we are building */ 00169 char *next_free; /* where to add next char to current object */ 00170 char *chunk_limit; /* address of char after current chunk */ 00171 union 00172 { 00173 PTR_INT_TYPE tempint; 00174 void *tempptr; 00175 } temp; /* Temporary for some macros. */ 00176 int alignment_mask; /* Mask of alignment for each object. */ 00177 /* These prototypes vary based on `use_extra_arg', and we use 00178 casts to the prototypeless function type in all assignments, 00179 but having prototypes here quiets -Wstrict-prototypes. */ 00180 struct _obstack_chunk *(*chunkfun) (void *, PTR_INT_TYPE); 00181 void (*freefun) (void *, struct _obstack_chunk *); 00182 void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ 00183 unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ 00184 unsigned maybe_empty_object:1;/* There is a possibility that the current 00185 chunk contains a zero-length object. This 00186 prevents freeing the chunk if we allocate 00187 a bigger chunk to replace it. */ 00188 unsigned alloc_failed:1; /* No longer used, as we now call the failed 00189 handler on error, but retained for binary 00190 compatibility. */ 00191 }; 00192 00193 /* Declare the external functions we use; they are in obstack.c. */ 00194 00195 FIRM_API void _obstack_newchunk (struct obstack *, PTR_INT_TYPE); 00196 FIRM_API int _obstack_begin (struct obstack *, int, int, 00197 void *(*) (PTR_INT_TYPE), void (*) (void *)); 00198 FIRM_API int _obstack_begin_1 (struct obstack *, int, int, 00199 void *(*) (void *, PTR_INT_TYPE), 00200 void (*) (void *, void *), void *); 00201 FIRM_API PTR_INT_TYPE _obstack_memory_used (struct obstack *); 00202 00203 FIRM_API void obstack_free (struct obstack *obstack, void *block); 00204 00205 00206 /* Error handler called when `obstack_chunk_alloc' failed to allocate 00207 more memory. This can be set to a user defined function which 00208 should either abort gracefully or use longjump - but shouldn't 00209 return. The default action is to print a message and abort. */ 00210 FIRM_API void (*obstack_alloc_failed_handler) (void); 00211 00212 /* Exit value used when `print_and_abort' is used. */ 00213 FIRM_API int obstack_exit_failure; 00214 00215 /* Pointer to beginning of object being allocated or to be allocated next. 00216 Note that this might not be the final address of the object 00217 because a new chunk might be needed to hold the final size. */ 00218 00219 #define obstack_base(h) ((void *) (h)->object_base) 00220 00221 /* Size for allocating ordinary chunks. */ 00222 00223 #define obstack_chunk_size(h) ((h)->chunk_size) 00224 00225 /* Pointer to next byte not yet allocated in current chunk. */ 00226 00227 #define obstack_next_free(h) ((h)->next_free) 00228 00229 /* Mask specifying low bits that should be clear in address of an object. */ 00230 00231 #define obstack_alignment_mask(h) ((h)->alignment_mask) 00232 00233 /* To prevent prototype warnings provide complete argument list. */ 00234 #define obstack_init(h) \ 00235 _obstack_begin ((h), 0, 0, \ 00236 (void *(*) (PTR_INT_TYPE)) obstack_chunk_alloc, \ 00237 (void (*) (void *)) obstack_chunk_free) 00238 00239 #define obstack_begin(h, size) \ 00240 _obstack_begin ((h), (size), 0, \ 00241 (void *(*) (PTR_INT_TYPE)) obstack_chunk_alloc, \ 00242 (void (*) (void *)) obstack_chunk_free) 00243 00244 #define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ 00245 _obstack_begin ((h), (size), (alignment), \ 00246 (void *(*) (PTR_INT_TYPE)) (chunkfun), \ 00247 (void (*) (void *)) (freefun)) 00248 00249 #define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ 00250 _obstack_begin_1 ((h), (size), (alignment), \ 00251 (void *(*) (void *, PTR_INT_TYPE)) (chunkfun), \ 00252 (void (*) (void *, void *)) (freefun), (arg)) 00253 00254 #define obstack_chunkfun(h, newchunkfun) \ 00255 ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, PTR_INT_TYPE)) (newchunkfun)) 00256 00257 #define obstack_freefun(h, newfreefun) \ 00258 ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun)) 00259 00260 #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar)) 00261 00262 #define obstack_blank_fast(h,n) ((h)->next_free += (n)) 00263 00264 #define obstack_memory_used(h) _obstack_memory_used (h) 00265 00266 #if defined __GNUC__ && defined __STDC__ && __STDC__ 00267 /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and 00268 does not implement __extension__. But that compiler doesn't define 00269 __GNUC_MINOR__. */ 00270 # if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) 00271 # define __extension__ 00272 # endif 00273 00274 /* For GNU C, if not -traditional, 00275 we can define these macros to compute all args only once 00276 without using a global variable. 00277 Also, we can avoid using the `temp' slot, to make faster code. */ 00278 00279 # define obstack_object_size(OBSTACK) \ 00280 __extension__ \ 00281 ({ struct obstack const *__o = (OBSTACK); \ 00282 (unsigned) (__o->next_free - __o->object_base); }) 00283 00284 # define obstack_room(OBSTACK) \ 00285 __extension__ \ 00286 ({ struct obstack const *__o = (OBSTACK); \ 00287 (unsigned) (__o->chunk_limit - __o->next_free); }) 00288 00289 # define obstack_make_room(OBSTACK,length) \ 00290 __extension__ \ 00291 ({ struct obstack *__o = (OBSTACK); \ 00292 int __len = (length); \ 00293 if (__o->chunk_limit - __o->next_free < __len) \ 00294 _obstack_newchunk (__o, __len); \ 00295 (void) 0; }) 00296 00297 # define obstack_empty_p(OBSTACK) \ 00298 __extension__ \ 00299 ({ struct obstack const *__o = (OBSTACK); \ 00300 (__o->chunk->prev == 0 \ 00301 && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \ 00302 __o->chunk->contents, \ 00303 __o->alignment_mask)); }) 00304 00305 # define obstack_grow(OBSTACK,where,length) \ 00306 __extension__ \ 00307 ({ struct obstack *__o = (OBSTACK); \ 00308 int __len = (length); \ 00309 if (__o->next_free + __len > __o->chunk_limit) \ 00310 _obstack_newchunk (__o, __len); \ 00311 memcpy (__o->next_free, where, __len); \ 00312 __o->next_free += __len; \ 00313 (void) 0; }) 00314 00315 # define obstack_grow0(OBSTACK,where,length) \ 00316 __extension__ \ 00317 ({ struct obstack *__o = (OBSTACK); \ 00318 int __len = (length); \ 00319 if (__o->next_free + __len + 1 > __o->chunk_limit) \ 00320 _obstack_newchunk (__o, __len + 1); \ 00321 memcpy (__o->next_free, where, __len); \ 00322 __o->next_free += __len; \ 00323 *(__o->next_free)++ = 0; \ 00324 (void) 0; }) 00325 00326 # define obstack_1grow(OBSTACK,datum) \ 00327 __extension__ \ 00328 ({ struct obstack *__o = (OBSTACK); \ 00329 if (__o->next_free + 1 > __o->chunk_limit) \ 00330 _obstack_newchunk (__o, 1); \ 00331 obstack_1grow_fast (__o, datum); \ 00332 (void) 0; }) 00333 00334 /* These assume that the obstack alignment is good enough for pointers 00335 or ints, and that the data added so far to the current object 00336 shares that much alignment. */ 00337 00338 # define obstack_ptr_grow(OBSTACK,datum) \ 00339 __extension__ \ 00340 ({ struct obstack *__o = (OBSTACK); \ 00341 if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ 00342 _obstack_newchunk (__o, sizeof (void *)); \ 00343 obstack_ptr_grow_fast (__o, datum); }) \ 00344 00345 # define obstack_int_grow(OBSTACK,datum) \ 00346 __extension__ \ 00347 ({ struct obstack *__o = (OBSTACK); \ 00348 if (__o->next_free + sizeof (int) > __o->chunk_limit) \ 00349 _obstack_newchunk (__o, sizeof (int)); \ 00350 obstack_int_grow_fast (__o, datum); }) 00351 00352 # define obstack_ptr_grow_fast(OBSTACK,aptr) \ 00353 __extension__ \ 00354 ({ struct obstack *__o1 = (OBSTACK); \ 00355 *(const void **) __o1->next_free = (aptr); \ 00356 __o1->next_free += sizeof (const void *); \ 00357 (void) 0; }) 00358 00359 # define obstack_int_grow_fast(OBSTACK,aint) \ 00360 __extension__ \ 00361 ({ struct obstack *__o1 = (OBSTACK); \ 00362 *(int *) __o1->next_free = (aint); \ 00363 __o1->next_free += sizeof (int); \ 00364 (void) 0; }) 00365 00366 # define obstack_blank(OBSTACK,length) \ 00367 __extension__ \ 00368 ({ struct obstack *__o = (OBSTACK); \ 00369 int __len = (length); \ 00370 if (__o->chunk_limit - __o->next_free < __len) \ 00371 _obstack_newchunk (__o, __len); \ 00372 obstack_blank_fast (__o, __len); \ 00373 (void) 0; }) 00374 00375 # define obstack_alloc(OBSTACK,length) \ 00376 __extension__ \ 00377 ({ struct obstack *__h = (OBSTACK); \ 00378 obstack_blank (__h, (length)); \ 00379 obstack_finish (__h); }) 00380 00381 # define obstack_copy(OBSTACK,where,length) \ 00382 __extension__ \ 00383 ({ struct obstack *__h = (OBSTACK); \ 00384 obstack_grow (__h, (where), (length)); \ 00385 obstack_finish (__h); }) 00386 00387 # define obstack_copy0(OBSTACK,where,length) \ 00388 __extension__ \ 00389 ({ struct obstack *__h = (OBSTACK); \ 00390 obstack_grow0 (__h, (where), (length)); \ 00391 obstack_finish (__h); }) 00392 00393 /* The local variable is named __o1 to avoid a name conflict 00394 when obstack_blank is called. */ 00395 # define obstack_finish(OBSTACK) \ 00396 __extension__ \ 00397 ({ struct obstack *__o1 = (OBSTACK); \ 00398 void *__value = (void *) __o1->object_base; \ 00399 if (__o1->next_free == __value) \ 00400 __o1->maybe_empty_object = 1; \ 00401 __o1->next_free \ 00402 = __PTR_ALIGN (__o1->object_base, __o1->next_free, \ 00403 __o1->alignment_mask); \ 00404 if (__o1->next_free - (char *)__o1->chunk \ 00405 > __o1->chunk_limit - (char *)__o1->chunk) \ 00406 __o1->next_free = __o1->chunk_limit; \ 00407 __o1->object_base = __o1->next_free; \ 00408 __value; }) 00409 00410 # define obstack_free(OBSTACK, OBJ) \ 00411 __extension__ \ 00412 ({ struct obstack *__o = (OBSTACK); \ 00413 void *__obj = (OBJ); \ 00414 if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ 00415 __o->next_free = __o->object_base = (char *)__obj; \ 00416 else (obstack_free) (__o, __obj); }) 00417 00418 #else /* not __GNUC__ or not __STDC__ */ 00419 00420 # define obstack_object_size(h) \ 00421 (unsigned) ((h)->next_free - (h)->object_base) 00422 00423 # define obstack_room(h) \ 00424 (unsigned) ((h)->chunk_limit - (h)->next_free) 00425 00426 # define obstack_empty_p(h) \ 00427 ((h)->chunk->prev == 0 \ 00428 && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \ 00429 (h)->chunk->contents, \ 00430 (h)->alignment_mask)) 00431 00432 /* Note that the call to _obstack_newchunk is enclosed in (..., 0) 00433 so that we can avoid having void expressions 00434 in the arms of the conditional expression. 00435 Casting the third operand to void was tried before, 00436 but some compilers won't accept it. */ 00437 00438 # define obstack_make_room(h,length) \ 00439 ( (h)->temp.tempint = (length), \ 00440 (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ 00441 ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0)) 00442 00443 # define obstack_grow(h,where,length) \ 00444 ( (h)->temp.tempint = (length), \ 00445 (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ 00446 ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ 00447 memcpy ((h)->next_free, where, (h)->temp.tempint), \ 00448 (h)->next_free += (h)->temp.tempint) 00449 00450 # define obstack_grow0(h,where,length) \ 00451 ( (h)->temp.tempint = (length), \ 00452 (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \ 00453 ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \ 00454 memcpy ((h)->next_free, where, (h)->temp.tempint), \ 00455 (h)->next_free += (h)->temp.tempint, \ 00456 *((h)->next_free)++ = 0) 00457 00458 # define obstack_1grow(h,datum) \ 00459 ( (((h)->next_free + 1 > (h)->chunk_limit) \ 00460 ? (_obstack_newchunk ((h), 1), 0) : 0), \ 00461 obstack_1grow_fast (h, datum)) 00462 00463 # define obstack_ptr_grow(h,datum) \ 00464 ( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ 00465 ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ 00466 obstack_ptr_grow_fast (h, datum)) 00467 00468 # define obstack_int_grow(h,datum) \ 00469 ( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ 00470 ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ 00471 obstack_int_grow_fast (h, datum)) 00472 00473 # define obstack_ptr_grow_fast(h,aptr) \ 00474 (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr)) 00475 00476 # define obstack_int_grow_fast(h,aint) \ 00477 (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint)) 00478 00479 # define obstack_blank(h,length) \ 00480 ( (h)->temp.tempint = (length), \ 00481 (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \ 00482 ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ 00483 obstack_blank_fast (h, (h)->temp.tempint)) 00484 00485 # define obstack_alloc(h,length) \ 00486 (obstack_blank ((h), (length)), obstack_finish ((h))) 00487 00488 # define obstack_copy(h,where,length) \ 00489 (obstack_grow ((h), (where), (length)), obstack_finish ((h))) 00490 00491 # define obstack_copy0(h,where,length) \ 00492 (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) 00493 00494 # define obstack_finish(h) \ 00495 ( ((h)->next_free == (h)->object_base \ 00496 ? (((h)->maybe_empty_object = 1), 0) \ 00497 : 0), \ 00498 (h)->temp.tempptr = (h)->object_base, \ 00499 (h)->next_free \ 00500 = __PTR_ALIGN ((h)->object_base, (h)->next_free, \ 00501 (h)->alignment_mask), \ 00502 (((h)->next_free - (char *) (h)->chunk \ 00503 > (h)->chunk_limit - (char *) (h)->chunk) \ 00504 ? ((h)->next_free = (h)->chunk_limit) : 0), \ 00505 (h)->object_base = (h)->next_free, \ 00506 (h)->temp.tempptr) 00507 00508 # define obstack_free(h,obj) \ 00509 ( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \ 00510 ((((h)->temp.tempint > 0 \ 00511 && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \ 00512 ? (PTR_INT_TYPE) ((h)->next_free = (h)->object_base \ 00513 = (h)->temp.tempint + (char *) (h)->chunk) \ 00514 : (((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0))) 00515 00516 #endif /* not __GNUC__ or not __STDC__ */ 00517 00522 #ifdef __cplusplus 00523 # define FIRM_NOTHROW throw () 00524 #else 00525 # define FIRM_NOTHROW 00526 #endif 00527 00533 #if defined(__GNUC__) 00534 # define FIRM_PRINTF(a,b) __attribute__((__format__(__printf__, a, b))) 00535 #else 00536 # define FIRM_PRINTF(a,b) 00537 #endif 00538 00542 FIRM_API int obstack_printf(struct obstack *obst, const char *fmt, ...) 00543 FIRM_NOTHROW FIRM_PRINTF(2, 3); 00544 FIRM_API int obstack_vprintf(struct obstack *obst, const char *fmt, va_list ap) 00545 FIRM_NOTHROW FIRM_PRINTF(2, 0); 00546 00549 #include "../end.h" 00550 00551 #endif