File Coverage

pl_console.c
Criterion Covered Total %
statement 45 47 95.7
branch 12 16 75.0
condition n/a
subroutine n/a
pod n/a
total 57 63 90.4


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(pTHX_ duk_uint_t flags,
14             const char* fmt, va_list ap)
15             {
16 29 100         PerlIO* fp = (flags & DUK_CONSOLE_TO_STDERR) ? PerlIO_stderr() : PerlIO_stdout();
17 29           int ret = PerlIO_vprintf(fp, fmt, ap);
18              
19 29 50         if (flags & DUK_CONSOLE_FLUSH) {
20 29           PerlIO_flush(fp);
21             }
22 29           return ret;
23             }
24              
25              
26              
27 106           static void save_msg(pTHX_ Duk* duk, const char* target, SV* message)
28             {
29 106           STRLEN tlen = strlen(target);
30 106           AV* data = 0;
31 106           int top = 0;
32 106           SV* pvalue = 0;
33 106           SV** found = hv_fetch(duk->msgs, target, tlen, 0);
34 106 100         if (found) {
35 4           SV* ref = SvRV(*found);
36             /* value not a valid arrayref? bail out */
37 4 50         if (SvTYPE(ref) != SVt_PVAV) {
38 0           return;
39             }
40 4           data = (AV*) ref;
41 4           top = av_len(data);
42             } else {
43 102           SV* ref = 0;
44 102           data = newAV();
45 102           ref = newRV_noinc((SV*) data);
46 102 50         if (hv_store(duk->msgs, target, tlen, ref, 0)) {
47 102           SvREFCNT_inc(ref);
48             }
49 102           top = -1;
50             }
51              
52 106           pvalue = sv_2mortal(message);
53 106 50         if (av_store(data, ++top, pvalue)) {
54 106           SvREFCNT_inc(pvalue);
55             }
56             else {
57 0           croak("Could not store message in target %*.*s\n", (int) tlen, (int) tlen, target);
58             }
59             }
60              
61              
62 106           static int save_console_messages(pTHX_ Duk* duk,duk_uint_t flags,
63             const char* fmt, va_list ap)
64             {
65 106 100         const char* target = (flags & DUK_CONSOLE_TO_STDERR) ? "stderr" : "stdout";
66 106           SV* message = newSVpvs("");
67             va_list args_copy;
68 106           va_copy(args_copy, ap);
69 106           sv_vcatpvf(message, fmt, &args_copy);
70 106           save_msg(aTHX_ duk, target, message);
71 106           return SvCUR(message);
72             }
73              
74 135           int pl_console_callback(void* data, duk_uint_t flags,const char* fmt, va_list ap)
75             {
76             dTHX;
77 135           Duk* duk = (Duk*) data;
78              
79 135 100         if (duk->flags & DUK_OPT_FLAG_SAVE_MESSAGES) {
80 106           return save_console_messages(aTHX_ duk,flags,fmt,ap);
81             }
82             else {
83 29           return print_console_messages(aTHX_ flags,fmt,ap);
84             }
85             }
86              
87 373           int pl_console_init(Duk* duk)
88             {
89             /* initialize console object */
90 373           duk_console_init(duk->ctx, DUK_CONSOLE_PROXY_WRAPPER | DUK_CONSOLE_FLUSH);
91            
92             /* save our duk pointer to the ctx so it can get it back later when we do callbacks */
93 373           duk_push_thread_stash(duk->ctx,duk->ctx);
94 373           duk_push_pointer(duk->ctx, duk);
95 373           duk_put_prop_string(duk->ctx, -2, PL_NAME_CONSOLE_GENERIC_CALLBACK);
96 373           duk_pop(duk->ctx);
97              
98 373           return 0;
99             }