Fixup API to get closer to a libjq
This commit is contained in:
1 parent
69fa279e3c
commit
3f86e97f70
8 files changed
+203
-75
No files matched your search
+18
-16
@@ -14,6 +14,22 @@ static int bytecode_operation_length(uint16_t* codeptr) {
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_code(int indent, struct bytecode* bc) {
|
||||||
|
int pc = 0;
|
||||||
|
while (pc < bc->codelen) {
|
||||||
|
printf("%*s", indent, "");
|
||||||
|
dump_operation(bc, bc->code + pc);
|
||||||
|
printf("\n");
|
||||||
|
pc += bytecode_operation_length(bc->code + pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void symbol_table_free(struct symbol_table* syms) {
|
||||||
|
jv_mem_free(syms->cfunctions);
|
||||||
|
jv_free(syms->cfunc_names);
|
||||||
|
jv_mem_free(syms);
|
||||||
|
}
|
||||||
|
|
||||||
void dump_disassembly(int indent, struct bytecode* bc) {
|
void dump_disassembly(int indent, struct bytecode* bc) {
|
||||||
if (bc->nclosures > 0) {
|
if (bc->nclosures > 0) {
|
||||||
printf("%*s[params: ", indent, "");
|
printf("%*s[params: ", indent, "");
|
||||||
@@ -37,16 +53,6 @@ void dump_disassembly(int indent, struct bytecode* bc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_code(int indent, struct bytecode* bc) {
|
|
||||||
int pc = 0;
|
|
||||||
while (pc < bc->codelen) {
|
|
||||||
printf("%*s", indent, "");
|
|
||||||
dump_operation(bc, bc->code + pc);
|
|
||||||
printf("\n");
|
|
||||||
pc += bytecode_operation_length(bc->code + pc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct bytecode* getlevel(struct bytecode* bc, int level) {
|
static struct bytecode* getlevel(struct bytecode* bc, int level) {
|
||||||
while (level > 0) {
|
while (level > 0) {
|
||||||
bc = bc->parent;
|
bc = bc->parent;
|
||||||
@@ -109,13 +115,9 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void symbol_table_free(struct symbol_table* syms) {
|
|
||||||
jv_mem_free(syms->cfunctions);
|
|
||||||
jv_free(syms->cfunc_names);
|
|
||||||
jv_mem_free(syms);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bytecode_free(struct bytecode* bc) {
|
void bytecode_free(struct bytecode* bc) {
|
||||||
|
if (!bc)
|
||||||
|
return;
|
||||||
jv_mem_free(bc->code);
|
jv_mem_free(bc->code);
|
||||||
jv_free(bc->constants);
|
jv_free(bc->constants);
|
||||||
for (int i=0; i<bc->nsubfunctions; i++)
|
for (int i=0; i<bc->nsubfunctions; i++)
|
||||||
|
|||||||
@@ -39,10 +39,8 @@ struct bytecode {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void dump_disassembly(int, struct bytecode* code);
|
void dump_disassembly(int, struct bytecode* code);
|
||||||
void dump_code(int, struct bytecode* code);
|
|
||||||
void dump_operation(struct bytecode* bc, uint16_t* op);
|
void dump_operation(struct bytecode* bc, uint16_t* op);
|
||||||
|
|
||||||
void symbol_table_free(struct symbol_table* syms);
|
|
||||||
void bytecode_free(struct bytecode* bc);
|
void bytecode_free(struct bytecode* bc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -23,6 +23,9 @@ struct jq_state {
|
|||||||
struct forkable_stack data_stk;
|
struct forkable_stack data_stk;
|
||||||
struct forkable_stack frame_stk;
|
struct forkable_stack frame_stk;
|
||||||
struct forkable_stack fork_stk;
|
struct forkable_stack fork_stk;
|
||||||
|
void (*nomem_handler)(void *);
|
||||||
|
void *nomem_handler_data;
|
||||||
|
struct bytecode* bc;
|
||||||
jv path;
|
jv path;
|
||||||
int subexp_nest;
|
int subexp_nest;
|
||||||
int debug_trace_enabled;
|
int debug_trace_enabled;
|
||||||
@@ -118,6 +121,17 @@ uint16_t* stack_restore(jq_state *jq){
|
|||||||
return retaddr;
|
return retaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void jq_reset(jq_state *jq) {
|
||||||
|
while (stack_restore(jq)) {}
|
||||||
|
assert(forkable_stack_empty(&jq->fork_stk));
|
||||||
|
assert(forkable_stack_empty(&jq->data_stk));
|
||||||
|
assert(forkable_stack_empty(&jq->frame_stk));
|
||||||
|
|
||||||
|
if (jv_get_kind(jq->path) != JV_KIND_INVALID)
|
||||||
|
jv_free(jq->path);
|
||||||
|
jq->path = jv_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uint16_t* pc) {
|
static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uint16_t* pc) {
|
||||||
uint16_t level = *pc++;
|
uint16_t level = *pc++;
|
||||||
@@ -147,6 +161,8 @@ void print_error(jv value) {
|
|||||||
jv jq_next(jq_state *jq) {
|
jv jq_next(jq_state *jq) {
|
||||||
jv cfunc_input[MAX_CFUNCTION_ARGS];
|
jv cfunc_input[MAX_CFUNCTION_ARGS];
|
||||||
|
|
||||||
|
jv_nomem_handler(jq->nomem_handler, jq->nomem_handler_data);
|
||||||
|
|
||||||
uint16_t* pc = stack_restore(jq);
|
uint16_t* pc = stack_restore(jq);
|
||||||
assert(pc);
|
assert(pc);
|
||||||
|
|
||||||
@@ -552,28 +568,41 @@ jv jq_next(jq_state *jq) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jq_state *jq_init(void) {
|
||||||
|
jq_state *jq;
|
||||||
|
jq = jv_mem_alloc_unguarded(sizeof(*jq));
|
||||||
|
if (jq == NULL)
|
||||||
|
return NULL;
|
||||||
|
memset(jq, 0, sizeof(*jq));
|
||||||
|
jq->debug_trace_enabled = 0;
|
||||||
|
jq->initial_execution = 1;
|
||||||
|
forkable_stack_init(&jq->data_stk, sizeof(data_stk_elem) * 100);
|
||||||
|
forkable_stack_init(&jq->frame_stk, 1024);
|
||||||
|
forkable_stack_init(&jq->fork_stk, 1024);
|
||||||
|
jq->path = jv_null();
|
||||||
|
return jq;
|
||||||
|
}
|
||||||
|
|
||||||
void jq_init(struct bytecode* bc, jv input, jq_state **jq, int flags) {
|
void jq_set_nomem_handler(jq_state *jq, void (*nomem_handler)(void *), void *data) {
|
||||||
jq_state *new_jq;
|
jv_nomem_handler(nomem_handler, data);
|
||||||
new_jq = jv_mem_alloc(sizeof(*new_jq));
|
jq->nomem_handler = nomem_handler;
|
||||||
memset(new_jq, 0, sizeof(*new_jq));
|
jq->nomem_handler_data = data;
|
||||||
new_jq->path = jv_null();
|
}
|
||||||
forkable_stack_init(&new_jq->data_stk, sizeof(data_stk_elem) * 100);
|
|
||||||
forkable_stack_init(&new_jq->frame_stk, 1024);
|
void jq_start(jq_state *jq, jv input, int flags) {
|
||||||
forkable_stack_init(&new_jq->fork_stk, 1024);
|
jv_nomem_handler(jq->nomem_handler, jq->nomem_handler_data);
|
||||||
|
jq_reset(jq);
|
||||||
stack_push(new_jq, input);
|
stack_push(jq, input);
|
||||||
struct closure top = {bc, -1};
|
struct closure top = {jq->bc, -1};
|
||||||
frame_push(&new_jq->frame_stk, top, 0);
|
frame_push(&jq->frame_stk, top, 0);
|
||||||
stack_save(new_jq, bc->code);
|
stack_save(jq, jq->bc->code);
|
||||||
stack_switch(new_jq);
|
stack_switch(jq);
|
||||||
if (flags & JQ_DEBUG_TRACE) {
|
if (flags & JQ_DEBUG_TRACE) {
|
||||||
new_jq->debug_trace_enabled = 1;
|
jq->debug_trace_enabled = 1;
|
||||||
} else {
|
} else {
|
||||||
new_jq->debug_trace_enabled = 0;
|
jq->debug_trace_enabled = 0;
|
||||||
}
|
}
|
||||||
new_jq->initial_execution = 1;
|
jq->initial_execution = 1;
|
||||||
*jq = new_jq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void jq_teardown(jq_state **jq) {
|
void jq_teardown(jq_state **jq) {
|
||||||
@@ -582,25 +611,26 @@ void jq_teardown(jq_state **jq) {
|
|||||||
return;
|
return;
|
||||||
*jq = NULL;
|
*jq = NULL;
|
||||||
|
|
||||||
while (stack_restore(old_jq)) {}
|
jq_reset(old_jq);
|
||||||
|
|
||||||
assert(forkable_stack_empty(&old_jq->fork_stk));
|
|
||||||
assert(forkable_stack_empty(&old_jq->data_stk));
|
|
||||||
assert(forkable_stack_empty(&old_jq->frame_stk));
|
|
||||||
forkable_stack_free(&old_jq->fork_stk);
|
forkable_stack_free(&old_jq->fork_stk);
|
||||||
forkable_stack_free(&old_jq->data_stk);
|
forkable_stack_free(&old_jq->data_stk);
|
||||||
forkable_stack_free(&old_jq->frame_stk);
|
forkable_stack_free(&old_jq->frame_stk);
|
||||||
|
bytecode_free(old_jq->bc);
|
||||||
jv_free(old_jq->path);
|
old_jq->bc = 0;
|
||||||
jv_mem_free(old_jq);
|
jv_mem_free(old_jq);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bytecode* jq_compile_args(const char* str, jv args) {
|
int jq_compile_args(jq_state *jq, const char* str, jv args) {
|
||||||
|
jv_nomem_handler(jq->nomem_handler, jq->nomem_handler_data);
|
||||||
assert(jv_get_kind(args) == JV_KIND_ARRAY);
|
assert(jv_get_kind(args) == JV_KIND_ARRAY);
|
||||||
struct locfile locations;
|
struct locfile locations;
|
||||||
locfile_init(&locations, str, strlen(str));
|
locfile_init(&locations, str, strlen(str));
|
||||||
block program;
|
block program;
|
||||||
struct bytecode* bc = 0;
|
jq_reset(jq);
|
||||||
|
if (jq->bc) {
|
||||||
|
bytecode_free(jq->bc);
|
||||||
|
jq->bc = 0;
|
||||||
|
}
|
||||||
int nerrors = jq_parse(&locations, &program);
|
int nerrors = jq_parse(&locations, &program);
|
||||||
if (nerrors == 0) {
|
if (nerrors == 0) {
|
||||||
for (int i=0; i<jv_array_length(jv_copy(args)); i++) {
|
for (int i=0; i<jv_array_length(jv_copy(args)); i++) {
|
||||||
@@ -613,16 +643,20 @@ struct bytecode* jq_compile_args(const char* str, jv args) {
|
|||||||
jv_free(args);
|
jv_free(args);
|
||||||
nerrors = builtins_bind(&program);
|
nerrors = builtins_bind(&program);
|
||||||
if (nerrors == 0) {
|
if (nerrors == 0) {
|
||||||
nerrors = block_compile(program, &locations, &bc);
|
nerrors = block_compile(program, &locations, &jq->bc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nerrors) {
|
if (nerrors) {
|
||||||
fprintf(stderr, "%d compile %s\n", nerrors, nerrors > 1 ? "errors" : "error");
|
fprintf(stderr, "%d compile %s\n", nerrors, nerrors > 1 ? "errors" : "error");
|
||||||
}
|
}
|
||||||
locfile_free(&locations);
|
locfile_free(&locations);
|
||||||
return bc;
|
return jq->bc != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bytecode* jq_compile(const char* str) {
|
int jq_compile(jq_state *jq, const char* str) {
|
||||||
return jq_compile_args(str, jv_array());
|
return jq_compile_args(jq, str, jv_array());
|
||||||
|
}
|
||||||
|
|
||||||
|
void jq_dump_disassembly(jq_state *jq, int indent) {
|
||||||
|
dump_disassembly(indent, jq->bc);
|
||||||
}
|
}
|
||||||
@@ -2,19 +2,20 @@
|
|||||||
#define EXECUTE_H
|
#define EXECUTE_H
|
||||||
#include "bytecode.h"
|
#include "bytecode.h"
|
||||||
|
|
||||||
|
typedef struct jq_state jq_state;
|
||||||
|
|
||||||
|
int jq_compile(jq_state *, const char* str);
|
||||||
struct bytecode* jq_compile(const char* str);
|
|
||||||
|
|
||||||
/* args must be an array of the form [{name:"foo", value:"thing"}, {name:"bar",value:3}] */
|
/* args must be an array of the form [{name:"foo", value:"thing"}, {name:"bar",value:3}] */
|
||||||
struct bytecode* jq_compile_args(const char* str, jv args);
|
int jq_compile_args(jq_state *, const char* str, jv args);
|
||||||
|
|
||||||
typedef struct jq_state jq_state;
|
|
||||||
enum {JQ_DEBUG_TRACE = 1};
|
enum {JQ_DEBUG_TRACE = 1};
|
||||||
|
|
||||||
void jq_init(struct bytecode* bc, jv value, jq_state **, int flags);
|
jq_state *jq_init(void);
|
||||||
|
void jq_set_nomem_handler(jq_state *, void (*)(void *), void *);
|
||||||
|
void jq_start(jq_state *, jv value, int flags);
|
||||||
jv jq_next(jq_state *);
|
jv jq_next(jq_state *);
|
||||||
void jq_teardown(jq_state **);
|
void jq_teardown(jq_state **);
|
||||||
|
void jq_dump_disassembly(jq_state *, int);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -27,6 +27,9 @@ static void run_jq_tests(FILE *testdata) {
|
|||||||
int tests = 0, passed = 0, invalid = 0;
|
int tests = 0, passed = 0, invalid = 0;
|
||||||
jq_state *jq = NULL;
|
jq_state *jq = NULL;
|
||||||
|
|
||||||
|
jq = jq_init();
|
||||||
|
assert(jq);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!fgets(buf, sizeof(buf), testdata)) break;
|
if (!fgets(buf, sizeof(buf), testdata)) break;
|
||||||
if (skipline(buf)) continue;
|
if (skipline(buf)) continue;
|
||||||
@@ -34,15 +37,15 @@ static void run_jq_tests(FILE *testdata) {
|
|||||||
printf("Testing %s\n", buf);
|
printf("Testing %s\n", buf);
|
||||||
int pass = 1;
|
int pass = 1;
|
||||||
tests++;
|
tests++;
|
||||||
struct bytecode* bc = jq_compile(buf);
|
int compiled = jq_compile(jq, buf);
|
||||||
if (!bc) {invalid++; continue;}
|
if (!compiled) {invalid++; continue;}
|
||||||
printf("Disassembly:\n");
|
printf("Disassembly:\n");
|
||||||
dump_disassembly(2, bc);
|
jq_dump_disassembly(jq, 2);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
if (!fgets(buf, sizeof(buf), testdata)) { invalid++; break; }
|
if (!fgets(buf, sizeof(buf), testdata)) { invalid++; break; }
|
||||||
jv input = jv_parse(buf);
|
jv input = jv_parse(buf);
|
||||||
if (!jv_is_valid(input)){ invalid++; continue; }
|
if (!jv_is_valid(input)){ invalid++; continue; }
|
||||||
jq_init(bc, input, &jq, JQ_DEBUG_TRACE);
|
jq_start(jq, input, JQ_DEBUG_TRACE);
|
||||||
|
|
||||||
while (fgets(buf, sizeof(buf), testdata)) {
|
while (fgets(buf, sizeof(buf), testdata)) {
|
||||||
if (skipline(buf)) break;
|
if (skipline(buf)) break;
|
||||||
@@ -81,10 +84,9 @@ static void run_jq_tests(FILE *testdata) {
|
|||||||
jv_free(extra);
|
jv_free(extra);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jq_teardown(&jq);
|
|
||||||
bytecode_free(bc);
|
|
||||||
passed+=pass;
|
passed+=pass;
|
||||||
}
|
}
|
||||||
|
jq_teardown(&jq);
|
||||||
printf("%d of %d tests passed (%d malformed)\n", passed,tests,invalid);
|
printf("%d of %d tests passed (%d malformed)\n", passed,tests,invalid);
|
||||||
if (passed != tests) exit(1);
|
if (passed != tests) exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
+82
@@ -2,11 +2,89 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "jv_alloc.h"
|
#include "jv_alloc.h"
|
||||||
|
|
||||||
|
struct nomem_handler {
|
||||||
|
jv_nomem_handler_f handler;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef USE_PTHREAD_KEY
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
static __declspec(thread) struct nomem_handler nomem_handler;
|
||||||
|
#else
|
||||||
|
static __thread struct nomem_handler nomem_handler;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {
|
||||||
|
nomem_handler.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void memory_exhausted() {
|
||||||
|
if (nomem_handler.handler)
|
||||||
|
nomem_handler.handler(nomem_handler.data); // Maybe handler() will longjmp() to safety
|
||||||
|
// Or not
|
||||||
|
fprintf(stderr, "error: cannot allocate memory\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_PTHREAD_KEY_CREATE
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
pthread_key_t nomem_handler_key;
|
||||||
|
pthread_once_t mem_once = PTHREAD_ONCE_INIT;
|
||||||
|
|
||||||
|
static void tsd_init(void) {
|
||||||
|
if (pthread_key_create(&nomem_handler_key, NULL) != 0) {
|
||||||
|
fprintf(stderr, "error: cannot create thread specific key");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {
|
||||||
|
pthread_once(&mem_once, tsd_init); // cannot fail
|
||||||
|
struct nomem_handler *nomem_handler = calloc(1, sizeof (nomem_handler));
|
||||||
|
if (nomem_handler == NULL) {
|
||||||
|
handler(data);
|
||||||
|
fprintf(stderr, "error: cannot allocate memory\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
nomem_handler.handler = handler;
|
||||||
|
nomem_handler.data = data;
|
||||||
|
if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) {
|
||||||
|
handler(data);
|
||||||
|
fprintf(stderr, "error: cannot set thread specific data");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void memory_exhausted() {
|
||||||
|
jv_nomem_handler_f handler;
|
||||||
|
|
||||||
|
pthread_once(&mem_once, tsd_init);
|
||||||
|
handler = pthread_getspecific(nomem_handler_key);
|
||||||
|
if (handler)
|
||||||
|
handler(); // Maybe handler() will longjmp() to safety
|
||||||
|
// Or not
|
||||||
|
fprintf(stderr, "error: cannot allocate memory\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static struct nomem_handler nomem_handler;
|
||||||
|
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {
|
||||||
|
nomem_handler.handler = handler;
|
||||||
|
nomem_handler.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
static void memory_exhausted() {
|
static void memory_exhausted() {
|
||||||
fprintf(stderr, "error: cannot allocate memory\n");
|
fprintf(stderr, "error: cannot allocate memory\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_PTHREAD_KEY_CREATE */
|
||||||
|
#endif /* !USE_PTHREAD_KEY */
|
||||||
|
|
||||||
|
|
||||||
void* jv_mem_alloc(size_t sz) {
|
void* jv_mem_alloc(size_t sz) {
|
||||||
void* p = malloc(sz);
|
void* p = malloc(sz);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
@@ -15,6 +93,10 @@ void* jv_mem_alloc(size_t sz) {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* jv_mem_alloc_unguarded(size_t sz) {
|
||||||
|
return malloc(sz);
|
||||||
|
}
|
||||||
|
|
||||||
void jv_mem_free(void* p) {
|
void jv_mem_free(void* p) {
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ static void jv_mem_invalidate(void* mem, size_t n) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void (*jv_nomem_handler_f)(void *);
|
||||||
|
void jv_nomem_handler(jv_nomem_handler_f, void *);
|
||||||
void* jv_mem_alloc(size_t);
|
void* jv_mem_alloc(size_t);
|
||||||
|
void* jv_mem_alloc_unguarded(size_t);
|
||||||
void jv_mem_free(void*);
|
void jv_mem_free(void*);
|
||||||
__attribute__((warn_unused_result)) void* jv_mem_realloc(void*, size_t);
|
__attribute__((warn_unused_result)) void* jv_mem_realloc(void*, size_t);
|
||||||
|
|
||||||
|
|||||||
@@ -65,11 +65,9 @@ enum {
|
|||||||
DUMP_DISASM = 2048,
|
DUMP_DISASM = 2048,
|
||||||
};
|
};
|
||||||
static int options = 0;
|
static int options = 0;
|
||||||
static struct bytecode* bc;
|
|
||||||
|
|
||||||
static void process(jv value, int flags) {
|
static void process(jq_state *jq, jv value, int flags) {
|
||||||
jq_state *jq = NULL;
|
jq_start(jq, value, flags);
|
||||||
jq_init(bc, value, &jq, flags);
|
|
||||||
jv result;
|
jv result;
|
||||||
while (jv_is_valid(result = jq_next(jq))) {
|
while (jv_is_valid(result = jq_next(jq))) {
|
||||||
if ((options & RAW_OUTPUT) && jv_get_kind(result) == JV_KIND_STRING) {
|
if ((options & RAW_OUTPUT) && jv_get_kind(result) == JV_KIND_STRING) {
|
||||||
@@ -94,7 +92,6 @@ static void process(jv value, int flags) {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
jv_free(result);
|
jv_free(result);
|
||||||
jq_teardown(&jq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* current_input;
|
FILE* current_input;
|
||||||
@@ -126,13 +123,22 @@ static int read_more(char* buf, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
jq_state *jq;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int compiled = 0;
|
||||||
|
|
||||||
if (argc) progname = argv[0];
|
if (argc) progname = argv[0];
|
||||||
|
|
||||||
if (argc > 1 && !strcmp(argv[1], "--run-tests")) {
|
if (argc > 1 && !strcmp(argv[1], "--run-tests")) {
|
||||||
return jq_testsuite(argc - 1, argv + 1);
|
return jq_testsuite(argc - 1, argv + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jq = jq_init();
|
||||||
|
if (jq == NULL) {
|
||||||
|
perror("malloc");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
const char* program = 0;
|
const char* program = 0;
|
||||||
input_filenames = jv_mem_alloc(sizeof(const char*) * argc);
|
input_filenames = jv_mem_alloc(sizeof(const char*) * argc);
|
||||||
ninput_files = 0;
|
ninput_files = 0;
|
||||||
@@ -231,20 +237,20 @@ int main(int argc, char* argv[]) {
|
|||||||
jv_free(data);
|
jv_free(data);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
bc = jq_compile_args(jv_string_value(data), program_arguments);
|
compiled = jq_compile_args(jq, jv_string_value(data), program_arguments);
|
||||||
jv_free(data);
|
jv_free(data);
|
||||||
} else {
|
} else {
|
||||||
bc = jq_compile_args(program, program_arguments);
|
compiled = jq_compile_args(jq, program, program_arguments);
|
||||||
}
|
}
|
||||||
if (!bc) return 1;
|
if (!compiled) return 1;
|
||||||
|
|
||||||
if (options & DUMP_DISASM) {
|
if (options & DUMP_DISASM) {
|
||||||
dump_disassembly(0, bc);
|
jq_dump_disassembly(jq, 0);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options & PROVIDE_NULL) {
|
if (options & PROVIDE_NULL) {
|
||||||
process(jv_null(), jq_flags);
|
process(jq, jv_null(), jq_flags);
|
||||||
} else {
|
} else {
|
||||||
jv slurped;
|
jv slurped;
|
||||||
if (options & SLURP) {
|
if (options & SLURP) {
|
||||||
@@ -265,7 +271,7 @@ int main(int argc, char* argv[]) {
|
|||||||
slurped = jv_string_concat(slurped, jv_string(buf));
|
slurped = jv_string_concat(slurped, jv_string(buf));
|
||||||
} else {
|
} else {
|
||||||
if (buf[len-1] == '\n') buf[len-1] = 0;
|
if (buf[len-1] == '\n') buf[len-1] = 0;
|
||||||
process(jv_string(buf), jq_flags);
|
process(jq, jv_string(buf), jq_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -275,7 +281,7 @@ int main(int argc, char* argv[]) {
|
|||||||
if (options & SLURP) {
|
if (options & SLURP) {
|
||||||
slurped = jv_array_append(slurped, value);
|
slurped = jv_array_append(slurped, value);
|
||||||
} else {
|
} else {
|
||||||
process(value, jq_flags);
|
process(jq, value, jq_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (jv_invalid_has_msg(jv_copy(value))) {
|
if (jv_invalid_has_msg(jv_copy(value))) {
|
||||||
@@ -293,11 +299,11 @@ int main(int argc, char* argv[]) {
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (options & SLURP) {
|
if (options & SLURP) {
|
||||||
process(slurped, jq_flags);
|
process(jq, slurped, jq_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
jv_mem_free(input_filenames);
|
jv_mem_free(input_filenames);
|
||||||
bytecode_free(bc);
|
jq_teardown(&jq);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user