mescc: Support gcc-3.4.0: alloca.
authorJan Nieuwenhuizen <janneke@gnu.org>
Wed, 6 Jun 2018 17:44:29 +0000 (19:44 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Wed, 6 Jun 2018 17:44:29 +0000 (19:44 +0200)
* lib/alloca.c: New file.
* AUTHORS: Mention it.
* lib/libc+gnu.c: Add it.
* include/stdlib.h: Declare alloca.

AUTHORS
include/stdlib.h
lib/alloca.c [new file with mode: 0644]
lib/libc+gnu.c
lib/m4.c

diff --git a/AUTHORS b/AUTHORS
index ea7de2fbbce40a60b4c23ee684b655262ccf270c..3686cbb507e40532ec1c739e863ca3eb3ad8013c 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -8,8 +8,12 @@ lib/libc.c (fopen)
 Han-Wen Nienhuys <hanwen@xs4all.nl>
 lib/libc+tcc.c (_memmem, memmem)
 
+
 List of imported files
 
+D A Gwyn
+lib/alloca.c
+
 Based on Guile ECMAScript
 module/language/c/lexer.mes
 
index 36c21d8dc962de9b8328a58e98373a70be49193c..230291f2b8d8bbd8bf89822953c7d2d8b8b8d451 100644 (file)
 typedef unsigned long size_t;
 #endif
 
+#if _ALLOCA_UNSIGNED
+void * alloca (unsigned size);
+#else
+void * alloca (size_t size);
+#endif
 int atoi (char const *s);
 void * calloc (size_t nmemb, size_t size);
 void exit (int);
@@ -55,6 +60,9 @@ unsigned long long strtoull (char const *nptr, char **endptr, int base);
 #define EXIT_FAILURE 1
 #define EXIT_SUCCESS 0
 
+#ifndef NULL
+#define NULL 0
+#endif
 
 #if __MESC__
 typedef int (*comparison_fn_t) (void const *, void const *);
diff --git a/lib/alloca.c b/lib/alloca.c
new file mode 100644 (file)
index 0000000..53dbdc8
--- /dev/null
@@ -0,0 +1,98 @@
+/* alloca.c -- allocate automatically reclaimed memory
+   (Mostly) portable public-domain implementation -- D A Gwyn
+
+   This implementation of the PWB library alloca function,
+   which is used to allocate space off the run-time stack so
+   that it is automatically reclaimed upon procedure exit,
+   was inspired by discussions with J. Q. Johnson of Cornell.
+
+   There are some preprocessor constants that can
+   be defined when compiling for your specific system, for
+   improved efficiency; however, the defaults should be okay.
+
+   The general concept of this implementation is to keep
+   track of all alloca-allocated blocks, and reclaim any
+   that are found to be deeper in the stack than the current
+   invocation.  This heuristic does not reclaim storage as
+   soon as it becomes invalid, but it will do so eventually.
+
+   As a special case, alloca(0) reclaims storage without
+   allocating any.  It is a good idea to use alloca(0) in
+   your main control loop, etc. to force garbage collection.  */
+
+#include <unistd.h>
+
+#define ALIGN_SIZE 4
+#define ADDRESS_FUNCTION(arg) &(arg)
+#define STACK_DIR -1
+
+union alloca_header
+{
+  char align[ALIGN_SIZE];      /* To force sizeof(union alloca_header).  */
+  struct
+    {
+      union alloca_header *next;               /* For chaining headers.  */
+      char *deep;              /* For stack depth measure.  */
+    } h;
+};
+
+static union alloca_header *last_alloca_header = NULL; /* -> last alloca header.  */
+
+/* Return a void * to at least SIZE bytes of storage,
+   which will be automatically reclaimed upon exit from
+   the procedure that called alloca.  Originally, this space
+   was supposed to be taken from the current stack frame of the
+   caller, but that method cannot be made to work for some
+   implementations of C, for example under Gould's UTX/32.  */
+
+void *
+alloca (size_t size)
+{
+  char probe;          /* Probes stack depth: */
+  char *depth = ADDRESS_FUNCTION (probe);
+
+  /* Reclaim garbage, defined as all alloca'd storage that
+     was allocated from deeper in the stack than currently.  */
+
+  {
+    union alloca_header *hp;   /* Traverses linked list.  */
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if ((STACK_DIR > 0 && hp->h.deep > depth)
+         || (STACK_DIR < 0 && hp->h.deep < depth))
+       {
+         union alloca_header *np = hp->h.next;
+
+         free ((void *) hp);   /* Collect garbage.  */
+
+         hp = np;              /* -> next header.  */
+       }
+      else
+       break;                  /* Rest are not deeper.  */
+
+    last_alloca_header = hp;   /* -> last valid storage.  */
+
+  }
+
+  if (size == 0)
+    return NULL;               /* No allocation required.  */
+
+  /* Allocate combined header + user data storage.  */
+
+  {
+    void * new = malloc (sizeof (union alloca_header) + size);
+    /* Address of header.  */
+
+    if (new == 0)
+      abort();
+
+    ((union alloca_header *) new)->h.next = last_alloca_header;
+    ((union alloca_header *) new)->h.deep = depth;
+
+    last_alloca_header = (union alloca_header *) new;
+
+    /* User storage begins just after header.  */
+
+    return (void *) ((char *) new + sizeof (union alloca_header));
+  }
+}
index 5cd48c23a0dc51fe9734a4b8a14c0d2248981fd9..abdedd344a8672872f523c24f0114ec323dcf5b2 100644 (file)
@@ -23,4 +23,5 @@
 #include <m4.c>
 #include <binutils.c>
 #include <gcc.c>
+#include <alloca.c>
 #include <glibc.c>
index f1e4ae7dce925d6fe103ae50feb01a8a7da03232..b4ff9c2e718af6d9147255218c6b2c2081dff305 100644 (file)
--- a/lib/m4.c
+++ b/lib/m4.c
@@ -19,7 +19,7 @@
  */
 
 int
-abort (int x)
+abort ()
 {
   eputs ("abort stub\n");
   return 0;