various fixes, gc can handle running the whole test suite

in a loop hundreds of times.  the heuristics for growing
the heap still cause it to grow very slowly over time,
but nonetheless slower than boehm.
This commit is contained in:
Alex Shinn 2009-06-19 17:57:40 +09:00
parent 9e6a0c1300
commit 56dcf497de
7 changed files with 167 additions and 159 deletions

View file

@ -9,21 +9,17 @@ LIBDIR=$(PREFIX)/lib
INCDIR=$(PREFIX)/include/chibi-scheme
MODDIR=$(PREFIX)/share/chibi-scheme
LDFLAGS=-lm
LDFLAGS=-lm #-lgc -L/opt/local/lib
# -Oz for smaller size on darwin
CFLAGS=-Wall -O2 -g #-save-temps
CFLAGS=-Wall -O2 -g #-I/opt/local/include #-save-temps
./gc/gc.a: ./gc/alloc.c
cd gc && make
sexp.o: sexp.c gc.c sexp.h config.h defaults.h Makefile
sexp.o: sexp.c gc.c sexp.h config.h Makefile
gcc -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
eval.o: eval.c debug.c opcodes.c eval.h sexp.h config.h defaults.h Makefile
eval.o: eval.c debug.c opcodes.c eval.h sexp.h config.h Makefile
gcc -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
main.o: main.c eval.c debug.c opcodes.c eval.h sexp.h config.h defaults.h Makefile
main.o: main.c eval.c debug.c opcodes.c eval.h sexp.h config.h Makefile
gcc -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
chibi-scheme: main.o sexp.o

View file

@ -14,8 +14,8 @@
/* uncomment this if you only want fixnum support */
/* #define USE_FLONUMS 0 */
/* uncomment this if you want immediate flonums */
#define USE_IMMEDIATE_FLONUMS 1
/* uncomment this if you want immediate flonums (experimental) */
/* #define USE_IMMEDIATE_FLONUMS 1 */
/* uncomment this if you don't need extended math operations */
/* #define USE_MATH 0 */
@ -32,9 +32,75 @@
/* uncomment this to disable string ports */
/* #define USE_STRING_STREAMS 0 */
/* uncomment this to disable a small optimization for let */
/* #define USE_FAST_LET 0 */
/* uncomment this to disable stack checks */
/* #define USE_CHECK_STACK 0 */
/* uncomment this to enable debugging utilities */
/* #define USE_DEBUG 1 */
/************************************************************************/
/* DEFAULTS - DO NOT MODIFY ANYTHING BELOW THIS LINE */
/************************************************************************/
#if HAVE_ERR_H
#include <err.h>
#else
/* requires msg be a string literal, and at least one argument */
#define errx(code, msg, ...) (fprintf(stderr,msg"\n",__VA_ARGS__), exit(code))
#endif
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
#define SEXP_BSD 1
#else
#define SEXP_BSD 0
#define _GNU_SOURCE
#endif
#ifndef USE_BOEHM
#define USE_BOEHM 0
#endif
#ifndef USE_MALLOC
#define USE_MALLOC 0
#endif
#ifndef USE_DEBUG_GC
#define USE_DEBUG_GC 0
#endif
#ifndef USE_FLONUMS
#define USE_FLONUMS 1
#endif
#ifndef USE_IMMEDIATE_FLONUMS
#define USE_IMMEDIATE_FLONUMS 0
#endif
#ifndef USE_MATH
#define USE_MATH 1
#endif
#ifndef USE_WARN_UNDEFS
#define USE_WARN_UNDEFS 1
#endif
#ifndef USE_HUFF_SYMS
#define USE_HUFF_SYMS 1
#endif
#ifndef USE_HASH_SYMS
#define USE_HASH_SYMS 1
#endif
#ifndef USE_DEBUG
#define USE_DEBUG 1
#endif
#ifndef USE_STRING_STREAMS
#define USE_STRING_STREAMS 1
#endif
#ifndef USE_CHECK_STACK
#define USE_CHECK_STACK 1
#endif

View file

