aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2014-09-08 22:30:44 +0200
committerThomas White <taw@bitwiz.org.uk>2014-09-08 22:30:44 +0200
commit5eaef1d4fcce1cfba848f081f06f3ec14a4e80a7 (patch)
treefdb0a245de7fd44c6624bab5d9600bc4cd2a939e
parentcba13eb85af0714aa7ffa605773215baf5833612 (diff)
Copy SCBlocks when executing a macro
-rw-r--r--src/sc_interp.c26
-rw-r--r--src/sc_parse.c64
-rw-r--r--src/sc_parse.h5
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);