Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : /*
4 : : utility functions used by the runtime system, generated code, and Base library
5 : : */
6 : : #include "platform.h"
7 : :
8 : : #include <stdlib.h>
9 : : #include <stdio.h>
10 : : #include <string.h>
11 : : #include <stdarg.h>
12 : : #include <setjmp.h>
13 : : #include <sys/types.h>
14 : : #include <errno.h>
15 : : #include <fcntl.h>
16 : : #include <inttypes.h>
17 : : #if defined(_OS_WINDOWS_)
18 : : #include <malloc.h>
19 : : #else
20 : : #include <unistd.h>
21 : : #endif
22 : : #include <ctype.h>
23 : : #include "julia.h"
24 : : #include "julia_internal.h"
25 : : #include "julia_assert.h"
26 : :
27 : : #ifdef __cplusplus
28 : : extern "C" {
29 : : #endif
30 : :
31 : : // exceptions -----------------------------------------------------------------
32 : :
33 : 11265 : JL_DLLEXPORT void JL_NORETURN jl_error(const char *str)
34 : : {
35 [ + + ]: 11265 : if (jl_errorexception_type == NULL) {
36 : 4 : jl_printf(JL_STDERR, "ERROR: %s\n", str);
37 : 4 : jl_exit(1);
38 : : }
39 : 11261 : jl_value_t *msg = jl_pchar_to_string((char*)str, strlen(str));
40 : 11261 : JL_GC_PUSH1(&msg);
41 : 11261 : jl_throw(jl_new_struct(jl_errorexception_type, msg));
42 : : }
43 : :
44 : : extern int vasprintf(char **str, const char *fmt, va_list ap);
45 : :
46 : 21466 : jl_value_t *jl_vexceptionf(jl_datatype_t *exception_type,
47 : : const char *fmt, va_list args)
48 : : {
49 [ + + ]: 21466 : if (exception_type == NULL) {
50 : 26 : jl_printf(JL_STDERR, "ERROR: ");
51 : 26 : jl_vprintf(JL_STDERR, fmt, args);
52 : 26 : jl_printf(JL_STDERR, "\n");
53 : 26 : jl_exit(1);
54 : : }
55 : 21440 : char *str = NULL;
56 : 21440 : int ok = vasprintf(&str, fmt, args);
57 : : jl_value_t *msg;
58 [ - + ]: 21440 : if (ok < 0) { // vasprintf failed
59 : 0 : msg = jl_cstr_to_string("internal error: could not display error message");
60 : : }
61 : : else {
62 : 21440 : msg = jl_pchar_to_string(str, strlen(str));
63 : 21440 : free(str);
64 : : }
65 : 21440 : JL_GC_PUSH1(&msg);
66 : 21440 : jl_value_t *e = jl_new_struct(exception_type, msg);
67 : 21440 : JL_GC_POP();
68 : 21440 : return e;
69 : : }
70 : :
71 : 21408 : JL_DLLEXPORT void JL_NORETURN jl_errorf(const char *fmt, ...)
72 : : {
73 : : va_list args;
74 : 21408 : va_start(args, fmt);
75 : 21408 : jl_value_t *e = jl_vexceptionf(jl_errorexception_type, fmt, args);
76 : 21382 : va_end(args);
77 : 21382 : jl_throw(e);
78 : : }
79 : :
80 : 22 : JL_DLLEXPORT void JL_NORETURN jl_exceptionf(jl_datatype_t *exception_type,
81 : : const char *fmt, ...)
82 : : {
83 : : va_list args;
84 : 22 : va_start(args, fmt);
85 : 22 : jl_value_t *e = jl_vexceptionf(exception_type, fmt, args);
86 : 22 : va_end(args);
87 : 22 : jl_throw(e);
88 : : }
89 : :
90 : 0 : jl_value_t *jl_get_exceptionf(jl_datatype_t *exception_type,
91 : : const char *fmt, ...)
92 : : {
93 : : va_list args;
94 : 0 : va_start(args, fmt);
95 : 0 : jl_value_t *e = jl_vexceptionf(exception_type, fmt, args);
96 : 0 : va_end(args);
97 : 0 : return e;
98 : : }
99 : :
100 : 5 : JL_DLLEXPORT void JL_NORETURN jl_too_few_args(const char *fname, int min)
101 : : {
102 : 5 : jl_exceptionf(jl_argumenterror_type, "%s: too few arguments (expected %d)", fname, min);
103 : : }
104 : :
105 : 0 : JL_DLLEXPORT void JL_NORETURN jl_too_many_args(const char *fname, int max)
106 : : {
107 : 0 : jl_exceptionf(jl_argumenterror_type, "%s: too many arguments (expected %d)", fname, max);
108 : : }
109 : :
110 : : // with function name / location description, plus extra context
111 : 2192 : JL_DLLEXPORT void JL_NORETURN jl_type_error_rt(const char *fname, const char *context,
112 : : jl_value_t *expected JL_MAYBE_UNROOTED,
113 : : jl_value_t *got JL_MAYBE_UNROOTED)
114 : : {
115 : 2192 : jl_value_t *ctxt=NULL;
116 : 2192 : JL_GC_PUSH3(&ctxt, &expected, &got);
117 : 2192 : ctxt = jl_pchar_to_string((char*)context, strlen(context));
118 : 2192 : jl_value_t *ex = jl_new_struct(jl_typeerror_type, jl_symbol(fname), ctxt, expected, got);
119 : 2192 : jl_throw(ex);
120 : : }
121 : :
122 : : // with function name or description only
123 : 163 : JL_DLLEXPORT void JL_NORETURN jl_type_error(const char *fname,
124 : : jl_value_t *expected JL_MAYBE_UNROOTED,
125 : : jl_value_t *got JL_MAYBE_UNROOTED)
126 : : {
127 : 163 : jl_type_error_rt(fname, "", expected, got);
128 : : }
129 : :
130 : 91 : JL_DLLEXPORT void JL_NORETURN jl_undefined_var_error(jl_sym_t *var)
131 : : {
132 : 91 : jl_throw(jl_new_struct(jl_undefvarerror_type, var));
133 : : }
134 : :
135 : 2080 : JL_DLLEXPORT void JL_NORETURN jl_atomic_error(char *str) // == jl_exceptionf(jl_atomicerror_type, "%s", str)
136 : : {
137 : 2080 : jl_value_t *msg = jl_pchar_to_string((char*)str, strlen(str));
138 : 2080 : JL_GC_PUSH1(&msg);
139 : 2080 : jl_throw(jl_new_struct(jl_atomicerror_type, msg));
140 : : }
141 : :
142 : :
143 : 73 : JL_DLLEXPORT void JL_NORETURN jl_bounds_error(jl_value_t *v, jl_value_t *t)
144 : : {
145 : 73 : JL_GC_PUSH2(&v, &t); // root arguments so the caller doesn't need to
146 : 73 : jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t));
147 : : }
148 : :
149 : 0 : JL_DLLEXPORT void JL_NORETURN jl_bounds_error_v(jl_value_t *v, jl_value_t **idxs, size_t nidxs)
150 : : {
151 : 0 : jl_value_t *t = NULL;
152 : : // items in idxs are assumed to already be rooted
153 : 0 : JL_GC_PUSH2(&v, &t); // root v so the caller doesn't need to
154 : 0 : t = jl_f_tuple(NULL, idxs, nidxs);
155 : 0 : jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t));
156 : : }
157 : :
158 : 1 : JL_DLLEXPORT void JL_NORETURN jl_bounds_error_tuple_int(jl_value_t **v, size_t nv, size_t i)
159 : : {
160 : : // values in v are expected to already be gc-rooted
161 : 1 : jl_bounds_error_int(jl_f_tuple(NULL, v, nv), i);
162 : : }
163 : :
164 : 52 : JL_DLLEXPORT void JL_NORETURN jl_bounds_error_unboxed_int(void *data, jl_value_t *vt, size_t i)
165 : : {
166 : 52 : jl_value_t *t = NULL, *v = NULL;
167 : : // data is expected to be gc-safe (either gc-rooted, or alloca)
168 : : // vt is expected to be gc-rooted (in a linfo-root probably)
169 : 52 : JL_GC_PUSH2(&v, &t);
170 : 52 : v = jl_new_bits(vt, data);
171 : 52 : t = jl_box_long(i);
172 : 52 : jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t));
173 : : }
174 : :
175 : 8282 : JL_DLLEXPORT void JL_NORETURN jl_bounds_error_int(jl_value_t *v JL_MAYBE_UNROOTED, size_t i)
176 : : {
177 : 8282 : jl_value_t *t = NULL;
178 : 8282 : JL_GC_PUSH2(&v, &t); // root arguments so the caller doesn't need to
179 : 8282 : t = jl_box_long(i);
180 : 8282 : jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t));
181 : : }
182 : :
183 : 71 : JL_DLLEXPORT void JL_NORETURN jl_bounds_error_ints(jl_value_t *v JL_MAYBE_UNROOTED,
184 : : size_t *idxs, size_t nidxs)
185 : : {
186 : : size_t i;
187 : 71 : jl_value_t *t = NULL;
188 : 71 : JL_GC_PUSH2(&v, &t); // root arguments so the caller doesn't need to
189 : 71 : t = (jl_value_t*)jl_alloc_svec(nidxs);
190 [ + + ]: 160 : for (i = 0; i < nidxs; i++) {
191 : 89 : jl_svecset(t, i, jl_box_long(idxs[i]));
192 : : }
193 : 71 : t = jl_f_tuple(NULL, jl_svec_data(t), nidxs);
194 : 71 : jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t));
195 : : }
196 : :
197 : 2 : JL_DLLEXPORT void JL_NORETURN jl_eof_error(void)
198 : : {
199 : : jl_datatype_t *eof_error =
200 : 2 : (jl_datatype_t*)jl_get_global(jl_base_module, jl_symbol("EOFError"));
201 [ - + ]: 2 : assert(eof_error != NULL);
202 : 2 : jl_throw(jl_new_struct(eof_error));
203 : : }
204 : :
205 : : // get kwsorter field, with appropriate error check and message
206 : 194902 : JL_DLLEXPORT jl_value_t *jl_get_keyword_sorter(jl_value_t *f)
207 : : {
208 : 194902 : return jl_get_kwsorter(jl_typeof(f));
209 : : }
210 : :
211 : 38016100 : JL_DLLEXPORT void jl_typeassert(jl_value_t *x, jl_value_t *t)
212 : : {
213 [ + + ]: 38016100 : if (!jl_isa(x,t))
214 : 6 : jl_type_error("typeassert", t, x);
215 : 38016100 : }
216 : :
217 : : #ifndef HAVE_SSP
218 : : JL_DLLEXPORT uintptr_t __stack_chk_guard = (uintptr_t)0xBAD57ACCBAD67ACC; // 0xBADSTACKBADSTACK
219 : :
220 : 0 : JL_DLLEXPORT void __stack_chk_fail(void)
221 : : {
222 : : /* put your panic function or similar in here */
223 : 0 : fprintf(stderr, "fatal error: stack corruption detected\n");
224 : 0 : jl_gc_debug_critical_error();
225 : 0 : abort(); // end with abort, since the compiler destroyed the stack upon entry to this function, there's no going back now
226 : : }
227 : : #endif
228 : :
229 : : // exceptions -----------------------------------------------------------------
230 : :
231 : 96273900 : JL_DLLEXPORT void jl_enter_handler(jl_handler_t *eh)
232 : : {
233 : 96273900 : jl_task_t *ct = jl_current_task;
234 : : // Must have no safepoint
235 : 96273900 : eh->prev = ct->eh;
236 : 96273900 : eh->gcstack = ct->gcstack;
237 : 96273900 : eh->gc_state = jl_atomic_load_relaxed(&ct->ptls->gc_state);
238 : 96273900 : eh->locks_len = ct->ptls->locks.len;
239 : 96273900 : eh->defer_signal = ct->ptls->defer_signal;
240 : 96273900 : eh->world_age = ct->world_age;
241 : 96273900 : ct->eh = eh;
242 : : #ifdef ENABLE_TIMINGS
243 : : eh->timing_stack = ct->ptls->timing_stack;
244 : : #endif
245 : 96273900 : }
246 : :
247 : : // Restore thread local state to saved state in error handler `eh`.
248 : : // This is executed in two circumstances:
249 : : // * We leave a try block through normal control flow
250 : : // * An exception causes a nonlocal jump to the catch block. In this case
251 : : // there's additional cleanup required, eg pushing the exception stack.
252 : 91420300 : JL_DLLEXPORT void jl_eh_restore_state(jl_handler_t *eh)
253 : : {
254 : 91420300 : jl_task_t *ct = jl_current_task;
255 : : #ifdef _OS_WINDOWS_
256 : : if (ct->ptls->needs_resetstkoflw) {
257 : : _resetstkoflw();
258 : : ct->ptls->needs_resetstkoflw = 0;
259 : : }
260 : : #endif
261 : : // `eh` may be not equal to `ct->eh`. See `jl_pop_handler`
262 : : // This function should **NOT** have any safepoint before the ones at the
263 : : // end.
264 : 91420300 : sig_atomic_t old_defer_signal = ct->ptls->defer_signal;
265 : 91420300 : int8_t old_gc_state = jl_atomic_load_relaxed(&ct->ptls->gc_state);
266 : 91420300 : ct->eh = eh->prev;
267 : 91420300 : ct->gcstack = eh->gcstack;
268 : 91420300 : small_arraylist_t *locks = &ct->ptls->locks;
269 : 91420300 : int unlocks = locks->len > eh->locks_len;
270 [ + + ]: 91420300 : if (unlocks) {
271 [ + + ]: 62637 : for (size_t i = locks->len; i > eh->locks_len; i--)
272 : 31319 : jl_mutex_unlock_nogc((jl_mutex_t*)locks->items[i - 1]);
273 : 31318 : locks->len = eh->locks_len;
274 : : }
275 : 91420300 : ct->world_age = eh->world_age;
276 : 91420300 : ct->ptls->defer_signal = eh->defer_signal;
277 [ - + ]: 91420300 : if (old_gc_state != eh->gc_state) {
278 : 0 : jl_atomic_store_release(&ct->ptls->gc_state, eh->gc_state);
279 [ # # ]: 0 : if (old_gc_state) {
280 : 0 : jl_gc_safepoint_(ct->ptls);
281 : : }
282 : : }
283 [ + + + + ]: 91420300 : if (old_defer_signal && !eh->defer_signal) {
284 : 21898 : jl_sigint_safepoint(ct->ptls);
285 : : }
286 [ + + + + ]: 91420300 : if (jl_atomic_load_relaxed(&jl_gc_have_pending_finalizers) &&
287 [ + + ]: 1313 : unlocks && eh->locks_len == 0) {
288 : 5 : jl_gc_run_pending_finalizers(ct);
289 : : }
290 : 91420300 : }
291 : :
292 : 63305700 : JL_DLLEXPORT void jl_pop_handler(int n)
293 : : {
294 : 63305700 : jl_task_t *ct = jl_current_task;
295 [ - + ]: 63305700 : if (__unlikely(n <= 0))
296 : 0 : return;
297 : 63305700 : jl_handler_t *eh = ct->eh;
298 [ + + ]: 64484700 : while (--n > 0)
299 : 1178960 : eh = eh->prev;
300 : 63305700 : jl_eh_restore_state(eh);
301 : : }
302 : :
303 : 96346500 : JL_DLLEXPORT size_t jl_excstack_state(void) JL_NOTSAFEPOINT
304 : : {
305 : 96346500 : jl_task_t *ct = jl_current_task;
306 : 96346500 : jl_excstack_t *s = ct->excstack;
307 [ + + ]: 96346500 : return s ? s->top : 0;
308 : : }
309 : :
310 : 253298 : JL_DLLEXPORT void jl_restore_excstack(size_t state) JL_NOTSAFEPOINT
311 : : {
312 : 253298 : jl_task_t *ct = jl_current_task;
313 : 253298 : jl_excstack_t *s = ct->excstack;
314 [ + - ]: 253298 : if (s) {
315 [ - + ]: 253298 : assert(s->top >= state);
316 : 253298 : s->top = state;
317 : : }
318 : 253298 : }
319 : :
320 : 1454 : static void jl_copy_excstack(jl_excstack_t *dest, jl_excstack_t *src) JL_NOTSAFEPOINT
321 : : {
322 [ - + ]: 1454 : assert(dest->reserved_size >= src->top);
323 : 1454 : memcpy(jl_excstack_raw(dest), jl_excstack_raw(src), sizeof(jl_bt_element_t)*src->top);
324 : 1454 : dest->top = src->top;
325 : 1454 : }
326 : :
327 : 253874 : static void jl_reserve_excstack(jl_excstack_t **stack JL_REQUIRE_ROOTED_SLOT,
328 : : size_t reserved_size)
329 : : {
330 : 253874 : jl_excstack_t *s = *stack;
331 [ + + + + ]: 253874 : if (s && s->reserved_size >= reserved_size)
332 : 248300 : return;
333 : 5574 : size_t bufsz = sizeof(jl_excstack_t) + sizeof(uintptr_t)*reserved_size;
334 : 5574 : jl_task_t *ct = jl_current_task;
335 : 5574 : jl_excstack_t *new_s = (jl_excstack_t*)jl_gc_alloc_buf(ct->ptls, bufsz);
336 : 5574 : new_s->top = 0;
337 : 5574 : new_s->reserved_size = reserved_size;
338 [ + + ]: 5574 : if (s)
339 : 1454 : jl_copy_excstack(new_s, s);
340 : 5574 : *stack = new_s;
341 : : }
342 : :
343 : 253874 : void jl_push_excstack(jl_excstack_t **stack JL_REQUIRE_ROOTED_SLOT JL_ROOTING_ARGUMENT,
344 : : jl_value_t *exception JL_ROOTED_ARGUMENT,
345 : : jl_bt_element_t *bt_data, size_t bt_size)
346 : : {
347 [ + + ]: 253874 : jl_reserve_excstack(stack, (*stack ? (*stack)->top : 0) + bt_size + 2);
348 : 253874 : jl_excstack_t *s = *stack;
349 : 253874 : jl_bt_element_t *rawstack = jl_excstack_raw(s);
350 : 253874 : memcpy(rawstack + s->top, bt_data, sizeof(jl_bt_element_t)*bt_size);
351 : 253874 : s->top += bt_size + 2;
352 : 253874 : rawstack[s->top-2].uintptr = bt_size;
353 : 253874 : rawstack[s->top-1].jlvalue = exception;
354 : 253874 : }
355 : :
356 : : // conversion -----------------------------------------------------------------
357 : :
358 : 0 : JL_DLLEXPORT void *(jl_symbol_name)(jl_sym_t *s)
359 : : {
360 : 0 : return jl_symbol_name(s);
361 : : }
362 : :
363 : : // WARNING: THIS FUNCTION IS NEVER CALLED BUT INLINE BY CCALL
364 : 0 : JL_DLLEXPORT void *jl_array_ptr(jl_array_t *a)
365 : : {
366 : 0 : return a->data;
367 : : }
368 : 0 : JL_DLLEXPORT jl_value_t *jl_value_ptr(jl_value_t *a)
369 : : {
370 : 0 : return a;
371 : : }
372 : :
373 : : // optimization of setfield which bypasses boxing of the idx (and checking field type validity)
374 : 6247 : JL_DLLEXPORT void jl_set_nth_field(jl_value_t *v, size_t idx0, jl_value_t *rhs)
375 : : {
376 : 6247 : jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
377 [ + + ]: 6247 : if (!st->name->mutabl)
378 : 1 : jl_errorf("setfield!: immutable struct of type %s cannot be changed", jl_symbol_name(st->name->name));
379 [ + + ]: 6246 : if (idx0 >= jl_datatype_nfields(st))
380 : 1 : jl_bounds_error_int(v, idx0 + 1);
381 : : //jl_value_t *ft = jl_field_type(st, idx0);
382 : : //if (!jl_isa(rhs, ft)) {
383 : : // jl_type_error("setfield!", ft, rhs);
384 : : //}
385 : : //int isatomic = jl_field_isatomic(st, idx0);
386 : : //if (isatomic) ...
387 : 6245 : set_nth_field(st, v, idx0, rhs, 0);
388 : 6245 : }
389 : :
390 : :
391 : : // parsing --------------------------------------------------------------------
392 : :
393 : 45368 : static int substr_isspace(char *p, char *pend)
394 : : {
395 [ + + ]: 49093 : while (p != pend) {
396 [ + + ]: 3741 : if (!isspace((unsigned char)*p)) {
397 : 16 : return 0;
398 : : }
399 : 3725 : p++;
400 : : }
401 : 45352 : return 1;
402 : : }
403 : :
404 : 15345 : JL_DLLEXPORT jl_nullable_float64_t jl_try_substrtod(char *str, size_t offset, size_t len)
405 : : {
406 : : char *p;
407 : 15345 : char *bstr = str+offset;
408 : 15345 : char *pend = bstr+len;
409 : 15345 : char *tofree = NULL;
410 : 15345 : int hasvalue = 0;
411 : :
412 : 15345 : errno = 0;
413 [ + + + + : 15345 : if (!(*pend == '\0' || isspace((unsigned char)*pend) || *pend == ',')) {
+ + ]
414 : : // confusing data outside substring. must copy.
415 : : char *newstr;
416 [ + - ]: 11165 : if (len + 1 < jl_page_size) {
417 : 11165 : newstr = (char*)alloca(len + 1);
418 : : }
419 : : else {
420 : 0 : newstr = tofree = (char*)malloc_s(len + 1);
421 : : }
422 : 11165 : memcpy(newstr, bstr, len);
423 : 11165 : newstr[len] = 0;
424 : 11165 : bstr = newstr;
425 : 11165 : pend = bstr+len;
426 : : }
427 : 15345 : double out = jl_strtod_c(bstr, &p);
428 : :
429 [ - + - - : 15345 : if (errno==ERANGE && (out==0 || out==HUGE_VAL || out==-HUGE_VAL)) {
- - - - ]
430 : 0 : hasvalue = 0;
431 : : }
432 [ + + ]: 15345 : else if (p == bstr) {
433 : 709 : hasvalue = 0;
434 : : }
435 : : else {
436 : : // Deal with case where the substring might be something like "1 ",
437 : : // which is OK, and "1 X", which we don't allow.
438 : 14636 : hasvalue = substr_isspace(p, pend) ? 1 : 0;
439 : : }
440 : :
441 [ - + ]: 15345 : if (__unlikely(tofree))
442 : 0 : free(tofree);
443 : :
444 : 15345 : jl_nullable_float64_t ret = {(uint8_t)hasvalue, out};
445 : 15345 : return ret;
446 : : }
447 : :
448 : 0 : JL_DLLEXPORT int jl_substrtod(char *str, size_t offset, size_t len, double *out)
449 : : {
450 : 0 : jl_nullable_float64_t nd = jl_try_substrtod(str, offset, len);
451 [ # # ]: 0 : if (0 != nd.hasvalue) {
452 : 0 : *out = nd.value;
453 : 0 : return 0;
454 : : }
455 : 0 : return 1;
456 : : }
457 : :
458 : : // MSVC pre-2013 did not define HUGE_VALF
459 : : #ifndef HUGE_VALF
460 : : #define HUGE_VALF (1e25f * 1e25f)
461 : : #endif
462 : :
463 : 30732 : JL_DLLEXPORT jl_nullable_float32_t jl_try_substrtof(char *str, size_t offset, size_t len)
464 : : {
465 : : char *p;
466 : 30732 : char *bstr = str+offset;
467 : 30732 : char *pend = bstr+len;
468 : 30732 : char *tofree = NULL;
469 : 30732 : int hasvalue = 0;
470 : :
471 : 30732 : errno = 0;
472 [ + + + - : 30732 : if (!(*pend == '\0' || isspace((unsigned char)*pend) || *pend == ',')) {
+ + ]
473 : : // confusing data outside substring. must copy.
474 : : char *newstr;
475 [ + - ]: 3 : if (len + 1 < jl_page_size) {
476 : 3 : newstr = (char*)alloca(len + 1);
477 : : }
478 : : else {
479 : 0 : newstr = tofree = (char*)malloc_s(len + 1);
480 : : }
481 : 3 : memcpy(newstr, bstr, len);
482 : 3 : newstr[len] = 0;
483 : 3 : bstr = newstr;
484 : 3 : pend = bstr+len;
485 : : }
486 : : #if defined(_OS_WINDOWS_) && !defined(_COMPILER_GCC_)
487 : : float out = (float)jl_strtod_c(bstr, &p);
488 : : #else
489 : 30732 : float out = jl_strtof_c(bstr, &p);
490 : : #endif
491 : :
492 [ - + - - : 30732 : if (errno==ERANGE && (out==0 || out==HUGE_VALF || out==-HUGE_VALF)) {
- - - - ]
493 : 0 : hasvalue = 0;
494 : : }
495 [ - + ]: 30732 : else if (p == bstr) {
496 : 0 : hasvalue = 0;
497 : : }
498 : : else {
499 : : // Deal with case where the substring might be something like "1 ",
500 : : // which is OK, and "1 X", which we don't allow.
501 : 30732 : hasvalue = substr_isspace(p, pend) ? 1 : 0;
502 : : }
503 : :
504 [ - + ]: 30732 : if (__unlikely(tofree))
505 : 0 : free(tofree);
506 : :
507 : 30732 : jl_nullable_float32_t ret = {(uint8_t)hasvalue, out};
508 : 30732 : return ret;
509 : : }
510 : :
511 : 0 : JL_DLLEXPORT int jl_substrtof(char *str, int offset, size_t len, float *out)
512 : : {
513 : 0 : jl_nullable_float32_t nf = jl_try_substrtof(str, offset, len);
514 [ # # ]: 0 : if (0 != nf.hasvalue) {
515 : 0 : *out = nf.value;
516 : 0 : return 0;
517 : : }
518 : 0 : return 1;
519 : : }
520 : :
521 : : // showing --------------------------------------------------------------------
522 : :
523 : 574 : JL_DLLEXPORT void jl_flush_cstdio(void) JL_NOTSAFEPOINT
524 : : {
525 : 574 : fflush(stdout);
526 : 574 : fflush(stderr);
527 : 574 : }
528 : :
529 : 0 : JL_DLLEXPORT jl_value_t *jl_stdout_obj(void) JL_NOTSAFEPOINT
530 : : {
531 [ # # ]: 0 : if (jl_base_module == NULL)
532 : 0 : return NULL;
533 : 0 : jl_binding_t *stdout_obj = jl_get_module_binding(jl_base_module, jl_symbol("stdout"));
534 [ # # ]: 0 : return stdout_obj ? jl_atomic_load_relaxed(&stdout_obj->value) : NULL;
535 : : }
536 : :
537 : 0 : JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) JL_NOTSAFEPOINT
538 : : {
539 [ # # ]: 0 : if (jl_base_module == NULL)
540 : 0 : return NULL;
541 : 0 : jl_binding_t *stderr_obj = jl_get_module_binding(jl_base_module, jl_symbol("stderr"));
542 [ # # ]: 0 : return stderr_obj ? jl_atomic_load_relaxed(&stderr_obj->value) : NULL;
543 : : }
544 : :
545 : : // toys for debugging ---------------------------------------------------------
546 : :
547 : 0 : static size_t jl_show_svec(JL_STREAM *out, jl_svec_t *t, const char *head, const char *opn, const char *cls) JL_NOTSAFEPOINT
548 : : {
549 : 0 : size_t i, n=0, len = jl_svec_len(t);
550 : 0 : n += jl_printf(out, "%s", head);
551 : 0 : n += jl_printf(out, "%s", opn);
552 [ # # ]: 0 : for (i = 0; i < len; i++) {
553 : 0 : jl_value_t *v = jl_svecref(t,i);
554 : 0 : n += jl_static_show(out, v);
555 [ # # ]: 0 : if (i != len-1)
556 : 0 : n += jl_printf(out, ", ");
557 : : }
558 : 0 : n += jl_printf(out, "%s", cls);
559 : 0 : return n;
560 : : }
561 : :
562 : : struct recur_list {
563 : : struct recur_list *prev;
564 : : jl_value_t *v;
565 : : };
566 : :
567 : : static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, struct recur_list *depth) JL_NOTSAFEPOINT;
568 : : static size_t jl_static_show_next_(JL_STREAM *out, jl_value_t *v, jl_value_t *prev, struct recur_list *depth) JL_NOTSAFEPOINT;
569 : :
570 : : JL_DLLEXPORT int jl_id_start_char(uint32_t wc) JL_NOTSAFEPOINT;
571 : : JL_DLLEXPORT int jl_id_char(uint32_t wc) JL_NOTSAFEPOINT;
572 : :
573 : 11750 : JL_DLLEXPORT int jl_is_identifier(char *str) JL_NOTSAFEPOINT
574 : : {
575 : 11750 : size_t i = 0;
576 : 11750 : uint32_t wc = u8_nextchar(str, &i);
577 [ + + ]: 11750 : if (!jl_id_start_char(wc))
578 : 593 : return 0;
579 [ + + ]: 72068 : while ((wc = u8_nextchar(str, &i)) != 0) {
580 [ + + ]: 60921 : if (!jl_id_char(wc))
581 : 10 : return 0;
582 : : }
583 : 11147 : return 1;
584 : : }
585 : :
586 : 26614 : static jl_datatype_t *first_arg_datatype(jl_value_t *a JL_PROPAGATES_ROOT, int got_tuple1) JL_NOTSAFEPOINT
587 : : {
588 [ + + ]: 26614 : if (jl_is_datatype(a)) {
589 [ + + ]: 19693 : if (got_tuple1)
590 : 13294 : return (jl_datatype_t*)a;
591 [ + - ]: 6399 : if (jl_is_tuple_type(a)) {
592 [ - + ]: 6399 : if (jl_nparams(a) < 1)
593 : 0 : return NULL;
594 : 6399 : return first_arg_datatype(jl_tparam0(a), 1);
595 : : }
596 : 0 : return NULL;
597 : : }
598 [ + + ]: 6921 : else if (jl_is_typevar(a)) {
599 : 50 : return first_arg_datatype(((jl_tvar_t*)a)->ub, got_tuple1);
600 : : }
601 [ + + ]: 6871 : else if (jl_is_unionall(a)) {
602 : 6840 : return first_arg_datatype(((jl_unionall_t*)a)->body, got_tuple1);
603 : : }
604 [ + + ]: 31 : else if (jl_is_uniontype(a)) {
605 : 25 : jl_uniontype_t *u = (jl_uniontype_t*)a;
606 : 25 : jl_datatype_t *d1 = first_arg_datatype(u->a, got_tuple1);
607 [ - + ]: 25 : if (d1 == NULL) return NULL;
608 : 25 : jl_datatype_t *d2 = first_arg_datatype(u->b, got_tuple1);
609 [ + + + + ]: 25 : if (d2 == NULL || d1->name != d2->name)
610 : 21 : return NULL;
611 : 4 : return d1;
612 : : }
613 : 6 : return NULL;
614 : : }
615 : :
616 : : // get DataType of first tuple element (if present), or NULL if cannot be determined
617 : 6399 : JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT
618 : : {
619 : 6399 : return first_arg_datatype(argtypes, 0);
620 : : }
621 : :
622 : : // get DataType implied by a single given type, or `nothing`
623 : 6876 : JL_DLLEXPORT jl_value_t *jl_argument_datatype(jl_value_t *argt JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT
624 : : {
625 : 6876 : jl_datatype_t *dt = first_arg_datatype(argt, 1);
626 [ + + ]: 6876 : if (dt == NULL)
627 : 11 : return jl_nothing;
628 : 6865 : return (jl_value_t*)dt;
629 : : }
630 : :
631 : 13641 : static int is_globname_binding(jl_value_t *v, jl_datatype_t *dv) JL_NOTSAFEPOINT
632 : : {
633 [ + + ]: 13641 : jl_sym_t *globname = dv->name->mt != NULL ? dv->name->mt->name : NULL;
634 [ + + + - : 13641 : if (globname && dv->name->module && jl_binding_resolved_p(dv->name->module, globname)) {
+ + ]
635 : 13113 : jl_binding_t *b = jl_get_module_binding(dv->name->module, globname);
636 [ + - + + ]: 13113 : if (b && b->constp) {
637 : 10850 : jl_value_t *bv = jl_atomic_load_relaxed(&b->value);
638 : : // The `||` makes this function work for both function instances and function types.
639 [ + + + + ]: 10850 : if (bv == v || jl_typeof(bv) == v)
640 : 2116 : return 1;
641 : : }
642 : : }
643 : 11525 : return 0;
644 : : }
645 : :
646 : 2116 : static int is_globfunction(jl_value_t *v, jl_datatype_t *dv, jl_sym_t **globname_out) JL_NOTSAFEPOINT
647 : : {
648 [ + - ]: 2116 : jl_sym_t *globname = dv->name->mt != NULL ? dv->name->mt->name : NULL;
649 : 2116 : *globname_out = globname;
650 [ + - + + : 2116 : if (globname && !strchr(jl_symbol_name(globname), '#') && !strchr(jl_symbol_name(globname), '@')) {
+ - ]
651 : 2075 : return 1;
652 : : }
653 : 41 : return 0;
654 : : }
655 : :
656 : 10994 : static size_t jl_static_show_x_sym_escaped(JL_STREAM *out, jl_sym_t *name) JL_NOTSAFEPOINT
657 : : {
658 : 10994 : size_t n = 0;
659 : :
660 : 10994 : char *sn = jl_symbol_name(name);
661 : 10994 : int hidden = 0;
662 [ + + + + ]: 10994 : if (!(jl_is_identifier(sn) || jl_is_operator(sn))) {
663 : 431 : hidden = 1;
664 : : }
665 : :
666 [ + + ]: 10994 : if (hidden) {
667 : 431 : n += jl_printf(out, "var\"");
668 : : }
669 : 10994 : n += jl_printf(out, "%s", sn);
670 [ + + ]: 10994 : if (hidden) {
671 : 431 : n += jl_printf(out, "\"");
672 : : }
673 : 10994 : return n;
674 : : }
675 : :
676 : : // `jl_static_show()` cannot call `jl_subtype()`, for the GC reasons
677 : : // explained in the comment on `jl_static_show_x_()`, below.
678 : : // This function checks if `vt <: Function` without triggering GC.
679 : 364 : static int jl_static_is_function_(jl_datatype_t *vt) JL_NOTSAFEPOINT {
680 [ - + ]: 364 : if (!jl_function_type) { // Make sure there's a Function type defined.
681 : 0 : return 0;
682 : : }
683 : 364 : int _iter_count = 0; // To prevent infinite loops from corrupt type objects.
684 [ + + ]: 740 : while (vt != jl_any_type) {
685 [ - + ]: 381 : if (vt == NULL) {
686 : 0 : return 0;
687 [ - + ]: 381 : } else if (_iter_count > 10000) {
688 : : // We are very likely stuck in a cyclic datastructure, so we assume this is
689 : : // _not_ a Function.
690 : 0 : return 0;
691 [ + + ]: 381 : } else if (vt == jl_function_type) {
692 : 5 : return 1;
693 : : }
694 : 376 : vt = vt->super;
695 : 376 : _iter_count += 1;
696 : : }
697 : 359 : return 0;
698 : : }
699 : :
700 : : // `v` might be pointing to a field inlined in a structure therefore
701 : : // `jl_typeof(v)` may not be the same with `vt` and only `vt` should be
702 : : // used to determine the type of the value.
703 : : // This is necessary to make sure that this function doesn't allocate any
704 : : // memory through the Julia GC
705 : 24049 : static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt,
706 : : struct recur_list *depth) JL_NOTSAFEPOINT
707 : : {
708 : 24049 : size_t n = 0;
709 [ - + ]: 24049 : if ((uintptr_t)vt < 4096U) {
710 : 0 : n += jl_printf(out, "<?#%p::%p>", (void*)v, (void*)vt);
711 : : }
712 [ - + ]: 24049 : else if ((uintptr_t)v < 4096U) {
713 : 0 : n += jl_printf(out, "<?#%p::", (void*)v);
714 : 0 : n += jl_static_show_x(out, (jl_value_t*)vt, depth);
715 : 0 : n += jl_printf(out, ">");
716 : : }
717 : : // These need to be special cased because they
718 : : // exist only by pointer identity in early startup
719 [ + + ]: 24049 : else if (v == (jl_value_t*)jl_simplevector_type) {
720 : 17 : n += jl_printf(out, "Core.SimpleVector");
721 : : }
722 [ + + ]: 24032 : else if (v == (jl_value_t*)jl_typename_type) {
723 : 2 : n += jl_printf(out, "Core.TypeName");
724 : : }
725 [ + + ]: 24030 : else if (v == (jl_value_t*)jl_symbol_type) {
726 : 323 : n += jl_printf(out, "Symbol");
727 : : }
728 [ + + ]: 23707 : else if (v == (jl_value_t*)jl_methtable_type) {
729 : 1 : n += jl_printf(out, "Core.MethodTable");
730 : : }
731 [ + + ]: 23706 : else if (v == (jl_value_t*)jl_any_type) {
732 : 629 : n += jl_printf(out, "Any");
733 : : }
734 [ + + ]: 23077 : else if (v == (jl_value_t*)jl_type_type) {
735 : 90 : n += jl_printf(out, "Type");
736 : : }
737 [ + + ]: 22987 : else if (vt == jl_method_type) {
738 : 11 : jl_method_t *m = (jl_method_t*)v;
739 : 11 : n += jl_static_show_func_sig(out, m->sig);
740 : : }
741 [ - + ]: 22976 : else if (vt == jl_method_instance_type) {
742 : 0 : jl_method_instance_t *li = (jl_method_instance_t*)v;
743 [ # # ]: 0 : if (jl_is_method(li->def.method)) {
744 : 0 : n += jl_static_show_func_sig(out, li->specTypes);
745 : 0 : n += jl_printf(out, " from ");
746 : 0 : n += jl_static_show_func_sig(out, li->def.method->sig);
747 : : }
748 : : else {
749 : 0 : n += jl_static_show_x(out, (jl_value_t*)li->def.module, depth);
750 : 0 : n += jl_printf(out, ".<toplevel thunk> -> ");
751 : 0 : n += jl_static_show_x(out, li->uninferred, depth);
752 : : }
753 : : }
754 [ - + ]: 22976 : else if (vt == jl_typename_type) {
755 : 0 : n += jl_static_show_x(out, jl_unwrap_unionall(((jl_typename_t*)v)->wrapper), depth);
756 : 0 : n += jl_printf(out, ".name");
757 : : }
758 [ - + ]: 22976 : else if (vt == jl_simplevector_type) {
759 : 0 : n += jl_show_svec(out, (jl_svec_t*)v, "svec", "(", ")");
760 : : }
761 [ + + ]: 22976 : else if (v == (jl_value_t*)jl_unionall_type) {
762 : : // avoid printing `typeof(Type)` for `UnionAll`.
763 : 8 : n += jl_printf(out, "UnionAll");
764 : : }
765 [ + + ]: 22968 : else if (vt == jl_vararg_type) {
766 : 95 : jl_vararg_t *vm = (jl_vararg_t*)v;
767 : 95 : n += jl_printf(out, "Vararg");
768 [ + - ]: 95 : if (vm->T) {
769 : 95 : n += jl_printf(out, "{");
770 : 95 : n += jl_static_show_x(out, vm->T, depth);
771 [ + + ]: 95 : if (vm->N) {
772 : 7 : n += jl_printf(out, ", ");
773 : 7 : n += jl_static_show_x(out, vm->N, depth);
774 : : }
775 : 95 : n += jl_printf(out, "}");
776 : : }
777 : : }
778 [ + + ]: 22873 : else if (vt == jl_datatype_type) {
779 : : // typeof(v) == DataType, so v is a Type object.
780 : : // Types are printed as a fully qualified name, with parameters, e.g.
781 : : // `Base.Set{Int}`, and function types are printed as e.g. `typeof(Main.f)`
782 : 13636 : jl_datatype_t *dv = (jl_datatype_t*)v;
783 : : jl_sym_t *globname;
784 [ + + + + ]: 13636 : int globfunc = is_globname_binding(v, dv) && is_globfunction(v, dv, &globname);
785 [ + + ]: 13636 : jl_sym_t *sym = globfunc ? globname : dv->name->name;
786 : 13636 : char *sn = jl_symbol_name(sym);
787 : 13636 : size_t quote = 0;
788 [ + + ]: 13636 : if (dv->name == jl_tuple_typename) {
789 [ + + ]: 3410 : if (dv == jl_tuple_type)
790 : 3410 : return jl_printf(out, "Tuple");
791 : 3206 : int taillen = 1, tlen = jl_nparams(dv), i;
792 [ + + ]: 3879 : for (i = tlen-2; i >= 0; i--) {
793 [ + + ]: 3298 : if (jl_tparam(dv, i) == jl_tparam(dv, tlen-1))
794 : 673 : taillen++;
795 : : else
796 : 2625 : break;
797 : : }
798 [ + + + + ]: 3206 : if (taillen == tlen && taillen > 3) {
799 : 22 : n += jl_printf(out, "NTuple{%d, ", tlen);
800 : 22 : n += jl_static_show_x(out, jl_tparam0(dv), depth);
801 : 22 : n += jl_printf(out, "}");
802 : : }
803 : : else {
804 : 3184 : n += jl_printf(out, "Tuple{");
805 [ + + + + ]: 11650 : for (i = 0; i < (taillen > 3 ? tlen-taillen : tlen); i++) {
806 [ + + ]: 8466 : if (i > 0)
807 : 5319 : n += jl_printf(out, ", ");
808 : 8466 : n += jl_static_show_x(out, jl_tparam(dv, i), depth);
809 : : }
810 [ + + ]: 3184 : if (taillen > 3) {
811 : 28 : n += jl_printf(out, ", Vararg{");
812 : 28 : n += jl_static_show_x(out, jl_tparam(dv, tlen-1), depth);
813 : 28 : n += jl_printf(out, ", %d}", taillen);
814 : : }
815 : 3184 : n += jl_printf(out, "}");
816 : : }
817 : 3206 : return n;
818 : : }
819 [ + + ]: 10226 : if (globfunc) {
820 : 2072 : n += jl_printf(out, "typeof(");
821 : : }
822 [ + - + + : 10226 : if (jl_core_module && (dv->name->module != jl_core_module || !jl_module_exports_p(jl_core_module, sym))) {
+ + ]
823 : 4866 : n += jl_static_show_x(out, (jl_value_t*)dv->name->module, depth);
824 : 4866 : n += jl_printf(out, ".");
825 : 4866 : size_t i = 0;
826 [ + + + + ]: 4866 : if (globfunc && !jl_id_start_char(u8_nextchar(sn, &i))) {
827 : 156 : n += jl_printf(out, ":(");
828 : 156 : quote = 1;
829 : : }
830 : : }
831 : 10226 : n += jl_static_show_x_sym_escaped(out, sym);
832 [ + + ]: 10226 : if (globfunc) {
833 : 2072 : n += jl_printf(out, ")");
834 [ + + ]: 2072 : if (quote) {
835 : 156 : n += jl_printf(out, ")");
836 : : }
837 : : }
838 [ + - + + ]: 10226 : if (dv->parameters && (jl_value_t*)dv != dv->name->wrapper) {
839 : 2973 : size_t j, tlen = jl_nparams(dv);
840 [ + - ]: 2973 : if (tlen > 0) {
841 : 2973 : n += jl_printf(out, "{");
842 [ + + ]: 7589 : for (j = 0; j < tlen; j++) {
843 : 4616 : jl_value_t *p = jl_tparam(dv,j);
844 : 4616 : n += jl_static_show_x(out, p, depth);
845 [ + + ]: 4616 : if (j != tlen-1)
846 : 1643 : n += jl_printf(out, ", ");
847 : : }
848 : 2973 : n += jl_printf(out, "}");
849 : : }
850 : : }
851 : : }
852 [ - + ]: 9237 : else if (vt == jl_intrinsic_type) {
853 : 0 : int f = *(uint32_t*)jl_data_ptr(v);
854 : 0 : n += jl_printf(out, "#<intrinsic #%d %s>", f, jl_intrinsic_name(f));
855 : : }
856 [ + + ]: 9237 : else if (vt == jl_int64_type) {
857 : 530 : n += jl_printf(out, "%" PRId64, *(int64_t*)v);
858 : : }
859 [ - + ]: 8707 : else if (vt == jl_int32_type) {
860 : 0 : n += jl_printf(out, "%" PRId32, *(int32_t*)v);
861 : : }
862 [ - + ]: 8707 : else if (vt == jl_int16_type) {
863 : 0 : n += jl_printf(out, "%" PRId16, *(int16_t*)v);
864 : : }
865 [ - + ]: 8707 : else if (vt == jl_int8_type) {
866 : 0 : n += jl_printf(out, "%" PRId8, *(int8_t*)v);
867 : : }
868 [ - + ]: 8707 : else if (vt == jl_uint64_type) {
869 : 0 : n += jl_printf(out, "0x%016" PRIx64, *(uint64_t*)v);
870 : : }
871 [ - + ]: 8707 : else if (vt == jl_uint32_type) {
872 : 0 : n += jl_printf(out, "0x%08" PRIx32, *(uint32_t*)v);
873 : : }
874 [ - + ]: 8707 : else if (vt == jl_uint16_type) {
875 : 0 : n += jl_printf(out, "0x%04" PRIx16, *(uint16_t*)v);
876 : : }
877 [ - + ]: 8707 : else if (vt == jl_uint8_type) {
878 : 0 : n += jl_printf(out, "0x%02" PRIx8, *(uint8_t*)v);
879 : : }
880 [ + - - + ]: 8707 : else if (jl_pointer_type && jl_is_cpointer_type((jl_value_t*)vt)) {
881 : : #ifdef _P64
882 : 0 : n += jl_printf(out, "0x%016" PRIx64, *(uint64_t*)v);
883 : : #else
884 : : n += jl_printf(out, "0x%08" PRIx32, *(uint32_t*)v);
885 : : #endif
886 : : }
887 [ - + ]: 8707 : else if (vt == jl_float32_type) {
888 : 0 : n += jl_printf(out, "%gf", *(float*)v);
889 : : }
890 [ + + ]: 8707 : else if (vt == jl_float64_type) {
891 : 2 : n += jl_printf(out, "%g", *(double*)v);
892 : : }
893 [ + + ]: 8705 : else if (vt == jl_bool_type) {
894 [ + - ]: 2 : n += jl_printf(out, "%s", *(uint8_t*)v ? "true" : "false");
895 : : }
896 [ + - + - : 8703 : else if (v == jl_nothing || (jl_nothing && (jl_value_t*)vt == jl_typeof(jl_nothing))) {
- + ]
897 : 0 : n += jl_printf(out, "nothing");
898 : : }
899 [ + + ]: 8703 : else if (vt == jl_string_type) {
900 : 19 : n += jl_printf(out, "\"");
901 : 19 : jl_uv_puts(out, jl_string_data(v), jl_string_len(v)); n += jl_string_len(v);
902 : 19 : n += jl_printf(out, "\"");
903 : : }
904 [ + + ]: 8684 : else if (v == jl_bottom_type) {
905 : 10 : n += jl_printf(out, "Union{}");
906 : : }
907 [ + + ]: 8674 : else if (vt == jl_uniontype_type) {
908 : 30 : n += jl_printf(out, "Union{");
909 [ + + ]: 64 : while (jl_is_uniontype(v)) {
910 : : // tail-recurse on b to flatten the printing of the Union structure in the common case
911 : 34 : n += jl_static_show_x(out, ((jl_uniontype_t*)v)->a, depth);
912 : 34 : n += jl_printf(out, ", ");
913 : 34 : v = ((jl_uniontype_t*)v)->b;
914 : : }
915 : 30 : n += jl_static_show_x(out, v, depth);
916 : 30 : n += jl_printf(out, "}");
917 : : }
918 [ + + ]: 8644 : else if (vt == jl_unionall_type) {
919 : 378 : jl_unionall_t *ua = (jl_unionall_t*)v;
920 : 378 : n += jl_static_show_x(out, ua->body, depth);
921 : 378 : n += jl_printf(out, " where ");
922 : 378 : n += jl_static_show_x(out, (jl_value_t*)ua->var, depth->prev);
923 : : }
924 [ - + ]: 8266 : else if (vt == jl_typename_type) {
925 : 0 : n += jl_printf(out, "typename(");
926 : 0 : n += jl_static_show_x(out, jl_unwrap_unionall(((jl_typename_t*)v)->wrapper), depth);
927 : 0 : n += jl_printf(out, ")");
928 : : }
929 [ + + ]: 8266 : else if (vt == jl_tvar_type) {
930 : : // show type-var bounds only if they aren't going to be printed by UnionAll later
931 : 764 : jl_tvar_t *var = (jl_tvar_t*)v;
932 : : struct recur_list *p;
933 : 764 : int showbounds = 1;
934 [ + + ]: 2952 : for (p = depth; p != NULL; p = p->prev) {
935 [ + + + + ]: 2572 : if (jl_is_unionall(p->v) && ((jl_unionall_t*)p->v)->var == var) {
936 : 384 : showbounds = 0;
937 : 384 : break;
938 : : }
939 : : }
940 : 764 : jl_value_t *lb = var->lb, *ub = var->ub;
941 [ + + - + ]: 764 : if (showbounds && lb != jl_bottom_type) {
942 : : // show type-var lower bound if it is defined
943 : 0 : int ua = jl_is_unionall(lb);
944 [ # # ]: 0 : if (ua)
945 : 0 : n += jl_printf(out, "(");
946 : 0 : n += jl_static_show_x(out, lb, depth);
947 [ # # ]: 0 : if (ua)
948 : 0 : n += jl_printf(out, ")");
949 : 0 : n += jl_printf(out, "<:");
950 : : }
951 : 764 : n += jl_static_show_x_sym_escaped(out, var->name);
952 [ + + + + : 764 : if (showbounds && (ub != (jl_value_t*)jl_any_type || lb != jl_bottom_type)) {
- + ]
953 : : // show type-var upper bound if it is defined, or if we showed the lower bound
954 : 195 : int ua = jl_is_unionall(ub);
955 : 195 : n += jl_printf(out, "<:");
956 [ + + ]: 195 : if (ua)
957 : 1 : n += jl_printf(out, "(");
958 : 195 : n += jl_static_show_x(out, ub, depth);
959 [ + + ]: 195 : if (ua)
960 : 1 : n += jl_printf(out, ")");
961 : : }
962 : : }
963 [ + + ]: 7502 : else if (vt == jl_module_type) {
964 : 6356 : jl_module_t *m = (jl_module_t*)v;
965 [ + + + + ]: 6356 : if (m->parent != m && m->parent != jl_main_module) {
966 : 1472 : n += jl_static_show_x(out, (jl_value_t*)m->parent, depth);
967 : 1472 : n += jl_printf(out, ".");
968 : : }
969 : 6356 : n += jl_printf(out, "%s", jl_symbol_name(m->name));
970 : : }
971 [ + + ]: 1146 : else if (vt == jl_symbol_type) {
972 : 751 : char *sn = jl_symbol_name((jl_sym_t*)v);
973 [ + + + + ]: 751 : int quoted = !jl_is_identifier(sn) && jl_operator_precedence(sn) == 0;
974 [ + + ]: 751 : if (quoted)
975 : 11 : n += jl_printf(out, "Symbol(\"");
976 : : else
977 : 740 : n += jl_printf(out, ":");
978 : 751 : n += jl_printf(out, "%s", sn);
979 [ + + ]: 751 : if (quoted)
980 : 11 : n += jl_printf(out, "\")");
981 : : }
982 [ + + ]: 395 : else if (vt == jl_ssavalue_type) {
983 : 10 : n += jl_printf(out, "SSAValue(%" PRIuPTR ")",
984 : 10 : (uintptr_t)((jl_ssavalue_t*)v)->id);
985 : : }
986 [ + + ]: 385 : else if (vt == jl_globalref_type) {
987 : 5 : n += jl_static_show_x(out, (jl_value_t*)jl_globalref_mod(v), depth);
988 : 5 : char *name = jl_symbol_name(jl_globalref_name(v));
989 [ + - ]: 5 : n += jl_printf(out, jl_is_identifier(name) ? ".%s" : ".:(%s)", name);
990 : : }
991 [ - + ]: 380 : else if (vt == jl_gotonode_type) {
992 : 0 : n += jl_printf(out, "goto %" PRIuPTR, jl_gotonode_label(v));
993 : : }
994 [ + + ]: 380 : else if (vt == jl_quotenode_type) {
995 : 1 : jl_value_t *qv = *(jl_value_t**)v;
996 [ - + ]: 1 : if (!jl_is_symbol(qv)) {
997 : 0 : n += jl_printf(out, "quote ");
998 : : }
999 : : else {
1000 : 1 : n += jl_printf(out, ":(");
1001 : : }
1002 : 1 : n += jl_static_show_x(out, qv, depth);
1003 [ - + ]: 1 : if (!jl_is_symbol(qv)) {
1004 : 0 : n += jl_printf(out, " end");
1005 : : }
1006 : : else {
1007 : 1 : n += jl_printf(out, ")");
1008 : : }
1009 : : }
1010 [ - + ]: 379 : else if (vt == jl_newvarnode_type) {
1011 : 0 : n += jl_printf(out, "<newvar ");
1012 : 0 : n += jl_static_show_x(out, *(jl_value_t**)v, depth);
1013 : 0 : n += jl_printf(out, ">");
1014 : : }
1015 [ - + ]: 379 : else if (vt == jl_linenumbernode_type) {
1016 : 0 : n += jl_printf(out, "#= ");
1017 : 0 : n += jl_static_show_x(out, jl_linenode_file(v), depth);
1018 : 0 : n += jl_printf(out, ":%" PRIuPTR " =#", jl_linenode_line(v));
1019 : : }
1020 [ + + ]: 379 : else if (vt == jl_expr_type) {
1021 : 7 : jl_expr_t *e = (jl_expr_t*)v;
1022 [ - + - - ]: 7 : if (e->head == jl_assign_sym && jl_array_len(e->args) == 2) {
1023 : 0 : n += jl_static_show_x(out, jl_exprarg(e,0), depth);
1024 : 0 : n += jl_printf(out, " = ");
1025 : 0 : n += jl_static_show_x(out, jl_exprarg(e,1), depth);
1026 : : }
1027 : : else {
1028 : 7 : char sep = ' ';
1029 : 7 : n += jl_printf(out, "Expr(:%s", jl_symbol_name(e->head));
1030 : 7 : size_t i, len = jl_array_len(e->args);
1031 [ + + ]: 28 : for (i = 0; i < len; i++) {
1032 : 21 : n += jl_printf(out, ",%c", sep);
1033 : 21 : n += jl_static_show_x(out, jl_exprarg(e,i), depth);
1034 : : }
1035 : 7 : n += jl_printf(out, ")");
1036 : : }
1037 : : }
1038 [ + - - + ]: 372 : else if (jl_array_type && jl_is_array_type(vt)) {
1039 : 0 : n += jl_printf(out, "Array{");
1040 : 0 : n += jl_static_show_x(out, (jl_value_t*)jl_tparam0(vt), depth);
1041 : 0 : n += jl_printf(out, ", (");
1042 : 0 : size_t i, ndims = jl_array_ndims(v);
1043 [ # # ]: 0 : if (ndims == 1)
1044 : 0 : n += jl_printf(out, "%" PRIdPTR ",", jl_array_dim0(v));
1045 : : else
1046 [ # # ]: 0 : for (i = 0; i < ndims; i++)
1047 [ # # ]: 0 : n += jl_printf(out, (i > 0 ? ", %" PRIdPTR : "%" PRIdPTR), jl_array_dim(v, i));
1048 : 0 : n += jl_printf(out, ")}[");
1049 : 0 : size_t j, tlen = jl_array_len(v);
1050 : 0 : jl_array_t *av = (jl_array_t*)v;
1051 : 0 : jl_value_t *el_type = jl_tparam0(vt);
1052 [ # # # # ]: 0 : char *typetagdata = (!av->flags.ptrarray && jl_is_uniontype(el_type)) ? jl_array_typetagdata(av) : NULL;
1053 : 0 : int nlsep = 0;
1054 [ # # ]: 0 : if (av->flags.ptrarray) {
1055 : : // print arrays with newlines, unless the elements are probably small
1056 [ # # ]: 0 : for (j = 0; j < tlen; j++) {
1057 : 0 : jl_value_t **ptr = ((jl_value_t**)av->data) + j;
1058 : 0 : jl_value_t *p = *ptr;
1059 [ # # # # ]: 0 : if (p != NULL && (uintptr_t)p >= 4096U) {
1060 : 0 : jl_value_t *p_ty = jl_typeof(p);
1061 [ # # ]: 0 : if ((uintptr_t)p_ty >= 4096U) {
1062 [ # # ]: 0 : if (!jl_isbits(p_ty)) {
1063 : 0 : nlsep = 1;
1064 : 0 : break;
1065 : : }
1066 : : }
1067 : : }
1068 : : }
1069 : : }
1070 [ # # # # ]: 0 : if (nlsep && tlen > 1)
1071 : 0 : n += jl_printf(out, "\n ");
1072 [ # # ]: 0 : for (j = 0; j < tlen; j++) {
1073 [ # # ]: 0 : if (av->flags.ptrarray) {
1074 : 0 : jl_value_t **ptr = ((jl_value_t**)av->data) + j;
1075 : 0 : n += jl_static_show_x(out, *ptr, depth);
1076 : : }
1077 : : else {
1078 : 0 : char *ptr = ((char*)av->data) + j * av->elsize;
1079 [ # # ]: 0 : n += jl_static_show_x_(out, (jl_value_t*)ptr,
1080 : 0 : typetagdata ? (jl_datatype_t*)jl_nth_union_component(el_type, typetagdata[j]) : (jl_datatype_t*)el_type,
1081 : : depth);
1082 : : }
1083 [ # # ]: 0 : if (j != tlen - 1)
1084 [ # # ]: 0 : n += jl_printf(out, nlsep ? ",\n " : ", ");
1085 : : }
1086 : 0 : n += jl_printf(out, "]");
1087 : : }
1088 [ - + ]: 372 : else if (vt == jl_loaderror_type) {
1089 : 0 : n += jl_printf(out, "LoadError(at ");
1090 : 0 : n += jl_static_show_x(out, *(jl_value_t**)v, depth);
1091 : : // Access the field directly to avoid allocation
1092 : 0 : n += jl_printf(out, " line %" PRIdPTR, ((intptr_t*)v)[1]);
1093 : 0 : n += jl_printf(out, ": ");
1094 : 0 : n += jl_static_show_x(out, ((jl_value_t**)v)[2], depth);
1095 : 0 : n += jl_printf(out, ")");
1096 : : }
1097 [ + + ]: 372 : else if (vt == jl_errorexception_type) {
1098 : 8 : n += jl_printf(out, "ErrorException(");
1099 : 8 : n += jl_static_show_x(out, *(jl_value_t**)v, depth);
1100 : 8 : n += jl_printf(out, ")");
1101 : : }
1102 [ + + + + ]: 368 : else if (jl_static_is_function_(vt) && is_globname_binding(v, (jl_datatype_t*)vt)) {
1103 : : // v is function instance (an instance of a Function type).
1104 : 4 : jl_datatype_t *dv = (jl_datatype_t*)vt;
1105 : : jl_sym_t *sym;
1106 : 4 : int globfunc = is_globfunction(v, dv, &sym);
1107 : 4 : int quote = 0;
1108 [ + - - + : 4 : if (jl_core_module && (dv->name->module != jl_core_module || !jl_module_exports_p(jl_core_module, sym))) {
- - ]
1109 : 4 : n += jl_static_show_x(out, (jl_value_t*)dv->name->module, depth);
1110 : 4 : n += jl_printf(out, ".");
1111 : :
1112 : 4 : size_t i = 0;
1113 : 4 : char *sn = jl_symbol_name(sym);
1114 [ + + + + ]: 4 : if (globfunc && !jl_id_start_char(u8_nextchar(sn, &i))) {
1115 : 2 : n += jl_printf(out, ":(");
1116 : 2 : quote = 1;
1117 : : }
1118 : : }
1119 : :
1120 : 4 : n += jl_static_show_x_sym_escaped(out, sym);
1121 : :
1122 [ + + ]: 4 : if (globfunc) {
1123 [ + + ]: 3 : if (quote) {
1124 : 2 : n += jl_printf(out, ")");
1125 : : }
1126 : : }
1127 : : }
1128 [ + - + - ]: 360 : else if (jl_datatype_type && jl_is_datatype(vt)) {
1129 : : // typeof(v) isa DataType, so v is an *instance of* a type that is a Datatype,
1130 : : // meaning v is e.g. an instance of a struct. These are printed as a call to a
1131 : : // type constructor, such as e.g. `Base.UnitRange{Int64}(start=1, stop=2)`
1132 : 360 : int istuple = jl_is_tuple_type(vt), isnamedtuple = jl_is_namedtuple_type(vt);
1133 : 360 : size_t tlen = jl_datatype_nfields(vt);
1134 [ - + ]: 360 : if (isnamedtuple) {
1135 [ # # ]: 0 : if (tlen == 0)
1136 : 0 : n += jl_printf(out, "NamedTuple");
1137 : : }
1138 [ + + ]: 360 : else if (!istuple) {
1139 : 13 : n += jl_static_show_x(out, (jl_value_t*)vt, depth);
1140 : : }
1141 : 360 : n += jl_printf(out, "(");
1142 : 360 : size_t nb = jl_datatype_size(vt);
1143 [ + + + + ]: 361 : if (nb > 0 && tlen == 0) {
1144 : 1 : uint8_t *data = (uint8_t*)v;
1145 : 1 : n += jl_printf(out, "0x");
1146 [ + + ]: 17 : for(int i = nb - 1; i >= 0; --i)
1147 : 16 : n += jl_printf(out, "%02" PRIx8, data[i]);
1148 : : }
1149 : : else {
1150 : 359 : size_t i = 0;
1151 [ - + ]: 359 : if (vt == jl_typemap_entry_type)
1152 : 0 : i = 1;
1153 [ - + ]: 359 : jl_value_t *names = isnamedtuple ? jl_tparam0(vt) : (jl_value_t*)jl_field_names(vt);
1154 [ + + ]: 1111 : for (; i < tlen; i++) {
1155 [ + + ]: 752 : if (!istuple) {
1156 [ - + ]: 17 : jl_value_t *fname = isnamedtuple ? jl_fieldref_noalloc(names, i) : jl_svecref(names, i);
1157 : 17 : n += jl_printf(out, "%s=", jl_symbol_name((jl_sym_t*)fname));
1158 : : }
1159 : 752 : size_t offs = jl_field_offset(vt, i);
1160 : 752 : char *fld_ptr = (char*)v + offs;
1161 [ + + ]: 752 : if (jl_field_isptr(vt, i)) {
1162 : 751 : n += jl_static_show_x(out, *(jl_value_t**)fld_ptr, depth);
1163 : : }
1164 : : else {
1165 : 1 : jl_datatype_t *ft = (jl_datatype_t*)jl_field_type_concrete(vt, i);
1166 [ - + ]: 1 : if (jl_is_uniontype(ft)) {
1167 : 0 : uint8_t sel = ((uint8_t*)fld_ptr)[jl_field_size(vt, i) - 1];
1168 : 0 : ft = (jl_datatype_t*)jl_nth_union_component((jl_value_t*)ft, sel);
1169 : : }
1170 : 1 : n += jl_static_show_x_(out, (jl_value_t*)fld_ptr, ft, depth);
1171 : : }
1172 [ + + - + : 752 : if ((istuple || isnamedtuple) && tlen == 1)
+ + ]
1173 : 153 : n += jl_printf(out, ",");
1174 [ + + ]: 599 : else if (i != tlen - 1)
1175 : 414 : n += jl_printf(out, ", ");
1176 : : }
1177 [ - + ]: 359 : if (vt == jl_typemap_entry_type) {
1178 : 0 : n += jl_printf(out, ", next=↩︎\n ");
1179 : 0 : jl_value_t *next = (jl_value_t*)jl_atomic_load_relaxed(&((jl_typemap_entry_t*)v)->next);
1180 : 0 : n += jl_static_show_next_(out, next, v, depth);
1181 : : }
1182 : : }
1183 : 360 : n += jl_printf(out, ")");
1184 : : }
1185 : : else {
1186 : 0 : n += jl_printf(out, "<?#%p::", (void*)v);
1187 : 0 : n += jl_static_show_x(out, (jl_value_t*)vt, depth);
1188 : 0 : n += jl_printf(out, ">");
1189 : : }
1190 : 20639 : return n;
1191 : : }
1192 : :
1193 : 24048 : static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, struct recur_list *depth) JL_NOTSAFEPOINT
1194 : : {
1195 : : // show values without calling a julia method or allocating through the GC
1196 : 24048 : return jl_static_show_next_(out, v, NULL, depth);
1197 : : }
1198 : :
1199 : 24048 : static size_t jl_static_show_next_(JL_STREAM *out, jl_value_t *v, jl_value_t *prev, struct recur_list *depth) JL_NOTSAFEPOINT
1200 : : {
1201 : : // helper for showing a typemap list by following the next pointers
1202 : : // while being careful about avoiding any recursion due to malformed (circular) references
1203 [ - + ]: 24048 : if (v == NULL) {
1204 : 0 : return jl_printf(out, "#<null>");
1205 : : }
1206 [ - + ]: 24048 : else if ((uintptr_t)v < 4096U) {
1207 : 0 : return jl_printf(out, "#<%d>", (int)(uintptr_t)v);
1208 : : }
1209 : 24048 : unsigned int dist = 1;
1210 : 24048 : struct recur_list this_item = {depth, v},
1211 : 24048 : *newdepth = &this_item,
1212 : 24048 : *p = depth;
1213 [ + + ]: 70041 : while (p) {
1214 [ - + - - ]: 45993 : if (jl_typeis(v, jl_typemap_entry_type) && newdepth == &this_item) {
1215 : 0 : jl_value_t *m = p->v;
1216 : 0 : unsigned nid = 1;
1217 [ # # # # ]: 0 : while (m && jl_typeis(m, jl_typemap_entry_type)) {
1218 [ # # ]: 0 : if (m == v) {
1219 : 0 : return jl_printf(out, "<typemap reference #%u @-%u ", nid, dist) +
1220 : 0 : jl_static_show_x(out, (jl_value_t*)((jl_typemap_entry_t*)m)->sig, depth) +
1221 : 0 : jl_printf(out, ">");
1222 : : }
1223 [ # # ]: 0 : if (m == prev) {
1224 : 0 : newdepth = depth;
1225 : 0 : break;
1226 : : }
1227 : : // verify that we aren't trying to follow a circular list
1228 : : // by following the list again, and ensuring this is the only link to next
1229 : 0 : jl_value_t *mnext = (jl_value_t*)jl_atomic_load_relaxed(&((jl_typemap_entry_t*)m)->next);
1230 : 0 : jl_value_t *m2 = p->v;
1231 [ # # ]: 0 : if (m2 == mnext)
1232 : 0 : break;
1233 [ # # # # ]: 0 : while (m2 && jl_typeis(m2, jl_typemap_entry_type)) {
1234 : 0 : jl_value_t *mnext2 = (jl_value_t*)jl_atomic_load_relaxed(&((jl_typemap_entry_t*)m2)->next);
1235 [ # # ]: 0 : if (mnext2 == mnext) {
1236 [ # # ]: 0 : if (m2 != m)
1237 : 0 : mnext = NULL;
1238 : 0 : break;
1239 : : }
1240 : 0 : m2 = mnext2;
1241 : : }
1242 : 0 : m = mnext;
1243 : 0 : nid++;
1244 : : }
1245 : : }
1246 [ - + ]: 45993 : if (p->v == v)
1247 : 0 : return jl_printf(out, "<circular reference @-%u>", dist);
1248 : 45993 : dist++;
1249 : 45993 : p = p->prev;
1250 : : }
1251 : 24048 : return jl_static_show_x_(out, v, (jl_datatype_t*)jl_typeof(v), newdepth);
1252 : : }
1253 : :
1254 : 2649 : JL_DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v) JL_NOTSAFEPOINT
1255 : : {
1256 : 2649 : return jl_static_show_x(out, v, 0);
1257 : : }
1258 : :
1259 : 19 : JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) JL_NOTSAFEPOINT
1260 : : {
1261 : 19 : size_t n = 0;
1262 : : size_t i;
1263 : 19 : jl_value_t *ftype = (jl_value_t*)jl_first_argument_datatype(type);
1264 [ + + ]: 19 : if (ftype == NULL)
1265 : 5 : return jl_static_show(s, type);
1266 : 14 : jl_unionall_t *tvars = (jl_unionall_t*)type;
1267 : 14 : int nvars = jl_subtype_env_size(type);
1268 : 14 : struct recur_list *depth = NULL;
1269 [ + + ]: 14 : if (nvars > 0) {
1270 : 1 : depth = (struct recur_list*)alloca(sizeof(struct recur_list) * nvars);
1271 [ + + ]: 3 : for (i = 0; i < nvars; i++) {
1272 [ + + ]: 2 : depth[i].prev = i == 0 ? NULL : &depth[i - 1];
1273 : 2 : depth[i].v = type;
1274 : 2 : type = ((jl_unionall_t*)type)->body;
1275 : : }
1276 : 1 : depth += nvars - 1;
1277 : : }
1278 [ - + ]: 14 : if (!jl_is_datatype(type)) {
1279 : 0 : n += jl_static_show(s, type);
1280 : 0 : return n;
1281 : : }
1282 [ - + - - ]: 14 : if (jl_nparams(ftype) == 0 || ftype == ((jl_datatype_t*)ftype)->name->wrapper) {
1283 : 14 : n += jl_printf(s, "%s", jl_symbol_name(((jl_datatype_t*)ftype)->name->mt->name));
1284 : : }
1285 : : else {
1286 : 0 : n += jl_printf(s, "(::");
1287 : 0 : n += jl_static_show_x(s, ftype, depth);
1288 : 0 : n += jl_printf(s, ")");
1289 : : }
1290 : 14 : size_t tl = jl_nparams(type);
1291 : 14 : n += jl_printf(s, "(");
1292 [ + + ]: 21 : for (i = 1; i < tl; i++) {
1293 : 7 : jl_value_t *tp = jl_tparam(type, i);
1294 [ + + ]: 7 : if (i != tl - 1) {
1295 : 1 : n += jl_static_show_x(s, tp, depth);
1296 : 1 : n += jl_printf(s, ", ");
1297 : : }
1298 : : else {
1299 [ + + ]: 6 : if (jl_vararg_kind(tp) == JL_VARARG_UNBOUND) {
1300 : 1 : tp = jl_unwrap_vararg(tp);
1301 [ - + ]: 1 : if (jl_is_unionall(tp))
1302 : 0 : n += jl_printf(s, "(");
1303 : 1 : n += jl_static_show_x(s, tp, depth);
1304 [ - + ]: 1 : if (jl_is_unionall(tp))
1305 : 0 : n += jl_printf(s, ")");
1306 : 1 : n += jl_printf(s, "...");
1307 : : }
1308 : : else {
1309 : 5 : n += jl_static_show_x(s, tp, depth);
1310 : : }
1311 : : }
1312 : : }
1313 : 14 : n += jl_printf(s, ")");
1314 [ + + ]: 14 : if (jl_is_unionall(tvars)) {
1315 : 1 : depth -= nvars - 1;
1316 : 1 : int first = 1;
1317 : 1 : n += jl_printf(s, " where {");
1318 [ + + ]: 3 : while (jl_is_unionall(tvars)) {
1319 [ + + ]: 2 : if (!first)
1320 : 1 : n += jl_printf(s, ", ");
1321 [ + + ]: 2 : n += jl_static_show_x(s, (jl_value_t*)tvars->var, first ? NULL : depth);
1322 : 2 : tvars = (jl_unionall_t*)tvars->body;
1323 [ + + ]: 2 : if (!first)
1324 : 1 : depth += 1;
1325 : 2 : first = 0;
1326 : : }
1327 : 1 : n += jl_printf(s, "}");
1328 : : }
1329 : 14 : return n;
1330 : : }
1331 : :
1332 : 0 : JL_DLLEXPORT void jl_(void *jl_value) JL_NOTSAFEPOINT
1333 : : {
1334 : 0 : jl_jmp_buf *old_buf = jl_get_safe_restore();
1335 : : jl_jmp_buf buf;
1336 : 0 : jl_set_safe_restore(&buf);
1337 [ # # ]: 0 : if (!jl_setjmp(buf, 0)) {
1338 : 0 : jl_static_show((JL_STREAM*)STDERR_FILENO, (jl_value_t*)jl_value);
1339 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO,"\n");
1340 : : }
1341 : : else {
1342 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "\n!!! ERROR in jl_ -- ABORTING !!!\n");
1343 : : }
1344 : 0 : jl_set_safe_restore(old_buf);
1345 : 0 : }
1346 : :
1347 : 5 : JL_DLLEXPORT void jl_breakpoint(jl_value_t *v)
1348 : : {
1349 : : // put a breakpoint in your debugger here
1350 : 5 : }
1351 : :
1352 : 103 : JL_DLLEXPORT void jl_test_failure_breakpoint(jl_value_t *v)
1353 : : {
1354 : : // put a breakpoint in your debugger here
1355 : 103 : }
1356 : :
1357 : : // logging tools --------------------------------------------------------------
1358 : :
1359 : 0 : void jl_log(int level, jl_value_t *module, jl_value_t *group, jl_value_t *id,
1360 : : jl_value_t *file, jl_value_t *line, jl_value_t *kwargs,
1361 : : jl_value_t *msg)
1362 : : {
1363 : : static jl_value_t *logmsg_func = NULL;
1364 [ # # # # ]: 0 : if (!logmsg_func && jl_base_module) {
1365 : 0 : jl_value_t *corelogging = jl_get_global(jl_base_module, jl_symbol("CoreLogging"));
1366 [ # # # # ]: 0 : if (corelogging && jl_is_module(corelogging)) {
1367 : 0 : logmsg_func = jl_get_global((jl_module_t*)corelogging, jl_symbol("logmsg_shim"));
1368 : : }
1369 : : }
1370 [ # # ]: 0 : if (!logmsg_func) {
1371 : : ios_t str_;
1372 : 0 : ios_mem(&str_, 300);
1373 : 0 : JL_STREAM* str = (JL_STREAM*)&str_;
1374 [ # # ]: 0 : if (jl_is_string(msg)) {
1375 : 0 : jl_uv_puts(str, jl_string_data(msg), jl_string_len(msg));
1376 : : }
1377 [ # # ]: 0 : else if (jl_is_symbol(msg)) {
1378 : 0 : jl_printf(str, "%s", jl_symbol_name((jl_sym_t*)msg));
1379 : : }
1380 : 0 : jl_printf(str, "\n@ ");
1381 [ # # ]: 0 : if (jl_is_string(file)) {
1382 : 0 : jl_uv_puts(str, jl_string_data(file), jl_string_len(file));
1383 : : }
1384 [ # # ]: 0 : else if (jl_is_symbol(file)) {
1385 : 0 : jl_printf(str, "%s", jl_symbol_name((jl_sym_t*)file));
1386 : : }
1387 : 0 : jl_printf(str, ":");
1388 : 0 : jl_static_show(str, line);
1389 : 0 : jl_safe_printf("%s [Fallback logging]: %.*s\n",
1390 : : level < JL_LOGLEVEL_INFO ? "Debug" :
1391 [ # # ]: 0 : level < JL_LOGLEVEL_WARN ? "Info" :
1392 [ # # ]: 0 : level < JL_LOGLEVEL_ERROR ? "Warning" : "Error",
1393 [ # # ]: 0 : (int)str_.size, str_.buf);
1394 : 0 : ios_close(&str_);
1395 : 0 : return;
1396 : : }
1397 : : jl_value_t **args;
1398 : 0 : const int nargs = 9;
1399 : 0 : JL_GC_PUSHARGS(args, nargs);
1400 : 0 : args[0] = logmsg_func;
1401 : 0 : args[1] = jl_box_long(level);
1402 : 0 : args[2] = msg;
1403 : : // Would some of the jl_nothing here be better as `missing` instead?
1404 [ # # ]: 0 : args[3] = module ? module : jl_nothing;
1405 [ # # ]: 0 : args[4] = group ? group : jl_nothing;
1406 [ # # ]: 0 : args[5] = id ? id : jl_nothing;
1407 [ # # ]: 0 : args[6] = file ? file : jl_nothing;
1408 [ # # ]: 0 : args[7] = line ? line : jl_nothing;
1409 [ # # ]: 0 : args[8] = kwargs ? kwargs : (jl_value_t*)jl_alloc_vec_any(0);
1410 : 0 : jl_apply(args, nargs);
1411 : 0 : JL_GC_POP();
1412 : : }
1413 : :
1414 : : #ifdef __cplusplus
1415 : : }
1416 : : #endif
|