-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathnode_find.c
More file actions
149 lines (131 loc) · 3.47 KB
/
Copy pathnode_find.c
File metadata and controls
149 lines (131 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#ifndef _AMALGAMATE_
#include "script.h"
#include "xstr.h"
#include "env.h"
#include "utils.h"
#include "paths.h"
#include "alloc.h"
#include <string.h>
#endif
static void _library_find(struct node *n) {
struct node *nn = n->child;
struct unit *unit = unit_peek();
struct xstr *names = xstr_create_empty();
for (nn = nn->next; nn; nn = nn->next) {
if (node_is_can_be_value(nn)) {
const char *val = node_value(nn);
if (val && *val != '\0') {
xstr_printf(names, "\1%s", val);
}
}
}
struct xstr *dirs = xstr_create_empty();
const char *ldir = env_libdir();
bool sld = strcmp(ldir, "lib") != 0;
xstr_printf(dirs, "\1%s/%s/", unit->cache_dir, ldir);
if (sld) {
xstr_printf(dirs, "\1%s/lib/", unit->cache_dir);
}
if (strcmp(unit->cache_dir, g_env.project.cache_dir) != 0) {
xstr_printf(dirs, "\1%s/%s/", g_env.project.cache_dir, ldir);
if (sld) {
xstr_printf(dirs, "\1%s/lib/", g_env.project.cache_dir);
}
}
const char *home = getenv("HOME");
if (home) {
xstr_printf(dirs, "\1%s/.local/%s/", home, ldir);
if (sld) {
xstr_printf(dirs, "\1%s/.local/lib/", home);
}
}
xstr_printf(dirs, "\1/usr/local/%s/", ldir);
if (sld) {
xstr_cat(dirs, "\1/usr/local/lib/");
}
xstr_printf(dirs, "\1/usr/%s/", ldir);
if (sld) {
xstr_cat(dirs, "\1/usr/lib/");
}
xstr_printf(dirs, "\1/%s/", ldir);
if (sld) {
xstr_cat(dirs, "\1/lib/");
}
struct vlist_iter iter_dirs;
vlist_iter_init(xstr_ptr(dirs), &iter_dirs);
while (vlist_iter_next(&iter_dirs)) {
struct vlist_iter iter_names;
vlist_iter_init(xstr_ptr(names), &iter_names);
while (vlist_iter_next(&iter_names)) {
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "%.*s%.*s",
(int) iter_dirs.len, iter_dirs.item, (int) iter_names.len, iter_names.item);
if (path_is_exist(buf)) {
n->impl = xstrdup(buf);
goto finish;
}
}
}
finish:
xstr_destroy(names);
xstr_destroy(dirs);
}
static const char* _find_value_get(struct node *n) {
if (n->impl) {
if ((uintptr_t) n->impl == (uintptr_t) -1) {
return "";
} else {
return n->impl;
}
}
n->impl = (void*) (intptr_t) -1;
const char *nv = n->value;
while(*nv == '!') ++nv;
if (strcmp("library", nv) == 0) {
_library_find(n);
}
if (!n->impl) {
n->impl = (void*) (uintptr_t) -1;
}
if ((uintptr_t) n->impl == (uintptr_t) -1) {
return "";
} else {
return n->impl;
}
}
static struct unit* _unit_for_find(struct node *n, struct node *nn, const char **keyp) {
if (nn->type == NODE_TYPE_BAG) {
if (strcmp(nn->value, "root") == 0) {
*keyp = node_value(nn->child);
return unit_root();
} else if (strcmp(nn->value, "parent") == 0) {
*keyp = node_value(nn->child);
return unit_parent(n);
}
} else {
*keyp = node_value(nn);
}
return unit_peek();
}
static void _find_init(struct node *n) {
const char *key = 0;
struct unit *unit = n->child ? _unit_for_find(n, n->child, &key) : 0;
if (!key) {
node_fatal(AK_ERROR_SCRIPT_SYNTAX, n, "No name specified for '%s' directive", n->value);
return;
}
unit_env_set_node(unit, key, n, TAG_INIT);
}
static void _find_dispose(struct node *n) {
if ((uintptr_t) n->impl != (uintptr_t) -1) {
free(n->impl);
}
n->impl = 0;
}
int node_find_setup(struct node *n) {
n->flags |= NODE_FLG_NO_CWD;
n->init = _find_init;
n->value_get = _find_value_get;
n->dispose = _find_dispose;
return 0;
}