diff options
-rw-r--r-- | src/sc_interp.c | 26 | ||||
-rw-r--r-- | src/sc_parse.c | 64 | ||||
-rw-r--r-- | src/sc_parse.h | 5 |
3 files changed, 73 insertions, 22 deletions
diff --git a/src/sc_interp.c b/src/sc_interp.c index 7b63b0d..896d3ef 100644 --- a/src/sc_interp.c +++ b/src/sc_interp.c @@ -603,17 +603,29 @@ static int check_macro(const char *name, SCInterpreter *scin) } -static void exec_macro(const char *name, SCInterpreter *scin) +static void exec_macro(SCBlock *bl, SCInterpreter *scin) { - int i; + SCBlock *mchild; struct sc_state *st = &scin->state[scin->j]; - for ( i=0; i<st->n_macros; i++ ) { - if ( strcmp(st->macros[i].name, name) == 0 ) { - sc_interp_add_blocks(scin, st->macros[i].bl); - return; + mchild = sc_block_macro_child(bl); + if ( mchild == NULL ) { + + int i; + const char *name; + + /* Copy macro blocks into structure */ + name = sc_block_name(bl); + for ( i=0; i<st->n_macros; i++ ) { + if ( strcmp(st->macros[i].name, name) == 0 ) { + mchild = sc_block_copy(st->macros[i].bl); + sc_block_set_macro_child(bl, mchild); + } } + } + + sc_interp_add_blocks(scin, mchild); } @@ -648,7 +660,7 @@ int sc_interp_add_blocks(SCInterpreter *scin, SCBlock *bl) } else if ( check_macro(name, scin) ) { maybe_recurse_before(scin, child); - exec_macro(name, scin); + exec_macro(bl, scin); maybe_recurse_after(scin, child); } else if ( strcmp(name, "pad") == 0 ) { diff --git a/src/sc_parse.c b/src/sc_parse.c index f30d6b0..93a346e 100644 --- a/src/sc_parse.c +++ b/src/sc_parse.c @@ -43,6 +43,7 @@ struct _scblock SCBlock *next; SCBlock *prev; SCBlock *child; + SCBlock *macro_child; struct frame *fr; }; @@ -55,6 +56,8 @@ SCBlock *sc_block_new() bl = calloc(1, sizeof(SCBlock)); if ( bl == NULL ) return NULL; + bl->macro_child = NULL; + return bl; } @@ -71,6 +74,18 @@ SCBlock *sc_block_child(const SCBlock *bl) } +SCBlock *sc_block_macro_child(const SCBlock *bl) +{ + return bl->macro_child; +} + + +void sc_block_set_macro_child(SCBlock *bl, SCBlock *mchild) +{ + bl->macro_child = mchild; +} + + const char *sc_block_name(const SCBlock *bl) { return bl->name; @@ -145,20 +160,7 @@ SCBlock *sc_block_append_end(SCBlock *bl, char *name, char *opt, char *contents) bl = bl->next; }; - bln->name = name; - bln->options = opt; - bln->contents = contents; - bln->child = NULL; - bln->next = NULL; - - if ( bl == NULL ) { - bln->prev = NULL; - } else { - bl->next = bln; - bln->prev = bl; - } - - return bln; + return sc_block_append(bl, name, opt, contents, NULL); } @@ -286,7 +288,8 @@ void show_sc_block(const SCBlock *bl, const char *prefix) printf("%s", prefix); if ( bl->name != NULL ) printf("\\%s ", bl->name); if ( bl->options != NULL ) printf("[%s] ", bl->options); - if ( bl->contents != NULL ) printf("{%s}", bl->contents); + if ( bl->contents != NULL ) printf("{%s} ", bl->contents); + if ( bl->fr != NULL ) printf("-> frame %p", bl->fr); printf("\n"); if ( bl->child != NULL ) { @@ -581,3 +584,34 @@ void sc_delete_text(SCBlock *b1, int o1, SCBlock *b2, int o2) } } } + + +/* Create a deep copy of "bl", including all its children */ +SCBlock *sc_block_copy(const SCBlock *bl) +{ + SCBlock *copy; + SCBlock *first_copy; + + first_copy = sc_block_new(); + + copy = first_copy; + do { + + if ( bl->name != NULL ) copy->name = strdup(bl->name); + if ( bl->options != NULL ) copy->options = strdup(bl->options); + if ( bl->contents != NULL ) copy->contents = strdup(bl->contents); + if ( bl->child != NULL ) copy->child = sc_block_copy(bl->child); + + bl = bl->next; + + if ( bl != NULL ) { + SCBlock *nn; + nn = sc_block_new(); + copy->next = nn; + copy = nn; + } + + } while ( bl != NULL ); + + return first_copy; +} diff --git a/src/sc_parse.h b/src/sc_parse.h index a5c1514..1e80c8c 100644 --- a/src/sc_parse.h +++ b/src/sc_parse.h @@ -35,12 +35,17 @@ extern SCBlock *sc_parse(const char *sc); extern void sc_block_free(SCBlock *bl); +extern SCBlock *sc_block_copy(const SCBlock *bl); + extern SCBlock *sc_block_next(const SCBlock *bl); extern SCBlock *sc_block_child(const SCBlock *bl); +extern SCBlock *sc_block_macro_child(const SCBlock *bl); extern const char *sc_block_name(const SCBlock *bl); extern const char *sc_block_options(const SCBlock *bl); extern const char *sc_block_contents(const SCBlock *bl); +extern void sc_block_set_macro_child(SCBlock *bl, SCBlock *mchild); + extern SCBlock *sc_block_append(SCBlock *bl, char *name, char *opt, char *contents, SCBlock **blfp); |