xref: /netbsd-src/external/gpl3/gdb/dist/gnulib/import/alloca.c (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
18dffb485Schristos /* alloca.c -- allocate automatically reclaimed memory
2*4b169a6bSchristos    This file is in the public domain.  */
3*4b169a6bSchristos 
4*4b169a6bSchristos /* (Mostly) portable implementation -- D A Gwyn
58dffb485Schristos 
68dffb485Schristos    This implementation of the PWB library alloca function,
78dffb485Schristos    which is used to allocate space off the run-time stack so
88dffb485Schristos    that it is automatically reclaimed upon procedure exit,
98dffb485Schristos    was inspired by discussions with J. Q. Johnson of Cornell.
108dffb485Schristos    J.Otto Tennant <jot@cray.com> contributed the Cray support.
118dffb485Schristos 
128dffb485Schristos    There are some preprocessor constants that can
138dffb485Schristos    be defined when compiling for your specific system, for
148dffb485Schristos    improved efficiency; however, the defaults should be okay.
158dffb485Schristos 
168dffb485Schristos    The general concept of this implementation is to keep
178dffb485Schristos    track of all alloca-allocated blocks, and reclaim any
188dffb485Schristos    that are found to be deeper in the stack than the current
198dffb485Schristos    invocation.  This heuristic does not reclaim storage as
208dffb485Schristos    soon as it becomes invalid, but it will do so eventually.
218dffb485Schristos 
228dffb485Schristos    As a special case, alloca(0) reclaims storage without
238dffb485Schristos    allocating any.  It is a good idea to use alloca(0) in
248dffb485Schristos    your main control loop, etc. to force garbage collection.  */
258dffb485Schristos 
268dffb485Schristos #include <config.h>
278dffb485Schristos 
288dffb485Schristos #include <alloca.h>
298dffb485Schristos 
308dffb485Schristos #include <string.h>
318dffb485Schristos #include <stdlib.h>
328dffb485Schristos 
338dffb485Schristos #ifdef emacs
348dffb485Schristos # include "lisp.h"
358dffb485Schristos # include "blockinput.h"
368dffb485Schristos # ifdef EMACS_FREE
378dffb485Schristos #  undef free
388dffb485Schristos #  define free EMACS_FREE
398dffb485Schristos # endif
408dffb485Schristos #else
418dffb485Schristos # define memory_full() abort ()
428dffb485Schristos #endif
438dffb485Schristos 
44*4b169a6bSchristos /* If compiling with GCC or clang, this file is not needed.  */
45*4b169a6bSchristos #if !(defined __GNUC__ || defined __clang__)
468dffb485Schristos 
478dffb485Schristos /* If someone has defined alloca as a macro,
488dffb485Schristos    there must be some other way alloca is supposed to work.  */
498dffb485Schristos # ifndef alloca
508dffb485Schristos 
518dffb485Schristos #  ifdef emacs
528dffb485Schristos #   ifdef static
538dffb485Schristos /* actually, only want this if static is defined as ""
548dffb485Schristos    -- this is for usg, in which emacs must undefine static
558dffb485Schristos    in order to make unexec workable
568dffb485Schristos    */
578dffb485Schristos #    ifndef STACK_DIRECTION
588dffb485Schristos you
598dffb485Schristos lose
608dffb485Schristos -- must know STACK_DIRECTION at compile-time
618dffb485Schristos /* Using #error here is not wise since this file should work for
628dffb485Schristos    old and obscure compilers.  */
638dffb485Schristos #    endif /* STACK_DIRECTION undefined */
648dffb485Schristos #   endif /* static */
658dffb485Schristos #  endif /* emacs */
668dffb485Schristos 
678dffb485Schristos /* Define STACK_DIRECTION if you know the direction of stack
688dffb485Schristos    growth for your system; otherwise it will be automatically
698dffb485Schristos    deduced at run-time.
708dffb485Schristos 
718dffb485Schristos    STACK_DIRECTION > 0 => grows toward higher addresses
728dffb485Schristos    STACK_DIRECTION < 0 => grows toward lower addresses
738dffb485Schristos    STACK_DIRECTION = 0 => direction of growth unknown  */
748dffb485Schristos 
758dffb485Schristos #  ifndef STACK_DIRECTION
768dffb485Schristos #   define STACK_DIRECTION      0       /* Direction unknown.  */
778dffb485Schristos #  endif
788dffb485Schristos 
798dffb485Schristos #  if STACK_DIRECTION != 0
808dffb485Schristos 
818dffb485Schristos #   define STACK_DIR    STACK_DIRECTION /* Known at compile-time.  */
828dffb485Schristos 
838dffb485Schristos #  else /* STACK_DIRECTION == 0; need run-time code.  */
848dffb485Schristos 
858dffb485Schristos static int stack_dir;           /* 1 or -1 once known.  */
868dffb485Schristos #   define STACK_DIR    stack_dir
878dffb485Schristos 
888dffb485Schristos static int
898dffb485Schristos find_stack_direction (int *addr, int depth)
908dffb485Schristos {
918dffb485Schristos   int dir, dummy = 0;
928dffb485Schristos   if (! addr)
938dffb485Schristos     addr = &dummy;
948dffb485Schristos   *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1;
958dffb485Schristos   dir = depth ? find_stack_direction (addr, depth - 1) : 0;
968dffb485Schristos   return dir + dummy;
978dffb485Schristos }
988dffb485Schristos 
998dffb485Schristos #  endif /* STACK_DIRECTION == 0 */
1008dffb485Schristos 
1018dffb485Schristos /* An "alloca header" is used to:
1028dffb485Schristos    (a) chain together all alloca'ed blocks;
1038dffb485Schristos    (b) keep track of stack depth.
1048dffb485Schristos 
1058dffb485Schristos    It is very important that sizeof(header) agree with malloc
1068dffb485Schristos    alignment chunk size.  The following default should work okay.  */
1078dffb485Schristos 
1088dffb485Schristos #  ifndef       ALIGN_SIZE
1098dffb485Schristos #   define ALIGN_SIZE   sizeof(double)
1108dffb485Schristos #  endif
1118dffb485Schristos 
1128dffb485Schristos typedef union hdr
1138dffb485Schristos {
1148dffb485Schristos   char align[ALIGN_SIZE];       /* To force sizeof(header).  */
1158dffb485Schristos   struct
1168dffb485Schristos     {
1178dffb485Schristos       union hdr *next;          /* For chaining headers.  */
1188dffb485Schristos       char *deep;               /* For stack depth measure.  */
1198dffb485Schristos     } h;
1208dffb485Schristos } header;
1218dffb485Schristos 
1228dffb485Schristos static header *last_alloca_header = NULL;       /* -> last alloca header.  */
1238dffb485Schristos 
1248dffb485Schristos /* Return a pointer to at least SIZE bytes of storage,
1258dffb485Schristos    which will be automatically reclaimed upon exit from
1268dffb485Schristos    the procedure that called alloca.  Originally, this space
1278dffb485Schristos    was supposed to be taken from the current stack frame of the
1288dffb485Schristos    caller, but that method cannot be made to work for some
1298dffb485Schristos    implementations of C, for example under Gould's UTX/32.  */
1308dffb485Schristos 
1318dffb485Schristos void *
alloca(size_t size)1328dffb485Schristos alloca (size_t size)
1338dffb485Schristos {
1348dffb485Schristos   auto char probe;              /* Probes stack depth: */
135*4b169a6bSchristos   register char *depth = &probe;
1368dffb485Schristos 
1378dffb485Schristos #  if STACK_DIRECTION == 0
1388dffb485Schristos   if (STACK_DIR == 0)           /* Unknown growth direction.  */
1398dffb485Schristos     STACK_DIR = find_stack_direction (NULL, (size & 1) + 20);
1408dffb485Schristos #  endif
1418dffb485Schristos 
1428dffb485Schristos   /* Reclaim garbage, defined as all alloca'd storage that
1438dffb485Schristos      was allocated from deeper in the stack than currently.  */
1448dffb485Schristos 
1458dffb485Schristos   {
1468dffb485Schristos     register header *hp;        /* Traverses linked list.  */
1478dffb485Schristos 
1488dffb485Schristos #  ifdef emacs
1498dffb485Schristos     BLOCK_INPUT;
1508dffb485Schristos #  endif
1518dffb485Schristos 
1528dffb485Schristos     for (hp = last_alloca_header; hp != NULL;)
1538dffb485Schristos       if ((STACK_DIR > 0 && hp->h.deep > depth)
1548dffb485Schristos           || (STACK_DIR < 0 && hp->h.deep < depth))
1558dffb485Schristos         {
1568dffb485Schristos           register header *np = hp->h.next;
1578dffb485Schristos 
1588dffb485Schristos           free (hp);            /* Collect garbage.  */
1598dffb485Schristos 
1608dffb485Schristos           hp = np;              /* -> next header.  */
1618dffb485Schristos         }
1628dffb485Schristos       else
1638dffb485Schristos         break;                  /* Rest are not deeper.  */
1648dffb485Schristos 
1658dffb485Schristos     last_alloca_header = hp;    /* -> last valid storage.  */
1668dffb485Schristos 
1678dffb485Schristos #  ifdef emacs
1688dffb485Schristos     UNBLOCK_INPUT;
1698dffb485Schristos #  endif
1708dffb485Schristos   }
1718dffb485Schristos 
1728dffb485Schristos   if (size == 0)
1738dffb485Schristos     return NULL;                /* No allocation required.  */
1748dffb485Schristos 
1758dffb485Schristos   /* Allocate combined header + user data storage.  */
1768dffb485Schristos 
1778dffb485Schristos   {
1788dffb485Schristos     /* Address of header.  */
1798dffb485Schristos     register header *new;
1808dffb485Schristos 
1818dffb485Schristos     size_t combined_size = sizeof (header) + size;
1828dffb485Schristos     if (combined_size < sizeof (header))
1838dffb485Schristos       memory_full ();
1848dffb485Schristos 
1858dffb485Schristos     new = malloc (combined_size);
1868dffb485Schristos 
1878dffb485Schristos     if (! new)
1888dffb485Schristos       memory_full ();
1898dffb485Schristos 
1908dffb485Schristos     new->h.next = last_alloca_header;
1918dffb485Schristos     new->h.deep = depth;
1928dffb485Schristos 
1938dffb485Schristos     last_alloca_header = new;
1948dffb485Schristos 
1958dffb485Schristos     /* User storage begins just after header.  */
1968dffb485Schristos 
1978dffb485Schristos     return (void *) (new + 1);
1988dffb485Schristos   }
1998dffb485Schristos }
2008dffb485Schristos 
2018dffb485Schristos # endif /* no alloca */
202*4b169a6bSchristos #endif /* not GCC || clang */
203