Coverage Report

Created: 2026-10-17 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jq/src/builtin.c
Line
Count
Source
1
#if __SIZEOF_POINTER__==4
2
# define _TIME_BITS 64
3
#endif
4
#ifndef __sun__
5
# define _XOPEN_SOURCE
6
# define _XOPEN_SOURCE_EXTENDED 1
7
#else
8
# define _XPG6
9
# define __EXTENSIONS__
10
#endif
11
#ifdef __OpenBSD__
12
# define _BSD_SOURCE
13
#endif
14
#include <sys/time.h>
15
#include <stdlib.h>
16
#include <stddef.h>
17
#include <assert.h>
18
#include <ctype.h>
19
#include <limits.h>
20
#include <math.h>
21
#ifdef HAVE_LIBONIG
22
#include <oniguruma.h>
23
#endif
24
#include <string.h>
25
#include <time.h>
26
#ifdef WIN32
27
#include <windows.h>
28
#endif
29
#include "builtin.h"
30
#include "compile.h"
31
#include "jq_parser.h"
32
#include "bytecode.h"
33
#include "linker.h"
34
#include "locfile.h"
35
#include "iso8601.h"
36
#include "jv_unicode.h"
37
#include "jv_alloc.h"
38
#include "jv_dtoa.h"
39
#include "jv_dtoa_tsd.h"
40
#include "jv_private.h"
41
#include "util.h"
42
43
44
#define BINOP(name) \
45
0
static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
46
0
  jv_free(input); \
47
0
  return binop_ ## name(a, b); \
48
0
}
Unexecuted instantiation: builtin.c:f_plus
Unexecuted instantiation: builtin.c:f_minus
Unexecuted instantiation: builtin.c:f_multiply
Unexecuted instantiation: builtin.c:f_divide
Unexecuted instantiation: builtin.c:f_mod
Unexecuted instantiation: builtin.c:f_equal
Unexecuted instantiation: builtin.c:f_notequal
Unexecuted instantiation: builtin.c:f_less
Unexecuted instantiation: builtin.c:f_lesseq
Unexecuted instantiation: builtin.c:f_greater
Unexecuted instantiation: builtin.c:f_greatereq
49
BINOPS
50
#undef BINOP
51
52
53
0
static jv type_error(jv bad, const char* msg) {
54
0
  char errbuf[30];
55
0
  const char *badkind = jv_kind_name(jv_get_kind(bad));
56
0
  jv err = jv_invalid_with_msg(jv_string_fmt(
57
0
        "%s (%s) %s", badkind,
58
0
        jv_dump_string_trunc(bad, errbuf, sizeof(errbuf)), msg));
59
0
  return err;
60
0
}
61
62
0
static jv type_error2(jv bad1, jv bad2, const char* msg) {
63
0
  char errbuf1[30], errbuf2[30];
64
0
  const char *badkind1 = jv_kind_name(jv_get_kind(bad1));
65
0
  const char *badkind2 = jv_kind_name(jv_get_kind(bad2));
66
0
  jv err = jv_invalid_with_msg(jv_string_fmt(
67
0
        "%s (%s) and %s (%s) %s", badkind1,
68
0
        jv_dump_string_trunc(bad1, errbuf1, sizeof(errbuf1)),
69
0
        badkind2,
70
0
        jv_dump_string_trunc(bad2, errbuf2, sizeof(errbuf2)), msg));
71
0
  return err;
72
0
}
73
74
0
static inline jv ret_error(jv bad, jv msg) {
75
0
  jv_free(bad);
76
0
  return jv_invalid_with_msg(msg);
77
0
}
78
79
0
static inline jv ret_error2(jv bad1, jv bad2, jv msg) {
80
0
  jv_free(bad1);
81
0
  jv_free(bad2);
82
0
  return jv_invalid_with_msg(msg);
83
0
}
84
85
0
jv binop_plus(jv a, jv b) {
86
0
  if (jv_get_kind(a) == JV_KIND_NULL) {
87
0
    jv_free(a);
88
0
    return b;
89
0
  } else if (jv_get_kind(b) == JV_KIND_NULL) {
90
0
    jv_free(b);
91
0
    return a;
92
0
  } else if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
93
0
    jv r = jv_number(jv_number_value(a) +
94
0
                     jv_number_value(b));
95
0
    jv_free(a);
96
0
    jv_free(b);
97
0
    return r;
98
0
  } else if (jv_get_kind(a) == JV_KIND_STRING && jv_get_kind(b) == JV_KIND_STRING) {
99
0
    return jv_string_concat(a, b);
100
0
  } else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) {
101
0
    return jv_array_concat(a, b);
102
0
  } else if (jv_get_kind(a) == JV_KIND_OBJECT && jv_get_kind(b) == JV_KIND_OBJECT) {
103
0
    return jv_object_merge(a, b);
104
0
  } else {
105
0
    return type_error2(a, b, "cannot be added");
106
0
  }
107
0
}
108
109
#ifdef __APPLE__
110
// macOS has a bunch of libm deprecation warnings, so let's clean those up
111
#ifdef HAVE_TGAMMA
112
#define HAVE_GAMMA
113
#define gamma tgamma
114
#endif
115
#ifdef HAVE___EXP10
116
#define HAVE_EXP10
117
#define exp10 __exp10
118
#endif
119
#ifdef HAVE_REMAINDER
120
#define HAVE_DREM
121
#define drem remainder
122
#endif
123
124
// We replace significand with our own, since there's not a rename-replacement
125
#ifdef HAVE_FREXP
126
static double __jq_significand(double x) {
127
  int z;
128
  return 2*frexp(x, &z);
129
}
130
#define HAVE_SIGNIFICAND
131
#define significand __jq_significand
132
#elif defined(HAVE_SCALBN) && defined(HAVE_ILOGB)
133
static double __jq_significand(double x) {
134
  return scalbn(x, -ilogb(x));
135
}
136
#define HAVE_SIGNIFICAND
137
#define significand __jq_significand
138
#endif
139
140
#endif // ifdef __APPLE__
141
142
#define LIBM_DD(name) \
143
0
static jv f_ ## name(jq_state *jq, jv input) { \
144
0
  if (jv_get_kind(input) != JV_KIND_NUMBER) { \
145
0
    return type_error(input, "number required"); \
146
0
  } \
147
0
  jv ret = jv_number(name(jv_number_value(input))); \
148
0
  jv_free(input); \
149
0
  return ret; \
150
0
}
Unexecuted instantiation: builtin.c:f_acos
Unexecuted instantiation: builtin.c:f_acosh
Unexecuted instantiation: builtin.c:f_asin
Unexecuted instantiation: builtin.c:f_asinh
Unexecuted instantiation: builtin.c:f_atan
Unexecuted instantiation: builtin.c:f_atanh
Unexecuted instantiation: builtin.c:f_cbrt
Unexecuted instantiation: builtin.c:f_cos
Unexecuted instantiation: builtin.c:f_cosh
Unexecuted instantiation: builtin.c:f_exp
Unexecuted instantiation: builtin.c:f_exp2
Unexecuted instantiation: builtin.c:f_floor
Unexecuted instantiation: builtin.c:f_j0
Unexecuted instantiation: builtin.c:f_j1
Unexecuted instantiation: builtin.c:f_log
Unexecuted instantiation: builtin.c:f_log10
Unexecuted instantiation: builtin.c:f_log2
Unexecuted instantiation: builtin.c:f_sin
Unexecuted instantiation: builtin.c:f_sinh
Unexecuted instantiation: builtin.c:f_sqrt
Unexecuted instantiation: builtin.c:f_tan
Unexecuted instantiation: builtin.c:f_tanh
Unexecuted instantiation: builtin.c:f_tgamma
Unexecuted instantiation: builtin.c:f_y0
Unexecuted instantiation: builtin.c:f_y1
Unexecuted instantiation: builtin.c:f_ceil
Unexecuted instantiation: builtin.c:f_erf
Unexecuted instantiation: builtin.c:f_erfc
Unexecuted instantiation: builtin.c:f_exp10
Unexecuted instantiation: builtin.c:f_expm1
Unexecuted instantiation: builtin.c:f_fabs
Unexecuted instantiation: builtin.c:f_gamma
Unexecuted instantiation: builtin.c:f_lgamma
Unexecuted instantiation: builtin.c:f_log1p
Unexecuted instantiation: builtin.c:f_logb
Unexecuted instantiation: builtin.c:f_nearbyint
Unexecuted instantiation: builtin.c:f_rint
Unexecuted instantiation: builtin.c:f_round
Unexecuted instantiation: builtin.c:f_significand
Unexecuted instantiation: builtin.c:f_trunc
151
#define LIBM_DD_NO(name) \
152
static jv f_ ## name(jq_state *jq, jv input) { \
153
  jv error = jv_string("Error: " #name "/0 not found at build time"); \
154
  return ret_error(input, error); \
155
}
156
157
#define LIBM_DDD(name) \
158
0
static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
159
0
  jv_free(input); \
160
0
  if (jv_get_kind(a) != JV_KIND_NUMBER) { \
161
0
    jv_free(b); \
162
0
    return type_error(a, "number required"); \
163
0
  } \
164
0
  if (jv_get_kind(b) != JV_KIND_NUMBER) { \
165
0
    jv_free(a); \
166
0
    return type_error(b, "number required"); \
167
0
  } \
168
0
  jv ret = jv_number(name(jv_number_value(a), jv_number_value(b))); \
169
0
  jv_free(a); \
170
0
  jv_free(b); \
171
0
  return ret; \
172
0
}
Unexecuted instantiation: builtin.c:f_atan2
Unexecuted instantiation: builtin.c:f_hypot
Unexecuted instantiation: builtin.c:f_pow
Unexecuted instantiation: builtin.c:f_remainder
Unexecuted instantiation: builtin.c:f_jn
Unexecuted instantiation: builtin.c:f_yn
Unexecuted instantiation: builtin.c:f_copysign
Unexecuted instantiation: builtin.c:f_drem
Unexecuted instantiation: builtin.c:f_fdim
Unexecuted instantiation: builtin.c:f_fmax
Unexecuted instantiation: builtin.c:f_fmin
Unexecuted instantiation: builtin.c:f_fmod
Unexecuted instantiation: builtin.c:f_nextafter
Unexecuted instantiation: builtin.c:f_nexttoward
Unexecuted instantiation: builtin.c:f_scalb
Unexecuted instantiation: builtin.c:f_scalbln
Unexecuted instantiation: builtin.c:f_ldexp
173
#define LIBM_DDD_NO(name) \
174
static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
175
  jv_free(b); \
176
  jv error = jv_string("Error: " #name "/2 not found at build time"); \
177
  return ret_error2(input, a, error); \
178
}
179
180
#define LIBM_DDDD(name) \
181
0
static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
182
0
  jv_free(input); \
183
0
  if (jv_get_kind(a) != JV_KIND_NUMBER) { \
184
0
    jv_free(b); \
185
0
    jv_free(c); \
186
0
    return type_error(a, "number required"); \
187
0
  } \
188
0
  if (jv_get_kind(b) != JV_KIND_NUMBER) { \
189
0
    jv_free(a); \
190
0
    jv_free(c); \
191
0
    return type_error(b, "number required"); \
192
0
  } \
193
0
  if (jv_get_kind(c) != JV_KIND_NUMBER) { \
194
0
    jv_free(a); \
195
0
    jv_free(b); \
196
0
    return type_error(c, "number required"); \
197
0
  } \
198
0
  jv ret = jv_number(name(jv_number_value(a), jv_number_value(b), jv_number_value(c))); \
199
0
  jv_free(a); \
200
0
  jv_free(b); \
201
0
  jv_free(c); \
202
0
  return ret; \
203
0
}
204
#define LIBM_DDDD_NO(name) \
205
static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
206
  jv_free(c); \
207
  jv_free(b); \
208
  jv error = jv_string("Error: " #name "/3 not found at build time"); \
209
  return ret_error2(input, a, error); \
210
}
211
212
#define LIBM_DA(name, type) \
213
0
static jv f_ ## name(jq_state *jq, jv input) { \
214
0
  if (jv_get_kind(input) != JV_KIND_NUMBER) { \
215
0
    return type_error(input, "number required"); \
216
0
  } \
217
0
  type value; \
218
0
  double d = name(jv_number_value(input), &value); \
219
0
  jv ret = JV_ARRAY(jv_number(d), jv_number(value)); \
220
0
  jv_free(input); \
221
0
  return ret; \
