Toshaan Bharvani
5 months ago
6 changed files with 33339 additions and 75 deletions
@ -0,0 +1,25 @@ |
|||||||
|
diff -up jq-1.6/src/jv.c.iteration jq-1.6/src/jv.c |
||||||
|
--- jq-1.6/src/jv.c.iteration 2022-10-21 14:17:26.977551386 +0200 |
||||||
|
+++ jq-1.6/src/jv.c 2022-10-21 14:18:43.562430867 +0200 |
||||||
|
@@ -308,6 +308,7 @@ static jv jvp_literal_number_new(const c |
||||||
|
n->refcnt = JV_REFCNT_INIT; |
||||||
|
n->literal_data = NULL; |
||||||
|
decContext *ctx = DEC_CONTEXT(); |
||||||
|
+ decContextClearStatus(ctx, DEC_Conversion_syntax); |
||||||
|
decNumberFromString(&n->num_decimal, literal, ctx); |
||||||
|
n->num_double = NAN; |
||||||
|
|
||||||
|
diff -up jq-1.6/tests/optional.test.iteration jq-1.6/tests/optional.test |
||||||
|
--- jq-1.6/tests/optional.test.iteration 2022-10-21 14:22:04.191734821 +0200 |
||||||
|
+++ jq-1.6/tests/optional.test 2022-10-21 14:23:45.820901911 +0200 |
||||||
|
@@ -17,4 +17,9 @@ strftime("%A, %B %e, %Y") |
||||||
|
1435677542.822351 |
||||||
|
"Tuesday, June 30, 2015" |
||||||
|
|
||||||
|
- |
||||||
|
+# iteration must continue after hello |
||||||
|
+.[]|tonumber? |
||||||
|
+["1", "hello", "3", 4] |
||||||
|
+1 |
||||||
|
+3 |
||||||
|
+4 |
@ -0,0 +1,851 @@ |
|||||||
|
man.test from commit 50a7022ea68fb37faefdcd7a35661df72fbfd655 |
||||||
|
|
||||||
|
diff --git a/tests/man.test b/tests/man.test |
||||||
|
new file mode 100644 |
||||||
|
index 0000000..2a49eff |
||||||
|
--- /dev/null |
||||||
|
+++ b/tests/man.test |
||||||
|
@@ -0,0 +1,843 @@ |
||||||
|
+. |
||||||
|
+"Hello, world!" |
||||||
|
+"Hello, world!" |
||||||
|
+ |
||||||
|
+.foo |
||||||
|
+{"foo": 42, "bar": "less interesting data"} |
||||||
|
+42 |
||||||
|
+ |
||||||
|
+.foo |
||||||
|
+{"notfoo": true, "alsonotfoo": false} |
||||||
|
+null |
||||||
|
+ |
||||||
|
+.["foo"] |
||||||
|
+{"foo": 42} |
||||||
|
+42 |
||||||
|
+ |
||||||
|
+.foo? |
||||||
|
+{"foo": 42, "bar": "less interesting data"} |
||||||
|
+42 |
||||||
|
+ |
||||||
|
+.foo? |
||||||
|
+{"notfoo": true, "alsonotfoo": false} |
||||||
|
+null |
||||||
|
+ |
||||||
|
+.["foo"]? |
||||||
|
+{"foo": 42} |
||||||
|
+42 |
||||||
|
+ |
||||||
|
+[.foo?] |
||||||
|
+[1,2] |
||||||
|
+[] |
||||||
|
+ |
||||||
|
+.[0] |
||||||
|
+[{"name":"JSON", "good":true}, {"name":"XML", "good":false}] |
||||||
|
+{"name":"JSON", "good":true} |
||||||
|
+ |
||||||
|
+.[2] |
||||||
|
+[{"name":"JSON", "good":true}, {"name":"XML", "good":false}] |
||||||
|
+null |
||||||
|
+ |
||||||
|
+.[-2] |
||||||
|
+[1,2,3] |
||||||
|
+2 |
||||||
|
+ |
||||||
|
+.[2:4] |
||||||
|
+["a","b","c","d","e"] |
||||||
|
+["c", "d"] |
||||||
|
+ |
||||||
|
+.[2:4] |
||||||
|
+"abcdefghi" |
||||||
|
+"cd" |
||||||
|
+ |
||||||
|
+.[:3] |
||||||
|
+["a","b","c","d","e"] |
||||||
|
+["a", "b", "c"] |
||||||
|
+ |
||||||
|
+.[-2:] |
||||||
|
+["a","b","c","d","e"] |
||||||
|
+["d", "e"] |
||||||
|
+ |
||||||
|
+.[] |
||||||
|
+[{"name":"JSON", "good":true}, {"name":"XML", "good":false}] |
||||||
|
+{"name":"JSON", "good":true} |
||||||
|
+{"name":"XML", "good":false} |
||||||
|
+ |
||||||
|
+.[] |
||||||
|
+[] |
||||||
|
+ |
||||||
|
+.[] |
||||||
|
+{"a": 1, "b": 1} |
||||||
|
+1 |
||||||
|
+1 |
||||||
|
+ |
||||||
|
+.foo, .bar |
||||||
|
+{"foo": 42, "bar": "something else", "baz": true} |
||||||
|
+42 |
||||||
|
+"something else" |
||||||
|
+ |
||||||
|
+.user, .projects[] |
||||||
|
+{"user":"stedolan", "projects": ["jq", "wikiflow"]} |
||||||
|
+"stedolan" |
||||||
|
+"jq" |
||||||
|
+"wikiflow" |
||||||
|
+ |
||||||
|
+.[4,2] |
||||||
|
+["a","b","c","d","e"] |
||||||
|
+"e" |
||||||
|
+"c" |
||||||
|
+ |
||||||
|
+.[] | .name |
||||||
|
+[{"name":"JSON", "good":true}, {"name":"XML", "good":false}] |
||||||
|
+"JSON" |
||||||
|
+"XML" |
||||||
|
+ |
||||||
|
+(. + 2) * 5 |
||||||
|
+1 |
||||||
|
+15 |
||||||
|
+ |
||||||
|
+[.user, .projects[]] |
||||||
|
+{"user":"stedolan", "projects": ["jq", "wikiflow"]} |
||||||
|
+["stedolan", "jq", "wikiflow"] |
||||||
|
+ |
||||||
|
+[ .[] | . * 2] |
||||||
|
+[1, 2, 3] |
||||||
|
+[2, 4, 6] |
||||||
|
+ |
||||||
|
+{user, title: .titles[]} |
||||||
|
+{"user":"stedolan","titles":["JQ Primer", "More JQ"]} |
||||||
|
+{"user":"stedolan", "title": "JQ Primer"} |
||||||
|
+{"user":"stedolan", "title": "More JQ"} |
||||||
|
+ |
||||||
|
+{(.user): .titles} |
||||||
|
+{"user":"stedolan","titles":["JQ Primer", "More JQ"]} |
||||||
|
+{"stedolan": ["JQ Primer", "More JQ"]} |
||||||
|
+ |
||||||
|
+..|.a? |
||||||
|
+[[{"a":1}]] |
||||||
|
+1 |
||||||
|
+ |
||||||
|
+.a + 1 |
||||||
|
+{"a": 7} |
||||||
|
+8 |
||||||
|
+ |
||||||
|
+.a + .b |
||||||
|
+{"a": [1,2], "b": [3,4]} |
||||||
|
+[1,2,3,4] |
||||||
|
+ |
||||||
|
+.a + null |
||||||
|
+{"a": 1} |
||||||
|
+1 |
||||||
|
+ |
||||||
|
+.a + 1 |
||||||
|
+{} |
||||||
|
+1 |
||||||
|
+ |
||||||
|
+{a: 1} + {b: 2} + {c: 3} + {a: 42} |
||||||
|
+null |
||||||
|
+{"a": 42, "b": 2, "c": 3} |
||||||
|
+ |
||||||
|
+4 - .a |
||||||
|
+{"a":3} |
||||||
|
+1 |
||||||
|
+ |
||||||
|
+. - ["xml", "yaml"] |
||||||
|
+["xml", "yaml", "json"] |
||||||
|
+["json"] |
||||||
|
+ |
||||||
|
+10 / . * 3 |
||||||
|
+5 |
||||||
|
+6 |
||||||
|
+ |
||||||
|
+. / ", " |
||||||
|
+"a, b,c,d, e" |
||||||
|
+["a","b,c,d","e"] |
||||||
|
+ |
||||||
|
+{"k": {"a": 1, "b": 2}} * {"k": {"a": 0,"c": 3}} |
||||||
|
+null |
||||||
|
+{"k": {"a": 0, "b": 2, "c": 3}} |
||||||
|
+ |
||||||
|
+.[] | (1 / .)? |
||||||
|
+[1,0,-1] |
||||||
|
+1 |
||||||
|
+-1 |
||||||
|
+ |
||||||
|
+.[] | length |
||||||
|
+[[1,2], "string", {"a":2}, null] |
||||||
|
+2 |
||||||
|
+6 |
||||||
|
+1 |
||||||
|
+0 |
||||||
|
+ |
||||||
|
+utf8bytelength |
||||||
|
+"\u03bc" |
||||||
|
+2 |
||||||
|
+ |
||||||
|
+keys |
||||||
|
+{"abc": 1, "abcd": 2, "Foo": 3} |
||||||
|
+["Foo", "abc", "abcd"] |
||||||
|
+ |
||||||
|
+keys |
||||||
|
+[42,3,35] |
||||||
|
+[0,1,2] |
||||||
|
+ |
||||||
|
+map(has("foo")) |
||||||
|
+[{"foo": 42}, {}] |
||||||
|
+[true, false] |
||||||
|
+ |
||||||
|
+map(has(2)) |
||||||
|
+[[0,1], ["a","b","c"]] |
||||||
|
+[false, true] |
||||||
|
+ |
||||||
|
+.[] | in({"foo": 42}) |
||||||
|
+["foo", "bar"] |
||||||
|
+true |
||||||
|
+false |
||||||
|
+ |
||||||
|
+map(in([0,1])) |
||||||
|
+[2, 0] |
||||||
|
+[false, true] |
||||||
|
+ |
||||||
|
+map(.+1) |
||||||
|
+[1,2,3] |
||||||
|
+[2,3,4] |
||||||
|
+ |
||||||
|
+map_values(.+1) |
||||||
|
+{"a": 1, "b": 2, "c": 3} |
||||||
|
+{"a": 2, "b": 3, "c": 4} |
||||||
|
+ |
||||||
|
+path(.a[0].b) |
||||||
|
+null |
||||||
|
+["a",0,"b"] |
||||||
|
+ |
||||||
|
+[path(..)] |
||||||
|
+{"a":[{"b":1}]} |
||||||
|
+[[],["a"],["a",0],["a",0,"b"]] |
||||||
|
+ |
||||||
|
+del(.foo) |
||||||
|
+{"foo": 42, "bar": 9001, "baz": 42} |
||||||
|
+{"bar": 9001, "baz": 42} |
||||||
|
+ |
||||||
|
+del(.[1, 2]) |
||||||
|
+["foo", "bar", "baz"] |
||||||
|
+["foo"] |
||||||
|
+ |
||||||
|
+getpath(["a","b"]) |
||||||
|
+null |
||||||
|
+null |
||||||
|
+ |
||||||
|
+[getpath(["a","b"], ["a","c"])] |
||||||
|
+{"a":{"b":0, "c":1}} |
||||||
|
+[0, 1] |
||||||
|
+ |
||||||
|
+setpath(["a","b"]; 1) |
||||||
|
+null |
||||||
|
+{"a": {"b": 1}} |
||||||
|
+ |
||||||
|
+setpath(["a","b"]; 1) |
||||||
|
+{"a":{"b":0}} |
||||||
|
+{"a": {"b": 1}} |
||||||
|
+ |
||||||
|
+setpath([0,"a"]; 1) |
||||||
|
+null |
||||||
|
+[{"a":1}] |
||||||
|
+ |
||||||
|
+delpaths([["a","b"]]) |
||||||
|
+{"a":{"b":1},"x":{"y":2}} |
||||||
|
+{"a":{},"x":{"y":2}} |
||||||
|
+ |
||||||
|
+to_entries |
||||||
|
+{"a": 1, "b": 2} |
||||||
|
+[{"key":"a", "value":1}, {"key":"b", "value":2}] |
||||||
|
+ |
||||||
|
+from_entries |
||||||
|
+[{"key":"a", "value":1}, {"key":"b", "value":2}] |
||||||
|
+{"a": 1, "b": 2} |
||||||
|
+ |
||||||
|
+with_entries(.key |= "KEY_" + .) |
||||||
|
+{"a": 1, "b": 2} |
||||||
|
+{"KEY_a": 1, "KEY_b": 2} |
||||||
|
+ |
||||||
|
+map(select(. >= 2)) |
||||||
|
+[1,5,3,0,7] |
||||||
|
+[5,3,7] |
||||||
|
+ |
||||||
|
+.[] | select(.id == "second") |
||||||
|
+[{"id": "first", "val": 1}, {"id": "second", "val": 2}] |
||||||
|
+{"id": "second", "val": 2} |
||||||
|
+ |
||||||
|
+.[]|numbers |
||||||
|
+[[],{},1,"foo",null,true,false] |
||||||
|
+1 |
||||||
|
+ |
||||||
|
+1, empty, 2 |
||||||
|
+null |
||||||
|
+1 |
||||||
|
+2 |
||||||
|
+ |
||||||
|
+[1,2,empty,3] |
||||||
|
+null |
||||||
|
+[1,2,3] |
||||||
|
+ |
||||||
|
+try error("\($__loc__)") catch . |
||||||
|
+null |
||||||
|
+"{\"file\":\"<top-level>\",\"line\":1}" |
||||||
|
+ |
||||||
|
+[paths] |
||||||
|
+[1,[[],{"a":2}]] |
||||||
|
+[[0],[1],[1,0],[1,1],[1,1,"a"]] |
||||||
|
+ |
||||||
|
+[paths(scalars)] |
||||||
|
+[1,[[],{"a":2}]] |
||||||
|
+[[0],[1,1,"a"]] |
||||||
|
+ |
||||||
|
+add |
||||||
|
+["a","b","c"] |
||||||
|
+"abc" |
||||||
|
+ |
||||||
|
+add |
||||||
|
+[1, 2, 3] |
||||||
|
+6 |
||||||
|
+ |
||||||
|
+add |
||||||
|
+[] |
||||||
|
+null |
||||||
|
+ |
||||||
|
+any |
||||||
|
+[true, false] |
||||||
|
+true |
||||||
|
+ |
||||||
|
+any |
||||||
|
+[false, false] |
||||||
|
+false |
||||||
|
+ |
||||||
|
+any |
||||||
|
+[] |
||||||
|
+false |
||||||
|
+ |
||||||
|
+all |
||||||
|
+[true, false] |
||||||
|
+false |
||||||
|
+ |
||||||
|
+all |
||||||
|
+[true, true] |
||||||
|
+true |
||||||
|
+ |
||||||
|
+all |
||||||
|
+[] |
||||||
|
+true |
||||||
|
+ |
||||||
|
+flatten |
||||||
|
+[1, [2], [[3]]] |
||||||
|
+[1, 2, 3] |
||||||
|
+ |
||||||
|
+flatten(1) |
||||||
|
+[1, [2], [[3]]] |
||||||
|
+[1, 2, [3]] |
||||||
|
+ |
||||||
|
+flatten |
||||||
|
+[[]] |
||||||
|
+[] |
||||||
|
+ |
||||||
|
+flatten |
||||||
|
+[{"foo": "bar"}, [{"foo": "baz"}]] |
||||||
|
+[{"foo": "bar"}, {"foo": "baz"}] |
||||||
|
+ |
||||||
|
+range(2;4) |
||||||
|
+null |
||||||
|
+2 |
||||||
|
+3 |
||||||
|
+ |
||||||
|
+[range(2;4)] |
||||||
|
+null |
||||||
|
+[2,3] |
||||||
|
+ |
||||||
|
+[range(4)] |
||||||
|
+null |
||||||
|
+[0,1,2,3] |
||||||
|
+ |
||||||
|
+[range(0;10;3)] |
||||||
|
+null |
||||||
|
+[0,3,6,9] |
||||||
|
+ |
||||||
|
+[range(0;10;-1)] |
||||||
|
+null |
||||||
|
+[] |
||||||
|
+ |
||||||
|
+[range(0;-5;-1)] |
||||||
|
+null |
||||||
|
+[0,-1,-2,-3,-4] |
||||||
|
+ |
||||||
|
+floor |
||||||
|
+3.14159 |
||||||
|
+3 |
||||||
|
+ |
||||||
|
+sqrt |
||||||
|
+9 |
||||||
|
+3 |
||||||
|
+ |
||||||
|
+.[] | tonumber |
||||||
|
+[1, "1"] |
||||||
|
+1 |
||||||
|
+1 |
||||||
|
+ |
||||||
|
+.[] | tostring |
||||||
|
+[1, "1", [1]] |
||||||
|
+"1" |
||||||
|
+"1" |
||||||
|
+"[1]" |
||||||
|
+ |
||||||
|
+map(type) |
||||||
|
+[0, false, [], {}, null, "hello"] |
||||||
|
+["number", "boolean", "array", "object", "null", "string"] |
||||||
|
+ |
||||||
|
+.[] | (infinite * .) < 0 |
||||||
|
+[-1, 1] |
||||||
|
+true |
||||||
|
+false |
||||||
|
+ |
||||||
|
+infinite, nan | type |
||||||
|
+null |
||||||
|
+"number" |
||||||
|
+"number" |
||||||
|
+ |
||||||
|
+sort |
||||||
|
+[8,3,null,6] |
||||||
|
+[null,3,6,8] |
||||||
|
+ |
||||||
|
+sort_by(.foo) |
||||||
|
+[{"foo":4, "bar":10}, {"foo":3, "bar":100}, {"foo":2, "bar":1}] |
||||||
|
+[{"foo":2, "bar":1}, {"foo":3, "bar":100}, {"foo":4, "bar":10}] |
||||||
|
+ |
||||||
|
+group_by(.foo) |
||||||
|
+[{"foo":1, "bar":10}, {"foo":3, "bar":100}, {"foo":1, "bar":1}] |
||||||
|
+[[{"foo":1, "bar":10}, {"foo":1, "bar":1}], [{"foo":3, "bar":100}]] |
||||||
|
+ |
||||||
|
+min |
||||||
|
+[5,4,2,7] |
||||||
|
+2 |
||||||
|
+ |
||||||
|
+max_by(.foo) |
||||||
|
+[{"foo":1, "bar":14}, {"foo":2, "bar":3}] |
||||||
|
+{"foo":2, "bar":3} |
||||||
|
+ |
||||||
|
+unique |
||||||
|
+[1,2,5,3,5,3,1,3] |
||||||
|
+[1,2,3,5] |
||||||
|
+ |
||||||
|
+unique_by(.foo) |
||||||
|
+[{"foo": 1, "bar": 2}, {"foo": 1, "bar": 3}, {"foo": 4, "bar": 5}] |
||||||
|
+[{"foo": 1, "bar": 2}, {"foo": 4, "bar": 5}] |
||||||
|
+ |
||||||
|
+unique_by(length) |
||||||
|
+["chunky", "bacon", "kitten", "cicada", "asparagus"] |
||||||
|
+["bacon", "chunky", "asparagus"] |
||||||
|
+ |
||||||
|
+reverse |
||||||
|
+[1,2,3,4] |
||||||
|
+[4,3,2,1] |
||||||
|
+ |
||||||
|
+contains("bar") |
||||||
|
+"foobar" |
||||||
|
+true |
||||||
|
+ |
||||||
|
+contains(["baz", "bar"]) |
||||||
|
+["foobar", "foobaz", "blarp"] |
||||||
|
+true |
||||||
|
+ |
||||||
|
+contains(["bazzzzz", "bar"]) |
||||||
|
+["foobar", "foobaz", "blarp"] |
||||||
|
+false |
||||||
|
+ |
||||||
|
+contains({foo: 12, bar: [{barp: 12}]}) |
||||||
|
+{"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]} |
||||||
|
+true |
||||||
|
+ |
||||||
|
+contains({foo: 12, bar: [{barp: 15}]}) |
||||||
|
+{"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]} |
||||||
|
+false |
||||||
|
+ |
||||||
|
+indices(", ") |
||||||
|
+"a,b, cd, efg, hijk" |
||||||
|
+[3,7,12] |
||||||
|
+ |
||||||
|
+indices(1) |
||||||
|
+[0,1,2,1,3,1,4] |
||||||
|
+[1,3,5] |
||||||
|
+ |
||||||
|
+indices([1,2]) |
||||||
|
+[0,1,2,3,1,4,2,5,1,2,6,7] |
||||||
|
+[1,8] |
||||||
|
+ |
||||||
|
+index(", ") |
||||||
|
+"a,b, cd, efg, hijk" |
||||||
|
+3 |
||||||
|
+ |
||||||
|
+rindex(", ") |
||||||
|
+"a,b, cd, efg, hijk" |
||||||
|
+12 |
||||||
|
+ |
||||||
|
+inside("foobar") |
||||||
|
+"bar" |
||||||
|
+true |
||||||
|
+ |
||||||
|
+inside(["foobar", "foobaz", "blarp"]) |
||||||
|
+["baz", "bar"] |
||||||
|
+true |
||||||
|
+ |
||||||
|
+inside(["foobar", "foobaz", "blarp"]) |
||||||
|
+["bazzzzz", "bar"] |
||||||
|
+false |
||||||
|
+ |
||||||
|
+inside({"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]}) |
||||||
|
+{"foo": 12, "bar": [{"barp": 12}]} |
||||||
|
+true |
||||||
|
+ |
||||||
|
+inside({"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]}) |
||||||
|
+{"foo": 12, "bar": [{"barp": 15}]} |
||||||
|
+false |
||||||
|
+ |
||||||
|
+[.[]|startswith("foo")] |
||||||
|
+["fo", "foo", "barfoo", "foobar", "barfoob"] |
||||||
|
+[false, true, false, true, false] |
||||||
|
+ |
||||||
|
+[.[]|endswith("foo")] |
||||||
|
+["foobar", "barfoo"] |
||||||
|
+[false, true] |
||||||
|
+ |
||||||
|
+combinations |
||||||
|
+[[1,2], [3, 4]] |
||||||
|
+[1, 3] |
||||||
|
+[1, 4] |
||||||
|
+[2, 3] |
||||||
|
+[2, 4] |
||||||
|
+ |
||||||
|
+combinations(2) |
||||||
|
+[0, 1] |
||||||
|
+[0, 0] |
||||||
|
+[0, 1] |
||||||
|
+[1, 0] |
||||||
|
+[1, 1] |
||||||
|
+ |
||||||
|
+[.[]|ltrimstr("foo")] |
||||||
|
+["fo", "foo", "barfoo", "foobar", "afoo"] |
||||||
|
+["fo","","barfoo","bar","afoo"] |
||||||
|
+ |
||||||
|
+[.[]|rtrimstr("foo")] |
||||||
|
+["fo", "foo", "barfoo", "foobar", "foob"] |
||||||
|
+["fo","","bar","foobar","foob"] |
||||||
|
+ |
||||||
|
+explode |
||||||
|
+"foobar" |
||||||
|
+[102,111,111,98,97,114] |
||||||
|
+ |
||||||
|
+implode |
||||||
|
+[65, 66, 67] |
||||||
|
+"ABC" |
||||||
|
+ |
||||||
|
+split(", ") |
||||||
|
+"a, b,c,d, e, " |
||||||
|
+["a","b,c,d","e",""] |
||||||
|
+ |
||||||
|
+join(", ") |
||||||
|
+["a","b,c,d","e"] |
||||||
|
+"a, b,c,d, e" |
||||||
|
+ |
||||||
|
+join(" ") |
||||||
|
+["a",1,2.3,true,null,false] |
||||||
|
+"a 1 2.3 true false" |
||||||
|
+ |
||||||
|
+[while(.<100; .*2)] |
||||||
|
+1 |
||||||
|
+[1,2,4,8,16,32,64] |
||||||
|
+ |
||||||
|
+[.,1]|until(.[0] < 1; [.[0] - 1, .[1] * .[0]])|.[1] |
||||||
|
+4 |
||||||
|
+24 |
||||||
|
+ |
||||||
|
+recurse(.foo[]) |
||||||
|
+{"foo":[{"foo": []}, {"foo":[{"foo":[]}]}]} |
||||||
|
+{"foo":[{"foo":[]},{"foo":[{"foo":[]}]}]} |
||||||
|
+{"foo":[]} |
||||||
|
+{"foo":[{"foo":[]}]} |
||||||
|
+{"foo":[]} |
||||||
|
+ |
||||||
|
+recurse |
||||||
|
+{"a":0,"b":[1]} |
||||||
|
+{"a":0,"b":[1]} |
||||||
|
+0 |
||||||
|
+[1] |
||||||
|
+1 |
||||||
|
+ |
||||||
|
+recurse(. * .; . < 20) |
||||||
|
+2 |
||||||
|
+2 |
||||||
|
+4 |
||||||
|
+16 |
||||||
|
+ |
||||||
|
+walk(if type == "array" then sort else . end) |
||||||
|
+[[4, 1, 7], [8, 5, 2], [3, 6, 9]] |
||||||
|
+[[1,4,7],[2,5,8],[3,6,9]] |
||||||
|
+ |
||||||
|
+walk( if type == "object" then with_entries( .key |= sub( "^_+"; "") ) else . end ) |
||||||
|
+[ { "_a": { "__b": 2 } } ] |
||||||
|
+[{"a":{"b":2}}] |
||||||
|
+ |
||||||
|
+$ENV.PAGER |
||||||
|
+null |
||||||
|
+"less" |
||||||
|
+ |
||||||
|
+env.PAGER |
||||||
|
+null |
||||||
|
+"less" |
||||||
|
+ |
||||||
|
+transpose |
||||||
|
+[[1], [2,3]] |
||||||
|
+[[1,2],[null,3]] |
||||||
|
+ |
||||||
|
+bsearch(0) |
||||||
|
+[0,1] |
||||||
|
+0 |
||||||
|
+ |
||||||
|
+bsearch(0) |
||||||
|
+[1,2,3] |
||||||
|
+-1 |
||||||
|
+ |
||||||
|
+bsearch(4) as $ix | if $ix < 0 then .[-(1+$ix)] = 4 else . end |
||||||
|
+[1,2,3] |
||||||
|
+[1,2,3,4] |
||||||
|
+ |
||||||
|
+"The input was \(.), which is one less than \(.+1)" |
||||||
|
+42 |
||||||
|
+"The input was 42, which is one less than 43" |
||||||
|
+ |
||||||
|
+[.[]|tostring] |
||||||
|
+[1, "foo", ["foo"]] |
||||||
|
+["1","foo","[\"foo\"]"] |
||||||
|
+ |
||||||
|
+[.[]|tojson] |
||||||
|
+[1, "foo", ["foo"]] |
||||||
|
+["1","\"foo\"","[\"foo\"]"] |
||||||
|
+ |
||||||
|
+[.[]|tojson|fromjson] |
||||||
|
+[1, "foo", ["foo"]] |
||||||
|
+[1,"foo",["foo"]] |
||||||
|
+ |
||||||
|
+@html |
||||||
|
+"This works if x < y" |
||||||
|
+"This works if x < y" |
||||||
|
+ |
||||||
|
+@sh "echo \(.)" |
||||||
|
+"O'Hara's Ale" |
||||||
|
+"echo 'O'\\''Hara'\\''s Ale'" |
||||||
|
+ |
||||||
|
+@base64 |
||||||
|
+"This is a message" |
||||||
|
+"VGhpcyBpcyBhIG1lc3NhZ2U=" |
||||||
|
+ |
||||||
|
+@base64d |
||||||
|
+"VGhpcyBpcyBhIG1lc3NhZ2U=" |
||||||
|
+"This is a message" |
||||||
|
+ |
||||||
|
+fromdate |
||||||
|
+"2015-03-05T23:51:47Z" |
||||||
|
+1425599507 |
||||||
|
+ |
||||||
|
+strptime("%Y-%m-%dT%H:%M:%SZ") |
||||||
|
+"2015-03-05T23:51:47Z" |
||||||
|
+[2015,2,5,23,51,47,4,63] |
||||||
|
+ |
||||||
|
+strptime("%Y-%m-%dT%H:%M:%SZ")|mktime |
||||||
|
+"2015-03-05T23:51:47Z" |
||||||
|
+1425599507 |
||||||
|
+ |
||||||
|
+.[] == 1 |
||||||
|
+[1, 1.0, "1", "banana"] |
||||||
|
+true |
||||||
|
+true |
||||||
|
+false |
||||||
|
+false |
||||||
|
+ |
||||||
|
+if . == 0 then "zero" elif . == 1 then "one" else "many" end |
||||||
|
+2 |
||||||
|
+"many" |
||||||
|
+ |
||||||
|
+. < 5 |
||||||
|
+2 |
||||||
|
+true |
||||||
|
+ |
||||||
|
+42 and "a string" |
||||||
|
+null |
||||||
|
+true |
||||||
|
+ |
||||||
|
+(true, false) or false |
||||||
|
+null |
||||||
|
+true |
||||||
|
+false |
||||||
|
+ |
||||||
|
+(true, true) and (true, false) |
||||||
|
+null |
||||||
|
+true |
||||||
|
+false |
||||||
|
+true |
||||||
|
+false |
||||||
|
+ |
||||||
|
+[true, false | not] |
||||||
|
+null |
||||||
|
+[false, true] |
||||||
|
+ |
||||||
|
+.foo // 42 |
||||||
|
+{"foo": 19} |
||||||
|
+19 |
||||||
|
+ |
||||||
|
+.foo // 42 |
||||||
|
+{} |
||||||
|
+42 |
||||||
|
+ |
||||||
|
+try .a catch ". is not an object" |
||||||
|
+true |
||||||
|
+". is not an object" |
||||||
|
+ |
||||||
|
+[.[]|try .a] |
||||||
|
+[{}, true, {"a":1}] |
||||||
|
+[null, 1] |
||||||
|
+ |
||||||
|
+try error("some exception") catch . |
||||||
|
+true |
||||||
|
+"some exception" |
||||||
|
+ |
||||||
|
+[.[]|(.a)?] |
||||||
|
+[{}, true, {"a":1}] |
||||||
|
+[null, 1] |
||||||
|
+ |
||||||
|
+test("foo") |
||||||
|
+"foo" |
||||||
|
+true |
||||||
|
+ |
||||||
|
+.[] | test("a b c # spaces are ignored"; "ix") |
||||||
|
+["xabcd", "ABC"] |
||||||
|
+true |
||||||
|
+true |
||||||
|
+ |
||||||
|
+match("(abc)+"; "g") |
||||||
|
+"abc abc" |
||||||
|
+{"offset": 0, "length": 3, "string": "abc", "captures": [{"offset": 0, "length": 3, "string": "abc", "name": null}]} |
||||||
|
+{"offset": 4, "length": 3, "string": "abc", "captures": [{"offset": 4, "length": 3, "string": "abc", "name": null}]} |
||||||
|
+ |
||||||
|
+match("foo") |
||||||
|
+"foo bar foo" |
||||||
|
+{"offset": 0, "length": 3, "string": "foo", "captures": []} |
||||||
|
+ |
||||||
|
+match(["foo", "ig"]) |
||||||
|
+"foo bar FOO" |
||||||
|
+{"offset": 0, "length": 3, "string": "foo", "captures": []} |
||||||
|
+{"offset": 8, "length": 3, "string": "FOO", "captures": []} |
||||||
|
+ |
||||||
|
+match("foo (?<bar123>bar)? foo"; "ig") |
||||||
|
+"foo bar foo foo foo" |
||||||
|
+{"offset": 0, "length": 11, "string": "foo bar foo", "captures": [{"offset": 4, "length": 3, "string": "bar", "name": "bar123"}]} |
||||||
|
+{"offset": 12, "length": 8, "string": "foo foo", "captures": [{"offset": -1, "length": 0, "string": null, "name": "bar123"}]} |
||||||
|
+ |
||||||
|
+[ match("."; "g")] | length |
||||||
|
+"abc" |
||||||
|
+3 |
||||||
|
+ |
||||||
|
+capture("(?<a>[a-z]+)-(?<n>[0-9]+)") |
||||||
|
+"xyzzy-14" |
||||||
|
+{ "a": "xyzzy", "n": "14" } |
||||||
|
+ |
||||||
|
+.bar as $x | .foo | . + $x |
||||||
|
+{"foo":10, "bar":200} |
||||||
|
+210 |
||||||
|
+ |
||||||
|
+. as $i|[(.*2|. as $i| $i), $i] |
||||||
|
+5 |
||||||
|
+[10,5] |
||||||
|
+ |
||||||
|
+. as [$a, $b, {c: $c}] | $a + $b + $c |
||||||
|
+[2, 3, {"c": 4, "d": 5}] |
||||||
|
+9 |
||||||
|
+ |
||||||
|
+.[] as [$a, $b] | {a: $a, b: $b} |
||||||
|
+[[0], [0, 1], [2, 1, 0]] |
||||||
|
+{"a":0,"b":null} |
||||||
|
+{"a":0,"b":1} |
||||||
|
+{"a":2,"b":1} |
||||||
|
+ |
||||||
|
+.[] as {$a, $b, c: {$d, $e}} ?// {$a, $b, c: [{$d, $e}]} | {$a, $b, $d, $e} |
||||||
|
+[{"a": 1, "b": 2, "c": {"d": 3, "e": 4}}, {"a": 1, "b": 2, "c": [{"d": 3, "e": 4}]}] |
||||||
|
+{"a":1,"b":2,"d":3,"e":4} |
||||||
|
+{"a":1,"b":2,"d":3,"e":4} |
||||||
|
+ |
||||||
|
+.[] as {$a, $b, c: {$d}} ?// {$a, $b, c: [{$e}]} | {$a, $b, $d, $e} |
||||||
|
+[{"a": 1, "b": 2, "c": {"d": 3, "e": 4}}, {"a": 1, "b": 2, "c": [{"d": 3, "e": 4}]}] |
||||||
|
+{"a":1,"b":2,"d":3,"e":null} |
||||||
|
+{"a":1,"b":2,"d":null,"e":4} |
||||||
|
+ |
||||||
|
+.[] as [$a] ?// [$b] | if $a != null then error("err: \($a)") else {$a,$b} end |
||||||
|
+[[3]] |
||||||
|
+{"a":null,"b":3} |
||||||
|
+ |
||||||
|
+def addvalue(f): . + [f]; map(addvalue(.[0])) |
||||||
|
+[[1,2],[10,20]] |
||||||
|
+[[1,2,1], [10,20,10]] |
||||||
|
+ |
||||||
|
+def addvalue(f): f as $x | map(. + $x); addvalue(.[0]) |
||||||
|
+[[1,2],[10,20]] |
||||||
|
+[[1,2,1,2], [10,20,1,2]] |
||||||
|
+ |
||||||
|
+reduce .[] as $item (0; . + $item) |
||||||
|
+[10,2,5,3] |
||||||
|
+20 |
||||||
|
+ |
||||||
|
+isempty(empty) |
||||||
|
+null |
||||||
|
+true |
||||||
|
+ |
||||||
|
+[limit(3;.[])] |
||||||
|
+[0,1,2,3,4,5,6,7,8,9] |
||||||
|
+[0,1,2] |
||||||
|
+ |
||||||
|
+[first(range(.)), last(range(.)), nth(./2; range(.))] |
||||||
|
+10 |
||||||
|
+[0,9,5] |
||||||
|
+ |
||||||
|
+[range(.)]|[first, last, nth(5)] |
||||||
|
+10 |
||||||
|
+[0,9,5] |
||||||
|
+ |
||||||
|
+[foreach .[] as $item ([[],[]]; if $item == null then [[],.[0]] else [(.[0] + [$item]),[]] end; if $item == null then .[1] else empty end)] |
||||||
|
+[1,2,3,4,null,"a","b",null] |
||||||
|
+[[1,2,3,4],["a","b"]] |
||||||
|
+ |
||||||
|
+def range(init; upto; by): def _range: if (by > 0 and . < upto) or (by < 0 and . > upto) then ., ((.+by)|_range) else . end; if by == 0 then init else init|_range end | select((by > 0 and . < upto) or (by < 0 and . > upto)); range(0; 10; 3) |
||||||
|
+null |
||||||
|
+0 |
||||||
|
+3 |
||||||
|
+6 |
||||||
|
+9 |
||||||
|
+ |
||||||
|
+def while(cond; update): def _while: if cond then ., (update | _while) else empty end; _while; [while(.<100; .*2)] |
||||||
|
+1 |
||||||
|
+[1,2,4,8,16,32,64] |
||||||
|
+ |
||||||
|
+[1|truncate_stream([[0],1],[[1,0],2],[[1,0]],[[1]])] |
||||||
|
+1 |
||||||
|
+[[[0],2],[[0]]] |
||||||
|
+ |
||||||
|
+fromstream(1|truncate_stream([[0],1],[[1,0],2],[[1,0]],[[1]])) |
||||||
|
+null |
||||||
|
+[2] |
||||||
|
+ |
||||||
|
+. as $dot|fromstream($dot|tostream)|.==$dot |
||||||
|
+[0,[1,{"a":1},{"b":2}]] |
||||||
|
+true |
||||||
|
+ |
||||||
|
+(..|select(type=="boolean")) |= if . then 1 else 0 end |
||||||
|
+[true,false,[5,true,[true,[false]],false]] |
||||||
|
+[1,0,[5,1,[1,[0]],0]] |
||||||
|
+ |
||||||
|
+.foo += 1 |
||||||
|
+{"foo": 42} |
||||||
|
+{"foo": 43} |
||||||
|
+ |
@ -0,0 +1,244 @@ |
|||||||
|
commit fead9669cb67badb22789d3ed1888779ed85c679 |
||||||
|
Author: Tomas Halman <thalman@redhat.com> |
||||||
|
Date: Thu Mar 9 11:34:44 2023 +0100 |
||||||
|
|
||||||
|
Test that jq works in threads |
||||||
|
|
||||||
|
This patch implements test that searches a key in simple |
||||||
|
json in pthread. |
||||||
|
|
||||||
|
diff -up jq-1.6/src/jq_test.c.orig jq-1.6/src/jq_test.c |
||||||
|
--- jq-1.6/src/jq_test.c.orig 2023-03-09 14:02:16.980062057 +0100 |
||||||
|
+++ jq-1.6/src/jq_test.c 2023-03-09 14:03:38.347017032 +0100 |
||||||
|
@@ -2,12 +2,17 @@ |
||||||
|
#include <stdio.h> |
||||||
|
#include <string.h> |
||||||
|
#include <stdlib.h> |
||||||
|
+#ifdef HAVE_PTHREAD |
||||||
|
+#include <pthread.h> |
||||||
|
+#endif |
||||||
|
#include "jv.h" |
||||||
|
#include "jq.h" |
||||||
|
|
||||||
|
static void jv_test(); |
||||||
|
static void run_jq_tests(jv, int, FILE *, int, int); |
||||||
|
- |
||||||
|
+#ifdef HAVE_PTHREAD |
||||||
|
+static void run_jq_pthread_tests(); |
||||||
|
+#endif |
||||||
|
|
||||||
|
int jq_testsuite(jv libdirs, int verbose, int argc, char* argv[]) { |
||||||
|
FILE *testdata = stdin; |
||||||
|
@@ -32,6 +37,9 @@ int jq_testsuite(jv libdirs, int verbose |
||||||
|
} |
||||||
|
} |
||||||
|
run_jq_tests(libdirs, verbose, testdata, skip, take); |
||||||
|
+#ifdef HAVE_PTHREAD |
||||||
|
+ run_jq_pthread_tests(); |
||||||
|
+#endif |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
@@ -105,7 +113,7 @@ static void run_jq_tests(jv lib_dirs, in |
||||||
|
if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n')) |
||||||
|
break; |
||||||
|
} |
||||||
|
- |
||||||
|
+ |
||||||
|
must_fail = 0; |
||||||
|
check_msg = 0; |
||||||
|
|
||||||
|
@@ -229,7 +237,7 @@ static void run_jq_tests(jv lib_dirs, in |
||||||
|
total_skipped = tests_to_skip - skip; |
||||||
|
} |
||||||
|
|
||||||
|
- printf("%d of %d tests passed (%d malformed, %d skipped)\n", |
||||||
|
+ printf("%d of %d tests passed (%d malformed, %d skipped)\n", |
||||||
|
passed, tests, invalid, total_skipped); |
||||||
|
|
||||||
|
if (skip > 0) { |
||||||
|
@@ -241,6 +249,88 @@ static void run_jq_tests(jv lib_dirs, in |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
+/// pthread regression test |
||||||
|
+#ifdef HAVE_PTHREAD |
||||||
|
+#define NUMBER_OF_THREADS 3 |
||||||
|
+struct test_pthread_data { |
||||||
|
+ int result; |
||||||
|
+}; |
||||||
|
+ |
||||||
|
+static int test_pthread_jq_parse(jq_state *jq, struct jv_parser *parser) |
||||||
|
+{ |
||||||
|
+ int rv = 0; |
||||||
|
+ jv value; |
||||||
|
+ |
||||||
|
+ value = jv_parser_next(parser); |
||||||
|
+ while (jv_is_valid(value)) { |
||||||
|
+ jq_start(jq, value, 0); |
||||||
|
+ jv result = jq_next(jq); |
||||||
|
+ |
||||||
|
+ while (jv_is_valid(result)) { |
||||||
|
+ jv_free(result); |
||||||
|
+ result = jq_next(jq); |
||||||
|
+ } |
||||||
|
+ jv_free(result); |
||||||
|
+ value = jv_parser_next(parser); |
||||||
|
+ } |
||||||
|
+ jv_free(value); |
||||||
|
+ return rv; |
||||||
|
+} |
||||||
|
+ |
||||||
|
+static void *test_pthread_run(void *ptr) { |
||||||
|
+ int rv; |
||||||
|
+ jq_state *jq; |
||||||
|
+ const char *prg = ".data"; |
||||||
|
+ const char *buf = "{ \"data\": 1 }"; |
||||||
|
+ struct test_pthread_data *data = ptr; |
||||||
|
+ |
||||||
|
+ jq = jq_init(); |
||||||
|
+ if (jq_compile(jq, prg) == 0) { |
||||||
|
+ jq_teardown(&jq); |
||||||
|
+ return NULL; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ struct jv_parser *parser = jv_parser_new(0); |
||||||
|
+ jv_parser_set_buf(parser, buf, strlen(buf), 0); |
||||||
|
+ rv = test_pthread_jq_parse(jq, parser); |
||||||
|
+ |
||||||
|
+ data->result = rv; |
||||||
|
+ |
||||||
|
+ jv_parser_free(parser); |
||||||
|
+ jq_teardown(&jq); |
||||||
|
+ return NULL; |
||||||
|
+} |
||||||
|
+ |
||||||
|
+static void run_jq_pthread_tests() { |
||||||
|
+ pthread_t threads[NUMBER_OF_THREADS]; |
||||||
|
+ struct test_pthread_data data[NUMBER_OF_THREADS]; |
||||||
|
+ int createerror; |
||||||
|
+ int a; |
||||||
|
+ |
||||||
|
+ memset(&threads, 0, sizeof(threads)); |
||||||
|
+ memset(&data, 0, sizeof(data)); |
||||||
|
+ |
||||||
|
+ // Create all threads |
||||||
|
+ for (a = 0; a < NUMBER_OF_THREADS; ++a) { |
||||||
|
+ createerror = pthread_create(&threads[a], NULL, test_pthread_run, &data[a]); |
||||||
|
+ assert(createerror == 0); |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ // wait for all threads |
||||||
|
+ for(a = 0; a < NUMBER_OF_THREADS; ++a) { |
||||||
|
+ if (threads[a] != 0) { |
||||||
|
+ pthread_join(threads[a], NULL); |
||||||
|
+ } |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ // check results |
||||||
|
+ for(a = 0; a < NUMBER_OF_THREADS; ++a) { |
||||||
|
+ assert(data[a].result == 0); |
||||||
|
+ } |
||||||
|
+} |
||||||
|
+#endif // HAVE_PTHREAD |
||||||
|
+ |
||||||
|
+ |
||||||
|
static void jv_test() { |
||||||
|
/// JSON parser regression tests |
||||||
|
{ |
||||||
|
|
||||||
|
commit f05c5bb521f404592b137e02a1b8abd50da87ca3 |
||||||
|
Author: Tomas Halman <thalman@redhat.com> |
||||||
|
Date: Wed Mar 1 20:07:28 2023 +0100 |
||||||
|
|
||||||
|
Fix segmentation fault when using jq in threads |
||||||
|
|
||||||
|
In previous code nomem_handler in jv_alloc.c is called only once |
||||||
|
and therefore the structure is not initialized for second and |
||||||
|
following threads. |
||||||
|
|
||||||
|
This leads to segmentation fault in multi-threading environment. |
||||||
|
|
||||||
|
This patch moves initialization of nomem_handler out of the |
||||||
|
pthread_once call. |
||||||
|
|
||||||
|
diff -up jq-1.6/src/jv_alloc.c.orig jq-1.6/src/jv_alloc.c |
||||||
|
--- jq-1.6/src/jv_alloc.c.orig 2018-11-02 02:49:29.000000000 +0100 |
||||||
|
+++ jq-1.6/src/jv_alloc.c 2023-03-09 14:13:47.810177037 +0100 |
||||||
|
@@ -45,9 +45,11 @@ static void memory_exhausted() { |
||||||
|
#ifdef HAVE_PTHREAD_KEY_CREATE |
||||||
|
#include <pthread.h> |
||||||
|
|
||||||
|
-pthread_key_t nomem_handler_key; |
||||||
|
-pthread_once_t mem_once = PTHREAD_ONCE_INIT; |
||||||
|
+static pthread_key_t nomem_handler_key; |
||||||
|
+static pthread_once_t mem_once = PTHREAD_ONCE_INIT; |
||||||
|
|
||||||
|
+/* tsd_fini is called on application exit */ |
||||||
|
+/* it clears the nomem_handler allocated in the main thread */ |
||||||
|
static void tsd_fini(void) { |
||||||
|
struct nomem_handler *nomem_handler; |
||||||
|
nomem_handler = pthread_getspecific(nomem_handler_key); |
||||||
|
@@ -57,30 +59,45 @@ static void tsd_fini(void) { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
+/* The tsd_fini_thread is a destructor set by calling */ |
||||||
|
+/* pthread_key_create(&nomem_handler_key, tsd_fini_thread) */ |
||||||
|
+/* It is called when thread ends */ |
||||||
|
+static void tsd_fini_thread(void *nomem_handler) { |
||||||
|
+ free(nomem_handler); |
||||||
|
+} |
||||||
|
+ |
||||||
|
static void tsd_init(void) { |
||||||
|
- if (pthread_key_create(&nomem_handler_key, NULL) != 0) { |
||||||
|
- fprintf(stderr, "error: cannot create thread specific key"); |
||||||
|
+ if (pthread_key_create(&nomem_handler_key, tsd_fini_thread) != 0) { |
||||||
|
+ fprintf(stderr, "jq: error: cannot create thread specific key"); |
||||||
|
abort(); |
||||||
|
} |
||||||
|
if (atexit(tsd_fini) != 0) { |
||||||
|
- fprintf(stderr, "error: cannot set an exit handler"); |
||||||
|
+ fprintf(stderr, "jq: error: cannot set an exit handler"); |
||||||
|
abort(); |
||||||
|
} |
||||||
|
- struct nomem_handler *nomem_handler = calloc(1, sizeof(struct nomem_handler)); |
||||||
|
- if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) { |
||||||
|
- fprintf(stderr, "error: cannot set thread specific data"); |
||||||
|
- abort(); |
||||||
|
+} |
||||||
|
+ |
||||||
|
+static void tsd_init_nomem_handler(void) |
||||||
|
+{ |
||||||
|
+ if (pthread_getspecific(nomem_handler_key) == NULL) { |
||||||
|
+ struct nomem_handler *nomem_handler = calloc(1, sizeof(struct nomem_handler)); |
||||||
|
+ if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) { |
||||||
|
+ fprintf(stderr, "jq: error: cannot set thread specific data"); |
||||||
|
+ abort(); |
||||||
|
+ } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) { |
||||||
|
pthread_once(&mem_once, tsd_init); // cannot fail |
||||||
|
+ tsd_init_nomem_handler(); |
||||||
|
+ |
||||||
|
struct nomem_handler *nomem_handler; |
||||||
|
|
||||||
|
nomem_handler = pthread_getspecific(nomem_handler_key); |
||||||
|
if (nomem_handler == NULL) { |
||||||
|
handler(data); |
||||||
|
- fprintf(stderr, "error: cannot allocate memory\n"); |
||||||
|
+ fprintf(stderr, "jq: error: cannot allocate memory\n"); |
||||||
|
abort(); |
||||||
|
} |
||||||
|
nomem_handler->handler = handler; |
||||||
|
@@ -91,6 +108,8 @@ static void memory_exhausted() { |
||||||
|
struct nomem_handler *nomem_handler; |
||||||
|
|
||||||
|
pthread_once(&mem_once, tsd_init); |
||||||
|
+ tsd_init_nomem_handler(); |
||||||
|
+ |
||||||
|
nomem_handler = pthread_getspecific(nomem_handler_key); |
||||||
|
if (nomem_handler) |
||||||
|
nomem_handler->handler(nomem_handler->data); // Maybe handler() will longjmp() to safety |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue