Skip to content

Commit 33edf4c

Browse files
committed
* macros implementation
1 parent 41219ca commit 33edf4c

File tree

5 files changed

+156
-77
lines changed

5 files changed

+156
-77
lines changed

node_call.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,117 @@
11
#ifndef _AMALGAMATE_
22
#include "script.h"
3+
#include "utils.h"
4+
#include "alloc.h"
5+
#include "ulist.h"
36
#endif
47

8+
#define MACRO_MAX_ARGS_NUM 64
9+
10+
struct _call {
11+
const char *key; ///< Macro name
12+
struct node *n; ///< Call Parent node
13+
struct node *mn; ///< Macro node
14+
struct node *prev; ///< Call Prev node
15+
struct node *cloned; ///< Macro cloned node
16+
struct ulist nodes; ///< Nodes stack. struct node*
17+
struct node *args[MACRO_MAX_ARGS_NUM];
18+
};
19+
20+
static int _call_macro_visit(struct node *n, int lvl, void *d) {
21+
struct _call *call = d;
22+
23+
if (call->mn == n /*skip macro itself */ || call->mn->child == n /* skip macro name */) {
24+
return 0;
25+
}
26+
27+
if (lvl < 0) {
28+
ulist_pop(&call->nodes);
29+
return 0;
30+
}
31+
32+
// Macro arg
33+
if (n->value[0] == '&' && n->value[0] == '\0' && n->child && !n->child->next) {
34+
int rc = 0;
35+
int idx = utils_strtol(n->child->value, 10, &rc);
36+
if (rc || idx < 1 || idx >= MACRO_MAX_ARGS_NUM) {
37+
node_fatal(rc, n, "Invalid macro arg index: %d", idx);
38+
return 0;
39+
}
40+
idx--;
41+
n = call->args[idx];
42+
if (!n) {
43+
node_fatal(rc, call->n, "Call argument: %d for macro: %s is not set", (idx + 1), call->key);
44+
return 0;
45+
}
46+
}
47+
48+
struct node *parent = *(struct node**) ulist_peek(&call->nodes);
49+
struct node *nn = node_clone_and_register(n);
50+
nn->parent = parent;
51+
52+
// Add node to the parent
53+
if (!parent->child) {
54+
parent->child = nn;
55+
} else {
56+
struct node *c = parent->child;
57+
while (c && c->next) {
58+
c = c->next;
59+
}
60+
c->next = nn;
61+
}
62+
63+
node_bind(nn);
64+
ulist_push(&call->nodes, &nn);
65+
return 0;
66+
}
67+
68+
static void _call_init(struct node *n) {
69+
struct unit *unit = unit_peek();
70+
const char *key = node_value(n->child);
71+
if (!key) {
72+
node_warn(n, "No name specified for 'call' directive");
73+
return;
74+
}
75+
struct node *mn = unit_env_get_node(unit, key);
76+
if (!mn) {
77+
node_fatal(0, n, "Unknown script macro: %s", key);
78+
return;
79+
}
80+
struct _call *call = xcalloc(1, sizeof(*call));
81+
call->key = key;
82+
call->mn = mn;
83+
call->n = n;
84+
call->prev = node_find_prev_sibling(n);
85+
ulist_init(&call->nodes, 32, sizeof(struct node*));
86+
n->impl = call;
87+
88+
int idx = 0;
89+
for (struct node *pn = n->child->next; pn; pn = pn->next) {
90+
if (idx >= MACRO_MAX_ARGS_NUM) {
91+
node_fatal(0, n, "Exceeded the maximum number of macro args: " Q_STR(MACRO_MAX_ARGS_NUM));
92+
return;
93+
}
94+
call->args[idx++] = pn;
95+
}
96+
97+
ulist_push(&call->nodes, &n->parent);
98+
int rc = node_visit(mn, 1, call, _call_macro_visit);
99+
if (rc) {
100+
node_fatal(rc, n, 0);
101+
}
102+
}
103+
104+
static void _call_dispose(struct node *n) {
105+
struct _call *call = n->impl;
106+
if (call) {
107+
ulist_destroy_keep(&call->nodes);
108+
free(call);
109+
}
110+
}
111+
5112
int node_call_setup(struct node *n) {
113+
n->flags |= NODE_FLG_NO_CWD;
114+
n->init = _call_init;
115+
n->dispose = _call_dispose;
6116
return 0;
7117
}

