@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.
Files changed (131) hide show
  1. package/.editorconfig +5 -0
  2. package/.jshintignore +1 -0
  3. package/.jshintrc +23 -0
  4. package/binding.gyp +56 -0
  5. package/configure +26 -0
  6. package/deps/jq/.gitattributes +2 -0
  7. package/deps/jq/.travis.yml +53 -0
  8. package/deps/jq/AUTHORS +73 -0
  9. package/deps/jq/COPYING +70 -0
  10. package/deps/jq/ChangeLog +1349 -0
  11. package/deps/jq/Makefile.am +198 -0
  12. package/deps/jq/NEWS +88 -0
  13. package/deps/jq/README.md +64 -0
  14. package/deps/jq/builtin.c +1684 -0
  15. package/deps/jq/builtin.h +10 -0
  16. package/deps/jq/bytecode.c +161 -0
  17. package/deps/jq/bytecode.h +92 -0
  18. package/deps/jq/compile-ios.sh +102 -0
  19. package/deps/jq/compile.c +1210 -0
  20. package/deps/jq/compile.h +101 -0
  21. package/deps/jq/config/m4/check-math-func.m4 +4 -0
  22. package/deps/jq/config/m4/find-func-no-libs.m4 +8 -0
  23. package/deps/jq/config/m4/find-func-no-libs2.m4 +62 -0
  24. package/deps/jq/config/m4/find-func.m4 +9 -0
  25. package/deps/jq/config/m4/misc.m4 +3 -0
  26. package/deps/jq/configure.ac +221 -0
  27. package/deps/jq/docs/Gemfile +7 -0
  28. package/deps/jq/docs/Gemfile.lock +63 -0
  29. package/deps/jq/docs/README.md +25 -0
  30. package/deps/jq/docs/Rakefile +145 -0
  31. package/deps/jq/docs/content/1.tutorial/default.yml +327 -0
  32. package/deps/jq/docs/content/2.download/default.yml +117 -0
  33. package/deps/jq/docs/content/3.manual/manual.yml +2878 -0
  34. package/deps/jq/docs/content/3.manual/v1.3/manual.yml +1270 -0
  35. package/deps/jq/docs/content/3.manual/v1.4/manual.yml +1672 -0
  36. package/deps/jq/docs/content/index/index.yml +51 -0
  37. package/deps/jq/docs/default_manpage.md +22 -0
  38. package/deps/jq/docs/public/.htaccess +28 -0
  39. package/deps/jq/docs/public/bootstrap/css/bootstrap-responsive.css +1058 -0
  40. package/deps/jq/docs/public/bootstrap/css/bootstrap-responsive.min.css +9 -0
  41. package/deps/jq/docs/public/bootstrap/css/bootstrap.css +5224 -0
  42. package/deps/jq/docs/public/bootstrap/css/bootstrap.min.css +9 -0
  43. package/deps/jq/docs/public/bootstrap/img/glyphicons-halflings-white.png +0 -0
  44. package/deps/jq/docs/public/bootstrap/img/glyphicons-halflings.png +0 -0
  45. package/deps/jq/docs/public/bootstrap/js/bootstrap.js +2027 -0
  46. package/deps/jq/docs/public/bootstrap/js/bootstrap.min.js +6 -0
  47. package/deps/jq/docs/public/css/base.scss +99 -0
  48. package/deps/jq/docs/public/jq.png +0 -0
  49. package/deps/jq/docs/public/robots.txt +2 -0
  50. package/deps/jq/docs/site.yml +18 -0
  51. package/deps/jq/docs/templates/default.liquid +34 -0
  52. package/deps/jq/docs/templates/index.liquid +60 -0
  53. package/deps/jq/docs/templates/manual.liquid +122 -0
  54. package/deps/jq/docs/templates/shared/_footer.liquid +5 -0
  55. package/deps/jq/docs/templates/shared/_head.liquid +12 -0
  56. package/deps/jq/docs/templates/shared/_header.liquid +26 -0
  57. package/deps/jq/exec_stack.h +112 -0
  58. package/deps/jq/execute.c +1155 -0
  59. package/deps/jq/inject_errors.c +112 -0
  60. package/deps/jq/jq.1.default +39 -0
  61. package/deps/jq/jq.1.prebuilt +3075 -0
  62. package/deps/jq/jq.h +60 -0
  63. package/deps/jq/jq.spec +70 -0
  64. package/deps/jq/jq_parser.h +9 -0
  65. package/deps/jq/jq_test.c +346 -0
  66. package/deps/jq/jv.c +1333 -0
  67. package/deps/jq/jv.h +240 -0
  68. package/deps/jq/jv_alloc.c +179 -0
  69. package/deps/jq/jv_alloc.h +27 -0
  70. package/deps/jq/jv_aux.c +619 -0
  71. package/deps/jq/jv_dtoa.c +4275 -0
  72. package/deps/jq/jv_dtoa.h +22 -0
  73. package/deps/jq/jv_file.c +49 -0
  74. package/deps/jq/jv_parse.c +852 -0
  75. package/deps/jq/jv_print.c +348 -0
  76. package/deps/jq/jv_unicode.c +96 -0
  77. package/deps/jq/jv_unicode.h +11 -0
  78. package/deps/jq/jv_utf8_tables.h +37 -0
  79. package/deps/jq/lexer.c +2442 -0
  80. package/deps/jq/lexer.h +362 -0
  81. package/deps/jq/lexer.l +184 -0
  82. package/deps/jq/libm.h +160 -0
  83. package/deps/jq/linker.c +393 -0
  84. package/deps/jq/linker.h +7 -0
  85. package/deps/jq/locfile.c +91 -0
  86. package/deps/jq/locfile.h +29 -0
  87. package/deps/jq/m4/ax_compare_version.m4 +177 -0
  88. package/deps/jq/m4/ax_prog_bison_version.m4 +68 -0
  89. package/deps/jq/main.c +566 -0
  90. package/deps/jq/opcode_list.h +44 -0
  91. package/deps/jq/parser.c +3914 -0
  92. package/deps/jq/parser.h +193 -0
  93. package/deps/jq/parser.y +923 -0
  94. package/deps/jq/scripts/crosscompile +42 -0
  95. package/deps/jq/scripts/gen_utf8_tables.py +32 -0
  96. package/deps/jq/scripts/version +5 -0
  97. package/deps/jq/setup.sh +33 -0
  98. package/deps/jq/tests/jq.test +1235 -0
  99. package/deps/jq/tests/jqtest +5 -0
  100. package/deps/jq/tests/mantest +7 -0
  101. package/deps/jq/tests/modules/.jq +5 -0
  102. package/deps/jq/tests/modules/a.jq +2 -0
  103. package/deps/jq/tests/modules/b/b.jq +2 -0
  104. package/deps/jq/tests/modules/c/c.jq +16 -0
  105. package/deps/jq/tests/modules/c/d.jq +1 -0
  106. package/deps/jq/tests/modules/data.json +4 -0
  107. package/deps/jq/tests/modules/lib/jq/e/e.jq +1 -0
  108. package/deps/jq/tests/modules/lib/jq/f.jq +1 -0
  109. package/deps/jq/tests/modules/syntaxerror/syntaxerror.jq +1 -0
  110. package/deps/jq/tests/modules/test_bind_order.jq +4 -0
  111. package/deps/jq/tests/modules/test_bind_order0.jq +1 -0
  112. package/deps/jq/tests/modules/test_bind_order1.jq +2 -0
  113. package/deps/jq/tests/modules/test_bind_order2.jq +2 -0
  114. package/deps/jq/tests/onig.supp +21 -0
  115. package/deps/jq/tests/onig.test +85 -0
  116. package/deps/jq/tests/onigtest +5 -0
  117. package/deps/jq/tests/setup +36 -0
  118. package/deps/jq/tests/shtest +205 -0
  119. package/deps/jq/tests/torture/input0.json +7 -0
  120. package/deps/jq/util.c +462 -0
  121. package/deps/jq/util.h +64 -0
  122. package/deps/jq.gyp +35 -0
  123. package/index.d.ts +3 -0
  124. package/jest.config.js +10 -0
  125. package/lib/index.js +14 -0
  126. package/package.json +48 -0
  127. package/reports/jest-port-api.xml +35 -0
  128. package/src/binding.cc +177 -0
  129. package/src/binding.h +13 -0
  130. package/test/santiy.test.js +122 -0
  131. package/util/configure.js +27 -0
@@ -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
+ }
@@ -0,0 +1,7 @@
1
+ #ifndef LINKER_H
2
+ #define LINKER_H
3
+
4
+ int load_program(jq_state *jq, struct locfile* src, block *out_block);
5
+ jv load_module_meta(jq_state *jq, jv modname);
6
+
7
+ #endif
@@ -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