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