Annotation of researchv10dc/cmd/gcc/alloca.c, revision 1.1.1.1

1.1       root        1: /*
                      2:        alloca -- (mostly) portable public-domain implementation
                      3: 
                      4:        last edit:      86/01/26        D A Gwyn
                      5: 
                      6:        This implementation of the PWB library alloca() function,
                      7:        which is used to allocate space off the run-time stack so
                      8:        that it is automatically reclaimed upon procedure exit, 
                      9:        was inspired by discussions with J. Q. Johnson of Cornell.
                     10: 
                     11:        It should work under any C implementation that uses an
                     12:        actual procedure stack (as opposed to a linked list of
                     13:        frames).  There are some preprocessor constants that can
                     14:        be defined when compiling for your specific system, for
                     15:        improved efficiency; however, the defaults should be okay.
                     16: 
                     17:        The general concept of this implementation is to keep
                     18:        track of all alloca()-allocated blocks, and reclaim any
                     19:        that are found to be deeper in the stack than the current
                     20:        invocation.  This heuristic does not reclaim storage as
                     21:        soon as it becomes invalid, but it will do so eventually.
                     22: 
                     23:        As a special case, alloca(0) reclaims storage without
                     24:        allocating any.  It is a good idea to use alloca(0) in
                     25:        your main control loop, etc. to force garbage collection.
                     26: */
                     27: #ifndef lint
                     28: static char    SCCSid[] = "@(#)alloca.c        1.1";   /* for the "what" utility */
                     29: #endif
                     30: 
                     31: #ifdef X3J11
                     32: typedef void   *pointer;               /* generic pointer type */
                     33: #else
                     34: typedef char   *pointer;               /* generic pointer type */
                     35: #endif
                     36: 
                     37: #define        NULL    0                       /* null pointer constant */
                     38: 
                     39: extern void    free();
                     40: extern pointer xmalloc();
                     41: 
                     42: /*
                     43:        Define STACK_DIRECTION if you know the direction of stack
                     44:        growth for your system; otherwise it will be automatically
                     45:        deduced at run-time.
                     46: 
                     47:        STACK_DIRECTION > 0 => grows toward higher addresses
                     48:        STACK_DIRECTION < 0 => grows toward lower addresses
                     49:        STACK_DIRECTION = 0 => direction of growth unknown
                     50: */
                     51: 
                     52: #ifndef STACK_DIRECTION
                     53: #define        STACK_DIRECTION 0               /* direction unknown */
                     54: #endif
                     55: 
                     56: #if STACK_DIRECTION != 0
                     57: 
                     58: #define        STACK_DIR       STACK_DIRECTION /* known at compile-time */
                     59: 
                     60: #else  /* STACK_DIRECTION == 0; need run-time code */
                     61: 
                     62: static int     stack_dir;              /* 1 or -1 once known */
                     63: #define        STACK_DIR       stack_dir
                     64: 
                     65: static void
                     66: find_stack_direction (/* void */)
                     67: {
                     68:   static char  *addr = NULL;   /* address of first
                     69:                                   `dummy', once known */
                     70:   auto char    dummy;          /* to get stack address */
                     71: 
                     72:   if (addr == NULL)
                     73:     {                          /* initial entry */
                     74:       addr = &dummy;
                     75: 
                     76:       find_stack_direction (); /* recurse once */
                     77:     }
                     78:   else                         /* second entry */
                     79:     if (&dummy > addr)
                     80:       stack_dir = 1;           /* stack grew upward */
                     81:     else
                     82:       stack_dir = -1;          /* stack grew downward */
                     83: }
                     84: 
                     85: #endif /* STACK_DIRECTION == 0 */
                     86: 
                     87: /*
                     88:        An "alloca header" is used to:
                     89:        (a) chain together all alloca()ed blocks;
                     90:        (b) keep track of stack depth.
                     91: 
                     92:        It is very important that sizeof(header) agree with malloc()
                     93:        alignment chunk size.  The following default should work okay.
                     94: */
                     95: 
                     96: #ifndef        ALIGN_SIZE
                     97: #define        ALIGN_SIZE      sizeof(double)
                     98: #endif
                     99: 
                    100: typedef union hdr
                    101: {
                    102:   char align[ALIGN_SIZE];      /* to force sizeof(header) */
                    103:   struct
                    104:     {
                    105:       union hdr *next;         /* for chaining headers */
                    106:       char *deep;              /* for stack depth measure */
                    107:     } h;
                    108: } header;
                    109: 
                    110: /*
                    111:        alloca( size ) returns a pointer to at least `size' bytes of
                    112:        storage which will be automatically reclaimed upon exit from
                    113:        the procedure that called alloca().  Originally, this space
                    114:        was supposed to be taken from the current stack frame of the
                    115:        caller, but that method cannot be made to work for some
                    116:        implementations of C, for example under Gould's UTX/32.
                    117: */
                    118: 
                    119: pointer
                    120: alloca (size)                          /* returns pointer to storage */
                    121:      unsigned  size;           /* # bytes to allocate */
                    122: {
                    123:   static header        *last = NULL;   /* -> last alloca header */
                    124:   auto char    probe;          /* probes stack depth: */
                    125:   register char        *depth = &probe;
                    126: 
                    127: #if STACK_DIRECTION == 0
                    128:   if (STACK_DIR == 0)          /* unknown growth direction */
                    129:     find_stack_direction ();
                    130: #endif
                    131: 
                    132:                                /* Reclaim garbage, defined as all alloca()ed storage that
                    133:                                   was allocated from deeper in the stack than currently. */
                    134: 
                    135:   {
                    136:     register header    *hp;    /* traverses linked list */
                    137: 
                    138:     for (hp = last; hp != NULL;)
                    139:       if (STACK_DIR > 0 && hp->h.deep > depth
                    140:          || STACK_DIR < 0 && hp->h.deep < depth)
                    141:        {
                    142:          register header       *np = hp->h.next;
                    143: 
                    144:          free ((pointer) hp);  /* collect garbage */
                    145: 
                    146:          hp = np;              /* -> next header */
                    147:        }
                    148:       else
                    149:        break;                  /* rest are not deeper */
                    150: 
                    151:     last = hp;                 /* -> last valid storage */
                    152:   }
                    153: 
                    154:   if (size == 0)
                    155:     return NULL;               /* no allocation required */
                    156: 
                    157:   /* Allocate combined header + user data storage. */
                    158: 
                    159:   {
                    160:     register pointer   new = xmalloc (sizeof (header) + size);
                    161:     /* address of header */
                    162: 
                    163:     ((header *)new)->h.next = last;
                    164:     ((header *)new)->h.deep = depth;
                    165: 
                    166:     last = (header *)new;
                    167: 
                    168:     /* User storage begins just after header. */
                    169: 
                    170:     return (pointer)((char *)new + sizeof(header));
                    171:   }
                    172: }
                    173: 
                    174: /* like malloc and realloc but check for no memory left */
                    175: /*
                    176: pointer
                    177: xmalloc (size)
                    178:      int size;
                    179: {
                    180:   pointer val = (pointer) malloc (size);
                    181:   if (!val) memory_full ();
                    182:   return val;
                    183: }
                    184: 
                    185: pointer
                    186: xrealloc (block, size)
                    187:      long *block;
                    188:      int size;
                    189: {
                    190:   pointer val = (pointer) realloc (block, size);
                    191:   if (!val) memory_full ();
                    192:   return val;
                    193: }
                    194: memory_full ()
                    195: {
                    196:   error ("Memory exhausted");
                    197: }
                    198: */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.