This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
parts/inc/inctools: Add fcn to return integer version
[perl5.git] / dist / Devel-PPPort / parts / inc / mess
CommitLineData
f87c37b1
P
1################################################################################
2##
3## Copyright (C) 2017, Pali <pali@cpan.org>
4##
5## This program is free software; you can redistribute it and/or
6## modify it under the same terms as Perl itself.
7##
8################################################################################
9
10=provides
11
12croak_sv
13die_sv
14mess_sv
15warn_sv
16
17vmess
18mess_nocontext
19mess
20
21warn_nocontext
f87c37b1
P
22
23croak_nocontext
f87c37b1
P
24
25croak_no_modify
26Perl_croak_no_modify
27
28croak_memory_wrap
29croak_xs_usage
30
31PERL_ARGS_ASSERT_CROAK_XS_USAGE
32
33=dontwarn
34
35NEED_mess
36NEED_mess_nocontext
37NEED_vmess
f87c37b1
P
38
39=implementation
40
41#ifdef NEED_mess_sv
42#define NEED_mess
43#endif
44
45#ifdef NEED_mess
46#define NEED_mess_nocontext
47#define NEED_vmess
48#endif
49
50#ifndef croak_sv
51#if { VERSION >= 5.7.3 } || ( { VERSION >= 5.6.1 } && { VERSION < 5.7.0 } )
52# if ( { VERSION >= 5.8.0 } && { VERSION < 5.8.9 } ) || ( { VERSION >= 5.9.0 } && { VERSION < 5.10.1 } )
f1305528
P
53# define D_PPP_FIX_UTF8_ERRSV_FOR_SV(sv) \
54 STMT_START { \
55 SV *_errsv = ERRSV; \
56 SvFLAGS(_errsv) = (SvFLAGS(_errsv) & ~SVf_UTF8) | \
57 (SvFLAGS(sv) & SVf_UTF8); \
f87c37b1
P
58 } STMT_END
59# else
f1305528 60# define D_PPP_FIX_UTF8_ERRSV_FOR_SV(sv) STMT_START {} STMT_END
f87c37b1 61# endif
f1305528
P
62# define croak_sv(sv) \
63 STMT_START { \
64 SV *_sv = (sv); \
65 if (SvROK(_sv)) { \
66 sv_setsv(ERRSV, _sv); \
67 croak(NULL); \
68 } else { \
69 D_PPP_FIX_UTF8_ERRSV_FOR_SV(_sv); \
70 croak("%" SVf, SVfARG(_sv)); \
71 } \
f87c37b1
P
72 } STMT_END
73#elif { VERSION >= 5.4.0 }
74# define croak_sv(sv) croak("%" SVf, SVfARG(sv))
75#else
76# define croak_sv(sv) croak("%s", SvPV_nolen(sv))
77#endif
78#endif
79
80#ifndef die_sv
81#if { NEED die_sv }
82OP *
83die_sv(pTHX_ SV *sv)
84{
85 croak_sv(sv);
86 return (OP *)NULL;
87}
88#endif
89#endif
90
91#ifndef warn_sv
92#if { VERSION >= 5.4.0 }
93# define warn_sv(sv) warn("%" SVf, SVfARG(sv))
94#else
95# define warn_sv(sv) warn("%s", SvPV_nolen(sv))
96#endif
97#endif
98
99#ifndef vmess
100#if { NEED vmess }
101SV*
102vmess(pTHX_ const char* pat, va_list* args)
103{
104 mess(pat, args);
105 return PL_mess_sv;
106}
107#endif
108#endif
109
110#if { VERSION < 5.6.0 }
111#undef mess
112#endif
113
114#if !defined(mess_nocontext) && !defined(Perl_mess_nocontext)
115#if { NEED mess_nocontext }
116SV*
117mess_nocontext(const char* pat, ...)
118{
119 dTHX;
120 SV *sv;
121 va_list args;
122 va_start(args, pat);
123 sv = vmess(pat, &args);
124 va_end(args);
125 return sv;
126}
127#endif
128#endif
129
130#ifndef mess
131#if { NEED mess }
132SV*
133mess(pTHX_ const char* pat, ...)
134{
135 SV *sv;
136 va_list args;
137 va_start(args, pat);
138 sv = vmess(pat, &args);
139 va_end(args);
140 return sv;
141}
142#ifdef mess_nocontext
143#define mess mess_nocontext
144#else
145#define mess Perl_mess_nocontext
146#endif
147#endif
148#endif
149
150#ifndef mess_sv
151#if { NEED mess_sv }
152SV *
153mess_sv(pTHX_ SV *basemsg, bool consume)
154{
155 SV *tmp;
156 SV *ret;
157
158 if (SvPOK(basemsg) && SvCUR(basemsg) && *(SvEND(basemsg)-1) == '\n') {
159 if (consume)
160 return basemsg;
161 ret = mess("");
162 SvSetSV_nosteal(ret, basemsg);
163 return ret;
164 }
165
166 if (consume) {
167 sv_catsv(basemsg, mess(""));
168 return basemsg;
169 }
170
171 ret = mess("");
172 tmp = newSVsv(ret);
173 SvSetSV_nosteal(ret, basemsg);
174 sv_catsv(ret, tmp);
175 sv_dec(tmp);
176 return ret;
177}
178#endif
179#endif
180
181#ifndef warn_nocontext
182#define warn_nocontext warn
183#endif
184
f87c37b1
P
185#ifndef croak_nocontext
186#define croak_nocontext croak
187#endif
188
f87c37b1 189#ifndef croak_no_modify
95afac5c 190#define croak_no_modify() croak_nocontext("%s", PL_no_modify)
f87c37b1
P
191#define Perl_croak_no_modify() croak_no_modify()
192#endif
193
194#ifndef croak_memory_wrap
195#if { VERSION >= 5.9.2 } || ( { VERSION >= 5.8.6 } && { VERSION < 5.9.0 } )
95afac5c 196# define croak_memory_wrap() croak_nocontext("%s", PL_memory_wrap)
f87c37b1 197#else
95afac5c 198# define croak_memory_wrap() croak_nocontext("panic: memory wrap")
f87c37b1
P
199#endif
200#endif
201
368e5f5e
TC
202#ifndef croak_xs_usage
203#if { NEED croak_xs_usage }
204
f87c37b1
P
205#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
206#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)
207#endif
208
f87c37b1 209void
0e9335ba 210croak_xs_usage(const CV *const cv, const char *const params)
f87c37b1 211{
d397b1c4 212 dTHX;
f87c37b1
P
213 const GV *const gv = CvGV(cv);
214
215 PERL_ARGS_ASSERT_CROAK_XS_USAGE;
216
217 if (gv) {
218 const char *const gvname = GvNAME(gv);
219 const HV *const stash = GvSTASH(gv);
220 const char *const hvname = stash ? HvNAME(stash) : NULL;
221
222 if (hvname)
223 croak("Usage: %s::%s(%s)", hvname, gvname, params);
224 else
225 croak("Usage: %s(%s)", gvname, params);
226 } else {
227 /* Pants. I don't think that it should be possible to get here. */
228 croak("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
229 }
230}
231#endif
232#endif
233
234=xsinit
235
236#define NEED_die_sv
237#define NEED_mess_sv
238#define NEED_croak_xs_usage
239
f1305528
P
240=xsmisc
241
242static IV counter;
243static void reset_counter(void) { counter = 0; }
244static void inc_counter(void) { counter++; }
245
f87c37b1
P
246=xsubs
247
248void
249croak_sv(sv)
250 SV *sv
251CODE:
252 croak_sv(sv);
253
254void
f1305528
P
255croak_sv_errsv()
256CODE:
257 croak_sv(ERRSV);
258
259void
260croak_sv_with_counter(sv)
261 SV *sv
262CODE:
263 reset_counter();
264 croak_sv((inc_counter(), sv));
265
266IV
267get_counter()
268CODE:
269 RETVAL = counter;
270OUTPUT:
271 RETVAL
272
273void
f87c37b1
P
274die_sv(sv)
275 SV *sv
f87c37b1 276CODE:
61862610 277 (void)die_sv(sv);
f87c37b1
P
278
279void
280warn_sv(sv)
281 SV *sv
282CODE:
283 warn_sv(sv);
284
285SV *
286mess_sv(sv, consume)
287 SV *sv
288 bool consume
289CODE:
290 RETVAL = newSVsv(mess_sv(sv, consume));
291OUTPUT:
292 RETVAL
293
294void
295croak_no_modify()
296CODE:
297 croak_no_modify();
298
299void
300croak_memory_wrap()
301CODE:
302 croak_memory_wrap();
303
304void
305croak_xs_usage(params)
306 char *params
307CODE:
308 croak_xs_usage(cv, params);
309
f1305528 310=tests plan => 102
f87c37b1
P
311
312BEGIN { if ($] lt '5.006') { $^W = 0; } }
313
314my $warn;
315my $die;
316local $SIG{__WARN__} = sub { $warn = $_[0] };
317local $SIG{__DIE__} = sub { $die = $_[0] };
318
319my $scalar_ref = \do {my $tmp = 10};
320my $array_ref = [];
321my $hash_ref = {};
322my $obj = bless {}, 'Package';
323
324undef $die;
325ok !defined eval { Devel::PPPort::croak_sv("\xE1\n") };
326ok $@, "\xE1\n";
327ok $die, "\xE1\n";
328
329undef $die;
330ok !defined eval { Devel::PPPort::croak_sv(10) };
331ok $@ =~ /^10 at $0 line /;
332ok $die =~ /^10 at $0 line /;
333
334undef $die;
335$@ = 'should not be visible (1)';
336ok !defined eval {
337 $@ = 'should not be visible (2)';
338 Devel::PPPort::croak_sv('');
339};
340ok $@ =~ /^ at $0 line /;
341ok $die =~ /^ at $0 line /;
342
343undef $die;
344$@ = 'should not be visible';
345ok !defined eval {
346 $@ = 'this must be visible';
347 Devel::PPPort::croak_sv($@)
348};
349ok $@ =~ /^this must be visible at $0 line /;
350ok $die =~ /^this must be visible at $0 line /;
351
352undef $die;
353$@ = 'should not be visible';
354ok !defined eval {
355 $@ = "this must be visible\n";
356 Devel::PPPort::croak_sv($@)
357};
358ok $@, "this must be visible\n";
359ok $die, "this must be visible\n";
360
361undef $die;
f1305528
P
362$@ = 'should not be visible';
363ok !defined eval {
364 $@ = 'this must be visible';
365 Devel::PPPort::croak_sv_errsv()
366};
367ok $@ =~ /^this must be visible at $0 line /;
368ok $die =~ /^this must be visible at $0 line /;
369
370undef $die;
371$@ = 'should not be visible';
372ok !defined eval {
373 $@ = "this must be visible\n";
374 Devel::PPPort::croak_sv_errsv()
375};
376ok $@, "this must be visible\n";
377ok $die, "this must be visible\n";
378
379undef $die;
380ok !defined eval { Devel::PPPort::croak_sv_with_counter("message\n") };
381ok $@, "message\n";
382ok Devel::PPPort::get_counter(), 1;
383
384undef $die;
f87c37b1
P
385ok !defined eval { Devel::PPPort::croak_sv('') };
386ok $@ =~ /^ at $0 line /;
387ok $die =~ /^ at $0 line /;
388
389undef $die;
390ok !defined eval { Devel::PPPort::croak_sv("\xE1") };
391ok $@ =~ /^\xE1 at $0 line /;
392ok $die =~ /^\xE1 at $0 line /;
393
394undef $die;
395ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1") };
396ok $@ =~ /^\xC3\xA1 at $0 line /;
397ok $die =~ /^\xC3\xA1 at $0 line /;
398
399undef $warn;
400Devel::PPPort::warn_sv("\xE1\n");
401ok $warn, "\xE1\n";
402
403undef $warn;
404Devel::PPPort::warn_sv(10);
405ok $warn =~ /^10 at $0 line /;
406
407undef $warn;
408Devel::PPPort::warn_sv('');
409ok $warn =~ /^ at $0 line /;
410
411undef $warn;
412Devel::PPPort::warn_sv("\xE1");
413ok $warn =~ /^\xE1 at $0 line /;
414
415undef $warn;
416Devel::PPPort::warn_sv("\xC3\xA1");
417ok $warn =~ /^\xC3\xA1 at $0 line /;
418
419ok Devel::PPPort::mess_sv("\xE1\n", 0), "\xE1\n";
420ok Devel::PPPort::mess_sv(do {my $tmp = "\xE1\n"}, 1), "\xE1\n";
421
422ok Devel::PPPort::mess_sv(10, 0) =~ /^10 at $0 line /;
423ok Devel::PPPort::mess_sv(do {my $tmp = 10}, 1) =~ /^10 at $0 line /;
424
425ok Devel::PPPort::mess_sv('', 0) =~ /^ at $0 line /;
426ok Devel::PPPort::mess_sv(do {my $tmp = ''}, 1) =~ /^ at $0 line /;
427
428ok Devel::PPPort::mess_sv("\xE1", 0) =~ /^\xE1 at $0 line /;
429ok Devel::PPPort::mess_sv(do {my $tmp = "\xE1"}, 1) =~ /^\xE1 at $0 line /;
430
431ok Devel::PPPort::mess_sv("\xC3\xA1", 0) =~ /^\xC3\xA1 at $0 line /;
432ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1"}, 1) =~ /^\xC3\xA1 at $0 line /;
433
434if ($] ge '5.006') {
435 BEGIN { if ($] ge '5.006' && $] lt '5.008') { require utf8; utf8->import(); } }
436
437 undef $die;
438 ok !defined eval { Devel::PPPort::croak_sv("\x{100}\n") };
439 ok $@, "\x{100}\n";
440 if ($] ne '5.008') {
441 ok $die, "\x{100}\n";
442 } else {
443 skip 'skip: broken utf8 support in die hook', 0;
444 }
445
446 undef $die;
447 ok !defined eval { Devel::PPPort::croak_sv("\x{100}") };
448 ok $@ =~ /^\x{100} at $0 line /;
449 if ($] ne '5.008') {
450 ok $die =~ /^\x{100} at $0 line /;
451 } else {
452 skip 'skip: broken utf8 support in die hook', 0;
453 }
454
455 if ($] ne '5.008') {
456 undef $warn;
457 Devel::PPPort::warn_sv("\x{100}\n");
458 ok $warn, "\x{100}\n";
459
460 undef $warn;
461 Devel::PPPort::warn_sv("\x{100}");
462 ok (my $tmp = $warn) =~ /^\x{100} at $0 line /;
463 } else {
464 skip 'skip: broken utf8 support in warn hook', 0 for 1..2;
465 }
466
467 ok Devel::PPPort::mess_sv("\x{100}\n", 0), "\x{100}\n";
468 ok Devel::PPPort::mess_sv(do {my $tmp = "\x{100}\n"}, 1), "\x{100}\n";
469
470 ok Devel::PPPort::mess_sv("\x{100}", 0) =~ /^\x{100} at $0 line /;
471 ok Devel::PPPort::mess_sv(do {my $tmp = "\x{100}"}, 1) =~ /^\x{100} at $0 line /;
472} else {
473 skip 'skip: no utf8 support', 0 for 1..12;
474}
475
10417d47
P
476if (ord('A') != 65) {
477 skip 'skip: no ASCII support', 0 for 1..24;
a4c10f7d 478} elsif ($] ge '5.008' && $] ne '5.012000') {
f87c37b1
P
479 undef $die;
480 ok !defined eval { Devel::PPPort::croak_sv(eval '"\N{U+E1}\n"') };
481 ok $@, "\xE1\n";
482 ok $die, "\xE1\n";
483
484 undef $die;
485 ok !defined eval { Devel::PPPort::croak_sv(eval '"\N{U+E1}"') };
486 ok $@ =~ /^\xE1 at $0 line /;
487 ok $die =~ /^\xE1 at $0 line /;
488
489 {
490 undef $die;
491 my $expect = eval '"\N{U+C3}\N{U+A1}\n"';
492 ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1\n") };
493 ok $@, $expect;
494 ok $die, $expect;
495 }
496
497 {
498 undef $die;
499 my $expect = eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
500 ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1") };
501 ok $@ =~ $expect;
502 ok $die =~ $expect;
503 }
504
505 undef $warn;
506 Devel::PPPort::warn_sv(eval '"\N{U+E1}\n"');
507 ok $warn, "\xE1\n";
508
509 undef $warn;
510 Devel::PPPort::warn_sv(eval '"\N{U+E1}"');
511 ok $warn =~ /^\xE1 at $0 line /;
512
513 undef $warn;
514 Devel::PPPort::warn_sv("\xC3\xA1\n");
515 ok $warn, eval '"\N{U+C3}\N{U+A1}\n"';
516
517 undef $warn;
518 Devel::PPPort::warn_sv("\xC3\xA1");
519 ok $warn =~ eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
520
521 ok Devel::PPPort::mess_sv(eval('"\N{U+E1}\n"'), 0), eval '"\N{U+E1}\n"';
522 ok Devel::PPPort::mess_sv(do {my $tmp = eval '"\N{U+E1}\n"'}, 1), eval '"\N{U+E1}\n"';
523
524 ok Devel::PPPort::mess_sv(eval('"\N{U+E1}"'), 0) =~ eval 'qr/^\N{U+E1} at $0 line /';
525 ok Devel::PPPort::mess_sv(do {my $tmp = eval '"\N{U+E1}"'}, 1) =~ eval 'qr/^\N{U+E1} at $0 line /';
526
527 ok Devel::PPPort::mess_sv("\xC3\xA1\n", 0), eval '"\N{U+C3}\N{U+A1}\n"';
528 ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1\n"}, 1), eval '"\N{U+C3}\N{U+A1}\n"';
529
530 ok Devel::PPPort::mess_sv("\xC3\xA1", 0) =~ eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
531 ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1"}, 1) =~ eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
532} else {
533 skip 'skip: no support for \N{U+..} syntax', 0 for 1..24;
534}
535
536if ($] ge '5.007003' or ($] ge '5.006001' and $] lt '5.007')) {
537 undef $die;
538 ok !defined eval { Devel::PPPort::croak_sv($scalar_ref) };
539 ok $@ == $scalar_ref;
540 ok $die == $scalar_ref;
541
542 undef $die;
543 ok !defined eval { Devel::PPPort::croak_sv($array_ref) };
544 ok $@ == $array_ref;
545 ok $die == $array_ref;
546
547 undef $die;
548 ok !defined eval { Devel::PPPort::croak_sv($hash_ref) };
549 ok $@ == $hash_ref;
550 ok $die == $hash_ref;
551
552 undef $die;
553 ok !defined eval { Devel::PPPort::croak_sv($obj) };
554 ok $@ == $obj;
555 ok $die == $obj;
556} else {
557 skip 'skip: no support for exceptions', 0 for 1..12;
558}
559
560ok !defined eval { Devel::PPPort::croak_no_modify() };
561ok $@ =~ /^Modification of a read-only value attempted at $0 line /;
562
563ok !defined eval { Devel::PPPort::croak_memory_wrap() };
564ok $@ =~ /^panic: memory wrap at $0 line /;
565
566ok !defined eval { Devel::PPPort::croak_xs_usage("params") };
567ok $@ =~ /^Usage: Devel::PPPort::croak_xs_usage\(params\) at $0 line /;