|
|
1.1 ! root 1: /* obstack.h - object stack macros ! 2: Copyright (C) 1988 Free Software Foundation, Inc. ! 3: ! 4: NO WARRANTY ! 5: ! 6: BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY ! 7: NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT ! 8: WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, ! 9: RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS" ! 10: WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, ! 11: BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ! 12: FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY ! 13: AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE ! 14: DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR ! 15: CORRECTION. ! 16: ! 17: IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. ! 18: STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY ! 19: WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE ! 20: LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR ! 21: OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE ! 22: USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR ! 23: DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR ! 24: A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS ! 25: PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH ! 26: DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. ! 27: ! 28: GENERAL PUBLIC LICENSE TO COPY ! 29: ! 30: 1. You may copy and distribute verbatim copies of this source file ! 31: as you receive it, in any medium, provided that you conspicuously and ! 32: appropriately publish on each copy a valid copyright notice "Copyright ! 33: (C) 1988 Free Software Foundation, Inc."; and include following the ! 34: copyright notice a verbatim copy of the above disclaimer of warranty ! 35: and of this License. You may charge a distribution fee for the ! 36: physical act of transferring a copy. ! 37: ! 38: 2. You may modify your copy or copies of this source file or ! 39: any portion of it, and copy and distribute such modifications under ! 40: the terms of Paragraph 1 above, provided that you also do the following: ! 41: ! 42: a) cause the modified files to carry prominent notices stating ! 43: that you changed the files and the date of any change; and ! 44: ! 45: b) cause the whole of any work that you distribute or publish, ! 46: that in whole or in part contains or is a derivative of this ! 47: program or any part thereof, to be licensed at no charge to all ! 48: third parties on terms identical to those contained in this ! 49: License Agreement (except that you may choose to grant more extensive ! 50: warranty protection to some or all third parties, at your option). ! 51: ! 52: c) You may charge a distribution fee for the physical act of ! 53: transferring a copy, and you may at your option offer warranty ! 54: protection in exchange for a fee. ! 55: ! 56: Mere aggregation of another unrelated program with this program (or its ! 57: derivative) on a volume of a storage or distribution medium does not bring ! 58: the other program under the scope of these terms. ! 59: ! 60: 3. You may copy and distribute this program or any portion of it in ! 61: compiled, executable or object code form under the terms of Paragraphs ! 62: 1 and 2 above provided that you do the following: ! 63: ! 64: a) accompany it with the complete corresponding machine-readable ! 65: source code, which must be distributed under the terms of ! 66: Paragraphs 1 and 2 above; or, ! 67: ! 68: b) accompany it with a written offer, valid for at least three ! 69: years, to give any third party free (except for a nominal ! 70: shipping charge) a complete machine-readable copy of the ! 71: corresponding source code, to be distributed under the terms of ! 72: Paragraphs 1 and 2 above; or, ! 73: ! 74: c) accompany it with the information you received as to where the ! 75: corresponding source code may be obtained. (This alternative is ! 76: allowed only for noncommercial distribution and only if you ! 77: received the program in object code or executable form alone.) ! 78: ! 79: For an executable file, complete source code means all the source code for ! 80: all modules it contains; but, as a special exception, it need not include ! 81: source code for modules which are standard libraries that accompany the ! 82: operating system on which the executable file runs. ! 83: ! 84: 4. You may not copy, sublicense, distribute or transfer this program ! 85: except as expressly provided under this License Agreement. Any attempt ! 86: otherwise to copy, sublicense, distribute or transfer this program is void and ! 87: your rights to use the program under this License agreement shall be ! 88: automatically terminated. However, parties who have received computer ! 89: software programs from you with this License Agreement will not have ! 90: their licenses terminated so long as such parties remain in full compliance. ! 91: ! 92: 5. If you wish to incorporate parts of this program into other free ! 93: programs whose distribution conditions are different, write to the Free ! 94: Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet ! 95: worked out a simple rule that can be stated here, but we will often permit ! 96: this. We will be guided by the two goals of preserving the free status of ! 97: all derivatives our free software and of promoting the sharing and reuse of ! 98: software. ! 99: ! 100: ! 101: In other words, you are welcome to use, share and improve this program. ! 102: You are forbidden to forbid anyone else to use, share and improve ! 103: what you give them. Help stamp out software-hoarding! */ ! 104: ! 105: ! 106: /* Summary: ! 107: ! 108: All the apparent functions defined here are macros. The idea ! 109: is that you would use these pre-tested macros to solve a ! 110: very specific set of problems, and they would run fast. ! 111: Caution: no side-effects in arguments please!! They may be ! 112: evaluated MANY times!! ! 113: ! 114: These macros operate a stack of objects. Each object starts life ! 115: small, and may grow to maturity. (Consider building a word syllable ! 116: by syllable.) An object can move while it is growing. Once it has ! 117: been "finished" it never changes address again. So the "top of the ! 118: stack" is typically an immature growing object, while the rest of the ! 119: stack is of mature, fixed size and fixed address objects. ! 120: ! 121: These routines grab large chunks of memory, using a function you ! 122: supply, called `obstack_chunk_alloc'. On occasion, they free chunks, ! 123: by calling `obstack_chunk_free'. You must define them and declare ! 124: them before using any obstack macros. ! 125: ! 126: Each independent stack is represented by a `struct obstack'. ! 127: Each of the obstack macros expects a pointer to such a structure ! 128: as the first argument. ! 129: ! 130: One motivation for this package is the problem of growing char strings ! 131: in symbol tables. Unless you are "facist pig with a read-only mind" ! 132: [Gosper's immortal quote from HAKMEM item 154, out of context] you ! 133: would not like to put any arbitrary upper limit on the length of your ! 134: symbols. ! 135: ! 136: In practice this often means you will build many short symbols and a ! 137: few long symbols. At the time you are reading a symbol you don't know ! 138: how long it is. One traditional method is to read a symbol into a ! 139: buffer, realloc()ating the buffer every time you try to read a symbol ! 140: that is longer than the buffer. This is beaut, but you still will ! 141: want to copy the symbol from the buffer to a more permanent ! 142: symbol-table entry say about half the time. ! 143: ! 144: With obstacks, you can work differently. Use one obstack for all symbol ! 145: names. As you read a symbol, grow the name in the obstack gradually. ! 146: When the name is complete, finalize it. Then, if the symbol exists already, ! 147: free the newly read name. ! 148: ! 149: The way we do this is to take a large chunk, allocating memory from ! 150: low addresses. When you want to build a aymbol in the chunk you just ! 151: add chars above the current "high water mark" in the chunk. When you ! 152: have finished adding chars, because you got to the end of the symbol, ! 153: you know how long the chars are, and you can create a new object. ! 154: Mostly the chars will not burst over the highest address of the chunk, ! 155: because you would typically expect a chunk to be (say) 100 times as ! 156: long as an average object. ! 157: ! 158: In case that isn't clear, when we have enough chars to make up ! 159: the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) ! 160: so we just point to it where it lies. No moving of chars is ! 161: needed and this is the second win: potentially long strings need ! 162: never be explicitly shuffled. Once an object is formed, it does not ! 163: change its address during its lifetime. ! 164: ! 165: When the chars burst over a chunk boundary, we allocate a larger ! 166: chunk, and then copy the partly formed object from the end of the old ! 167: chunk to the beggining of the new larger chunk. We then carry on ! 168: accreting characters to the end of the object as we normaly would. ! 169: ! 170: A special macro is provided to add a single char at a time to a ! 171: growing object. This allows the use of register variables, which ! 172: break the ordinary 'growth' macro. ! 173: ! 174: Summary: ! 175: We allocate large chunks. ! 176: We carve out one object at a time from the current chunk. ! 177: Once carved, an object never moves. ! 178: We are free to append data of any size to the currently ! 179: growing object. ! 180: Exactly one object is growing in an obstack at any one time. ! 181: You can run one obstack per control block. ! 182: You may have as many control blocks as you dare. ! 183: Because of the way we do it, you can `unwind' a obstack ! 184: back to a previous state. (You may remove objects much ! 185: as you would with a stack.) ! 186: */ ! 187: ! 188: ! 189: /* Don't do the contents of this file more than once. */ ! 190: ! 191: #ifndef __OBSTACKS__ ! 192: #define __OBSTACKS__ ! 193: ! 194: struct _obstack_chunk /* Lives at front of each chunk. */ ! 195: { ! 196: char *limit; /* 1 past end of this chunk */ ! 197: struct _obstack_chunk *prev; /* address of prior chunk or NULL */ ! 198: char contents[4]; /* objects begin here */ ! 199: }; ! 200: ! 201: struct obstack /* control current object in current chunk */ ! 202: { ! 203: long chunk_size; /* preferred size to allocate chunks in */ ! 204: struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */ ! 205: char *object_base; /* address of object we are building */ ! 206: char *next_free; /* where to add next char to current object */ ! 207: char *chunk_limit; /* address of char after current chunk */ ! 208: int temp; /* Temporary for some macros. */ ! 209: int alignment_mask; /* Mask of alignment for each object. */ ! 210: struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ ! 211: void (*freefun) (); /* User's function to free a chunk. */ ! 212: }; ! 213: ! 214: #ifdef __STDC__ ! 215: ! 216: /* Do the function-declarations after the structs ! 217: but before defining the macros. */ ! 218: ! 219: void obstack_init (struct obstack *obstack); ! 220: ! 221: void * obstack_alloc (struct obstack *obstack, int size); ! 222: ! 223: void * obstack_copy (struct obstack *obstack, void *address, int size); ! 224: void * obstack_copy0 (struct obstack *obstack, void *address, int size); ! 225: ! 226: void obstack_free (struct obstack *obstack, void *block); ! 227: ! 228: void obstack_blank (struct obstack *obstack, int size); ! 229: ! 230: void obstack_grow (struct obstack *obstack, void *data, int size); ! 231: void obstack_grow0 (struct obstack *obstack, void *data, int size); ! 232: ! 233: void obstack_1grow (struct obstack *obstack, int data_char); ! 234: ! 235: void * obstack_finish (struct obstack *obstack); ! 236: ! 237: int obstack_object_size (struct obstack *obstack); ! 238: ! 239: int obstack_room (struct obstack *obstack); ! 240: void obstack_1grow_fast (struct obstack *obstack, int data_char); ! 241: void obstack_blank_fast (struct obstack *obstack, int size); ! 242: ! 243: void * obstack_base (struct obstack *obstack); ! 244: void * obstack_next_free (struct obstack *obstack); ! 245: int obstack_alignment_mask (struct obstack *obstack); ! 246: int obstack_chunk_size (struct obstack *obstack); ! 247: ! 248: #endif /* __STDC__ */ ! 249: ! 250: /* Non-ANSI C cannot really support alternative functions for these macros, ! 251: so we do not declare them. */ ! 252: ! 253: /* Pointer to beginning of object being allocated or to be allocated next. ! 254: Note that this might not be the final address of the object ! 255: because a new chunk might be needed to hold the final size. */ ! 256: ! 257: #define obstack_base(h) ((h)->object_base) ! 258: ! 259: /* Size for allocating ordinary chunks. */ ! 260: ! 261: #define obstack_chunk_size(h) ((h)->chunk_size) ! 262: ! 263: /* Pointer to next byte not yet allocated in current chunk. */ ! 264: ! 265: #define obstack_next_free(h) ((h)->next_free) ! 266: ! 267: /* Mask specifying low bits that should be clear in address of an object. */ ! 268: ! 269: #define obstack_alignment_mask(h) ((h)->alignment_mask) ! 270: ! 271: #define obstack_init(h) \ ! 272: _obstack_begin ((h), 4096 - 4, 0, obstack_chunk_alloc, obstack_chunk_free) ! 273: ! 274: #define obstack_begin(h, size) \ ! 275: _obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free) ! 276: ! 277: #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar) ! 278: ! 279: #define obstack_blank_fast(h,n) ((h)->next_free += (n)) ! 280: ! 281: #ifdef __GNUC__ ! 282: ! 283: /* For GNU C we can define these macros to compute all args only once ! 284: without using a global variable. ! 285: Also, we can avoid using the `temp' slot, to make faster code. */ ! 286: ! 287: #define obstack_object_size(OBSTACK) \ ! 288: ({ struct obstack *__o = (OBSTACK); \ ! 289: (unsigned) (__o->next_free - __o->object_base); }) ! 290: ! 291: #define obstack_room(OBSTACK) \ ! 292: ({ struct obstack *__o = (OBSTACK); \ ! 293: (unsigned) (__o->chunk_limit - __o->next_free); }) ! 294: ! 295: #define obstack_grow(OBSTACK,where,length) \ ! 296: ({ struct obstack *__o = (OBSTACK); \ ! 297: int __len = (length); \ ! 298: ((__o->next_free + __len > __o->chunk_limit) \ ! 299: ? _obstack_newchunk (__o, __len) : 0); \ ! 300: bcopy (where, __o->next_free, __len); \ ! 301: __o->next_free += __len; \ ! 302: (void) 0; }) ! 303: ! 304: #define obstack_grow0(OBSTACK,where,length) \ ! 305: ({ struct obstack *__o = (OBSTACK); \ ! 306: int __len = (length); \ ! 307: ((__o->next_free + __len + 1 > __o->chunk_limit) \ ! 308: ? _obstack_newchunk (__o, __len + 1) : 0), \ ! 309: bcopy (where, __o->next_free, __len), \ ! 310: __o->next_free += __len, \ ! 311: *(__o->next_free)++ = 0; \ ! 312: (void) 0; }) ! 313: ! 314: #define obstack_1grow(OBSTACK,datum) \ ! 315: ({ struct obstack *__o = (OBSTACK); \ ! 316: ((__o->next_free + 1 > __o->chunk_limit) \ ! 317: ? _obstack_newchunk (__o, 1) : 0), \ ! 318: *(__o->next_free)++ = (datum); \ ! 319: (void) 0; }) ! 320: ! 321: #define obstack_blank(OBSTACK,length) \ ! 322: ({ struct obstack *__o = (OBSTACK); \ ! 323: int __len = (length); \ ! 324: ((__o->next_free + __len > __o->chunk_limit) \ ! 325: ? _obstack_newchunk (__o, __len) : 0); \ ! 326: __o->next_free += __len; \ ! 327: (void) 0; }) ! 328: ! 329: #define obstack_alloc(OBSTACK,length) \ ! 330: ({ struct obstack *__h = (OBSTACK); \ ! 331: obstack_blank (__h, (length)); \ ! 332: obstack_finish (__h); }) ! 333: ! 334: #define obstack_copy(OBSTACK,where,length) \ ! 335: ({ struct obstack *__h = (OBSTACK); \ ! 336: obstack_grow (__h, (where), (length)); \ ! 337: obstack_finish (__h); }) ! 338: ! 339: #define obstack_copy0(OBSTACK,where,length) \ ! 340: ({ struct obstack *__h = (OBSTACK); \ ! 341: obstack_grow0 (__h, (where), (length)); \ ! 342: obstack_finish (__h); }) ! 343: ! 344: #define obstack_finish(OBSTACK) \ ! 345: ({ struct obstack *__o = (OBSTACK); \ ! 346: void *value = (void *) __o->object_base; \ ! 347: __o->next_free \ ! 348: = (char*)((int)(__o->next_free+__o->alignment_mask) \ ! 349: & ~ (__o->alignment_mask)); \ ! 350: ((__o->next_free - (char *)__o->chunk \ ! 351: > __o->chunk_limit - (char *)__o->chunk) \ ! 352: ? __o->next_free = __o->chunk_limit : 0); \ ! 353: __o->object_base = __o->next_free; \ ! 354: value; }) ! 355: ! 356: #define obstack_free(OBSTACK, OBJ) \ ! 357: ({ struct obstack *__o = (OBSTACK); \ ! 358: void *__obj = (OBJ); \ ! 359: if (__obj >= (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ ! 360: __o->next_free = __o->object_base = __obj; \ ! 361: else (obstack_free) (__o, __obj); }) ! 362: ! 363: #else /* not __GNUC__ */ ! 364: ! 365: /* The non-GNU macros copy the obstack-pointer into this global variable ! 366: to avoid multiple evaluation. */ ! 367: ! 368: extern struct obstack *_obstack; ! 369: ! 370: #define obstack_object_size(h) \ ! 371: (unsigned) (_obstack = (h), (h)->next_free - (h)->object_base) ! 372: ! 373: #define obstack_room(h) \ ! 374: (unsigned) (_obstack = (h), (h)->chunk_limit - (h)->next_free) ! 375: ! 376: #define obstack_grow(h,where,length) \ ! 377: ( (h)->temp = (length), \ ! 378: (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ! 379: ? _obstack_newchunk ((h), (h)->temp) : 0), \ ! 380: bcopy (where, (h)->next_free, (h)->temp), \ ! 381: (h)->next_free += (h)->temp) ! 382: ! 383: #define obstack_grow0(h,where,length) \ ! 384: ( (h)->temp = (length), \ ! 385: (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ ! 386: ? _obstack_newchunk ((h), (h)->temp + 1) : 0), \ ! 387: bcopy (where, (h)->next_free, (h)->temp), \ ! 388: (h)->next_free += (h)->temp, \ ! 389: *((h)->next_free)++ = 0) ! 390: ! 391: #define obstack_1grow(h,datum) \ ! 392: ( (((h)->next_free + 1 > (h)->chunk_limit) \ ! 393: ? _obstack_newchunk ((h), 1) : 0), \ ! 394: *((h)->next_free)++ = (datum)) ! 395: ! 396: #define obstack_blank(h,length) \ ! 397: ( (h)->temp = (length), \ ! 398: (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ! 399: ? _obstack_newchunk ((h), (h)->temp) : 0), \ ! 400: (h)->next_free += (h)->temp) ! 401: ! 402: #define obstack_alloc(h,length) \ ! 403: (obstack_blank ((h), (length)), obstack_finish ((h))) ! 404: ! 405: #define obstack_copy(h,where,length) \ ! 406: (obstack_grow ((h), (where), (length)), obstack_finish ((h))) ! 407: ! 408: #define obstack_copy0(h,where,length) \ ! 409: (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) ! 410: ! 411: #define obstack_finish(h) \ ! 412: ( (h)->temp = (int) (h)->object_base, \ ! 413: (h)->next_free \ ! 414: = (char*)((int)((h)->next_free+(h)->alignment_mask) \ ! 415: & ~ ((h)->alignment_mask)), \ ! 416: (((h)->next_free - (char *)(h)->chunk \ ! 417: > (h)->chunk_limit - (char *)(h)->chunk) \ ! 418: ? ((h)->next_free = (h)->chunk_limit) : 0), \ ! 419: (h)->object_base = (h)->next_free, \ ! 420: (char *) (h)->temp) ! 421: ! 422: #ifdef __STDC__ ! 423: #define obstack_free(h,obj) \ ! 424: ( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ ! 425: (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ! 426: ? (int) ((h)->next_free = (h)->object_base \ ! 427: = (h)->temp + (char *) (h)->chunk) \ ! 428: : ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0))) ! 429: #else ! 430: #define obstack_free(h,obj) \ ! 431: ( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ ! 432: (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ! 433: ? (int) ((h)->next_free = (h)->object_base \ ! 434: = (h)->temp + (char *) (h)->chunk) \ ! 435: : (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk))) ! 436: #endif ! 437: ! 438: #endif /* not __GNUC__ */ ! 439: ! 440: #endif /* not __OBSTACKS__ */ ! 441:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.