1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-24 12:20:20 +02:00

Merge commit '29776e85da' into boehm-demers-weiser-gc

Conflicts:
	libguile/gc-card.c
	libguile/gc.c
	libguile/gc.h
	libguile/ports.c
This commit is contained in:
Ludovic Courtès 2008-09-10 22:50:04 +02:00
commit 6774820f1e
45 changed files with 2244 additions and 798 deletions

View file

@ -1,3 +1,120 @@
2007-10-02 Ludovic Courtès <ludo@gnu.org>
* threads.c (on_thread_exit): Don't call `scm_leave_guile ()'
since we're already in non-guile mode. Reported by Greg Toxel
for NetBSD.
2007-10-01 Ludovic Courtès <ludo@gnu.org>
* ports.c (flush_output_port): Expect directly a port instead of
a pair. Fixes a bug in the new port table (2007-08-26).
2007-09-11 Kevin Ryde <user42@zip.com.au>
* posix.c (scm_putenv): Confine the putenv("NAME=") bit to mingw, use
putenv("NAME") as the fallback everywhere else. In particular this is
needed for solaris 9. Reported by Frank Storbeck.
2007-09-03 Ludovic Courtès <ludo@gnu.org>
* read.c (flush_ws): Handle SCSH block comments.
2007-09-03 Ludovic Courtès <ludo@gnu.org>
Fix alignment issues which showed up at least on SPARC.
* socket.c (scm_t_max_sockaddr, scm_t_getsockopt_result): New.
(scm_inet_pton): Change DST to `scm_t_uint32' for correct
alignment.
(scm_getsockopt): Change OPTVAL to `scm_t_getsockopt_result' for
correct alignment.
(_scm_from_sockaddr): Change ADDRESS to `scm_t_max_sockaddr *'.
(scm_from_sockaddr): Cast ADDRESS to `scm_t_max_sockaddr *'.
(MAX_SIZE_UN, MAX_SIZE_IN6): Removed.
(scm_accept, scm_getsockname, scm_getpeername, scm_recvfrom):
Use `scm_t_max_sockaddr' instead of "char max_addr[MAX_ADDR_SIZE]".
2007-09-03 Kevin Ryde <user42@zip.com.au>
* numbers.c (scm_log): Test HAVE_CLOG as well as HAVE_COMPLEX_DOUBLE
before using clog(). It's possible for gcc to provide the "complex
double" type, but for the system not to have the complex funcs.
(scm_exp): Ditto HAVE_CEXP for cexp().
(clog, cexp, carg): Remove fallback definitions. These only
duplicated the code within scm_log and scm_exp, and the latter have to
exist for the case when there's no "complex double". So better just
fix up the conditionals selecting between the complex funcs and plain
doubles than worry about fallbacks.
2007-09-02 Ludovic Courtès <ludo@gnu.org>
* socket.c (scm_make_socket_address): Free C_ADDRESS after use.
This fixes a memory leak.
2007-08-26 Han-Wen Nienhuys <hanwen@lilypond.org>
* fports.c gc-card.c gc.c gc.h ioext.c ports.c ports.h weaks.h
gc.c: replace port table with weak hash table. This simplifies
memory management, and fixes freed cells appearing in
port-for-each output.
* init.c (cleanup_for_exit): abort cleanup if init_mutex is still
held.
2007-08-23 Ludovic Courtès <ludo@gnu.org>
* read.c (scm_read_quote): Record position and copy source
expression when asked to. Reported by Kevin.
* stime.c: Define `_REENTRANT' only if not already defined.
2007-08-21 Kevin Ryde <user42@zip.com.au>
* gc-card.c (scm_i_card_statistics): Record scm_tc7_number types as
tc16 values so big, real, complex and fraction can be distinguished.
(scm_i_tag_name): Return "number" for scm_tc7_number, not NULL. NULL
was making numbers come out as "type 23" in gc-live-object-stats.
Fix tests of the tc16 number types, they were checked under
scm_tc7_number, but the values went down the tag>=255 smob case.
Put smob case under scm_tc7_smob instead of using tag>=255, per
recommendation in comments with scm_tc7_smob to use symbolic values.
Use SCM_TC2SMOBNUM to extract scm_smobs index, instead of explicit
code. Lose some unnecessary "break" statements.
(scm_i_card_statistics): Use scm_hashq_create_handle_x and modify the
element returned, rather than two lookups scm_hashq_ref and
scm_hashq_set_x.
2007-08-17 Kevin Ryde <user42@zip.com.au>
* stime.c: Add #define _REENTRANT, to get gmtime_r() prototype on
solaris 2.6. Reported by anirkko.
2007-07-29 Ludovic Courtès <ludo@gnu.org>
* Makefile.am (INCLUDES): Added Gnulib includes.
(gnulib_library): New.
(libguile_i18n_v_@LIBGUILE_I18N_MAJOR@_la_LIBADD): Added
`$(gnulib_library)'.
(libguile_la_LIBADD): Likewise.
* posix.c: Don't define `_GNU_SOURCE' since `gl_EARLY' arranges
to define it when available.
* srfi-14.c: Likewise.
* i18n.c: Likewise. Include Gnulib's <alloca.h>
* eval.c: Include Gnulib's <alloca.h>.
* filesys.c: Likewise.
* read.c: Don't include <strings.h> and don't provide an
`strncasecmp ()' replacement; use Gnulib's <string.h> and
`strncasecmp ()' instead.
2007-07-25 Ludovic Courtès <ludo@gnu.org>
* eval.c (macroexp): When `scm_ilength (res) <= 0', return
immediately. This used to produce a circular memoized
expression, e.g., for `(set (quote x) #t)'.
2007-07-22 Ludovic Courtès <ludo@gnu.org>
Overhauled the reader, making it faster.

View file

@ -1,6 +1,6 @@
## Process this file with Automake to create Makefile.in
##
## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
##
## This file is part of GUILE.
##
@ -25,8 +25,12 @@ AUTOMAKE_OPTIONS = gnu
DEFS = @DEFS@
## Check for headers in $(srcdir)/.., so that #include
## <libguile/MUMBLE.h> will find MUMBLE.h in this dir when we're
## building.
INCLUDES = -I.. -I$(top_srcdir)
## building. Also look for Gnulib headers in `lib'.
INCLUDES = -I.. -I$(top_srcdir) \
-I$(top_srcdir)/lib -I$(top_builddir)/lib
## The Gnulib Libtool archive.
gnulib_library = $(top_builddir)/lib/libgnu.la
ETAGS_ARGS = --regex='/SCM_\(GLOBAL_\)?\(G?PROC\|G?PROC1\|SYMBOL\|VCELL\|CONST_LONG\).*\"\([^\"]\)*\"/\3/' \
--regex='/[ \t]*SCM_[G]?DEFINE1?[ \t]*(\([^,]*\),[^,]*/\1/'
@ -114,7 +118,7 @@ libguile_i18n_v_@LIBGUILE_I18N_MAJOR@_la_SOURCES = i18n.c
libguile_i18n_v_@LIBGUILE_I18N_MAJOR@_la_CFLAGS = \
$(libguile_la_CFLAGS)
libguile_i18n_v_@LIBGUILE_I18N_MAJOR@_la_LIBADD = \
libguile.la
libguile.la $(gnulib_library)
libguile_i18n_v_@LIBGUILE_I18N_MAJOR@_la_LDFLAGS = \
-module -L$(builddir) -lguile \
-version-info @LIBGUILE_I18N_INTERFACE@
@ -186,7 +190,7 @@ noinst_HEADERS = convert.i.c \
private-gc.h private-options.h
libguile_la_DEPENDENCIES = @LIBLOBJS@
libguile_la_LIBADD = @LIBLOBJS@
libguile_la_LIBADD = @LIBLOBJS@ $(gnulib_library)
libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
# These are headers visible as <guile/mumble.h>

View file

@ -27,25 +27,9 @@
# include <config.h>
#endif
#include "libguile/__scm.h"
#include <alloca.h>
/* This blob per the Autoconf manual (under "Particular Functions"). */
#if HAVE_ALLOCA_H
# include <alloca.h>
#elif defined __GNUC__
# define alloca __builtin_alloca
#elif defined _AIX
# define alloca __alloca
#elif defined _MSC_VER
# include <malloc.h>
# define alloca _alloca
#else
# include <stddef.h>
# ifdef __cplusplus
extern "C"
# endif
void *alloca (size_t);
#endif
#include "libguile/__scm.h"
#include <assert.h>
#include "libguile/_scm.h"
@ -874,26 +858,29 @@ macroexp (SCM x, SCM env)
SCM_SETCAR (x, orig_sym); /* Undo memoizing effect of lookupcar */
res = scm_call_2 (SCM_MACRO_CODE (proc), x, env);
if (scm_ilength (res) <= 0)
res = scm_list_2 (SCM_IM_BEGIN, res);
/* Result of expansion is not a list. */
return (scm_list_2 (SCM_IM_BEGIN, res));
else
{
/* njrev: Several queries here: (1) I don't see how it can be
correct that the SCM_SETCAR 2 lines below this comment needs
protection, but the SCM_SETCAR 6 lines above does not, so
something here is probably wrong. (2) macroexp() is now only
used in one place - scm_m_generalized_set_x - whereas all other
macro expansion happens through expand_user_macros. Therefore
(2.1) perhaps macroexp() could be eliminated completely now?
(2.2) Does expand_user_macros need any critical section
protection? */
/* njrev: Several queries here: (1) I don't see how it can be
correct that the SCM_SETCAR 2 lines below this comment needs
protection, but the SCM_SETCAR 6 lines above does not, so
something here is probably wrong. (2) macroexp() is now only
used in one place - scm_m_generalized_set_x - whereas all other
macro expansion happens through expand_user_macros. Therefore
(2.1) perhaps macroexp() could be eliminated completely now?
(2.2) Does expand_user_macros need any critical section
protection? */
SCM_CRITICAL_SECTION_START;
SCM_SETCAR (x, SCM_CAR (res));
SCM_SETCDR (x, SCM_CDR (res));
SCM_CRITICAL_SECTION_END;
SCM_CRITICAL_SECTION_START;
SCM_SETCAR (x, SCM_CAR (res));
SCM_SETCDR (x, SCM_CDR (res));
SCM_CRITICAL_SECTION_END;
goto macro_tail;
goto macro_tail;
}
}
/* Start of the memoizers for the standard R5RS builtin macros. */

