Annotation of 43BSDReno/contrib/emacs-18.55/src/alloca.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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