Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

report filename:line on runtime errors #752

Closed
wants to merge 1 commit into from

Conversation

agordon
Copy link
Contributor

@agordon agordon commented Apr 17, 2015

On runtime errors (ending in invalid state at 'main.c:process()'),
print the input filename and current line number which triggered the
error.

  • util.c:
    struct jq_util_input_state: add variables
    jq_util_input_init(): initialize new variables
    jq_util_input_read_more(): update current file/line number on
    fgets() calls.
    jq_util_input_get_position(): helper functions returning a JV_STRING
    containing the current file/line.
    strncpyz(): helper function for safe string copy
  • main.c:
    process(): upon invalid result ('uncaught jq exception'), get the
    current input position and print it to stderr.
  • jq.h: declare 'jq_input_get_position()'.

With this patch, runtime errors printed to stderr will contain the
filename and line of the offending input.

Examples:

With stdin and multiple lines:

$ printf '{"a":43}\n{"a":{"b":66}}\n' | ./jq '.a+1'
44
jq: error (at stdin:2): object and number cannot be added

With multiple files:

$ printf '{"a":43}' > 1.json
$ printf '{"a":"hello"}\n' > 2.json
$ printf '{"a":{"b":66}}\n' > 3.json
$ ./jq '[.a]|@tsv' 1.json 2.json 3.json
"43"
"hello"
jq: error (at 3.json:1): object is not valid in a csv row

With very long lines (spanning multiple fgets calls):

$ (  printf '{"a":43}\n' ;
     printf '{"a":{"b":[' ; seq 10000 | paste -d, -s | tr -d '\n' ;
     printf ']}}\n' ;
     printf '{"a":"hello"}\n' ) | ./jq '[.a] | @tsv'
"43"
jq: error (at stdin:2): object is not valid in a csv row
"hello"

With raw input:

$ seq 1000 | ./jq --raw-input 'select(.=="700") | . + 10'
jq: error (at stdin:700): string and number cannot be added

Caveat:
The reported line will be the last line of the (valid) parsed JSON data.
Example:

$ printf '{\n"a":\n"hello"\n\n\n}\n' | ./jq '.a+4'
jq: error (at stdin:6): string and number cannot be added

minor ugly hack:
The call the get the current filename/line in 'main.c' is hard-coded
to 'jq_util_input_get_position()' which somewhat bypasses the idea
of using an input callback (e.g. 'jq_set_input_cb()').
But since similar calls to 'jq_utl_input_XXXX' are also hard-coded in
'main.c', the input callback mechanism isn't really generatic at the moment.

On runtime errors (ending in invalid state at 'main.c:process()'),
print the input filename and current line number which triggered the
error.

* util.c:
  struct jq_util_input_state: add variables
  jq_util_input_init(): initialize new variables
  jq_util_input_read_more(): update current file/line number on
                             `fgets()` calls.
  jq_util_input_get_position(): helper functions returning a JV_STRING
                                containing the current file/line.
  strncpyz(): helper function for safe string copy

* main.c:
  process(): upon invalid result ('uncaught jq exception'), get the
             current input position and print it to stderr.

* jq.h: declare 'jq_input_get_position()'.

With this patch, runtime errors printed to stderr will contain the
filename and line of the offending input.

Examples:

With stdin and multiple lines:

    $ printf '{"a":43}\n{"a":{"b":66}}\n' | ./jq '.a+1'
    44
    jq: error (at stdin:2): object and number cannot be added

With multiple files:

    $ printf '{"a":43}' > 1.json
    $ printf '{"a":"hello"}\n' > 2.json
    $ printf '{"a":{"b":66}}\n' > 3.json
    $ ./jq '[.a]|@TSV' 1.json 2.json 3.json
    "43"
    "hello"
    jq: error (at 3.json:1): object is not valid in a csv row

With very long lines (spanning multiple `fgets` calls):

    $ (  printf '{"a":43}\n' ;
         printf '{"a":{"b":[' ; seq 10000 | paste -d, -s | tr -d '\n' ;
         printf ']}}\n' ;
         printf '{"a":"hello"}\n' ) | ./jq '[.a] | @TSV'
    "43"
    jq: error (at stdin:2): object is not valid in a csv row
    "hello"

With raw input:

    $ seq 1000 | ./jq --raw-input 'select(.=="700") | . + 10'
    jq: error (at stdin:700): string and number cannot be added

Caveat:
The reported line will be the last line of the (valid) parsed JSON data.
Example:

    $ printf '{\n"a":\n"hello"\n\n\n}\n' | ./jq '.a+4'
    jq: error (at stdin:6): string and number cannot be added

minor ugly hack:
The call the get the current filename/line in 'main.c' is hard-coded
to 'jq_util_input_get_position()' which somewhat bypasses the idea
of using an input callback (e.g. 'jq_set_input_cb()').
But since similar calls to 'jq_utl_input_XXXX' are also hard-coded in
'main.c', the input callback mechanism isn't really generatic at the moment.
agordon added a commit to agordon/jq that referenced this pull request Apr 17, 2015
based on previous patch (jqlang#752), this adds 'filename' and 'line' built-in
functions to jq (discussed in jqlang#743).

Example:

    $ printf '{"a":1}\n{"a":2}\n' > 4.json
    $ printf '{"a":"hello"}\n' > 5.json
    $ ./jq '{ "file":filename, "line":line, "value":.a }' 4.json 5.json
    {
      "file": "4.json",
      "line": 1,
      "value": 1
    }
    {
      "file": "4.json",
      "line": 2,
      "value": 2
    }
    {
      "file": "5.json",
      "line": 1,
      "value": "hello"
    }
@nicowilliams
Copy link
Contributor

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants