| OLD | NEW |
| 1 /* alloca.c -- allocate automatically reclaimed memory | 1 /* alloca.c -- allocate automatically reclaimed memory |
| 2 (Mostly) portable public-domain implementation -- D A Gwyn | 2 (Mostly) portable public-domain implementation -- D A Gwyn |
| 3 | 3 |
| 4 This implementation of the PWB library alloca function, | 4 This implementation of the PWB library alloca function, |
| 5 which is used to allocate space off the run-time stack so | 5 which is used to allocate space off the run-time stack so |
| 6 that it is automatically reclaimed upon procedure exit, | 6 that it is automatically reclaimed upon procedure exit, |
| 7 was inspired by discussions with J. Q. Johnson of Cornell. | 7 was inspired by discussions with J. Q. Johnson of Cornell. |
| 8 J.Otto Tennant <jot@cray.com> contributed the Cray support. | 8 J.Otto Tennant <jot@cray.com> contributed the Cray support. |
| 9 | 9 |
| 10 There are some preprocessor constants that can | 10 There are some preprocessor constants that can |
| 11 be defined when compiling for your specific system, for | 11 be defined when compiling for your specific system, for |
| 12 improved efficiency; however, the defaults should be okay. | 12 improved efficiency; however, the defaults should be okay. |
| 13 | 13 |
| 14 The general concept of this implementation is to keep | 14 The general concept of this implementation is to keep |
| 15 track of all alloca-allocated blocks, and reclaim any | 15 track of all alloca-allocated blocks, and reclaim any |
| 16 that are found to be deeper in the stack than the current | 16 that are found to be deeper in the stack than the current |
| 17 invocation. This heuristic does not reclaim storage as | 17 invocation. This heuristic does not reclaim storage as |
| 18 soon as it becomes invalid, but it will do so eventually. | 18 soon as it becomes invalid, but it will do so eventually. |
| 19 | 19 |
| 20 As a special case, alloca(0) reclaims storage without | 20 As a special case, alloca(0) reclaims storage without |
| 21 allocating any. It is a good idea to use alloca(0) in | 21 allocating any. It is a good idea to use alloca(0) in |
| 22 your main control loop, etc. to force garbage collection. */ | 22 your main control loop, etc. to force garbage collection. */ |
| 23 | 23 |
| 24 /* | 24 #include <config.h> |
| 25 | 25 |
| 26 @deftypefn Replacement void* alloca (size_t @var{size}) | 26 #include <alloca.h> |
| 27 | 27 |
| 28 This function allocates memory which will be automatically reclaimed | 28 #include <string.h> |
| 29 after the procedure exits. The @libib{} implementation does not free | 29 #include <stdlib.h> |
| 30 the memory immediately but will do so eventually during subsequent | |
| 31 calls to this function. Memory is allocated using @code{xmalloc} under | |
| 32 normal circumstances. | |
| 33 | 30 |
| 34 The header file @file{alloca-conf.h} can be used in conjunction with the | 31 #ifdef emacs |
| 35 GNU Autoconf test @code{AC_FUNC_ALLOCA} to test for and properly make | 32 # include "lisp.h" |
| 36 available this function. The @code{AC_FUNC_ALLOCA} test requires that | 33 # include "blockinput.h" |
| 37 client code use a block of preprocessor code to be safe (see the Autoconf | 34 # ifdef EMACS_FREE |
| 38 manual for more); this header incorporates that logic and more, including | 35 # undef free |
| 39 the possibility of a GCC built-in function. | 36 # define free EMACS_FREE |
| 40 | 37 # endif |
| 41 @end deftypefn | 38 #else |
| 42 | 39 # define memory_full() abort () |
| 43 */ | |
| 44 | |
| 45 #ifdef HAVE_CONFIG_H | |
| 46 #include <config.h> | |
| 47 #endif | 40 #endif |
| 48 | 41 |
| 49 #include <libiberty.h> | 42 /* If compiling with GCC 2, this file's not needed. */ |
| 43 #if !defined (__GNUC__) || __GNUC__ < 2 |
| 50 | 44 |
| 51 #ifdef HAVE_STRING_H | 45 /* If someone has defined alloca as a macro, |
| 52 #include <string.h> | 46 there must be some other way alloca is supposed to work. */ |
| 53 #endif | 47 # ifndef alloca |
| 54 #ifdef HAVE_STDLIB_H | |
| 55 #include <stdlib.h> | |
| 56 #endif | |
| 57 | 48 |
| 58 /* These variables are used by the ASTRDUP implementation that relies | 49 # ifdef emacs |
| 59 on C_alloca. */ | 50 # ifdef static |
| 60 #ifdef __cplusplus | 51 /* actually, only want this if static is defined as "" |
| 61 extern "C" { | 52 -- this is for usg, in which emacs must undefine static |
| 62 #endif /* __cplusplus */ | 53 in order to make unexec workable |
| 63 const char *libiberty_optr; | 54 */ |
| 64 char *libiberty_nptr; | 55 # ifndef STACK_DIRECTION |
| 65 unsigned long libiberty_len; | 56 you |
| 66 #ifdef __cplusplus | 57 lose |
| 67 } | 58 -- must know STACK_DIRECTION at compile-time |
| 68 #endif /* __cplusplus */ | 59 /* Using #error here is not wise since this file should work for |
| 60 old and obscure compilers. */ |
| 61 # endif /* STACK_DIRECTION undefined */ |
| 62 # endif /* static */ |
| 63 # endif /* emacs */ |
| 69 | 64 |
| 70 /* If your stack is a linked list of frames, you have to | 65 /* If your stack is a linked list of frames, you have to |
| 71 provide an "address metric" ADDRESS_FUNCTION macro. */ | 66 provide an "address metric" ADDRESS_FUNCTION macro. */ |
| 72 | 67 |
| 73 #if defined (CRAY) && defined (CRAY_STACKSEG_END) | 68 # if defined (CRAY) && defined (CRAY_STACKSEG_END) |
| 74 static long i00afunc (); | 69 long i00afunc (); |
| 75 #define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) | 70 # define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) |
| 76 #else | 71 # else |
| 77 #define ADDRESS_FUNCTION(arg) &(arg) | 72 # define ADDRESS_FUNCTION(arg) &(arg) |
| 78 #endif | 73 # endif |
| 79 | |
| 80 #ifndef NULL | |
| 81 #define»NULL» 0 | |
| 82 #endif | |
| 83 | 74 |
| 84 /* Define STACK_DIRECTION if you know the direction of stack | 75 /* Define STACK_DIRECTION if you know the direction of stack |
| 85 growth for your system; otherwise it will be automatically | 76 growth for your system; otherwise it will be automatically |
| 86 deduced at run-time. | 77 deduced at run-time. |
| 87 | 78 |
| 88 STACK_DIRECTION > 0 => grows toward higher addresses | 79 STACK_DIRECTION > 0 => grows toward higher addresses |
| 89 STACK_DIRECTION < 0 => grows toward lower addresses | 80 STACK_DIRECTION < 0 => grows toward lower addresses |
| 90 STACK_DIRECTION = 0 => direction of growth unknown */ | 81 STACK_DIRECTION = 0 => direction of growth unknown */ |
| 91 | 82 |
| 92 #ifndef STACK_DIRECTION | 83 # ifndef STACK_DIRECTION |
| 93 #define»STACK_DIRECTION»0» /* Direction unknown. */ | 84 # define STACK_DIRECTION 0 /* Direction unknown. */ |
| 94 #endif | 85 # endif |
| 95 | 86 |
| 96 #if STACK_DIRECTION != 0 | 87 # if STACK_DIRECTION != 0 |
| 97 | 88 |
| 98 #define»STACK_DIR» STACK_DIRECTION»/* Known at compile-time. */ | 89 # define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ |
| 99 | 90 |
| 100 #else /* STACK_DIRECTION == 0; need run-time code. */ | 91 # else /* STACK_DIRECTION == 0; need run-time code. */ |
| 101 | 92 |
| 102 static int stack_dir;» » /* 1 or -1 once known. */ | 93 static int stack_dir; /* 1 or -1 once known. */ |
| 103 #define»STACK_DIR» stack_dir | 94 # define STACK_DIR stack_dir |
| 104 | 95 |
| 105 static void | 96 static int |
| 106 find_stack_direction (void) | 97 find_stack_direction (int *addr, int depth) |
| 107 { | 98 { |
| 108 static char *addr = NULL;» /* Address of first `dummy', once known. */ | 99 int dir, dummy = 0; |
| 109 auto char dummy;» » /* To get stack address. */ | 100 if (! addr) |
| 110 | 101 addr = &dummy; |
| 111 if (addr == NULL) | 102 *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; |
| 112 {» » » » /* Initial entry. */ | 103 dir = depth ? find_stack_direction (addr, depth - 1) : 0; |
| 113 addr = ADDRESS_FUNCTION (dummy); | 104 return dir + dummy; |
| 114 | |
| 115 find_stack_direction ();» /* Recurse once. */ | |
| 116 } | |
| 117 else | |
| 118 { | |
| 119 /* Second entry. */ | |
| 120 if (ADDRESS_FUNCTION (dummy) > addr) | |
| 121 » stack_dir = 1;» » /* Stack grew upward. */ | |
| 122 else | |
| 123 » stack_dir = -1;»» /* Stack grew downward. */ | |
| 124 } | |
| 125 } | 105 } |
| 126 | 106 |
| 127 #endif /* STACK_DIRECTION == 0 */ | 107 # endif /* STACK_DIRECTION == 0 */ |
| 128 | 108 |
| 129 /* An "alloca header" is used to: | 109 /* An "alloca header" is used to: |
| 130 (a) chain together all alloca'ed blocks; | 110 (a) chain together all alloca'ed blocks; |
| 131 (b) keep track of stack depth. | 111 (b) keep track of stack depth. |
| 132 | 112 |
| 133 It is very important that sizeof(header) agree with malloc | 113 It is very important that sizeof(header) agree with malloc |
| 134 alignment chunk size. The following default should work okay. */ | 114 alignment chunk size. The following default should work okay. */ |
| 135 | 115 |
| 136 #ifndef»ALIGN_SIZE | 116 # ifndef ALIGN_SIZE |
| 137 #define»ALIGN_SIZE» sizeof(double) | 117 # define ALIGN_SIZE sizeof(double) |
| 138 #endif | 118 # endif |
| 139 | 119 |
| 140 typedef union hdr | 120 typedef union hdr |
| 141 { | 121 { |
| 142 char align[ALIGN_SIZE];» /* To force sizeof(header). */ | 122 char align[ALIGN_SIZE]; /* To force sizeof(header). */ |
| 143 struct | 123 struct |
| 144 { | 124 { |
| 145 union hdr *next;» » /* For chaining headers. */ | 125 union hdr *next; /* For chaining headers. */ |
| 146 char *deep;» » /* For stack depth measure. */ | 126 char *deep; /* For stack depth measure. */ |
| 147 } h; | 127 } h; |
| 148 } header; | 128 } header; |
| 149 | 129 |
| 150 static header *last_alloca_header = NULL;» /* -> last alloca header. */ | 130 static header *last_alloca_header = NULL; /* -> last alloca header. */ |
| 151 | 131 |
| 152 /* Return a pointer to at least SIZE bytes of storage, | 132 /* Return a pointer to at least SIZE bytes of storage, |
| 153 which will be automatically reclaimed upon exit from | 133 which will be automatically reclaimed upon exit from |
| 154 the procedure that called alloca. Originally, this space | 134 the procedure that called alloca. Originally, this space |
| 155 was supposed to be taken from the current stack frame of the | 135 was supposed to be taken from the current stack frame of the |
| 156 caller, but that method cannot be made to work for some | 136 caller, but that method cannot be made to work for some |
| 157 implementations of C, for example under Gould's UTX/32. */ | 137 implementations of C, for example under Gould's UTX/32. */ |
| 158 | 138 |
| 159 /* @undocumented C_alloca */ | 139 void * |
| 160 | 140 alloca (size_t size) |
| 161 PTR | |
| 162 C_alloca (size_t size) | |
| 163 { | 141 { |
| 164 auto char probe;» » /* Probes stack depth: */ | 142 auto char probe; /* Probes stack depth: */ |
| 165 register char *depth = ADDRESS_FUNCTION (probe); | 143 register char *depth = ADDRESS_FUNCTION (probe); |
| 166 | 144 |
| 167 #if STACK_DIRECTION == 0 | 145 # if STACK_DIRECTION == 0 |
| 168 if (STACK_DIR == 0)» » /* Unknown growth direction. */ | 146 if (STACK_DIR == 0) /* Unknown growth direction. */ |
| 169 find_stack_direction (); | 147 STACK_DIR = find_stack_direction (NULL, (size & 1) + 20); |
| 170 #endif | 148 # endif |
| 171 | 149 |
| 172 /* Reclaim garbage, defined as all alloca'd storage that | 150 /* Reclaim garbage, defined as all alloca'd storage that |
| 173 was allocated from deeper in the stack than currently. */ | 151 was allocated from deeper in the stack than currently. */ |
| 174 | 152 |
| 175 { | 153 { |
| 176 register header *hp;» /* Traverses linked list. */ | 154 register header *hp; /* Traverses linked list. */ |
| 155 |
| 156 # ifdef emacs |
| 157 BLOCK_INPUT; |
| 158 # endif |
| 177 | 159 |
| 178 for (hp = last_alloca_header; hp != NULL;) | 160 for (hp = last_alloca_header; hp != NULL;) |
| 179 if ((STACK_DIR > 0 && hp->h.deep > depth) | 161 if ((STACK_DIR > 0 && hp->h.deep > depth) |
| 180 » || (STACK_DIR < 0 && hp->h.deep < depth)) | 162 || (STACK_DIR < 0 && hp->h.deep < depth)) |
| 181 » { | 163 { |
| 182 » register header *np = hp->h.next; | 164 register header *np = hp->h.next; |
| 183 | 165 |
| 184 » free ((PTR) hp);» /* Collect garbage. */ | 166 free (hp); /* Collect garbage. */ |
| 185 | 167 |
| 186 » hp = np;» » /* -> next header. */ | 168 hp = np; /* -> next header. */ |
| 187 » } | 169 } |
| 188 else | 170 else |
| 189 » break;» » » /* Rest are not deeper. */ | 171 break; /* Rest are not deeper. */ |
| 190 | 172 |
| 191 last_alloca_header = hp;» /* -> last valid storage. */ | 173 last_alloca_header = hp; /* -> last valid storage. */ |
| 174 |
| 175 # ifdef emacs |
| 176 UNBLOCK_INPUT; |
| 177 # endif |
| 192 } | 178 } |
| 193 | 179 |
| 194 if (size == 0) | 180 if (size == 0) |
| 195 return NULL;» » /* No allocation required. */ | 181 return NULL; /* No allocation required. */ |
| 196 | 182 |
| 197 /* Allocate combined header + user data storage. */ | 183 /* Allocate combined header + user data storage. */ |
| 198 | 184 |
| 199 { | 185 { |
| 200 register void *new_storage = XNEWVEC (char, sizeof (header) + size); | |
| 201 /* Address of header. */ | 186 /* Address of header. */ |
| 187 register header *new; |
| 202 | 188 |
| 203 if (new_storage == 0) | 189 size_t combined_size = sizeof (header) + size; |
| 204 abort(); | 190 if (combined_size < sizeof (header)) |
| 191 memory_full (); |
| 205 | 192 |
| 206 ((header *) new_storage)->h.next = last_alloca_header; | 193 new = malloc (combined_size); |
| 207 ((header *) new_storage)->h.deep = depth; | |
| 208 | 194 |
| 209 last_alloca_header = (header *) new_storage; | 195 if (! new) |
| 196 memory_full (); |
| 197 |
| 198 new->h.next = last_alloca_header; |
| 199 new->h.deep = depth; |
| 200 |
| 201 last_alloca_header = new; |
| 210 | 202 |
| 211 /* User storage begins just after header. */ | 203 /* User storage begins just after header. */ |
| 212 | 204 |
| 213 return (PTR) ((char *) new_storage + sizeof (header)); | 205 return (void *) (new + 1); |
| 214 } | 206 } |
| 215 } | 207 } |
| 216 | 208 |
| 217 #if defined (CRAY) && defined (CRAY_STACKSEG_END) | 209 # if defined (CRAY) && defined (CRAY_STACKSEG_END) |
| 218 | 210 |
| 219 #ifdef DEBUG_I00AFUNC | 211 # ifdef DEBUG_I00AFUNC |
| 220 #include <stdio.h> | 212 # include <stdio.h> |
| 221 #endif | 213 # endif |
| 222 | 214 |
| 223 #ifndef CRAY_STACK | 215 # ifndef CRAY_STACK |
| 224 #define CRAY_STACK | 216 # define CRAY_STACK |
| 225 #ifndef CRAY2 | 217 # ifndef CRAY2 |
| 226 /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ | 218 /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ |
| 227 struct stack_control_header | 219 struct stack_control_header |
| 228 { | 220 { |
| 229 long shgrow:32;» » /* Number of times stack has grown. */ | 221 long shgrow:32; /* Number of times stack has grown. */ |
| 230 long shaseg:32;» » /* Size of increments to stack. */ | 222 long shaseg:32; /* Size of increments to stack. */ |
| 231 long shhwm:32;» » /* High water mark of stack. */ | 223 long shhwm:32; /* High water mark of stack. */ |
| 232 long shsize:32;» » /* Current size of stack (all segments). */ | 224 long shsize:32; /* Current size of stack (all segments). */ |
| 233 }; | 225 }; |
| 234 | 226 |
| 235 /* The stack segment linkage control information occurs at | 227 /* The stack segment linkage control information occurs at |
| 236 the high-address end of a stack segment. (The stack | 228 the high-address end of a stack segment. (The stack |
| 237 grows from low addresses to high addresses.) The initial | 229 grows from low addresses to high addresses.) The initial |
| 238 part of the stack segment linkage control information is | 230 part of the stack segment linkage control information is |
| 239 0200 (octal) words. This provides for register storage | 231 0200 (octal) words. This provides for register storage |
| 240 for the routine which overflows the stack. */ | 232 for the routine which overflows the stack. */ |
| 241 | 233 |
| 242 struct stack_segment_linkage | 234 struct stack_segment_linkage |
| 243 { | 235 { |
| 244 long ss[0200];» » /* 0200 overflow words. */ | 236 long ss[0200]; /* 0200 overflow words. */ |
| 245 long sssize:32;» » /* Number of words in this segment. */ | 237 long sssize:32; /* Number of words in this segment. */ |
| 246 long ssbase:32;» » /* Offset to stack base. */ | 238 long ssbase:32; /* Offset to stack base. */ |
| 247 long:32; | 239 long:32; |
| 248 long sspseg:32;» » /* Offset to linkage control of previous | 240 long sspseg:32; /* Offset to linkage control of previous |
| 249 » » » » segment of stack. */ | 241 segment of stack. */ |
| 250 long:32; | 242 long:32; |
| 251 long sstcpt:32;» » /* Pointer to task common address block. */ | 243 long sstcpt:32; /* Pointer to task common address block. */ |
| 252 long sscsnm;» » /* Private control structure number for | 244 long sscsnm; /* Private control structure number for |
| 253 » » » » microtasking. */ | 245 microtasking. */ |
| 254 long ssusr1;» » /* Reserved for user. */ | 246 long ssusr1; /* Reserved for user. */ |
| 255 long ssusr2;» » /* Reserved for user. */ | 247 long ssusr2; /* Reserved for user. */ |
| 256 long sstpid;» » /* Process ID for pid based multi-tasking. */ | 248 long sstpid; /* Process ID for pid based multi-tasking. */ |
| 257 long ssgvup;» » /* Pointer to multitasking thread giveup. */ | 249 long ssgvup; /* Pointer to multitasking thread giveup. */ |
| 258 long sscray[7];» » /* Reserved for Cray Research. */ | 250 long sscray[7]; /* Reserved for Cray Research. */ |
| 259 long ssa0; | 251 long ssa0; |
| 260 long ssa1; | 252 long ssa1; |
| 261 long ssa2; | 253 long ssa2; |
| 262 long ssa3; | 254 long ssa3; |
| 263 long ssa4; | 255 long ssa4; |
| 264 long ssa5; | 256 long ssa5; |
| 265 long ssa6; | 257 long ssa6; |
| 266 long ssa7; | 258 long ssa7; |
| 267 long sss0; | 259 long sss0; |
| 268 long sss1; | 260 long sss1; |
| 269 long sss2; | 261 long sss2; |
| 270 long sss3; | 262 long sss3; |
| 271 long sss4; | 263 long sss4; |
| 272 long sss5; | 264 long sss5; |
| 273 long sss6; | 265 long sss6; |
| 274 long sss7; | 266 long sss7; |
| 275 }; | 267 }; |
| 276 | 268 |
| 277 #else /* CRAY2 */ | 269 # else /* CRAY2 */ |
| 278 /* The following structure defines the vector of words | 270 /* The following structure defines the vector of words |
| 279 returned by the STKSTAT library routine. */ | 271 returned by the STKSTAT library routine. */ |
| 280 struct stk_stat | 272 struct stk_stat |
| 281 { | 273 { |
| 282 long now;» » » /* Current total stack size. */ | 274 long now; /* Current total stack size. */ |
| 283 long maxc;» » » /* Amount of contiguous space which would | 275 long maxc; /* Amount of contiguous space which would |
| 284 » » » » be required to satisfy the maximum | 276 be required to satisfy the maximum |
| 285 » » » » stack demand to date. */ | 277 stack demand to date. */ |
| 286 long high_water;» » /* Stack high-water mark. */ | 278 long high_water; /* Stack high-water mark. */ |
| 287 long overflows;» » /* Number of stack overflow ($STKOFEN) calls. *
/ | 279 long overflows; /* Number of stack overflow ($STKOFEN) calls. *
/ |
| 288 long hits;» » » /* Number of internal buffer hits. */ | 280 long hits; /* Number of internal buffer hits. */ |
| 289 long extends;» » /* Number of block extensions. */ | 281 long extends; /* Number of block extensions. */ |
| 290 long stko_mallocs;» » /* Block allocations by $STKOFEN. */ | 282 long stko_mallocs; /* Block allocations by $STKOFEN. */ |
| 291 long underflows;» » /* Number of stack underflow calls ($STKRETN).
*/ | 283 long underflows; /* Number of stack underflow calls ($STKRETN).
*/ |
| 292 long stko_free;» » /* Number of deallocations by $STKRETN. */ | 284 long stko_free; /* Number of deallocations by $STKRETN. */ |
| 293 long stkm_free;» » /* Number of deallocations by $STKMRET. */ | 285 long stkm_free; /* Number of deallocations by $STKMRET. */ |
| 294 long segments;» » /* Current number of stack segments. */ | 286 long segments; /* Current number of stack segments. */ |
| 295 long maxs;» » » /* Maximum number of stack segments so far. */ | 287 long maxs; /* Maximum number of stack segments so far. */ |
| 296 long pad_size;» » /* Stack pad size. */ | 288 long pad_size; /* Stack pad size. */ |
| 297 long current_address;» /* Current stack segment address. */ | 289 long current_address; /* Current stack segment address. */ |
| 298 long current_size;» » /* Current stack segment size. This | 290 long current_size; /* Current stack segment size. This |
| 299 » » » » number is actually corrupted by STKSTAT to | 291 number is actually corrupted by STKSTAT to |
| 300 » » » » include the fifteen word trailer area. */ | 292 include the fifteen word trailer area. */ |
| 301 long initial_address;» /* Address of initial segment. */ | 293 long initial_address; /* Address of initial segment. */ |
| 302 long initial_size;» » /* Size of initial segment. */ | 294 long initial_size; /* Size of initial segment. */ |
| 303 }; | 295 }; |
| 304 | 296 |
| 305 /* The following structure describes the data structure which trails | 297 /* The following structure describes the data structure which trails |
| 306 any stack segment. I think that the description in 'asdef' is | 298 any stack segment. I think that the description in 'asdef' is |
| 307 out of date. I only describe the parts that I am sure about. */ | 299 out of date. I only describe the parts that I am sure about. */ |
| 308 | 300 |
| 309 struct stk_trailer | 301 struct stk_trailer |
| 310 { | 302 { |
| 311 long this_address;» » /* Address of this block. */ | 303 long this_address; /* Address of this block. */ |
| 312 long this_size;» » /* Size of this block (does not include | 304 long this_size; /* Size of this block (does not include |
| 313 » » » » this trailer). */ | 305 this trailer). */ |
| 314 long unknown2; | 306 long unknown2; |
| 315 long unknown3; | 307 long unknown3; |
| 316 long link;» » » /* Address of trailer block of previous | 308 long link; /* Address of trailer block of previous |
| 317 » » » » segment. */ | 309 segment. */ |
| 318 long unknown5; | 310 long unknown5; |
| 319 long unknown6; | 311 long unknown6; |
| 320 long unknown7; | 312 long unknown7; |
| 321 long unknown8; | 313 long unknown8; |
| 322 long unknown9; | 314 long unknown9; |
| 323 long unknown10; | 315 long unknown10; |
| 324 long unknown11; | 316 long unknown11; |
| 325 long unknown12; | 317 long unknown12; |
| 326 long unknown13; | 318 long unknown13; |
| 327 long unknown14; | 319 long unknown14; |
| 328 }; | 320 }; |
| 329 | 321 |
| 330 #endif /* CRAY2 */ | 322 # endif /* CRAY2 */ |
| 331 #endif /* not CRAY_STACK */ | 323 # endif /* not CRAY_STACK */ |
| 332 | 324 |
| 333 #ifdef CRAY2 | 325 # ifdef CRAY2 |
| 334 /* Determine a "stack measure" for an arbitrary ADDRESS. | 326 /* Determine a "stack measure" for an arbitrary ADDRESS. |
| 335 I doubt that "lint" will like this much. */ | 327 I doubt that "lint" will like this much. */ |
| 336 | 328 |
| 337 static long | 329 static long |
| 338 i00afunc (long *address) | 330 i00afunc (long *address) |
| 339 { | 331 { |
| 340 struct stk_stat status; | 332 struct stk_stat status; |
| 341 struct stk_trailer *trailer; | 333 struct stk_trailer *trailer; |
| 342 long *block, size; | 334 long *block, size; |
| 343 long result = 0; | 335 long result = 0; |
| 344 | 336 |
| 345 /* We want to iterate through all of the segments. The first | 337 /* We want to iterate through all of the segments. The first |
| 346 step is to get the stack status structure. We could do this | 338 step is to get the stack status structure. We could do this |
| 347 more quickly and more directly, perhaps, by referencing the | 339 more quickly and more directly, perhaps, by referencing the |
| 348 $LM00 common block, but I know that this works. */ | 340 $LM00 common block, but I know that this works. */ |
| 349 | 341 |
| 350 STKSTAT (&status); | 342 STKSTAT (&status); |
| 351 | 343 |
| 352 /* Set up the iteration. */ | 344 /* Set up the iteration. */ |
| 353 | 345 |
| 354 trailer = (struct stk_trailer *) (status.current_address | 346 trailer = (struct stk_trailer *) (status.current_address |
| 355 » » » » + status.current_size | 347 + status.current_size |
| 356 » » » » - 15); | 348 - 15); |
| 357 | 349 |
| 358 /* There must be at least one stack segment. Therefore it is | 350 /* There must be at least one stack segment. Therefore it is |
| 359 a fatal error if "trailer" is null. */ | 351 a fatal error if "trailer" is null. */ |
| 360 | 352 |
| 361 if (trailer == 0) | 353 if (trailer == 0) |
| 362 abort (); | 354 abort (); |
| 363 | 355 |
| 364 /* Discard segments that do not contain our argument address. */ | 356 /* Discard segments that do not contain our argument address. */ |
| 365 | 357 |
| 366 while (trailer != 0) | 358 while (trailer != 0) |
| 367 { | 359 { |
| 368 block = (long *) trailer->this_address; | 360 block = (long *) trailer->this_address; |
| 369 size = trailer->this_size; | 361 size = trailer->this_size; |
| 370 if (block == 0 || size == 0) | 362 if (block == 0 || size == 0) |
| 371 » abort (); | 363 abort (); |
| 372 trailer = (struct stk_trailer *) trailer->link; | 364 trailer = (struct stk_trailer *) trailer->link; |
| 373 if ((block <= address) && (address < (block + size))) | 365 if ((block <= address) && (address < (block + size))) |
| 374 » break; | 366 break; |
| 375 } | 367 } |
| 376 | 368 |
| 377 /* Set the result to the offset in this segment and add the sizes | 369 /* Set the result to the offset in this segment and add the sizes |
| 378 of all predecessor segments. */ | 370 of all predecessor segments. */ |
| 379 | 371 |
| 380 result = address - block; | 372 result = address - block; |
| 381 | 373 |
| 382 if (trailer == 0) | 374 if (trailer == 0) |
| 383 { | 375 { |
| 384 return result; | 376 return result; |
| 385 } | 377 } |
| 386 | 378 |
| 387 do | 379 do |
| 388 { | 380 { |
| 389 if (trailer->this_size <= 0) | 381 if (trailer->this_size <= 0) |
| 390 » abort (); | 382 abort (); |
| 391 result += trailer->this_size; | 383 result += trailer->this_size; |
| 392 trailer = (struct stk_trailer *) trailer->link; | 384 trailer = (struct stk_trailer *) trailer->link; |
| 393 } | 385 } |
| 394 while (trailer != 0); | 386 while (trailer != 0); |
| 395 | 387 |
| 396 /* We are done. Note that if you present a bogus address (one | 388 /* We are done. Note that if you present a bogus address (one |
| 397 not in any segment), you will get a different number back, formed | 389 not in any segment), you will get a different number back, formed |
| 398 from subtracting the address of the first block. This is probably | 390 from subtracting the address of the first block. This is probably |
| 399 not what you want. */ | 391 not what you want. */ |
| 400 | 392 |
| 401 return (result); | 393 return (result); |
| 402 } | 394 } |
| 403 | 395 |
| 404 #else /* not CRAY2 */ | 396 # else /* not CRAY2 */ |
| 405 /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. | 397 /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. |
| 406 Determine the number of the cell within the stack, | 398 Determine the number of the cell within the stack, |
| 407 given the address of the cell. The purpose of this | 399 given the address of the cell. The purpose of this |
| 408 routine is to linearize, in some sense, stack addresses | 400 routine is to linearize, in some sense, stack addresses |
| 409 for alloca. */ | 401 for alloca. */ |
| 410 | 402 |
| 411 static long | 403 static long |
| 412 i00afunc (long address) | 404 i00afunc (long address) |
| 413 { | 405 { |
| 414 long stkl = 0; | 406 long stkl = 0; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 439 size = ssptr->sssize; | 431 size = ssptr->sssize; |
| 440 | 432 |
| 441 this_segment = stkl - size; | 433 this_segment = stkl - size; |
| 442 | 434 |
| 443 /* It is possible that calling this routine itself caused | 435 /* It is possible that calling this routine itself caused |
| 444 a stack overflow. Discard stack segments which do not | 436 a stack overflow. Discard stack segments which do not |
| 445 contain the target address. */ | 437 contain the target address. */ |
| 446 | 438 |
| 447 while (!(this_segment <= address && address <= stkl)) | 439 while (!(this_segment <= address && address <= stkl)) |
| 448 { | 440 { |
| 449 #ifdef DEBUG_I00AFUNC | 441 # ifdef DEBUG_I00AFUNC |
| 450 fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); | 442 fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); |
| 451 #endif | 443 # endif |
| 452 if (pseg == 0) | 444 if (pseg == 0) |
| 453 » break; | 445 break; |
| 454 stkl = stkl - pseg; | 446 stkl = stkl - pseg; |
| 455 ssptr = (struct stack_segment_linkage *) stkl; | 447 ssptr = (struct stack_segment_linkage *) stkl; |
| 456 size = ssptr->sssize; | 448 size = ssptr->sssize; |
| 457 pseg = ssptr->sspseg; | 449 pseg = ssptr->sspseg; |
| 458 this_segment = stkl - size; | 450 this_segment = stkl - size; |
| 459 } | 451 } |
| 460 | 452 |
| 461 result = address - this_segment; | 453 result = address - this_segment; |
| 462 | 454 |
| 463 /* If you subtract pseg from the current end of the stack, | 455 /* If you subtract pseg from the current end of the stack, |
| 464 you get the address of the previous stack segment's end. | 456 you get the address of the previous stack segment's end. |
| 465 This seems a little convoluted to me, but I'll bet you save | 457 This seems a little convoluted to me, but I'll bet you save |
| 466 a cycle somewhere. */ | 458 a cycle somewhere. */ |
| 467 | 459 |
| 468 while (pseg != 0) | 460 while (pseg != 0) |
| 469 { | 461 { |
| 470 #ifdef DEBUG_I00AFUNC | 462 # ifdef DEBUG_I00AFUNC |
| 471 fprintf (stderr, "%011o %011o\n", pseg, size); | 463 fprintf (stderr, "%011o %011o\n", pseg, size); |
| 472 #endif | 464 # endif |
| 473 stkl = stkl - pseg; | 465 stkl = stkl - pseg; |
| 474 ssptr = (struct stack_segment_linkage *) stkl; | 466 ssptr = (struct stack_segment_linkage *) stkl; |
| 475 size = ssptr->sssize; | 467 size = ssptr->sssize; |
| 476 pseg = ssptr->sspseg; | 468 pseg = ssptr->sspseg; |
| 477 result += size; | 469 result += size; |
| 478 } | 470 } |
| 479 return (result); | 471 return (result); |
| 480 } | 472 } |
| 481 | 473 |
| 482 #endif /* not CRAY2 */ | 474 # endif /* not CRAY2 */ |
| 483 #endif /* CRAY */ | 475 # endif /* CRAY */ |
| 476 |
| 477 # endif /* no alloca */ |
| 478 #endif /* not GCC 2 */ |
| OLD | NEW |