home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / CLIPPER / MISC / AWK.ZIP / OBSTACK.H < prev    next >
Encoding:
Text File  |  1988-09-09  |  9.2 KB  |  226 lines

  1. /**
  2.  * $Revision:   1.1  $
  3.  * $Log:   C:/AWK/OBSTACK.H_V  $
  4.  * 
  5.  *    Rev 1.1   09 Sep 1988 18:34:00   vince
  6.  * MC 5.1 version
  7.  * 
  8.  *    Rev 1.0   09 Sep 1988 18:03:54   vince
  9.  * Original source
  10.  *
  11.  *   obstack.h - object stack macros
  12.  *   Copyright (c) 1986 Free Software Foundation, Inc.
  13.  *
  14.  * Summary:
  15.  *
  16.  * All the apparent functions defined here are macros. The idea
  17.  * is that you would use these pre-tested macros to solve a
  18.  * very specific set of problems, and they would run fast.
  19.  * Caution: no side-effects in arguments please!! They may be
  20.  * evaluated MANY times!!
  21.  * 
  22.  * These macros operate a stack of objects.  Each object starts life
  23.  * small, and may grow to maturity.  (Consider building a word syllable
  24.  * by syllable.)  An object can move while it is growing.  Once it has
  25.  * been "finished" it never changes address again.  So the "top of the
  26.  * stack" is typically an immature growing object, while the rest of the
  27.  * stack is of mature, fixed size and fixed address objects.
  28.  * 
  29.  * These routines grab large chunks of memory, using a function you
  30.  * supply, called `obstack_chunk_alloc'.  On occasion, they free chunks,
  31.  * by calling `obstack_chunk_free'.  You must define them and declare
  32.  * them before using any obstack macros.
  33.  * 
  34.  * Each independent stack is represented by a `struct obstack'.
  35.  * Each of the obstack macros expects a pointer to such a structure
  36.  * as the first argument.
  37.  * 
  38.  * One motivation for this package is the problem of growing char strings
  39.  * in symbol tables.  Unless you are "facist pig with a read-only mind"
  40.  * [Gosper's immortal quote from HAKMEM item 154, out of context] you
  41.  * would not like to put any arbitrary upper limit on the length of your
  42.  * symbols.
  43.  * 
  44.  * In practice this often means you will build many short symbols and a
  45.  * few long symbols.  At the time you are reading a symbol you don't know
  46.  * how long it is.  One traditional method is to read a symbol into a
  47.  * buffer, realloc()ating the buffer every time you try to read a symbol
  48.  * that is longer than the buffer.  This is beaut, but you still will
  49.  * want to copy the symbol from the buffer to a more permanent
  50.  * symbol-table entry say about half the time.
  51.  * 
  52.  * With obstacks, you can work differently.  Use one obstack for all symbol
  53.  * names.  As you read a symbol, grow the name in the obstack gradually.
  54.  * When the name is complete, finalize it.  Then, if the symbol exists already,
  55.  * free the newly read name.
  56.  * 
  57.  * The way we do this is to take a large chunk, allocating memory from
  58.  * low addresses.  When you want to build a aymbol in the chunk you just
  59.  * add chars above the current "high water mark" in the chunk.  When you
  60.  * have finished adding chars, because you got to the end of the symbol,
  61.  * you know how long the chars are, and you can create a new object.
  62.  * Mostly the chars will not burst over the highest address of the chunk,
  63.  * because you would typically expect a chunk to be (say) 100 times as
  64.  * long as an average object.
  65.  * 
  66.  * In case that isn't clear, when we have enough chars to make up
  67.  * the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
  68.  * so we just point to it where it lies.  No moving of chars is
  69.  * needed and this is the second win: potentially long strings need
  70.  * never be explicitly shuffled. Once an object is formed, it does not
  71.  * change its address during its lifetime.
  72.  * 
  73.  * When the chars burst over a chunk boundary, we allocate a larger
  74.  * chunk, and then copy the partly formed object from the end of the old
  75.  * chunk to the beggining of the new larger chunk.  We then carry on
  76.  * accreting characters to the end of the object as we normaly would.
  77.  * 
  78.  * A special macro is provided to add a single char at a time to a
  79.  * growing object.  This allows the use of register variables, which
  80.  * break the ordinary 'growth' macro.
  81.  * 
  82.  * Summary:
  83.  *         We allocate large chunks.
  84.  *         We carve out one object at a time from the current chunk.
  85.  *         Once carved, an object never moves.
  86.  *         We are free to append data of any size to the currently
  87.  *           growing object.
  88.  *         Exactly one object is growing in an obstack at any one time.
  89.  *         You can run one obstack per control block.
  90.  *         You may have as many control blocks as you dare.
  91.  *         Because of the way we do it, you can `unwind' a obstack
  92.  *           back to a previous state. (You may remove objects much
  93.  *           as you would with a stack.)
  94.  * 
  95.  *    Modifications by Andrew D. Estes, July 1988
  96.  */
  97.  
  98. #ifndef obstackH
  99.  
  100. /* Added to allow large model under MSC -ADE- */
  101.  
  102. #if (defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM))
  103. #define INT long
  104. #else
  105. #define INT int
  106. #endif
  107.  
  108. #define obstackH
  109. /* these #defines keep it brief */
  110. #define _Ll struct obstack_chunk
  111. #define _LL (8) 
  112.  
  113. struct obstack_chunk                   /* Lives at front of each chunk. */
  114. {
  115.    char *obstack_l_limit;              /* 1 past end of this chunk */
  116.    _Ll *obstack_l_prev;                /* address of prior chunk or NULL */
  117.    char obstack_l_0[4];                /* objects begin here */
  118. };
  119.  
  120. #if 0
  121. This function, called like malloc but not returning on failure, must return a chunk of the size given to it as argument, aligned on a boundary of 2 ** OBSTACK_LOG_DEFAULT_ALIGNMENT bytes.
  122.  
  123. struct obstack_chunk *obstack_chunk_alloc();
  124. #endif
  125.  
  126. struct obstack                         /* control current object in current chunk */
  127. {
  128.    long chunk_size;                    /* preferred size to allocate chunks in */
  129.    _Ll *chunk;                         /* address of current struct obstack_chunk */
  130.    char *object_base;                  /* address of object we are building */
  131.    char *next_free;                    /* where to add next char to current object */
  132.    char *chunk_limit;                  /* address of char after current chunk */
  133.    INT temp;                           /* Temporary for some macros.  [was int -ADE-] */
  134.    int alignment_mask;                 /* Mask of alignment for each object. */
  135. };
  136.  
  137. /*
  138.  * Pointer to beginning of object being allocated or to be allocated next. Note that this
  139.  * might not be the final address of the object because a new chunk might be needed to
  140.  * hold the final size.  
  141.  */
  142.  
  143. #define obstack_base(h) ((h)->object_base)
  144.  
  145. /* Pointer to next byte not yet allocated in current chunk.  */
  146.  
  147. #define obstack_next_free(h) ((h)->next_free)
  148.  
  149. /* Size of object currently growing */
  150.  
  151. #define obstack_object_size(h)  ((h)->next_free - (h)->object_base)
  152.  
  153. /* Mask specifying low bits that should be clear in address of an object.  */
  154.  
  155. #define obstack_alignment_mask(h) ((h)->alignment_mask)
  156.  
  157. #define obstack_init(h) obstack_begin (h, 4096 - 4 - _LL)
  158.  
  159. #define obstack_begin(h,try_length)     \
  160. ((h)->chunk_size = (try_length) + (_LL),    \
  161.  (h)->alignment_mask = ((1 << 2) - 1),     \
  162.  _obstack_begin ((h), obstack_chunk_alloc))
  163.  
  164. #define obstack_grow(h,where,length)     \
  165. ( (h)->temp = (length),       \
  166.   (((h)->next_free + (h)->temp > (h)->chunk_limit)   \
  167.    ? _obstack_newchunk ((h), obstack_chunk_alloc, (h)->temp) : 0), \
  168.   bcopy (where, (h)->next_free, (h)->temp),    \
  169.   (h)->next_free += (h)->temp)
  170.  
  171. #define obstack_grow0(h,where,length)     \
  172. ( (h)->temp = (length),       \
  173.   (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit)   \
  174.    ? _obstack_newchunk ((h), obstack_chunk_alloc, (h)->temp + 1) : 0), \
  175.   bcopy (where, (h)->next_free, (h)->temp),    \
  176.   (h)->next_free += (h)->temp,      \
  177.   *((h)->next_free)++ = 0)
  178.  
  179. #define obstack_1grow(h,datum)      \
  180. ( (((h)->next_free + 1 > (h)->chunk_limit)    \
  181.    ? _obstack_newchunk ((h), obstack_chunk_alloc, (INT)1) : 0),   \
  182.   *((h)->next_free)++ = (datum))
  183.  
  184. #define obstack_blank(h,length)      \
  185. ( (h)->temp = (length),       \
  186.   (((h)->next_free + (h)->temp > (h)->chunk_limit)   \
  187.    ? _obstack_newchunk ((h), obstack_chunk_alloc, (h)->temp) : 0), \
  188.   (h)->next_free += (h)->temp)
  189.  
  190. #define obstack_alloc(h,length)      \
  191.  (obstack_blank ((h), (length)), obstack_finish (h))
  192.  
  193. #define obstack_copy(h,where,length)     \
  194.  (obstack_grow ((h), (where), (length)), obstack_finish (h))
  195.  
  196. #define obstack_copy0(h,where,length)     \
  197.  (obstack_grow0 ((h), (where), (length)), obstack_finish (h))
  198.  
  199. #define obstack_room(h) ((long unsigned int)    \
  200.  ((h)->chunk_limit - (h)->next_free))
  201.  
  202. #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
  203.  
  204. #define obstack_blank_fast(h,n) ((h)->next_free += (n))
  205.  
  206. #define obstack_finish(h)        \
  207.  ((h)->temp = (long) (h)->object_base,      \
  208.   (h)->next_free       \
  209.  = (char*)((long)((h)->next_free+(h)->alignment_mask)   \
  210.        & ~ ((h)->alignment_mask)),    \
  211.   (((h)->next_free - (char *)(h)->chunk     \
  212.     > (h)->chunk_limit - (char *)(h)->chunk)    \
  213.    ? (h)->next_free = (h)->chunk_limit : 0),    \
  214.   (h)->object_base = (h)->next_free,     \
  215.   (char *) (h)->temp)
  216.  
  217. #define obstack_free(h,obj)      \
  218. (((h)->temp = (char *)(obj) - (char *) (h)->chunk),   \
  219.  (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
  220.   ? (int) ((h)->next_free = (h)->object_base    \
  221.     = (h)->temp + (char *) (h)->chunk)    \
  222.   : (int) _obstack_free ((h), obstack_chunk_free,   \
  223.     (h)->temp + (char *) (h)->chunk)))
  224.  
  225. #endif
  226.