|
|
1.1 ! root 1: /* obstack.h - 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 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 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: /* Summary: ! 19: ! 20: All the apparent functions defined here are macros. The idea ! 21: is that you would use these pre-tested macros to solve a ! 22: very specific set of problems, and they would run fast. ! 23: Caution: no side-effects in arguments please!! They may be ! 24: evaluated MANY times!! ! 25: ! 26: These macros operate a stack of objects. Each object starts life ! 27: small, and may grow to maturity. (Consider building a word syllable ! 28: by syllable.) An object can move while it is growing. Once it has ! 29: been "finished" it never changes address again. So the "top of the ! 30: stack" is typically an immature growing object, while the rest of the ! 31: stack is of mature, fixed size and fixed address objects. ! 32: ! 33: These routines grab large chunks of memory, using a function you ! 34: supply, called `obstack_chunk_alloc'. On occasion, they free chunks, ! 35: by calling `obstack_chunk_free'. You must define them and declare ! 36: them before using any obstack macros. ! 37: ! 38: Each independent stack is represented by a `struct obstack'. ! 39: Each of the obstack macros expects a pointer to such a structure ! 40: as the first argument. ! 41: ! 42: One motivation for this package is the problem of growing char strings ! 43: in symbol tables. Unless you are "fascist pig with a read-only mind" ! 44: [Gosper's immortal quote from HAKMEM item 154, out of context] you ! 45: would not like to put any arbitrary upper limit on the length of your ! 46: symbols. ! 47: ! 48: In practice this often means you will build many short symbols and a ! 49: few long symbols. At the time you are reading a symbol you don't know ! 50: how long it is. One traditional method is to read a symbol into a ! 51: buffer, realloc()ating the buffer every time you try to read a symbol ! 52: that is longer than the buffer. This is beaut, but you still will ! 53: want to copy the symbol from the buffer to a more permanent ! 54: symbol-table entry say about half the time. ! 55: ! 56: With obstacks, you can work differently. Use one obstack for all symbol ! 57: names. As you read a symbol, grow the name in the obstack gradually. ! 58: When the name is complete, finalize it. Then, if the symbol exists already, ! 59: free the newly read name. ! 60: ! 61: The way we do this is to take a large chunk, allocating memory from ! 62: low addresses. When you want to build a symbol in the chunk you just ! 63: add chars above the current "high water mark" in the chunk. When you ! 64: have finished adding chars, because you got to the end of the symbol, ! 65: you know how long the chars are, and you can create a new object. ! 66: Mostly the chars will not burst over the highest address of the chunk, ! 67: because you would typically expect a chunk to be (say) 100 times as ! 68: long as an average object. ! 69: ! 70: In case that isn't clear, when we have enough chars to make up ! 71: the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) ! 72: so we just point to it where it lies. No moving of chars is ! 73: needed and this is the second win: potentially long strings need ! 74: never be explicitly shuffled. Once an object is formed, it does not ! 75: change its address during its lifetime. ! 76: ! 77: When the chars burst over a chunk boundary, we allocate a larger ! 78: chunk, and then copy the partly formed object from the end of the old ! 79: chunk to the beginning of the new larger chunk. We then carry on ! 80: accreting characters to the end of the object as we normally would. ! 81: ! 82: A special macro is provided to add a single char at a time to a ! 83: growing object. This allows the use of register variables, which ! 84: break the ordinary 'growth' macro. ! 85: ! 86: Summary: ! 87: We allocate large chunks. ! 88: We carve out one object at a time from the current chunk. ! 89: Once carved, an object never moves. ! 90: We are free to append data of any size to the currently ! 91: growing object. ! 92: Exactly one object is growing in an obstack at any one time. ! 93: You can run one obstack per control block. ! 94: You may have as many control blocks as you dare. ! 95: Because of the way we do it, you can `unwind' a obstack ! 96: back to a previous state. (You may remove objects much ! 97: as you would with a stack.) ! 98: */ ! 99: ! 100: ! 101: /* Don't do the contents of this file more than once. */ ! 102: ! 103: #ifndef __OBSTACKS__ ! 104: #define __OBSTACKS__ ! 105: ! 106: /* We use subtraction of (char *)0 instead of casting to int ! 107: because on word-addressable machines a simple cast to int ! 108: may ignore the byte-within-word field of the pointer. */ ! 109: ! 110: #ifndef __PTR_TO_INT ! 111: #define __PTR_TO_INT(P) ((P) - (char *)0) ! 112: #endif ! 113: ! 114: #ifndef __INT_TO_PTR ! 115: #define __INT_TO_PTR(P) ((P) + (char *)0) ! 116: #endif ! 117: ! 118: struct _obstack_chunk /* Lives at front of each chunk. */ ! 119: { ! 120: char *limit; /* 1 past end of this chunk */ ! 121: struct _obstack_chunk *prev; /* address of prior chunk or NULL */ ! 122: char contents[4]; /* objects begin here */ ! 123: }; ! 124: ! 125: struct obstack /* control current object in current chunk */ ! 126: { ! 127: long chunk_size; /* preferred size to allocate chunks in */ ! 128: struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */ ! 129: char *object_base; /* address of object we are building */ ! 130: char *next_free; /* where to add next char to current object */ ! 131: char *chunk_limit; /* address of char after current chunk */ ! 132: int temp; /* Temporary for some macros. */ ! 133: int alignment_mask; /* Mask of alignment for each object. */ ! 134: struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ ! 135: void (*freefun) (); /* User's function to free a chunk. */ ! 136: /* Nonzero means there is a possibility the current chunk contains ! 137: a zero-length object. This prevents freeing the chunk ! 138: if we allocate a bigger chunk to replace it. */ ! 139: char maybe_empty_object; ! 140: }; ! 141: ! 142: /* Declare the external functions we use; they are in obstack.c. */ ! 143: ! 144: #ifdef __STDC__ ! 145: extern void _obstack_newchunk (struct obstack *, int); ! 146: extern void _obstack_free (struct obstack *, void *); ! 147: extern void _obstack_begin (struct obstack *, int, int, ! 148: void *(*) (), void (*) ()); ! 149: #else ! 150: extern void _obstack_newchunk (); ! 151: extern void _obstack_free (); ! 152: extern void _obstack_begin (); ! 153: #endif ! 154: ! 155: #ifdef __STDC__ ! 156: ! 157: /* Do the function-declarations after the structs ! 158: but before defining the macros. */ ! 159: ! 160: void obstack_init (struct obstack *obstack); ! 161: ! 162: void * obstack_alloc (struct obstack *obstack, int size); ! 163: ! 164: void * obstack_copy (struct obstack *obstack, void *address, int size); ! 165: void * obstack_copy0 (struct obstack *obstack, void *address, int size); ! 166: ! 167: void obstack_free (struct obstack *obstack, void *block); ! 168: ! 169: void obstack_blank (struct obstack *obstack, int size); ! 170: ! 171: void obstack_grow (struct obstack *obstack, void *data, int size); ! 172: void obstack_grow0 (struct obstack *obstack, void *data, int size); ! 173: ! 174: void obstack_1grow (struct obstack *obstack, int data_char); ! 175: void obstack_ptr_grow (struct obstack *obstack, void *data); ! 176: void obstack_int_grow (struct obstack *obstack, int data); ! 177: ! 178: void * obstack_finish (struct obstack *obstack); ! 179: ! 180: int obstack_object_size (struct obstack *obstack); ! 181: ! 182: int obstack_room (struct obstack *obstack); ! 183: void obstack_1grow_fast (struct obstack *obstack, int data_char); ! 184: void obstack_ptr_grow_fast (struct obstack *obstack, void *data); ! 185: void obstack_int_grow_fast (struct obstack *obstack, int data); ! 186: void obstack_blank_fast (struct obstack *obstack, int size); ! 187: ! 188: void * obstack_base (struct obstack *obstack); ! 189: void * obstack_next_free (struct obstack *obstack); ! 190: int obstack_alignment_mask (struct obstack *obstack); ! 191: int obstack_chunk_size (struct obstack *obstack); ! 192: ! 193: #endif /* __STDC__ */ ! 194: ! 195: /* Non-ANSI C cannot really support alternative functions for these macros, ! 196: so we do not declare them. */ ! 197: ! 198: /* Pointer to beginning of object being allocated or to be allocated next. ! 199: Note that this might not be the final address of the object ! 200: because a new chunk might be needed to hold the final size. */ ! 201: ! 202: #define obstack_base(h) ((h)->object_base) ! 203: ! 204: /* Size for allocating ordinary chunks. */ ! 205: ! 206: #define obstack_chunk_size(h) ((h)->chunk_size) ! 207: ! 208: /* Pointer to next byte not yet allocated in current chunk. */ ! 209: ! 210: #define obstack_next_free(h) ((h)->next_free) ! 211: ! 212: /* Mask specifying low bits that should be clear in address of an object. */ ! 213: ! 214: #define obstack_alignment_mask(h) ((h)->alignment_mask) ! 215: ! 216: #define obstack_init(h) \ ! 217: _obstack_begin ((h), 0, 0, \ ! 218: (void *(*) ()) obstack_chunk_alloc, obstack_chunk_free) ! 219: ! 220: #define obstack_begin(h, size) \ ! 221: _obstack_begin ((h), (size), 0, \ ! 222: (void *(*) ()) obstack_chunk_alloc, obstack_chunk_free) ! 223: ! 224: #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar) ! 225: ! 226: #define obstack_blank_fast(h,n) ((h)->next_free += (n)) ! 227: ! 228: #if defined (__GNUC__) && defined (__STDC__) ! 229: #if __GNUC__ < 2 ! 230: #define __extension__ ! 231: #endif ! 232: ! 233: /* For GNU C, if not -traditional, ! 234: we can define these macros to compute all args only once ! 235: without using a global variable. ! 236: Also, we can avoid using the `temp' slot, to make faster code. */ ! 237: ! 238: #define obstack_object_size(OBSTACK) \ ! 239: __extension__ \ ! 240: ({ struct obstack *__o = (OBSTACK); \ ! 241: (unsigned) (__o->next_free - __o->object_base); }) ! 242: ! 243: #define obstack_room(OBSTACK) \ ! 244: __extension__ \ ! 245: ({ struct obstack *__o = (OBSTACK); \ ! 246: (unsigned) (__o->chunk_limit - __o->next_free); }) ! 247: ! 248: /* Note that the call to _obstack_newchunk is enclosed in (..., 0) ! 249: so that we can avoid having void expressions ! 250: in the arms of the conditional expression. ! 251: Casting the third operand to void was tried before, ! 252: but some compilers won't accept it. */ ! 253: #define obstack_grow(OBSTACK,where,length) \ ! 254: __extension__ \ ! 255: ({ struct obstack *__o = (OBSTACK); \ ! 256: int __len = (length); \ ! 257: ((__o->next_free + __len > __o->chunk_limit) \ ! 258: ? (_obstack_newchunk (__o, __len), 0) : 0); \ ! 259: bcopy (where, __o->next_free, __len); \ ! 260: __o->next_free += __len; \ ! 261: (void) 0; }) ! 262: ! 263: #define obstack_grow0(OBSTACK,where,length) \ ! 264: __extension__ \ ! 265: ({ struct obstack *__o = (OBSTACK); \ ! 266: int __len = (length); \ ! 267: ((__o->next_free + __len + 1 > __o->chunk_limit) \ ! 268: ? (_obstack_newchunk (__o, __len + 1), 0) : 0), \ ! 269: bcopy (where, __o->next_free, __len), \ ! 270: __o->next_free += __len, \ ! 271: *(__o->next_free)++ = 0; \ ! 272: (void) 0; }) ! 273: ! 274: #define obstack_1grow(OBSTACK,datum) \ ! 275: __extension__ \ ! 276: ({ struct obstack *__o = (OBSTACK); \ ! 277: ((__o->next_free + 1 > __o->chunk_limit) \ ! 278: ? (_obstack_newchunk (__o, 1), 0) : 0), \ ! 279: *(__o->next_free)++ = (datum); \ ! 280: (void) 0; }) ! 281: ! 282: /* These assume that the obstack alignment is good enough for pointers or ints, ! 283: and that the data added so far to the current object ! 284: shares that much alignment. */ ! 285: ! 286: #define obstack_ptr_grow(OBSTACK,datum) \ ! 287: __extension__ \ ! 288: ({ struct obstack *__o = (OBSTACK); \ ! 289: ((__o->next_free + sizeof (void *) > __o->chunk_limit) \ ! 290: ? (_obstack_newchunk (__o, sizeof (void *)), 0) : 0), \ ! 291: *((void **)__o->next_free)++ = ((void *)datum); \ ! 292: (void) 0; }) ! 293: ! 294: #define obstack_int_grow(OBSTACK,datum) \ ! 295: __extension__ \ ! 296: ({ struct obstack *__o = (OBSTACK); \ ! 297: ((__o->next_free + sizeof (int) > __o->chunk_limit) \ ! 298: ? (_obstack_newchunk (__o, sizeof (int)), 0) : 0), \ ! 299: *((int *)__o->next_free)++ = ((int)datum); \ ! 300: (void) 0; }) ! 301: ! 302: #define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void *)aptr) ! 303: #define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint) ! 304: ! 305: #define obstack_blank(OBSTACK,length) \ ! 306: __extension__ \ ! 307: ({ struct obstack *__o = (OBSTACK); \ ! 308: int __len = (length); \ ! 309: ((__o->chunk_limit - __o->next_free < __len) \ ! 310: ? (_obstack_newchunk (__o, __len), 0) : 0); \ ! 311: __o->next_free += __len; \ ! 312: (void) 0; }) ! 313: ! 314: #define obstack_alloc(OBSTACK,length) \ ! 315: __extension__ \ ! 316: ({ struct obstack *__h = (OBSTACK); \ ! 317: obstack_blank (__h, (length)); \ ! 318: obstack_finish (__h); }) ! 319: ! 320: #define obstack_copy(OBSTACK,where,length) \ ! 321: __extension__ \ ! 322: ({ struct obstack *__h = (OBSTACK); \ ! 323: obstack_grow (__h, (where), (length)); \ ! 324: obstack_finish (__h); }) ! 325: ! 326: #define obstack_copy0(OBSTACK,where,length) \ ! 327: __extension__ \ ! 328: ({ struct obstack *__h = (OBSTACK); \ ! 329: obstack_grow0 (__h, (where), (length)); \ ! 330: obstack_finish (__h); }) ! 331: ! 332: /* The local variable is named __o1 to avoid a name conflict ! 333: when obstack_blank is called. */ ! 334: #define obstack_finish(OBSTACK) \ ! 335: __extension__ \ ! 336: ({ struct obstack *__o1 = (OBSTACK); \ ! 337: void *value = (void *) __o1->object_base; \ ! 338: if (__o1->next_free == value) \ ! 339: __o1->maybe_empty_object = 1; \ ! 340: __o1->next_free \ ! 341: = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\ ! 342: & ~ (__o1->alignment_mask)); \ ! 343: ((__o1->next_free - (char *)__o1->chunk \ ! 344: > __o1->chunk_limit - (char *)__o1->chunk) \ ! 345: ? (__o1->next_free = __o1->chunk_limit) : 0); \ ! 346: __o1->object_base = __o1->next_free; \ ! 347: value; }) ! 348: ! 349: #define obstack_free(OBSTACK, OBJ) \ ! 350: __extension__ \ ! 351: ({ struct obstack *__o = (OBSTACK); \ ! 352: void *__obj = (OBJ); \ ! 353: if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ ! 354: __o->next_free = __o->object_base = __obj; \ ! 355: else (obstack_free) (__o, __obj); }) ! 356: ! 357: #else /* not __GNUC__ or not __STDC__ */ ! 358: ! 359: #define obstack_object_size(h) \ ! 360: (unsigned) ((h)->next_free - (h)->object_base) ! 361: ! 362: #define obstack_room(h) \ ! 363: (unsigned) ((h)->chunk_limit - (h)->next_free) ! 364: ! 365: #define obstack_grow(h,where,length) \ ! 366: ( (h)->temp = (length), \ ! 367: (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ! 368: ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ ! 369: bcopy (where, (h)->next_free, (h)->temp), \ ! 370: (h)->next_free += (h)->temp) ! 371: ! 372: #define obstack_grow0(h,where,length) \ ! 373: ( (h)->temp = (length), \ ! 374: (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ ! 375: ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \ ! 376: bcopy (where, (h)->next_free, (h)->temp), \ ! 377: (h)->next_free += (h)->temp, \ ! 378: *((h)->next_free)++ = 0) ! 379: ! 380: #define obstack_1grow(h,datum) \ ! 381: ( (((h)->next_free + 1 > (h)->chunk_limit) \ ! 382: ? (_obstack_newchunk ((h), 1), 0) : 0), \ ! 383: *((h)->next_free)++ = (datum)) ! 384: ! 385: #define obstack_ptr_grow(h,datum) \ ! 386: ( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ ! 387: ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ ! 388: *((char **)(((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *)datum)) ! 389: ! 390: #define obstack_int_grow(h,datum) \ ! 391: ( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ ! 392: ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ ! 393: *((int *)(((h)->next_free+=sizeof(int))-sizeof(int))) = ((int)datum)) ! 394: ! 395: #define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char *)aptr) ! 396: #define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint) ! 397: ! 398: #define obstack_blank(h,length) \ ! 399: ( (h)->temp = (length), \ ! 400: (((h)->chunk_limit - (h)->next_free < (h)->temp) \ ! 401: ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ ! 402: (h)->next_free += (h)->temp) ! 403: ! 404: #define obstack_alloc(h,length) \ ! 405: (obstack_blank ((h), (length)), obstack_finish ((h))) ! 406: ! 407: #define obstack_copy(h,where,length) \ ! 408: (obstack_grow ((h), (where), (length)), obstack_finish ((h))) ! 409: ! 410: #define obstack_copy0(h,where,length) \ ! 411: (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) ! 412: ! 413: #define obstack_finish(h) \ ! 414: ( ((h)->next_free == (h)->object_base \ ! 415: ? (((h)->maybe_empty_object = 1), 0) \ ! 416: : 0), \ ! 417: (h)->temp = __PTR_TO_INT ((h)->object_base), \ ! 418: (h)->next_free \ ! 419: = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \ ! 420: & ~ ((h)->alignment_mask)), \ ! 421: (((h)->next_free - (char *)(h)->chunk \ ! 422: > (h)->chunk_limit - (char *)(h)->chunk) \ ! 423: ? ((h)->next_free = (h)->chunk_limit) : 0), \ ! 424: (h)->object_base = (h)->next_free, \ ! 425: __INT_TO_PTR ((h)->temp)) ! 426: ! 427: #ifdef __STDC__ ! 428: #define obstack_free(h,obj) \ ! 429: ( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ ! 430: (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ! 431: ? (int) ((h)->next_free = (h)->object_base \ ! 432: = (h)->temp + (char *) (h)->chunk) \ ! 433: : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0))) ! 434: #else ! 435: #define obstack_free(h,obj) \ ! 436: ( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ ! 437: (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ! 438: ? (int) ((h)->next_free = (h)->object_base \ ! 439: = (h)->temp + (char *) (h)->chunk) \ ! 440: : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0))) ! 441: #endif ! 442: ! 443: #endif /* not __GNUC__ or not __STDC__ */ ! 444: ! 445: #endif /* not __OBSTACKS__ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.