static void find_stack_direction() { 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. */ } }
static void find_stack_direction (/* void */) { 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 */ }
static void find_stack_direction (char **ptr) { auto char dummy; /* To get stack address. */ if (*ptr == NULL) { /* Initial entry. */ *ptr = ADDRESS_FUNCTION (dummy); find_stack_direction (ptr); /* Recurse once. */ } else { /* Second entry. */ if (ADDRESS_FUNCTION (dummy) > *ptr) stack_dir = 1; /* Stack grew upward. */ else stack_dir = -1; /* Stack grew downward. */ } }
void * alloca (unsigned size) { 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 (); #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. */ 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; free ((void *) hp); /* Collect garbage. */ hp = np; /* -> next header. */ } else break; /* Rest are not deeper. */ last_alloca_header = hp; /* -> last valid storage. */ } if (size == 0) return NULL; /* No allocation required. */ /* Allocate combined header + user data storage. */ { register void * newptr = malloc (sizeof (header) + size); /* Address of header. */ ((header *) newptr)->h.next = last_alloca_header; ((header *) newptr)->h.deep = depth; last_alloca_header = (header *) newptr; /* User storage begins just after header. */ return (void *) ((char *) newptr + sizeof (header)); } }