1 
2 #ifdef __STDC__
3 #include <stdlib.h>
4 #else
5 #include <memory.h>
6 #include <string.h>
7 #endif
8 
9 #if defined(__TINYC__) || defined(__HP_cc)
10 typedef union mem_cell
11 {
12    union mem_cell *next;	/* A pointer to the next mem */
13    unsigned int size;		/* An int >= sizeof pointer */
14    char *depth;			/* For the alloca hack */
15 }
16 mem;
17 
18 #define m_size(p)  ((p) [0].size)	/* For malloc */
19 #define m_next(p)  ((p) [1].next)	/* For malloc and alloca */
20 #define m_deep(p)  ((p) [0].depth)	/* For alloca */
21 
22 static mem *alloca_stack = 0;
23 
24 void *
alloca(size)25 alloca(size)
26 size_t size;
27 {
28    auto char probe;		/* Probes stack depth: */
29    register mem *hp;
30 
31    /*
32     * Reclaim garbage, defined as all alloca'd storage that was allocated
33     * from deeper in the stack than currently.
34     */
35 
36    for (hp = alloca_stack; hp != 0;)
37       if (m_deep(hp) < &probe)
38       {
39 	 register mem *np = m_next(hp);
40 	 free((void *) hp);	/* Collect garbage.  */
41 	 hp = np;		/* -> next header.  */
42       }
43       else
44 	 break;			/* Rest are not deeper.  */
45 
46    alloca_stack = hp;		/* -> last valid storage.  */
47    if (size == 0)
48       return 0;			/* No allocation required.  */
49 
50    hp = (mem *) malloc(sizeof(mem)*2 + size);
51    if (hp == 0)
52       return hp;
53 
54    m_next(hp) = alloca_stack;
55    m_deep(hp) = &probe;
56    alloca_stack = hp;
57 
58    /* User storage begins just after header.  */
59    return (void *) (hp + 2);
60 }
61 #endif
62