222
0
}
Unexecuted instantiation: builtin.c:f_modf
Unexecuted instantiation: builtin.c:f_frexp
Unexecuted instantiation: builtin.c:f_lgamma_r
223
#define LIBM_DA_NO(name, type) \
224
static jv f_ ## name(jq_state *jq, jv input) { \
225
  jv error = jv_string("Error: " #name "/0 not found at build time"); \
226
  return ret_error(input, error); \
227
}
228
229
#include "libm.h"
230
#undef LIBM_DDDD_NO
231
#undef LIBM_DDD_NO
232
#undef LIBM_DD_NO
233
#undef LIBM_DA_NO
234
#undef LIBM_DDDD
235
#undef LIBM_DDD
236
#undef LIBM_DD
237
#undef LIBM_DA
238
239
#ifdef __APPLE__
240
#undef gamma
241
#undef drem
242
#undef significand
243
#undef exp10
244
#endif
245
246
0
static jv f_negate(jq_state *jq, jv input) {
247
0
  if (jv_get_kind(input) != JV_KIND_NUMBER) {
248
0
    return type_error(input, "cannot be negated");
249
0
  }
250
0
  jv ret = jv_number_negate(input);
251
0
  jv_free(input);
252
0
  return ret;
253
0
}
254
255
0
static jv f_startswith(jq_state *jq, jv a, jv b) {
256
0
  if (jv_get_kind(a) != JV_KIND_STRING || jv_get_kind(b) != JV_KIND_STRING)
257
0
    return ret_error2(a, b, jv_string("startswith() requires string inputs"));
258
0
  int alen = jv_string_length_bytes(jv_copy(a));
259
0
  int blen = jv_string_length_bytes(jv_copy(b));
260
0
  jv ret;
261
262
0
  if (blen <= alen && memcmp(jv_string_value(a), jv_string_value(b), blen) == 0)
263
0
    ret = jv_true();
264
0
  else
265
0
    ret = jv_false();
266
0
  jv_free(a);
267
0
  jv_free(b);
268
0
  return ret;
269
0
}
270
271
0
static jv f_endswith(jq_state *jq, jv a, jv b) {
272
0
  if (jv_get_kind(a) != JV_KIND_STRING || jv_get_kind(b) != JV_KIND_STRING)
273
0
    return ret_error2(a, b, jv_string("endswith() requires string inputs"));
274
0
  const char *astr = jv_string_value(a);
275
0
  const char *bstr = jv_string_value(b);
276
0
  size_t alen = jv_string_length_bytes(jv_copy(a));
277
0
  size_t blen = jv_string_length_bytes(jv_copy(b));
278
0
  jv ret;
279
280
0
  if (alen < blen ||
281
0
     memcmp(astr + (alen - blen), bstr, blen) != 0)
282
0
    ret = jv_false();
283
0
  else
284
0
    ret = jv_true();
285
0
  jv_free(a);
286
0
  jv_free(b);
287
0
  return ret;
288
0
}
289
290
0
jv binop_minus(jv a, jv b) {
291
0
  if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
292
0
    jv r = jv_number(jv_number_value(a) - jv_number_value(b));
293
0
    jv_free(a);
294
0
    jv_free(b);
295
0
    return r;
296
0
  } else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) {
297
0
    jv out = jv_array();
298
0
    jv_array_foreach(a, i, x) {
299
0
      int include = 1;
300
0
      jv_array_foreach(b, j, y) {
301
0
        int equal = jv_equal(jv_copy(x), y);
302
0
        if (equal < 0) {
303
0
          jv_free(out);
304
0
          jv_free(x);
305
0
          jv_free(a);
306
0
          jv_free(b);
307
0
          return jv_invalid_with_msg(jv_string("Equality check too deep"));
308
0
        }
309
0
        if (equal) {
310
0
          include = 0;
311
0
          break;
312
0
        }
313
0
      }
314
0
      if (include)
315
0
        out = jv_array_append(out, jv_copy(x));
316
0
      jv_free(x);
317
0
    }
318
0
    jv_free(a);
319
0
    jv_free(b);
320
0
    return out;
321
0
  } else {
322
0
    return type_error2(a, b, "cannot be subtracted");
323
0
  }
324
0
}
325
326
0
jv binop_multiply(jv a, jv b) {
327
0
  jv_kind ak = jv_get_kind(a);
328
0
  jv_kind bk = jv_get_kind(b);
329
0
  if (ak == JV_KIND_NUMBER && bk == JV_KIND_NUMBER) {
330
0
    jv r = jv_number(jv_number_value(a) * jv_number_value(b));
331
0
    jv_free(a);
332
0
    jv_free(b);
333
0
    return r;
334
0
  } else if ((ak == JV_KIND_STRING && bk == JV_KIND_NUMBER) ||
335
0
             (ak == JV_KIND_NUMBER && bk == JV_KIND_STRING)) {
336
0
    jv str = a;
337
0
    jv num = b;
338
0
    if (ak == JV_KIND_NUMBER) {
339
0
      str = b;
340
0
      num = a;
341
0
    }
342
0
    double d = jv_number_value(num);
343
0
    jv_free(num);
344
0
    return jv_string_repeat(str,
345
0
        d < 0 || isnan(d) ? -1 : d > INT_MAX ? INT_MAX : (int)d);
346
0
  } else if (ak == JV_KIND_OBJECT && bk == JV_KIND_OBJECT) {
347
0
    return jv_object_merge_recursive(a, b);
348
0
  } else {
349
0
    return type_error2(a, b, "cannot be multiplied");
350
0
  }
351
0
}
352
353
0
jv binop_divide(jv a, jv b) {
354
0
  if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
355
0
    if (jv_number_value(b) == 0.0)
356
0
      return type_error2(a, b, "cannot be divided because the divisor is zero");
357
0
    jv r = jv_number(jv_number_value(a) / jv_number_value(b));
358
0
    jv_free(a);
359
0
    jv_free(b);
360
0
    return r;
361
0
  } else if (jv_get_kind(a) == JV_KIND_STRING && jv_get_kind(b) == JV_KIND_STRING) {
362
0
    return jv_string_split(a, b);
363
0
  } else {
364
0
    return type_error2(a, b, "cannot be divided");
365
0
  }
366
0
}
367
368
0
#define dtoi(n) ((n) < INTMAX_MIN ? INTMAX_MIN : -(n) <= INTMAX_MIN ? INTMAX_MAX : (intmax_t)(n))
369
0
jv binop_mod(jv a, jv b) {
370
0
  if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
371
0
    double na = jv_number_value(a);
372
0
    double nb = jv_number_value(b);
373
0
    if (isnan(na) || isnan(nb)) {
374
0
      jv_free(a);
375
0
      jv_free(b);
376
0
      return jv_number(NAN);
377
0
    }
378
0
    intmax_t bi = dtoi(nb);
379
0
    if (bi == 0)
380
0
      return type_error2(a, b, "cannot be divided (remainder) because the divisor is zero");
381
    // Check if the divisor is -1 to avoid overflow when the dividend is INTMAX_MIN.
382
0
    jv r = jv_number(bi == -1 ? 0 : dtoi(na) % bi);
383
0
    jv_free(a);
384
0
    jv_free(b);
385
0
    return r;
386
0
  } else {
387
0
    return type_error2(a, b, "cannot be divided (remainder)");
388
0
  }
