Annotation of coherent/g/usr/bin/gzip/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: #ifndef alloca  /* If compiling with GCC, this file's not needed.  */
        !            49: 
        !            50: #ifdef __STDC__
        !            51: typedef void   *pointer;               /* generic pointer type */
        !            52: #else
        !            53: typedef char   *pointer;               /* generic pointer type */
        !            54: #endif
        !            55: 
        !            56: #define        NULL    0                       /* null pointer constant */
        !            57: 
        !            58: extern void    free();
        !            59: extern pointer xmalloc();
        !            60: 
        !            61: /*
        !            62:        Define STACK_DIRECTION if you know the direction of stack
        !            63:        growth for your system; otherwise it will be automatically
        !            64:        deduced at run-time.
        !            65: 
        !            66:        STACK_DIRECTION > 0 => grows toward higher addresses
        !            67:        STACK_DIRECTION < 0 => grows toward lower addresses
        !            68:        STACK_DIRECTION = 0 => direction of growth unknown
        !            69: */
        !            70: 
        !            71: #ifndef STACK_DIRECTION
        !            72: #define        STACK_DIRECTION 0               /* direction unknown */
        !            73: #endif
        !            74: 
        !            75: #if STACK_DIRECTION != 0
        !            76: 
        !            77: #define        STACK_DIR       STACK_DIRECTION /* known at compile-time */
        !            78: 
        !            79: #else  /* STACK_DIRECTION == 0; need run-time code */
        !            80: 
        !            81: static int     stack_dir;              /* 1 or -1 once known */
        !            82: #define        STACK_DIR       stack_dir
        !            83: 
        !            84: static void
        !            85: find_stack_direction (/* void */)
        !            86: {
        !            87:   static char  *addr = NULL;   /* address of first
        !            88:                                   `dummy', once known */
        !            89:   auto char    dummy;          /* to get stack address */
        !            90: 
        !            91:   if (addr == NULL)
        !            92:     {                          /* initial entry */
        !            93:       addr = &dummy;
        !            94: 
        !            95:       find_stack_direction (); /* recurse once */
        !            96:     }
        !            97:   else                         /* second entry */
        !            98:     if (&dummy > addr)
        !            99:       stack_dir = 1;           /* stack grew upward */
        !           100:     else
        !           101:       stack_dir = -1;          /* stack grew downward */
        !           102: }
        !           103: 
        !           104: #endif /* STACK_DIRECTION == 0 */
        !           105: 
        !           106: /*
        !           107:        An "alloca header" is used to:
        !           108:        (a) chain together all alloca()ed blocks;
        !           109:        (b) keep track of stack depth.
        !           110: 
        !           111:        It is very important that sizeof(header) agree with malloc()
        !           112:        alignment chunk size.  The following default should work okay.
        !           113: */
        !           114: 
        !           115: #ifndef        ALIGN_SIZE
        !           116: #define        ALIGN_SIZE      sizeof(double)
        !           117: #endif
        !           118: 
        !           119: typedef union hdr
        !           120: {
        !           121:   char align[ALIGN_SIZE];      /* to force sizeof(header) */
        !           122:   struct
        !           123:     {
        !           124:       union hdr *next;         /* for chaining headers */
        !           125:       char *deep;              /* for stack depth measure */
        !           126:     } h;
        !           127: } header;
        !           128: 
        !           129: /*
        !           130:        alloca( size ) returns a pointer to at least `size' bytes of
        !           131:        storage which will be automatically reclaimed upon exit from
        !           132:        the procedure that called alloca().  Originally, this space
        !           133:        was supposed to be taken from the current stack frame of the
        !           134:        caller, but that method cannot be made to work for some
        !           135:        implementations of C, for example under Gould's UTX/32.
        !           136: */
        !           137: 
        !           138: static header *last_alloca_header = NULL; /* -> last alloca header */
        !           139: 
        !           140: pointer
        !           141: alloca (size)                  /* returns pointer to storage */
        !           142:      unsigned  size;           /* # bytes to allocate */
        !           143: {
        !           144:   auto char    probe;          /* probes stack depth: */
        !           145:   register char        *depth = &probe;
        !           146: 
        !           147: #if STACK_DIRECTION == 0
        !           148:   if (STACK_DIR == 0)          /* unknown growth direction */
        !           149:     find_stack_direction ();
        !           150: #endif
        !           151: 
        !           152:                                /* Reclaim garbage, defined as all alloca()ed storage that
        !           153:                                   was allocated from deeper in the stack than currently. */
        !           154: 
        !           155:   {
        !           156:     register header    *hp;    /* traverses linked list */
        !           157: 
        !           158:     for (hp = last_alloca_header; hp != NULL;)
        !           159:       if ((STACK_DIR > 0 && hp->h.deep > depth)
        !           160:          || (STACK_DIR < 0 && hp->h.deep < depth))
        !           161:        {
        !           162:          register header       *np = hp->h.next;
        !           163: 
        !           164:          free ((pointer) hp);  /* collect garbage */
        !           165: 
        !           166:          hp = np;              /* -> next header */
        !           167:        }
        !           168:       else
        !           169:        break;                  /* rest are not deeper */
        !           170: 
        !           171:     last_alloca_header = hp;   /* -> last valid storage */
        !           172:   }
        !           173: 
        !           174:   if (size == 0)
        !           175:     return NULL;               /* no allocation required */
        !           176: 
        !           177:   /* Allocate combined header + user data storage. */
        !           178: 
        !           179:   {
        !           180:     register pointer   new = xmalloc (sizeof (header) + size);
        !           181:     /* address of header */
        !           182: 
        !           183:     ((header *)new)->h.next = last_alloca_header;
        !           184:     ((header *)new)->h.deep = depth;
        !           185: 
        !           186:     last_alloca_header = (header *)new;
        !           187: 
        !           188:     /* User storage begins just after header. */
        !           189: 
        !           190:     return (pointer)((char *)new + sizeof(header));
        !           191:   }
        !           192: }
        !           193: 
        !           194: #endif /* no alloca */

unix.superglobalmegacorp.com

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