@ -1,70 +0,0 @@
/* defaults.h -- defaults for unspecified configs */
/* Copyright (c) 2009 Alex Shinn. All rights reserved. */
/* BSD-style license: http://synthcode.com/license.txt */
#if HAVE_ERR_H
#include <err.h>
#else
/* requires msg be a string literal, and at least one argument */
#define errx(code, msg, ...) (fprintf(stderr,msg"\n",__VA_ARGS__), exit(code))
#endif
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
#define SEXP_BSD 1
#else
#define SEXP_BSD 0
#define _GNU_SOURCE
#endif
#ifndef USE_BOEHM
#define USE_BOEHM 0
#endif
#ifndef USE_MALLOC
#define USE_MALLOC 0
#endif
#ifndef USE_DEBUG_GC
#define USE_DEBUG_GC 0
#endif
#ifndef USE_FLONUMS
#define USE_FLONUMS 1
#endif
#ifndef USE_IMMEDIATE_FLONUMS
#define USE_IMMEDIATE_FLONUMS 0
#endif
#ifndef USE_MATH
#define USE_MATH 1
#endif
#ifndef USE_WARN_UNDEFS
#define USE_WARN_UNDEFS 1
#endif
#ifndef USE_HUFF_SYMS
#define USE_HUFF_SYMS 1
#endif
#ifndef USE_HASH_SYMS
#define USE_HASH_SYMS 1
#endif
#ifndef USE_DEBUG
#define USE_DEBUG 1
#endif
#ifndef USE_STRING_STREAMS
#define USE_STRING_STREAMS 1
#endif
#ifndef USE_FAST_LET
#define USE_FAST_LET 1
#endif
#ifndef USE_CHECK_STACK
#define USE_CHECK_STACK 0
#endif

50
eval.c
View file