389
0
}
390
#undef dtoi
391
392
0
jv binop_equal(jv a, jv b) {
393
0
  int r = jv_equal(a, b);
394
0
  if (r < 0)
395
0
    return jv_invalid_with_msg(jv_string("Equality check too deep"));
396
0
  return jv_bool(r);
397
0
}
398
399
0
jv binop_notequal(jv a, jv b) {
400
0
  int r = jv_equal(a, b);
401
0
  if (r < 0)
402
0
    return jv_invalid_with_msg(jv_string("Equality check too deep"));
403
0
  return jv_bool(!r);
404
0
}
405
406
enum cmp_op {
407
  CMP_OP_LESS,
408
  CMP_OP_GREATER,
409
  CMP_OP_LESSEQ,
410
  CMP_OP_GREATEREQ
411
};
412
413
0
static jv order_cmp(jv a, jv b, enum cmp_op op) {
414
0
  int r = jv_cmp(a, b);
415
0
  if (r == INT_MIN)
416
0
    return jv_invalid_with_msg(jv_string("Comparison too deep"));
417
0
  return jv_bool((op == CMP_OP_LESS && r < 0) ||
418
0
                 (op == CMP_OP_LESSEQ && r <= 0) ||
419
0
                 (op == CMP_OP_GREATEREQ && r >= 0) ||
420
0
                 (op == CMP_OP_GREATER && r > 0));
421
0
}
422
423
0
jv binop_less(jv a, jv b) {
424
0
  return order_cmp(a, b, CMP_OP_LESS);
425
0
}
426
427
0
jv binop_greater(jv a, jv b) {
428
0
  return order_cmp(a, b, CMP_OP_GREATER);
429
0
}
430
431
0
jv binop_lesseq(jv a, jv b) {
432
0
  return order_cmp(a, b, CMP_OP_LESSEQ);
433
0
}
434
435
0
jv binop_greatereq(jv a, jv b) {
436
0
  return order_cmp(a, b, CMP_OP_GREATEREQ);
437
0
}
438
439
0
static jv f_contains(jq_state *jq, jv a, jv b) {
440
0
  if (jv_get_kind(a) == jv_get_kind(b)) {
441
0
    int r = jv_contains(a, b);
442
0
    if (r < 0)
443
0
      return jv_invalid_with_msg(jv_string("Containment check too deep"));
444
0
    return jv_bool(r);
445
0
  } else {
446
0
    return type_error2(a, b, "cannot have their containment checked");
447
0
  }
448
0
}
449
450
0
static jv f_dump(jq_state *jq, jv input) {
451
0
  return jv_dump_string(input, 0);
452
0
}
453
454
0
static jv f_json_parse(jq_state *jq, jv input) {
455
0
  if (jv_get_kind(input) != JV_KIND_STRING)
456
0
    return type_error(input, "only strings can be parsed");
457
0
  jv res = jv_parse_sized(jv_string_value(input),
458
0
                          jv_string_length_bytes(jv_copy(input)));
459
0
  jv_free(input);
460
0
  return res;
461
0
}
462
463
0
static jv f_tonumber(jq_state *jq, jv input) {
464
0
  if (jv_get_kind(input) == JV_KIND_NUMBER) {
465
0
    return input;
466
0
  }
467
0
  if (jv_get_kind(input) == JV_KIND_STRING) {
468
0
    const char* s = jv_string_value(input);
469
0
    int len = jv_string_length_bytes(jv_copy(input));
470
0
    if ((size_t)len != strlen(s)) {
471
0
      return type_error(input, "cannot be parsed as a number");
472
0
    }
473
0
#ifdef USE_DECNUM
474
0
    jv number = jv_number_with_literal(s);
475
0
    if (jv_get_kind(number) == JV_KIND_INVALID) {
476
0
      return type_error(input, "cannot be parsed as a number");
477
0
    }
478
#else
479
    char *end = 0;
480
    double d = jvp_strtod(tsd_dtoa_context_get(), s, &end);
481
    if (end == 0 || *end != 0) {
482
      return type_error(input, "cannot be parsed as a number");
483
    }
484
    jv number = jv_number(d);
485
#endif
486
0
    jv_free(input);
487
0
    return number;
488
0
  }
489
0
  return type_error(input, "cannot be parsed as a number");
490
0
}
491
492
0
static jv f_toboolean(jq_state *jq, jv input) {
493
0
  if (jv_get_kind(input) == JV_KIND_TRUE || jv_get_kind(input) == JV_KIND_FALSE) {
494
0
    return input;
495
0
  }
496
0
  if (jv_get_kind(input) == JV_KIND_STRING) {
497
0
    const char *s = jv_string_value(input);
498
0
    int len = jv_string_length_bytes(jv_copy(input));
499
0
    if ((size_t)len != strlen(s)) {
500
0
      return type_error(input, "cannot be parsed as a boolean");
501
0
    }
502
0
    if (strcmp(s, "true") == 0) {
503
0
      jv_free(input);
504
0
      return jv_true();
505
0
    } else if (strcmp(s, "false") == 0) {
506
0
      jv_free(input);
507
0
      return jv_false();
508
0
    }
509
0
  }
510
0
  return type_error(input, "cannot be parsed as a boolean");
511
0
}
512
513
0
static jv f_length(jq_state *jq, jv input) {
514
0
  if (jv_get_kind(input) == JV_KIND_ARRAY) {
515
0
    return jv_number(jv_array_length(input));
516
0
  } else if (jv_get_kind(input) == JV_KIND_OBJECT) {
517
0
    return jv_number(jv_object_length(input));
518
0
  } else if (jv_get_kind(input) == JV_KIND_STRING) {
519
0
    return jv_number(jv_string_length_codepoints(input));
520
0
  } else if (jv_get_kind(input) == JV_KIND_NUMBER) {
521
0
    jv r = jv_number_abs(input);
522
0
    jv_free(input);
523
0
    return r;
524
0
  } else if (jv_get_kind(input) == JV_KIND_NULL) {
525
0
    jv_free(input);
526
0
    return jv_number(0);
527
0
  } else {
528
0
    return type_error(input, "has no length");
529
0
  }
530
0
}
531
532
0
static jv f_tostring(jq_state *jq, jv input) {
533
0
  if (jv_get_kind(input) == JV_KIND_STRING) {
534
0
    return input;
535
0
  } else {
536
0
    return jv_dump_string(input, 0);
537
0
  }
538
0
}
539
540
0
static jv f_utf8bytelength(jq_state *jq, jv input) {
541
0
  if (jv_get_kind(input) != JV_KIND_STRING)
542
0
    return type_error(input, "only strings have UTF-8 byte length");
543
0
  return jv_number(jv_string_length_bytes(input));
544
0
}
545
546
static const unsigned char URI_UNRESERVED[128] = {
547
  // 1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
548
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00
549
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10
550
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, // 0x20: - .
551
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 0x30: 0-9
552
  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40: A-O
553
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 0x50: P-Z _
554
  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60: a-o
555
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, // 0x70: p-z ~
556
};
557
558
#define CHARS_ALPHANUM "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
559
560
static const unsigned char BASE64_ENCODE_TABLE[64 + 1] = CHARS_ALPHANUM "+/";
561
static const unsigned char BASE64_INVALID_ENTRY = 0xFF;
562
static const unsigned char BASE64_DECODE_TABLE[256] = {
563
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
564
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
565
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
566
  62, // +
567
  0xFF, 0xFF, 0xFF,
568
  63, // /
569
  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // 0-9
570
  0xFF, 0xFF, 0xFF,
571
  99, // =
572
  0xFF, 0xFF, 0xFF,
573
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // A-Z
574
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
575
  26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,  // a-z
576
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
577
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
578
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
579
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
580
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
581
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
582
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
583
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
584
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
585
};
586
587
588
0
static jv escape_string(jv input, const char* escapings) {
589
590
0
  assert(jv_get_kind(input) == JV_KIND_STRING);
591
0
  const char* lookup[128] = {0};
592
0
  const char* p = escapings;
593
0
  lookup[0] = "\\0";
594
0
  while (*p) {
595
0
    lookup[(int)*p] = p+1;
596
0
    p++;
597
0
    p += strlen(p);
598
0
    p++;
599
0
  }
600
601
0
  jv ret = jv_string("");
602
0
  const char* i = jv_string_value(input);
603
0
  const char* end = i + jv_string_length_bytes(jv_copy(input));
604
0
  const char* cstart;
605
0
  int c = 0;
606
0
  while ((i = jvp_utf8_next((cstart = i), end, &c))) {
607
0
    if (c < 128 && lookup[c]) {
608
0
      ret = jv_string_append_str(ret, lookup[c]);
609
0
    } else {
610
0
      ret = jv_string_append_buf(ret, cstart, i - cstart);
611
0
    }
612
0
  }
613
0
  jv_free(input);
614
0
  return ret;
615
616
0
}
617
618
0
static jv f_format(jq_state *jq, jv input, jv fmt) {
619
0
  if (jv_get_kind(fmt) != JV_KIND_STRING) {
620
0
    jv_free(input);
621
0
    return type_error(fmt, "is not a valid format");
622
0
  }
623
0
  const char* fmt_s = jv_string_value(fmt);
624
0
  if (!strcmp(fmt_s, "json")) {
625
0
    jv_free(fmt);
626
0
    return jv_dump_string(input, 0);
627
0
  } else if (!strcmp(fmt_s, "text")) {
628
0
    jv_free(fmt);
629
0
    return f_tostring(jq, input);
630
0
  } else if (!strcmp(fmt_s, "csv") || !strcmp(fmt_s, "tsv")) {
631
0
    const char *quotes, *sep, *escapings;
632
0
    const char *msg;
633
0
    if (!strcmp(fmt_s, "csv")) {
634
0
      msg = "cannot be csv-formatted, only array";
635
0
      quotes = "\"";
636
0
      sep = ",";
637
0
      escapings = "\"\"\"\0";
638
0
    } else {
639
0
      msg = "cannot be tsv-formatted, only array";
640
0
      assert(!strcmp(fmt_s, "tsv"));
641
0
      quotes = "";
642
0
      sep = "\t";
643
0
      escapings = "\t\\t\0\r\\r\0\n\\n\0\\\\\\\0";
644
0
    }
645
0
    jv_free(fmt);
646
0
    if (jv_get_kind(input) != JV_KIND_ARRAY)
647
0
      return type_error(input, msg);
648
0
    jv line = jv_string("");
649
0
    jv_array_foreach(input, i, x) {
650
0
      if (i) line = jv_string_append_str(line, sep);
651
0
      switch (jv_get_kind(x)) {
652
0
      case JV_KIND_NULL:
653
        /* null rendered as empty string */
654
0
        jv_free(x);
655
0
        break;
656
0
      case JV_KIND_TRUE:
657
0
      case JV_KIND_FALSE:
658
0
        line = jv_string_concat(line, jv_dump_string(x, 0));
659
0
        break;
660
0
      case JV_KIND_NUMBER:
661
0
        if (jv_number_value(x) != jv_number_value(x)) {
662
          /* NaN, render as empty string */
663
0
          jv_free(x);
664
0
        } else {
665
0
          line = jv_string_concat(line, jv_dump_string(x, 0));
666
0
        }
667
0
        break;
668
0
      case JV_KIND_STRING: {
669
0
        line = jv_string_append_str(line, quotes);
670
0
        line = jv_string_concat(line, escape_string(x, escapings));
671
0
        line = jv_string_append_str(line, quotes);
672
0
        break;
673
0
      }
674
0
      default:
675
0
        jv_free(input);
676
0
        jv_free(line);
677
0
        return type_error(x, "is not valid in a csv row");
678
0
      }
679
0
    }
680
0
    jv_free(input);
681
0
    return line;
682
0
  } else if (!strcmp(fmt_s, "html")) {
683
0
    jv_free(fmt);
684
0
    return escape_string(f_tostring(jq, input), "&&amp;\0<&lt;\0>&gt;\0'&apos;\0\"&quot;\0");
685
0
  } else if (!strcmp(fmt_s, "uri")) {
686
0
    jv_free(fmt);
687
0
    input = f_tostring(jq, input);
688
0
    const char* s = jv_string_value(input);
689
0
    int len = jv_string_length_bytes(jv_copy(input));
690
0
    char *result = jv_mem_alloc((size_t)len * 3 + 1);
691
0
    uint32_t ri = 0;
692
0
    for (int i = 0; i < len; i++) {
693
0
      unsigned c = (unsigned)(unsigned char)s[i];
694
0
      if (c < 128 && URI_UNRESERVED[c]) {
695
0
        result[ri++] = (char)c;
696
0
      } else {
697
0
        result[ri++] = '%';
698
0
        result[ri++] = "0123456789ABCDEF"[c >> 4];
699
0
        result[ri++] = "0123456789ABCDEF"[c & 0x0F];
700
0
      }
701
0
    }
702
0
    jv line = jv_string_sized(result, ri);
703
0
    free(result);
704
0
    jv_free(input);
705
0
    return line;
706
0
  } else if (!strcmp(fmt_s, "urid")) {
707
0
    jv_free(fmt);
708
0
    input = f_tostring(jq, input);
709
0
    const char *errmsg = "is not a valid uri encoding";
710
0
    const char *s = jv_string_value(input);
711
0
    int len = jv_string_length_bytes(jv_copy(input));
712
0
    char *result = jv_mem_alloc((size_t)len + 1);
713
0
    uint32_t ri = 0;
714
0
    for (int i = 0; i < len; i++) {
715
0
      char c = s[i];
716
0
      if (c != '%') {
717
0
        result[ri++] = c;
718
0
      } else {
719
0
        int hi = 0, lo = 0;
720
0
        for (int j = 0; j < 2; j++) {
721
0
          if (++i >= len) {
722
0
            free(result);
723
0
            return type_error(input, errmsg);
724
0
          }
725
0
          int *d = j == 0 ? &hi : &lo;
726
0
          c = s[i];
727
0
          if ('0' <= c && c <= '9') *d = c - '0';
728
0
          else if ('a' <= c && c <= 'f') *d = c - 'a' + 10;
729
0
          else if ('A' <= c && c <= 'F') *d = c - 'A' + 10;
730
0
          else {
731
0
            free(result);
732
0
            return type_error(input, errmsg);
733
0
          }
734
0
        }
735
0
        result[ri++] = (hi << 4) | lo;
736
0
      }
737
0
    }
738
0
    if (!jvp_utf8_is_valid(result, result + ri)) {
739
0
      free(result);
740
0
      return type_error(input, errmsg);
741
0
    }
742
0
    jv line = jv_string_sized(result, ri);
743
0
    free(result);
744
0
    jv_free(input);
745
0
    return line;
746
0
  } else if (!strcmp(fmt_s, "sh")) {
747
0
    jv_free(fmt);
748
0
    if (jv_get_kind(input) != JV_KIND_ARRAY)
749
0
      input = jv_array_set(jv_array(), 0, input);
750
0
    jv line = jv_string("");
751
0
    jv_array_foreach(input, i, x) {
752
0
      if (i) line = jv_string_append_str(line, " ");
753
0
      switch (jv_get_kind(x)) {
754
0
      case JV_KIND_NULL:
755
0
      case JV_KIND_TRUE:
756
0
      case JV_KIND_FALSE:
757
0
      case JV_KIND_NUMBER:
758
0
        line = jv_string_concat(line, jv_dump_string(x, 0));
759
0
        break;
760
761
0
      case JV_KIND_STRING: {
762
0
        line = jv_string_append_str(line, "'");
763
0
        line = jv_string_concat(line, escape_string(x, "''\\''\0"));
764
0
        line = jv_string_append_str(line, "'");
765
0
        break;
766
0
      }
767
768
0
      default:
769
0
        jv_free(input);
770
0
        jv_free(line);
771
0
        return type_error(x, "can not be escaped for shell");
772
0
      }
773
0
    }
774
0
    jv_free(input);
775
0
    return line;
776
0
  } else if (!strcmp(fmt_s, "base64")) {
777
0
    jv_free(fmt);
778
0
    input = f_tostring(jq, input);
779
0
    jv line = jv_string("");
780
0
    const unsigned char* data = (const unsigned char*)jv_string_value(input);
781
0
    int len = jv_string_length_bytes(jv_copy(input));
782
0
    for (int i=0; i<len; i+=3) {
783
0
      uint32_t code = 0;
784
0
      int n = len - i >= 3 ? 3 : len-i;
785
0
      for (int j=0; j<3; j++) {
786
0
        code <<= 8;
787
0
        code |= j < n ? (unsigned)data[i+j] : 0;
788
0
      }
789
0
      char buf[4];
790
0
      for (int j=0; j<4; j++) {
791
0
        buf[j] = BASE64_ENCODE_TABLE[(code >> (18 - j*6)) & 0x3f];
792
0
      }
793
0
      if (n < 3) buf[3] = '=';
794
0
      if (n < 2) buf[2] = '=';
795
0
      line = jv_string_append_buf(line, buf, sizeof(buf));
796
0
    }
797
0
    jv_free(input);
798
0
    return line;
799
0
  } else if (!strcmp(fmt_s, "base64d")) {
800
0
    jv_free(fmt);
801
0
    input = f_tostring(jq, input);
802
0
    const unsigned char* data = (const unsigned char*)jv_string_value(input);
803
0
    int len = jv_string_length_bytes(jv_copy(input));
804
0
    size_t decoded_len = MAX((3 * (size_t)len) / 4, (size_t)1); // 3 usable bytes for every 4 bytes of input
805
0
    char *result = jv_mem_calloc(decoded_len, sizeof(char));
806
0
    uint32_t ri = 0;
807
0
    int input_bytes_read=0;
808
0
    uint32_t code = 0;
809
0
    for (int i=0; i<len && data[i] != '='; i++) {
810
0
      if (BASE64_DECODE_TABLE[data[i]] == BASE64_INVALID_ENTRY) {
811
0
        free(result);
812
0
        return type_error(input, "is not valid base64 data");
813
0
      }
814
815
0
      code <<= 6;
816
0
      code |= BASE64_DECODE_TABLE[data[i]];
817
0
      input_bytes_read++;
818
819
0
      if (input_bytes_read == 4) {
820
0
        result[ri++] = (code >> 16) & 0xFF;
821
0
        result[ri++] = (code >> 8) & 0xFF;
822
0
        result[ri++] = code & 0xFF;
823
0
        input_bytes_read = 0;
824
0
        code = 0;
825
0
      }
826
0
    }
827
0
    if (input_bytes_read == 3) {
828
0
      result[ri++] = (code >> 10) & 0xFF;
829
0
      result[ri++] = (code >> 2) & 0xFF;
830
0
    } else if (input_bytes_read == 2) {
831
0
      result[ri++] = (code >> 4) & 0xFF;
832
0
    } else if (input_bytes_read == 1) {
833
0
      free(result);
834
0
      return type_error(input, "trailing base64 byte found");
835
0
    }
836
837
0
    jv line = jv_string_sized(result, ri);
838
0
    jv_free(input);
839
0
    free(result);
840
0
    return line;
841
0
  } else {
842
0
    jv_free(input);
843
0
    return jv_invalid_with_msg(jv_string_concat(fmt, jv_string(" is not a valid format")));
844
0
  }
845
0
}
846
847
0
static jv f_keys(jq_state *jq, jv input) {
848
0
  if (jv_get_kind(input) == JV_KIND_OBJECT || jv_get_kind(input) == JV_KIND_ARRAY) {
849
0
    return jv_keys(input);
850
0
  } else {
851
0
    return type_error(input, "has no keys");
852
0
  }
853
0
}
854
855
0
static jv f_keys_unsorted(jq_state *jq, jv input) {
856
0
  if (jv_get_kind(input) == JV_KIND_OBJECT || jv_get_kind(input) == JV_KIND_ARRAY) {
857
0
    return jv_keys_unsorted(input);
858
0
  } else {
859
0
    return type_error(input, "has no keys");
860
0
  }
861
0
}
862
863
0
static jv f_sort(jq_state *jq, jv input){
864
0
  if (jv_get_kind(input) == JV_KIND_ARRAY) {
865
0
    return jv_sort(input, jv_copy(input));
866
0
  } else {
867
0
    return type_error(input, "cannot be sorted, as it is not an array");
868
0
  }
869
0
}
870
871
0
static jv f_sort_by_impl(jq_state *jq, jv input, jv keys) {
872
0
  if (jv_get_kind(input) == JV_KIND_ARRAY &&
873
0
      jv_get_kind(keys) == JV_KIND_ARRAY &&
874
0
      jv_array_length(jv_copy(input)) == jv_array_length(jv_copy(keys))) {
875
0
    return jv_sort(input, keys);
876
0
  } else {
877
0
    return type_error2(input, keys, "cannot be sorted, as they are not both arrays");
878
0
  }
879
0
}
880
881
/*
882
 * Assuming the input array is sorted, bsearch/1 returns
883
 * the index of the target if the target is in the input array; and otherwise
884
 * (-1 - ix), where ix is the insertion point that would leave the array sorted.
885
 * If the input is not sorted, bsearch will terminate but with irrelevant results.
886
 */
