source: Sophya/trunk/SophyaLib/UnixMac/src/alloca.c@ 4086

Last change on this file since 4086 was 683, checked in by ansari, 26 years ago

Compilation Mac pour CodeWarrior PRO 5

File size: 5.8 KB
Line 
1/* $Id: alloca.c,v 1.1 1999-12-10 17:11:19 ansari Exp $ */
2
3/*
4 alloca -- (mostly) portable public-domain implementation -- D A Gwyn
5
6 last edit: 86/05/30 rms
7 include config.h, since on VMS it renames some symbols.
8 Use xmalloc instead of malloc.
9
10 This implementation of the PWB library alloca() function,
11 which is used to allocate space off the run-time stack so
12 that it is automatically reclaimed upon procedure exit,
13 was inspired by discussions with J. Q. Johnson of Cornell.
14
15 It should work under any C implementation that uses an
16 actual procedure stack (as opposed to a linked list of
17 frames). There are some preprocessor constants that can
18 be defined when compiling for your specific system, for
19 improved efficiency; however, the defaults should be okay.
20
21 The general concept of this implementation is to keep
22 track of all alloca()-allocated blocks, and reclaim any
23 that are found to be deeper in the stack than the current
24 invocation. This heuristic does not reclaim storage as
25 soon as it becomes invalid, but it will do so eventually.
26
27 As a special case, alloca(0) reclaims storage without
28 allocating any. It is a good idea to use alloca(0) in
29 your main control loop, etc. to force garbage collection.
30*/
31#ifndef lint
32static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
33#endif
34
35#ifdef __MWERKS__
36#pragma once
37#include <stdlib.h>
38#include "alloca.h"
39void *alloca (unsigned);
40static void *xmalloc (unsigned);
41#endif /* THINK_C */
42
43#include <stdio.h>
44
45#ifdef emacs
46#include "config.h"
47/* THINK_C chokes on following line, even though emacs is not defined
48#ifdef static
49*/
50/* actually, only want this if static is defined as ""
51 -- this is for usg, in which emacs must undefine static
52 in order to make unexec workable
53 */
54#ifndef STACK_DIRECTION
55you
56lose
57-- must know STACK_DIRECTION at compile-time
58#endif /* STACK_DIRECTION undefined */
59/*
60#endif /* static */
61#endif /* emacs */
62
63#ifndef alloca /* If compiling with GCC, this file's not needed. */
64
65#ifdef __STDC__
66typedef void *pointer; /* generic pointer type */
67#else
68typedef char *pointer; /* generic pointer type */
69#endif
70
71#ifndef NULL
72#define NULL 0 /* null pointer constant */
73#endif
74
75extern void free();
76extern pointer xmalloc();
77
78/*
79 Define STACK_DIRECTION if you know the direction of stack
80 growth for your system; otherwise it will be automatically
81 deduced at run-time.
82
83 STACK_DIRECTION > 0 => grows toward higher addresses
84 STACK_DIRECTION < 0 => grows toward lower addresses
85 STACK_DIRECTION = 0 => direction of growth unknown
86*/
87
88#ifndef STACK_DIRECTION
89#define STACK_DIRECTION 0 /* direction unknown */
90#endif
91
92#if STACK_DIRECTION != 0
93
94#define STACK_DIR STACK_DIRECTION /* known at compile-time */
95
96#else /* STACK_DIRECTION == 0; need run-time code */
97
98static int stack_dir; /* 1 or -1 once known */
99#define STACK_DIR stack_dir
100
101static void
102find_stack_direction (/* void */)
103{
104 static char *addr = NULL; /* address of first
105 `dummy', once known */
106 auto char dummy; /* to get stack address */
107
108 if (addr == NULL)
109 { /* initial entry */
110 addr = &dummy;
111
112 find_stack_direction (); /* recurse once */
113 }
114 else /* second entry */
115 if (&dummy > addr)
116 stack_dir = 1; /* stack grew upward */
117 else
118 stack_dir = -1; /* stack grew downward */
119}
120
121#endif /* STACK_DIRECTION == 0 */
122
123/*
124 An "alloca header" is used to:
125 (a) chain together all alloca()ed blocks;
126 (b) keep track of stack depth.
127
128 It is very important that sizeof(header) agree with malloc()
129 alignment chunk size. The following default should work okay.
130*/
131
132#ifndef ALIGN_SIZE
133#define ALIGN_SIZE sizeof(double)
134#endif
135
136typedef union hdr
137{
138 char align[ALIGN_SIZE]; /* to force sizeof(header) */
139 struct
140 {
141 union hdr *next; /* for chaining headers */
142 char *deep; /* for stack depth measure */
143 } h;
144} header;
145
146/*
147 alloca( size ) returns a pointer to at least `size' bytes of
148 storage which will be automatically reclaimed upon exit from
149 the procedure that called alloca(). Originally, this space
150 was supposed to be taken from the current stack frame of the
151 caller, but that method cannot be made to work for some
152 implementations of C, for example under Gould's UTX/32.
153*/
154
155static header *last_alloca_header = NULL; /* -> last alloca header */
156
157pointer
158alloca (size) /* returns pointer to storage */
159 unsigned size; /* # bytes to allocate */
160{
161 auto char probe; /* probes stack depth: */
162 register char *depth = &probe;
163
164#if STACK_DIRECTION == 0
165 if (STACK_DIR == 0) /* unknown growth direction */
166 find_stack_direction ();
167#endif
168
169 /* Reclaim garbage, defined as all alloca()ed storage that
170 was allocated from deeper in the stack than currently. */
171
172 {
173 register header *hp; /* traverses linked list */
174
175 for (hp = last_alloca_header; hp != NULL;)
176 if ((STACK_DIR > 0 && hp->h.deep > depth)
177 || (STACK_DIR < 0 && hp->h.deep < depth))
178 {
179 register header *np = hp->h.next;
180
181 free ((pointer) hp); /* collect garbage */
182
183 hp = np; /* -> next header */
184 }
185 else
186 break; /* rest are not deeper */
187
188 last_alloca_header = hp; /* -> last valid storage */
189 }
190
191 if (size == 0)
192 return NULL; /* no allocation required */
193
194 /* Allocate combined header + user data storage. */
195
196 {
197 register pointer new = xmalloc (sizeof (header) + size);
198 /* address of header */
199
200 ((header *)new)->h.next = last_alloca_header;
201 ((header *)new)->h.deep = depth;
202
203 last_alloca_header = (header *)new;
204
205 /* User storage begins just after header. */
206
207 return (pointer)((char *)new + sizeof(header));
208 }
209}
210
211#ifdef __MWERKS__
212static void*
213xmalloc (unsigned size)
214{
215 void *new_mem = (void*) malloc (size);
216
217 if (new_mem == NULL)
218 {
219 fprintf (stderr, "xmalloc: request for %u bytes failed.\n", size);
220 abort ();
221 }
222
223 return new_mem;
224}
225#endif /* THINK_C */
226
227#endif /* no alloca */
Note: See TracBrowser for help on using the repository browser.