Blame gl/alloca.c

Packit Service 4684c1
/* alloca.c -- allocate automatically reclaimed memory
Packit Service 4684c1
   (Mostly) portable public-domain implementation -- D A Gwyn
Packit Service 4684c1
Packit Service 4684c1
   This implementation of the PWB library alloca function,
Packit Service 4684c1
   which is used to allocate space off the run-time stack so
Packit Service 4684c1
   that it is automatically reclaimed upon procedure exit,
Packit Service 4684c1
   was inspired by discussions with J. Q. Johnson of Cornell.
Packit Service 4684c1
   J.Otto Tennant <jot@cray.com> contributed the Cray support.
Packit Service 4684c1
Packit Service 4684c1
   There are some preprocessor constants that can
Packit Service 4684c1
   be defined when compiling for your specific system, for
Packit Service 4684c1
   improved efficiency; however, the defaults should be okay.
Packit Service 4684c1
Packit Service 4684c1
   The general concept of this implementation is to keep
Packit Service 4684c1
   track of all alloca-allocated blocks, and reclaim any
Packit Service 4684c1
   that are found to be deeper in the stack than the current
Packit Service 4684c1
   invocation.  This heuristic does not reclaim storage as
Packit Service 4684c1
   soon as it becomes invalid, but it will do so eventually.
Packit Service 4684c1
Packit Service 4684c1
   As a special case, alloca(0) reclaims storage without
Packit Service 4684c1
   allocating any.  It is a good idea to use alloca(0) in
Packit Service 4684c1
   your main control loop, etc. to force garbage collection.  */
Packit Service 4684c1
Packit Service 4684c1
#include <config.h>
Packit Service 4684c1
Packit Service 4684c1
#include <alloca.h>
Packit Service 4684c1
Packit Service 4684c1
#include <string.h>
Packit Service 4684c1
#include <stdlib.h>
Packit Service 4684c1
Packit Service 4684c1
#ifdef emacs
Packit Service 4684c1
# include "lisp.h"
Packit Service 4684c1
# include "blockinput.h"
Packit Service 4684c1
# ifdef EMACS_FREE
Packit Service 4684c1
#  undef free
Packit Service 4684c1
#  define free EMACS_FREE
Packit Service 4684c1
# endif
Packit Service 4684c1
#else
Packit Service 4684c1
# define memory_full() abort ()
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
/* If compiling with GCC 2, this file's not needed.  */
Packit Service 4684c1
#if !defined (__GNUC__) || __GNUC__ < 2
Packit Service 4684c1
Packit Service 4684c1
/* If someone has defined alloca as a macro,
Packit Service 4684c1
   there must be some other way alloca is supposed to work.  */
Packit Service 4684c1
# ifndef alloca
Packit Service 4684c1
Packit Service 4684c1
#  ifdef emacs
Packit Service 4684c1
#   ifdef static
Packit Service 4684c1
/* actually, only want this if static is defined as ""
Packit Service 4684c1
   -- this is for usg, in which emacs must undefine static
Packit Service 4684c1
   in order to make unexec workable
Packit Service 4684c1
   */
Packit Service 4684c1
#    ifndef STACK_DIRECTION
Packit Service 4684c1
you
Packit Service 4684c1
lose
Packit Service 4684c1
-- must know STACK_DIRECTION at compile-time
Packit Service 4684c1
/* Using #error here is not wise since this file should work for
Packit Service 4684c1
   old and obscure compilers.  */
Packit Service 4684c1
#    endif /* STACK_DIRECTION undefined */
Packit Service 4684c1
#   endif /* static */
Packit Service 4684c1
#  endif /* emacs */
Packit Service 4684c1
Packit Service 4684c1
/* If your stack is a linked list of frames, you have to
Packit Service 4684c1
   provide an "address metric" ADDRESS_FUNCTION macro.  */
Packit Service 4684c1
Packit Service 4684c1
#  if defined (CRAY) && defined (CRAY_STACKSEG_END)
Packit Service 4684c1
long i00afunc ();
Packit Service 4684c1
#   define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
Packit Service 4684c1
#  else
Packit Service 4684c1
#   define ADDRESS_FUNCTION(arg) &(arg)
Packit Service 4684c1
#  endif
Packit Service 4684c1
Packit Service 4684c1
/* Define STACK_DIRECTION if you know the direction of stack
Packit Service 4684c1
   growth for your system; otherwise it will be automatically
Packit Service 4684c1
   deduced at run-time.
Packit Service 4684c1
Packit Service 4684c1
   STACK_DIRECTION > 0 => grows toward higher addresses
Packit Service 4684c1
   STACK_DIRECTION < 0 => grows toward lower addresses
Packit Service 4684c1
   STACK_DIRECTION = 0 => direction of growth unknown  */