node_macro.c

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,8 @@
11
#ifndef _AMALGAMATE_
22
#include "script.h"
3-
#include "alloc.h"
4-
#include "utils.h"
53
#endif
64

7-
#define MACRO_MAX_ARGS_NUM 64
8-
9-
struct _macro {
10-
struct node *args[MACRO_MAX_ARGS_NUM];
11-
};
12-
13-
static int _macro_args_visitor(struct node *n, int lvl, void *ctx) {
14-
if (lvl < 0) {
15-
return 0;
16-
}
17-
struct _macro *m = n->impl;
18-
if (!(n->value[0] == '&' && n->value[1] == '\0' && n->child)) {
19-
return 0;
20-
}
21-
int rc = 0;
22-
int idx = utils_strtol(n->child->value, 10, &rc);
23-
if (rc || idx < 1 || idx > MACRO_MAX_ARGS_NUM) {
24-
node_fatal(0, n, "Invalid macro argument index");
25-
return 0;
26-
}
27-
idx--;
28-
m->args[idx] = n;
29-
return 0;
30-
}
31-
32-
static void _macro_args_init(struct node *n) {
33-
akcheck(node_visit(n, 1, 0, _macro_args_visitor));
34-
}
35-
36-
static void _macro_hide(struct node *n) {
5+
static void _macro_remove(struct node *n) {
376
struct node *prev = node_find_prev_sibling(n);
387
if (prev) {
398
prev->next = n->next;
@@ -49,20 +18,12 @@ static void _macro_init(struct node *n) {
4918
node_warn(n, "No name specified for 'macro' directive");
5019
return;
5120
}
52-
struct _macro *m = xcalloc(1, sizeof(*m));
53-
_macro_args_init(n);
54-
_macro_hide(n);
21+
_macro_remove(n);
5522
unit_env_set_node(unit, key, n);
5623
}
5724

58-
static void _macro_dispose(struct node *n) {
59-
struct _macro *m = n->impl;
60-
free(m);
61-
}
62-
6325
int node_macro_setup(struct node *n) {
6426
n->flags |= NODE_FLG_NO_CWD;
6527
n->init = _macro_init;
66-
n->dispose = _macro_dispose;
6728
return 0;
6829
}

script.c

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,30 @@ static struct xnode* _node_text_push(struct _yycontext *yy, const char *text) {
210210
return _push_and_register(yy, _node_text(yy, text));
211211
}
212212

213+
int node_bind(struct node *n) {
214+
return _node_bind(n);
215+
}
216+
217+
struct node* node_clone_and_register(struct node *n_) {
218+
struct sctx *ctx = n_->ctx;
219+
struct xnode *n = (struct xnode*) n_;
220+
struct xnode *x = pool_calloc(g_env.pool, sizeof(*x));
221+
*x = *n;
222+
x->base.flags = 0;
223+
x->base.child = 0;
224+
x->base.next = 0;
225+
x->base.parent = 0;
226+
x->base.impl = 0;
227+
x->base.value_get = 0;
228+
x->base.init = 0;
229+
x->base.setup = 0;
230+
x->base.build = 0;
231+
x->base.post_build = 0;
232+
x->base.dispose = 0;
233+
_node_register(ctx, x);
234+
return (struct node*) x;
235+
}
236+
213237
static char* _text_escaped(char *wp, const char *rp) {
214238
// Replace: \} \{ \n \r \t
215239
int esc = 0;
@@ -445,16 +469,17 @@ static void _script_destroy(struct sctx *s) {
445469

446470
static int _node_bind(struct node *n) {
447471
int rc = 0;
448-
// Tree has been built since its safe to compute node name
449-
if (n->type != NODE_TYPE_SCRIPT) {
450-
n->name = pool_printf(g_env.pool, "%s:%-3u %5s", _node_file(n), n->lnum, n->value);
451-
} else {
452-
n->name = pool_printf(g_env.pool, "%s %5s", _node_file(n), "");
453-
}
454-
n->vfile = pool_printf(g_env.pool, ".%u", n->index);
455-
456472
if (!(n->flags & NODE_FLG_BOUND)) {
457473
n->flags |= NODE_FLG_BOUND;
474+
475+
// Tree has been built since its safe to compute node name
476+
if (n->type != NODE_TYPE_SCRIPT) {
477+
n->name = pool_printf(g_env.pool, "%s:%-3u %5s", _node_file(n), n->lnum, n->value);
478+
} else {
479+
n->name = pool_printf(g_env.pool, "%s %5s", _node_file(n), "");
480+
}
481+
n->vfile = pool_printf(g_env.pool, ".%u", n->index);
482+
458483
switch (n->type) {
459484
case NODE_TYPE_SCRIPT:
460485
rc = node_script_setup(n);
@@ -575,7 +600,7 @@ const char* node_value(struct node *n) {
575600
}
576601

577602
void node_reset(struct node *n) {
578-
n->flags &= ~(NODE_FLG_UPDATED | NODE_FLG_BUILT | NODE_FLG_SETUP | NODE_FLG_INIT);
603+
n->flags &= ~(NODE_FLG_BUILT | NODE_FLG_SETUP | NODE_FLG_INIT);
579604
}
580605

581606
static void _init_subnodes(struct node *n) {
@@ -609,30 +634,6 @@ static void _post_build_subnodes(struct node *n) {
609634
}
610635
}
611636

612-
static void _macro_call_init(struct node *n) {
613-
}
614-
615-
static void _macros_init(struct sctx *s) {
616-
for (int i = 0; i < s->nodes.num; ++i) {
617-
struct node *n = NODE_AT(&s->nodes, i);
618-
if (n->type == NODE_TYPE_MACRO) {
619-
n->flags |= NODE_FLG_SETUP;
620-
_node_context_push(n);
621-
n->init(n);
622-
_node_context_pop(n);
623-
}
624-
}
625-
for (int i = 0; i < s->nodes.num; ++i) {
626-
struct node *n = NODE_AT(&s->nodes, i);
627-
if (n->type == NODE_TYPE_CALL && !(n->flags & NODE_FLG_CALLED)) {
628-
n->flags |= NODE_FLG_CALLED;
629-
_node_context_push(n);
630-
_macro_call_init(n);
631-
_node_context_pop(n);
632-
}
633-
}
634-
}
635-
636637
void node_init(struct node *n) {
637638
if (!node_is_init(n)) {
638639
n->flags |= NODE_FLG_INIT;
@@ -641,6 +642,8 @@ void node_init(struct node *n) {
641642
case NODE_TYPE_INCLUDE:
642643
case NODE_TYPE_FOREACH:
643644
case NODE_TYPE_IN_SOURCES:
645+
case NODE_TYPE_MACRO:
646+
case NODE_TYPE_CALL:
644647
_node_context_push(n);
645648
n->init(n);
646649
_init_subnodes(n);
@@ -790,7 +793,6 @@ int script_include(struct node *parent, const char *file, struct node **out) {
790793

791794
void script_build(struct sctx *s) {
792795
akassert(s->root);
793-
_macros_init(s);
794796
node_init(s->root);
795797
node_setup(s->root);
796798
node_build(s->root);

script.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,13 @@
4040
#define NODE_FLG_BOUND 0x01U
4141
#define NODE_FLG_INIT 0x02U
4242
#define NODE_FLG_SETUP 0x04U
43-
#define NODE_FLG_UPDATED 0x08U // Node product updated as result of build
43+
// Vacant: 0x08U
4444
#define NODE_FLG_BUILT 0x10U // Node built
4545
#define NODE_FLG_POST_BUILT 0x20U // Node post-built
4646
#define NODE_FLG_IN_CACHE 0x40U
4747
#define NODE_FLG_IN_SRC 0x80U
4848
#define NODE_FLG_NO_CWD 0x100U
4949
#define NODE_FLG_NEGATE 0x200U
50-
#define NODE_FLG_CALLED 0x400U
5150

5251
#define NODE_FLG_IN_ANY (NODE_FLG_IN_SRC | NODE_FLG_IN_CACHE | NODE_FLG_NO_CWD)
5352

@@ -205,4 +204,8 @@ void node_warn(struct node *n, const char *fmt, ...);
205204
int node_error(int rc, struct node *n, const char *fmt, ...);
206205

207206

207+
struct node* node_clone_and_register(struct node*);
208+
209+
int node_bind(struct node*);
210+
208211
#endif

utils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include <sys/types.h>
1111
#endif
1212

13+
#define Q_XSTR(s) Q_STR(s)
14+
#define Q_STR(s) #s
15+
1316
static inline bool utils_char_is_space(char c) {
1417
return c == 32 || (c >= 9 && c <= 13);
1518
}

0 commit comments

Comments
 (0)