diff options
author | Adrian Thurston <thurston@complang.org> | 2016-03-09 18:12:18 +0100 |
---|---|---|
committer | Adrian Thurston <thurston@complang.org> | 2016-03-09 18:12:18 +0100 |
commit | 0814cc34b38b6c0667427577890b0803d7d835ab (patch) | |
tree | 9948c3fee6b288a3980e062075cc0641cba15dbe | |
parent | 977743c0de8c62930a468ebbce99cdfdb5e214e5 (diff) | |
download | colm-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.c | 6 | ||||
-rw-r--r-- | src/colm.h | 2 | ||||
-rw-r--r-- | src/input.c | 31 | ||||
-rw-r--r-- | src/program.c | 20 | ||||
-rw-r--r-- | src/program.h | 3 |
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; @@ -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 |