summaryrefslogtreecommitdiff
path: root/ar/alloca.c
diff options
context:
space:
mode:
Diffstat (limited to 'ar/alloca.c')
-rw-r--r--ar/alloca.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/ar/alloca.c b/ar/alloca.c
new file mode 100644
index 0000000..880c100
--- /dev/null
+++ b/ar/alloca.c
@@ -0,0 +1,61 @@
+
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <memory.h>
+#include <string.h>
+#endif
+
+#ifdef __TINYC__
+typedef union mem_cell
+{
+ union mem_cell *next; /* A pointer to the next mem */
+ unsigned int size; /* An int >= sizeof pointer */
+ char *depth; /* For the alloca hack */
+}
+mem;
+
+#define m_size(p) ((p) [0].size) /* For malloc */
+#define m_next(p) ((p) [1].next) /* For malloc and alloca */
+#define m_deep(p) ((p) [0].depth) /* For alloca */
+
+static mem *alloca_stack = 0;
+
+void *
+alloca(size)
+size_t size;
+{
+ auto char probe; /* Probes stack depth: */
+ register mem *hp;
+
+ /*
+ * Reclaim garbage, defined as all alloca'd storage that was allocated
+ * from deeper in the stack than currently.
+ */
+
+ for (hp = alloca_stack; hp != 0;)
+ if (m_deep(hp) < &probe)
+ {
+ register mem *np = m_next(hp);
+ free((void *) hp); /* Collect garbage. */
+ hp = np; /* -> next header. */
+ }
+ else
+ break; /* Rest are not deeper. */
+
+ alloca_stack = hp; /* -> last valid storage. */
+ if (size == 0)
+ return 0; /* No allocation required. */
+
+ hp = (mem *) malloc(sizeof(mem)*2 + size);
+ if (hp == 0)
+ return hp;
+
+ m_next(hp) = alloca_stack;
+ m_deep(hp) = &probe;
+ alloca_stack = hp;
+
+ /* User storage begins just after header. */
+ return (void *) (hp + 2);
+}
+#endif