@ -1310,8 +1310,10 @@ sexp vm (sexp ctx, sexp proc) {
goto make_call;
case OP_CALL:
#if USE_CHECK_STACK
if (top >= INIT_STACK_SIZE)
sexp_raise("out of stack space", SEXP_NULL);
if (top+16 >= INIT_STACK_SIZE) {
fprintf(stderr, "out of stack space\n");
exit(70);
}
#endif
i = sexp_unbox_integer(_WORD0);
tmp1 = _ARG1;
@ -1550,9 +1552,9 @@ sexp vm (sexp ctx, sexp proc) {
else if (sexp_flonump(_ARG1) && sexp_flonump(_ARG2))
_ARG2 = sexp_fp_add(ctx, _ARG1, _ARG2);
else if (sexp_flonump(_ARG1) && sexp_integerp(_ARG2))
_ARG2 = sexp_fp_add(ctx, _ARG1, sexp_integer_to_flonum(ctx, _ARG2));
_ARG2 = sexp_make_flonum(ctx, sexp_flonum_value(_ARG1) + (double)sexp_unbox_integer(_ARG2));
else if (sexp_integerp(_ARG1) && sexp_flonump(_ARG2))
_ARG2 = sexp_fp_add(ctx, sexp_integer_to_flonum(ctx, _ARG1), _ARG2);
_ARG2 = sexp_make_flonum(ctx, (double)sexp_unbox_integer(_ARG1) + sexp_flonum_value(_ARG2));
#endif
else sexp_raise("+: not a number", sexp_list2(ctx, _ARG1, _ARG2));
top--;
@ -1564,9 +1566,9 @@ sexp vm (sexp ctx, sexp proc) {
else if (sexp_flonump(_ARG1) && sexp_flonump(_ARG2))
_ARG2 = sexp_fp_sub(ctx, _ARG1, _ARG2);
else if (sexp_flonump(_ARG1) && sexp_integerp(_ARG2))
_ARG2 = sexp_fp_sub(ctx, _ARG1, sexp_integer_to_flonum(ctx, _ARG2));
_ARG2 = sexp_make_flonum(ctx, sexp_flonum_value(_ARG1) - (double)sexp_unbox_integer(_ARG2));
else if (sexp_integerp(_ARG1) && sexp_flonump(_ARG2))
_ARG2 = sexp_fp_sub(ctx, sexp_integer_to_flonum(ctx, _ARG1), _ARG2);
_ARG2 = sexp_make_flonum(ctx, (double)sexp_unbox_integer(_ARG1) - sexp_flonum_value(_ARG2));
#endif
else sexp_raise("-: not a number", sexp_list2(ctx, _ARG1, _ARG2));
top--;
@ -1578,9 +1580,9 @@ sexp vm (sexp ctx, sexp proc) {
else if (sexp_flonump(_ARG1) && sexp_flonump(_ARG2))
_ARG2 = sexp_fp_mul(ctx, _ARG1, _ARG2);
else if (sexp_flonump(_ARG1) && sexp_integerp(_ARG2))
_ARG2 = sexp_fp_mul(ctx, _ARG1, sexp_integer_to_flonum(ctx, _ARG2));
_ARG2 = sexp_make_flonum(ctx, sexp_flonum_value(_ARG1) * (double)sexp_unbox_integer(_ARG2));
else if (sexp_integerp(_ARG1) && sexp_flonump(_ARG2))
_ARG2 = sexp_fp_mul(ctx, sexp_integer_to_flonum(ctx, _ARG1), _ARG2);
_ARG2 = sexp_make_flonum(ctx, (double)sexp_unbox_integer(_ARG1) * sexp_flonum_value(_ARG2));
#endif
else sexp_raise("*: not a number", sexp_list2(ctx, _ARG1, _ARG2));
top--;
@ -1588,17 +1590,22 @@ sexp vm (sexp ctx, sexp proc) {
case OP_DIV:
if (_ARG2 == sexp_make_integer(0))
sexp_raise("divide by zero", SEXP_NULL);
if (sexp_integerp(_ARG1) && sexp_integerp(_ARG2))
_ARG2 = sexp_fp_div(ctx,
sexp_integer_to_flonum(ctx, _ARG1),
sexp_integer_to_flonum(ctx, _ARG2));
if (sexp_integerp(_ARG1) && sexp_integerp(_ARG2)) {
#if USE_FLONUMS
_ARG1 = sexp_integer_to_flonum(ctx, _ARG1);
_ARG2 = sexp_integer_to_flonum(ctx, _ARG2);
_ARG2 = sexp_fp_div(ctx, _ARG1, _ARG2);
#else
_ARG2 = sexp_fx_div(_ARG1, _ARG2);
#endif
}
#if USE_FLONUMS
else if (sexp_flonump(_ARG1) && sexp_flonump(_ARG2))
_ARG2 = sexp_fp_div(ctx, _ARG1, _ARG2);
else if (sexp_flonump(_ARG1) && sexp_integerp(_ARG2))
_ARG2 = sexp_fp_div(ctx, _ARG1, sexp_integer_to_flonum(ctx, _ARG2));
_ARG2 = sexp_make_flonum(ctx, sexp_flonum_value(_ARG1) / (double)sexp_unbox_integer(_ARG2));
else if (sexp_integerp(_ARG1) && sexp_flonump(_ARG2))
_ARG2 = sexp_fp_div(ctx, sexp_integer_to_flonum(ctx, _ARG1), _ARG2);
_ARG2 = sexp_make_flonum(ctx, (double)sexp_unbox_integer(_ARG1) / sexp_flonum_value(_ARG2));
#endif
else sexp_raise("/: not a number", sexp_list2(ctx, _ARG1, _ARG2));
top--;
@ -1804,7 +1811,7 @@ static sexp sexp_open_input_file (sexp ctx, sexp path) {
if (! in)
return
sexp_user_exception(ctx, SEXP_FALSE, "couldn't open input file", path);
return sexp_make_input_port(ctx, in, sexp_string_data(path));
return sexp_make_input_port(ctx, in, path);
}
static sexp sexp_open_output_file (sexp ctx, sexp path) {
@ -1815,7 +1822,7 @@ static sexp sexp_open_output_file (sexp ctx, sexp path) {
if (! out)
return
sexp_user_exception(ctx, SEXP_FALSE, "couldn't open output file", path);
return sexp_make_input_port(ctx, out, sexp_string_data(path));
return sexp_make_input_port(ctx, out, path);
}
static sexp sexp_close_port (sexp ctx, sexp port) {
@ -1834,13 +1841,16 @@ static void sexp_warn_undefs (sexp from, sexp to, sexp out) {
}
sexp sexp_load (sexp ctx, sexp source, sexp env) {
sexp tmp, out, res=SEXP_VOID;
sexp tmp, out;
sexp_gc_var(ctx, ctx2, s_ctx2);
sexp_gc_var(ctx, x, s_x);
sexp_gc_var(ctx, in, s_in);
sexp_gc_var(ctx, res, s_res);
sexp_gc_preserve(ctx, ctx2, s_ctx2);
sexp_gc_preserve(ctx, x, s_x);
sexp_gc_preserve(ctx, in, s_in);
sexp_gc_preserve(ctx, res, s_res);
res = SEXP_VOID;
in = sexp_open_input_file(ctx, source);
out = env_global_ref(env, the_cur_err_symbol, SEXP_FALSE);
ctx2 = sexp_make_context(ctx, NULL, env);
@ -2021,11 +2031,11 @@ static sexp sexp_make_standard_env (sexp ctx, sexp version) {
env_define(ctx, e, sexp_intern(ctx, sexp_opcode_name(op)), op);
}
env_define(ctx, e, the_cur_in_symbol,
sexp_make_input_port(ctx, stdin, NULL));
sexp_make_input_port(ctx, stdin, SEXP_FALSE));
env_define(ctx, e, the_cur_out_symbol,
sexp_make_output_port(ctx, stdout, NULL));
sexp_make_output_port(ctx, stdout, SEXP_FALSE));
env_define(ctx, e, the_cur_err_symbol,
sexp_make_output_port(ctx, stderr, NULL));
sexp_make_output_port(ctx, stderr, SEXP_FALSE));
env_define(ctx, e, the_interaction_env_symbol, e);
sexp_gc_release(ctx, e, s_e);
return e;

34
gc.c
View file

@ -4,11 +4,12 @@
#include "sexp.h"
/* #define SEXP_INITIAL_HEAP_SIZE (2*1024*1024) */
#define SEXP_INITIAL_HEAP_SIZE 37000
#define SEXP_INITIAL_HEAP_SIZE (2*1024*1024)
#define SEXP_MAXIMUM_HEAP_SIZE 0
#define SEXP_MINIMUM_OBJECT_SIZE (sexp_sizeof(flonum))
#define SEXP_GROW_HEAP_RATIO 0.8
#define SEXP_MINIMUM_OBJECT_SIZE (sexp_sizeof(pair))
#define SEXP_GROW_HEAP_RATIO 0.7
#define sexp_heap_align(n) sexp_align(n, 4)
typedef struct sexp_heap *sexp_heap;
@ -67,7 +68,7 @@ void sexp_mark (sexp x) {
#if USE_DEBUG_GC
int stack_references_pointer_p (sexp ctx, sexp x) {
sexp *p;
for (p=&x; p<stack_base; p++)
for (p=(&x)+1; p<stack_base; p++)
if (*p == x)
return 1;
return 0;
@ -76,8 +77,8 @@ int stack_references_pointer_p (sexp ctx, sexp x) {
#define stack_references_pointer_p(ctx, x) 0
#endif
sexp sexp_sweep (sexp ctx) {
sexp_uint_t freed, max_freed=0, sum_freed=0, size;
sexp sexp_sweep (sexp ctx, size_t *sum_freed_ptr) {
size_t freed, max_freed=0, sum_freed=0, size;
sexp_heap h = heap;
sexp p, q, r;
char *end;
@ -133,10 +134,11 @@ sexp sexp_sweep (sexp ctx) {
}
}
}
sum_freed_ptr[0] = sum_freed;
return sexp_make_integer(max_freed);
}
sexp sexp_gc (sexp ctx) {
sexp sexp_gc (sexp ctx, size_t *sum_freed) {
sexp res;
int i;
sexp_mark(continuation_resumer);
@ -144,14 +146,17 @@ sexp sexp_gc (sexp ctx) {
for (i=0; i<SEXP_SYMBOL_TABLE_SIZE; i++)
sexp_mark(sexp_symbol_table[i]);
sexp_mark(ctx);
res = sexp_sweep(ctx);
res = sexp_sweep(ctx, sum_freed);
return res;
}
sexp_heap sexp_make_heap (size_t size) {
sexp free, next;
sexp_heap h = (sexp_heap) malloc(sizeof(struct sexp_heap) + size);
if (h) {
if (! h) {
fprintf(stderr, "out of memory allocating %ld byte heap, aborting\n", size);
exit(70);
}
h->size = size;
h->data = (char*) sexp_heap_align((sexp_uint_t)&(h->data));
free = h->free_list = (sexp) h->data;
@ -163,7 +168,6 @@ sexp_heap sexp_make_heap (size_t size) {
sexp_pointer_tag(next) = SEXP_PAIR;
sexp_car(next) = (sexp) (size - sexp_heap_align(sexp_sizeof(pair)));
sexp_cdr(next) = SEXP_NULL;
}
return h;
}
@ -205,15 +209,15 @@ void* sexp_try_alloc (sexp ctx, size_t size) {
void* sexp_alloc (sexp ctx, size_t size) {
void *res;
size_t freed;
size_t max_freed, sum_freed;
sexp_heap h;
size = sexp_heap_align(size);
res = sexp_try_alloc(ctx, size);
if (! res) {
freed = sexp_unbox_integer(sexp_gc(ctx));
max_freed = sexp_unbox_integer(sexp_gc(ctx, &sum_freed));
h = sexp_heap_last(heap);
if (((freed < size)
|| ((h->size - freed) < h->size*(1 - SEXP_GROW_HEAP_RATIO)))
if (((max_freed < size)
|| ((h->size - sum_freed) < (h->size*(1 - SEXP_GROW_HEAP_RATIO))))
&& ((! SEXP_MAXIMUM_HEAP_SIZE) || (size < SEXP_MAXIMUM_HEAP_SIZE)))
sexp_grow_heap(ctx, size);
res = sexp_try_alloc(ctx, size);

53
sexp.c
View file

@ -6,12 +6,12 @@
/* optional huffman-compressed immediate symbols */
#if USE_HUFF_SYMS
struct huff_entry {
struct sexp_huff_entry {
unsigned char len;
unsigned short bits;
};
#include "opt/sexp-hufftabs.c"
static struct huff_entry huff_table[] = {
static struct sexp_huff_entry huff_table[] = {
#include "opt/sexp-huff.c"
};
#endif
@ -67,8 +67,8 @@ static struct sexp_struct sexp_types[] = {
_DEF_TYPE(SEXP_VECTOR, sexp_offsetof(vector, data), 0, sexp_offsetof(vector, length), 1, sexp_sizeof(vector), sexp_offsetof(vector, length), 4, "vector"),
_DEF_TYPE(SEXP_FLONUM, 0, 0, 0, 0, sexp_sizeof(flonum), 0, 0, "flonum"),
_DEF_TYPE(SEXP_BIGNUM, 0, 0, 0, 0, sexp_sizeof(bignum), sexp_offsetof(bignum, length), 4, "bignum"),
_DEF_TYPE(SEXP_IPORT, sexp_offsetof(port, cookie), 1, 0, 0, sexp_sizeof(port), 0, 0, "input-port"),
_DEF_TYPE(SEXP_OPORT, sexp_offsetof(port, cookie), 1, 0, 0, sexp_sizeof(port), 0, 0, "output-port"),
_DEF_TYPE(SEXP_IPORT, sexp_offsetof(port, name), 2, 0, 0, sexp_sizeof(port), 0, 0, "input-port"),
_DEF_TYPE(SEXP_OPORT, sexp_offsetof(port, name), 2, 0, 0, sexp_sizeof(port), 0, 0, "output-port"),
_DEF_TYPE(SEXP_EXCEPTION, sexp_offsetof(exception, kind), 6, 0, 0, sexp_sizeof(exception), 0, 0, "exception"),
_DEF_TYPE(SEXP_PROCEDURE, sexp_offsetof(procedure, bc), 2, 0, 0, sexp_sizeof(procedure), 0, 0, "procedure"),
_DEF_TYPE(SEXP_MACRO, sexp_offsetof(macro, proc), 2, 0, 0, sexp_sizeof(macro), 0, 0, "macro"),
@ -214,8 +214,7 @@ static sexp sexp_read_error (sexp ctx, char *msg, sexp irritants, sexp port) {
sexp_gc_var(ctx, str, s_str);
sexp_gc_preserve(ctx, name, s_name);
sexp_gc_preserve(ctx, str, s_str);
name = (sexp_port_name(port)
? sexp_c_string(ctx, sexp_port_name(port), -1) : SEXP_FALSE);
name = (sexp_port_name(port) ? sexp_port_name(port) : SEXP_FALSE);
str = sexp_c_string(ctx, msg, -1);
res = sexp_make_exception(ctx, the_read_error_symbol,
str, irritants, SEXP_FALSE, name,
@ -402,7 +401,8 @@ sexp sexp_make_string(sexp ctx, sexp len, sexp ch) {
sexp sexp_c_string(sexp ctx, char *str, sexp_sint_t slen) {
sexp_sint_t len = ((slen >= 0) ? slen : strlen(str));
sexp s = sexp_make_string(ctx, sexp_make_integer(len), SEXP_VOID);
memcpy(sexp_string_data(s), str, len+1);
memcpy(sexp_string_data(s), str, len);
sexp_string_data(s)[len] = '\0';
return s;
}
@ -425,7 +425,8 @@ sexp sexp_substring (sexp ctx, sexp str, sexp start, sexp end) {
res = sexp_make_string(ctx, sexp_fx_sub(end, start), SEXP_VOID);
memcpy(sexp_string_data(res),
sexp_string_data(str)+sexp_unbox_integer(start),
sexp_string_length(res)+1);
sexp_string_length(res));
sexp_string_data(res)[sexp_string_length(res)] = '\0';
return res;
}
@ -442,7 +443,7 @@ static sexp_uint_t sexp_string_hash(char *str, sexp_uint_t acc) {
#endif
sexp sexp_intern(sexp ctx, char *str) {
struct huff_entry he;
struct sexp_huff_entry he;
sexp_uint_t len, res=FNV_OFFSET_BASIS, space=3, newbits, bucket;
char c, *p=str;
sexp ls;
@ -529,9 +530,10 @@ sexp sexp_vector(sexp ctx, int count, ...) {
#if SEXP_BSD
#define sexp_stream_buf(vec) sexp_vector_ref((sexp)vec, sexp_make_integer(0))
#define sexp_stream_size(vec) sexp_vector_ref((sexp)vec, sexp_make_integer(1))
#define sexp_stream_pos(vec) sexp_vector_ref((sexp)vec, sexp_make_integer(2))
#define sexp_stream_ctx(vec) sexp_vector_ref((sexp)vec, sexp_make_integer(0))
#define sexp_stream_buf(vec) sexp_vector_ref((sexp)vec, sexp_make_integer(1))
#define sexp_stream_size(vec) sexp_vector_ref((sexp)vec, sexp_make_integer(2))
#define sexp_stream_pos(vec) sexp_vector_ref((sexp)vec, sexp_make_integer(3))
int sstream_read (void *vec, char *dst, int n) {
sexp_uint_t len = sexp_unbox_integer(sexp_stream_size(vec));
@ -550,7 +552,9 @@ int sstream_write (void *vec, const char *src, int n) {
pos = sexp_unbox_integer(sexp_stream_pos(vec));
newpos = pos+n;
if (newpos >= len) {
newbuf = sexp_make_string(NULL, sexp_make_integer(newpos*2), SEXP_VOID);
newbuf = sexp_make_string(sexp_stream_ctx(vec),
sexp_make_integer(newpos*2),
SEXP_VOID);
memcpy(sexp_string_data(newbuf),
sexp_string_data(sexp_stream_buf(vec)),
pos);
@ -580,10 +584,11 @@ sexp sexp_make_input_string_port (sexp ctx, sexp str) {
sexp res;
sexp_gc_var(ctx, cookie, s_cookie);
sexp_gc_preserve(ctx, cookie, s_cookie);
cookie = sexp_vector(ctx, 3, str, sexp_make_integer(sexp_string_length(str)),
cookie = sexp_vector(ctx, 4, ctx, str,
sexp_make_integer(sexp_string_length(str)),
sexp_make_integer(0));
in = funopen(cookie, &sstream_read, NULL, &sstream_seek, NULL);
res = sexp_make_input_port(ctx, in, NULL);
res = sexp_make_input_port(ctx, in, SEXP_FALSE);
sexp_port_cookie(res) = cookie;
sexp_gc_release(ctx, cookie, s_cookie);
return res;
@ -595,10 +600,10 @@ sexp sexp_make_output_string_port (sexp ctx) {
sexp_gc_var(ctx, cookie, s_cookie);
sexp_gc_preserve(ctx, cookie, s_cookie);
size = sexp_make_integer(SEXP_INIT_STRING_PORT_SIZE);
cookie = sexp_vector(ctx, 3, sexp_make_string(NULL, size, SEXP_VOID),
cookie = sexp_vector(ctx, 4, ctx, sexp_make_string(ctx, size, SEXP_VOID),
size, sexp_make_integer(0));
out = funopen(cookie, NULL, &sstream_write, &sstream_seek, NULL);
res = sexp_make_output_port(ctx, out, NULL);
res = sexp_make_output_port(ctx, out, SEXP_FALSE);
sexp_port_cookie(res) = cookie;
sexp_gc_release(ctx, cookie, s_cookie);
return res;
@ -617,14 +622,14 @@ sexp sexp_get_output_string (sexp ctx, sexp port) {
sexp sexp_make_input_string_port (sexp ctx, sexp str) {
FILE *in = fmemopen(sexp_string_data(str), sexp_string_length(str), "r");
return sexp_make_input_port(in, NULL);
return sexp_make_input_port(ctx, in, SEXP_FALSE);
}
sexp sexp_make_output_string_port (sexp ctx) {
FILE *out;
sexp buf = sexp_alloc_type(ctx, string, SEXP_STRING), res;
out = open_memstream(&sexp_string_data(buf), &sexp_string_length(buf));
res = sexp_make_input_port(out, NULL);
res = sexp_make_input_port(ctx, out, SEXP_FALSE);
sexp_port_cookie(res) = buf;
return res;
}
@ -641,18 +646,18 @@ sexp sexp_get_output_string (sexp ctx, sexp port) {
#endif
sexp sexp_make_input_port (sexp ctx, FILE* in, char *path) {
sexp sexp_make_input_port (sexp ctx, FILE* in, sexp name) {
sexp p = sexp_alloc_type(ctx, port, SEXP_IPORT);
sexp_port_stream(p) = in;
sexp_port_name(p) = path;
sexp_port_name(p) = name;
sexp_port_line(p) = 0;
return p;
}
sexp sexp_make_output_port (sexp ctx, FILE* out, char *path) {
sexp sexp_make_output_port (sexp ctx, FILE* out, sexp name) {
sexp p = sexp_alloc_type(ctx, port, SEXP_OPORT);
sexp_port_stream(p) = out;
sexp_port_name(p) = path;
sexp_port_name(p) = name;
sexp_port_line(p) = 0;
return p;
}
@ -665,7 +670,7 @@ void sexp_write (sexp obj, sexp out) {
char *str=NULL;
if (! obj) {
sexp_write_string("#<null>", out);
sexp_write_string("#<null>", out); /* shouldn't happen */
} else if (sexp_pointerp(obj)) {
switch (sexp_pointer_tag(obj)) {
case SEXP_PAIR:

11
sexp.h
View file

@ -6,7 +6,6 @@
#define SEXP_H
#include "config.h"
#include "defaults.h"
#include <ctype.h>
#include <stdio.h>
@ -14,7 +13,6 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sysexits.h>
#include <sys/types.h>
#include <math.h>
@ -123,8 +121,8 @@ struct sexp_struct {
} symbol;
struct {
FILE *stream;
char *name;
sexp_uint_t line;
sexp name;
sexp cookie;
} port;
struct {
@ -216,7 +214,7 @@ struct sexp_struct {
#define sexp_gc_preserve(ctx, x, y)
#define sexp_gc_release(ctx, x, y)
#include "gc/include/gc.h"
#include "gc.h"
#define sexp_alloc(ctx, size) GC_malloc(size)
#define sexp_alloc_atomic(ctx, size) GC_malloc_atomic(size)
#define sexp_realloc(ctx, x, size) GC_realloc(x, size)
@ -257,7 +255,6 @@ void *sexp_realloc(sexp ctx, sexp x, size_t size);
#endif
#define sexp_align(n, bits) (((n)+(1<<(bits))-1)&(((sexp_uint_t)-1)-((1<<(bits))-1)))
#define sexp_heap_align(n) sexp_align(n, 4)
#define sexp_sizeof(x) (offsetof(struct sexp_struct, value) \
+ sizeof(((sexp)0)->value.x))
@ -540,8 +537,8 @@ sexp sexp_read_number(sexp ctx, sexp in, int base);
sexp sexp_read_raw(sexp ctx, sexp in);
sexp sexp_read(sexp ctx, sexp in);
sexp sexp_read_from_string(sexp ctx, char *str);
sexp sexp_make_input_port(sexp ctx, FILE* in, char *path);
sexp sexp_make_output_port(sexp ctx, FILE* out, char *path);
sexp sexp_make_input_port(sexp ctx, FILE* in, sexp name);
sexp sexp_make_output_port(sexp ctx, FILE* out, sexp name);
sexp sexp_make_input_string_port(sexp ctx, sexp str);
sexp sexp_make_output_string_port(sexp ctx);
sexp sexp_get_output_string(sexp ctx, sexp port);