|
|
1.1 ! root 1: /* obstack.c - subroutines used implicitly by object stack macros ! 2: Copyright (C) 1988 Free Software Foundation, Inc. ! 3: ! 4: This file is part of the libiberty library. ! 5: Libiberty is free software; you can redistribute it and/or ! 6: modify it under the terms of the GNU Library General Public ! 7: License as published by the Free Software Foundation; either ! 8: version 2 of the License, or (at your option) any later version. ! 9: ! 10: Libiberty is distributed in the hope that it will be useful, ! 11: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 13: Library General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU Library General Public ! 16: License along with libiberty; see the file COPYING.LIB. If ! 17: not, write to the Free Software Foundation, Inc., 675 Mass Ave, ! 18: Cambridge, MA 02139, USA. */ ! 19: ! 20: #include "obstack.h" ! 21: ! 22: #ifdef __STDC__ ! 23: #define POINTER void * ! 24: #else ! 25: #define POINTER char * ! 26: #endif ! 27: ! 28: /* Determine default alignment. */ ! 29: struct fooalign {char x; double d;}; ! 30: #define DEFAULT_ALIGNMENT \ ! 31: ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0)) ! 32: /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. ! 33: But in fact it might be less smart and round addresses to as much as ! 34: DEFAULT_ROUNDING. So we prepare for it to do that. */ ! 35: union fooround {long x; double d;}; ! 36: #define DEFAULT_ROUNDING (sizeof (union fooround)) ! 37: ! 38: /* When we copy a long block of data, this is the unit to do it with. ! 39: On some machines, copying successive ints does not work; ! 40: in such a case, redefine COPYING_UNIT to `long' (if that works) ! 41: or `char' as a last resort. */ ! 42: #ifndef COPYING_UNIT ! 43: #define COPYING_UNIT int ! 44: #endif ! 45: ! 46: /* The non-GNU-C macros copy the obstack into this global variable ! 47: to avoid multiple evaluation. */ ! 48: ! 49: struct obstack *_obstack; ! 50: ! 51: /* Define a macro that either calls functions with the traditional malloc/free ! 52: calling interface, or calls functions with the mmalloc/mfree interface ! 53: (that adds an extra first argument), based on the state of use_extra_arg. ! 54: For free, do not use ?:, since some compilers, like the MIPS compilers, ! 55: do not allow (expr) ? void : void. */ ! 56: ! 57: #define CALL_CHUNKFUN(h, size) \ ! 58: (((h) -> use_extra_arg) \ ! 59: ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ ! 60: : (*(h)->chunkfun) ((size))) ! 61: ! 62: #define CALL_FREEFUN(h, old_chunk) \ ! 63: do { \ ! 64: if ((h) -> use_extra_arg) \ ! 65: (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ ! 66: else \ ! 67: (*(h)->freefun) ((old_chunk)); \ ! 68: } while (0) ! 69: ! 70: ! 71: /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). ! 72: Objects start on multiples of ALIGNMENT (0 means use default). ! 73: CHUNKFUN is the function to use to allocate chunks, ! 74: and FREEFUN the function to free them. */ ! 75: ! 76: void ! 77: _obstack_begin (h, size, alignment, chunkfun, freefun) ! 78: struct obstack *h; ! 79: int size; ! 80: int alignment; ! 81: POINTER (*chunkfun) (); ! 82: void (*freefun) (); ! 83: { ! 84: register struct _obstack_chunk* chunk; /* points to new chunk */ ! 85: ! 86: if (alignment == 0) ! 87: alignment = DEFAULT_ALIGNMENT; ! 88: if (size == 0) ! 89: /* Default size is what GNU malloc can fit in a 4096-byte block. */ ! 90: { ! 91: /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. ! 92: Use the values for range checking, because if range checking is off, ! 93: the extra bytes won't be missed terribly, but if range checking is on ! 94: and we used a larger request, a whole extra 4096 bytes would be ! 95: allocated. ! 96: ! 97: These number are irrelevant to the new GNU malloc. I suspect it is ! 98: less sensitive to the size of the request. */ ! 99: int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) ! 100: + 4 + DEFAULT_ROUNDING - 1) ! 101: & ~(DEFAULT_ROUNDING - 1)); ! 102: size = 4096 - extra; ! 103: } ! 104: ! 105: h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; ! 106: h->freefun = freefun; ! 107: h->chunk_size = size; ! 108: h->alignment_mask = alignment - 1; ! 109: h->use_extra_arg = 0; ! 110: ! 111: chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); ! 112: h->next_free = h->object_base = chunk->contents; ! 113: h->chunk_limit = chunk->limit ! 114: = (char *) chunk + h->chunk_size; ! 115: chunk->prev = 0; ! 116: /* The initial chunk now contains no empty object. */ ! 117: h->maybe_empty_object = 0; ! 118: } ! 119: ! 120: void ! 121: _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) ! 122: struct obstack *h; ! 123: int size; ! 124: int alignment; ! 125: POINTER (*chunkfun) (); ! 126: void (*freefun) (); ! 127: POINTER arg; ! 128: { ! 129: register struct _obstack_chunk* chunk; /* points to new chunk */ ! 130: ! 131: if (alignment == 0) ! 132: alignment = DEFAULT_ALIGNMENT; ! 133: if (size == 0) ! 134: /* Default size is what GNU malloc can fit in a 4096-byte block. */ ! 135: { ! 136: /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. ! 137: Use the values for range checking, because if range checking is off, ! 138: the extra bytes won't be missed terribly, but if range checking is on ! 139: and we used a larger request, a whole extra 4096 bytes would be ! 140: allocated. ! 141: ! 142: These number are irrelevant to the new GNU malloc. I suspect it is ! 143: less sensitive to the size of the request. */ ! 144: int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) ! 145: + 4 + DEFAULT_ROUNDING - 1) ! 146: & ~(DEFAULT_ROUNDING - 1)); ! 147: size = 4096 - extra; ! 148: } ! 149: ! 150: h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; ! 151: h->freefun = freefun; ! 152: h->chunk_size = size; ! 153: h->alignment_mask = alignment - 1; ! 154: h->extra_arg = arg; ! 155: h->use_extra_arg = 1; ! 156: ! 157: chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); ! 158: h->next_free = h->object_base = chunk->contents; ! 159: h->chunk_limit = chunk->limit ! 160: = (char *) chunk + h->chunk_size; ! 161: chunk->prev = 0; ! 162: /* The initial chunk now contains no empty object. */ ! 163: h->maybe_empty_object = 0; ! 164: } ! 165: ! 166: /* Allocate a new current chunk for the obstack *H ! 167: on the assumption that LENGTH bytes need to be added ! 168: to the current object, or a new object of length LENGTH allocated. ! 169: Copies any partial object from the end of the old chunk ! 170: to the beginning of the new one. */ ! 171: ! 172: void ! 173: _obstack_newchunk (h, length) ! 174: struct obstack *h; ! 175: int length; ! 176: { ! 177: register struct _obstack_chunk* old_chunk = h->chunk; ! 178: register struct _obstack_chunk* new_chunk; ! 179: register long new_size; ! 180: register int obj_size = h->next_free - h->object_base; ! 181: register int i; ! 182: int already; ! 183: ! 184: /* Compute size for new chunk. */ ! 185: new_size = (obj_size + length) + (obj_size >> 3) + 100; ! 186: if (new_size < h->chunk_size) ! 187: new_size = h->chunk_size; ! 188: ! 189: /* Allocate and initialize the new chunk. */ ! 190: new_chunk = h->chunk = CALL_CHUNKFUN (h, new_size); ! 191: new_chunk->prev = old_chunk; ! 192: new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; ! 193: ! 194: /* Move the existing object to the new chunk. ! 195: Word at a time is fast and is safe if the object ! 196: is sufficiently aligned. */ ! 197: if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) ! 198: { ! 199: for (i = obj_size / sizeof (COPYING_UNIT) - 1; ! 200: i >= 0; i--) ! 201: ((COPYING_UNIT *)new_chunk->contents)[i] ! 202: = ((COPYING_UNIT *)h->object_base)[i]; ! 203: /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, ! 204: but that can cross a page boundary on a machine ! 205: which does not do strict alignment for COPYING_UNITS. */ ! 206: already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); ! 207: } ! 208: else ! 209: already = 0; ! 210: /* Copy remaining bytes one by one. */ ! 211: for (i = already; i < obj_size; i++) ! 212: new_chunk->contents[i] = h->object_base[i]; ! 213: ! 214: /* If the object just copied was the only data in OLD_CHUNK, ! 215: free that chunk and remove it from the chain. ! 216: But not if that chunk might contain an empty object. */ ! 217: if (h->object_base == old_chunk->contents && ! h->maybe_empty_object) ! 218: { ! 219: new_chunk->prev = old_chunk->prev; ! 220: CALL_FREEFUN (h, old_chunk); ! 221: } ! 222: ! 223: h->object_base = new_chunk->contents; ! 224: h->next_free = h->object_base + obj_size; ! 225: /* The new chunk certainly contains no empty object yet. */ ! 226: h->maybe_empty_object = 0; ! 227: } ! 228: ! 229: /* Return nonzero if object OBJ has been allocated from obstack H. ! 230: This is here for debugging. ! 231: If you use it in a program, you are probably losing. */ ! 232: ! 233: int ! 234: _obstack_allocated_p (h, obj) ! 235: struct obstack *h; ! 236: POINTER obj; ! 237: { ! 238: register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ ! 239: register struct _obstack_chunk* plp; /* point to previous chunk if any */ ! 240: ! 241: lp = (h)->chunk; ! 242: /* We use >= rather than > since the object cannot be exactly at ! 243: the beginning of the chunk but might be an empty object exactly ! 244: at the end of an adjacent chunk. */ ! 245: while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) ! 246: { ! 247: plp = lp->prev; ! 248: lp = plp; ! 249: } ! 250: return lp != 0; ! 251: } ! 252: ! 253: /* Free objects in obstack H, including OBJ and everything allocate ! 254: more recently than OBJ. If OBJ is zero, free everything in H. */ ! 255: ! 256: #undef obstack_free ! 257: ! 258: /* This function has two names with identical definitions. ! 259: This is the first one, called from non-ANSI code. */ ! 260: ! 261: void ! 262: _obstack_free (h, obj) ! 263: struct obstack *h; ! 264: POINTER obj; ! 265: { ! 266: register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ ! 267: register struct _obstack_chunk* plp; /* point to previous chunk if any */ ! 268: ! 269: lp = h->chunk; ! 270: /* We use >= because there cannot be an object at the beginning of a chunk. ! 271: But there can be an empty object at that address ! 272: at the end of another chunk. */ ! 273: while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) ! 274: { ! 275: plp = lp->prev; ! 276: CALL_FREEFUN (h, lp); ! 277: lp = plp; ! 278: /* If we switch chunks, we can't tell whether the new current ! 279: chunk contains an empty object, so assume that it may. */ ! 280: h->maybe_empty_object = 1; ! 281: } ! 282: if (lp) ! 283: { ! 284: h->object_base = h->next_free = (char *)(obj); ! 285: h->chunk_limit = lp->limit; ! 286: h->chunk = lp; ! 287: } ! 288: else if (obj != 0) ! 289: /* obj is not in any of the chunks! */ ! 290: abort (); ! 291: } ! 292: ! 293: /* This function is used from ANSI code. */ ! 294: ! 295: void ! 296: obstack_free (h, obj) ! 297: struct obstack *h; ! 298: POINTER obj; ! 299: { ! 300: register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ ! 301: register struct _obstack_chunk* plp; /* point to previous chunk if any */ ! 302: ! 303: lp = h->chunk; ! 304: /* We use >= because there cannot be an object at the beginning of a chunk. ! 305: But there can be an empty object at that address ! 306: at the end of another chunk. */ ! 307: while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) ! 308: { ! 309: plp = lp->prev; ! 310: CALL_FREEFUN (h, lp); ! 311: lp = plp; ! 312: /* If we switch chunks, we can't tell whether the new current ! 313: chunk contains an empty object, so assume that it may. */ ! 314: h->maybe_empty_object = 1; ! 315: } ! 316: if (lp) ! 317: { ! 318: h->object_base = h->next_free = (char *)(obj); ! 319: h->chunk_limit = lp->limit; ! 320: h->chunk = lp; ! 321: } ! 322: else if (obj != 0) ! 323: /* obj is not in any of the chunks! */ ! 324: abort (); ! 325: } ! 326: ! 327: #if 0 ! 328: /* These are now turned off because the applications do not use it ! 329: and it uses bcopy via obstack_grow, which causes trouble on sysV. */ ! 330: ! 331: /* Now define the functional versions of the obstack macros. ! 332: Define them to simply use the corresponding macros to do the job. */ ! 333: ! 334: #ifdef __STDC__ ! 335: /* These function definitions do not work with non-ANSI preprocessors; ! 336: they won't pass through the macro names in parentheses. */ ! 337: ! 338: /* The function names appear in parentheses in order to prevent ! 339: the macro-definitions of the names from being expanded there. */ ! 340: ! 341: POINTER (obstack_base) (obstack) ! 342: struct obstack *obstack; ! 343: { ! 344: return obstack_base (obstack); ! 345: } ! 346: ! 347: POINTER (obstack_next_free) (obstack) ! 348: struct obstack *obstack; ! 349: { ! 350: return obstack_next_free (obstack); ! 351: } ! 352: ! 353: int (obstack_object_size) (obstack) ! 354: struct obstack *obstack; ! 355: { ! 356: return obstack_object_size (obstack); ! 357: } ! 358: ! 359: int (obstack_room) (obstack) ! 360: struct obstack *obstack; ! 361: { ! 362: return obstack_room (obstack); ! 363: } ! 364: ! 365: void (obstack_grow) (obstack, pointer, length) ! 366: struct obstack *obstack; ! 367: POINTER pointer; ! 368: int length; ! 369: { ! 370: obstack_grow (obstack, pointer, length); ! 371: } ! 372: ! 373: void (obstack_grow0) (obstack, pointer, length) ! 374: struct obstack *obstack; ! 375: POINTER pointer; ! 376: int length; ! 377: { ! 378: obstack_grow0 (obstack, pointer, length); ! 379: } ! 380: ! 381: void (obstack_1grow) (obstack, character) ! 382: struct obstack *obstack; ! 383: int character; ! 384: { ! 385: obstack_1grow (obstack, character); ! 386: } ! 387: ! 388: void (obstack_blank) (obstack, length) ! 389: struct obstack *obstack; ! 390: int length; ! 391: { ! 392: obstack_blank (obstack, length); ! 393: } ! 394: ! 395: void (obstack_1grow_fast) (obstack, character) ! 396: struct obstack *obstack; ! 397: int character; ! 398: { ! 399: obstack_1grow_fast (obstack, character); ! 400: } ! 401: ! 402: void (obstack_blank_fast) (obstack, length) ! 403: struct obstack *obstack; ! 404: int length; ! 405: { ! 406: obstack_blank_fast (obstack, length); ! 407: } ! 408: ! 409: POINTER (obstack_finish) (obstack) ! 410: struct obstack *obstack; ! 411: { ! 412: return obstack_finish (obstack); ! 413: } ! 414: ! 415: POINTER (obstack_alloc) (obstack, length) ! 416: struct obstack *obstack; ! 417: int length; ! 418: { ! 419: return obstack_alloc (obstack, length); ! 420: } ! 421: ! 422: POINTER (obstack_copy) (obstack, pointer, length) ! 423: struct obstack *obstack; ! 424: POINTER pointer; ! 425: int length; ! 426: { ! 427: return obstack_copy (obstack, pointer, length); ! 428: } ! 429: ! 430: POINTER (obstack_copy0) (obstack, pointer, length) ! 431: struct obstack *obstack; ! 432: POINTER pointer; ! 433: int length; ! 434: { ! 435: return obstack_copy0 (obstack, pointer, length); ! 436: } ! 437: ! 438: #endif /* __STDC__ */ ! 439: ! 440: #endif /* 0 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.