File Coverage

pl_console.c
Criterion Covered Total %
statement 40 42 95.2
branch 12 16 75.0
condition n/a
subroutine n/a
pod n/a
total 52 58 89.6


line stmt bran cond sub pod time code
1             #include
2             #include "duk_console.h"
3             #include "pl_util.h"
4             #include "pl_console.h"
5              
6             #define NEED_newRV_noinc_GLOBAL
7             #include "ppport.h"
8              
9             #if !defined(va_copy)
10             #define va_copy(dest, src) __va_copy(dest, src)
11             #endif
12              
13 29           static int print_console_messages(duk_uint_t flags, void* data,
14             const char* fmt, va_list ap)
15             {
16             dTHX;
17 29 100         PerlIO* fp = (flags & DUK_CONSOLE_TO_STDERR) ? PerlIO_stderr() : PerlIO_stdout();
18 29           int ret = PerlIO_vprintf(fp, fmt, ap);
19              
20             UNUSED_ARG(data);
21 29 50         if (flags & DUK_CONSOLE_FLUSH) {
22 29           PerlIO_flush(fp);
23             }
24 29           return ret;
25             }
26              
27              
28 6           static void save_msg(pTHX_ Duk* duk, const char* target, SV* message)
29             {
30 6           STRLEN tlen = strlen(target);
31 6           AV* data = 0;
32 6           int top = 0;
33 6           SV* pvalue = 0;
34 6           SV** found = hv_fetch(duk->msgs, target, tlen, 0);
35 6 100         if (found) {
36 4           SV* ref = SvRV(*found);
37             /* value not a valid arrayref? bail out */
38 4 50         if (SvTYPE(ref) != SVt_PVAV) {
39 0           return;
40             }
41 4           data = (AV*) ref;
42 4           top = av_len(data);
43             } else {
44 2           SV* ref = 0;
45 2           data = newAV();
46 2           ref = newRV_noinc((SV*) data);
47 2 50         if (hv_store(duk->msgs, target, tlen, ref, 0)) {
48 2           SvREFCNT_inc(ref);
49             }
50 2           top = -1;
51             }
52              
53 6           pvalue = sv_2mortal(message);
54 6 50         if (av_store(data, ++top, pvalue)) {
55 6           SvREFCNT_inc(pvalue);
56             }
57             else {
58 0           croak("Could not store message in target %*.*s\n", (int) tlen, (int) tlen, target);
59             }
60             }
61              
62 6           static int save_console_messages(duk_uint_t flags, void* data,
63             const char* fmt, va_list ap)
64             {
65             dTHX;
66 6           Duk* duk = (Duk*) data;
67 6 100         const char* target = (flags & DUK_CONSOLE_TO_STDERR) ? "stderr" : "stdout";
68 6           SV* message = newSVpvs("");
69             va_list args_copy;
70 6           va_copy(args_copy, ap);
71 6           sv_vcatpvf(message, fmt, &args_copy);
72 6           save_msg(aTHX_ duk, target, message);
73 6           return SvCUR(message);
74             }
75              
76 262           int pl_console_init(Duk* duk)
77             {
78             /* initialize console object */
79 262           duk_console_init(duk->ctx, DUK_CONSOLE_PROXY_WRAPPER | DUK_CONSOLE_FLUSH);
80              
81 262 100         if (duk->flags & DUK_OPT_FLAG_SAVE_MESSAGES) {
82 1           duk_console_register_handler(save_console_messages, duk);
83             }
84             else {
85 261           duk_console_register_handler(print_console_messages, duk);
86             }
87              
88 262           return 0;
89             }