Annotation of 43BSDReno/contrib/emacs-18.55/src/alloca.c, revision 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.