887
0
static jv f_bsearch(jq_state *jq, jv input, jv target) {
888
0
  if (jv_get_kind(input) != JV_KIND_ARRAY) {
889
0
    jv_free(target);
890
0
    return type_error(input, "cannot be searched from");
891
0
  }
892
0
  int start = 0;
893
0
  int end = jv_array_length(jv_copy(input));
894
0
  jv answer = jv_invalid();
895
0
  while (start < end) {
896
0
    int mid = start + (end - start) / 2;
897
0
    int result = jv_cmp(jv_copy(target), jv_array_get(jv_copy(input), mid));
898
0
    if (result == INT_MIN) {
899
0
      jv_free(answer);
900
0
      jv_free(input);
901
0
      jv_free(target);
902
0
      return jv_invalid_with_msg(jv_string("Comparison too deep"));
903
0
    }
904
0
    if (result == 0) {
905
0
      answer = jv_number(mid);
906
0
      break;
907
0
    } else if (result < 0) {
908
0
      end = mid;
909
0
    } else {
910
0
      start = mid + 1;
911
0
    }
912
0
  }
913
0
  if (!jv_is_valid(answer)) {
914
0
    answer = jv_number(-1 - start);
915
0
  }
916
0
  jv_free(input);
917
0
  jv_free(target);
918
0
  return answer;
919
0
}
920
921
0
static jv f_group_by_impl(jq_state *jq, jv input, jv keys) {
922
0
  if (jv_get_kind(input) == JV_KIND_ARRAY &&
923
0
      jv_get_kind(keys) == JV_KIND_ARRAY &&
924
0
      jv_array_length(jv_copy(input)) == jv_array_length(jv_copy(keys))) {
925
0
    return jv_group(input, keys);
926
0
  } else {
927
0
    return type_error2(input, keys, "cannot be sorted, as they are not both arrays");
928
0
  }
929
0
}
930
931
0
static jv f_unique(jq_state *jq, jv input) {
932
0
  if (jv_get_kind(input) == JV_KIND_ARRAY) {
933
0
    return jv_unique(input, jv_copy(input));
934
0
  } else {
935
0
    return type_error(input, "cannot be sorted, as it is not an array");
936
0
  }
937
0
}
938
939
0
static jv f_unique_by_impl(jq_state *jq, jv input, jv keys) {
940
0
  if (jv_get_kind(input) == JV_KIND_ARRAY &&
941
0
      jv_get_kind(keys) == JV_KIND_ARRAY &&
942
0
      jv_array_length(jv_copy(input)) == jv_array_length(jv_copy(keys))) {
943
0
    return jv_unique(input, keys);
944
0
  } else {
945
0
    return type_error2(input, keys, "cannot be sorted, as they are not both arrays");
946
0
  }
947
0
}
948
949
#ifdef HAVE_LIBONIG
950
static int f_match_name_iter(const UChar* name, const UChar *name_end, int ngroups,
951
0
    int *groups, regex_t *reg, void *arg) {
952
0
  jv captures = *(jv*)arg;
953
0
  for (int i = 0; i < ngroups; ++i) {
954
0
    jv cap = jv_array_get(jv_copy(captures),groups[i]-1);
955
0
    if (jv_get_kind(cap) == JV_KIND_OBJECT) {
956
0
      cap = jv_object_set(cap, jv_string("name"), jv_string_sized((const char*)name, name_end-name));
957
0
      captures = jv_array_set(captures,groups[i]-1,cap);
958
0
    } else {
959
0
      jv_free(cap);
960
0
    }
961
0
  }
962
0
  *(jv *)arg = captures;
963
0
  return 0;
964
0
}
965
966
0
static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
967
0
  int test = jv_equal(testmode, jv_true());
968
0
  jv result;
969
0
  int onigret;
970
0
  int global = 0;
971
0
  regex_t *reg;
972
0
  OnigErrorInfo einfo;
973
0
  OnigRegion* region;
974
975
0
  if (jv_get_kind(input) != JV_KIND_STRING) {
976
0
    jv_free(regex);
977
0
    jv_free(modifiers);
978
0
    return type_error(input, "cannot be matched, as it is not a string");
979
0
  }
980
981
0
  if (jv_get_kind(regex) != JV_KIND_STRING) {
982
0
    jv_free(input);
983
0
    jv_free(modifiers);
984
0
    return type_error(regex, "is not a string");
985
0
  }
986
987
0
  OnigOptionType options = ONIG_OPTION_CAPTURE_GROUP;
988
989
0
  if (jv_get_kind(modifiers) == JV_KIND_STRING) {
990
0
    jv modarray = jv_string_explode(jv_copy(modifiers));
991
0
    jv_array_foreach(modarray, i, mod) {
992
0
      switch ((int)jv_number_value(mod)) {
993
0
        case 'g':
994
0
          global = 1;
995
0
          break;
996
0
        case 'i':
997
0
          options |= ONIG_OPTION_IGNORECASE;
998
0
          break;
999
0
        case 'x':
1000
0
          options |= ONIG_OPTION_EXTEND;
1001
0
          break;
1002
0
        case 'm':
1003
0
          options |= ONIG_OPTION_MULTILINE;
1004
0
          break;
1005
0
        case 's':
1006
0
          options |= ONIG_OPTION_SINGLELINE;
1007
0
          break;
1008
0
        case 'p':
1009
0
          options |= ONIG_OPTION_MULTILINE | ONIG_OPTION_SINGLELINE;
1010
0
          break;
1011
0
        case 'l':
1012
0
          options |= ONIG_OPTION_FIND_LONGEST;
1013
0
          break;
1014
0
        case 'n':
1015
0
          options |= ONIG_OPTION_FIND_NOT_EMPTY;
1016
0
          break;
1017
0
        default:
1018
0
          jv_free(input);
1019
0
          jv_free(regex);
1020
0
          jv_free(modarray);
1021
0
          return jv_invalid_with_msg(jv_string_concat(modifiers,
1022
0
                jv_string(" is not a valid modifier string")));
1023
0
      }
1024
0
    }
1025
0
    jv_free(modarray);
1026
0
  } else if (jv_get_kind(modifiers) != JV_KIND_NULL) {
1027
    // If it isn't a string or null, then it is the wrong type...
1028
0
    jv_free(input);
1029
0
    jv_free(regex);
1030
0
    return type_error(modifiers, "is not a string");
1031
0
  }
1032
1033
0
  jv_free(modifiers);
1034
1035
0
  onigret = onig_new(&reg, (const UChar*)jv_string_value(regex),
1036
0
      (const UChar*)(jv_string_value(regex) + jv_string_length_bytes(jv_copy(regex))),
1037
0
      options, ONIG_ENCODING_UTF8, ONIG_SYNTAX_PERL_NG, &einfo);
1038
0
  if (onigret != ONIG_NORMAL) {
1039
0
    UChar ebuf[ONIG_MAX_ERROR_MESSAGE_LEN];
1040
0
    onig_error_code_to_str(ebuf, onigret, &einfo);
1041
0
    jv_free(input);
1042
0
    jv_free(regex);
1043
0
    return jv_invalid_with_msg(jv_string_concat(jv_string("Regex failure: "),
1044
0
          jv_string((char*)ebuf)));
1045
0
  }
1046
0
  result = test ? jv_false() : jv_array();
1047
0
  const char *input_string = jv_string_value(input);
1048
0
  const UChar* start = (const UChar*)jv_string_value(input);
1049
0
  const unsigned long length = jv_string_length_bytes(jv_copy(input));
1050
0
  const UChar* end = start + length;
1051
0
  region = onig_region_new();