View file

@ -29,23 +29,7 @@
# include <config.h>
#endif
/* This blob per the Autoconf manual (under "Particular Functions"). */
#if HAVE_ALLOCA_H
# include <alloca.h>
#elif defined __GNUC__
# define alloca __builtin_alloca
#elif defined _AIX
# define alloca __alloca
#elif defined _MSC_VER
# include <malloc.h>
# define alloca _alloca
#else
# include <stddef.h>
# ifdef __cplusplus
extern "C"
# endif
void *alloca (size_t);
#endif
#include <alloca.h>
#include <stdio.h>
#include <errno.h>

View file

@ -31,6 +31,7 @@
#include "libguile/gc.h"
#include "libguile/posix.h"
#include "libguile/dynwind.h"
#include "libguile/hashtab.h"
#include "libguile/fports.h"
@ -220,32 +221,35 @@ SCM_DEFINE (scm_setvbuf, "setvbuf", 2, 1, 0,
/* Move ports with the specified file descriptor to new descriptors,
* resetting the revealed count to 0.
*/
static SCM
scm_i_evict_port (SCM handle, void *closure)
{
int fd = * (int*) closure;
SCM port = SCM_CAR (handle);
if (SCM_FPORTP (port))
{
scm_t_fport *fp = SCM_FSTREAM (port);
if (fp->fdes == fd)
{
fp->fdes = dup (fd);
if (fp->fdes == -1)
scm_syserror ("scm_evict_ports");
scm_set_port_revealed_x (port, scm_from_int (0));
}
}
return handle;
}
void
scm_evict_ports (int fd)
{
long i;
scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
for (i = 0; i < scm_i_port_table_size; i++)
{
SCM port = scm_i_port_table[i]->port;
if (SCM_FPORTP (port))
{
scm_t_fport *fp = SCM_FSTREAM (port);
if (fp->fdes == fd)
{
fp->fdes = dup (fd);
if (fp->fdes == -1)
scm_syserror ("scm_evict_ports");
scm_set_port_revealed_x (port, scm_from_int (0));
}
}
}
scm_internal_hash_for_each_handle (&scm_i_evict_port,
(void*) &fd,
scm_i_port_weak_hash);
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
}

View file

@ -15,28 +15,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define _GNU_SOURCE /* Ask for glibc's `newlocale' API */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#if HAVE_ALLOCA_H
# include <alloca.h>
#elif defined __GNUC__
# define alloca __builtin_alloca
#elif defined _AIX
# define alloca __alloca
#elif defined _MSC_VER
# include <malloc.h>
# define alloca _alloca
#else
# include <stddef.h>
# ifdef __cplusplus
extern "C"
# endif
void *alloca (size_t);
#endif
#include <alloca.h>
#include "libguile/_scm.h"
#include "libguile/feature.h"

View file

@ -395,6 +395,14 @@ really_cleanup_for_exit (void *unused)
static void
cleanup_for_exit ()
{
if (scm_i_pthread_mutex_trylock (&scm_i_init_mutex) == 0)
scm_i_pthread_mutex_unlock (&scm_i_init_mutex);
else
{
fprintf (stderr, "Cannot exit gracefully when init is in progress; aborting.\n");
abort ();
}
/* This function might be called in non-guile mode, so we need to
enter it temporarily.
*/
@ -474,6 +482,7 @@ scm_i_init_guile (SCM_STACKITEM *base)
scm_init_backtrace (); /* Requires fluids */
scm_init_fports ();
scm_init_strports ();
scm_init_ports ();
scm_init_gdbint (); /* Requires strports */
scm_init_hash ();
scm_init_hashtab ();
@ -492,7 +501,6 @@ scm_i_init_guile (SCM_STACKITEM *base)
scm_init_numbers ();
scm_init_options ();
scm_init_pairs ();
scm_init_ports ();
#ifdef HAVE_POSIX
scm_init_filesys ();
scm_init_posix ();

View file

@ -26,13 +26,14 @@
#include <errno.h>
#include "libguile/_scm.h"
#include "libguile/ioext.h"
#include "libguile/fports.h"
#include "libguile/dynwind.h"
#include "libguile/feature.h"
#include "libguile/fports.h"
#include "libguile/hashtab.h"
#include "libguile/ioext.h"
#include "libguile/ports.h"
#include "libguile/strings.h"
#include "libguile/validate.h"
#include "libguile/dynwind.h"
#include <fcntl.h>
@ -266,6 +267,19 @@ SCM_DEFINE (scm_primitive_move_to_fdes, "primitive-move->fdes", 2, 0, 0,
}
#undef FUNC_NAME
static SCM
get_matching_port (void *closure, SCM port, SCM val, SCM result)
{
int fd = * (int *) closure;
scm_t_port *entry = SCM_PTAB_ENTRY (port);
if (SCM_OPFPORTP (port)
&& ((scm_t_fport *) entry->stream)->fdes == fd)
result = scm_cons (port, result);
return result;
}
/* Return a list of ports using a given file descriptor. */
SCM_DEFINE (scm_fdes_to_ports, "fdes->ports", 1, 0, 0,
(SCM fd),
@ -275,18 +289,12 @@ SCM_DEFINE (scm_fdes_to_ports, "fdes->ports", 1, 0, 0,
#define FUNC_NAME s_scm_fdes_to_ports
{
SCM result = SCM_EOL;
int int_fd;
long i;
int_fd = scm_to_int (fd);
int int_fd = scm_to_int (fd);
scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
for (i = 0; i < scm_i_port_table_size; i++)
{
if (SCM_OPFPORTP (scm_i_port_table[i]->port)
&& ((scm_t_fport *) scm_i_port_table[i]->stream)->fdes == int_fd)
result = scm_cons (scm_i_port_table[i]->port, result);
}
result = scm_internal_hash_fold (get_matching_port,
(void*) &int_fd, result,
scm_i_port_weak_hash);
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
return result;
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005, 2006 Free Software Foundation, Inc.
/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005, 2006, 2007 Free Software Foundation, Inc.
*
* Portions Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories
* and Bellcore. See scm_divide.
@ -5998,35 +5998,6 @@ scm_is_number (SCM z)
return scm_is_true (scm_number_p (z));
}
#ifdef HAVE_COMPLEX_DOUBLE
#ifndef HAVE_CLOG
complex double clog (complex double z);
complex double
clog (complex double z)
{
return log(cabs(z))+I*carg(z);
}
#endif
#ifndef HAVE_CEXP
complex double cexp (complex double z);
complex double
cexp (complex double z)
{
return exp (cabs (z)) * cos(carg (z) + I*sin(carg (z)));
}
#endif
#ifndef HAVE_CARG
double carg (complex double z);
double
carg (complex double z)
{
return atan2 (cimag(z), creal(z));
}
#endif
#endif /* HAVE_COMPLEX_DOUBLE */
/* In the following functions we dispatch to the real-arg funcs like log()
when we know the arg is real, instead of just handing everything to
@ -6041,7 +6012,7 @@ SCM_DEFINE (scm_log, "log", 1, 0, 0,
{
if (SCM_COMPLEXP (z))
{
#if HAVE_COMPLEX_DOUBLE
#if HAVE_COMPLEX_DOUBLE && HAVE_CLOG
return scm_from_complex_double (clog (SCM_COMPLEX_VALUE (z)));
#else
double re = SCM_COMPLEX_REAL (z);
@ -6107,7 +6078,7 @@ SCM_DEFINE (scm_exp, "exp", 1, 0, 0,
{
if (SCM_COMPLEXP (z))
{
#if HAVE_COMPLEX_DOUBLE
#if HAVE_COMPLEX_DOUBLE && HAVE_CEXP
return scm_from_complex_double (cexp (SCM_COMPLEX_VALUE (z)));
#else
return scm_c_make_polar (exp (SCM_COMPLEX_REAL (z)),

View file

@ -42,12 +42,14 @@
#include "libguile/dynwind.h"
#include "libguile/keywords.h"
#include "libguile/hashtab.h"
#include "libguile/root.h"
#include "libguile/strings.h"
#include "libguile/mallocs.h"
#include "libguile/validate.h"
#include "libguile/ports.h"
#include "libguile/vectors.h"
#include "libguile/weaks.h"
#include "libguile/fluids.h"
#ifdef HAVE_STRING_H
@ -84,7 +86,7 @@
/* scm_ptobs scm_numptob
* implement a dynamicly resized array of ptob records.
* implement a dynamically resized array of ptob records.
* Indexes into this table are used when generating type
* tags for smobjects (if you know a tag you can get an index and conversely).
*/
@ -485,10 +487,11 @@ scm_i_dynwind_current_load_port (SCM port)
/* The port table --- an array of pointers to ports. */
scm_t_port **scm_i_port_table = NULL;
long scm_i_port_table_size = 0; /* Number of ports in SCM_I_PORT_TABLE. */
long scm_i_port_table_room = 20; /* Actual size of the array. */
/*
We need a global registry of ports to flush them all at exit, and to
get all the ports matching a file descriptor.
*/
SCM scm_i_port_weak_hash;
scm_i_pthread_mutex_t scm_i_port_table_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
@ -567,33 +570,15 @@ scm_new_port_table_entry (scm_t_bits tag)
SCM z = scm_cons (SCM_EOL, SCM_EOL);
scm_t_port *entry = (scm_t_port *) scm_gc_calloc (sizeof (scm_t_port), "port");
if (scm_i_port_table_size == scm_i_port_table_room)
{
/* initial malloc is in gc.c. this doesn't use scm_gc_malloc etc.,
since it can never be freed during gc. */
/* XXX (Ludo): Why not do it actually? */
size_t new_size = scm_i_port_table_room * 2;
/* XXX (Ludo): Can we use `GC_REALLOC' with
`GC_MALLOC_ATOMIC'-allocated data? */
void *newt = scm_gc_realloc ((char *) scm_i_port_table,
scm_i_port_table_room * sizeof (scm_t_port *),
new_size * sizeof (scm_t_port *),
"port-table");
scm_i_port_table = (scm_t_port **) newt;
scm_i_port_table_room = new_size;
}
entry->entry = scm_i_port_table_size;
entry->file_name = SCM_BOOL_F;
entry->rw_active = SCM_PORT_NEITHER;
scm_i_port_table[scm_i_port_table_size] = entry;
scm_i_port_table_size++;
entry->port = z;
SCM_SET_CELL_TYPE(z, tag);
SCM_SETPTAB_ENTRY(z, entry);
SCM_SET_CELL_TYPE (z, tag);
SCM_SETPTAB_ENTRY (z, entry);
scm_hashq_set_x (scm_i_port_weak_hash, z, SCM_BOOL_F);
/* For each new port, register a finalizer so that it port type's free
function can be invoked eventually. */
@ -611,8 +596,8 @@ scm_add_to_port_table (SCM port)
scm_t_port * pt = SCM_PTAB_ENTRY(z);
pt->port = port;
SCM_SETCAR(z, SCM_EOL);
SCM_SETCDR(z, SCM_EOL);
SCM_SETCAR (z, SCM_EOL);
SCM_SETCDR (z, SCM_EOL);
SCM_SETPTAB_ENTRY (port, pt);
return pt;
}
@ -622,57 +607,30 @@ scm_add_to_port_table (SCM port)
/* Remove a port from the table and destroy it. */
/* This function is not and should not be thread safe. */
void
scm_remove_from_port_table (SCM port)
#define FUNC_NAME "scm_remove_from_port_table"
scm_i_remove_port (SCM port)
#define FUNC_NAME "scm_remove_port"
{
scm_t_port *p = SCM_PTAB_ENTRY (port);
long i = p->entry;
if (i >= scm_i_port_table_size)
SCM_MISC_ERROR ("Port not in table: ~S", scm_list_1 (port));
if (p->putback_buf)
scm_gc_free (p->putback_buf, p->putback_buf_size, "putback buffer");
scm_gc_free (p, sizeof (scm_t_port), "port");
/* Since we have just freed slot i we can shrink the table by moving
the last entry to that slot... */
if (i < scm_i_port_table_size - 1)
{
scm_i_port_table[i] = scm_i_port_table[scm_i_port_table_size - 1];
scm_i_port_table[i]->entry = i;
}
SCM_SETPTAB_ENTRY (port, 0);
scm_i_port_table_size--;
scm_hashq_remove_x (scm_i_port_weak_hash, port);
}
#undef FUNC_NAME
#ifdef GUILE_DEBUG
/* Functions for debugging. */
#ifdef GUILE_DEBUG
SCM_DEFINE (scm_pt_size, "pt-size", 0, 0, 0,
(),
"Return the number of ports in the port table. @code{pt-size}\n"
"is only included in @code{--enable-guile-debug} builds.")
#define FUNC_NAME s_scm_pt_size
{
return scm_from_int (scm_i_port_table_size);
}
#undef FUNC_NAME
SCM_DEFINE (scm_pt_member, "pt-member", 1, 0, 0,
(SCM index),
"Return the port at @var{index} in the port table.\n"
"@code{pt-member} is only included in\n"
"@code{--enable-guile-debug} builds.")
#define FUNC_NAME s_scm_pt_member
{
size_t i = scm_to_size_t (index);
if (i >= scm_i_port_table_size)
return SCM_BOOL_F;
else
return scm_i_port_table[i]->port;
return scm_from_int (SCM_HASHTABLE_N_ITEMS (scm_i_port_weak_hash));
}
#undef FUNC_NAME
#endif
@ -833,7 +791,7 @@ SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
else
rv = 0;
scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
scm_remove_from_port_table (port);
scm_i_remove_port (port);
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
SCM_CLR_PORT_OPEN_FLAG (port);
return scm_from_bool (rv >= 0);
@ -871,10 +829,20 @@ SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
}
#undef FUNC_NAME
static SCM
scm_i_collect_keys_in_vector (void *closure, SCM key, SCM value, SCM result)
{
int *i = (int*) closure;
scm_c_vector_set_x (result, *i, key);
(*i)++;
return result;
}
void
scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
{
long i;
int i = 0;
size_t n;
SCM ports;
@ -884,20 +852,20 @@ scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
collect the ports into a vector. -mvo */
scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
n = scm_i_port_table_size;
n = SCM_HASHTABLE_N_ITEMS (scm_i_port_weak_hash);
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
ports = scm_c_make_vector (n, SCM_BOOL_F);
scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
if (n > scm_i_port_table_size)
n = scm_i_port_table_size;
for (i = 0; i < n; i++)
SCM_SIMPLE_VECTOR_SET (ports, i, scm_i_port_table[i]->port);
scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
ports = scm_internal_hash_fold (scm_i_collect_keys_in_vector, &i,
ports, scm_i_port_weak_hash);
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
for (i = 0; i < n; i++)
proc (data, SCM_SIMPLE_VECTOR_REF (ports, i));
for (i = 0; i < n; i++) {
SCM p = SCM_SIMPLE_VECTOR_REF (ports, i);
if (SCM_PORTP (p))
proc (data, p);
}
scm_remember_upto_here_1 (ports);
}
@ -1000,21 +968,21 @@ SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
}
#undef FUNC_NAME
static void
flush_output_port (void *closure, SCM port)
{
if (SCM_OPOUTPORTP (port))
scm_flush (port);
}
SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
(),
"Equivalent to calling @code{force-output} on\n"
"all open output ports. The return value is unspecified.")
#define FUNC_NAME s_scm_flush_all_ports
{
size_t i;
scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
for (i = 0; i < scm_i_port_table_size; i++)
{
if (SCM_OPOUTPORTP (scm_i_port_table[i]->port))
scm_flush (scm_i_port_table[i]->port);
}
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
scm_c_port_for_each (&flush_output_port, NULL);
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
@ -1806,6 +1774,8 @@ scm_init_ports ()
cur_errport_fluid = scm_permanent_object (scm_make_fluid ());
cur_loadport_fluid = scm_permanent_object (scm_make_fluid ());
scm_i_port_weak_hash = scm_permanent_object (scm_make_weak_key_hash_table (SCM_I_MAKINUM(31)));
#include "libguile/ports.x"
}

