@port-labs/jq-node-bindings 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +5 -0
- package/.jshintignore +1 -0
- package/.jshintrc +23 -0
- package/binding.gyp +56 -0
- package/configure +26 -0
- package/deps/jq/.gitattributes +2 -0
- package/deps/jq/.travis.yml +53 -0
- package/deps/jq/AUTHORS +73 -0
- package/deps/jq/COPYING +70 -0
- package/deps/jq/ChangeLog +1349 -0
- package/deps/jq/Makefile.am +198 -0
- package/deps/jq/NEWS +88 -0
- package/deps/jq/README.md +64 -0
- package/deps/jq/builtin.c +1684 -0
- package/deps/jq/builtin.h +10 -0
- package/deps/jq/bytecode.c +161 -0
- package/deps/jq/bytecode.h +92 -0
- package/deps/jq/compile-ios.sh +102 -0
- package/deps/jq/compile.c +1210 -0
- package/deps/jq/compile.h +101 -0
- package/deps/jq/config/m4/check-math-func.m4 +4 -0
- package/deps/jq/config/m4/find-func-no-libs.m4 +8 -0
- package/deps/jq/config/m4/find-func-no-libs2.m4 +62 -0
- package/deps/jq/config/m4/find-func.m4 +9 -0
- package/deps/jq/config/m4/misc.m4 +3 -0
- package/deps/jq/configure.ac +221 -0
- package/deps/jq/docs/Gemfile +7 -0
- package/deps/jq/docs/Gemfile.lock +63 -0
- package/deps/jq/docs/README.md +25 -0
- package/deps/jq/docs/Rakefile +145 -0
- package/deps/jq/docs/content/1.tutorial/default.yml +327 -0
- package/deps/jq/docs/content/2.download/default.yml +117 -0
- package/deps/jq/docs/content/3.manual/manual.yml +2878 -0
- package/deps/jq/docs/content/3.manual/v1.3/manual.yml +1270 -0
- package/deps/jq/docs/content/3.manual/v1.4/manual.yml +1672 -0
- package/deps/jq/docs/content/index/index.yml +51 -0
- package/deps/jq/docs/default_manpage.md +22 -0
- package/deps/jq/docs/public/.htaccess +28 -0
- package/deps/jq/docs/public/bootstrap/css/bootstrap-responsive.css +1058 -0
- package/deps/jq/docs/public/bootstrap/css/bootstrap-responsive.min.css +9 -0
- package/deps/jq/docs/public/bootstrap/css/bootstrap.css +5224 -0
- package/deps/jq/docs/public/bootstrap/css/bootstrap.min.css +9 -0
- package/deps/jq/docs/public/bootstrap/img/glyphicons-halflings-white.png +0 -0
- package/deps/jq/docs/public/bootstrap/img/glyphicons-halflings.png +0 -0
- package/deps/jq/docs/public/bootstrap/js/bootstrap.js +2027 -0
- package/deps/jq/docs/public/bootstrap/js/bootstrap.min.js +6 -0
- package/deps/jq/docs/public/css/base.scss +99 -0
- package/deps/jq/docs/public/jq.png +0 -0
- package/deps/jq/docs/public/robots.txt +2 -0
- package/deps/jq/docs/site.yml +18 -0
- package/deps/jq/docs/templates/default.liquid +34 -0
- package/deps/jq/docs/templates/index.liquid +60 -0
- package/deps/jq/docs/templates/manual.liquid +122 -0
- package/deps/jq/docs/templates/shared/_footer.liquid +5 -0
- package/deps/jq/docs/templates/shared/_head.liquid +12 -0
- package/deps/jq/docs/templates/shared/_header.liquid +26 -0
- package/deps/jq/exec_stack.h +112 -0
- package/deps/jq/execute.c +1155 -0
- package/deps/jq/inject_errors.c +112 -0
- package/deps/jq/jq.1.default +39 -0
- package/deps/jq/jq.1.prebuilt +3075 -0
- package/deps/jq/jq.h +60 -0
- package/deps/jq/jq.spec +70 -0
- package/deps/jq/jq_parser.h +9 -0
- package/deps/jq/jq_test.c +346 -0
- package/deps/jq/jv.c +1333 -0
- package/deps/jq/jv.h +240 -0
- package/deps/jq/jv_alloc.c +179 -0
- package/deps/jq/jv_alloc.h +27 -0
- package/deps/jq/jv_aux.c +619 -0
- package/deps/jq/jv_dtoa.c +4275 -0
- package/deps/jq/jv_dtoa.h +22 -0
- package/deps/jq/jv_file.c +49 -0
- package/deps/jq/jv_parse.c +852 -0
- package/deps/jq/jv_print.c +348 -0
- package/deps/jq/jv_unicode.c +96 -0
- package/deps/jq/jv_unicode.h +11 -0
- package/deps/jq/jv_utf8_tables.h +37 -0
- package/deps/jq/lexer.c +2442 -0
- package/deps/jq/lexer.h +362 -0
- package/deps/jq/lexer.l +184 -0
- package/deps/jq/libm.h +160 -0
- package/deps/jq/linker.c +393 -0
- package/deps/jq/linker.h +7 -0
- package/deps/jq/locfile.c +91 -0
- package/deps/jq/locfile.h +29 -0
- package/deps/jq/m4/ax_compare_version.m4 +177 -0
- package/deps/jq/m4/ax_prog_bison_version.m4 +68 -0
- package/deps/jq/main.c +566 -0
- package/deps/jq/opcode_list.h +44 -0
- package/deps/jq/parser.c +3914 -0
- package/deps/jq/parser.h +193 -0
- package/deps/jq/parser.y +923 -0
- package/deps/jq/scripts/crosscompile +42 -0
- package/deps/jq/scripts/gen_utf8_tables.py +32 -0
- package/deps/jq/scripts/version +5 -0
- package/deps/jq/setup.sh +33 -0
- package/deps/jq/tests/jq.test +1235 -0
- package/deps/jq/tests/jqtest +5 -0
- package/deps/jq/tests/mantest +7 -0
- package/deps/jq/tests/modules/.jq +5 -0
- package/deps/jq/tests/modules/a.jq +2 -0
- package/deps/jq/tests/modules/b/b.jq +2 -0
- package/deps/jq/tests/modules/c/c.jq +16 -0
- package/deps/jq/tests/modules/c/d.jq +1 -0
- package/deps/jq/tests/modules/data.json +4 -0
- package/deps/jq/tests/modules/lib/jq/e/e.jq +1 -0
- package/deps/jq/tests/modules/lib/jq/f.jq +1 -0
- package/deps/jq/tests/modules/syntaxerror/syntaxerror.jq +1 -0
- package/deps/jq/tests/modules/test_bind_order.jq +4 -0
- package/deps/jq/tests/modules/test_bind_order0.jq +1 -0
- package/deps/jq/tests/modules/test_bind_order1.jq +2 -0
- package/deps/jq/tests/modules/test_bind_order2.jq +2 -0
- package/deps/jq/tests/onig.supp +21 -0
- package/deps/jq/tests/onig.test +85 -0
- package/deps/jq/tests/onigtest +5 -0
- package/deps/jq/tests/setup +36 -0
- package/deps/jq/tests/shtest +205 -0
- package/deps/jq/tests/torture/input0.json +7 -0
- package/deps/jq/util.c +462 -0
- package/deps/jq/util.h +64 -0
- package/deps/jq.gyp +35 -0
- package/index.d.ts +3 -0
- package/jest.config.js +10 -0
- package/lib/index.js +14 -0
- package/package.json +48 -0
- package/reports/jest-port-api.xml +35 -0
- package/src/binding.cc +177 -0
- package/src/binding.h +13 -0
- package/test/santiy.test.js +122 -0
- package/util/configure.js +27 -0
package/deps/jq/linker.c
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
#include <assert.h>
|
|
2
|
+
#include <errno.h>
|
|
3
|
+
#include <limits.h>
|
|
4
|
+
#include <string.h>
|
|
5
|
+
#include <stdio.h>
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <stdint.h>
|
|
8
|
+
#include <sys/stat.h>
|
|
9
|
+
#include <libgen.h>
|
|
10
|
+
|
|
11
|
+
#ifdef WIN32
|
|
12
|
+
#include <windows.h>
|
|
13
|
+
#include <shlwapi.h>
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
#include "jq_parser.h"
|
|
17
|
+
#include "locfile.h"
|
|
18
|
+
#include "jv.h"
|
|
19
|
+
#include "jq.h"
|
|
20
|
+
#include "parser.h"
|
|
21
|
+
#include "util.h"
|
|
22
|
+
#include "compile.h"
|
|
23
|
+
|
|
24
|
+
struct lib_loading_state {
|
|
25
|
+
char **names;
|
|
26
|
+
block *defs;
|
|
27
|
+
uint64_t ct;
|
|
28
|
+
};
|
|
29
|
+
static int load_library(jq_state *jq, jv lib_path, int is_data, int raw,
|
|
30
|
+
const char *as, block *out_block,
|
|
31
|
+
struct lib_loading_state *lib_state);
|
|
32
|
+
|
|
33
|
+
static int path_is_relative(jv p) {
|
|
34
|
+
const char *s = jv_string_value(p);
|
|
35
|
+
|
|
36
|
+
#ifdef WIN32
|
|
37
|
+
int res = PathIsRelativeA(s);
|
|
38
|
+
#else
|
|
39
|
+
int res = *s != '/';
|
|
40
|
+
#endif
|
|
41
|
+
jv_free(p);
|
|
42
|
+
return res;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
// Given a lib_path to search first, creates a chain of search paths
|
|
47
|
+
// in the following order:
|
|
48
|
+
// 1. lib_path
|
|
49
|
+
// 2. -L paths passed in on the command line (from jq_state*) or builtin list
|
|
50
|
+
static jv build_lib_search_chain(jq_state *jq, jv search_path, jv jq_origin, jv lib_origin) {
|
|
51
|
+
assert(jv_get_kind(search_path) == JV_KIND_ARRAY);
|
|
52
|
+
jv expanded = jv_array();
|
|
53
|
+
jv expanded_elt;
|
|
54
|
+
jv err = jv_null();
|
|
55
|
+
jv_array_foreach(search_path, i, path) {
|
|
56
|
+
if (jv_get_kind(path) != JV_KIND_STRING) {
|
|
57
|
+
jv_free(path);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
path = expand_path(path);
|
|
61
|
+
if (!jv_is_valid(path)) {
|
|
62
|
+
err = path;
|
|
63
|
+
path = jv_null();
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (strcmp(".",jv_string_value(path)) == 0) {
|
|
67
|
+
expanded_elt = jv_copy(path);
|
|
68
|
+
} else if (strncmp("$ORIGIN/",jv_string_value(path),sizeof("$ORIGIN/") - 1) == 0) {
|
|
69
|
+
expanded_elt = jv_string_fmt("%s/%s",
|
|
70
|
+
jv_string_value(jq_origin),
|
|
71
|
+
jv_string_value(path) + sizeof ("$ORIGIN/") - 1);
|
|
72
|
+
} else if (jv_get_kind(lib_origin) == JV_KIND_STRING &&
|
|
73
|
+
path_is_relative(jv_copy(path))) {
|
|
74
|
+
expanded_elt = jv_string_fmt("%s/%s",
|
|
75
|
+
jv_string_value(lib_origin),
|
|
76
|
+
jv_string_value(path));
|
|
77
|
+
} else {
|
|
78
|
+
expanded_elt = path;
|
|
79
|
+
path = jv_invalid();
|
|
80
|
+
}
|
|
81
|
+
expanded = jv_array_append(expanded, expanded_elt);
|
|
82
|
+
jv_free(path);
|
|
83
|
+
}
|
|
84
|
+
jv_free(jq_origin);
|
|
85
|
+
jv_free(lib_origin);
|
|
86
|
+
jv_free(search_path);
|
|
87
|
+
return JV_ARRAY(expanded, err);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Doesn't actually check that name not be an absolute path, and we
|
|
91
|
+
// don't have to: we always append relative paths to others (with a '/'
|
|
92
|
+
// in between).
|
|
93
|
+
static jv validate_relpath(jv name) {
|
|
94
|
+
const char *s = jv_string_value(name);
|
|
95
|
+
if (strchr(s, '\\')) {
|
|
96
|
+
jv res = jv_invalid_with_msg(jv_string_fmt("Modules must be named by relative paths using '/', not '\\' (%s)", s));
|
|
97
|
+
jv_free(name);
|
|
98
|
+
return res;
|
|
99
|
+
}
|
|
100
|
+
jv components = jv_string_split(jv_copy(name), jv_string("/"));
|
|
101
|
+
jv rp = jv_array_get(jv_copy(components), 0);
|
|
102
|
+
components = jv_array_slice(components, 1, jv_array_length(jv_copy(components)));
|
|
103
|
+
jv_array_foreach(components, i, x) {
|
|
104
|
+
if (!strcmp(jv_string_value(x), "..")) {
|
|
105
|
+
jv_free(x);
|
|
106
|
+
jv_free(rp);
|
|
107
|
+
jv_free(components);
|
|
108
|
+
jv res = jv_invalid_with_msg(jv_string_fmt("Relative paths to modules may not traverse to parent directories (%s)", s));
|
|
109
|
+
jv_free(name);
|
|
110
|
+
return res;
|
|
111
|
+
}
|
|
112
|
+
if (i > 0 && jv_equal(jv_copy(x), jv_array_get(jv_copy(components), i - 1))) {
|
|
113
|
+
jv_free(x);
|
|
114
|
+
jv_free(rp);
|
|
115
|
+
jv_free(components);
|
|
116
|
+
jv res = jv_invalid_with_msg(jv_string_fmt("module names must not have equal consecutive components: %s",
|
|
117
|
+
jv_string_value(name)));
|
|
118
|
+
jv_free(name);
|
|
119
|
+
return res;
|
|
120
|
+
}
|
|
121
|
+
rp = jv_string_concat(rp, jv_string_concat(jv_string("/"), x));
|
|
122
|
+
}
|
|
123
|
+
jv_free(components);
|
|
124
|
+
jv_free(name);
|
|
125
|
+
return rp;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Assumes name has been validated
|
|
129
|
+
static jv jv_basename(jv name) {
|
|
130
|
+
const char *s = jv_string_value(name);
|
|
131
|
+
const char *p = strrchr(s, '/');
|
|
132
|
+
if (!p)
|
|
133
|
+
return name;
|
|
134
|
+
jv res = jv_string_fmt("%s", p);
|
|
135
|
+
jv_free(name);
|
|
136
|
+
return res;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Asummes validated relative path to module
|
|
140
|
+
static jv find_lib(jq_state *jq, jv rel_path, jv search, const char *suffix, jv jq_origin, jv lib_origin) {
|
|
141
|
+
if (jv_get_kind(search) != JV_KIND_ARRAY)
|
|
142
|
+
return jv_invalid_with_msg(jv_string_fmt("Module search path must be an array"));
|
|
143
|
+
if (jv_get_kind(rel_path) != JV_KIND_STRING)
|
|
144
|
+
return jv_invalid_with_msg(jv_string_fmt("Module path must be a string"));
|
|
145
|
+
|
|
146
|
+
struct stat st;
|
|
147
|
+
int ret;
|
|
148
|
+
|
|
149
|
+
// Ideally we should cache this somewhere
|
|
150
|
+
search = build_lib_search_chain(jq, search, jq_origin, lib_origin);
|
|
151
|
+
jv err = jv_array_get(jv_copy(search), 1);
|
|
152
|
+
search = jv_array_get(search, 0);
|
|
153
|
+
|
|
154
|
+
jv bname = jv_basename(jv_copy(rel_path));
|
|
155
|
+
|
|
156
|
+
jv_array_foreach(search, i, spath) {
|
|
157
|
+
if (jv_get_kind(spath) == JV_KIND_NULL) {
|
|
158
|
+
jv_free(spath);
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
if (jv_get_kind(spath) != JV_KIND_STRING ||
|
|
162
|
+
strcmp(jv_string_value(spath), "") == 0) {
|
|
163
|
+
jv_free(spath);
|
|
164
|
+
continue; /* XXX report non-strings in search path?? */
|
|
165
|
+
}
|
|
166
|
+
// Try ${search_dir}/${rel_path}.jq
|
|
167
|
+
jv testpath = jq_realpath(jv_string_fmt("%s/%s%s",
|
|
168
|
+
jv_string_value(spath),
|
|
169
|
+
jv_string_value(rel_path),
|
|
170
|
+
suffix));
|
|
171
|
+
ret = stat(jv_string_value(testpath),&st);
|
|
172
|
+
if (ret == -1 && errno == ENOENT) {
|
|
173
|
+
jv_free(testpath);
|
|
174
|
+
// Try ${search_dir}/$(dirname ${rel_path})/jq/main.jq
|
|
175
|
+
testpath = jq_realpath(jv_string_fmt("%s/%s/%s%s",
|
|
176
|
+
jv_string_value(spath),
|
|
177
|
+
jv_string_value(rel_path),
|
|
178
|
+
"jq/main",
|
|
179
|
+
suffix));
|
|
180
|
+
ret = stat(jv_string_value(testpath),&st);
|
|
181
|
+
}
|
|
182
|
+
if (ret == -1 && errno == ENOENT) {
|
|
183
|
+
jv_free(testpath);
|
|
184
|
+
// Try ${search_dir}/${rel_path}/$(basename ${rel_path}).jq
|
|
185
|
+
testpath = jq_realpath(jv_string_fmt("%s/%s/%s%s",
|
|
186
|
+
jv_string_value(spath),
|
|
187
|
+
jv_string_value(rel_path),
|
|
188
|
+
jv_string_value(bname),
|
|
189
|
+
suffix));
|
|
190
|
+
ret = stat(jv_string_value(testpath),&st);
|
|
191
|
+
}
|
|
192
|
+
if (ret == 0) {
|
|
193
|
+
jv_free(err);
|
|
194
|
+
jv_free(rel_path);
|
|
195
|
+
jv_free(search);
|
|
196
|
+
jv_free(bname);
|
|
197
|
+
jv_free(spath);
|
|
198
|
+
return testpath;
|
|
199
|
+
}
|
|
200
|
+
jv_free(testpath);
|
|
201
|
+
jv_free(spath);
|
|
202
|
+
}
|
|
203
|
+
jv output;
|
|
204
|
+
if (!jv_is_valid(err)) {
|
|
205
|
+
err = jv_invalid_get_msg(err);
|
|
206
|
+
output = jv_invalid_with_msg(jv_string_fmt("module not found: %s (%s)",
|
|
207
|
+
jv_string_value(rel_path),
|
|
208
|
+
jv_string_value(err)));
|
|
209
|
+
} else {
|
|
210
|
+
output = jv_invalid_with_msg(jv_string_fmt("module not found: %s",
|
|
211
|
+
jv_string_value(rel_path)));
|
|
212
|
+
}
|
|
213
|
+
jv_free(err);
|
|
214
|
+
jv_free(rel_path);
|
|
215
|
+
jv_free(search);
|
|
216
|
+
jv_free(bname);
|
|
217
|
+
return output;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
static jv default_search(jq_state *jq, jv value) {
|
|
221
|
+
if (!jv_is_valid(value)) {
|
|
222
|
+
// dependent didn't say; prepend . to system search path listj
|
|
223
|
+
jv_free(value);
|
|
224
|
+
return jv_array_concat(JV_ARRAY(jv_string(".")), jq_get_lib_dirs(jq));
|
|
225
|
+
}
|
|
226
|
+
if (jv_get_kind(value) != JV_KIND_ARRAY)
|
|
227
|
+
return JV_ARRAY(value);
|
|
228
|
+
return value;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// XXX Split this into a util that takes a callback, and then...
|
|
232
|
+
static int process_dependencies(jq_state *jq, jv jq_origin, jv lib_origin, block *src_block, struct lib_loading_state *lib_state) {
|
|
233
|
+
jv deps = block_take_imports(src_block);
|
|
234
|
+
block bk = *src_block;
|
|
235
|
+
int nerrors = 0;
|
|
236
|
+
const char *as_str = NULL;
|
|
237
|
+
|
|
238
|
+
jv_array_foreach(deps, i, dep) {
|
|
239
|
+
int is_data = jv_get_kind(jv_object_get(jv_copy(dep), jv_string("is_data"))) == JV_KIND_TRUE;
|
|
240
|
+
int raw = 0;
|
|
241
|
+
jv v = jv_object_get(jv_copy(dep), jv_string("raw"));
|
|
242
|
+
if (jv_get_kind(v) == JV_KIND_TRUE)
|
|
243
|
+
raw = 1;
|
|
244
|
+
jv_free(v);
|
|
245
|
+
jv relpath = validate_relpath(jv_object_get(jv_copy(dep), jv_string("relpath")));
|
|
246
|
+
jv as = jv_object_get(jv_copy(dep), jv_string("as"));
|
|
247
|
+
assert(!jv_is_valid(as) || jv_get_kind(as) == JV_KIND_STRING);
|
|
248
|
+
if (jv_get_kind(as) == JV_KIND_STRING)
|
|
249
|
+
as_str = jv_string_value(as);
|
|
250
|
+
jv search = default_search(jq, jv_object_get(dep, jv_string("search")));
|
|
251
|
+
// dep is now freed; do not reuse
|
|
252
|
+
|
|
253
|
+
// find_lib does a lot of work that could be cached...
|
|
254
|
+
jv resolved = find_lib(jq, relpath, search, is_data ? ".json" : ".jq", jv_copy(jq_origin), jv_copy(lib_origin));
|
|
255
|
+
// XXX ...move the rest of this into a callback.
|
|
256
|
+
if (!jv_is_valid(resolved)) {
|
|
257
|
+
jv emsg = jv_invalid_get_msg(resolved);
|
|
258
|
+
jq_report_error(jq, jv_string_fmt("jq: error: %s\n",jv_string_value(emsg)));
|
|
259
|
+
jv_free(emsg);
|
|
260
|
+
jv_free(as);
|
|
261
|
+
jv_free(deps);
|
|
262
|
+
jv_free(jq_origin);
|
|
263
|
+
jv_free(lib_origin);
|
|
264
|
+
return 1;
|
|
265
|
+
}
|
|
266
|
+
uint64_t state_idx = 0;
|
|
267
|
+
for (; state_idx < lib_state->ct; ++state_idx) {
|
|
268
|
+
if (strcmp(lib_state->names[state_idx],jv_string_value(resolved)) == 0)
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
if (state_idx < lib_state->ct) { // Found
|
|
272
|
+
jv_free(resolved);
|
|
273
|
+
// Bind the library to the program
|
|
274
|
+
bk = block_bind_library(lib_state->defs[state_idx], bk, OP_IS_CALL_PSEUDO, as_str);
|
|
275
|
+
} else { // Not found. Add it to the table before binding.
|
|
276
|
+
block dep_def_block = gen_noop();
|
|
277
|
+
nerrors += load_library(jq, resolved, is_data, raw, as_str, &dep_def_block, lib_state);
|
|
278
|
+
// resolved has been freed
|
|
279
|
+
if (nerrors == 0) {
|
|
280
|
+
// Bind the library to the program
|
|
281
|
+
bk = block_bind_library(dep_def_block, bk, OP_IS_CALL_PSEUDO, as_str);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
jv_free(as);
|
|
285
|
+
}
|
|
286
|
+
jv_free(lib_origin);
|
|
287
|
+
jv_free(jq_origin);
|
|
288
|
+
jv_free(deps);
|
|
289
|
+
return nerrors;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Loads the library at lib_path into lib_state, putting the library's defs
|
|
293
|
+
// into *out_block
|
|
294
|
+
static int load_library(jq_state *jq, jv lib_path, int is_data, int raw, const char *as, block *out_block, struct lib_loading_state *lib_state) {
|
|
295
|
+
int nerrors = 0;
|
|
296
|
+
struct locfile* src = NULL;
|
|
297
|
+
block program;
|
|
298
|
+
jv data;
|
|
299
|
+
if (is_data && !raw)
|
|
300
|
+
data = jv_load_file(jv_string_value(lib_path), 0);
|
|
301
|
+
else
|
|
302
|
+
data = jv_load_file(jv_string_value(lib_path), 1);
|
|
303
|
+
int state_idx;
|
|
304
|
+
if (!jv_is_valid(data)) {
|
|
305
|
+
if (jv_invalid_has_msg(jv_copy(data)))
|
|
306
|
+
data = jv_invalid_get_msg(data);
|
|
307
|
+
else
|
|
308
|
+
data = jv_string("unknown error");
|
|
309
|
+
jq_report_error(jq, jv_string_fmt("jq: error loading data file %s: %s\n", jv_string_value(lib_path), jv_string_value(data)));
|
|
310
|
+
nerrors++;
|
|
311
|
+
goto out;
|
|
312
|
+
} else if (is_data) {
|
|
313
|
+
// import "foo" as $bar;
|
|
314
|
+
program = gen_const_global(jv_copy(data), as);
|
|
315
|
+
} else {
|
|
316
|
+
// import "foo" as bar;
|
|
317
|
+
src = locfile_init(jq, jv_string_value(lib_path), jv_string_value(data), jv_string_length_bytes(jv_copy(data)));
|
|
318
|
+
nerrors += jq_parse_library(src, &program);
|
|
319
|
+
if (nerrors == 0) {
|
|
320
|
+
char *lib_origin = strdup(jv_string_value(lib_path));
|
|
321
|
+
nerrors += process_dependencies(jq, jq_get_jq_origin(jq),
|
|
322
|
+
jv_string(dirname(lib_origin)),
|
|
323
|
+
&program, lib_state);
|
|
324
|
+
free(lib_origin);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
state_idx = lib_state->ct++;
|
|
328
|
+
lib_state->names = realloc(lib_state->names, lib_state->ct * sizeof(const char *));
|
|
329
|
+
lib_state->defs = realloc(lib_state->defs, lib_state->ct * sizeof(block));
|
|
330
|
+
lib_state->names[state_idx] = strdup(jv_string_value(lib_path));
|
|
331
|
+
lib_state->defs[state_idx] = program;
|
|
332
|
+
*out_block = program;
|
|
333
|
+
if (src)
|
|
334
|
+
locfile_free(src);
|
|
335
|
+
out:
|
|
336
|
+
jv_free(lib_path);
|
|
337
|
+
jv_free(data);
|
|
338
|
+
return nerrors;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// FIXME It'd be nice to have an option to search the same search path
|
|
342
|
+
// as we do in process_dependencies.
|
|
343
|
+
jv load_module_meta(jq_state *jq, jv mod_relpath) {
|
|
344
|
+
// We can't know the caller's origin; we could though, if it was passed in
|
|
345
|
+
jv lib_path = find_lib(jq, validate_relpath(mod_relpath), jq_get_lib_dirs(jq), ".jq", jq_get_jq_origin(jq), jv_null());
|
|
346
|
+
if (!jv_is_valid(lib_path))
|
|
347
|
+
return lib_path;
|
|
348
|
+
jv meta = jv_null();
|
|
349
|
+
jv data = jv_load_file(jv_string_value(lib_path), 1);
|
|
350
|
+
if (jv_is_valid(data)) {
|
|
351
|
+
block program;
|
|
352
|
+
struct locfile* src = locfile_init(jq, jv_string_value(lib_path), jv_string_value(data), jv_string_length_bytes(jv_copy(data)));
|
|
353
|
+
int nerrors = jq_parse_library(src, &program);
|
|
354
|
+
if (nerrors == 0) {
|
|
355
|
+
meta = block_module_meta(program);
|
|
356
|
+
if (jv_get_kind(meta) == JV_KIND_NULL)
|
|
357
|
+
meta = jv_object();
|
|
358
|
+
meta = jv_object_set(meta, jv_string("deps"), block_take_imports(&program));
|
|
359
|
+
}
|
|
360
|
+
locfile_free(src);
|
|
361
|
+
block_free(program);
|
|
362
|
+
}
|
|
363
|
+
jv_free(lib_path);
|
|
364
|
+
jv_free(data);
|
|
365
|
+
return meta;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
int load_program(jq_state *jq, struct locfile* src, block *out_block) {
|
|
369
|
+
int nerrors = 0;
|
|
370
|
+
block program;
|
|
371
|
+
struct lib_loading_state lib_state = {0,0,0};
|
|
372
|
+
nerrors = jq_parse(src, &program);
|
|
373
|
+
if (nerrors)
|
|
374
|
+
return nerrors;
|
|
375
|
+
|
|
376
|
+
nerrors = process_dependencies(jq, jq_get_jq_origin(jq), jq_get_prog_origin(jq), &program, &lib_state);
|
|
377
|
+
block libs = gen_noop();
|
|
378
|
+
for (uint64_t i = 0; i < lib_state.ct; ++i) {
|
|
379
|
+
free(lib_state.names[i]);
|
|
380
|
+
if (nerrors == 0 && !block_is_const(lib_state.defs[i]))
|
|
381
|
+
libs = block_join(libs, lib_state.defs[i]);
|
|
382
|
+
else
|
|
383
|
+
block_free(lib_state.defs[i]);
|
|
384
|
+
}
|
|
385
|
+
free(lib_state.names);
|
|
386
|
+
free(lib_state.defs);
|
|
387
|
+
if (nerrors)
|
|
388
|
+
block_free(program);
|
|
389
|
+
else
|
|
390
|
+
*out_block = block_drop_unreferenced(block_join(libs, program));
|
|
391
|
+
|
|
392
|
+
return nerrors;
|
|
393
|
+
}
|
package/deps/jq/linker.h
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#include <assert.h>
|
|
2
|
+
#include <errno.h>
|
|
3
|
+
#include <stdarg.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include <stdio.h>
|
|
6
|
+
#include <string.h>
|
|
7
|
+
#include "jq.h"
|
|
8
|
+
#include "jv_alloc.h"
|
|
9
|
+
#include "locfile.h"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
struct locfile* locfile_init(jq_state *jq, const char *fname, const char* data, int length) {
|
|
13
|
+
struct locfile* l = jv_mem_alloc(sizeof(struct locfile));
|
|
14
|
+
l->jq = jq;
|
|
15
|
+
l->fname = jv_string(fname);
|
|
16
|
+
l->data = jv_mem_alloc(length);
|
|
17
|
+
memcpy((char*)l->data,data,length);
|
|
18
|
+
l->length = length;
|
|
19
|
+
l->nlines = 1;
|
|
20
|
+
l->refct = 1;
|
|
21
|
+
for (int i=0; i<length; i++) {
|
|
22
|
+
if (data[i] == '\n') l->nlines++;
|
|
23
|
+
}
|
|
24
|
+
l->linemap = jv_mem_alloc(sizeof(int) * (l->nlines + 1));
|
|
25
|
+
l->linemap[0] = 0;
|
|
26
|
+
int line = 1;
|
|
27
|
+
for (int i=0; i<length; i++) {
|
|
28
|
+
if (data[i] == '\n') {
|
|
29
|
+
l->linemap[line] = i+1; // at start of line, not of \n
|
|
30
|
+
line++;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
l->linemap[l->nlines] = length+1; // virtual last \n
|
|
34
|
+
return l;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
struct locfile* locfile_retain(struct locfile* l) {
|
|
38
|
+
l->refct++;
|
|
39
|
+
return l;
|
|
40
|
+
}
|
|
41
|
+
void locfile_free(struct locfile* l) {
|
|
42
|
+
if (--(l->refct) == 0) {
|
|
43
|
+
jv_free(l->fname);
|
|
44
|
+
jv_mem_free(l->linemap);
|
|
45
|
+
jv_mem_free((char*)l->data);
|
|
46
|
+
jv_mem_free(l);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
int locfile_get_line(struct locfile* l, int pos) {
|
|
51
|
+
assert(pos < l->length);
|
|
52
|
+
int line = 1;
|
|
53
|
+
while (l->linemap[line] <= pos) line++; // == if pos at start (before, never ==, because pos never on \n)
|
|
54
|
+
assert(line-1 < l->nlines);
|
|
55
|
+
return line-1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static int locfile_line_length(struct locfile* l, int line) {
|
|
59
|
+
assert(line < l->nlines);
|
|
60
|
+
return l->linemap[line+1] - l->linemap[line] -1; // -1 to omit \n
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void locfile_locate(struct locfile* l, location loc, const char* fmt, ...) {
|
|
64
|
+
va_list fmtargs;
|
|
65
|
+
va_start(fmtargs, fmt);
|
|
66
|
+
int startline;
|
|
67
|
+
int offset;
|
|
68
|
+
|
|
69
|
+
if (loc.start != -1) {
|
|
70
|
+
startline = locfile_get_line(l, loc.start);
|
|
71
|
+
offset = l->linemap[startline];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
jv m1 = jv_string_vfmt(fmt, fmtargs);
|
|
75
|
+
if (!jv_is_valid(m1)) {
|
|
76
|
+
jq_report_error(l->jq, m1);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (loc.start == -1) {
|
|
80
|
+
jq_report_error(l->jq, jv_string_fmt("jq: error: %s\n<unknown location>", jv_string_value(m1)));
|
|
81
|
+
jv_free(m1);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
jv m2 = jv_string_fmt("%s at %s, line %d:\n%.*s%*s", jv_string_value(m1),
|
|
85
|
+
jv_string_value(l->fname), startline + 1,
|
|
86
|
+
locfile_line_length(l, startline), l->data + offset,
|
|
87
|
+
loc.start - offset, "");
|
|
88
|
+
jv_free(m1);
|
|
89
|
+
jq_report_error(l->jq, m2);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#ifndef LOCFILE_H
|
|
2
|
+
#define LOCFILE_H
|
|
3
|
+
|
|
4
|
+
#include "jq.h"
|
|
5
|
+
|
|
6
|
+
typedef struct {
|
|
7
|
+
int start, end;
|
|
8
|
+
} location;
|
|
9
|
+
|
|
10
|
+
static const location UNKNOWN_LOCATION = {-1, -1};
|
|
11
|
+
|
|
12
|
+
struct locfile {
|
|
13
|
+
jv fname;
|
|
14
|
+
const char* data;
|
|
15
|
+
int length;
|
|
16
|
+
int* linemap;
|
|
17
|
+
int nlines;
|
|
18
|
+
char *error;
|
|
19
|
+
jq_state *jq;
|
|
20
|
+
int refct;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
struct locfile* locfile_init(jq_state *, const char *, const char *, int);
|
|
24
|
+
struct locfile* locfile_retain(struct locfile *);
|
|
25
|
+
int locfile_get_line(struct locfile *, int);
|
|
26
|
+
void locfile_free(struct locfile *);
|
|
27
|
+
void locfile_locate(struct locfile *, location, const char *, ...);
|
|
28
|
+
|
|
29
|
+
#endif
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# ===========================================================================
|
|
2
|
+
# http://www.gnu.org/software/autoconf-archive/ax_compare_version.html
|
|
3
|
+
# ===========================================================================
|
|
4
|
+
#
|
|
5
|
+
# SYNOPSIS
|
|
6
|
+
#
|
|
7
|
+
# AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
|
|
8
|
+
#
|
|
9
|
+
# DESCRIPTION
|
|
10
|
+
#
|
|
11
|
+
# This macro compares two version strings. Due to the various number of
|
|
12
|
+
# minor-version numbers that can exist, and the fact that string
|
|
13
|
+
# comparisons are not compatible with numeric comparisons, this is not
|
|
14
|
+
# necessarily trivial to do in a autoconf script. This macro makes doing
|
|
15
|
+
# these comparisons easy.
|
|
16
|
+
#
|
|
17
|
+
# The six basic comparisons are available, as well as checking equality
|
|
18
|
+
# limited to a certain number of minor-version levels.
|
|
19
|
+
#
|
|
20
|
+
# The operator OP determines what type of comparison to do, and can be one
|
|
21
|
+
# of:
|
|
22
|
+
#
|
|
23
|
+
# eq - equal (test A == B)
|
|
24
|
+
# ne - not equal (test A != B)
|
|
25
|
+
# le - less than or equal (test A <= B)
|
|
26
|
+
# ge - greater than or equal (test A >= B)
|
|
27
|
+
# lt - less than (test A < B)
|
|
28
|
+
# gt - greater than (test A > B)
|
|
29
|
+
#
|
|
30
|
+
# Additionally, the eq and ne operator can have a number after it to limit
|
|
31
|
+
# the test to that number of minor versions.
|
|
32
|
+
#
|
|
33
|
+
# eq0 - equal up to the length of the shorter version
|
|
34
|
+
# ne0 - not equal up to the length of the shorter version
|
|
35
|
+
# eqN - equal up to N sub-version levels
|
|
36
|
+
# neN - not equal up to N sub-version levels
|
|
37
|
+
#
|
|
38
|
+
# When the condition is true, shell commands ACTION-IF-TRUE are run,
|
|
39
|
+
# otherwise shell commands ACTION-IF-FALSE are run. The environment
|
|
40
|
+
# variable 'ax_compare_version' is always set to either 'true' or 'false'
|
|
41
|
+
# as well.
|
|
42
|
+
#
|
|
43
|
+
# Examples:
|
|
44
|
+
#
|
|
45
|
+
# AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8])
|
|
46
|
+
# AX_COMPARE_VERSION([3.15],[lt],[3.15.8])
|
|
47
|
+
#
|
|
48
|
+
# would both be true.
|
|
49
|
+
#
|
|
50
|
+
# AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8])
|
|
51
|
+
# AX_COMPARE_VERSION([3.15],[gt],[3.15.8])
|
|
52
|
+
#
|
|
53
|
+
# would both be false.
|
|
54
|
+
#
|
|
55
|
+
# AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8])
|
|
56
|
+
#
|
|
57
|
+
# would be true because it is only comparing two minor versions.
|
|
58
|
+
#
|
|
59
|
+
# AX_COMPARE_VERSION([3.15.7],[eq0],[3.15])
|
|
60
|
+
#
|
|
61
|
+
# would be true because it is only comparing the lesser number of minor
|
|
62
|
+
# versions of the two values.
|
|
63
|
+
#
|
|
64
|
+
# Note: The characters that separate the version numbers do not matter. An
|
|
65
|
+
# empty string is the same as version 0. OP is evaluated by autoconf, not
|
|
66
|
+
# configure, so must be a string, not a variable.
|
|
67
|
+
#
|
|
68
|
+
# The author would like to acknowledge Guido Draheim whose advice about
|
|
69
|
+
# the m4_case and m4_ifvaln functions make this macro only include the
|
|
70
|
+
# portions necessary to perform the specific comparison specified by the
|
|
71
|
+
# OP argument in the final configure script.
|
|
72
|
+
#
|
|
73
|
+
# LICENSE
|
|
74
|
+
#
|
|
75
|
+
# Copyright (c) 2008 Tim Toolan <toolan@ele.uri.edu>
|
|
76
|
+
#
|
|
77
|
+
# Copying and distribution of this file, with or without modification, are
|
|
78
|
+
# permitted in any medium without royalty provided the copyright notice
|
|
79
|
+
# and this notice are preserved. This file is offered as-is, without any
|
|
80
|
+
# warranty.
|
|
81
|
+
|
|
82
|
+
#serial 11
|
|
83
|
+
|
|
84
|
+
dnl #########################################################################
|
|
85
|
+
AC_DEFUN([AX_COMPARE_VERSION], [
|
|
86
|
+
AC_REQUIRE([AC_PROG_AWK])
|
|
87
|
+
|
|
88
|
+
# Used to indicate true or false condition
|
|
89
|
+
ax_compare_version=false
|
|
90
|
+
|
|
91
|
+
# Convert the two version strings to be compared into a format that
|
|
92
|
+
# allows a simple string comparison. The end result is that a version
|
|
93
|
+
# string of the form 1.12.5-r617 will be converted to the form
|
|
94
|
+
# 0001001200050617. In other words, each number is zero padded to four
|
|
95
|
+
# digits, and non digits are removed.
|
|
96
|
+
AS_VAR_PUSHDEF([A],[ax_compare_version_A])
|
|
97
|
+
A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
|
|
98
|
+
-e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
|
|
99
|
+
-e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
|
|
100
|
+
-e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
|
|
101
|
+
-e 's/[[^0-9]]//g'`
|
|
102
|
+
|
|
103
|
+
AS_VAR_PUSHDEF([B],[ax_compare_version_B])
|
|
104
|
+
B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
|
|
105
|
+
-e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
|
|
106
|
+
-e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
|
|
107
|
+
-e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
|
|
108
|
+
-e 's/[[^0-9]]//g'`
|
|
109
|
+
|
|
110
|
+
dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary
|
|
111
|
+
dnl # then the first line is used to determine if the condition is true.
|
|
112
|
+
dnl # The sed right after the echo is to remove any indented white space.
|
|
113
|
+
m4_case(m4_tolower($2),
|
|
114
|
+
[lt],[
|
|
115
|
+
ax_compare_version=`echo "x$A
|
|
116
|
+
x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"`
|
|
117
|
+
],
|
|
118
|
+
[gt],[
|
|
119
|
+
ax_compare_version=`echo "x$A
|
|
120
|
+
x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"`
|
|
121
|
+
],
|
|
122
|
+
[le],[
|
|
123
|
+
ax_compare_version=`echo "x$A
|
|
124
|
+
x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"`
|
|
125
|
+
],
|
|
126
|
+
[ge],[
|
|
127
|
+
ax_compare_version=`echo "x$A
|
|
128
|
+
x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"`
|
|
129
|
+
],[
|
|
130
|
+
dnl Split the operator from the subversion count if present.
|
|
131
|
+
m4_bmatch(m4_substr($2,2),
|
|
132
|
+
[0],[
|
|
133
|
+
# A count of zero means use the length of the shorter version.
|
|
134
|
+
# Determine the number of characters in A and B.
|
|
135
|
+
ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'`
|
|
136
|
+
ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'`
|
|
137
|
+
|
|
138
|
+
# Set A to no more than B's length and B to no more than A's length.
|
|
139
|
+
A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"`
|
|
140
|
+
B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"`
|
|
141
|
+
],
|
|
142
|
+
[[0-9]+],[
|
|
143
|
+
# A count greater than zero means use only that many subversions
|
|
144
|
+
A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
|
|
145
|
+
B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
|
|
146
|
+
],
|
|
147
|
+
[.+],[
|
|
148
|
+
AC_WARNING(
|
|
149
|
+
[illegal OP numeric parameter: $2])
|
|
150
|
+
],[])
|
|
151
|
+
|
|
152
|
+
# Pad zeros at end of numbers to make same length.
|
|
153
|
+
ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`"
|
|
154
|
+
B="$B`echo $A | sed 's/./0/g'`"
|
|
155
|
+
A="$ax_compare_version_tmp_A"
|
|
156
|
+
|
|
157
|
+
# Check for equality or inequality as necessary.
|
|
158
|
+
m4_case(m4_tolower(m4_substr($2,0,2)),
|
|
159
|
+
[eq],[
|
|
160
|
+
test "x$A" = "x$B" && ax_compare_version=true
|
|
161
|
+
],
|
|
162
|
+
[ne],[
|
|
163
|
+
test "x$A" != "x$B" && ax_compare_version=true
|
|
164
|
+
],[
|
|
165
|
+
AC_WARNING([illegal OP parameter: $2])
|
|
166
|
+
])
|
|
167
|
+
])
|
|
168
|
+
|
|
169
|
+
AS_VAR_POPDEF([A])dnl
|
|
170
|
+
AS_VAR_POPDEF([B])dnl
|
|
171
|
+
|
|
172
|
+
dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE.
|
|
173
|
+
if test "$ax_compare_version" = "true" ; then
|
|
174
|
+
m4_ifvaln([$4],[$4],[:])dnl
|
|
175
|
+
m4_ifvaln([$5],[else $5])dnl
|
|
176
|
+
fi
|
|
177
|
+
]) dnl AX_COMPARE_VERSION
|