1052
0
  do {
1053
0
    onigret = onig_search(reg,
1054
0
        (const UChar*)jv_string_value(input), end, /* string boundaries */
1055
0
        start, end, /* search boundaries */
1056
0
        region, ONIG_OPTION_NONE);
1057
0
    if (onigret >= 0) {
1058
0
      if (test) {
1059
0
        result = jv_true();
1060
0
        break;
1061
0
      }
1062
1063
      // Zero-width match
1064
0
      if (region->end[0] == region->beg[0]) {
1065
0
        unsigned long idx;
1066
0
        const char *fr = (const char*)input_string;
1067
0
        for (idx = 0; fr < input_string+region->beg[0]; idx++) {
1068
0
          fr += jvp_utf8_decode_length(*fr);
1069
0
        }
1070
0
        jv match = jv_object_set(jv_object(), jv_string("offset"), jv_number(idx));
1071
0
        match = jv_object_set(match, jv_string("length"), jv_number(0));
1072
0
        match = jv_object_set(match, jv_string("string"), jv_string(""));
1073
0
        jv captures = jv_array();
1074
0
        for (int i = 1; i < region->num_regs; ++i) {
1075
0
          jv cap = jv_object();
1076
0
          if (region->beg[i] == -1) {
1077
0
            cap = jv_object_set(cap, jv_string("offset"), jv_number(-1));
1078
0
            cap = jv_object_set(cap, jv_string("string"), jv_null());
1079
0
          } else {
1080
0
            cap = jv_object_set(cap, jv_string("offset"), jv_number(idx));
1081
0
            cap = jv_object_set(cap, jv_string("string"), jv_string(""));
1082
0
          }
1083
0
          cap = jv_object_set(cap, jv_string("length"), jv_number(0));
1084
0
          cap = jv_object_set(cap, jv_string("name"), jv_null());
1085
0
          captures = jv_array_append(captures, cap);
1086
0
        }
1087
0
        onig_foreach_name(reg, f_match_name_iter, &captures);
1088
0
        match = jv_object_set(match, jv_string("captures"), captures);
1089
0
        result = jv_array_append(result, match);
1090
        // ensure '"qux" | match("(?=u)"; "g")' matches just once; advance the
1091
        // search start past the whole codepoint, not a single byte, so we don't
1092
        // land in the middle of a multibyte character (which would yield a
1093
        // spurious duplicate match at the same offset).
1094
0
        start = (const UChar*)(input_string + region->end[0] +
1095
0
            ((size_t)region->end[0] < length
1096
0
                 ? jvp_utf8_decode_length(input_string[region->end[0]])
1097
0
                 : 1));
1098
0
        continue;
1099
0
      }
1100
1101
0
      unsigned long idx;
1102
0
      unsigned long len;
1103
0
      const char *fr = (const char*)input_string;
1104
1105
0
      for (idx = len = 0; fr < input_string+region->end[0]; len++) {
1106
0
        if (fr == input_string+region->beg[0]) idx = len, len=0;
1107
0
        fr += jvp_utf8_decode_length(*fr);
1108
0
      }
1109
1110
0
      jv match = jv_object_set(jv_object(), jv_string("offset"), jv_number(idx));
1111
1112
0
      unsigned long blen = region->end[0]-region->beg[0];
1113
0
      match = jv_object_set(match, jv_string("length"), jv_number(len));
1114
0
      match = jv_object_set(match, jv_string("string"), jv_string_sized(input_string+region->beg[0],blen));
1115
0
      jv captures = jv_array();
1116
0
      for (int i = 1; i < region->num_regs; ++i) {
1117
        // Empty capture.
1118
0
        if (region->beg[i] == region->end[i]) {
1119
          // Didn't match.
1120
0
          jv cap;
1121
0
          if (region->beg[i] == -1) {
1122
0
            cap = jv_object_set(jv_object(), jv_string("offset"), jv_number(-1));
1123
0
            cap = jv_object_set(cap, jv_string("string"), jv_null());
1124
0
          } else {
1125
0
            fr = input_string;
1126
0
            for (idx = 0; fr < input_string+region->beg[i]; idx++) {
1127
0
              fr += jvp_utf8_decode_length(*fr);
1128
0
            }
1129
0
            cap = jv_object_set(jv_object(), jv_string("offset"), jv_number(idx));
1130
0
            cap = jv_object_set(cap, jv_string("string"), jv_string(""));
1131
0
          }
1132
0
          cap = jv_object_set(cap, jv_string("length"), jv_number(0));
1133
0
          cap = jv_object_set(cap, jv_string("name"), jv_null());
1134
0
          captures = jv_array_append(captures, cap);
1135
0
          continue;
1136
0
        }
1137
0
        fr = input_string;
1138
0
        for (idx = len = 0; fr < input_string+region->end[i]; len++) {
1139
0
          if (fr == input_string+region->beg[i]) idx = len, len=0;
1140
0
          fr += jvp_utf8_decode_length(*fr);
1141
0
        }
1142
1143
0
        blen = region->end[i]-region->beg[i];
1144
0
        jv cap = jv_object_set(jv_object(), jv_string("offset"), jv_number(idx));
1145
0
        cap = jv_object_set(cap, jv_string("length"), jv_number(len));
1146
0
        cap = jv_object_set(cap, jv_string("string"), jv_string_sized(input_string+region->beg[i],blen));
1147
0
        cap = jv_object_set(cap, jv_string("name"), jv_null());
1148
0
        captures = jv_array_append(captures,cap);
1149
0
      }
1150
0
      onig_foreach_name(reg,f_match_name_iter,&captures);
1151
0
      match = jv_object_set(match, jv_string("captures"), captures);
1152
0
      result = jv_array_append(result, match);
1153
0
      start = (const UChar*)(input_string+region->end[0]);
1154
0
      onig_region_free(region,0);
1155
0
    } else if (onigret == ONIG_MISMATCH) {
1156
0
      break;
1157
0
    } else { /* Error */
1158
0
      UChar ebuf[ONIG_MAX_ERROR_MESSAGE_LEN];
1159
0
      onig_error_code_to_str(ebuf, onigret, &einfo);
1160
0
      jv_free(result);
1161
0
      result = jv_invalid_with_msg(jv_string_concat(jv_string("Regex failure: "),
1162
0
            jv_string((char*)ebuf)));
1163
0
      break;
1164
0
    }
1165
0
  } while (global && start <= end);
1166
0
  onig_region_free(region,1);
1167
0
  region = NULL;
1168
0
  onig_free(reg);
1169
0
  jv_free(input);
1170
0
  jv_free(regex);
1171
0
  return result;
1172
0
}
1173
#else /* !HAVE_LIBONIG */
1174
static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
1175
  jv_free(input);
1176
  jv_free(regex);
1177
  jv_free(modifiers);
1178
  jv_free(testmode);
1179
  return jv_invalid_with_msg(jv_string("jq was compiled without ONIGURUMA regex library. match/test/sub and related functions are not available."));
1180
}
1181
#endif /* HAVE_LIBONIG */
1182
1183
0
static jv minmax_by(jv values, jv keys, int is_min) {
1184
0
  if (jv_get_kind(values) != JV_KIND_ARRAY)
1185
0
    return type_error2(values, keys, "cannot be iterated over");
1186
0
  if (jv_get_kind(keys) != JV_KIND_ARRAY)
1187
0
    return type_error2(values, keys, "cannot be iterated over");
1188
0
  if (jv_array_length(jv_copy(values)) != jv_array_length(jv_copy(keys)))
1189
0
    return type_error2(values, keys, "have wrong length");
1190
1191
0
  if (jv_array_length(jv_copy(values)) == 0) {
1192
0
    jv_free(values);
1193
0
    jv_free(keys);
1194
0
    return jv_null();
1195
0
  }
1196
0
  jv ret = jv_array_get(jv_copy(values), 0);
1197
0
  jv retkey = jv_array_get(jv_copy(keys), 0);
1198
0
  for (int i=1; i<jv_array_length(jv_copy(values)); i++) {
1199
0
    jv item = jv_array_get(jv_copy(keys), i);
1200
0
    int cmp = jv_cmp(jv_copy(item), jv_copy(retkey));
1201
0
    if (cmp == INT_MIN) {
1202
0
      jv_free(item);
1203
0
      jv_free(values);
1204
0
      jv_free(keys);
1205
0
      jv_free(retkey);
1206
0
      jv_free(ret);
1207
0
      return jv_invalid_with_msg(jv_string("Comparison too deep"));
1208
0
    }
1209
0
    if ((cmp < 0) == (is_min == 1)) {
1210
0
      jv_free(retkey);
1211
0
      retkey = item;
1212
0
      jv_free(ret);
1213
0
      ret = jv_array_get(jv_copy(values), i);
1214
0
    } else {
1215
0
      jv_free(item);
1216
0
    }
1217
0
  }
1218
0
  jv_free(values);
1219
0
  jv_free(keys);
1220
0
  jv_free(retkey);
1221
0
  return ret;
1222
0
}
1223
1224
0
static jv f_min(jq_state *jq, jv x) {
1225
0
  return minmax_by(x, jv_copy(x), 1);
1226
0
}
1227
1228
0
static jv f_max(jq_state *jq, jv x) {
1229
0
  return minmax_by(x, jv_copy(x), 0);
1230
0
}
1231
1232
0
static jv f_min_by_impl(jq_state *jq, jv x, jv y) {
1233
0
  return minmax_by(x, y, 1);
1234
0
}
1235
1236
0
static jv f_max_by_impl(jq_state *jq, jv x, jv y) {
1237
0
  return minmax_by(x, y, 0);
1238
0
}
1239
1240
1241
0
static jv f_type(jq_state *jq, jv input) {
1242
0
  jv out = jv_string(jv_kind_name(jv_get_kind(input)));
1243
0
  jv_free(input);
1244
0
  return out;
1245
0
}
1246
1247
0
static jv f_isinfinite(jq_state *jq, jv input) {
1248
0
  jv_kind k = jv_get_kind(input);
1249
0
  if (k != JV_KIND_NUMBER) {
1250
0
    jv_free(input);
1251
0
    return jv_false();
1252
0
  }
1253
0
  double n = jv_number_value(input);
1254
0
  jv_free(input);
1255
0
  return isinf(n) ? jv_true() : jv_false();
1256
0
}
1257
1258
0
static jv f_isnan(jq_state *jq, jv input) {
1259
0
  jv_kind k = jv_get_kind(input);
1260
0
  if (k != JV_KIND_NUMBER) {
1261
0
    jv_free(input);
1262
0
    return jv_false();
1263
0
  }
1264
0
  double n = jv_number_value(input);
1265
0
  jv_free(input);
1266
0
  return isnan(n) ? jv_true() : jv_false();
1267
0
}
1268
1269
0
static jv f_isnormal(jq_state *jq, jv input) {
1270
0
  jv_kind k = jv_get_kind(input);
1271
0
  if (k != JV_KIND_NUMBER) {
1272
0
    jv_free(input);
1273
0
    return jv_false();
1274
0
  }
1275
0
  double n = jv_number_value(input);
1276
0
  jv_free(input);
1277
0
  return isnormal(n) ? jv_true() : jv_false();
1278
0
}
1279
1280
0
static jv f_infinite(jq_state *jq, jv input) {
1281
0
  jv_free(input);
1282
0
  return jv_number(INFINITY);
1283
0
}
1284
1285
0
static jv f_nan(jq_state *jq, jv input) {
1286
0
  jv_free(input);
1287
0
  return jv_number(NAN);
1288
0
}
1289
1290
0
static jv f_error(jq_state *jq, jv input) {
1291
0
  return jv_invalid_with_msg(input);
1292
0
}
1293
1294
// FIXME Should autoconf check for this!
1295
#ifndef WIN32
1296
extern char **environ;
1297
#endif
1298
1299
0
static jv f_env(jq_state *jq, jv input) {
1300
0
  jv_free(input);
1301
0
  jv env = jv_object();
1302
0
  const char *var, *val;
1303
0
  for (char **e = environ; *e != NULL; e++) {
1304
0
    var = e[0];
1305
0
    val = strchr(e[0], '=');
1306
0
    if (val == NULL)
1307
0
      env = jv_object_set(env, jv_string(var), jv_null());
1308
0
    else if (val - var < INT_MAX)
1309
0
      env = jv_object_set(env, jv_string_sized(var, val - var), jv_string(val + 1));
1310
0
  }
1311
0
  return env;
1312
0
}
1313
1314
0
static jv f_halt(jq_state *jq, jv input) {
1315
0
  jv_free(input);
1316
0
  jq_halt(jq, jv_invalid(), jv_invalid());
1317
0
  return jv_true();
1318
0
}
1319
1320
0
static jv f_halt_error(jq_state *jq, jv input, jv a) {
1321
0
  if (jv_get_kind(a) != JV_KIND_NUMBER) {
1322
0
    jv_free(a);
1323
0
    return type_error(input, "halt_error/1: number required");
1324
0
  }
1325
0
  jq_halt(jq, a, input);
1326
0
  return jv_true();
1327
0
}
1328
1329
0
static jv f_get_search_list(jq_state *jq, jv input) {
1330
0
  jv_free(input);
1331
0
  return jq_get_lib_dirs(jq);
1332
0
}
1333
1334
0
static jv f_get_prog_origin(jq_state *jq, jv input) {
1335
0
  jv_free(input);
1336
0
  return jq_get_prog_origin(jq);
1337
0
}
1338
1339
0
static jv f_get_jq_origin(jq_state *jq, jv input) {
1340
0
  jv_free(input);
1341
0
  return jq_get_jq_origin(jq);
1342
0
}
1343
1344
0
static jv f_string_split(jq_state *jq, jv a, jv b) {
1345
0
  if (jv_get_kind(a) != JV_KIND_STRING || jv_get_kind(b) != JV_KIND_STRING) {
1346
0
    return ret_error2(a, b, jv_string("split input and separator must be strings"));
1347
0
  }
1348
0
  return jv_string_split(a, b);
1349
0
}
1350
1351
0
static jv f_string_explode(jq_state *jq, jv a) {
1352
0
  if (jv_get_kind(a) != JV_KIND_STRING) {
1353
0
    return ret_error(a, jv_string("explode input must be a string"));
1354
0
  }
1355
0
  return jv_string_explode(a);
1356
0
}
1357
1358
0
static jv f_string_indexes(jq_state *jq, jv a, jv b) {
1359
0
  if (jv_get_kind(a) != JV_KIND_STRING) {
1360
0
    jv_free(b);
1361
0
    return type_error(a, "cannot be searched, as it is not a string");
1362
0
  }
1363
0
  if (jv_get_kind(b) != JV_KIND_STRING) {
1364
0
    jv_free(a);
1365
0
    return type_error(b, "is not a string");
1366
0
  }
1367
0
  return jv_string_indexes(a, b);
1368
0
}
1369
1370
enum trim_op {
1371
  TRIM_LEFT  = 1 << 0,
1372
  TRIM_RIGHT = 1 << 1
1373
};
1374
1375
0
static jv string_trim(jv a, int op) {
1376
0
  if (jv_get_kind(a) != JV_KIND_STRING) {
1377
0
    return ret_error(a, jv_string("trim input must be a string"));
1378
0
  }
1379
1380
0
  int len = jv_string_length_bytes(jv_copy(a));
1381
0
  const char *start = jv_string_value(a);
1382
0
  const char *trim_start = start;
1383
0
  const char *end = trim_start + len;
1384
0
  const char *trim_end = end;
1385
0
  int c;
1386
1387
0
  if (op & TRIM_LEFT) {
1388
0
    for (;;) {
1389
0
      const char *ns = jvp_utf8_next(trim_start, end, &c);
1390
0
      if (!ns || !jvp_codepoint_is_whitespace(c))
1391
0
        break;
1392
0
      trim_start = ns;
1393
0
    }
1394
0
  }
1395
1396
  // make sure not empty string or start trim has trimmed everything
1397
0
  if ((op & TRIM_RIGHT) && trim_end > trim_start) {
1398
0
    for (;;) {
1399
0
      const char *ns = jvp_utf8_backtrack(trim_end-1, trim_start, NULL);
1400
0
      jvp_utf8_next(ns, trim_end, &c);
1401
0
      if (!jvp_codepoint_is_whitespace(c))
1402
0
        break;
1403
0
      trim_end = ns;
1404
0
      if (ns == trim_start)
1405
0
        break;
1406
0
    }
1407
0
  }
1408
1409
  // no new string needed if there is nothing to trim
1410
0
  if (trim_start == start && trim_end == end)
1411
0
    return a;
1412
1413
0
  jv ts = jv_string_sized(trim_start, trim_end - trim_start);
1414
0
  jv_free(a);
1415
0
  return ts;
1416
0
}
1417
1418
0
static jv f_string_trim(jq_state *jq, jv a)  { return string_trim(a, TRIM_LEFT | TRIM_RIGHT); }
1419
0
static jv f_string_ltrim(jq_state *jq, jv a) { return string_trim(a, TRIM_LEFT); }
1420
0
static jv f_string_rtrim(jq_state *jq, jv a) { return string_trim(a, TRIM_RIGHT); }
1421
1422
0
static jv f_string_implode(jq_state *jq, jv a) {
1423
0
  if (jv_get_kind(a) != JV_KIND_ARRAY) {
1424
0
    return ret_error(a, jv_string("implode input must be an array"));
1425
0
  }
1426
1427
0
  int len = jv_array_length(jv_copy(a));
1428
0
  jv s = jv_string_empty(len);
1429
1430
0
  for (int i = 0; i < len; i++) {
1431
0
    jv n = jv_array_get(jv_copy(a), i);
1432
0
    if (jv_get_kind(n) != JV_KIND_NUMBER || jvp_number_is_nan(n)) {
1433
0
      jv_free(a);
1434
0
      jv_free(s);
1435
0
      return type_error(n, "can't be imploded, unicode codepoint needs to be numeric");
1436
0
    }
1437
1438
0
    int nv = jv_number_value(n);
1439
0
    jv_free(n);
1440
    // outside codepoint range or in utf16 surrogate pair range
1441
0
    if (nv < 0 || nv > 0x10FFFF || (nv >= 0xD800 && nv <= 0xDFFF))
1442
0
      nv = 0xFFFD; // U+FFFD REPLACEMENT CHARACTER
1443
0
    s = jv_string_append_codepoint(s, nv);
1444
0
    if (!jv_is_valid(s)) break;
1445
0
  }
1446
1447
0
  jv_free(a);
1448
0
  return s;
1449
0
}
1450
1451
0
static jv f_setpath(jq_state *jq, jv a, jv b, jv c) { return jv_setpath(a, b, c); }
1452
extern jv _jq_path_append(jq_state *, jv, jv, jv);
1453
0
static jv f_getpath(jq_state *jq, jv a, jv b) {
1454
0
  return _jq_path_append(jq, a, b, jv_getpath(jv_copy(a), jv_copy(b)));
1455
0
}
1456
0
static jv f_delpaths(jq_state *jq, jv a, jv b) { return jv_delpaths(a, b); }
1457
0
static jv f_has(jq_state *jq, jv a, jv b) { return jv_has(a, b); }
1458
1459
0
static jv f_modulemeta(jq_state *jq, jv a) {
1460
0
  if (jv_get_kind(a) != JV_KIND_STRING) {
1461
0
    return ret_error(a, jv_string("modulemeta input module name must be a string"));
1462
0
  }
1463
0
  return load_module_meta(jq, a);
1464
0
}
1465
1466
0
static jv f_input(jq_state *jq, jv input) {
1467
0
  jv_free(input);
1468
0
  jq_input_cb cb;
1469
0
  void *data;
1470
0
  jq_get_input_cb(jq, &cb, &data);
1471
0
  if (cb == NULL)
1472
0
    return jv_invalid_with_msg(jv_string("break"));
1473
0
  jv v = cb(jq, data);
1474
0
  if (jv_is_valid(v) || jv_invalid_has_msg(jv_copy(v)))
1475
0
    return v;
1476
0
  return jv_invalid_with_msg(jv_string("break"));
1477
0
}
1478
1479
0
static jv f_debug(jq_state *jq, jv input) {
1480
0
  jq_msg_cb cb;
1481
0
  void *data;
1482
0
  jq_get_debug_cb(jq, &cb, &data);
1483
0
  if (cb != NULL)
1484
0
    cb(data, jv_copy(input));
1485
0
  return input;
1486
0
}
1487
1488
0
static jv f_stderr(jq_state *jq, jv input) {
1489
0
  jq_msg_cb cb;
1490
0
  void *data;
1491
0
  jq_get_stderr_cb(jq, &cb, &data);
1492
0
  if (cb != NULL)
1493
0
    cb(data, jv_copy(input));
1494
0
  return input;
1495
0
}
1496
1497
0
static jv tm2jv(struct tm *tm, double fsecs) {
1498
0
  return JV_ARRAY(jv_number(tm->tm_year + 1900),
1499
0
                  jv_number(tm->tm_mon),
1500
0
                  jv_number(tm->tm_mday),
1501
0
                  jv_number(tm->tm_hour),
1502
0
                  jv_number(tm->tm_min),
1503
0
                  jv_number(tm->tm_sec + (fsecs - floor(fsecs))),
1504
0
                  jv_number(tm->tm_wday),
1505
0
                  jv_number(tm->tm_yday));
1506
0
}
1507
1508
#if defined(WIN32) && !defined(HAVE_SETENV)
1509
static int setenv(const char *var, const char *val, int ovr)
1510
{
1511
  BOOL b;
1512
  char c[2];
1513
  if (!ovr)
1514
  {
1515
    DWORD d;
1516
    d = GetEnvironmentVariableA (var, c, 2);
1517
    if (0 != d && GetLastError () != ERROR_ENVVAR_NOT_FOUND) {
1518
      return d;
1519
    }
1520
  }
1521
  b = SetEnvironmentVariableA (var, val);
1522
  if (b) {
1523
    return 0;
1524
  }
1525
  return 1;
1526
}
1527
#endif
1528
1529
/*
1530
 * mktime() has side-effects and anyways, returns time in the local
1531
 * timezone, not UTC.  We want timegm(), which isn't standard.
1532
 *
1533
 * To make things worse, mktime() tells you what the timezone
1534
 * adjustment is, but you have to #define _BSD_SOURCE to get this
1535
 * field of struct tm on some systems.
1536
 *
1537
 * This is all to blame on POSIX, of course.
1538
 *
1539
 * Our wrapper tries to use timegm() if available, or mktime() and
1540
 * correct for its side-effects if possible.
1541
 *
1542
 * Returns (time_t)-2 if mktime()'s side-effects cannot be corrected.
1543
 */
