1
0
mirror of https://github.com/jqlang/jq.git synced 2025-04-20 04:47:43 +03:00

Make it easier to use jq with shebangs (fix #1044)

Allow a continuation on a comment immediately after a shebang to make
this traditional hack possible:

    #!/bin/sh
    # this next line is ignored by jq \
    exec jq -f "$0" "$@"
    # jq code follows

But continue only on the first line following a shebang, and only if
it's a comment.
This commit is contained in:
Nicolas Williams 2015-12-14 23:43:22 -06:00 committed by David Tolnay
parent 856a4b2f3f
commit 8f6f28c8d3
3 changed files with 22 additions and 1 deletions

View File

@ -129,6 +129,21 @@ enum {
};
static int options = 0;
static const char *skip_shebang(const char *p) {
if (strncmp(p, "#!", sizeof("#!") - 1) != 0)
return p;
const char *n = strchr(p, '\n');
if (n == NULL || n[1] != '#')
return p;
n = strchr(n + 1, '\n');
if (n == NULL || n[1] == '#' || n[1] == '\0' || n[-1] != '\\' || n[-2] == '\\')
return p;
n = strchr(n + 1, '\n');
if (n == NULL)
return p;
return n+1;
}
static int process(jq_state *jq, jv value, int flags, int dumpopts) {
int ret = 14; // No valid results && -e -> exit(4)
jq_start(jq, value, flags);
@ -493,7 +508,7 @@ int main(int argc, char* argv[]) {
goto out;
}
jq_set_attr(jq, jv_string("PROGRAM_ORIGIN"), jq_realpath(jv_string(dirname(program_origin))));
compiled = jq_compile_args(jq, jv_string_value(data), jv_copy(program_arguments));
compiled = jq_compile_args(jq, skip_shebang(jv_string_value(data)), jv_copy(program_arguments));
free(program_origin);
jv_free(data);
} else {

4
tests/jq-f-test.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
# this next line is ignored by jq, which otherwise does not continue comments \
exec jq -nef "$0" "$@"
true

View File

@ -2,6 +2,8 @@
. "${0%/*}/setup"
PATH=$JQBASEDIR:$PATH $JQBASEDIR/tests/jq-f-test.sh > /dev/null
if [ -f "$JQBASEDIR/.libs/libinject_errors.so" ]; then
# Do some simple error injection tests to check that we're handling
# I/O errors correctly.