Packit Service 4684c1
Packit Service 4684c1
#  ifndef STACK_DIRECTION
Packit Service 4684c1
#   define STACK_DIRECTION      0       /* Direction unknown.  */
Packit Service 4684c1
#  endif
Packit Service 4684c1
Packit Service 4684c1
#  if STACK_DIRECTION != 0
Packit Service 4684c1
Packit Service 4684c1
#   define STACK_DIR    STACK_DIRECTION /* Known at compile-time.  */
Packit Service 4684c1
Packit Service 4684c1
#  else /* STACK_DIRECTION == 0; need run-time code.  */
Packit Service 4684c1
Packit Service 4684c1
static int stack_dir;           /* 1 or -1 once known.  */
Packit Service 4684c1
#   define STACK_DIR    stack_dir
Packit Service 4684c1
Packit Service 4684c1
static int
Packit Service 4684c1
find_stack_direction (int *addr, int depth)
Packit Service 4684c1
{
Packit Service 4684c1
  int dir, dummy = 0;
Packit Service 4684c1
  if (! addr)
Packit Service 4684c1
    addr = &dummy;
Packit Service 4684c1
  *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1;
Packit Service 4684c1
  dir = depth ? find_stack_direction (addr, depth - 1) : 0;
Packit Service 4684c1
  return dir + dummy;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#  endif /* STACK_DIRECTION == 0 */
Packit Service 4684c1
Packit Service 4684c1
/* An "alloca header" is used to:
Packit Service 4684c1
   (a) chain together all alloca'ed blocks;
Packit Service 4684c1
   (b) keep track of stack depth.
Packit Service 4684c1
Packit Service 4684c1
   It is very important that sizeof(header) agree with malloc
Packit Service 4684c1
   alignment chunk size.  The following default should work okay.  */
Packit Service 4684c1
Packit Service 4684c1
#  ifndef       ALIGN_SIZE
Packit Service 4684c1
#   define ALIGN_SIZE   sizeof(double)
Packit Service 4684c1
#  endif
Packit Service 4684c1
Packit Service 4684c1
typedef union hdr
Packit Service 4684c1
{
Packit Service 4684c1
  char align[ALIGN_SIZE];       /* To force sizeof(header).  */
Packit Service 4684c1
  struct
Packit Service 4684c1
    {
Packit Service 4684c1
      union hdr *next;          /* For chaining headers.  */
Packit Service 4684c1
      char *deep;               /* For stack depth measure.  */
Packit Service 4684c1
    } h;
Packit Service 4684c1
} header;
Packit Service 4684c1
Packit Service 4684c1
static header *last_alloca_header = NULL;       /* -> last alloca header.  */
Packit Service 4684c1
Packit Service 4684c1
/* Return a pointer to at least SIZE bytes of storage,
Packit Service 4684c1
   which will be automatically reclaimed upon exit from
Packit Service 4684c1
   the procedure that called alloca.  Originally, this space
Packit Service 4684c1
   was supposed to be taken from the current stack frame of the
Packit Service 4684c1
   caller, but that method cannot be made to work for some
Packit Service 4684c1
   implementations of C, for example under Gould's UTX/32.  */
Packit Service 4684c1
Packit Service 4684c1
void *
Packit Service 4684c1
alloca (size_t size)
Packit Service 4684c1
{
Packit Service 4684c1
  auto char probe;              /* Probes stack depth: */
Packit Service 4684c1
  register char *depth = ADDRESS_FUNCTION (probe);
Packit Service 4684c1
Packit Service 4684c1
#  if STACK_DIRECTION == 0
Packit Service 4684c1
  if (STACK_DIR == 0)           /* Unknown growth direction.  */
Packit Service 4684c1
    STACK_DIR = find_stack_direction (NULL, (size & 1) + 20);
Packit Service 4684c1
#  endif
Packit Service 4684c1
Packit Service 4684c1
  /* Reclaim garbage, defined as all alloca'd storage that
Packit Service 4684c1
     was allocated from deeper in the stack than currently.  */
Packit Service 4684c1
Packit Service 4684c1
  {
Packit Service 4684c1
    register header *hp;        /* Traverses linked list.  */
Packit Service 4684c1
Packit Service 4684c1
#  ifdef emacs
Packit Service 4684c1
    BLOCK_INPUT;
Packit Service 4684c1
#  endif
Packit Service 4684c1
Packit Service 4684c1
    for (hp = last_alloca_header; hp != NULL;)
Packit Service 4684c1
      if ((STACK_DIR > 0 && hp->h.deep > depth)
Packit Service 4684c1
          || (STACK_DIR < 0 && hp->h.deep < depth))
Packit Service 4684c1
        {
Packit Service 4684c1
          register header *np = hp->h.next;
Packit Service 4684c1
Packit Service 4684c1
          free (hp);            /* Collect garbage.  */
Packit Service 4684c1
Packit Service 4684c1
          hp = np;              /* -> next header.  */
Packit Service 4684c1
        }
Packit Service 4684c1
      else
Packit Service 4684c1
        break;                  /* Rest are not deeper.  */
Packit Service 4684c1
Packit Service 4684c1
    last_alloca_header = hp;    /* -> last valid storage.  */
Packit Service 4684c1
Packit Service 4684c1
#  ifdef emacs
Packit Service 4684c1
    UNBLOCK_INPUT;
Packit Service 4684c1
#  endif
Packit Service 4684c1
  }
Packit Service 4684c1
Packit Service 4684c1
  if (size == 0)
Packit Service 4684c1
    return NULL;                /* No allocation required.  */
Packit Service 4684c1
Packit Service 4684c1
  /* Allocate combined header + user data storage.  */
Packit Service 4684c1
Packit Service 4684c1
  {
Packit Service 4684c1
    /* Address of header.  */
Packit Service 4684c1
    register header *new;
Packit Service 4684c1
Packit Service 4684c1
    size_t combined_size = sizeof (header) + size;
Packit Service 4684c1
    if (combined_size < sizeof (header))
Packit Service 4684c1
      memory_full ();
Packit Service 4684c1
Packit Service 4684c1
    new = malloc (combined_size);
Packit Service 4684c1
Packit Service 4684c1
    if (! new)
Packit Service 4684c1
      memory_full ();
Packit Service 4684c1
Packit Service 4684c1
    new->h.next = last_alloca_header;
Packit Service 4684c1
    new->h.deep = depth;
Packit Service 4684c1
Packit Service 4684c1
    last_alloca_header = new;
Packit Service 4684c1
Packit Service 4684c1
    /* User storage begins just after header.  */
Packit Service 4684c1
Packit Service 4684c1
    return (void *) (new + 1);
Packit Service 4684c1
  }
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#  if defined (CRAY) && defined (CRAY_STACKSEG_END)
Packit Service 4684c1
Packit Service 4684c1
#   ifdef DEBUG_I00AFUNC
Packit Service 4684c1
#    include <stdio.h>
Packit Service 4684c1
#   endif
Packit Service 4684c1
Packit Service 4684c1
#   ifndef CRAY_STACK
Packit Service 4684c1
#    define CRAY_STACK
Packit Service 4684c1
#    ifndef CRAY2
Packit Service 4684c1
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
Packit Service 4684c1
struct stack_control_header
Packit Service 4684c1
  {
Packit Service 4684c1
    long shgrow:32;             /* Number of times stack has grown.  */
Packit Service 4684c1
    long shaseg:32;             /* Size of increments to stack.  */
Packit Service 4684c1
    long shhwm:32;              /* High water mark of stack.  */
Packit Service 4684c1
    long shsize:32;             /* Current size of stack (all segments).  */
Packit Service 4684c1
  };
Packit Service 4684c1
Packit Service 4684c1
/* The stack segment linkage control information occurs at
Packit Service 4684c1
   the high-address end of a stack segment.  (The stack
Packit Service 4684c1
   grows from low addresses to high addresses.)  The initial
Packit Service 4684c1
   part of the stack segment linkage control information is
Packit Service 4684c1
   0200 (octal) words.  This provides for register storage
Packit Service 4684c1
   for the routine which overflows the stack.  */
Packit Service 4684c1
Packit Service 4684c1
struct stack_segment_linkage
Packit Service 4684c1
  {
Packit Service 4684c1
    long ss[0200];              /* 0200 overflow words.  */
Packit Service 4684c1
    long sssize:32;             /* Number of words in this segment.  */
Packit Service 4684c1
    long ssbase:32;             /* Offset to stack base.  */
Packit Service 4684c1
    long:32;
Packit Service 4684c1
    long sspseg:32;             /* Offset to linkage control of previous
Packit Service 4684c1
                                   segment of stack.  */
Packit Service 4684c1
    long:32;
Packit Service 4684c1
    long sstcpt:32;             /* Pointer to task common address block.  */
Packit Service 4684c1
    long sscsnm;                /* Private control structure number for
Packit Service 4684c1
                                   microtasking.  */
Packit Service 4684c1
    long ssusr1;                /* Reserved for user.  */
Packit Service 4684c1
    long ssusr2;                /* Reserved for user.  */
Packit Service 4684c1
    long sstpid;                /* Process ID for pid based multi-tasking.  */
Packit Service 4684c1
    long ssgvup;                /* Pointer to multitasking thread giveup.  */
Packit Service 4684c1
    long sscray[7];             /* Reserved for Cray Research.  */
Packit Service 4684c1
    long ssa0;
Packit Service 4684c1
    long ssa1;
Packit Service 4684c1
    long ssa2;
Packit Service 4684c1
    long ssa3;
Packit Service 4684c1
    long ssa4;
Packit Service 4684c1
    long ssa5;
Packit Service 4684c1
    long ssa6;
Packit Service 4684c1
    long ssa7;
Packit Service 4684c1
    long sss0;
Packit Service 4684c1
    long sss1;
Packit Service 4684c1
    long sss2;
Packit Service 4684c1
    long sss3;
Packit Service 4684c1
    long sss4;
Packit Service 4684c1
    long sss5;
Packit Service 4684c1
    long sss6;
Packit Service 4684c1
    long sss7;
Packit Service 4684c1
  };
Packit Service 4684c1
Packit Service 4684c1
#    else /* CRAY2 */
Packit Service 4684c1
/* The following structure defines the vector of words
Packit Service 4684c1
   returned by the STKSTAT library routine.  */
Packit Service 4684c1
struct stk_stat
Packit Service 4684c1
  {
Packit Service 4684c1
    long now;                   /* Current total stack size.  */
Packit Service 4684c1
    long maxc;                  /* Amount of contiguous space which would
Packit Service 4684c1
                                   be required to satisfy the maximum
Packit Service 4684c1
                                   stack demand to date.  */
Packit Service 4684c1
    long high_water;            /* Stack high-water mark.  */
Packit Service 4684c1
    long overflows;             /* Number of stack overflow ($STKOFEN) calls.  */
Packit Service 4684c1
    long hits;                  /* Number of internal buffer hits.  */
Packit Service 4684c1
    long extends;               /* Number of block extensions.  */
Packit Service 4684c1
    long stko_mallocs;          /* Block allocations by $STKOFEN.  */
Packit Service 4684c1
    long underflows;            /* Number of stack underflow calls ($STKRETN).  */
Packit Service 4684c1
    long stko_free;             /* Number of deallocations by $STKRETN.  */
Packit Service 4684c1
    long stkm_free;             /* Number of deallocations by $STKMRET.  */
Packit Service 4684c1
    long segments;              /* Current number of stack segments.  */
Packit Service 4684c1
    long maxs;                  /* Maximum number of stack segments so far.  */
Packit Service 4684c1
    long pad_size;              /* Stack pad size.  */
Packit Service 4684c1
    long current_address;       /* Current stack segment address.  */
Packit Service 4684c1
    long current_size;          /* Current stack segment size.  This
Packit Service 4684c1
                                   number is actually corrupted by STKSTAT to
Packit Service 4684c1
                                   include the fifteen word trailer area.  */
Packit Service 4684c1
    long initial_address;       /* Address of initial segment.  */
Packit Service 4684c1
    long initial_size;          /* Size of initial segment.  */
Packit Service 4684c1
  };
Packit Service 4684c1
Packit Service 4684c1
/* The following structure describes the data structure which trails
Packit Service 4684c1
   any stack segment.  I think that the description in 'asdef' is
Packit Service 4684c1
   out of date.  I only describe the parts that I am sure about.  */
Packit Service 4684c1
Packit Service 4684c1
struct stk_trailer
Packit Service 4684c1
  {
Packit Service 4684c1
    long this_address;          /* Address of this block.  */
Packit Service 4684c1
    long this_size;             /* Size of this block (does not include
Packit Service 4684c1
                                   this trailer).  */
Packit Service 4684c1
    long unknown2;
Packit Service 4684c1
    long unknown3;
Packit Service 4684c1
    long link;                  /* Address of trailer block of previous
Packit Service 4684c1
                                   segment.  */
Packit Service 4684c1
    long unknown5;
Packit Service 4684c1
    long unknown6;
Packit Service 4684c1
    long unknown7;
Packit Service 4684c1
    long unknown8;
Packit Service 4684c1
    long unknown9;
Packit Service 4684c1
    long unknown10;
Packit Service 4684c1
    long unknown11;
Packit Service 4684c1
    long unknown12;
Packit Service 4684c1
    long unknown13;
Packit Service 4684c1
    long unknown14;
Packit Service 4684c1
  };
Packit Service 4684c1
Packit Service 4684c1
#    endif /* CRAY2 */
Packit Service 4684c1
#   endif /* not CRAY_STACK */
Packit Service 4684c1
Packit Service 4684c1
#   ifdef CRAY2
Packit Service 4684c1
/* Determine a "stack measure" for an arbitrary ADDRESS.
Packit Service 4684c1
   I doubt that "lint" will like this much.  */
Packit Service 4684c1
Packit Service 4684c1
static long
Packit Service 4684c1
i00afunc (long *address)
Packit Service 4684c1
{
Packit Service 4684c1
  struct stk_stat status;
Packit Service 4684c1
  struct stk_trailer *trailer;
Packit Service 4684c1
  long *block, size;
Packit Service 4684c1
  long result = 0;
Packit Service 4684c1
Packit Service 4684c1
  /* We want to iterate through all of the segments.  The first
Packit Service 4684c1
     step is to get the stack status structure.  We could do this
Packit Service 4684c1
     more quickly and more directly, perhaps, by referencing the
Packit Service 4684c1
     $LM00 common block, but I know that this works.  */
Packit Service 4684c1
Packit Service 4684c1
  STKSTAT (&status);
Packit Service 4684c1
Packit Service 4684c1
  /* Set up the iteration.  */
Packit Service 4684c1
Packit Service 4684c1
  trailer = (struct stk_trailer *) (status.current_address
Packit Service 4684c1
                                    + status.current_size
Packit Service 4684c1
                                    - 15);
Packit Service 4684c1
Packit Service 4684c1
  /* There must be at least one stack segment.  Therefore it is
Packit Service 4684c1
     a fatal error if "trailer" is null.  */
Packit Service 4684c1
Packit Service 4684c1
  if (trailer == NULL)
Packit Service 4684c1
    abort ();
Packit Service 4684c1
Packit Service 4684c1
  /* Discard segments that do not contain our argument address.  */
Packit Service 4684c1
Packit Service 4684c1
  while (trailer != NULL)
Packit Service 4684c1
    {
Packit Service 4684c1
      block = (long *) trailer->this_address;
Packit Service 4684c1
      size = trailer->this_size;
Packit Service 4684c1
      if (block == NULL || size == 0)
Packit Service 4684c1
        abort ();
Packit Service 4684c1
      trailer = (struct stk_trailer *) trailer->link;
Packit Service 4684c1
      if ((block <= address) && (address < (block + size)))
Packit Service 4684c1
        break;
Packit Service 4684c1
    }
Packit Service 4684c1
Packit Service 4684c1
  /* Set the result to the offset in this segment and add the sizes
Packit Service 4684c1
     of all predecessor segments.  */
Packit Service 4684c1
Packit Service 4684c1
  result = address - block;
Packit Service 4684c1
Packit Service 4684c1
  if (trailer == NULL)
Packit Service 4684c1
    {
Packit Service 4684c1
      return result;
Packit Service 4684c1
    }
Packit Service 4684c1
Packit Service 4684c1
  do
Packit Service 4684c1
    {
Packit Service 4684c1
      if (trailer->this_size <= 0)
Packit Service 4684c1
        abort ();
Packit Service 4684c1
      result += trailer->this_size;
Packit Service 4684c1
      trailer = (struct stk_trailer *) trailer->link;
Packit Service 4684c1
    }
Packit Service 4684c1
  while (trailer != NULL);
Packit Service 4684c1
Packit Service 4684c1
  /* We are done.  Note that if you present a bogus address (one
Packit Service 4684c1
     not in any segment), you will get a different number back, formed
Packit Service 4684c1
     from subtracting the address of the first block.  This is probably
Packit Service 4684c1
     not what you want.  */
Packit Service 4684c1
Packit Service 4684c1
  return (result);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#   else /* not CRAY2 */
Packit Service 4684c1
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
Packit Service 4684c1
   Determine the number of the cell within the stack,
Packit Service 4684c1
   given the address of the cell.  The purpose of this
Packit Service 4684c1
   routine is to linearize, in some sense, stack addresses
Packit Service 4684c1
   for alloca.  */
Packit Service 4684c1
Packit Service 4684c1
static long
Packit Service 4684c1
i00afunc (long address)
Packit Service 4684c1
{
Packit Service 4684c1
  long stkl = 0;
Packit Service 4684c1
Packit Service 4684c1
  long size, pseg, this_segment, stack;
Packit Service 4684c1
  long result = 0;
Packit Service 4684c1
Packit Service 4684c1
  struct stack_segment_linkage *ssptr;
Packit Service 4684c1
Packit Service 4684c1
  /* Register B67 contains the address of the end of the
Packit Service 4684c1
     current stack segment.  If you (as a subprogram) store
Packit Service 4684c1
     your registers on the stack and find that you are past
Packit Service 4684c1
     the contents of B67, you have overflowed the segment.
Packit Service 4684c1
Packit Service 4684c1
     B67 also points to the stack segment linkage control
Packit Service 4684c1
     area, which is what we are really interested in.  */
Packit Service 4684c1
Packit Service 4684c1
  stkl = CRAY_STACKSEG_END ();
Packit Service 4684c1
  ssptr = (struct stack_segment_linkage *) stkl;
Packit Service 4684c1
Packit Service 4684c1
  /* If one subtracts 'size' from the end of the segment,
Packit Service 4684c1
     one has the address of the first word of the segment.
Packit Service 4684c1
Packit Service 4684c1
     If this is not the first segment, 'pseg' will be
Packit Service 4684c1
     nonzero.  */
Packit Service 4684c1
Packit Service 4684c1
  pseg = ssptr->sspseg;
Packit Service 4684c1
  size = ssptr->sssize;
Packit Service 4684c1
Packit Service 4684c1
  this_segment = stkl - size;
Packit Service 4684c1
Packit Service 4684c1
  /* It is possible that calling this routine itself caused
Packit Service 4684c1
     a stack overflow.  Discard stack segments which do not
Packit Service 4684c1
     contain the target address.  */
Packit Service 4684c1
Packit Service 4684c1
  while (!(this_segment <= address && address <= stkl))
Packit Service 4684c1
    {
Packit Service 4684c1
#    ifdef DEBUG_I00AFUNC
Packit Service 4684c1
      fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
Packit Service 4684c1
#    endif
Packit Service 4684c1
      if (pseg == 0)
Packit Service 4684c1
        break;
Packit Service 4684c1
      stkl = stkl - pseg;
Packit Service 4684c1
      ssptr = (struct stack_segment_linkage *) stkl;
Packit Service 4684c1
      size = ssptr->sssize;
Packit Service 4684c1
      pseg = ssptr->sspseg;
Packit Service 4684c1
      this_segment = stkl - size;
Packit Service 4684c1
    }
Packit Service 4684c1
Packit Service 4684c1
  result = address - this_segment;
Packit Service 4684c1
Packit Service 4684c1
  /* If you subtract pseg from the current end of the stack,
Packit Service 4684c1
     you get the address of the previous stack segment's end.
Packit Service 4684c1
     This seems a little convoluted to me, but I'll bet you save
Packit Service 4684c1
     a cycle somewhere.  */
Packit Service 4684c1
Packit Service 4684c1
  while (pseg != 0)
Packit Service 4684c1
    {
Packit Service 4684c1
#    ifdef DEBUG_I00AFUNC
Packit Service 4684c1
      fprintf (stderr, "%011o %011o\n", pseg, size);
Packit Service 4684c1
#    endif
Packit Service 4684c1
      stkl = stkl - pseg;
Packit Service 4684c1
      ssptr = (struct stack_segment_linkage *) stkl;
Packit Service 4684c1
      size = ssptr->sssize;
Packit Service 4684c1
      pseg = ssptr->sspseg;
Packit Service 4684c1
      result += size;
Packit Service 4684c1
    }
Packit Service 4684c1
  return (result);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#   endif /* not CRAY2 */
Packit Service 4684c1
#  endif /* CRAY */
Packit Service 4684c1
Packit Service 4684c1
# endif /* no alloca */
Packit Service 4684c1
#endif /* not GCC 2 */