1544
0
static time_t my_mktime(struct tm *tm) {
1545
0
#ifdef HAVE_TIMEGM
1546
0
  return timegm(tm);
1547
#elif HAVE_TM_TM_GMT_OFF
1548
1549
  time_t t = mktime(tm);
1550
  if (t == (time_t)-1)
1551
    return t;
1552
  return t + tm->tm_gmtoff;
1553
#elif HAVE_TM___TM_GMT_OFF
1554
  time_t t = mktime(tm);
1555
  if (t == (time_t)-1)
1556
    return t;
1557
  return t + tm->__tm_gmtoff;
1558
#elif WIN32
1559
  return _mkgmtime(tm);
1560
#else
1561
  char *tz;
1562
1563
  tz = (tz = getenv("TZ")) != NULL ? strdup(tz) : NULL;
1564
  if (tz != NULL)
1565
    setenv("TZ", "", 1);
1566
  time_t t = mktime(tm);
1567
  if (tz != NULL) {
1568
    setenv("TZ", tz, 1);
1569
    free(tz);
1570
  }
1571
  return t;
1572
#endif
1573
0
}
1574
1575
/* Compute and set tm_wday */
1576
0
static void set_tm_wday(struct tm *tm) {
1577
  /*
1578
   * https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Gauss.27s_algorithm
1579
   * https://cs.uwaterloo.ca/~alopez-o/math-faq/node73.html
1580
   *
1581
   * Tested with dates from 1900-01-01 through 2100-01-01.  This
1582
   * algorithm produces the wrong day-of-the-week number for dates in
1583
   * the range 1900-01-01..1900-02-28, and for 2100-01-01..2100-02-28.
1584
   * Since this is only needed on OS X and *BSD, we might just document
1585
   * this.
1586
   */
1587
0
  int century = (1900 + tm->tm_year) / 100;
1588
0
  int year = (1900 + tm->tm_year) % 100;
1589
0
  if (tm->tm_mon < 2)
1590
0
    year--;
1591
  /*
1592
   * The month value in the wday computation below is shifted so that
1593
   * March is 1, April is 2, .., January is 11, and February is 12.
1594
   */
1595
0
  int mon = tm->tm_mon - 1;
1596
0
  if (mon < 1)
1597
0
    mon += 12;
1598
0
  int wday =
1599
0
    (tm->tm_mday + (int)floor((2.6 * mon - 0.2)) + year + (int)floor(year / 4.0) + (int)floor(century / 4.0) - 2 * century) % 7;
1600
0
  if (wday < 0)
1601
0
    wday += 7;
1602
#if 0
1603
  /* See commentary above */
1604
  assert(wday == tm->tm_wday || tm->tm_wday == 8);
1605
#endif
1606
0
  tm->tm_wday = wday;
1607
0
}
1608
/*
1609
 * Compute and set tm_yday.
1610
 *
1611
 */
