summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@colm.net>2018-06-25 10:34:35 +0700
committerAdrian Thurston <thurston@colm.net>2018-06-25 10:34:35 +0700
commit2c3a53fcc12e2435cb8950c146c1f7fe63949b72 (patch)
tree2988c71ee8294bff43b8c8fe830d25f021634a06 /src
parent58fe99bfaa90bd59cc28a69d36407b06cbaac560 (diff)
downloadcolm-2c3a53fcc12e2435cb8950c146c1f7fe63949b72.tar.gz
limit the undoing of consumed data
When undoing the consume of make sure we don't send back more than we took out. Once we hit the limit then move backwards to the previous stream, which we now stash.
Diffstat (limited to 'src')
-rw-r--r--src/input.c53
-rw-r--r--src/input.h3
-rw-r--r--src/pdarun.c2
3 files changed, 41 insertions, 17 deletions
diff --git a/src/input.c b/src/input.c
index 6cdb7738..cd80d550 100644
--- a/src/input.c
+++ b/src/input.c
@@ -480,14 +480,21 @@ static int data_consume_data( struct stream_impl_data *ss, int length, location_
return consumed;
}
-static int data_undo_consume_data( struct stream_impl_data *ss, const char *data, int length )
+static int data_undo_consume_data( struct stream_impl_data *si, const char *data, int length )
{
- struct run_buf *new_buf = new_run_buf( 0 );
- new_buf->length = length;
- memcpy( new_buf->data, data, length );
- source_stream_data_prepend( ss, new_buf );
- undo_position_data( ss, data, length );
- ss->consumed -= length;
+ //printf( "data-undo-consume-data %p, undoing consume of %d bytes, consumed: %d\n", si, length, si->consumed );
+
+ if ( length > si->consumed )
+ length = si->consumed;
+
+ if ( length > 0 ) {
+ struct run_buf *new_buf = new_run_buf( 0 );
+ new_buf->length = length;
+ memcpy( new_buf->data, data, length );
+ source_stream_data_prepend( si, new_buf );
+ undo_position_data( si, data, length );
+ si->consumed -= length;
+ }
return length;
}
@@ -547,6 +554,19 @@ void init_stream_impl_data( struct stream_impl_data *is, char *name )
is->level = COLM_INDENT_OFF;
}
+static void input_stream_stash_head( struct stream_impl_seq *si, struct seq_buf *seq_buf )
+{
+ seq_buf->next = si->stash;
+ si->stash = seq_buf;
+}
+
+static struct seq_buf *input_stream_pop_stash( struct stream_impl_seq *si )
+{
+ struct seq_buf *seq_buf = si->stash;
+ si->stash = si->stash->next;
+ return seq_buf;
+}
+
static struct seq_buf *input_stream_seq_pop_head( struct stream_impl_seq *is )
{
struct seq_buf *ret = is->queue;
@@ -880,11 +900,7 @@ static int stream_consume_data( struct stream_impl_seq *is, int length, location
}
struct seq_buf *seq_buf = input_stream_seq_pop_head( is );
- //if ( run_Buf->type == RUN_BUF_SOURCE_TYPE ) {
- // stream_t *stream = runBuf->stream;
- // colm_tree_downref( prg, sp, (tree_t*) stream );
- //}
- free( seq_buf );
+ input_stream_stash_head( is, seq_buf );
}
return consumed;
@@ -892,12 +908,19 @@ static int stream_consume_data( struct stream_impl_seq *is, int length, location
static int stream_undo_consume_data( struct stream_impl_seq *is, const char *data, int length )
{
- //debug( REALM_INPUT, "undoing consume of %ld bytes\n", length );
+ //debug( REALM_INPUT, "stream %p, undoing consume of %ld bytes\n", is, length );
if ( is->consumed == 0 && is_source_stream( is ) ) {
struct stream_impl *si = is->queue->si;
- int len = si->funcs->undo_consume_data( si, data, length );
- return len;
+ int pushed_back = si->funcs->undo_consume_data( si, data, length );
+
+ if ( pushed_back < length ) {
+ struct seq_buf *b = input_stream_pop_stash( is );
+ input_stream_seq_prepend( is, b );
+ pushed_back += stream_undo_consume_data( is, data + pushed_back, length - pushed_back );
+ }
+
+ return pushed_back;
}
else {
struct seq_buf *new_buf = new_seq_buf( 0 );
diff --git a/src/input.h b/src/input.h
index 0cf77566..fbe2ec01 100644
--- a/src/input.h
+++ b/src/input.h
@@ -77,7 +77,6 @@ struct run_buf
{
enum run_buf_type type;
long length;
- struct colm_tree *tree;
long offset;
struct run_buf *next, *prev;
@@ -145,6 +144,8 @@ struct stream_impl_seq
struct seq_buf *queue;
struct seq_buf *queue_tail;
+ struct seq_buf *stash;
+
long line;
long column;
long byte;
diff --git a/src/pdarun.c b/src/pdarun.c
index 43676949..212e3a10 100644
--- a/src/pdarun.c
+++ b/src/pdarun.c
@@ -1969,7 +1969,7 @@ long colm_parse_loop( program_t *prg, tree_t **sp, struct pda_run *pda_run,
pda_run->stop = false;
while ( true ) {
- debug( prg, REALM_PARSE, "parse loop start" );
+ debug( prg, REALM_PARSE, "parse loop start\n" );
/* Pull the current scanner from the parser. This can change during
* parsing due to inputStream pushes, usually for the purpose of includes.