X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Falloca.c;h=ee0f01886826ad9dcba250aad66fe7bc25c06213;hb=8e0f64e4cd12f7779113bc438afd106dad3e1f1a;hp=3a1f4e273a56b8f4f65e39c35577a1826343de24;hpb=0632e115747ff96e93330c88f536d7354a7ce507;p=gnulib.git diff --git a/lib/alloca.c b/lib/alloca.c index 3a1f4e273..ee0f01886 100644 --- a/lib/alloca.c +++ b/lib/alloca.c @@ -81,38 +81,27 @@ long i00afunc (); STACK_DIRECTION = 0 => direction of growth unknown */ # ifndef STACK_DIRECTION -# define STACK_DIRECTION 0 /* Direction unknown. */ +# define STACK_DIRECTION 0 /* Direction unknown. */ # endif # if STACK_DIRECTION != 0 -# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ +# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ # else /* STACK_DIRECTION == 0; need run-time code. */ -static int stack_dir; /* 1 or -1 once known. */ -# define STACK_DIR stack_dir +static int stack_dir; /* 1 or -1 once known. */ +# define STACK_DIR stack_dir -static void -find_stack_direction (void) +static int +find_stack_direction (int *addr, int depth) { - static char *addr = NULL; /* Address of first `dummy', once known. */ - auto char dummy; /* To get stack address. */ - - if (addr == NULL) - { /* Initial entry. */ - addr = ADDRESS_FUNCTION (dummy); - - find_stack_direction (); /* Recurse once. */ - } - else - { - /* Second entry. */ - if (ADDRESS_FUNCTION (dummy) > addr) - stack_dir = 1; /* Stack grew upward. */ - else - stack_dir = -1; /* Stack grew downward. */ - } + int dir, dummy = 0; + if (! addr) + addr = &dummy; + *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; + dir = depth ? find_stack_direction (addr, depth - 1) : 0; + return dir + dummy; } # endif /* STACK_DIRECTION == 0 */ @@ -124,21 +113,21 @@ find_stack_direction (void) It is very important that sizeof(header) agree with malloc alignment chunk size. The following default should work okay. */ -# ifndef ALIGN_SIZE -# define ALIGN_SIZE sizeof(double) +# ifndef ALIGN_SIZE +# define ALIGN_SIZE sizeof(double) # endif typedef union hdr { - char align[ALIGN_SIZE]; /* To force sizeof(header). */ + char align[ALIGN_SIZE]; /* To force sizeof(header). */ struct { - union hdr *next; /* For chaining headers. */ - char *deep; /* For stack depth measure. */ + union hdr *next; /* For chaining headers. */ + char *deep; /* For stack depth measure. */ } h; } header; -static header *last_alloca_header = NULL; /* -> last alloca header. */ +static header *last_alloca_header = NULL; /* -> last alloca header. */ /* Return a pointer to at least SIZE bytes of storage, which will be automatically reclaimed upon exit from @@ -150,19 +139,19 @@ static header *last_alloca_header = NULL; /* -> last alloca header. */ void * alloca (size_t size) { - auto char probe; /* Probes stack depth: */ + auto char probe; /* Probes stack depth: */ register char *depth = ADDRESS_FUNCTION (probe); # if STACK_DIRECTION == 0 - if (STACK_DIR == 0) /* Unknown growth direction. */ - find_stack_direction (); + if (STACK_DIR == 0) /* Unknown growth direction. */ + STACK_DIR = find_stack_direction (NULL, (size & 1) + 20); # endif /* Reclaim garbage, defined as all alloca'd storage that was allocated from deeper in the stack than currently. */ { - register header *hp; /* Traverses linked list. */ + register header *hp; /* Traverses linked list. */ # ifdef emacs BLOCK_INPUT; @@ -170,18 +159,18 @@ alloca (size_t size) for (hp = last_alloca_header; hp != NULL;) if ((STACK_DIR > 0 && hp->h.deep > depth) - || (STACK_DIR < 0 && hp->h.deep < depth)) - { - register header *np = hp->h.next; + || (STACK_DIR < 0 && hp->h.deep < depth)) + { + register header *np = hp->h.next; - free (hp); /* Collect garbage. */ + free (hp); /* Collect garbage. */ - hp = np; /* -> next header. */ - } + hp = np; /* -> next header. */ + } else - break; /* Rest are not deeper. */ + break; /* Rest are not deeper. */ - last_alloca_header = hp; /* -> last valid storage. */ + last_alloca_header = hp; /* -> last valid storage. */ # ifdef emacs UNBLOCK_INPUT; @@ -189,7 +178,7 @@ alloca (size_t size) } if (size == 0) - return NULL; /* No allocation required. */ + return NULL; /* No allocation required. */ /* Allocate combined header + user data storage. */ @@ -229,10 +218,10 @@ alloca (size_t size) /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ struct stack_control_header { - long shgrow:32; /* Number of times stack has grown. */ - long shaseg:32; /* Size of increments to stack. */ - long shhwm:32; /* High water mark of stack. */ - long shsize:32; /* Current size of stack (all segments). */ + long shgrow:32; /* Number of times stack has grown. */ + long shaseg:32; /* Size of increments to stack. */ + long shhwm:32; /* High water mark of stack. */ + long shsize:32; /* Current size of stack (all segments). */ }; /* The stack segment linkage control information occurs at @@ -244,21 +233,21 @@ struct stack_control_header struct stack_segment_linkage { - long ss[0200]; /* 0200 overflow words. */ - long sssize:32; /* Number of words in this segment. */ - long ssbase:32; /* Offset to stack base. */ + long ss[0200]; /* 0200 overflow words. */ + long sssize:32; /* Number of words in this segment. */ + long ssbase:32; /* Offset to stack base. */ long:32; - long sspseg:32; /* Offset to linkage control of previous - segment of stack. */ + long sspseg:32; /* Offset to linkage control of previous + segment of stack. */ long:32; - long sstcpt:32; /* Pointer to task common address block. */ - long sscsnm; /* Private control structure number for - microtasking. */ - long ssusr1; /* Reserved for user. */ - long ssusr2; /* Reserved for user. */ - long sstpid; /* Process ID for pid based multi-tasking. */ - long ssgvup; /* Pointer to multitasking thread giveup. */ - long sscray[7]; /* Reserved for Cray Research. */ + long sstcpt:32; /* Pointer to task common address block. */ + long sscsnm; /* Private control structure number for + microtasking. */ + long ssusr1; /* Reserved for user. */ + long ssusr2; /* Reserved for user. */ + long sstpid; /* Process ID for pid based multi-tasking. */ + long ssgvup; /* Pointer to multitasking thread giveup. */ + long sscray[7]; /* Reserved for Cray Research. */ long ssa0; long ssa1; long ssa2; @@ -282,27 +271,27 @@ struct stack_segment_linkage returned by the STKSTAT library routine. */ struct stk_stat { - long now; /* Current total stack size. */ - long maxc; /* Amount of contiguous space which would - be required to satisfy the maximum - stack demand to date. */ - long high_water; /* Stack high-water mark. */ - long overflows; /* Number of stack overflow ($STKOFEN) calls. */ - long hits; /* Number of internal buffer hits. */ - long extends; /* Number of block extensions. */ - long stko_mallocs; /* Block allocations by $STKOFEN. */ - long underflows; /* Number of stack underflow calls ($STKRETN). */ - long stko_free; /* Number of deallocations by $STKRETN. */ - long stkm_free; /* Number of deallocations by $STKMRET. */ - long segments; /* Current number of stack segments. */ - long maxs; /* Maximum number of stack segments so far. */ - long pad_size; /* Stack pad size. */ - long current_address; /* Current stack segment address. */ - long current_size; /* Current stack segment size. This - number is actually corrupted by STKSTAT to - include the fifteen word trailer area. */ - long initial_address; /* Address of initial segment. */ - long initial_size; /* Size of initial segment. */ + long now; /* Current total stack size. */ + long maxc; /* Amount of contiguous space which would + be required to satisfy the maximum + stack demand to date. */ + long high_water; /* Stack high-water mark. */ + long overflows; /* Number of stack overflow ($STKOFEN) calls. */ + long hits; /* Number of internal buffer hits. */ + long extends; /* Number of block extensions. */ + long stko_mallocs; /* Block allocations by $STKOFEN. */ + long underflows; /* Number of stack underflow calls ($STKRETN). */ + long stko_free; /* Number of deallocations by $STKRETN. */ + long stkm_free; /* Number of deallocations by $STKMRET. */ + long segments; /* Current number of stack segments. */ + long maxs; /* Maximum number of stack segments so far. */ + long pad_size; /* Stack pad size. */ + long current_address; /* Current stack segment address. */ + long current_size; /* Current stack segment size. This + number is actually corrupted by STKSTAT to + include the fifteen word trailer area. */ + long initial_address; /* Address of initial segment. */ + long initial_size; /* Size of initial segment. */ }; /* The following structure describes the data structure which trails @@ -311,13 +300,13 @@ struct stk_stat struct stk_trailer { - long this_address; /* Address of this block. */ - long this_size; /* Size of this block (does not include - this trailer). */ + long this_address; /* Address of this block. */ + long this_size; /* Size of this block (does not include + this trailer). */ long unknown2; long unknown3; - long link; /* Address of trailer block of previous - segment. */ + long link; /* Address of trailer block of previous + segment. */ long unknown5; long unknown6; long unknown7; @@ -355,8 +344,8 @@ i00afunc (long *address) /* Set up the iteration. */ trailer = (struct stk_trailer *) (status.current_address - + status.current_size - - 15); + + status.current_size + - 15); /* There must be at least one stack segment. Therefore it is a fatal error if "trailer" is null. */ @@ -371,10 +360,10 @@ i00afunc (long *address) block = (long *) trailer->this_address; size = trailer->this_size; if (block == 0 || size == 0) - abort (); + abort (); trailer = (struct stk_trailer *) trailer->link; if ((block <= address) && (address < (block + size))) - break; + break; } /* Set the result to the offset in this segment and add the sizes @@ -390,7 +379,7 @@ i00afunc (long *address) do { if (trailer->this_size <= 0) - abort (); + abort (); result += trailer->this_size; trailer = (struct stk_trailer *) trailer->link; } @@ -453,7 +442,7 @@ i00afunc (long address) fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); # endif if (pseg == 0) - break; + break; stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; @@ -486,4 +475,4 @@ i00afunc (long address) # endif /* CRAY */ # endif /* no alloca */ -#endif /* not GCC version 2 */ +#endif /* not GCC 2 */