1612
0
static void set_tm_yday(struct tm *tm) {
1613
0
  static const int d[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
1614
0
  int mon = tm->tm_mon;
1615
0
  int year = 1900 + tm->tm_year;
1616
0
  int leap_day = 0;
1617
0
  if (tm->tm_mon > 1 &&
1618
0
      ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
1619
0
    leap_day = 1;
1620
1621
  /* Bound check index into d[] */
1622
0
  if (mon < 0)
1623
0
    mon = -mon;
1624
0
  if (mon > 11)
1625
0
    mon %= 12;
1626
1627
0
  int yday = d[mon] + leap_day + tm->tm_mday - 1;
1628
0
  assert(yday == tm->tm_yday || tm->tm_yday == 367);
1629
0
  tm->tm_yday = yday;
1630
0
}
1631
1632
0
static jv f_strptime(jq_state *jq, jv a, jv b) {
1633
0
  if (jv_get_kind(a) != JV_KIND_STRING || jv_get_kind(b) != JV_KIND_STRING) {
1634
0
    return ret_error2(a, b, jv_string("strptime/1 requires string inputs and arguments"));
1635
0
  }
1636
1637
0
  struct tm tm;
1638
0
  memset(&tm, 0, sizeof(tm));
1639
0
  tm.tm_wday = 8; // sentinel
1640
0
  tm.tm_yday = 367; // sentinel
1641
1642
0
  const char *input = jv_string_value(a);
1643
0
  const char *fmt = jv_string_value(b);
1644
0
  const char *end = strptime(input, fmt, &tm);
1645
0
  if (end == NULL || (*end != '\0' && !isspace((unsigned char)*end))) {
1646
0
    return ret_error2(a, b, jv_string_fmt("date \"%s\" does not match format \"%s\"", input, fmt));
1647
0
  }
1648
0
  jv_free(b);
1649
  /*
1650
   * This is OS X or some *BSD whose strptime() is just not that
1651
   * helpful!
1652
   *
1653
   * We don't know that the format string did involve parsing a
1654
   * year, or a month (if tm->tm_mon == 0).  But with our invalid
1655
   * day-of-week and day-of-year sentinel checks above, the worst
1656
   * this can do is produce garbage.
1657
   */
1658
#ifdef __APPLE__
1659
  /*
1660
   * Apple has made it worse, and different versions of the OS have different
1661
   * behaviors. Some versions just don't touch the fields, but others do, and
1662
   * sometimes provide wrong answers, at that! We can't tell at compile-time
1663
   * which behavior the target system will have, so instead we always use our
1664
   * functions to set these on OS X, and document that %u and %j are
1665
   * unsupported on OS X.
1666
   */
1667
  set_tm_wday(&tm);
1668
  set_tm_yday(&tm);
1669
#elif defined(WIN32) || !defined(HAVE_STRPTIME)
1670
  set_tm_wday(&tm);
1671
#else
1672
0
  if (tm.tm_wday == 8 && tm.tm_mday != 0 && tm.tm_mon >= 0 && tm.tm_mon <= 11)
1673
0
    set_tm_wday(&tm);
1674
0
  if (tm.tm_yday == 367 && tm.tm_mday != 0 && tm.tm_mon >= 0 && tm.tm_mon <= 11)
1675
0
    set_tm_yday(&tm);
1676
0
#endif
1677
0
  jv r = tm2jv(&tm, 0);
1678
0
  if (*end != '\0')
1679
0
    r = jv_array_append(r, jv_string(end));
1680
0
  jv_free(a); // must come after `*end` because `end` is a pointer into `a`'s string
1681
0
  return r;
1682
0
}
1683
1684
0
static jv f_fromdateiso8601(jq_state *jq, jv a) {
1685
0
  if (jv_get_kind(a) != JV_KIND_STRING)
1686
0
    return ret_error(a, jv_string("fromdateiso8601 requires string inputs"));
1687
0
  double t;
1688
0
  if (!iso8601_parse(jv_string_value(a), jv_string_length_bytes(jv_copy(a)), &t))
1689
0
    return ret_error(a, jv_string_fmt("date \"%s\" is not a valid ISO 8601 datetime",
1690
0
                                      jv_string_value(a)));
1691
0
  jv_free(a);
1692
0
  return jv_number(t);
1693
0
}
1694
1695
0
static int jv2tm(jv a, struct tm *tm, int localtime) {
1696
0
  memset(tm, 0, sizeof(*tm));
1697
0
  static const size_t offsets[] = {
1698
0
    offsetof(struct tm, tm_year),
1699
0
    offsetof(struct tm, tm_mon),
1700
0
    offsetof(struct tm, tm_mday),
1701
0
    offsetof(struct tm, tm_hour),
1702
0
    offsetof(struct tm, tm_min),
1703
0
    offsetof(struct tm, tm_sec),
1704
0
    offsetof(struct tm, tm_wday),
1705
0
    offsetof(struct tm, tm_yday),
1706
0
  };
1707
1708
0
  for (size_t i = 0; i < (sizeof offsets / sizeof *offsets); ++i) {
1709
0
    jv n = jv_array_get(jv_copy(a), i);
1710
0
    if (!jv_is_valid(n))
1711
0
      break;
1712
0
    if (jv_get_kind(n) != JV_KIND_NUMBER || jvp_number_is_nan(n)) {
1713
0
      jv_free(a);
1714
0
      jv_free(n);
1715
0
      return 0;
1716
0
    }
1717
0
    double d = jv_number_value(n);
1718
0
    if (i == 0) /* year */
1719
0
      d -= 1900;
1720
0
    *(int *)((void *)tm + offsets[i]) = d < INT_MIN ? INT_MIN :
1721
0
                                        d > INT_MAX ? INT_MAX : (int)d;
1722
0
    jv_free(n);
1723
0
  }
1724
1725
0
  if (localtime) {
1726
0
    tm->tm_isdst = -1;
1727
0
    mktime(tm);
1728
0
  } else {
1729
0
#ifdef HAVE_TIMEGM
1730
0
    timegm(tm);
1731
#elif HAVE_TM_TM_GMT_OFF
1732
    // tm->tm_gmtoff = 0;
1733
    tm->tm_zone = "GMT";
1734
#elif HAVE_TM___TM_GMT_OFF
1735
    // tm->__tm_gmtoff = 0;
1736
    tm->__tm_zone = "GMT";
1737
#endif
1738
    // tm->tm_isdst = 0;
1739
1740
    // The standard permits the tm structure to contain additional members. We
1741
    // hope it is okay to initialize them to zero, because the standard does not
1742
    // provide an alternative.
1743
0
  }
1744
1745
0
  jv_free(a);
1746
0
  return 1;
1747
0
}
1748
1749
#undef TO_TM_FIELD
1750
1751
0
static jv f_mktime(jq_state *jq, jv a) {
1752
0
  if (jv_get_kind(a) != JV_KIND_ARRAY)
1753
0
    return ret_error(a, jv_string("mktime requires array inputs"));
1754
0
  struct tm tm;
1755
0
  if (!jv2tm(a, &tm, 0))
1756
0
    return jv_invalid_with_msg(jv_string("mktime requires parsed datetime inputs"));
1757
0
  time_t t = my_mktime(&tm);
1758
0
  if (t == (time_t)-1)
1759
0
    return jv_invalid_with_msg(jv_string("invalid gmtime representation"));
1760
0
  if (t == (time_t)-2)
1761
0
    return jv_invalid_with_msg(jv_string("mktime not supported on this platform"));
1762
0
  return jv_number(t);
1763
0
}
1764
1765
#ifdef HAVE_GMTIME_R
1766
0
static jv f_gmtime(jq_state *jq, jv a) {
1767
0
  if (jv_get_kind(a) != JV_KIND_NUMBER)
1768
0
    return ret_error(a, jv_string("gmtime() requires numeric inputs"));
1769
0
  struct tm tm, *tmp;
1770
0
  memset(&tm, 0, sizeof(tm));
1771
0
  double fsecs = jv_number_value(a);
1772
0
  time_t secs = floor(fsecs);
1773
0
  jv_free(a);
1774
0
  tmp = gmtime_r(&secs, &tm);
1775
0
  if (tmp == NULL)
1776
0
    return jv_invalid_with_msg(jv_string("error converting number of seconds since epoch to datetime"));
1777
0
  return tm2jv(tmp, fsecs);
1778
0
}
1779
#elif defined HAVE_GMTIME
1780
static jv f_gmtime(jq_state *jq, jv a) {
1781
  if (jv_get_kind(a) != JV_KIND_NUMBER)
1782
    return ret_error(a, jv_string("gmtime requires numeric inputs"));
1783
  struct tm tm, *tmp;
1784
  memset(&tm, 0, sizeof(tm));
1785
  double fsecs = jv_number_value(a);
1786
  time_t secs = floor(fsecs);
1787
  jv_free(a);
1788
  tmp = gmtime(&secs);
1789
  if (tmp == NULL)
1790
    return jv_invalid_with_msg(jv_string("error converting number of seconds since epoch to datetime"));
1791
  return tm2jv(tmp, fsecs);
1792
}
1793
#else
1794
static jv f_gmtime(jq_state *jq, jv a) {
1795
  jv_free(a);
1796
  return jv_invalid_with_msg(jv_string("gmtime not implemented on this platform"));
1797
}
1798
#endif
1799
1800
#ifdef HAVE_LOCALTIME_R
1801
0
static jv f_localtime(jq_state *jq, jv a) {
1802
0
  if (jv_get_kind(a) != JV_KIND_NUMBER)
1803
0
    return ret_error(a, jv_string("localtime() requires numeric inputs"));
1804
0
  struct tm tm, *tmp;
1805
0
  memset(&tm, 0, sizeof(tm));
1806
0
  double fsecs = jv_number_value(a);
1807
0
  time_t secs = floor(fsecs);
1808
0
  jv_free(a);
1809
0
  tmp = localtime_r(&secs, &tm);
1810
0
  if (tmp == NULL)
1811
0
    return jv_invalid_with_msg(jv_string("error converting number of seconds since epoch to datetime"));
1812
0
  return tm2jv(tmp, fsecs);
1813
0
}
1814
#elif defined HAVE_GMTIME
1815
static jv f_localtime(jq_state *jq, jv a) {
1816
  if (jv_get_kind(a) != JV_KIND_NUMBER)
1817
    return ret_error(a, jv_string("localtime requires numeric inputs"));
1818
  struct tm tm, *tmp;
1819
  memset(&tm, 0, sizeof(tm));
1820
  double fsecs = jv_number_value(a);
1821
  time_t secs = floor(fsecs);
1822
  jv_free(a);
1823
  tmp = localtime(&secs);
1824
  if (tmp == NULL)
1825
    return jv_invalid_with_msg(jv_string("error converting number of seconds since epoch to datetime"));
1826
  return tm2jv(tmp, fsecs);
1827
}
1828
#else
1829
static jv f_localtime(jq_state *jq, jv a) {
1830
  jv_free(a);
1831
  return jv_invalid_with_msg(jv_string("localtime not implemented on this platform"));
1832
}
1833
#endif
1834
1835
#ifdef HAVE_STRFTIME
1836
0
static jv f_strftime(jq_state *jq, jv a, jv b) {
1837
0
  if (jv_get_kind(a) == JV_KIND_NUMBER) {
1838
0
    a = f_gmtime(jq, a);
1839
0
    if (!jv_is_valid(a)) {
1840
0
      jv_free(b);
1841
0
      return a;
1842
0
    }
1843
0
  } else if (jv_get_kind(a) != JV_KIND_ARRAY) {
1844
0
    return ret_error2(a, b, jv_string("strftime/1 requires parsed datetime inputs"));
1845
0
  }
1846
0
  if (jv_get_kind(b) != JV_KIND_STRING)
1847
0
    return ret_error2(a, b, jv_string("strftime/1 requires a string format"));
1848
0
  struct tm tm;
1849
0
  if (!jv2tm(a, &tm, 0))
1850
0
    return ret_error(b, jv_string("strftime/1 requires parsed datetime inputs"));
1851
1852
  /* Prepend a character so that strftime() returning 0 means the result
1853
   * did not fit, even if the format expands to nothing; it is trimmed below. */
1854
0
  b = jv_string_concat(jv_string(" "), b);
1855
0
  const char *fmt = jv_string_value(b);
1856
0
  size_t max_size = strlen(fmt) + 100;
1857
0
  char *buf = jv_mem_alloc(max_size);
1858
#if defined(__APPLE__) || defined(__sun)
1859
  /* Apple Libc (as of version 1669.40.2) contains a bug which causes it to
1860
   * ignore the `tm.tm_gmtoff` in favor of the global timezone. To print the
1861
   * proper timezone offset we temporarily switch the TZ to UTC. */
1862
  char *tz = (tz = getenv("TZ")) != NULL ? strdup(tz) : NULL;
1863
  setenv("TZ", "UTC", 1);
1864
#endif
1865
#if defined(__sun)
1866
  /* Solaris moreover needs call to tzset to take the changed environment into
1867
   * account ... */
1868
  tzset();
1869
#endif
1870
#ifdef __NetBSD__
1871
  timezone_t tz_utc = tzalloc("UTC");
1872
  size_t n = strftime_z(tz_utc, buf, max_size, fmt, &tm);
1873
  tzfree(tz_utc);
1874
#else
1875
0
  size_t n = strftime(buf, max_size, fmt, &tm);
1876
0
#endif
1877
#if defined(__APPLE__) || defined(__sun)
1878
  if (tz) {
1879
    setenv("TZ", tz, 1);
1880
    free(tz);
1881
  } else {
1882
    unsetenv("TZ");
1883
  }
1884
#endif
1885
#if defined(__sun)
1886
  tzset();
1887
#endif
1888
0
  jv_free(b);
1889
0
  if (n == 0 || n > max_size) {
1890
0
    free(buf);
1891
0
    return jv_invalid_with_msg(jv_string("strftime/1: result too long"));
1892
0
  }
1893
0
  jv ret = jv_string_sized(buf + 1, n - 1);
1894
0
  free(buf);
1895
0
  return ret;
1896
0
}
1897
#else
1898
static jv f_strftime(jq_state *jq, jv a, jv b) {
1899
  jv_free(a);
1900
  jv_free(b);
1901
  return jv_invalid_with_msg(jv_string("strftime/1 not implemented on this platform"));
1902
}
1903
#endif
1904
1905
#ifdef HAVE_STRFTIME
1906
0
static jv f_strflocaltime(jq_state *jq, jv a, jv b) {
1907
0
  if (jv_get_kind(a) == JV_KIND_NUMBER) {
1908
0
    a = f_localtime(jq, a);
1909
0
    if (!jv_is_valid(a)) {
1910
0
      jv_free(b);
1911
0
      return a;
1912
0
    }
1913
0
  } else if (jv_get_kind(a) != JV_KIND_ARRAY) {
1914
0
    return ret_error2(a, b, jv_string("strflocaltime/1 requires parsed datetime inputs"));
1915
0
  }
1916
0
  if (jv_get_kind(b) != JV_KIND_STRING)
1917
0
    return ret_error2(a, b, jv_string("strflocaltime/1 requires a string format"));
1918
0
  struct tm tm;
1919
0
  if (!jv2tm(a, &tm, 1))
1920
0
    return ret_error(b, jv_string("strflocaltime/1 requires parsed datetime inputs"));
1921
  /* Prepend a character so that strftime() returning 0 means the result
1922
   * did not fit, even if the format expands to nothing; it is trimmed below. */
1923
0
  b = jv_string_concat(jv_string(" "), b);
1924
0
  const char *fmt = jv_string_value(b);
1925
0
  size_t max_size = strlen(fmt) + 100;
1926
0
  char *buf = jv_mem_alloc(max_size);
1927
0
  size_t n = strftime(buf, max_size, fmt, &tm);
1928
0
  jv_free(b);
1929
0
  if (n == 0 || n > max_size) {
1930
0
    free(buf);
1931
0
    return jv_invalid_with_msg(jv_string("strflocaltime/1: result too long"));
1932
0
  }
1933
0
  jv ret = jv_string_sized(buf + 1, n - 1);
1934
0
  free(buf);
1935
0
  return ret;
1936
0
}
1937
#else
1938
static jv f_strflocaltime(jq_state *jq, jv a, jv b) {
1939
  jv_free(a);
1940
  jv_free(b);
1941
  return jv_invalid_with_msg(jv_string("strflocaltime/1 not implemented on this platform"));
1942
}
1943
#endif
1944
1945
#ifdef HAVE_GETTIMEOFDAY
1946
0
static jv f_now(jq_state *jq, jv a) {
1947
0
  jv_free(a);
1948
0
  struct timeval tv;
1949
0
  if (gettimeofday(&tv, NULL) == -1)
1950
0
    return jv_number(time(NULL));
1951
0
  return jv_number(tv.tv_sec + tv.tv_usec / 1000000.0);
1952
0
}
1953
#else
1954
static jv f_now(jq_state *jq, jv a) {
1955
  jv_free(a);
1956
  return jv_number(time(NULL));
1957
}
1958
#endif
1959
1960
0
static jv f_current_filename(jq_state *jq, jv a) {
1961
0
  jv_free(a);
1962
1963
0
  jv r = jq_util_input_get_current_filename(jq);
1964
0
  if (jv_is_valid(r))
1965
0
    return r;
1966
0
  jv_free(r);
1967
0
  return jv_null();
1968
0
}
1969
0
static jv f_current_line(jq_state *jq, jv a) {
1970
0
  jv_free(a);
1971
0
  return jq_util_input_get_current_line(jq);
1972
0
}
1973
1974
0
static jv f_have_decnum(jq_state *jq, jv a) {
1975
0
  jv_free(a);
1976
0
#ifdef USE_DECNUM
1977
0
  return jv_true();
1978
#else
1979
  return jv_false();
1980
#endif
1981
0
}
1982
1983
#define CFUNC(func, name, arity) \
1984
  {.fptr = { .a ## arity = func }, name, arity}
1985
1986
#define LIBM_DD(name) \
1987
  CFUNC(f_ ## name, #name, 1),
1988
#define LIBM_DD_NO(name) LIBM_DD(name)
1989
#define LIBM_DA(name, type) LIBM_DD(name)
1990
#define LIBM_DA_NO(name, type) LIBM_DD(name)
1991
1992
#define LIBM_DDD(name) \
1993
  CFUNC(f_ ## name, #name, 3),
1994
#define LIBM_DDD_NO(name) LIBM_DDD(name)
1995
1996
#define LIBM_DDDD(name) \
1997
  CFUNC(f_ ## name, #name, 4),
1998
#define LIBM_DDDD_NO(name) LIBM_DDDD(name)
1999
2000
static const struct cfunction function_list[] = {
2001
#include "libm.h"
2002
  CFUNC(f_negate, "_negate", 1),
2003
#define BINOP(name) CFUNC(f_ ## name, "_" #name, 3),
2004
BINOPS
2005
#undef BINOP
2006
  CFUNC(f_dump, "tojson", 1),
2007
  CFUNC(f_json_parse, "fromjson", 1),
2008
  CFUNC(f_tonumber, "tonumber", 1),
2009
  CFUNC(f_toboolean, "toboolean", 1),
2010
  CFUNC(f_tostring, "tostring", 1),
2011
  CFUNC(f_keys, "keys", 1),
2012
  CFUNC(f_keys_unsorted, "keys_unsorted", 1),
2013
  CFUNC(f_startswith, "startswith", 2),
2014
  CFUNC(f_endswith, "endswith", 2),
2015
  CFUNC(f_string_split, "split", 2),
2016
  CFUNC(f_string_explode, "explode", 1),
2017
  CFUNC(f_string_implode, "implode", 1),
2018
  CFUNC(f_string_indexes, "_strindices", 2),
2019
  CFUNC(f_string_trim, "trim", 1),
2020
  CFUNC(f_string_ltrim, "ltrim", 1),
2021
  CFUNC(f_string_rtrim, "rtrim", 1),
2022
  CFUNC(f_setpath, "setpath", 3),
2023
  CFUNC(f_getpath, "getpath", 2),
2024
  CFUNC(f_delpaths, "delpaths", 2),
2025
  CFUNC(f_has, "has", 2),
2026
  CFUNC(f_contains, "contains", 2),
2027
  CFUNC(f_length, "length", 1),
2028
  CFUNC(f_utf8bytelength, "utf8bytelength", 1),
2029
  CFUNC(f_type, "type", 1),
2030
  CFUNC(f_isinfinite, "isinfinite", 1),
2031
  CFUNC(f_isnan, "isnan", 1),
2032
  CFUNC(f_isnormal, "isnormal", 1),
2033
  CFUNC(f_infinite, "infinite", 1),
2034
  CFUNC(f_nan, "nan", 1),
2035
  CFUNC(f_sort, "sort", 1),
2036
  CFUNC(f_sort_by_impl, "_sort_by_impl", 2),
2037
  CFUNC(f_group_by_impl, "_group_by_impl", 2),
2038
  CFUNC(f_unique, "unique", 1),
2039
  CFUNC(f_unique_by_impl, "_unique_by_impl", 2),
2040
  CFUNC(f_bsearch, "bsearch", 2),
2041
  CFUNC(f_min, "min", 1),
2042
  CFUNC(f_max, "max", 1),
2043
  CFUNC(f_min_by_impl, "_min_by_impl", 2),
2044
  CFUNC(f_max_by_impl, "_max_by_impl", 2),
2045
  CFUNC(f_error, "error", 1),
2046
  CFUNC(f_format, "format", 2),
2047
  CFUNC(f_env, "env", 1),
2048
  CFUNC(f_halt, "halt", 1),
2049
  CFUNC(f_halt_error, "halt_error", 2),
2050
  CFUNC(f_get_search_list, "get_search_list", 1),
2051
  CFUNC(f_get_prog_origin, "get_prog_origin", 1),
2052
  CFUNC(f_get_jq_origin, "get_jq_origin", 1),
2053
  CFUNC(f_match, "_match_impl", 4),
2054
  CFUNC(f_modulemeta, "modulemeta", 1),
2055
  CFUNC(f_input, "input", 1),
2056
  CFUNC(f_debug, "debug", 1),
2057
  CFUNC(f_stderr, "stderr", 1),
2058
  CFUNC(f_fromdateiso8601, "fromdateiso8601", 1),
2059
  CFUNC(f_strptime, "strptime", 2),
2060
  CFUNC(f_strftime, "strftime", 2),
2061
  CFUNC(f_strflocaltime, "strflocaltime", 2),
2062
  CFUNC(f_mktime, "mktime", 1),
2063
  CFUNC(f_gmtime, "gmtime", 1),
2064
  CFUNC(f_localtime, "localtime", 1),
2065
  CFUNC(f_now, "now", 1),
2066
  CFUNC(f_current_filename, "input_filename", 1),
2067
  CFUNC(f_current_line, "input_line_number", 1),
2068
  CFUNC(f_have_decnum, "have_decnum", 1),
2069
  CFUNC(f_have_decnum, "have_literal_numbers", 1),
2070
};
2071
#undef LIBM_DDDD_NO
2072
#undef LIBM_DDD_NO
2073
#undef LIBM_DD_NO
2074
#undef LIBM_DA_NO
2075
#undef LIBM_DDDD
2076
#undef LIBM_DDD
2077
#undef LIBM_DD
2078
#undef LIBM_DA
2079
2080
// This is a hack to make last(g) yield no output values,
2081
// if g yields no output values, without using boxing.
2082
0
static block gen_last_1(void) {
2083
0
  block last_var = gen_op_var_fresh(STOREV, "last");
2084
0
  block is_empty_var = gen_op_var_fresh(STOREV, "is_empty");
2085
0
  block init = BLOCK(gen_op_simple(DUP),
2086
0
                     gen_const(jv_null()),
2087
0
                     last_var,
2088
0
                     gen_op_simple(DUP),
2089
0
                     gen_const(jv_true()),
2090
0
                     is_empty_var);
2091
0
  block call_arg = BLOCK(gen_call("arg", gen_noop()),
2092
0
                         gen_op_simple(DUP),
2093
0
                         gen_op_bound(STOREV, last_var),
2094
0
                         gen_const(jv_false()),
2095
0
                         gen_op_bound(STOREV, is_empty_var),
2096
0
                         gen_op_simple(BACKTRACK));
2097
0
  block if_empty = gen_op_simple(BACKTRACK);
2098
0
  return BLOCK(init,
2099
0
               gen_op_target(FORK, call_arg),
2100
0
               call_arg,
2101
0
               BLOCK(gen_op_bound(LOADVN, is_empty_var),
2102
0
                     gen_op_target(JUMP_F, if_empty),
2103
0
                     if_empty,
2104
0
                     gen_op_bound(LOADVN, last_var)));
2105
0
}
2106
2107
struct bytecoded_builtin { const char* name; block code; };
2108
0
static block bind_bytecoded_builtins(block b) {
2109
0
  block builtins = gen_noop();
2110
0
  {
2111
0
    struct bytecoded_builtin builtin_defs[] = {
2112
0
      {"empty", gen_op_simple(BACKTRACK)},
2113
0
      {"not", gen_condbranch(gen_const(jv_false()),
2114
0
                             gen_const(jv_true()))}
2115
0
    };
2116
0
    for (unsigned i=0; i<sizeof(builtin_defs)/sizeof(builtin_defs[0]); i++) {
2117
0
      builtins = BLOCK(builtins, gen_function(builtin_defs[i].name, gen_noop(),
2118
0
                                              builtin_defs[i].code));
2119
0
    }
2120
0
  }
2121
0
  {
2122
0
    struct bytecoded_builtin builtin_def_1arg[] = {
2123
0
      {"path", BLOCK(gen_op_simple(PATH_BEGIN),
2124
0
                     gen_call("arg", gen_noop()),
2125
0
                     gen_op_simple(PATH_END))},
2126
0
      {"last", gen_last_1()},
2127
0
    };
2128
0
    for (unsigned i=0; i<sizeof(builtin_def_1arg)/sizeof(builtin_def_1arg[0]); i++) {
2129
0
      builtins = BLOCK(builtins, gen_function(builtin_def_1arg[i].name,
2130
0
                                              gen_param("arg"),
2131
0
                                              builtin_def_1arg[i].code));
2132
0
    }
2133
0
  }
2134
0
  {
2135
0
    block rangevar = gen_op_var_fresh(STOREV, "rangevar");
2136
0
    builtins = BLOCK(builtins,
2137
0
        gen_function("range",
2138
0
                     BLOCK(gen_param_regular("start"),
2139
0
                           gen_param_regular("end"),
2140
0
                           gen_param_regular("step")),
2141
0
                     BLOCK(gen_op_unbound(LOADV, "step"),
2142
0
                           gen_op_simple(DUP),
2143
0
                           gen_op_unbound(LOADV, "end"),
2144
0
                           gen_op_simple(DUP),
2145
0
                           gen_op_unbound(LOADV, "start"),
2146
0
                           rangevar,
2147
0
                           gen_op_bound(RANGE, rangevar))));
2148
0
  }
2149
0
  return BLOCK(builtins, b);
2150
0
}
2151
2152
static const char jq_builtins[] = {
2153
/* Include jq-coded builtins */
2154
#include "src/builtin.inc"
2155
  '\0',
2156
};
2157
2158
0
static block gen_builtin_list(block builtins) {
2159
0
  jv list = jv_array_append(block_list_funcs(builtins, 1), jv_string("builtins/0"));
2160
0
  return BLOCK(builtins, gen_function("builtins", gen_noop(), gen_const(list)));
2161
0
}
2162
2163
0
int builtins_bind(jq_state *jq, block* bb) {
2164
0
  block builtins;
2165
0
  struct locfile* src = locfile_init(jq, "<builtin>", jq_builtins, sizeof(jq_builtins)-1);
2166
0
  int nerrors = jq_parse_library(src, &builtins);
2167
0
  assert(!nerrors);
2168
0
  locfile_free(src);
2169
2170
0
  builtins = bind_bytecoded_builtins(builtins);
2171
0
  builtins = gen_cbinding(function_list, sizeof(function_list)/sizeof(function_list[0]), builtins);
2172
0
  builtins = gen_builtin_list(builtins);
2173
2174
0
  *bb = block_bind_referenced(builtins, *bb, OP_IS_CALL_PSEUDO);
2175
0
  return nerrors;
2176
0
}