View file

@ -47,7 +47,6 @@ typedef enum scm_t_port_rw_active {
typedef struct
{
SCM port; /* Link back to the port object. */
long entry; /* Index in port table. */
int revealed; /* 0 not revealed, > 1 revealed.
* Revealed ports do not get GC'd.
*/
@ -109,9 +108,10 @@ typedef struct
size_t putback_buf_size; /* allocated size of putback_buf. */
} scm_t_port;
SCM_API scm_t_port **scm_i_port_table;
SCM_API long scm_i_port_table_size; /* Number of ports in scm_i_port_table. */
SCM_API scm_i_pthread_mutex_t scm_i_port_table_mutex;
SCM_API SCM scm_i_port_weak_hash;
#define SCM_READ_BUFFER_EMPTY_P(c_port) (c_port->read_pos >= c_port->read_end)
@ -241,7 +241,7 @@ SCM_API void scm_dynwind_current_input_port (SCM port);
SCM_API void scm_dynwind_current_output_port (SCM port);
SCM_API void scm_dynwind_current_error_port (SCM port);
SCM_API SCM scm_new_port_table_entry (scm_t_bits tag);
SCM_API void scm_remove_from_port_table (SCM port);
SCM_API void scm_i_remove_port (SCM port);
SCM_API void scm_grow_port_cbuf (SCM port, size_t requested);
SCM_API SCM scm_pt_size (void);
SCM_API SCM scm_pt_member (SCM member);

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -21,9 +21,6 @@
# include <config.h>
#endif
/* Make GNU/Linux libc declare everything it has. */
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
@ -1343,16 +1340,39 @@ SCM_DEFINE (scm_putenv, "putenv", 1, 0, 0,
if (strchr (c_str, '=') == NULL)
{
#ifdef HAVE_UNSETENV
/* No '=' in argument means we should remove the variable from
the environment. Not all putenvs understand this (for instance
FreeBSD 4.8 doesn't). To be safe, we do it explicitely using
unsetenv. */
/* We want no "=" in the argument to mean remove the variable from the
environment, but not all putenv()s understand this, for example
FreeBSD 4.8 doesn't. Getting it happening everywhere is a bit
painful. What unsetenv() exists, we use that, of course.
Traditionally putenv("NAME") removes a variable, for example that's
what we have to do on Solaris 9 (it doesn't have an unsetenv).
But on DOS and on that DOS overlay manager thing called W-whatever,
putenv("NAME=") must be used (it too doesn't have an unsetenv).
Supposedly on AIX a putenv("NAME") could cause a segfault, but also
supposedly AIX 5.3 and up has unsetenv() available so should be ok
with the latter there.
For the moment we hard code the DOS putenv("NAME=") style under
__MINGW32__ and do the traditional everywhere else. Such
system-name tests are bad, of course. It'd be possible to use a
configure test when doing a a native build. For example GNU R has
such a test (see R_PUTENV_AS_UNSETENV in
https://svn.r-project.org/R/trunk/m4/R.m4). But when cross
compiling there'd want to be a guess, one probably based on the
system name (ie. mingw or not), thus landing back in basically the
present hard-coded situation. Another possibility for a cross
build would be to try "NAME" then "NAME=" at runtime, if that's not
too much like overkill. */
#if HAVE_UNSETENV
/* when unsetenv() exists then we use it */
unsetenv (c_str);
free (c_str);
#else
/* On e.g. Win32 hosts putenv() called with 'name=' removes the
environment variable 'name'. */
#elif defined (__MINGW32__)
/* otherwise putenv("NAME=") on DOS */
int e;
size_t len = strlen (c_str);
char *ptr = scm_malloc (len + 2);
@ -1362,7 +1382,12 @@ SCM_DEFINE (scm_putenv, "putenv", 1, 0, 0,
e = errno; free (ptr); free (c_str); errno = e;
if (rv < 0)
SCM_SYSERROR;
#endif /* !HAVE_UNSETENV */
#else
/* otherwise traditional putenv("NAME") */
rv = putenv (c_str);
if (rv < 0)
SCM_SYSERROR;
#endif
}
else
{

View file

@ -26,9 +26,6 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "libguile/_scm.h"
#include "libguile/chars.h"
@ -182,29 +179,8 @@ static SCM *scm_read_hash_procedures;
(((_chr) <= UCHAR_MAX) ? tolower (_chr) : (_chr))
#ifndef HAVE_STRNCASECMP
/* XXX: Use Gnulib's `strncasecmp ()'. */
static int
strncasecmp (const char *s1, const char *s2, size_t len2)
{
while (*s1 && *s2 && len2 > 0)
{
int c1 = *s1, c2 = *s2;
if (CHAR_DOWNCASE (c1) != CHAR_DOWNCASE (c2))
return 0;
else
{
++s1;
++s2;
--len2;
}
}
return !(*s1 || *s2 || len2 > 0);
}
#endif
/* Read an SCSH block comment. */
static inline SCM scm_read_scsh_block_comment (int chr, SCM port);
/* Helper function similar to `scm_read_token ()'. Read from PORT until a
whitespace is read. Return zero if the whole token could fit in BUF,
@ -272,6 +248,21 @@ flush_ws (SCM port, const char *eoferr)
}
break;
case '#':
switch (c = scm_getc (port))
{
case EOF:
eoferr = "read_sharp";
goto goteof;
case '!':
scm_read_scsh_block_comment (c, port);
break;
default:
scm_ungetc (c, port);
return '#';
}
break;
case SCM_LINE_INCREMENTORS:
case SCM_SINGLE_SPACES:
case '\t':
@ -637,6 +628,8 @@ static SCM
scm_read_quote (int chr, SCM port)
{
SCM p;
long line = SCM_LINUM (port);
int column = SCM_COL (port) - 1;
switch (chr)
{
@ -670,6 +663,17 @@ scm_read_quote (int chr, SCM port)
}
p = scm_cons2 (p, scm_read_expression (port), SCM_EOL);
if (SCM_RECORD_POSITIONS_P)
scm_whash_insert (scm_source_whash, p,
scm_make_srcprops (line, column,
SCM_FILENAME (port),
SCM_COPY_SOURCE_P
? (scm_cons2 (SCM_CAR (p),
SCM_CAR (SCM_CDR (p)),
SCM_EOL))
: SCM_UNDEFINED,
SCM_EOL));
return p;
}

View file

@ -67,6 +67,26 @@
+ strlen ((ptr)->sun_path))
#endif
/* The largest possible socket address. Wrapping it in a union guarantees
that the compiler will make it suitably aligned. */
typedef union
{
struct sockaddr sockaddr;
struct sockaddr_in sockaddr_in;
#ifdef HAVE_UNIX_DOMAIN_SOCKETS
struct sockaddr_un sockaddr_un;
#endif
#ifdef HAVE_IPV6
struct sockaddr_in6 sockaddr_in6;
#endif
} scm_t_max_sockaddr;
/* Maximum size of a socket address. */
#define MAX_ADDR_SIZE (sizeof (scm_t_max_sockaddr))
SCM_DEFINE (scm_htons, "htons", 1, 0, 0,
@ -344,7 +364,7 @@ SCM_DEFINE (scm_inet_pton, "inet-pton", 2, 0, 0,
{
int af;
char *src;
char dst[16];
scm_t_uint32 dst[4];
int rv, eno;
af = scm_to_int (family);
@ -359,7 +379,7 @@ SCM_DEFINE (scm_inet_pton, "inet-pton", 2, 0, 0,
else if (rv == 0)
SCM_MISC_ERROR ("Bad address", SCM_EOL);
if (af == AF_INET)
return scm_from_ulong (ntohl (*(scm_t_uint32 *) dst));
return scm_from_ulong (ntohl (*dst));
else
return scm_from_ipv6 ((scm_t_uint8 *) dst);
}
@ -468,6 +488,17 @@ SCM_DEFINE (scm_socketpair, "socketpair", 3, 0, 0,
#undef FUNC_NAME
#endif
/* Possible results for `getsockopt ()'. Wrapping it into a union guarantees
suitable alignment. */
typedef union
{
#ifdef HAVE_STRUCT_LINGER
struct linger linger;
#endif
size_t size;
int integer;
} scm_t_getsockopt_result;
SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
(SCM sock, SCM level, SCM optname),
"Return an option value from socket port @var{sock}.\n"
@ -518,13 +549,8 @@ SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
{
int fd;
/* size of optval is the largest supported option. */
#ifdef HAVE_STRUCT_LINGER
char optval[sizeof (struct linger)];
socklen_t optlen = sizeof (struct linger);
#else
char optval[sizeof (size_t)];
socklen_t optlen = sizeof (size_t);
#endif
scm_t_getsockopt_result optval;
socklen_t optlen = sizeof (optval);
int ilevel;
int ioptname;
@ -534,7 +560,7 @@ SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
ioptname = scm_to_int (optname);
fd = SCM_FPORT_FDES (sock);
if (getsockopt (fd, ilevel, ioptname, (void *) optval, &optlen) == -1)
if (getsockopt (fd, ilevel, ioptname, (void *) &optval, &optlen) == -1)
SCM_SYSERROR;
if (ilevel == SOL_SOCKET)
@ -543,12 +569,12 @@ SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
if (ioptname == SO_LINGER)
{
#ifdef HAVE_STRUCT_LINGER
struct linger *ling = (struct linger *) optval;
struct linger *ling = (struct linger *) &optval;
return scm_cons (scm_from_long (ling->l_onoff),
scm_from_long (ling->l_linger));
#else
return scm_cons (scm_from_long (*(int *) optval),
return scm_cons (scm_from_long (*(int *) &optval),
scm_from_int (0));
#endif
}
@ -563,10 +589,10 @@ SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
#endif
)
{
return scm_from_size_t (*(size_t *) optval);
return scm_from_size_t (*(size_t *) &optval);
}
}
return scm_from_int (*(int *) optval);
return scm_from_int (*(int *) &optval);
}
#undef FUNC_NAME
@ -1011,12 +1037,11 @@ SCM_DEFINE (scm_listen, "listen", 2, 0, 0,
/* Put the components of a sockaddr into a new SCM vector. */
static SCM_C_INLINE_KEYWORD SCM
_scm_from_sockaddr (const struct sockaddr *address, unsigned addr_size,
const char *proc)
_scm_from_sockaddr (const scm_t_max_sockaddr *address, unsigned addr_size,
const char *proc)
{
short int fam = address->sa_family;
SCM result =SCM_EOL;
SCM result = SCM_EOL;
short int fam = ((struct sockaddr *) address)->sa_family;
switch (fam)
{
@ -1083,7 +1108,8 @@ _scm_from_sockaddr (const struct sockaddr *address, unsigned addr_size,
SCM
scm_from_sockaddr (const struct sockaddr *address, unsigned addr_size)
{
return (_scm_from_sockaddr (address, addr_size, "scm_from_sockaddr"));
return (_scm_from_sockaddr ((scm_t_max_sockaddr *) address,
addr_size, "scm_from_sockaddr"));
}
/* Convert ADDRESS, an address object returned by either
@ -1262,38 +1288,23 @@ SCM_DEFINE (scm_make_socket_address, "make-socket-address", 2, 0, 1,
"@code{connect} for details).")
#define FUNC_NAME s_scm_make_socket_address
{
SCM result = SCM_BOOL_F;
struct sockaddr *c_address;
size_t c_address_size;
c_address = scm_c_make_socket_address (family, address, args,
&c_address_size);
if (!c_address)
return SCM_BOOL_F;
if (c_address != NULL)
{
result = scm_from_sockaddr (c_address, c_address_size);
free (c_address);
}
return (scm_from_sockaddr (c_address, c_address_size));
return result;
}
#undef FUNC_NAME
/* calculate the size of a buffer large enough to hold any supported
sockaddr type. if the buffer isn't large enough, certain system
calls will return a truncated address. */
#if defined (HAVE_UNIX_DOMAIN_SOCKETS)
#define MAX_SIZE_UN sizeof (struct sockaddr_un)
#else
#define MAX_SIZE_UN 0
#endif
#if defined (HAVE_IPV6)
#define MAX_SIZE_IN6 sizeof (struct sockaddr_in6)
#else
#define MAX_SIZE_IN6 0
#endif
#define MAX_ADDR_SIZE max (max (sizeof (struct sockaddr_in), MAX_SIZE_IN6),\
MAX_SIZE_UN)
SCM_DEFINE (scm_accept, "accept", 1, 0, 0,
(SCM sock),
"Accept a connection on a bound, listening socket.\n"
@ -1315,17 +1326,18 @@ SCM_DEFINE (scm_accept, "accept", 1, 0, 0,
SCM address;
SCM newsock;
socklen_t addr_size = MAX_ADDR_SIZE;
char max_addr[MAX_ADDR_SIZE];
struct sockaddr *addr = (struct sockaddr *) max_addr;
scm_t_max_sockaddr addr;
sock = SCM_COERCE_OUTPORT (sock);
SCM_VALIDATE_OPFPORT (1, sock);
fd = SCM_FPORT_FDES (sock);
newfd = accept (fd, addr, &addr_size);
newfd = accept (fd, (struct sockaddr *) &addr, &addr_size);
if (newfd == -1)
SCM_SYSERROR;
newsock = SCM_SOCK_FD_TO_PORT (newfd);
address = _scm_from_sockaddr (addr, addr_size, FUNC_NAME);
address = _scm_from_sockaddr (&addr, addr_size,
FUNC_NAME);
return scm_cons (newsock, address);
}
#undef FUNC_NAME
@ -1339,15 +1351,15 @@ SCM_DEFINE (scm_getsockname, "getsockname", 1, 0, 0,
{
int fd;
socklen_t addr_size = MAX_ADDR_SIZE;
char max_addr[MAX_ADDR_SIZE];
struct sockaddr *addr = (struct sockaddr *) max_addr;
scm_t_max_sockaddr addr;
sock = SCM_COERCE_OUTPORT (sock);
SCM_VALIDATE_OPFPORT (1, sock);
fd = SCM_FPORT_FDES (sock);
if (getsockname (fd, addr, &addr_size) == -1)
if (getsockname (fd, (struct sockaddr *) &addr, &addr_size) == -1)
SCM_SYSERROR;
return _scm_from_sockaddr (addr, addr_size, FUNC_NAME);
return _scm_from_sockaddr (&addr, addr_size, FUNC_NAME);
}
#undef FUNC_NAME
@ -1361,15 +1373,15 @@ SCM_DEFINE (scm_getpeername, "getpeername", 1, 0, 0,
{
int fd;
socklen_t addr_size = MAX_ADDR_SIZE;
char max_addr[MAX_ADDR_SIZE];
struct sockaddr *addr = (struct sockaddr *) max_addr;
scm_t_max_sockaddr addr;
sock = SCM_COERCE_OUTPORT (sock);
SCM_VALIDATE_OPFPORT (1, sock);
fd = SCM_FPORT_FDES (sock);
if (getpeername (fd, addr, &addr_size) == -1)
if (getpeername (fd, (struct sockaddr *) &addr, &addr_size) == -1)
SCM_SYSERROR;
return _scm_from_sockaddr (addr, addr_size, FUNC_NAME);
return _scm_from_sockaddr (&addr, addr_size, FUNC_NAME);
}
#undef FUNC_NAME
@ -1505,8 +1517,7 @@ SCM_DEFINE (scm_recvfrom, "recvfrom!", 2, 3, 0,
size_t cend;
SCM address;
socklen_t addr_size = MAX_ADDR_SIZE;
char max_addr[MAX_ADDR_SIZE];
struct sockaddr *addr = (struct sockaddr *) max_addr;
scm_t_max_sockaddr addr;
SCM_VALIDATE_OPFPORT (1, sock);
fd = SCM_FPORT_FDES (sock);
@ -1523,20 +1534,21 @@ SCM_DEFINE (scm_recvfrom, "recvfrom!", 2, 3, 0,
/* recvfrom will not necessarily return an address. usually nothing
is returned for stream sockets. */
buf = scm_i_string_writable_chars (str);
addr->sa_family = AF_UNSPEC;
((struct sockaddr *) &addr)->sa_family = AF_UNSPEC;
SCM_SYSCALL (rv = recvfrom (fd, buf + offset,
cend - offset, flg,
addr, &addr_size));
(struct sockaddr *) &addr, &addr_size));
scm_i_string_stop_writing ();
if (rv == -1)
SCM_SYSERROR;
if (addr->sa_family != AF_UNSPEC)
address = _scm_from_sockaddr (addr, addr_size, FUNC_NAME);
if (((struct sockaddr *) &addr)->sa_family != AF_UNSPEC)
address = _scm_from_sockaddr (&addr, addr_size, FUNC_NAME);
else
address = SCM_BOOL_F;
scm_remember_upto_here_1 (str);
return scm_cons (scm_from_int (rv), address);
}
#undef FUNC_NAME

View file

@ -1,6 +1,6 @@
/* srfi-14.c --- SRFI-14 procedures for Guile
*
* Copyright (C) 2001, 2004, 2006 Free Software Foundation, Inc.
* Copyright (C) 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -22,8 +22,6 @@
#endif
#define _GNU_SOURCE /* Ask for `isblank ()'. */
#include <string.h>
#include <ctype.h>

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -32,6 +32,9 @@
hard coding __hpux. */
#define _GNU_SOURCE /* ask glibc for everything, in particular strptime */
#ifndef _REENTRANT
# define _REENTRANT /* ask solaris for gmtime_r prototype */
#endif
#ifdef __hpux
#define _POSIX_C_SOURCE 199506L /* for gmtime_r prototype */
#endif

View file

@ -487,20 +487,18 @@ do_thread_exit (void *v)
static void
on_thread_exit (void *v)
{
/* This handler is executed in non-guile mode. */
scm_i_thread *t = (scm_i_thread *)v, **tp;
scm_i_pthread_setspecific (scm_i_thread_key, v);
/* Unblocking the joining threads needs to happen in guile mode
since the queue is a SCM data structure.
*/
since the queue is a SCM data structure. */
scm_with_guile (do_thread_exit, v);
/* Removing ourself from the list of all threads needs to happen in
non-guile mode since all SCM values on our stack become
unprotected once we are no longer in the list.
*/
scm_leave_guile ();
unprotected once we are no longer in the list. */
scm_i_pthread_mutex_lock (&thread_admin_mutex);
for (tp = &all_threads; *tp; tp = &(*tp)->next_thread)
if (*tp == t)

View file

@ -99,6 +99,7 @@ SCM_API void scm_i_mark_weak_vector (SCM w);
SCM_API int scm_i_mark_weak_vectors_non_weaks (void);
SCM_API void scm_i_remove_weaks_from_weak_vectors (void);
#endif /* SCM_WEAKS_H */
/*