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