1 ################################################################################
3 ## Copyright (C) 2017, Pali <pali@cpan.org>
5 ## This program is free software; you can redistribute it and/or
6 ## modify it under the same terms as Perl itself.
8 ################################################################################
44 #define NEED_mess_nocontext
49 #if { VERSION >= 5.7.3 } || ( { VERSION >= 5.6.1 } && { VERSION < 5.7.0 } )
50 # if ( { VERSION >= 5.8.0 } && { VERSION < 5.8.9 } ) || ( { VERSION >= 5.9.0 } && { VERSION < 5.10.1 } )
51 # define D_PPP_FIX_UTF8_ERRSV_FOR_SV(sv) \
54 SvFLAGS(_errsv) = (SvFLAGS(_errsv) & ~SVf_UTF8) | \
55 (SvFLAGS(sv) & SVf_UTF8); \
58 # define D_PPP_FIX_UTF8_ERRSV_FOR_SV(sv) STMT_START {} STMT_END
60 # define croak_sv(sv) \
64 sv_setsv(ERRSV, _sv); \
67 D_PPP_FIX_UTF8_ERRSV_FOR_SV(_sv); \
68 croak("%" SVf, SVfARG(_sv)); \
71 #elif { VERSION >= 5.4.0 }
72 # define croak_sv(sv) croak("%" SVf, SVfARG(sv))
74 # define croak_sv(sv) croak("%s", SvPV_nolen(sv))
81 die_sv(pTHX_ SV *baseex)
90 #if { VERSION >= 5.4.0 }
91 # define warn_sv(sv) warn("%" SVf, SVfARG(sv))
93 # define warn_sv(sv) warn("%s", SvPV_nolen(sv))
97 #if ! defined vmess && { VERSION >= 5.4.0 }
101 vmess(pTHX_ const char* pat, va_list* args)
109 #if { VERSION < 5.6.0 } && { VERSION >= 5.4.0 }
113 #if !defined(mess_nocontext) && !defined(Perl_mess_nocontext) && { VERSION >= 5.4.0 }
114 #if { NEED mess_nocontext }
116 mess_nocontext(const char* pat, ...)
122 sv = vmess(pat, &args);
132 mess(pTHX_ const char* pat, ...)
137 sv = vmess(pat, &args);
141 #ifdef mess_nocontext
142 #define mess mess_nocontext
144 #define mess Perl_mess_nocontext
149 #if ! defined mess_sv && { VERSION >= 5.4.0 }
152 mess_sv(pTHX_ SV *basemsg, bool consume)
157 if (SvPOK(basemsg) && SvCUR(basemsg) && *(SvEND(basemsg)-1) == '\n') {
161 SvSetSV_nosteal(ret, basemsg);
166 sv_catsv(basemsg, mess(""));
172 SvSetSV_nosteal(ret, basemsg);
180 #ifndef warn_nocontext
181 #define warn_nocontext warn
184 #ifndef croak_nocontext
185 #define croak_nocontext croak
188 #ifndef croak_no_modify
189 #define croak_no_modify() croak_nocontext("%s", PL_no_modify)
190 #define Perl_croak_no_modify() croak_no_modify()
193 #ifndef croak_memory_wrap
194 #if { VERSION >= 5.9.2 } || ( { VERSION >= 5.8.6 } && { VERSION < 5.9.0 } )
195 # define croak_memory_wrap() croak_nocontext("%s", PL_memory_wrap)
197 # define croak_memory_wrap() croak_nocontext("panic: memory wrap")
201 #ifndef croak_xs_usage
202 #if { NEED croak_xs_usage }
206 croak_xs_usage(const CV *const cv, const char *const params)
209 const GV *const gv = CvGV(cv);
211 #ifdef PERL_ARGS_ASSERT_CROAK_XS_USAGE
212 PERL_ARGS_ASSERT_CROAK_XS_USAGE;
214 assert(cv); assert(params);
218 const char *const gvname = GvNAME(gv);
219 const HV *const stash = GvSTASH(gv);
220 const char *const hvname = stash ? HvNAME(stash) : NULL;
223 croak("Usage: %s::%s(%s)", hvname, gvname, params);
225 croak("Usage: %s(%s)", gvname, params);
227 /* Pants. I don't think that it should be possible to get here. */
228 croak("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
238 #define NEED_croak_xs_usage
243 static void reset_counter(void) { counter = 0; }
244 static void inc_counter(void) { counter++; }
260 croak_sv_with_counter(sv)
264 croak_sv((inc_counter(), sv));
285 #if { VERSION >= 5.4.0 }
292 RETVAL = newSVsv(mess_sv(sv, consume));
309 croak_xs_usage(params)
312 croak_xs_usage(cv, params);
316 BEGIN { if ("$]" < '5.006') { $^W = 0; } }
320 local $SIG{__WARN__} = sub { $warn = $_[0] };
321 local $SIG{__DIE__} = sub { $die = $_[0] };
323 my $scalar_ref = \do {my $tmp = 10};
326 my $obj = bless {}, 'Package';
329 ok !defined eval { Devel::PPPort::croak_sv("\xE1\n") };
334 ok !defined eval { Devel::PPPort::croak_sv(10) };
335 ok $@ =~ /^10 at $0 line /;
336 ok $die =~ /^10 at $0 line /;
339 $@ = 'should not be visible (1)';
341 $@ = 'should not be visible (2)';
342 Devel::PPPort::croak_sv('');
344 ok $@ =~ /^ at $0 line /;
345 ok $die =~ /^ at $0 line /;
348 $@ = 'should not be visible';
350 $@ = 'this must be visible';
351 Devel::PPPort::croak_sv($@)
353 ok $@ =~ /^this must be visible at $0 line /;
354 ok $die =~ /^this must be visible at $0 line /;
357 $@ = 'should not be visible';
359 $@ = "this must be visible\n";
360 Devel::PPPort::croak_sv($@)
362 ok $@, "this must be visible\n";
363 ok $die, "this must be visible\n";
366 $@ = 'should not be visible';
368 $@ = 'this must be visible';
369 Devel::PPPort::croak_sv_errsv()
371 ok $@ =~ /^this must be visible at $0 line /;
372 ok $die =~ /^this must be visible at $0 line /;
375 $@ = 'should not be visible';
377 $@ = "this must be visible\n";
378 Devel::PPPort::croak_sv_errsv()
380 ok $@, "this must be visible\n";
381 ok $die, "this must be visible\n";
384 ok !defined eval { Devel::PPPort::croak_sv_with_counter("message\n") };
386 ok Devel::PPPort::get_counter(), 1;
389 ok !defined eval { Devel::PPPort::croak_sv('') };
390 ok $@ =~ /^ at $0 line /;
391 ok $die =~ /^ at $0 line /;
394 ok !defined eval { Devel::PPPort::croak_sv("\xE1") };
395 ok $@ =~ /^\xE1 at $0 line /;
396 ok $die =~ /^\xE1 at $0 line /;
399 ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1") };
400 ok $@ =~ /^\xC3\xA1 at $0 line /;
401 ok $die =~ /^\xC3\xA1 at $0 line /;
404 Devel::PPPort::warn_sv("\xE1\n");
408 Devel::PPPort::warn_sv(10);
409 ok $warn =~ /^10 at $0 line /;
412 Devel::PPPort::warn_sv('');
413 ok $warn =~ /^ at $0 line /;
416 Devel::PPPort::warn_sv("\xE1");
417 ok $warn =~ /^\xE1 at $0 line /;
420 Devel::PPPort::warn_sv("\xC3\xA1");
421 ok $warn =~ /^\xC3\xA1 at $0 line /;
423 ok Devel::PPPort::mess_sv("\xE1\n", 0), "\xE1\n";
424 ok Devel::PPPort::mess_sv(do {my $tmp = "\xE1\n"}, 1), "\xE1\n";
426 ok Devel::PPPort::mess_sv(10, 0) =~ /^10 at $0 line /;
427 ok Devel::PPPort::mess_sv(do {my $tmp = 10}, 1) =~ /^10 at $0 line /;
429 ok Devel::PPPort::mess_sv('', 0) =~ /^ at $0 line /;
430 ok Devel::PPPort::mess_sv(do {my $tmp = ''}, 1) =~ /^ at $0 line /;
432 ok Devel::PPPort::mess_sv("\xE1", 0) =~ /^\xE1 at $0 line /;
433 ok Devel::PPPort::mess_sv(do {my $tmp = "\xE1"}, 1) =~ /^\xE1 at $0 line /;
435 ok Devel::PPPort::mess_sv("\xC3\xA1", 0) =~ /^\xC3\xA1 at $0 line /;
436 ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1"}, 1) =~ /^\xC3\xA1 at $0 line /;
438 if ("$]" >= '5.006') {
439 BEGIN { if ("$]" >= '5.006' && "$]" < '5.008') { require utf8; utf8->import(); } }
442 ok !defined eval { Devel::PPPort::croak_sv("\x{100}\n") };
443 if ("$]" < '5.007001' || "$]" > '5.007003') {
446 skip 'skip: broken utf8 support in die hook', 0;
448 if ("$]" < '5.007001' || "$]" > '5.008') {
449 ok $die, "\x{100}\n";
451 skip 'skip: broken utf8 support in die hook', 0;
455 ok !defined eval { Devel::PPPort::croak_sv("\x{100}") };
456 if ("$]" < '5.007001' || "$]" > '5.007003') {
457 ok $@ =~ /^\x{100} at $0 line /;
459 skip 'skip: broken utf8 support in die hook', 0;
461 if ("$]" < '5.007001' || "$]" > '5.008') {
462 ok $die =~ /^\x{100} at $0 line /;
464 skip 'skip: broken utf8 support in die hook', 0;
467 if ("$]" < '5.007001' || "$]" > '5.008') {
469 Devel::PPPort::warn_sv("\x{100}\n");
470 ok $warn, "\x{100}\n";
473 Devel::PPPort::warn_sv("\x{100}");
474 ok (my $tmp = $warn) =~ /^\x{100} at $0 line /;
477 skip 'skip: broken utf8 support in warn hook', 0;
481 ok Devel::PPPort::mess_sv("\x{100}\n", 0), "\x{100}\n";
482 ok Devel::PPPort::mess_sv(do {my $tmp = "\x{100}\n"}, 1), "\x{100}\n";
484 ok Devel::PPPort::mess_sv("\x{100}", 0) =~ /^\x{100} at $0 line /;
485 ok Devel::PPPort::mess_sv(do {my $tmp = "\x{100}"}, 1) =~ /^\x{100} at $0 line /;
488 skip 'skip: no utf8 support', 0;
492 if (ord('A') != 65) {
494 skip 'skip: no ASCII support', 0;
496 } elsif ( "$]" >= '5.008'
497 && "$]" != '5.013000' # Broken in these ranges
498 && ! ("$]" >= '5.011005' && "$]" <= '5.012000'))
501 ok !defined eval { Devel::PPPort::croak_sv(eval '"\N{U+E1}\n"') };
506 ok !defined eval { Devel::PPPort::croak_sv(eval '"\N{U+E1}"') };
507 ok $@ =~ /^\xE1 at $0 line /;
508 ok $die =~ /^\xE1 at $0 line /;
512 my $expect = eval '"\N{U+C3}\N{U+A1}\n"';
513 ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1\n") };
520 my $expect = eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
521 ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1") };
527 Devel::PPPort::warn_sv(eval '"\N{U+E1}\n"');
531 Devel::PPPort::warn_sv(eval '"\N{U+E1}"');
532 ok $warn =~ /^\xE1 at $0 line /;
535 Devel::PPPort::warn_sv("\xC3\xA1\n");
536 ok $warn, eval '"\N{U+C3}\N{U+A1}\n"';
539 Devel::PPPort::warn_sv("\xC3\xA1");
540 ok $warn =~ eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
542 if ("$]" < '5.004') {
544 skip 'skip: no support for mess_sv', 0;
548 ok Devel::PPPort::mess_sv(eval('"\N{U+E1}\n"'), 0), eval '"\N{U+E1}\n"';
549 ok Devel::PPPort::mess_sv(do {my $tmp = eval '"\N{U+E1}\n"'}, 1), eval '"\N{U+E1}\n"';
551 ok Devel::PPPort::mess_sv(eval('"\N{U+E1}"'), 0) =~ eval 'qr/^\N{U+E1} at $0 line /';
552 ok Devel::PPPort::mess_sv(do {my $tmp = eval '"\N{U+E1}"'}, 1) =~ eval 'qr/^\N{U+E1} at $0 line /';
554 ok Devel::PPPort::mess_sv("\xC3\xA1\n", 0), eval '"\N{U+C3}\N{U+A1}\n"';
555 ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1\n"}, 1), eval '"\N{U+C3}\N{U+A1}\n"';
557 ok Devel::PPPort::mess_sv("\xC3\xA1", 0) =~ eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
558 ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1"}, 1) =~ eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
562 skip 'skip: no support for \N{U+..} syntax', 0;
566 if ("$]" >= '5.007003' or ("$]" >= '5.006001' and "$]" < '5.007')) {
568 ok !defined eval { Devel::PPPort::croak_sv($scalar_ref) };
569 ok $@ == $scalar_ref;
570 ok $die == $scalar_ref;
573 ok !defined eval { Devel::PPPort::croak_sv($array_ref) };
575 ok $die == $array_ref;
578 ok !defined eval { Devel::PPPort::croak_sv($hash_ref) };
580 ok $die == $hash_ref;
583 ok !defined eval { Devel::PPPort::croak_sv($obj) };
588 skip 'skip: no support for exceptions', 0;
592 ok !defined eval { Devel::PPPort::croak_no_modify() };
593 ok $@ =~ /^Modification of a read-only value attempted at $0 line /;
595 ok !defined eval { Devel::PPPort::croak_memory_wrap() };
596 ok $@ =~ /^panic: memory wrap at $0 line /;
598 ok !defined eval { Devel::PPPort::croak_xs_usage("params") };
599 ok $@ =~ /^Usage: Devel::PPPort::croak_xs_usage\(params\) at $0 line /;