summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Williams <nico@cryptonector.com>2015-12-14 23:43:22 -0600
committerDavid Tolnay <dtolnay@gmail.com>2015-12-14 22:08:17 -0800
commit8f6f28c8d3fd6fb85439add3e812edeb5a887999 (patch)
treebafea41cdd81cfe35c8f18103a6616a69405e6c3
parent856a4b2f3faf2d6312aad47599e102c8c48d1bdd (diff)
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.
-rw-r--r--src/main.c17
-rwxr-xr-xtests/jq-f-test.sh4
-rwxr-xr-xtests/shtest2
3 files changed, 22 insertions, 1 deletions
diff --git a/src/main.c b/src/main.c
index 8ffa0dbb..eb9d35cf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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 {
diff --git a/tests/jq-f-test.sh b/tests/jq-f-test.sh
new file mode 100755
index 00000000..a9c2fcf3
--- /dev/null
+++ b/tests/jq-f-test.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# this next line is ignored by jq, which otherwise does not continue comments \
+exec jq -nef "$0" "$@"
+true
diff --git a/tests/shtest b/tests/shtest
index 1a956130..89ae6177 100755
--- a/tests/shtest
+++ b/tests/shtest
@@ -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.