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 ################################################################################
24 PERL_ARGS_ASSERT_CROAK_XS_USAGE
45 #define NEED_mess_nocontext
50 #if { VERSION >= 5.7.3 } || ( { VERSION >= 5.6.1 } && { VERSION < 5.7.0 } )
51 # if ( { VERSION >= 5.8.0 } && { VERSION < 5.8.9 } ) || ( { VERSION >= 5.9.0 } && { VERSION < 5.10.1 } )
52 # define D_PPP_FIX_UTF8_ERRSV_FOR_SV(sv) \
55 SvFLAGS(_errsv) = (SvFLAGS(_errsv) & ~SVf_UTF8) | \
56 (SvFLAGS(sv) & SVf_UTF8); \
59 # define D_PPP_FIX_UTF8_ERRSV_FOR_SV(sv) STMT_START {} STMT_END
61 # define croak_sv(sv) \
65 sv_setsv(ERRSV, _sv); \
68 D_PPP_FIX_UTF8_ERRSV_FOR_SV(_sv); \
69 croak("%" SVf, SVfARG(_sv)); \
72 #elif { VERSION >= 5.4.0 }
73 # define croak_sv(sv) croak("%" SVf, SVfARG(sv))
75 # define croak_sv(sv) croak("%s", SvPV_nolen(sv))
82 die_sv(pTHX_ SV *baseex)
91 #if { VERSION >= 5.4.0 }
92 # define warn_sv(sv) warn("%" SVf, SVfARG(sv))
94 # define warn_sv(sv) warn("%s", SvPV_nolen(sv))
98 #if ! defined vmess && { VERSION >= 5.4.0 }
102 vmess(pTHX_ const char* pat, va_list* args)
110 #if { VERSION < 5.6.0 } && { VERSION >= 5.4.0 }
114 #if !defined(mess_nocontext) && !defined(Perl_mess_nocontext) && { VERSION >= 5.4.0 }
115 #if { NEED mess_nocontext }
117 mess_nocontext(const char* pat, ...)
123 sv = vmess(pat, &args);
133 mess(pTHX_ const char* pat, ...)
138 sv = vmess(pat, &args);
142 #ifdef mess_nocontext
143 #define mess mess_nocontext
145 #define mess Perl_mess_nocontext
150 #if ! defined mess_sv && { VERSION >= 5.4.0 }
153 mess_sv(pTHX_ SV *basemsg, bool consume)
158 if (SvPOK(basemsg) && SvCUR(basemsg) && *(SvEND(basemsg)-1) == '\n') {
162 SvSetSV_nosteal(ret, basemsg);
167 sv_catsv(basemsg, mess(""));
173 SvSetSV_nosteal(ret, basemsg);
181 #ifndef warn_nocontext
182 #define warn_nocontext warn
185 #ifndef croak_nocontext
186 #define croak_nocontext croak
189 #ifndef croak_no_modify
190 #define croak_no_modify() croak_nocontext("%s", PL_no_modify)
191 #define Perl_croak_no_modify() croak_no_modify()
194 #ifndef croak_memory_wrap
195 #if { VERSION >= 5.9.2 } || ( { VERSION >= 5.8.6 } && { VERSION < 5.9.0 } )
196 # define croak_memory_wrap() croak_nocontext("%s", PL_memory_wrap)
198 # define croak_memory_wrap() croak_nocontext("panic: memory wrap")
202 #ifndef croak_xs_usage
203 #if { NEED croak_xs_usage }
204 #ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
205 #define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)
208 croak_xs_usage(const CV *const cv, const char *const params)
211 const GV *const gv = CvGV(cv);
213 PERL_ARGS_ASSERT_CROAK_XS_USAGE;
216 const char *const gvname = GvNAME(gv);
217 const HV *const stash = GvSTASH(gv);
218 const char *const hvname = stash ? HvNAME(stash) : NULL;
221 croak("Usage: %s::%s(%s)", hvname, gvname, params);
223 croak("Usage: %s(%s)", gvname, params);
225 /* Pants. I don't think that it should be possible to get here. */
226 croak("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
237 #define NEED_croak_xs_usage
242 static void reset_counter(void) { counter = 0; }
243 static void inc_counter(void) { counter++; }
259 croak_sv_with_counter(sv)
263 croak_sv((inc_counter(), sv));
284 #if { VERSION >= 5.4.0 }
291 RETVAL = newSVsv(mess_sv(sv, consume));
308 croak_xs_usage(params)
311 croak_xs_usage(cv, params);
315 BEGIN { if (ivers($]) < ivers('5.006')) { $^W = 0; } }
319 local $SIG{__WARN__} = sub { $warn = $_[0] };
320 local $SIG{__DIE__} = sub { $die = $_[0] };
322 my $scalar_ref = \do {my $tmp = 10};
325 my $obj = bless {}, 'Package';
328 ok !defined eval { Devel::PPPort::croak_sv("\xE1\n") };
333 ok !defined eval { Devel::PPPort::croak_sv(10) };
334 ok $@ =~ /^10 at \Q$0\E line /;
335 ok $die =~ /^10 at \Q$0\E line /;
338 $@ = 'should not be visible (1)';
340 $@ = 'should not be visible (2)';
341 Devel::PPPort::croak_sv('');
343 ok $@ =~ /^ at \Q$0\E line /;
344 ok $die =~ /^ at \Q$0\E line /;
347 $@ = 'should not be visible';
349 $@ = 'this must be visible';
350 Devel::PPPort::croak_sv($@)
352 ok $@ =~ /^this must be visible at \Q$0\E line /;
353 ok $die =~ /^this must be visible at \Q$0\E line /;
356 $@ = 'should not be visible';
358 $@ = "this must be visible\n";
359 Devel::PPPort::croak_sv($@)
361 is $@, "this must be visible\n";
362 is $die, "this must be visible\n";
365 $@ = 'should not be visible';
367 $@ = 'this must be visible';
368 Devel::PPPort::croak_sv_errsv()
370 ok $@ =~ /^this must be visible at \Q$0\E line /;
371 ok $die =~ /^this must be visible at \Q$0\E line /;
374 $@ = 'should not be visible';
376 $@ = "this must be visible\n";
377 Devel::PPPort::croak_sv_errsv()
379 is $@, "this must be visible\n";
380 is $die, "this must be visible\n";
383 ok !defined eval { Devel::PPPort::croak_sv_with_counter("message\n") };
385 is Devel::PPPort::get_counter(), 1;
388 ok !defined eval { Devel::PPPort::croak_sv('') };
389 ok $@ =~ /^ at \Q$0\E line /;
390 ok $die =~ /^ at \Q$0\E line /;
393 ok !defined eval { Devel::PPPort::croak_sv("\xE1") };
394 ok $@ =~ /^\xE1 at \Q$0\E line /;
395 ok $die =~ /^\xE1 at \Q$0\E line /;
398 ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1") };
399 ok $@ =~ /^\xC3\xA1 at \Q$0\E line /;
400 ok $die =~ /^\xC3\xA1 at \Q$0\E line /;
403 Devel::PPPort::warn_sv("\xE1\n");
407 Devel::PPPort::warn_sv(10);
408 ok $warn =~ /^10 at \Q$0\E line /;
411 Devel::PPPort::warn_sv('');
412 ok $warn =~ /^ at \Q$0\E line /;
415 Devel::PPPort::warn_sv("\xE1");
416 ok $warn =~ /^\xE1 at \Q$0\E line /;
419 Devel::PPPort::warn_sv("\xC3\xA1");
420 ok $warn =~ /^\xC3\xA1 at \Q$0\E line /;
422 is Devel::PPPort::mess_sv("\xE1\n", 0), "\xE1\n";
423 is Devel::PPPort::mess_sv(do {my $tmp = "\xE1\n"}, 1), "\xE1\n";
425 ok Devel::PPPort::mess_sv(10, 0) =~ /^10 at \Q$0\E line /;
426 ok Devel::PPPort::mess_sv(do {my $tmp = 10}, 1) =~ /^10 at \Q$0\E line /;
428 ok Devel::PPPort::mess_sv('', 0) =~ /^ at \Q$0\E line /;
429 ok Devel::PPPort::mess_sv(do {my $tmp = ''}, 1) =~ /^ at \Q$0\E line /;
431 ok Devel::PPPort::mess_sv("\xE1", 0) =~ /^\xE1 at \Q$0\E line /;
432 ok Devel::PPPort::mess_sv(do {my $tmp = "\xE1"}, 1) =~ /^\xE1 at \Q$0\E line /;
434 ok Devel::PPPort::mess_sv("\xC3\xA1", 0) =~ /^\xC3\xA1 at \Q$0\E line /;
435 ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1"}, 1) =~ /^\xC3\xA1 at \Q$0\E line /;
437 if (ivers($]) >= ivers('5.006')) {
438 BEGIN { if (ivers($]) >= ivers('5.006') && ivers($]) < ivers('5.008')) { require utf8; utf8->import(); } }
441 ok !defined eval { Devel::PPPort::croak_sv("\x{100}\n") };
442 if (ivers($]) < ivers('5.007001') || ivers($]) > ivers('5.007003')) {
445 skip 'skip: broken utf8 support in die hook', 1;
447 if (ivers($]) < ivers('5.007001') || ivers($]) > ivers('5.008')) {
448 is $die, "\x{100}\n";
450 skip 'skip: broken utf8 support in die hook', 1;
454 ok !defined eval { Devel::PPPort::croak_sv("\x{100}") };
455 if (ivers($]) < ivers('5.007001') || ivers($]) > ivers('5.007003')) {
456 ok $@ =~ /^\x{100} at \Q$0\E line /;
458 skip 'skip: broken utf8 support in die hook', 1;
460 if (ivers($]) < ivers('5.007001') || ivers($]) > ivers('5.008')) {
461 ok $die =~ /^\x{100} at \Q$0\E line /;
463 skip 'skip: broken utf8 support in die hook', 1;
466 if (ivers($]) < ivers('5.007001') || ivers($]) > ivers('5.008')) {
468 Devel::PPPort::warn_sv("\x{100}\n");
469 is $warn, "\x{100}\n";
472 Devel::PPPort::warn_sv("\x{100}");
473 ok (my $tmp = $warn) =~ /^\x{100} at \Q$0\E line /;
475 skip 'skip: broken utf8 support in warn hook', 2;
478 is Devel::PPPort::mess_sv("\x{100}\n", 0), "\x{100}\n";
479 is Devel::PPPort::mess_sv(do {my $tmp = "\x{100}\n"}, 1), "\x{100}\n";
481 ok Devel::PPPort::mess_sv("\x{100}", 0) =~ /^\x{100} at \Q$0\E line /;
482 ok Devel::PPPort::mess_sv(do {my $tmp = "\x{100}"}, 1) =~ /^\x{100} at \Q$0\E line /;
484 skip 'skip: no utf8 support', 12;
487 if (ord('A') != 65) {
488 skip 'skip: no ASCII support', 24;
489 } elsif ( ivers($]) >= ivers('5.008')
490 && ivers($]) != ivers('5.013000') # Broken in these ranges
491 && ! (ivers($]) >= ivers('5.011005') && ivers($]) <= ivers('5.012000')))
494 ok !defined eval { Devel::PPPort::croak_sv(eval '"\N{U+E1}\n"') };
499 ok !defined eval { Devel::PPPort::croak_sv(eval '"\N{U+E1}"') };
500 ok $@ =~ /^\xE1 at \Q$0\E line /;
501 ok $die =~ /^\xE1 at \Q$0\E line /;
505 my $expect = eval '"\N{U+C3}\N{U+A1}\n"';
506 ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1\n") };
513 my $expect = eval 'qr/^\N{U+C3}\N{U+A1} at \Q$0\E line /';
514 ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1") };
520 Devel::PPPort::warn_sv(eval '"\N{U+E1}\n"');
524 Devel::PPPort::warn_sv(eval '"\N{U+E1}"');
525 ok $warn =~ /^\xE1 at \Q$0\E line /;
528 Devel::PPPort::warn_sv("\xC3\xA1\n");
529 is $warn, eval '"\N{U+C3}\N{U+A1}\n"';
532 Devel::PPPort::warn_sv("\xC3\xA1");
533 ok $warn =~ eval 'qr/^\N{U+C3}\N{U+A1} at \Q$0\E line /';
535 if (ivers($]) < ivers('5.004')) {
536 skip 'skip: no support for mess_sv', 8;
539 is Devel::PPPort::mess_sv(eval('"\N{U+E1}\n"'), 0), eval '"\N{U+E1}\n"';
540 is Devel::PPPort::mess_sv(do {my $tmp = eval '"\N{U+E1}\n"'}, 1), eval '"\N{U+E1}\n"';
542 ok Devel::PPPort::mess_sv(eval('"\N{U+E1}"'), 0) =~ eval 'qr/^\N{U+E1} at \Q$0\E line /';
543 ok Devel::PPPort::mess_sv(do {my $tmp = eval '"\N{U+E1}"'}, 1) =~ eval 'qr/^\N{U+E1} at \Q$0\E line /';
545 is Devel::PPPort::mess_sv("\xC3\xA1\n", 0), eval '"\N{U+C3}\N{U+A1}\n"';
546 is Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1\n"}, 1), eval '"\N{U+C3}\N{U+A1}\n"';
548 ok Devel::PPPort::mess_sv("\xC3\xA1", 0) =~ eval 'qr/^\N{U+C3}\N{U+A1} at \Q$0\E line /';
549 ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1"}, 1) =~ eval 'qr/^\N{U+C3}\N{U+A1} at \Q$0\E line /';
552 skip 'skip: no support for \N{U+..} syntax', 24;
555 if (ivers($]) >= ivers('5.007003') or (ivers($]) >= ivers('5.006001') and ivers($]) < ivers('5.007'))) {
557 ok !defined eval { Devel::PPPort::croak_sv($scalar_ref) };
558 ok $@ == $scalar_ref;
559 ok $die == $scalar_ref;
562 ok !defined eval { Devel::PPPort::croak_sv($array_ref) };
564 ok $die == $array_ref;
567 ok !defined eval { Devel::PPPort::croak_sv($hash_ref) };
569 ok $die == $hash_ref;
572 ok !defined eval { Devel::PPPort::croak_sv($obj) };
576 skip 'skip: no support for exceptions', 12;
579 ok !defined eval { Devel::PPPort::croak_no_modify() };
580 ok $@ =~ /^Modification of a read-only value attempted at \Q$0\E line /;
582 ok !defined eval { Devel::PPPort::croak_memory_wrap() };
583 ok $@ =~ /^panic: memory wrap at \Q$0\E line /;
585 ok !defined eval { Devel::PPPort::croak_xs_usage("params") };
586 ok $@ =~ /^Usage: Devel::PPPort::croak_xs_usage\(params\) at \Q$0\E line /;