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