1141cc406Sopenharmony_ci/* alloca.c -- allocate automatically reclaimed memory 2141cc406Sopenharmony_ci (Mostly) portable public-domain implementation -- D A Gwyn 3141cc406Sopenharmony_ci 4141cc406Sopenharmony_ci This implementation of the PWB library alloca function, 5141cc406Sopenharmony_ci which is used to allocate space off the run-time stack so 6141cc406Sopenharmony_ci that it is automatically reclaimed upon procedure exit, 7141cc406Sopenharmony_ci was inspired by discussions with J. Q. Johnson of Cornell. 8141cc406Sopenharmony_ci J.Otto Tennant <jot@cray.com> contributed the Cray support. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci There are some preprocessor constants that can 11141cc406Sopenharmony_ci be defined when compiling for your specific system, for 12141cc406Sopenharmony_ci improved efficiency; however, the defaults should be okay. 13141cc406Sopenharmony_ci 14141cc406Sopenharmony_ci The general concept of this implementation is to keep 15141cc406Sopenharmony_ci track of all alloca-allocated blocks, and reclaim any 16141cc406Sopenharmony_ci that are found to be deeper in the stack than the current 17141cc406Sopenharmony_ci invocation. This heuristic does not reclaim storage as 18141cc406Sopenharmony_ci soon as it becomes invalid, but it will do so eventually. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci As a special case, alloca(0) reclaims storage without 21141cc406Sopenharmony_ci allocating any. It is a good idea to use alloca(0) in 22141cc406Sopenharmony_ci your main control loop, etc. to force garbage collection. */ 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci#ifdef HAVE_CONFIG_H 25141cc406Sopenharmony_ci#include "../include/sane/config.h" 26141cc406Sopenharmony_ci#endif 27141cc406Sopenharmony_ci 28141cc406Sopenharmony_ci#ifndef HAVE_ALLOCA 29141cc406Sopenharmony_ci 30141cc406Sopenharmony_ci#include "lalloca.h" 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci#ifdef emacs 33141cc406Sopenharmony_ci#include "blockinput.h" 34141cc406Sopenharmony_ci#endif 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci/* If compiling with GCC 2, this file's not needed. */ 37141cc406Sopenharmony_ci#if !defined (__GNUC__) || __GNUC__ < 2 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci/* If someone has defined alloca as a macro, 40141cc406Sopenharmony_ci there must be some other way alloca is supposed to work. */ 41141cc406Sopenharmony_ci#ifndef alloca 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci#ifdef emacs 44141cc406Sopenharmony_ci#ifdef static 45141cc406Sopenharmony_ci/* actually, only want this if static is defined as "" 46141cc406Sopenharmony_ci -- this is for usg, in which emacs must undefine static 47141cc406Sopenharmony_ci in order to make unexec workable 48141cc406Sopenharmony_ci */ 49141cc406Sopenharmony_ci#ifndef STACK_DIRECTION 50141cc406Sopenharmony_ciyou 51141cc406Sopenharmony_cilose 52141cc406Sopenharmony_ci-- must know STACK_DIRECTION at compile-time 53141cc406Sopenharmony_ci#endif /* STACK_DIRECTION undefined */ 54141cc406Sopenharmony_ci#endif /* static */ 55141cc406Sopenharmony_ci#endif /* emacs */ 56141cc406Sopenharmony_ci 57141cc406Sopenharmony_ci/* If your stack is a linked list of frames, you have to 58141cc406Sopenharmony_ci provide an "address metric" ADDRESS_FUNCTION macro. */ 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci#if defined (CRAY) && defined (CRAY_STACKSEG_END) 61141cc406Sopenharmony_cilong i00afunc (); 62141cc406Sopenharmony_ci#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) 63141cc406Sopenharmony_ci#else 64141cc406Sopenharmony_ci#define ADDRESS_FUNCTION(arg) &(arg) 65141cc406Sopenharmony_ci#endif 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci#if __STDC__ 68141cc406Sopenharmony_citypedef void *pointer; 69141cc406Sopenharmony_ci#else 70141cc406Sopenharmony_citypedef char *pointer; 71141cc406Sopenharmony_ci#endif 72141cc406Sopenharmony_ci 73141cc406Sopenharmony_ci#define NULL 0 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_ci/* Different portions of Emacs need to call different versions of 76141cc406Sopenharmony_ci malloc. The Emacs executable needs alloca to call xmalloc, because 77141cc406Sopenharmony_ci ordinary malloc isn't protected from input signals. On the other 78141cc406Sopenharmony_ci hand, the utilities in lib-src need alloca to call malloc; some of 79141cc406Sopenharmony_ci them are very simple, and don't have an xmalloc routine. 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci Non-Emacs programs expect this to call xmalloc. 82141cc406Sopenharmony_ci 83141cc406Sopenharmony_ci Callers below should use malloc. */ 84141cc406Sopenharmony_ci 85141cc406Sopenharmony_ciextern pointer malloc (); 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_ci/* Define STACK_DIRECTION if you know the direction of stack 88141cc406Sopenharmony_ci growth for your system; otherwise it will be automatically 89141cc406Sopenharmony_ci deduced at run-time. 90141cc406Sopenharmony_ci 91141cc406Sopenharmony_ci STACK_DIRECTION > 0 => grows toward higher addresses 92141cc406Sopenharmony_ci STACK_DIRECTION < 0 => grows toward lower addresses 93141cc406Sopenharmony_ci STACK_DIRECTION = 0 => direction of growth unknown */ 94141cc406Sopenharmony_ci 95141cc406Sopenharmony_ci#ifndef STACK_DIRECTION 96141cc406Sopenharmony_ci#define STACK_DIRECTION 0 /* Direction unknown. */ 97141cc406Sopenharmony_ci#endif 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci#if STACK_DIRECTION != 0 100141cc406Sopenharmony_ci 101141cc406Sopenharmony_ci#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ 102141cc406Sopenharmony_ci 103141cc406Sopenharmony_ci#else /* STACK_DIRECTION == 0; need run-time code. */ 104141cc406Sopenharmony_ci 105141cc406Sopenharmony_cistatic int stack_dir; /* 1 or -1 once known. */ 106141cc406Sopenharmony_ci#define STACK_DIR stack_dir 107141cc406Sopenharmony_ci 108141cc406Sopenharmony_cistatic void 109141cc406Sopenharmony_cifind_stack_direction () 110141cc406Sopenharmony_ci{ 111141cc406Sopenharmony_ci static char *addr = NULL; /* Address of first `dummy', once known. */ 112141cc406Sopenharmony_ci auto char dummy; /* To get stack address. */ 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci if (addr == NULL) 115141cc406Sopenharmony_ci { /* Initial entry. */ 116141cc406Sopenharmony_ci addr = ADDRESS_FUNCTION (dummy); 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci find_stack_direction (); /* Recurse once. */ 119141cc406Sopenharmony_ci } 120141cc406Sopenharmony_ci else 121141cc406Sopenharmony_ci { 122141cc406Sopenharmony_ci /* Second entry. */ 123141cc406Sopenharmony_ci if (ADDRESS_FUNCTION (dummy) > addr) 124141cc406Sopenharmony_ci stack_dir = 1; /* Stack grew upward. */ 125141cc406Sopenharmony_ci else 126141cc406Sopenharmony_ci stack_dir = -1; /* Stack grew downward. */ 127141cc406Sopenharmony_ci } 128141cc406Sopenharmony_ci} 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ci#endif /* STACK_DIRECTION == 0 */ 131141cc406Sopenharmony_ci 132141cc406Sopenharmony_ci/* An "alloca header" is used to: 133141cc406Sopenharmony_ci (a) chain together all alloca'ed blocks; 134141cc406Sopenharmony_ci (b) keep track of stack depth. 135141cc406Sopenharmony_ci 136141cc406Sopenharmony_ci It is very important that sizeof(header) agree with malloc 137141cc406Sopenharmony_ci alignment chunk size. The following default should work okay. */ 138141cc406Sopenharmony_ci 139141cc406Sopenharmony_ci#ifndef ALIGN_SIZE 140141cc406Sopenharmony_ci#define ALIGN_SIZE sizeof(double) 141141cc406Sopenharmony_ci#endif 142141cc406Sopenharmony_ci 143141cc406Sopenharmony_citypedef union hdr 144141cc406Sopenharmony_ci{ 145141cc406Sopenharmony_ci char align[ALIGN_SIZE]; /* To force sizeof(header). */ 146141cc406Sopenharmony_ci struct 147141cc406Sopenharmony_ci { 148141cc406Sopenharmony_ci union hdr *next; /* For chaining headers. */ 149141cc406Sopenharmony_ci char *deep; /* For stack depth measure. */ 150141cc406Sopenharmony_ci } h; 151141cc406Sopenharmony_ci} header; 152141cc406Sopenharmony_ci 153141cc406Sopenharmony_cistatic header *last_alloca_header = NULL; /* -> last alloca header. */ 154141cc406Sopenharmony_ci 155141cc406Sopenharmony_ci/* Return a pointer to at least SIZE bytes of storage, 156141cc406Sopenharmony_ci which will be automatically reclaimed upon exit from 157141cc406Sopenharmony_ci the procedure that called alloca. Originally, this space 158141cc406Sopenharmony_ci was supposed to be taken from the current stack frame of the 159141cc406Sopenharmony_ci caller, but that method cannot be made to work for some 160141cc406Sopenharmony_ci implementations of C, for example under Gould's UTX/32. */ 161141cc406Sopenharmony_ci 162141cc406Sopenharmony_cipointer 163141cc406Sopenharmony_cialloca (size) 164141cc406Sopenharmony_ci unsigned size; 165141cc406Sopenharmony_ci{ 166141cc406Sopenharmony_ci auto char probe; /* Probes stack depth: */ 167141cc406Sopenharmony_ci register char *depth = ADDRESS_FUNCTION (probe); 168141cc406Sopenharmony_ci 169141cc406Sopenharmony_ci#if STACK_DIRECTION == 0 170141cc406Sopenharmony_ci if (STACK_DIR == 0) /* Unknown growth direction. */ 171141cc406Sopenharmony_ci find_stack_direction (); 172141cc406Sopenharmony_ci#endif 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci /* Reclaim garbage, defined as all alloca'd storage that 175141cc406Sopenharmony_ci was allocated from deeper in the stack than currently. */ 176141cc406Sopenharmony_ci 177141cc406Sopenharmony_ci { 178141cc406Sopenharmony_ci register header *hp; /* Traverses linked list. */ 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_ci#ifdef emacs 181141cc406Sopenharmony_ci BLOCK_INPUT; 182141cc406Sopenharmony_ci#endif 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci for (hp = last_alloca_header; hp != NULL;) 185141cc406Sopenharmony_ci if ((STACK_DIR > 0 && hp->h.deep > depth) 186141cc406Sopenharmony_ci || (STACK_DIR < 0 && hp->h.deep < depth)) 187141cc406Sopenharmony_ci { 188141cc406Sopenharmony_ci register header *np = hp->h.next; 189141cc406Sopenharmony_ci 190141cc406Sopenharmony_ci free ((pointer) hp); /* Collect garbage. */ 191141cc406Sopenharmony_ci 192141cc406Sopenharmony_ci hp = np; /* -> next header. */ 193141cc406Sopenharmony_ci } 194141cc406Sopenharmony_ci else 195141cc406Sopenharmony_ci break; /* Rest are not deeper. */ 196141cc406Sopenharmony_ci 197141cc406Sopenharmony_ci last_alloca_header = hp; /* -> last valid storage. */ 198141cc406Sopenharmony_ci 199141cc406Sopenharmony_ci#ifdef emacs 200141cc406Sopenharmony_ci UNBLOCK_INPUT; 201141cc406Sopenharmony_ci#endif 202141cc406Sopenharmony_ci } 203141cc406Sopenharmony_ci 204141cc406Sopenharmony_ci if (size == 0) 205141cc406Sopenharmony_ci return NULL; /* No allocation required. */ 206141cc406Sopenharmony_ci 207141cc406Sopenharmony_ci /* Allocate combined header + user data storage. */ 208141cc406Sopenharmony_ci 209141cc406Sopenharmony_ci { 210141cc406Sopenharmony_ci register pointer new = malloc (sizeof (header) + size); 211141cc406Sopenharmony_ci /* Address of header. */ 212141cc406Sopenharmony_ci 213141cc406Sopenharmony_ci ((header *) new)->h.next = last_alloca_header; 214141cc406Sopenharmony_ci ((header *) new)->h.deep = depth; 215141cc406Sopenharmony_ci 216141cc406Sopenharmony_ci last_alloca_header = (header *) new; 217141cc406Sopenharmony_ci 218141cc406Sopenharmony_ci /* User storage begins just after header. */ 219141cc406Sopenharmony_ci 220141cc406Sopenharmony_ci return (pointer) ((char *) new + sizeof (header)); 221141cc406Sopenharmony_ci } 222141cc406Sopenharmony_ci} 223141cc406Sopenharmony_ci 224141cc406Sopenharmony_ci#if defined (CRAY) && defined (CRAY_STACKSEG_END) 225141cc406Sopenharmony_ci 226141cc406Sopenharmony_ci#ifdef DEBUG_I00AFUNC 227141cc406Sopenharmony_ci#include <stdio.h> 228141cc406Sopenharmony_ci#endif 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_ci#ifndef CRAY_STACK 231141cc406Sopenharmony_ci#define CRAY_STACK 232141cc406Sopenharmony_ci#ifndef CRAY2 233141cc406Sopenharmony_ci/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ 234141cc406Sopenharmony_cistruct stack_control_header 235141cc406Sopenharmony_ci { 236141cc406Sopenharmony_ci long shgrow:32; /* Number of times stack has grown. */ 237141cc406Sopenharmony_ci long shaseg:32; /* Size of increments to stack. */ 238141cc406Sopenharmony_ci long shhwm:32; /* High water mark of stack. */ 239141cc406Sopenharmony_ci long shsize:32; /* Current size of stack (all segments). */ 240141cc406Sopenharmony_ci }; 241141cc406Sopenharmony_ci 242141cc406Sopenharmony_ci/* The stack segment linkage control information occurs at 243141cc406Sopenharmony_ci the high-address end of a stack segment. (The stack 244141cc406Sopenharmony_ci grows from low addresses to high addresses.) The initial 245141cc406Sopenharmony_ci part of the stack segment linkage control information is 246141cc406Sopenharmony_ci 0200 (octal) words. This provides for register storage 247141cc406Sopenharmony_ci for the routine which overflows the stack. */ 248141cc406Sopenharmony_ci 249141cc406Sopenharmony_cistruct stack_segment_linkage 250141cc406Sopenharmony_ci { 251141cc406Sopenharmony_ci long ss[0200]; /* 0200 overflow words. */ 252141cc406Sopenharmony_ci long sssize:32; /* Number of words in this segment. */ 253141cc406Sopenharmony_ci long ssbase:32; /* Offset to stack base. */ 254141cc406Sopenharmony_ci long:32; 255141cc406Sopenharmony_ci long sspseg:32; /* Offset to linkage control of previous 256141cc406Sopenharmony_ci segment of stack. */ 257141cc406Sopenharmony_ci long:32; 258141cc406Sopenharmony_ci long sstcpt:32; /* Pointer to task common address block. */ 259141cc406Sopenharmony_ci long sscsnm; /* Private control structure number for 260141cc406Sopenharmony_ci microtasking. */ 261141cc406Sopenharmony_ci long ssusr1; /* Reserved for user. */ 262141cc406Sopenharmony_ci long ssusr2; /* Reserved for user. */ 263141cc406Sopenharmony_ci long sstpid; /* Process ID for pid based multi-tasking. */ 264141cc406Sopenharmony_ci long ssgvup; /* Pointer to multitasking thread giveup. */ 265141cc406Sopenharmony_ci long sscray[7]; /* Reserved for Cray Research. */ 266141cc406Sopenharmony_ci long ssa0; 267141cc406Sopenharmony_ci long ssa1; 268141cc406Sopenharmony_ci long ssa2; 269141cc406Sopenharmony_ci long ssa3; 270141cc406Sopenharmony_ci long ssa4; 271141cc406Sopenharmony_ci long ssa5; 272141cc406Sopenharmony_ci long ssa6; 273141cc406Sopenharmony_ci long ssa7; 274141cc406Sopenharmony_ci long sss0; 275141cc406Sopenharmony_ci long sss1; 276141cc406Sopenharmony_ci long sss2; 277141cc406Sopenharmony_ci long sss3; 278141cc406Sopenharmony_ci long sss4; 279141cc406Sopenharmony_ci long sss5; 280141cc406Sopenharmony_ci long sss6; 281141cc406Sopenharmony_ci long sss7; 282141cc406Sopenharmony_ci }; 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ci#else /* CRAY2 */ 285141cc406Sopenharmony_ci/* The following structure defines the vector of words 286141cc406Sopenharmony_ci returned by the STKSTAT library routine. */ 287141cc406Sopenharmony_cistruct stk_stat 288141cc406Sopenharmony_ci { 289141cc406Sopenharmony_ci long now; /* Current total stack size. */ 290141cc406Sopenharmony_ci long maxc; /* Amount of contiguous space which would 291141cc406Sopenharmony_ci be required to satisfy the maximum 292141cc406Sopenharmony_ci stack demand to date. */ 293141cc406Sopenharmony_ci long high_water; /* Stack high-water mark. */ 294141cc406Sopenharmony_ci long overflows; /* Number of stack overflow ($STKOFEN) calls. */ 295141cc406Sopenharmony_ci long hits; /* Number of internal buffer hits. */ 296141cc406Sopenharmony_ci long extends; /* Number of block extensions. */ 297141cc406Sopenharmony_ci long stko_mallocs; /* Block allocations by $STKOFEN. */ 298141cc406Sopenharmony_ci long underflows; /* Number of stack underflow calls ($STKRETN). */ 299141cc406Sopenharmony_ci long stko_free; /* Number of deallocations by $STKRETN. */ 300141cc406Sopenharmony_ci long stkm_free; /* Number of deallocations by $STKMRET. */ 301141cc406Sopenharmony_ci long segments; /* Current number of stack segments. */ 302141cc406Sopenharmony_ci long maxs; /* Maximum number of stack segments so far. */ 303141cc406Sopenharmony_ci long pad_size; /* Stack pad size. */ 304141cc406Sopenharmony_ci long current_address; /* Current stack segment address. */ 305141cc406Sopenharmony_ci long current_size; /* Current stack segment size. This 306141cc406Sopenharmony_ci number is actually corrupted by STKSTAT to 307141cc406Sopenharmony_ci include the fifteen word trailer area. */ 308141cc406Sopenharmony_ci long initial_address; /* Address of initial segment. */ 309141cc406Sopenharmony_ci long initial_size; /* Size of initial segment. */ 310141cc406Sopenharmony_ci }; 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci/* The following structure describes the data structure which trails 313141cc406Sopenharmony_ci any stack segment. I think that the description in 'asdef' is 314141cc406Sopenharmony_ci out of date. I only describe the parts that I am sure about. */ 315141cc406Sopenharmony_ci 316141cc406Sopenharmony_cistruct stk_trailer 317141cc406Sopenharmony_ci { 318141cc406Sopenharmony_ci long this_address; /* Address of this block. */ 319141cc406Sopenharmony_ci long this_size; /* Size of this block (does not include 320141cc406Sopenharmony_ci this trailer). */ 321141cc406Sopenharmony_ci long unknown2; 322141cc406Sopenharmony_ci long unknown3; 323141cc406Sopenharmony_ci long link; /* Address of trailer block of previous 324141cc406Sopenharmony_ci segment. */ 325141cc406Sopenharmony_ci long unknown5; 326141cc406Sopenharmony_ci long unknown6; 327141cc406Sopenharmony_ci long unknown7; 328141cc406Sopenharmony_ci long unknown8; 329141cc406Sopenharmony_ci long unknown9; 330141cc406Sopenharmony_ci long unknown10; 331141cc406Sopenharmony_ci long unknown11; 332141cc406Sopenharmony_ci long unknown12; 333141cc406Sopenharmony_ci long unknown13; 334141cc406Sopenharmony_ci long unknown14; 335141cc406Sopenharmony_ci }; 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_ci#endif /* CRAY2 */ 338141cc406Sopenharmony_ci#endif /* not CRAY_STACK */ 339141cc406Sopenharmony_ci 340141cc406Sopenharmony_ci#ifdef CRAY2 341141cc406Sopenharmony_ci/* Determine a "stack measure" for an arbitrary ADDRESS. 342141cc406Sopenharmony_ci I doubt that "lint" will like this much. */ 343141cc406Sopenharmony_ci 344141cc406Sopenharmony_cistatic long 345141cc406Sopenharmony_cii00afunc (long *address) 346141cc406Sopenharmony_ci{ 347141cc406Sopenharmony_ci struct stk_stat status; 348141cc406Sopenharmony_ci struct stk_trailer *trailer; 349141cc406Sopenharmony_ci long *block, size; 350141cc406Sopenharmony_ci long result = 0; 351141cc406Sopenharmony_ci 352141cc406Sopenharmony_ci /* We want to iterate through all of the segments. The first 353141cc406Sopenharmony_ci step is to get the stack status structure. We could do this 354141cc406Sopenharmony_ci more quickly and more directly, perhaps, by referencing the 355141cc406Sopenharmony_ci $LM00 common block, but I know that this works. */ 356141cc406Sopenharmony_ci 357141cc406Sopenharmony_ci STKSTAT (&status); 358141cc406Sopenharmony_ci 359141cc406Sopenharmony_ci /* Set up the iteration. */ 360141cc406Sopenharmony_ci 361141cc406Sopenharmony_ci trailer = (struct stk_trailer *) (status.current_address 362141cc406Sopenharmony_ci + status.current_size 363141cc406Sopenharmony_ci - 15); 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci /* There must be at least one stack segment. Therefore it is 366141cc406Sopenharmony_ci a fatal error if "trailer" is null. */ 367141cc406Sopenharmony_ci 368141cc406Sopenharmony_ci if (trailer == 0) 369141cc406Sopenharmony_ci abort (); 370141cc406Sopenharmony_ci 371141cc406Sopenharmony_ci /* Discard segments that do not contain our argument address. */ 372141cc406Sopenharmony_ci 373141cc406Sopenharmony_ci while (trailer != 0) 374141cc406Sopenharmony_ci { 375141cc406Sopenharmony_ci block = (long *) trailer->this_address; 376141cc406Sopenharmony_ci size = trailer->this_size; 377141cc406Sopenharmony_ci if (block == 0 || size == 0) 378141cc406Sopenharmony_ci abort (); 379141cc406Sopenharmony_ci trailer = (struct stk_trailer *) trailer->link; 380141cc406Sopenharmony_ci if ((block <= address) && (address < (block + size))) 381141cc406Sopenharmony_ci break; 382141cc406Sopenharmony_ci } 383141cc406Sopenharmony_ci 384141cc406Sopenharmony_ci /* Set the result to the offset in this segment and add the sizes 385141cc406Sopenharmony_ci of all predecessor segments. */ 386141cc406Sopenharmony_ci 387141cc406Sopenharmony_ci result = address - block; 388141cc406Sopenharmony_ci 389141cc406Sopenharmony_ci if (trailer == 0) 390141cc406Sopenharmony_ci { 391141cc406Sopenharmony_ci return result; 392141cc406Sopenharmony_ci } 393141cc406Sopenharmony_ci 394141cc406Sopenharmony_ci do 395141cc406Sopenharmony_ci { 396141cc406Sopenharmony_ci if (trailer->this_size <= 0) 397141cc406Sopenharmony_ci abort (); 398141cc406Sopenharmony_ci result += trailer->this_size; 399141cc406Sopenharmony_ci trailer = (struct stk_trailer *) trailer->link; 400141cc406Sopenharmony_ci } 401141cc406Sopenharmony_ci while (trailer != 0); 402141cc406Sopenharmony_ci 403141cc406Sopenharmony_ci /* We are done. Note that if you present a bogus address (one 404141cc406Sopenharmony_ci not in any segment), you will get a different number back, formed 405141cc406Sopenharmony_ci from subtracting the address of the first block. This is probably 406141cc406Sopenharmony_ci not what you want. */ 407141cc406Sopenharmony_ci 408141cc406Sopenharmony_ci return (result); 409141cc406Sopenharmony_ci} 410141cc406Sopenharmony_ci 411141cc406Sopenharmony_ci#else /* not CRAY2 */ 412141cc406Sopenharmony_ci/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. 413141cc406Sopenharmony_ci Determine the number of the cell within the stack, 414141cc406Sopenharmony_ci given the address of the cell. The purpose of this 415141cc406Sopenharmony_ci routine is to linearize, in some sense, stack addresses 416141cc406Sopenharmony_ci for alloca. */ 417141cc406Sopenharmony_ci 418141cc406Sopenharmony_cistatic long 419141cc406Sopenharmony_cii00afunc (long address) 420141cc406Sopenharmony_ci{ 421141cc406Sopenharmony_ci long stkl = 0; 422141cc406Sopenharmony_ci 423141cc406Sopenharmony_ci long size, pseg, this_segment, stack; 424141cc406Sopenharmony_ci long result = 0; 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci struct stack_segment_linkage *ssptr; 427141cc406Sopenharmony_ci 428141cc406Sopenharmony_ci /* Register B67 contains the address of the end of the 429141cc406Sopenharmony_ci current stack segment. If you (as a subprogram) store 430141cc406Sopenharmony_ci your registers on the stack and find that you are past 431141cc406Sopenharmony_ci the contents of B67, you have overflowed the segment. 432141cc406Sopenharmony_ci 433141cc406Sopenharmony_ci B67 also points to the stack segment linkage control 434141cc406Sopenharmony_ci area, which is what we are really interested in. */ 435141cc406Sopenharmony_ci 436141cc406Sopenharmony_ci stkl = CRAY_STACKSEG_END (); 437141cc406Sopenharmony_ci ssptr = (struct stack_segment_linkage *) stkl; 438141cc406Sopenharmony_ci 439141cc406Sopenharmony_ci /* If one subtracts 'size' from the end of the segment, 440141cc406Sopenharmony_ci one has the address of the first word of the segment. 441141cc406Sopenharmony_ci 442141cc406Sopenharmony_ci If this is not the first segment, 'pseg' will be 443141cc406Sopenharmony_ci nonzero. */ 444141cc406Sopenharmony_ci 445141cc406Sopenharmony_ci pseg = ssptr->sspseg; 446141cc406Sopenharmony_ci size = ssptr->sssize; 447141cc406Sopenharmony_ci 448141cc406Sopenharmony_ci this_segment = stkl - size; 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ci /* It is possible that calling this routine itself caused 451141cc406Sopenharmony_ci a stack overflow. Discard stack segments which do not 452141cc406Sopenharmony_ci contain the target address. */ 453141cc406Sopenharmony_ci 454141cc406Sopenharmony_ci while (!(this_segment <= address && address <= stkl)) 455141cc406Sopenharmony_ci { 456141cc406Sopenharmony_ci#ifdef DEBUG_I00AFUNC 457141cc406Sopenharmony_ci fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); 458141cc406Sopenharmony_ci#endif 459141cc406Sopenharmony_ci if (pseg == 0) 460141cc406Sopenharmony_ci break; 461141cc406Sopenharmony_ci stkl = stkl - pseg; 462141cc406Sopenharmony_ci ssptr = (struct stack_segment_linkage *) stkl; 463141cc406Sopenharmony_ci size = ssptr->sssize; 464141cc406Sopenharmony_ci pseg = ssptr->sspseg; 465141cc406Sopenharmony_ci this_segment = stkl - size; 466141cc406Sopenharmony_ci } 467141cc406Sopenharmony_ci 468141cc406Sopenharmony_ci result = address - this_segment; 469141cc406Sopenharmony_ci 470141cc406Sopenharmony_ci /* If you subtract pseg from the current end of the stack, 471141cc406Sopenharmony_ci you get the address of the previous stack segment's end. 472141cc406Sopenharmony_ci This seems a little convoluted to me, but I'll bet you save 473141cc406Sopenharmony_ci a cycle somewhere. */ 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_ci while (pseg != 0) 476141cc406Sopenharmony_ci { 477141cc406Sopenharmony_ci#ifdef DEBUG_I00AFUNC 478141cc406Sopenharmony_ci fprintf (stderr, "%011o %011o\n", pseg, size); 479141cc406Sopenharmony_ci#endif 480141cc406Sopenharmony_ci stkl = stkl - pseg; 481141cc406Sopenharmony_ci ssptr = (struct stack_segment_linkage *) stkl; 482141cc406Sopenharmony_ci size = ssptr->sssize; 483141cc406Sopenharmony_ci pseg = ssptr->sspseg; 484141cc406Sopenharmony_ci result += size; 485141cc406Sopenharmony_ci } 486141cc406Sopenharmony_ci return (result); 487141cc406Sopenharmony_ci} 488141cc406Sopenharmony_ci 489141cc406Sopenharmony_ci#endif /* not CRAY2 */ 490141cc406Sopenharmony_ci#endif /* CRAY */ 491141cc406Sopenharmony_ci 492141cc406Sopenharmony_ci#endif /* no alloca */ 493141cc406Sopenharmony_ci#endif /* not GCC version 2 */ 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci#endif /* !HAVE_ALLOCA */ 496