mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-06 01:16:17 +01:00
Add checks for alloca, defining G_NATIVE_ALLOCA if present.
Fri Jan 22 13:41:41 EST 1999 Jeff Garzik <jgarzik@pobox.com> * configure.in: Add checks for alloca, defining G_NATIVE_ALLOCA if present. * galloca.c: Import replacement alloca implementation from gettext 0.10.35. Begin to convert to using GLib types and functions. * glib.h: New macros g_alloca, g_alloca_gc, g_alloca_new, to perform stack-based memory allocations. * tests/Makefile.am, tests/queue-test.c, tests/alloca-test.c: New tests for g_alloca_*, GQueue ADT. * tests/stack-test.c: Fix pointer casts, include config.h, and call g_stack_free at end of run.
This commit is contained in:
parent
b5706b2604
commit
0d0f178c09
22
ChangeLog
22
ChangeLog
@ -1,7 +1,27 @@
|
||||
Fri Jan 22 13:41:41 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* configure.in:
|
||||
Add checks for alloca, defining G_NATIVE_ALLOCA if present.
|
||||
|
||||
* galloca.c:
|
||||
Import replacement alloca implementation from gettext 0.10.35.
|
||||
Begin to convert to using GLib types and functions.
|
||||
|
||||
* glib.h:
|
||||
New macros g_alloca, g_alloca_gc, g_alloca_new, to perform
|
||||
stack-based memory allocations.
|
||||
|
||||
* tests/Makefile.am, tests/queue-test.c, tests/alloca-test.c:
|
||||
New tests for g_alloca_*, GQueue ADT.
|
||||
|
||||
* tests/stack-test.c:
|
||||
Fix pointer casts, include config.h, and
|
||||
call g_stack_free at end of run.
|
||||
|
||||
Fri Jan 22 11:58:13 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* Makefile.am:
|
||||
Add gqueue.c
|
||||
Add gqueue.c.
|
||||
|
||||
* glib.h:
|
||||
Add GQueue struct and prototypes.
|
||||
|
@ -1,7 +1,27 @@
|
||||
Fri Jan 22 13:41:41 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* configure.in:
|
||||
Add checks for alloca, defining G_NATIVE_ALLOCA if present.
|
||||
|
||||
* galloca.c:
|
||||
Import replacement alloca implementation from gettext 0.10.35.
|
||||
Begin to convert to using GLib types and functions.
|
||||
|
||||
* glib.h:
|
||||
New macros g_alloca, g_alloca_gc, g_alloca_new, to perform
|
||||
stack-based memory allocations.
|
||||
|
||||
* tests/Makefile.am, tests/queue-test.c, tests/alloca-test.c:
|
||||
New tests for g_alloca_*, GQueue ADT.
|
||||
|
||||
* tests/stack-test.c:
|
||||
Fix pointer casts, include config.h, and
|
||||
call g_stack_free at end of run.
|
||||
|
||||
Fri Jan 22 11:58:13 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* Makefile.am:
|
||||
Add gqueue.c
|
||||
Add gqueue.c.
|
||||
|
||||
* glib.h:
|
||||
Add GQueue struct and prototypes.
|
||||
|
@ -1,7 +1,27 @@
|
||||
Fri Jan 22 13:41:41 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* configure.in:
|
||||
Add checks for alloca, defining G_NATIVE_ALLOCA if present.
|
||||
|
||||
* galloca.c:
|
||||
Import replacement alloca implementation from gettext 0.10.35.
|
||||
Begin to convert to using GLib types and functions.
|
||||
|
||||
* glib.h:
|
||||
New macros g_alloca, g_alloca_gc, g_alloca_new, to perform
|
||||
stack-based memory allocations.
|
||||
|
||||
* tests/Makefile.am, tests/queue-test.c, tests/alloca-test.c:
|
||||
New tests for g_alloca_*, GQueue ADT.
|
||||
|
||||
* tests/stack-test.c:
|
||||
Fix pointer casts, include config.h, and
|
||||
call g_stack_free at end of run.
|
||||
|
||||
Fri Jan 22 11:58:13 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* Makefile.am:
|
||||
Add gqueue.c
|
||||
Add gqueue.c.
|
||||
|
||||
* glib.h:
|
||||
Add GQueue struct and prototypes.
|
||||
|
@ -1,7 +1,27 @@
|
||||
Fri Jan 22 13:41:41 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* configure.in:
|
||||
Add checks for alloca, defining G_NATIVE_ALLOCA if present.
|
||||
|
||||
* galloca.c:
|
||||
Import replacement alloca implementation from gettext 0.10.35.
|
||||
Begin to convert to using GLib types and functions.
|
||||
|
||||
* glib.h:
|
||||
New macros g_alloca, g_alloca_gc, g_alloca_new, to perform
|
||||
stack-based memory allocations.
|
||||
|
||||
* tests/Makefile.am, tests/queue-test.c, tests/alloca-test.c:
|
||||
New tests for g_alloca_*, GQueue ADT.
|
||||
|
||||
* tests/stack-test.c:
|
||||
Fix pointer casts, include config.h, and
|
||||
call g_stack_free at end of run.
|
||||
|
||||
Fri Jan 22 11:58:13 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* Makefile.am:
|
||||
Add gqueue.c
|
||||
Add gqueue.c.
|
||||
|
||||
* glib.h:
|
||||
Add GQueue struct and prototypes.
|
||||
|
@ -1,7 +1,27 @@
|
||||
Fri Jan 22 13:41:41 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* configure.in:
|
||||
Add checks for alloca, defining G_NATIVE_ALLOCA if present.
|
||||
|
||||
* galloca.c:
|
||||
Import replacement alloca implementation from gettext 0.10.35.
|
||||
Begin to convert to using GLib types and functions.
|
||||
|
||||
* glib.h:
|
||||
New macros g_alloca, g_alloca_gc, g_alloca_new, to perform
|
||||
stack-based memory allocations.
|
||||
|
||||
* tests/Makefile.am, tests/queue-test.c, tests/alloca-test.c:
|
||||
New tests for g_alloca_*, GQueue ADT.
|
||||
|
||||
* tests/stack-test.c:
|
||||
Fix pointer casts, include config.h, and
|
||||
call g_stack_free at end of run.
|
||||
|
||||
Fri Jan 22 11:58:13 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* Makefile.am:
|
||||
Add gqueue.c
|
||||
Add gqueue.c.
|
||||
|
||||
* glib.h:
|
||||
Add GQueue struct and prototypes.
|
||||
|
@ -1,7 +1,27 @@
|
||||
Fri Jan 22 13:41:41 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* configure.in:
|
||||
Add checks for alloca, defining G_NATIVE_ALLOCA if present.
|
||||
|
||||
* galloca.c:
|
||||
Import replacement alloca implementation from gettext 0.10.35.
|
||||
Begin to convert to using GLib types and functions.
|
||||
|
||||
* glib.h:
|
||||
New macros g_alloca, g_alloca_gc, g_alloca_new, to perform
|
||||
stack-based memory allocations.
|
||||
|
||||
* tests/Makefile.am, tests/queue-test.c, tests/alloca-test.c:
|
||||
New tests for g_alloca_*, GQueue ADT.
|
||||
|
||||
* tests/stack-test.c:
|
||||
Fix pointer casts, include config.h, and
|
||||
call g_stack_free at end of run.
|
||||
|
||||
Fri Jan 22 11:58:13 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* Makefile.am:
|
||||
Add gqueue.c
|
||||
Add gqueue.c.
|
||||
|
||||
* glib.h:
|
||||
Add GQueue struct and prototypes.
|
||||
|
@ -1,7 +1,27 @@
|
||||
Fri Jan 22 13:41:41 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* configure.in:
|
||||
Add checks for alloca, defining G_NATIVE_ALLOCA if present.
|
||||
|
||||
* galloca.c:
|
||||
Import replacement alloca implementation from gettext 0.10.35.
|
||||
Begin to convert to using GLib types and functions.
|
||||
|
||||
* glib.h:
|
||||
New macros g_alloca, g_alloca_gc, g_alloca_new, to perform
|
||||
stack-based memory allocations.
|
||||
|
||||
* tests/Makefile.am, tests/queue-test.c, tests/alloca-test.c:
|
||||
New tests for g_alloca_*, GQueue ADT.
|
||||
|
||||
* tests/stack-test.c:
|
||||
Fix pointer casts, include config.h, and
|
||||
call g_stack_free at end of run.
|
||||
|
||||
Fri Jan 22 11:58:13 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* Makefile.am:
|
||||
Add gqueue.c
|
||||
Add gqueue.c.
|
||||
|
||||
* glib.h:
|
||||
Add GQueue struct and prototypes.
|
||||
|
@ -1,7 +1,27 @@
|
||||
Fri Jan 22 13:41:41 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* configure.in:
|
||||
Add checks for alloca, defining G_NATIVE_ALLOCA if present.
|
||||
|
||||
* galloca.c:
|
||||
Import replacement alloca implementation from gettext 0.10.35.
|
||||
Begin to convert to using GLib types and functions.
|
||||
|
||||
* glib.h:
|
||||
New macros g_alloca, g_alloca_gc, g_alloca_new, to perform
|
||||
stack-based memory allocations.
|
||||
|
||||
* tests/Makefile.am, tests/queue-test.c, tests/alloca-test.c:
|
||||
New tests for g_alloca_*, GQueue ADT.
|
||||
|
||||
* tests/stack-test.c:
|
||||
Fix pointer casts, include config.h, and
|
||||
call g_stack_free at end of run.
|
||||
|
||||
Fri Jan 22 11:58:13 EST 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* Makefile.am:
|
||||
Add gqueue.c
|
||||
Add gqueue.c.
|
||||
|
||||
* glib.h:
|
||||
Add GQueue struct and prototypes.
|
||||
|
47
configure.in
47
configure.in
@ -171,6 +171,12 @@ AC_HEADER_STDC
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_VPRINTF
|
||||
AC_FUNC_ALLOCA
|
||||
if test "x$ac_cv_func_alloca_works" = xyes; then
|
||||
glib_have_alloca=yes
|
||||
else
|
||||
glib_have_alloca=no
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(atexit on_exit)
|
||||
|
||||
@ -248,6 +254,7 @@ AC_CHECK_HEADERS(sys/time.h, AC_DEFINE(HAVE_SYS_TIME_H))
|
||||
AC_CHECK_HEADERS(sys/times.h, AC_DEFINE(HAVE_SYS_TIMES_H))
|
||||
AC_CHECK_HEADERS(unistd.h, AC_DEFINE(HAVE_UNISTD_H))
|
||||
AC_CHECK_HEADERS(values.h, AC_DEFINE(HAVE_VALUES_H))
|
||||
AC_CHECK_HEADER(alloca.h, glib_have_alloca_h=yes, glib_have_alloca_h=no)
|
||||
|
||||
# Check for some functions
|
||||
AC_CHECK_FUNCS(lstat strerror strsignal memmove vsnprintf strcasecmp strncasecmp poll)
|
||||
@ -904,6 +911,7 @@ _______EOF
|
||||
cat >>$outfile <<_______EOF
|
||||
$glib_atexit
|
||||
$glib_memmove
|
||||
$glib_alloca
|
||||
$glib_defines
|
||||
|
||||
$glib_vacopy
|
||||
@ -1169,6 +1177,45 @@ if test x$glib_working_wctype = xno; then
|
||||
#define G_HAVE_BROKEN_WCTYPE 1"
|
||||
fi
|
||||
|
||||
if test x$glib_have_alloca = xyes; then
|
||||
glib_alloca="
|
||||
|
||||
/* alloca support */"
|
||||
|
||||
if test x$glib_have_alloca_h = xyes; then
|
||||
glib_alloca="\$glib_alloca
|
||||
#define G_HAVE_ALLOCA_H 1"
|
||||
fi
|
||||
|
||||
glib_alloca="\$glib_alloca
|
||||
#define G_NATIVE_ALLOCA 1
|
||||
|
||||
/* BEGIN autoconf 2.13 alloca incantation
|
||||
NOTE: Do not un-indent the #pragma below. */
|
||||
/* AIX requires this to be the first thing in the file. */
|
||||
#ifdef __GNUC__
|
||||
# ifndef alloca
|
||||
# define alloca __builtin_alloca
|
||||
# endif
|
||||
#else
|
||||
# if G_HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
/* END autoconf 2.13 alloca incantation */
|
||||
|
||||
|
||||
"
|
||||
fi
|
||||
|
||||
case x$enable_threads in
|
||||
xyes) g_enable_threads_def="#define";;
|
||||
*) g_enable_threads_def="#undef ";;
|
||||
|
456
galloca.c
Normal file
456
galloca.c
Normal file
@ -0,0 +1,456 @@
|
||||
/* 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.
|
||||
J.Otto Tennant <jot@cray.com> contributed the Cray support.
|
||||
|
||||
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. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
|
||||
|
||||
#ifndef G_NATIVE_ALLOCA
|
||||
|
||||
|
||||
|
||||
/* If your stack is a linked list of frames, you have to
|
||||
provide an "address metric" ADDRESS_FUNCTION macro. */
|
||||
|
||||
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
long i00afunc ();
|
||||
#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
|
||||
#else
|
||||
#define ADDRESS_FUNCTION(arg) &(arg)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Define STACK_DIRECTION if you know the direction of stack
|
||||
growth for your system; otherwise it will be automatically
|
||||
deduced at run-time.
|
||||
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
|
||||
#ifndef STACK_DIRECTION
|
||||
#define STACK_DIRECTION 0 /* Direction unknown. */
|
||||
#endif
|
||||
|
||||
#if STACK_DIRECTION != 0
|
||||
|
||||
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
|
||||
|
||||
#else /* STACK_DIRECTION == 0; need run-time code. */
|
||||
|
||||
static int stack_dir; /* 1 or -1 once known. */
|
||||
#define STACK_DIR stack_dir
|
||||
|
||||
static void
|
||||
find_stack_direction ()
|
||||
{
|
||||
static char *addr = NULL; /* Address of first `dummy', once known. */
|
||||
auto char dummy; /* To get stack address. */
|
||||
|
||||
if (addr == NULL)
|
||||
{ /* Initial entry. */
|
||||
addr = ADDRESS_FUNCTION (dummy);
|
||||
|
||||
find_stack_direction (); /* Recurse once. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Second entry. */
|
||||
if (ADDRESS_FUNCTION (dummy) > addr)
|
||||
stack_dir = 1; /* Stack grew upward. */
|
||||
else
|
||||
stack_dir = -1; /* Stack grew downward. */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* STACK_DIRECTION == 0 */
|
||||
|
||||
|
||||
|
||||
/* An "alloca header" is used to:
|
||||
(a) chain together all alloca'ed blocks;
|
||||
(b) keep track of stack depth.
|
||||
|
||||
It is very important that sizeof(header) agree with malloc
|
||||
alignment chunk size. The following default should work okay. */
|
||||
|
||||
#ifndef ALIGN_SIZE
|
||||
#define ALIGN_SIZE sizeof(double)
|
||||
#endif
|
||||
|
||||
typedef union hdr
|
||||
{
|
||||
char align[ALIGN_SIZE]; /* To force sizeof(header). */
|
||||
struct
|
||||
{
|
||||
union hdr *next; /* For chaining headers. */
|
||||
char *deep; /* For stack depth measure. */
|
||||
} h;
|
||||
} header;
|
||||
|
||||
static header *last_alloca_header = NULL; /* -> last alloca header. */
|
||||
|
||||
/* Return a pointer 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. */
|
||||
|
||||
gpointer
|
||||
_g_alloca (guint size)
|
||||
{
|
||||
auto char probe; /* Probes stack depth: */
|
||||
char *depth = ADDRESS_FUNCTION (probe);
|
||||
|
||||
#if STACK_DIRECTION == 0
|
||||
if (STACK_DIR == 0) /* Unknown growth direction. */
|
||||
find_stack_direction ();
|
||||
#endif
|
||||
|
||||
/* Reclaim garbage, defined as all alloca'd storage that
|
||||
was allocated from deeper in the stack than currently. */
|
||||
|
||||
{
|
||||
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))
|
||||
{
|
||||
header *np = hp->h.next;
|
||||
|
||||
g_free ((gpointer) 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. */
|
||||
|
||||
{
|
||||
/* GLib: use mem chunks here? */
|
||||
gpointer new = g_malloc (sizeof (header) + size);
|
||||
/* Address of header. */
|
||||
|
||||
if (new == 0)
|
||||
abort();
|
||||
|
||||
((header *) new)->h.next = last_alloca_header;
|
||||
((header *) new)->h.deep = depth;
|
||||
|
||||
last_alloca_header = (header *) new;
|
||||
|
||||
/* User storage begins just after header. */
|
||||
|
||||
return (gpointer) ((char *) new + sizeof (header));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifndef CRAY_STACK
|
||||
#define CRAY_STACK
|
||||
#ifndef CRAY2
|
||||
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
|
||||
struct stack_control_header
|
||||
{
|
||||
long shgrow:32; /* Number of times stack has grown. */
|
||||
long shaseg:32; /* Size of increments to stack. */
|
||||
long shhwm:32; /* High water mark of stack. */
|
||||
long shsize:32; /* Current size of stack (all segments). */
|
||||
};
|
||||
|
||||
/* The stack segment linkage control information occurs at
|
||||
the high-address end of a stack segment. (The stack
|
||||
grows from low addresses to high addresses.) The initial
|
||||
part of the stack segment linkage control information is
|
||||
0200 (octal) words. This provides for register storage
|
||||
for the routine which overflows the stack. */
|
||||
|
||||
struct stack_segment_linkage
|
||||
{
|
||||
long ss[0200]; /* 0200 overflow words. */
|
||||
long sssize:32; /* Number of words in this segment. */
|
||||
long ssbase:32; /* Offset to stack base. */
|
||||
long:32;
|
||||
long sspseg:32; /* Offset to linkage control of previous
|
||||
segment of stack. */
|
||||
long:32;
|
||||
long sstcpt:32; /* Pointer to task common address block. */
|
||||
long sscsnm; /* Private control structure number for
|
||||
microtasking. */
|
||||
long ssusr1; /* Reserved for user. */
|
||||
long ssusr2; /* Reserved for user. */
|
||||
long sstpid; /* Process ID for pid based multi-tasking. */
|
||||
long ssgvup; /* Pointer to multitasking thread giveup. */
|
||||
long sscray[7]; /* Reserved for Cray Research. */
|
||||
long ssa0;
|
||||
long ssa1;
|
||||
long ssa2;
|
||||
long ssa3;
|
||||
long ssa4;
|
||||
long ssa5;
|
||||
long ssa6;
|
||||
long ssa7;
|
||||
long sss0;
|
||||
long sss1;
|
||||
long sss2;
|
||||
long sss3;
|
||||
long sss4;
|
||||
long sss5;
|
||||
long sss6;
|
||||
long sss7;
|
||||
};
|
||||
|
||||
#else /* CRAY2 */
|
||||
/* The following structure defines the vector of words
|
||||
returned by the STKSTAT library routine. */
|
||||
struct stk_stat
|
||||
{
|
||||
long now; /* Current total stack size. */
|
||||
long maxc; /* Amount of contiguous space which would
|
||||
be required to satisfy the maximum
|
||||
stack demand to date. */
|
||||
long high_water; /* Stack high-water mark. */
|
||||
long overflows; /* Number of stack overflow ($STKOFEN) calls. */
|
||||
long hits; /* Number of internal buffer hits. */
|
||||
long extends; /* Number of block extensions. */
|
||||
long stko_mallocs; /* Block allocations by $STKOFEN. */
|
||||
long underflows; /* Number of stack underflow calls ($STKRETN). */
|
||||
long stko_free; /* Number of deallocations by $STKRETN. */
|
||||
long stkm_free; /* Number of deallocations by $STKMRET. */
|
||||
long segments; /* Current number of stack segments. */
|
||||
long maxs; /* Maximum number of stack segments so far. */
|
||||
long pad_size; /* Stack pad size. */
|
||||
long current_address; /* Current stack segment address. */
|
||||
long current_size; /* Current stack segment size. This
|
||||
number is actually corrupted by STKSTAT to
|
||||
include the fifteen word trailer area. */
|
||||
long initial_address; /* Address of initial segment. */
|
||||
long initial_size; /* Size of initial segment. */
|
||||
};
|
||||
|
||||
/* The following structure describes the data structure which trails
|
||||
any stack segment. I think that the description in 'asdef' is
|
||||
out of date. I only describe the parts that I am sure about. */
|
||||
|
||||
struct stk_trailer
|
||||
{
|
||||
long this_address; /* Address of this block. */
|
||||
long this_size; /* Size of this block (does not include
|
||||
this trailer). */
|
||||
long unknown2;
|
||||
long unknown3;
|
||||
long link; /* Address of trailer block of previous
|
||||
segment. */
|
||||
long unknown5;
|
||||
long unknown6;
|
||||
long unknown7;
|
||||
long unknown8;
|
||||
long unknown9;
|
||||
long unknown10;
|
||||
long unknown11;
|
||||
long unknown12;
|
||||
long unknown13;
|
||||
long unknown14;
|
||||
};
|
||||
|
||||
#endif /* CRAY2 */
|
||||
#endif /* not CRAY_STACK */
|
||||
|
||||
#ifdef CRAY2
|
||||
/* Determine a "stack measure" for an arbitrary ADDRESS.
|
||||
I doubt that "lint" will like this much. */
|
||||
|
||||
static long
|
||||
i00afunc (long *address)
|
||||
{
|
||||
struct stk_stat status;
|
||||
struct stk_trailer *trailer;
|
||||
long *block, size;
|
||||
long result = 0;
|
||||
|
||||
/* We want to iterate through all of the segments. The first
|
||||
step is to get the stack status structure. We could do this
|
||||
more quickly and more directly, perhaps, by referencing the
|
||||
$LM00 common block, but I know that this works. */
|
||||
|
||||
STKSTAT (&status);
|
||||
|
||||
/* Set up the iteration. */
|
||||
|
||||
trailer = (struct stk_trailer *) (status.current_address
|
||||
+ status.current_size
|
||||
- 15);
|
||||
|
||||
/* There must be at least one stack segment. Therefore it is
|
||||
a fatal error if "trailer" is null. */
|
||||
|
||||
if (trailer == 0)
|
||||
abort ();
|
||||
|
||||
/* Discard segments that do not contain our argument address. */
|
||||
|
||||
while (trailer != 0)
|
||||
{
|
||||
block = (long *) trailer->this_address;
|
||||
size = trailer->this_size;
|
||||
if (block == 0 || size == 0)
|
||||
abort ();
|
||||
trailer = (struct stk_trailer *) trailer->link;
|
||||
if ((block <= address) && (address < (block + size)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the result to the offset in this segment and add the sizes
|
||||
of all predecessor segments. */
|
||||
|
||||
result = address - block;
|
||||
|
||||
if (trailer == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (trailer->this_size <= 0)
|
||||
abort ();
|
||||
result += trailer->this_size;
|
||||
trailer = (struct stk_trailer *) trailer->link;
|
||||
}
|
||||
while (trailer != 0);
|
||||
|
||||
/* We are done. Note that if you present a bogus address (one
|
||||
not in any segment), you will get a different number back, formed
|
||||
from subtracting the address of the first block. This is probably
|
||||
not what you want. */
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
#else /* not CRAY2 */
|
||||
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
|
||||
Determine the number of the cell within the stack,
|
||||
given the address of the cell. The purpose of this
|
||||
routine is to linearize, in some sense, stack addresses
|
||||
for alloca. */
|
||||
|
||||
static long
|
||||
i00afunc (long address)
|
||||
{
|
||||
long stkl = 0;
|
||||
|
||||
long size, pseg, this_segment, stack;
|
||||
long result = 0;
|
||||
|
||||
struct stack_segment_linkage *ssptr;
|
||||
|
||||
/* Register B67 contains the address of the end of the
|
||||
current stack segment. If you (as a subprogram) store
|
||||
your registers on the stack and find that you are past
|
||||
the contents of B67, you have overflowed the segment.
|
||||
|
||||
B67 also points to the stack segment linkage control
|
||||
area, which is what we are really interested in. */
|
||||
|
||||
stkl = CRAY_STACKSEG_END ();
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
|
||||
/* If one subtracts 'size' from the end of the segment,
|
||||
one has the address of the first word of the segment.
|
||||
|
||||
If this is not the first segment, 'pseg' will be
|
||||
nonzero. */
|
||||
|
||||
pseg = ssptr->sspseg;
|
||||
size = ssptr->sssize;
|
||||
|
||||
this_segment = stkl - size;
|
||||
|
||||
/* It is possible that calling this routine itself caused
|
||||
a stack overflow. Discard stack segments which do not
|
||||
contain the target address. */
|
||||
|
||||
while (!(this_segment <= address && address <= stkl))
|
||||
{
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
|
||||
#endif
|
||||
if (pseg == 0)
|
||||
break;
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
pseg = ssptr->sspseg;
|
||||
this_segment = stkl - size;
|
||||
}
|
||||
|
||||
result = address - this_segment;
|
||||
|
||||
/* If you subtract pseg from the current end of the stack,
|
||||
you get the address of the previous stack segment's end.
|
||||
This seems a little convoluted to me, but I'll bet you save
|
||||
a cycle somewhere. */
|
||||
|
||||
while (pseg != 0)
|
||||
{
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
fprintf (stderr, "%011o %011o\n", pseg, size);
|
||||
#endif
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
pseg = ssptr->sspseg;
|
||||
result += size;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
#endif /* not CRAY2 */
|
||||
#endif /* CRAY */
|
||||
|
||||
#endif /* !G_NATIVE_ALLOCA */
|
22
glib.h
22
glib.h
@ -318,6 +318,24 @@ extern "C" {
|
||||
} G_STMT_END
|
||||
|
||||
|
||||
|
||||
/* Stack-based temporary allocation
|
||||
*/
|
||||
|
||||
#if G_NATIVE_ALLOCA
|
||||
# define g_alloca alloca
|
||||
# define g_alloca_gc() /* nothing to do for garbage collection */
|
||||
#else /* !G_NATIVE_ALLOCA */
|
||||
gpointer _g_alloca (gulong size);
|
||||
# define g_alloca _g_alloca
|
||||
# define g_alloca_gc() _g_alloca (0)
|
||||
#endif /* !G_NATIVE_ALLOCA */
|
||||
|
||||
#define g_alloca_new(type, count) \
|
||||
((type *) g_alloca ((unsigned) sizeof (type) * (count)))
|
||||
|
||||
|
||||
|
||||
#define g_string(x) #x
|
||||
|
||||
|
||||
@ -977,8 +995,8 @@ void g_queue_push_back (GQueue *q, gpointer data);
|
||||
gpointer g_queue_pop_front (GQueue *q);
|
||||
gpointer g_queue_pop_back (GQueue *q);
|
||||
|
||||
#define q_queue_push q_queue_push_back
|
||||
#define q_queue_pop q_queue_pop_front
|
||||
#define g_queue_push g_queue_push_back
|
||||
#define g_queue_pop g_queue_pop_front
|
||||
|
||||
|
||||
|
||||
|
22
glib/glib.h
22
glib/glib.h
@ -318,6 +318,24 @@ extern "C" {
|
||||
} G_STMT_END
|
||||
|
||||
|
||||
|
||||
/* Stack-based temporary allocation
|
||||
*/
|
||||
|
||||
#if G_NATIVE_ALLOCA
|
||||
# define g_alloca alloca
|
||||
# define g_alloca_gc() /* nothing to do for garbage collection */
|
||||
#else /* !G_NATIVE_ALLOCA */
|
||||
gpointer _g_alloca (gulong size);
|
||||
# define g_alloca _g_alloca
|
||||
# define g_alloca_gc() _g_alloca (0)
|
||||
#endif /* !G_NATIVE_ALLOCA */
|
||||
|
||||
#define g_alloca_new(type, count) \
|
||||
((type *) g_alloca ((unsigned) sizeof (type) * (count)))
|
||||
|
||||
|
||||
|
||||
#define g_string(x) #x
|
||||
|
||||
|
||||
@ -977,8 +995,8 @@ void g_queue_push_back (GQueue *q, gpointer data);
|
||||
gpointer g_queue_pop_front (GQueue *q);
|
||||
gpointer g_queue_pop_back (GQueue *q);
|
||||
|
||||
#define q_queue_push q_queue_push_back
|
||||
#define q_queue_pop q_queue_pop_front
|
||||
#define g_queue_push g_queue_push_back
|
||||
#define g_queue_pop g_queue_pop_front
|
||||
|
||||
|
||||
|
||||
|
@ -34,3 +34,5 @@ dirname-test
|
||||
type-test
|
||||
strfunc-test
|
||||
stack-test
|
||||
queue-test
|
||||
alloca-test
|
||||
|
@ -2,11 +2,13 @@
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
||||
TESTS = \
|
||||
alloca-test \
|
||||
array-test \
|
||||
dirname-test \
|
||||
hash-test \
|
||||
list-test \
|
||||
node-test \
|
||||
queue-test \
|
||||
relation-test \
|
||||
slist-test \
|
||||
stack-test \
|
||||
@ -17,11 +19,13 @@ TESTS = \
|
||||
|
||||
noinst_PROGRAMS = $(TESTS)
|
||||
|
||||
alloca_test_LDADD = $(top_builddir)/libglib.la
|
||||
array_test_LDADD = $(top_builddir)/libglib.la
|
||||
dirname_test_LDADD = $(top_builddir)/libglib.la
|
||||
hash_test_LDADD = $(top_builddir)/libglib.la
|
||||
list_test_LDADD = $(top_builddir)/libglib.la
|
||||
node_test_LDADD = $(top_builddir)/libglib.la
|
||||
queue_test_LDADD = $(top_builddir)/libglib.la
|
||||
relation_test_LDADD = $(top_builddir)/libglib.la
|
||||
slist_test_LDADD = $(top_builddir)/libglib.la
|
||||
stack_test_LDADD = $(top_builddir)/libglib.la
|
||||
|
44
tests/alloca-test.c
Normal file
44
tests/alloca-test.c
Normal file
@ -0,0 +1,44 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
struct test_t {
|
||||
int age;
|
||||
char name [19];
|
||||
int stuph;
|
||||
};
|
||||
|
||||
|
||||
void test_alloca (void)
|
||||
{
|
||||
gpointer data;
|
||||
struct test_t *t;
|
||||
|
||||
data = g_alloca (15);
|
||||
strcpy ((char *) data, "blah blah blah");
|
||||
g_assert (strcmp ((char *) data, "blah blah blah") == 0);
|
||||
|
||||
t = g_alloca_new (struct test_t, 1);
|
||||
t->age = 142;
|
||||
t->stuph = 0xBEDAC0ED;
|
||||
strcpy (t->name, "nyognyou hoddypeak");
|
||||
g_assert (t->stuph == 0xBEDAC0ED);
|
||||
g_assert (strcmp (t->name, "nyognyou hoddypeak") == 0);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test_alloca ();
|
||||
|
||||
g_alloca_gc ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
70
tests/queue-test.c
Normal file
70
tests/queue-test.c
Normal file
@ -0,0 +1,70 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <glib.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
GQueue *q;
|
||||
|
||||
q = g_queue_new ();
|
||||
|
||||
g_queue_push (q, GINT_TO_POINTER (1));
|
||||
g_assert (g_list_length (q->list) == 1);
|
||||
g_queue_push (q, GINT_TO_POINTER (2));
|
||||
g_assert (g_list_length (q->list) == 2);
|
||||
g_queue_push (q, GINT_TO_POINTER (3));
|
||||
g_assert (g_list_length (q->list) == 3);
|
||||
g_queue_push (q, GINT_TO_POINTER (4));
|
||||
g_assert (g_list_length (q->list) == 4);
|
||||
g_queue_push (q, GINT_TO_POINTER (5));
|
||||
g_assert (g_list_length (q->list) == 5);
|
||||
|
||||
g_assert (g_queue_pop (q) == GINT_TO_POINTER (1));
|
||||
g_assert (g_list_length (q->list) == 4);
|
||||
g_assert (g_queue_pop (q) == GINT_TO_POINTER (2));
|
||||
g_assert (g_list_length (q->list) == 3);
|
||||
g_assert (g_queue_pop (q) == GINT_TO_POINTER (3));
|
||||
g_assert (g_list_length (q->list) == 2);
|
||||
g_assert (g_queue_pop (q) == GINT_TO_POINTER (4));
|
||||
g_assert (g_list_length (q->list) == 1);
|
||||
g_assert (g_queue_pop (q) == GINT_TO_POINTER (5));
|
||||
g_assert (g_list_length (q->list) == 0);
|
||||
g_assert (g_queue_pop (q) == NULL);
|
||||
g_assert (g_list_length (q->list) == 0);
|
||||
g_assert (g_queue_pop (q) == NULL);
|
||||
g_assert (g_list_length (q->list) == 0);
|
||||
|
||||
/************************/
|
||||
|
||||
g_queue_push_front (q, GINT_TO_POINTER (1));
|
||||
g_assert (g_list_length (q->list) == 1);
|
||||
g_queue_push_front (q, GINT_TO_POINTER (2));
|
||||
g_assert (g_list_length (q->list) == 2);
|
||||
g_queue_push_front (q, GINT_TO_POINTER (3));
|
||||
g_assert (g_list_length (q->list) == 3);
|
||||
g_queue_push_front (q, GINT_TO_POINTER (4));
|
||||
g_assert (g_list_length (q->list) == 4);
|
||||
g_queue_push_front (q, GINT_TO_POINTER (5));
|
||||
g_assert (g_list_length (q->list) == 5);
|
||||
|
||||
g_assert (g_queue_pop_front (q) == GINT_TO_POINTER (5));
|
||||
g_assert (g_list_length (q->list) == 4);
|
||||
g_assert (g_queue_pop_front (q) == GINT_TO_POINTER (4));
|
||||
g_assert (g_list_length (q->list) == 3);
|
||||
g_assert (g_queue_pop_front (q) == GINT_TO_POINTER (3));
|
||||
g_assert (g_list_length (q->list) == 2);
|
||||
g_assert (g_queue_pop_front (q) == GINT_TO_POINTER (2));
|
||||
g_assert (g_list_length (q->list) == 1);
|
||||
g_assert (g_queue_pop_front (q) == GINT_TO_POINTER (1));
|
||||
g_assert (g_list_length (q->list) == 0);
|
||||
g_assert (g_queue_pop_front (q) == NULL);
|
||||
g_assert (g_list_length (q->list) == 0);
|
||||
g_assert (g_queue_pop_front (q) == NULL);
|
||||
g_assert (g_list_length (q->list) == 0);
|
||||
|
||||
g_queue_free (q);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,3 +1,7 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
int main()
|
||||
@ -17,21 +21,23 @@ int main()
|
||||
g_stack_push (s, GINT_TO_POINTER (5));
|
||||
g_assert (g_list_length (s->list) == 5);
|
||||
|
||||
g_assert (g_stack_pop (s) == GPOINTER_TO_INT (5));
|
||||
g_assert (g_stack_pop (s) == GINT_TO_POINTER (5));
|
||||
g_assert (g_list_length (s->list) == 4);
|
||||
g_assert (g_stack_pop (s) == GPOINTER_TO_INT (4));
|
||||
g_assert (g_stack_pop (s) == GINT_TO_POINTER (4));
|
||||
g_assert (g_list_length (s->list) == 3);
|
||||
g_assert (g_stack_pop (s) == GPOINTER_TO_INT (3));
|
||||
g_assert (g_stack_pop (s) == GINT_TO_POINTER (3));
|
||||
g_assert (g_list_length (s->list) == 2);
|
||||
g_assert (g_stack_pop (s) == GPOINTER_TO_INT (2));
|
||||
g_assert (g_stack_pop (s) == GINT_TO_POINTER (2));
|
||||
g_assert (g_list_length (s->list) == 1);
|
||||
g_assert (g_stack_pop (s) == GPOINTER_TO_INT (1));
|
||||
g_assert (g_stack_pop (s) == GINT_TO_POINTER (1));
|
||||
g_assert (g_list_length (s->list) == 0);
|
||||
g_assert (g_stack_pop (s) == NULL);
|
||||
g_assert (g_list_length (s->list) == 0);
|
||||
g_assert (g_stack_pop (s) == NULL);
|
||||
g_assert (g_list_length (s->list) == 0);
|
||||
|
||||
g_stack_free (s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user