diff --git a/include/cyclone/runtime.h b/include/cyclone/runtime.h index 7a8cbc2b..ce05dc43 100644 --- a/include/cyclone/runtime.h +++ b/include/cyclone/runtime.h @@ -216,7 +216,7 @@ port_type Cyc_stdin(void); port_type Cyc_stderr(void); port_type Cyc_io_open_input_file(void *data, object str); port_type Cyc_io_open_output_file(void *data, object str); -port_type Cyc_io_open_output_string(void *data); +port_type *Cyc_io_open_output_string(void *data); void Cyc_io_get_output_string(void *data, object cont, object port); object Cyc_io_close_port(void *data, object port); object Cyc_io_close_input_port(void *data, object port); diff --git a/mstreams.c b/mstreams.c index 5ea1b5f0..da232716 100644 --- a/mstreams.c +++ b/mstreams.c @@ -33,14 +33,24 @@ if (type_is_pair_prim(clo)) { \ } \ } -port_type Cyc_io_open_output_string(void *data) +object Cyc_heap_alloc_port(void *data); +port_type *Cyc_io_open_output_string(void *data) { - make_port(p, NULL, 0); + // Allocate port on the heap so the location of mem_buf does not change + // make_port(p, NULL, 0); + port_type *p = (port_type *)Cyc_heap_alloc_port(data); + p->hdr.mark = ((gc_thread_data *)data)->gc_alloc_color; + p->hdr.grayed = 0; + p->tag = port_tag; + p->fp = NULL; + p->mode = 0; // Output + p->mem_buf = NULL; + p->mem_buf_len = 0; errno = 0; #if CYC_HAVE_OPEN_MEMSTREAM - p.fp = open_memstream(&(p.mem_buf), &(p.mem_buf_len)); + p->fp = open_memstream(&(p->mem_buf), &(p->mem_buf_len)); #endif - if (p.fp == NULL){ + if (p->fp == NULL){ Cyc_rt_raise2(data, "Unable to open memory stream", obj_int2obj(errno)); } return p; diff --git a/runtime.c b/runtime.c index be6f19b8..b2973d0e 100644 --- a/runtime.c +++ b/runtime.c @@ -926,6 +926,19 @@ object Cyc_write_char(void *data, object c, object port) return quote_void; } +// Internal function, do not use this anywhere outside the runtime +object Cyc_heap_alloc_port(void *data) +{ + object p = NULL; + int heap_grown; + p = gc_alloc(Cyc_heap, + sizeof(port_type), + boolean_f, // OK to populate manually over here + (gc_thread_data *)data, + &heap_grown); + return p; +} + // TODO: should not be a predicate, may end up moving these to Scheme code object memberp(void *data, object x, list l) { diff --git a/scheme/base.sld b/scheme/base.sld index fca004da..d4feaef3 100644 --- a/scheme/base.sld +++ b/scheme/base.sld @@ -1163,8 +1163,8 @@ ((p->mode == 0 && p->fp != NULL) ? boolean_t : boolean_f)); ") (define-c open-output-string "(void *data, int argc, closure _, object k)" - " port_type p = Cyc_io_open_output_string(data); - return_closcall1(data, k, &p); ") + " port_type *p = Cyc_io_open_output_string(data); + return_closcall1(data, k, p); ") (define-c get-output-string "(void *data, int argc, closure _, object k, object port)" " Cyc_io_get_output_string(data, k, port);