|
|
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 1, 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: #define obstack_chunk_alloc xmalloc ! 107: #define obstack_chunk_free xfree ! 108: ! 109: /* We use subtraction of (char *)0 instead of casting to int ! 110: because on word-addressable machines a simple cast to int ! 111: may ignore the byte-within-word field of the pointer. */ ! 112: ! 113: #ifndef __PTR_TO_INT ! 114: #define __PTR_TO_INT(P) ((P) - (char *)0) ! 115: #endif ! 116: ! 117: #ifndef __INT_TO_PTR ! 118: #define __INT_TO_PTR(P) ((P) + (char *)0) ! 119: #endif ! 120: ! 121: struct _obstack_chunk /* Lives at front of each chunk. */ ! 122: { ! 123: char *limit; /* 1 past end of this chunk */ ! 124: struct _obstack_chunk *prev; /* address of prior chunk or NULL */ ! 125: char contents[4]; /* objects begin here */ ! 126: }; ! 127: ! 128: struct obstack /* control current object in current chunk */ ! 129: { ! 130: long chunk_size; /* preferred size to allocate chunks in */ ! 131: struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */ ! 132: char *object_base; /* address of object we are building */ ! 133: char *next_free; /* where to add next char to current object */ ! 134: char *chunk_limit; /* address of char after current chunk */ ! 135: int temp; /* Temporary for some macros. */ ! 136: int alignment_mask; /* Mask of alignment for each object. */ ! 137: struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ ! 138: void (*freefun) (); /* User's function to free a chunk. */ ! 139: }; ! 140: ! 141: #ifdef __STDC__ ! 142: ! 143: /* Do the function-declarations after the structs ! 144: but before defining the macros. */ ! 145: ! 146: void obstack_init (struct obstack *obstack); ! 147: ! 148: void * obstack_alloc (struct obstack *obstack, int size); ! 149: ! 150: void * obstack_copy (struct obstack *obstack, void *address, int size); ! 151: void * obstack_copy0 (struct obstack *obstack, void *address, int size); ! 152: ! 153: void obstack_free (struct obstack *obstack, void *block); ! 154: ! 155: void obstack_blank (struct obstack *obstack, int size); ! 156: ! 157: void obstack_grow (struct obstack *obstack, void *data, int size); ! 158: void obstack_grow0 (struct obstack *obstack, void *data, int size); ! 159: ! 160: void obstack_1grow (struct obstack *obstack, int data_char); ! 161: void obstack_ptr_grow (struct obstack *obstack, void *data); ! 162: void obstack_int_grow (struct obstack *obstack, int data); ! 163: ! 164: void * obstack_finish (struct obstack *obstack); ! 165: ! 166: int obstack_object_size (struct obstack *obstack); ! 167: ! 168: int obstack_room (struct obstack *obstack); ! 169: void obstack_1grow_fast (struct obstack *obstack, int data_char); ! 170: void obstack_ptr_grow_fast (struct obstack *obstack, void *data); ! 171: void obstack_int_grow_fast (struct obstack *obstack, int data); ! 172: void obstack_blank_fast (struct obstack *obstack, int size); ! 173: ! 174: void * obstack_base (struct obstack *obstack); ! 175: void * obstack_next_free (struct obstack *obstack); ! 176: int obstack_alignment_mask (struct obstack *obstack); ! 177: int obstack_chunk_size (struct obstack *obstack); ! 178: ! 179: void _obstack_begin (struct obstack *h, int size, int alignment, ! 180: void * (*chunkfun)(long n), void (*freefun)()); ! 181: void _obstack_newchunk (struct obstack *h, int length); ! 182: #endif /* __STDC__ */ ! 183: ! 184: /* Non-ANSI C cannot really support alternative functions for these macros, ! 185: so we do not declare them. */ ! 186: ! 187: /* Pointer to beginning of object being allocated or to be allocated next. ! 188: Note that this might not be the final address of the object ! 189: because a new chunk might be needed to hold the final size. */ ! 190: ! 191: #define obstack_base(h) ((h)->object_base) ! 192: ! 193: /* Size for allocating ordinary chunks. */ ! 194: ! 195: #define obstack_chunk_size(h) ((h)->chunk_size) ! 196: ! 197: /* Pointer to next byte not yet allocated in current chunk. */ ! 198: ! 199: #define obstack_next_free(h) ((h)->next_free) ! 200: ! 201: /* Mask specifying low bits that should be clear in address of an object. */ ! 202: ! 203: #define obstack_alignment_mask(h) ((h)->alignment_mask) ! 204: ! 205: #define obstack_init(h) \ ! 206: _obstack_begin ((h), 0, 0, obstack_chunk_alloc, obstack_chunk_free) ! 207: ! 208: #define obstack_begin(h, size) \ ! 209: _obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free) ! 210: ! 211: #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar) ! 212: ! 213: #define obstack_blank_fast(h,n) ((h)->next_free += (n)) ! 214: ! 215: #if defined (__GNUC__) && defined (__STDC__) ! 216: ! 217: /* For GNU C, if not -traditional, ! 218: we can define these macros to compute all args only once ! 219: without using a global variable. ! 220: Also, we can avoid using the `temp' slot, to make faster code. */ ! 221: ! 222: #define obstack_object_size(OBSTACK) \ ! 223: ({ struct obstack *__o = (OBSTACK); \ ! 224: (unsigned) (__o->next_free - __o->object_base); }) ! 225: ! 226: #define obstack_room(OBSTACK) \ ! 227: ({ struct obstack *__o = (OBSTACK); \ ! 228: (unsigned) (__o->chunk_limit - __o->next_free); }) ! 229: ! 230: #define obstack_grow(OBSTACK,where,length) \ ! 231: ({ struct obstack *__o = (OBSTACK); \ ! 232: int __len = (length); \ ! 233: ((__o->next_free + __len > __o->chunk_limit) \ ! 234: ? _obstack_newchunk (__o, __len) : 0); \ ! 235: bcopy (where, __o->next_free, __len); \ ! 236: __o->next_free += __len; \ ! 237: (void) 0; }) ! 238: ! 239: #define obstack_grow0(OBSTACK,where,length) \ ! 240: ({ struct obstack *__o = (OBSTACK); \ ! 241: int __len = (length); \ ! 242: ((__o->next_free + __len + 1 > __o->chunk_limit) \ ! 243: ? _obstack_newchunk (__o, __len + 1) : 0), \ ! 244: bcopy (where, __o->next_free, __len), \ ! 245: __o->next_free += __len, \ ! 246: *(__o->next_free)++ = 0; \ ! 247: (void) 0; }) ! 248: ! 249: #define obstack_1grow(OBSTACK,datum) \ ! 250: ({ struct obstack *__o = (OBSTACK); \ ! 251: ((__o->next_free + 1 > __o->chunk_limit) \ ! 252: ? _obstack_newchunk (__o, 1) : 0), \ ! 253: *(__o->next_free)++ = (datum); \ ! 254: (void) 0; }) ! 255: ! 256: /* These assume that the obstack alignment is good enough for pointers or ints, ! 257: and that the data added so far to the current object ! 258: shares that much alignment. */ ! 259: ! 260: #define obstack_ptr_grow(OBSTACK,datum) \ ! 261: ({ struct obstack *__o = (OBSTACK); \ ! 262: ((__o->next_free + sizeof (void *) > __o->chunk_limit) \ ! 263: ? _obstack_newchunk (__o, sizeof (void *)) : 0), \ ! 264: *((void **)__o->next_free)++ = ((void *)datum); \ ! 265: (void) 0; }) ! 266: ! 267: #define obstack_int_grow(OBSTACK,datum) \ ! 268: ({ struct obstack *__o = (OBSTACK); \ ! 269: ((__o->next_free + sizeof (int) > __o->chunk_limit) \ ! 270: ? _obstack_newchunk (__o, sizeof (int)) : 0), \ ! 271: *((int *)__o->next_free)++ = ((int)datum); \ ! 272: (void) 0; }) ! 273: ! 274: #define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void *)aptr) ! 275: #define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint) ! 276: ! 277: #define obstack_blank(OBSTACK,length) \ ! 278: ({ struct obstack *__o = (OBSTACK); \ ! 279: int __len = (length); \ ! 280: ((__o->next_free + __len > __o->chunk_limit) \ ! 281: ? _obstack_newchunk (__o, __len) : 0); \ ! 282: __o->next_free += __len; \ ! 283: (void) 0; }) ! 284: ! 285: #define obstack_alloc(OBSTACK,length) \ ! 286: ({ struct obstack *__h = (OBSTACK); \ ! 287: obstack_blank (__h, (length)); \ ! 288: obstack_finish (__h); }) ! 289: ! 290: #define obstack_copy(OBSTACK,where,length) \ ! 291: ({ struct obstack *__h = (OBSTACK); \ ! 292: obstack_grow (__h, (where), (length)); \ ! 293: obstack_finish (__h); }) ! 294: ! 295: #define obstack_copy0(OBSTACK,where,length) \ ! 296: ({ struct obstack *__h = (OBSTACK); \ ! 297: obstack_grow0 (__h, (where), (length)); \ ! 298: obstack_finish (__h); }) ! 299: ! 300: #define obstack_finish(OBSTACK) \ ! 301: ({ struct obstack *__o = (OBSTACK); \ ! 302: void *value = (void *) __o->object_base; \ ! 303: __o->next_free \ ! 304: = __INT_TO_PTR ((__PTR_TO_INT (__o->next_free)+__o->alignment_mask)\ ! 305: & ~ (__o->alignment_mask)); \ ! 306: ((__o->next_free - (char *)__o->chunk \ ! 307: > __o->chunk_limit - (char *)__o->chunk) \ ! 308: ? (__o->next_free = __o->chunk_limit) : 0); \ ! 309: __o->object_base = __o->next_free; \ ! 310: value; }) ! 311: ! 312: #define obstack_free(OBSTACK, OBJ) \ ! 313: ({ struct obstack *__o = (OBSTACK); \ ! 314: void *__obj = (OBJ); \ ! 315: if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ ! 316: __o->next_free = __o->object_base = __obj; \ ! 317: else (obstack_free) (__o, __obj); }) ! 318: ! 319: #else /* not __GNUC__ or not __STDC__ */ ! 320: ! 321: #define obstack_object_size(h) \ ! 322: (unsigned) ((h)->next_free - (h)->object_base) ! 323: ! 324: #define obstack_room(h) \ ! 325: (unsigned) ((h)->chunk_limit - (h)->next_free) ! 326: ! 327: #define obstack_grow(h,where,length) \ ! 328: ( (h)->temp = (length), \ ! 329: (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ! 330: ? _obstack_newchunk ((h), (h)->temp) : 0), \ ! 331: bcopy (where, (h)->next_free, (h)->temp), \ ! 332: (h)->next_free += (h)->temp) ! 333: ! 334: #define obstack_grow0(h,where,length) \ ! 335: ( (h)->temp = (length), \ ! 336: (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ ! 337: ? _obstack_newchunk ((h), (h)->temp + 1) : 0), \ ! 338: bcopy (where, (h)->next_free, (h)->temp), \ ! 339: (h)->next_free += (h)->temp, \ ! 340: *((h)->next_free)++ = 0) ! 341: ! 342: #define obstack_1grow(h,datum) \ ! 343: ( (((h)->next_free + 1 > (h)->chunk_limit) \ ! 344: ? _obstack_newchunk ((h), 1) : 0), \ ! 345: *((h)->next_free)++ = (datum)) ! 346: ! 347: #define obstack_ptr_grow(h,datum) \ ! 348: ( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ ! 349: ? _obstack_newchunk ((h), sizeof (char *)) : 0), \ ! 350: *((char **)(h)->next_free)++ = ((char *)datum)) ! 351: ! 352: #define obstack_int_grow(h,datum) \ ! 353: ( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ ! 354: ? _obstack_newchunk ((h), sizeof (int)) : 0), \ ! 355: *((int *)(h)->next_free)++ = ((int)datum)) ! 356: ! 357: #define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char *)aptr) ! 358: #define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint) ! 359: ! 360: #define obstack_blank(h,length) \ ! 361: ( (h)->temp = (length), \ ! 362: (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ! 363: ? _obstack_newchunk ((h), (h)->temp) : 0), \ ! 364: (h)->next_free += (h)->temp) ! 365: ! 366: #define obstack_alloc(h,length) \ ! 367: (obstack_blank ((h), (length)), obstack_finish ((h))) ! 368: ! 369: #define obstack_copy(h,where,length) \ ! 370: (obstack_grow ((h), (where), (length)), obstack_finish ((h))) ! 371: ! 372: #define obstack_copy0(h,where,length) \ ! 373: (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) ! 374: ! 375: #define obstack_finish(h) \ ! 376: ( (h)->temp = __PTR_TO_INT ((h)->object_base), \ ! 377: (h)->next_free \ ! 378: = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \ ! 379: & ~ ((h)->alignment_mask)), \ ! 380: (((h)->next_free - (char *)(h)->chunk \ ! 381: > (h)->chunk_limit - (char *)(h)->chunk) \ ! 382: ? ((h)->next_free = (h)->chunk_limit) : 0), \ ! 383: (h)->object_base = (h)->next_free, \ ! 384: __INT_TO_PTR ((h)->temp)) ! 385: ! 386: #ifdef __STDC__ ! 387: #define obstack_free(h,obj) \ ! 388: ( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ ! 389: (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ! 390: ? (int) ((h)->next_free = (h)->object_base \ ! 391: = (h)->temp + (char *) (h)->chunk) \ ! 392: : ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0))) ! 393: #else ! 394: #define obstack_free(h,obj) \ ! 395: ( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ ! 396: (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ! 397: ? (int) ((h)->next_free = (h)->object_base \ ! 398: = (h)->temp + (char *) (h)->chunk) \ ! 399: : (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk))) ! 400: #endif ! 401: ! 402: #endif /* not __GNUC__ or not __STDC__ */ ! 403: ! 404: #endif /* not __OBSTACKS__ */ ! 405:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.