summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@complang.org>2016-03-09 18:12:18 +0100
committerAdrian Thurston <thurston@complang.org>2016-03-09 18:12:18 +0100
commit0814cc34b38b6c0667427577890b0803d7d835ab (patch)
tree9948c3fee6b288a3980e062075cc0641cba15dbe
parent977743c0de8c62930a468ebbce99cdfdb5e214e5 (diff)
downloadcolm-0814cc34b38b6c0667427577890b0803d7d835ab.tar.gz
manage file name allocations and allow them to be exported
File names used in locations need to live beyond a program delete, but allocating them when exporting locations is too costly. Instead manage them in the colm program and allow them to be exported so they can live beyond the colm program. Will do something similar with the token text.
-rw-r--r--src/bytecode.c6
-rw-r--r--src/colm.h2
-rw-r--r--src/input.c31
-rw-r--r--src/program.c20
-rw-r--r--src/program.h3
5 files changed, 55 insertions, 7 deletions
diff --git a/src/bytecode.c b/src/bytecode.c
index dc591af7..93d76914 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -121,7 +121,7 @@ static void rcode_downref( program_t *prg, tree_t **sp, code_t *instr );
static void open_stdout( program_t *prg )
{
if ( prg->stdout_val == 0 )
- prg->stdout_val = colm_stream_open_fd( prg, strdup("<stdout>"), 1 );
+ prg->stdout_val = colm_stream_open_fd( prg, "<stdout>", 1 );
}
static void flush_streams( program_t *prg )
@@ -3641,7 +3641,7 @@ again:
/* Pop the root object. */
vm_pop_tree();
if ( prg->stdin_val == 0 )
- prg->stdin_val = colm_stream_open_fd( prg, strdup("<stdin>"), 0 );
+ prg->stdin_val = colm_stream_open_fd( prg, "<stdin>", 0 );
vm_push_stream( prg->stdin_val );
break;
@@ -3662,7 +3662,7 @@ again:
/* Pop the root object. */
vm_pop_tree();
if ( prg->stderr_val == 0 )
- prg->stderr_val = colm_stream_open_fd( prg, strdup("<stderr>"), 2 );
+ prg->stderr_val = colm_stream_open_fd( prg, "<stderr>", 2 );
vm_push_stream( prg->stderr_val );
break;
diff --git a/src/colm.h b/src/colm.h
index 99e8810e..2240fe45 100644
--- a/src/colm.h
+++ b/src/colm.h
@@ -106,6 +106,8 @@ int colm_delete_program( struct colm_program *prg );
/* Set the pointer to the reduce struct used. */
void colm_set_reduce_ctx( struct colm_program *prg, void *ctx );
+const char **colm_extract_fns( struct colm_program *prg );
+
#ifdef __cplusplus
}
#endif
diff --git a/src/input.c b/src/input.c
index 9b925633..ed902fd7 100644
--- a/src/input.c
+++ b/src/input.c
@@ -35,6 +35,26 @@
#include <unistd.h>
#include <stdbool.h>
+char *colm_filename_add( program_t *prg, const char *fn )
+{
+ /* Search for it. */
+ const char **ptr = prg->stream_fns;
+ while ( *ptr != 0 ) {
+ if ( strcmp( *ptr, fn ) == 0 )
+ return (char*)*ptr;
+ ptr += 1;
+ }
+
+ /* Not present, find. */
+ int items = ptr - prg->stream_fns;
+
+ prg->stream_fns = realloc( prg->stream_fns, sizeof(char*) * ( items + 2 ) );
+ prg->stream_fns[items] = strdup( fn );
+ prg->stream_fns[items+1] = 0;
+
+ return (char*)prg->stream_fns[items];
+}
+
struct run_buf *new_run_buf( int sz )
{
struct run_buf *rb;
@@ -1093,7 +1113,7 @@ stream_t *colm_stream_new_struct( program_t *prg )
stream_t *colm_stream_open_fd( program_t *prg, char *name, long fd )
{
- struct stream_impl *impl = colm_impl_new_fd( name, fd );
+ struct stream_impl *impl = colm_impl_new_fd( colm_filename_add( prg, name ), fd );
struct colm_stream *s = colm_stream_new_struct( prg );
s->impl = impl;
@@ -1122,18 +1142,21 @@ stream_t *colm_stream_open_file( program_t *prg, tree_t *name, tree_t *mode )
char *file_name = (char*)malloc(string_length(head_name)+1);
memcpy( file_name, string_data(head_name), string_length(head_name) );
file_name[string_length(head_name)] = 0;
+
FILE *file = fopen( file_name, fopen_mode );
if ( file != 0 ) {
stream = colm_stream_new_struct( prg );
- stream->impl = colm_impl_new_file( file_name, file );
+ stream->impl = colm_impl_new_file( colm_filename_add( prg, file_name ), file );
}
+ free( file_name );
+
return stream;
}
stream_t *colm_stream_new( program_t *prg )
{
- struct stream_impl *impl = colm_impl_new_generic( strdup("<internal>") );
+ struct stream_impl *impl = colm_impl_new_generic( colm_filename_add( prg, "<internal>" ) );
struct colm_stream *stream = colm_stream_new_struct( prg );
stream->impl = impl;
return stream;
@@ -1149,7 +1172,7 @@ str_t *collect_string( program_t *prg, stream_t *s )
stream_t *colm_stream_open_collect( program_t *prg )
{
- struct stream_impl *impl = colm_impl_new_collect( strdup("<internal>") );
+ struct stream_impl *impl = colm_impl_new_collect( colm_filename_add( prg, "<internal>" ) );
struct colm_stream *stream = colm_stream_new_struct( prg );
stream->impl = impl;
return stream;
diff --git a/src/program.c b/src/program.c
index d2f9b200..d941cb31 100644
--- a/src/program.c
+++ b/src/program.c
@@ -195,6 +195,9 @@ program_t *colm_new_program( struct colm_sections *rtd )
vm_init( prg );
rtd->init_need();
+
+ prg->stream_fns = malloc( sizeof(char*) * 1 );
+ prg->stream_fns[0] = 0;
return prg;
}
@@ -233,6 +236,13 @@ void colm_set_reduce_ctx( struct colm_program *prg, void *ctx )
prg->red_ctx = ctx;
}
+const char **colm_extract_fns( struct colm_program *prg )
+{
+ const char **fns = prg->stream_fns;
+ prg->stream_fns = 0;
+ return fns;
+}
+
int colm_delete_program( program_t *prg )
{
tree_t **sp = prg->stack_root;
@@ -281,6 +291,16 @@ int colm_delete_program( program_t *prg )
vm_clear( prg );
+ if ( prg->stream_fns ) {
+ char **ptr = prg->stream_fns;
+ while ( *ptr != 0 ) {
+ free( *ptr );
+ ptr += 1;
+ }
+
+ free( prg->stream_fns );
+ }
+
free( prg );
return exit_status;
diff --git a/src/program.h b/src/program.h
index f3e63e4a..fa80b6bc 100644
--- a/src/program.h
+++ b/src/program.h
@@ -159,6 +159,9 @@ struct colm_program
tree_t *return_val;
void *red_ctx;
+
+ /* This can be extracted for ownership transfer before a program is deleted. */
+ const char **stream_fns;
};
#endif