Coverage Report

Created: 2023-11-19 06:57

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