This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Devel::PPPort: Do not run tests which use \N{U+XX} on Perl 5.12.0
[perl5.git] / dist / Devel-PPPort / parts / inc / mess
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
12 croak_sv
13 die_sv
14 mess_sv
15 warn_sv
16
17 vmess
18 mess_nocontext
19 mess
20
21 warn_nocontext
22
23 croak_nocontext
24
25 croak_no_modify
26 Perl_croak_no_modify
27
28 croak_memory_wrap
29 croak_xs_usage
30
31 PERL_ARGS_ASSERT_CROAK_XS_USAGE
32
33 =dontwarn
34
35 NEED_mess
36 NEED_mess_nocontext
37 NEED_vmess
38 _dppp_fix_utf8_errsv
39
40 =implementation
41
42 #ifdef NEED_mess_sv
43 #define NEED_mess
44 #endif
45
46 #ifdef NEED_mess
47 #define NEED_mess_nocontext
48 #define NEED_vmess
49 #endif
50
51 #ifndef croak_sv
52 #if { VERSION >= 5.7.3 } || ( { VERSION >= 5.6.1 } && { VERSION < 5.7.0 } )
53 #  if ( { VERSION >= 5.8.0 } && { VERSION < 5.8.9 } ) || ( { VERSION >= 5.9.0 } && { VERSION < 5.10.1 } )
54 #    define _dppp_fix_utf8_errsv(errsv, sv)                     \
55         STMT_START {                                            \
56             if (sv != ERRSV)                                    \
57                 SvFLAGS(ERRSV) = (SvFLAGS(ERRSV) & ~SVf_UTF8) | \
58                                  (SvFLAGS(sv) & SVf_UTF8);      \
59         } STMT_END
60 #  else
61 #    define _dppp_fix_utf8_errsv(errsv, sv) STMT_START {} STMT_END
62 #  endif
63 #  define croak_sv(sv)                        \
64     STMT_START {                              \
65         if (SvROK(sv)) {                      \
66             sv_setsv(ERRSV, sv);              \
67             croak(NULL);                      \
68         } else {                              \
69             _dppp_fix_utf8_errsv(ERRSV, sv);  \
70             croak("%" SVf, SVfARG(sv));       \
71         }                                     \
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 }
82 OP *
83 die_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 }
101 SV*
102 vmess(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 }
116 SV*
117 mess_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 }
132 SV*
133 mess(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 }
152 SV *
153 mess_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
185 #ifndef croak_nocontext
186 #define croak_nocontext croak
187 #endif
188
189 #ifndef croak_no_modify
190 #define croak_no_modify() croak("%s", PL_no_modify)
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 } )
196 #  define croak_memory_wrap() croak("%s", PL_memory_wrap)
197 #else
198 #  define croak_memory_wrap() croak("panic: memory wrap")
199 #endif
200 #endif
201
202 #ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
203 #define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)
204 #endif
205
206 #ifndef croak_xs_usage
207 #if { NEED croak_xs_usage }
208 void
209 croak_xs_usage(pTHX_ const CV *const cv, const char *const params)
210 {
211     const GV *const gv = CvGV(cv);
212
213     PERL_ARGS_ASSERT_CROAK_XS_USAGE;
214
215     if (gv) {
216         const char *const gvname = GvNAME(gv);
217         const HV *const stash = GvSTASH(gv);
218         const char *const hvname = stash ? HvNAME(stash) : NULL;
219
220         if (hvname)
221             croak("Usage: %s::%s(%s)", hvname, gvname, params);
222         else
223             croak("Usage: %s(%s)", gvname, params);
224     } else {
225         /* Pants. I don't think that it should be possible to get here. */
226         croak("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
227     }
228 }
229 #endif
230 #endif
231
232 =xsinit
233
234 #define NEED_die_sv
235 #define NEED_mess_sv
236 #define NEED_croak_xs_usage
237
238 =xsubs
239
240 void
241 croak_sv(sv)
242     SV *sv
243 CODE:
244     croak_sv(sv);
245
246 void
247 die_sv(sv)
248     SV *sv
249 CODE:
250     (void)die_sv(sv);
251
252 void
253 warn_sv(sv)
254     SV *sv
255 CODE:
256     warn_sv(sv);
257
258 SV *
259 mess_sv(sv, consume)
260     SV *sv
261     bool consume
262 CODE:
263     RETVAL = newSVsv(mess_sv(sv, consume));
264 OUTPUT:
265     RETVAL
266
267 void
268 croak_no_modify()
269 CODE:
270     croak_no_modify();
271
272 void
273 croak_memory_wrap()
274 CODE:
275     croak_memory_wrap();
276
277 void
278 croak_xs_usage(params)
279     char *params
280 CODE:
281     croak_xs_usage(cv, params);
282
283 =tests plan => 93
284
285 BEGIN { if ($] lt '5.006') { $^W = 0; } }
286
287 my $warn;
288 my $die;
289 local $SIG{__WARN__} = sub { $warn = $_[0] };
290 local $SIG{__DIE__} = sub { $die = $_[0] };
291
292 my $scalar_ref = \do {my $tmp = 10};
293 my $array_ref = [];
294 my $hash_ref = {};
295 my $obj = bless {}, 'Package';
296
297 undef $die;
298 ok !defined eval { Devel::PPPort::croak_sv("\xE1\n") };
299 ok $@, "\xE1\n";
300 ok $die, "\xE1\n";
301
302 undef $die;
303 ok !defined eval { Devel::PPPort::croak_sv(10) };
304 ok $@ =~ /^10 at $0 line /;
305 ok $die =~ /^10 at $0 line /;
306
307 undef $die;
308 $@ = 'should not be visible (1)';
309 ok !defined eval {
310     $@ = 'should not be visible (2)';
311     Devel::PPPort::croak_sv('');
312 };
313 ok $@ =~ /^ at $0 line /;
314 ok $die =~ /^ at $0 line /;
315
316 undef $die;
317 $@ = 'should not be visible';
318 ok !defined eval {
319     $@ = 'this must be visible';
320     Devel::PPPort::croak_sv($@)
321 };
322 ok $@ =~ /^this must be visible at $0 line /;
323 ok $die =~ /^this must be visible at $0 line /;
324
325 undef $die;
326 $@ = 'should not be visible';
327 ok !defined eval {
328     $@ = "this must be visible\n";
329     Devel::PPPort::croak_sv($@)
330 };
331 ok $@, "this must be visible\n";
332 ok $die, "this must be visible\n";
333
334 undef $die;
335 ok !defined eval { Devel::PPPort::croak_sv('') };
336 ok $@ =~ /^ at $0 line /;
337 ok $die =~ /^ at $0 line /;
338
339 undef $die;
340 ok !defined eval { Devel::PPPort::croak_sv("\xE1") };
341 ok $@ =~ /^\xE1 at $0 line /;
342 ok $die =~ /^\xE1 at $0 line /;
343
344 undef $die;
345 ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1") };
346 ok $@ =~ /^\xC3\xA1 at $0 line /;
347 ok $die =~ /^\xC3\xA1 at $0 line /;
348
349 undef $warn;
350 Devel::PPPort::warn_sv("\xE1\n");
351 ok $warn, "\xE1\n";
352
353 undef $warn;
354 Devel::PPPort::warn_sv(10);
355 ok $warn =~ /^10 at $0 line /;
356
357 undef $warn;
358 Devel::PPPort::warn_sv('');
359 ok $warn =~ /^ at $0 line /;
360
361 undef $warn;
362 Devel::PPPort::warn_sv("\xE1");
363 ok $warn =~ /^\xE1 at $0 line /;
364
365 undef $warn;
366 Devel::PPPort::warn_sv("\xC3\xA1");
367 ok $warn =~ /^\xC3\xA1 at $0 line /;
368
369 ok Devel::PPPort::mess_sv("\xE1\n", 0), "\xE1\n";
370 ok Devel::PPPort::mess_sv(do {my $tmp = "\xE1\n"}, 1), "\xE1\n";
371
372 ok Devel::PPPort::mess_sv(10, 0) =~ /^10 at $0 line /;
373 ok Devel::PPPort::mess_sv(do {my $tmp = 10}, 1) =~ /^10 at $0 line /;
374
375 ok Devel::PPPort::mess_sv('', 0) =~ /^ at $0 line /;
376 ok Devel::PPPort::mess_sv(do {my $tmp = ''}, 1) =~ /^ at $0 line /;
377
378 ok Devel::PPPort::mess_sv("\xE1", 0) =~ /^\xE1 at $0 line /;
379 ok Devel::PPPort::mess_sv(do {my $tmp = "\xE1"}, 1) =~ /^\xE1 at $0 line /;
380
381 ok Devel::PPPort::mess_sv("\xC3\xA1", 0) =~ /^\xC3\xA1 at $0 line /;
382 ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1"}, 1) =~ /^\xC3\xA1 at $0 line /;
383
384 if ($] ge '5.006') {
385     BEGIN { if ($] ge '5.006' && $] lt '5.008') { require utf8; utf8->import(); } }
386
387     undef $die;
388     ok !defined eval { Devel::PPPort::croak_sv("\x{100}\n") };
389     ok $@, "\x{100}\n";
390     if ($] ne '5.008') {
391         ok $die, "\x{100}\n";
392     } else {
393         skip 'skip: broken utf8 support in die hook', 0;
394     }
395
396     undef $die;
397     ok !defined eval { Devel::PPPort::croak_sv("\x{100}") };
398     ok $@ =~ /^\x{100} at $0 line /;
399     if ($] ne '5.008') {
400         ok $die =~ /^\x{100} at $0 line /;
401     } else {
402         skip 'skip: broken utf8 support in die hook', 0;
403     }
404
405     if ($] ne '5.008') {
406         undef $warn;
407         Devel::PPPort::warn_sv("\x{100}\n");
408         ok $warn, "\x{100}\n";
409
410         undef $warn;
411         Devel::PPPort::warn_sv("\x{100}");
412         ok (my $tmp = $warn) =~ /^\x{100} at $0 line /;
413     } else {
414         skip 'skip: broken utf8 support in warn hook', 0 for 1..2;
415     }
416
417     ok Devel::PPPort::mess_sv("\x{100}\n", 0), "\x{100}\n";
418     ok Devel::PPPort::mess_sv(do {my $tmp = "\x{100}\n"}, 1), "\x{100}\n";
419
420     ok Devel::PPPort::mess_sv("\x{100}", 0) =~ /^\x{100} at $0 line /;
421     ok Devel::PPPort::mess_sv(do {my $tmp = "\x{100}"}, 1) =~ /^\x{100} at $0 line /;
422 } else {
423     skip 'skip: no utf8 support', 0 for 1..12;
424 }
425
426 if (ord('A') != 65) {
427     skip 'skip: no ASCII support', 0 for 1..24;
428 } elsif ($] ge '5.008' && $] ne '5.012000') {
429     undef $die;
430     ok !defined eval { Devel::PPPort::croak_sv(eval '"\N{U+E1}\n"') };
431     ok $@, "\xE1\n";
432     ok $die, "\xE1\n";
433
434     undef $die;
435     ok !defined eval { Devel::PPPort::croak_sv(eval '"\N{U+E1}"') };
436     ok $@ =~ /^\xE1 at $0 line /;
437     ok $die =~ /^\xE1 at $0 line /;
438
439     {
440         undef $die;
441         my $expect = eval '"\N{U+C3}\N{U+A1}\n"';
442         ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1\n") };
443         ok $@, $expect;
444         ok $die, $expect;
445     }
446
447     {
448         undef $die;
449         my $expect = eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
450         ok !defined eval { Devel::PPPort::croak_sv("\xC3\xA1") };
451         ok $@ =~ $expect;
452         ok $die =~ $expect;
453     }
454
455     undef $warn;
456     Devel::PPPort::warn_sv(eval '"\N{U+E1}\n"');
457     ok $warn, "\xE1\n";
458
459     undef $warn;
460     Devel::PPPort::warn_sv(eval '"\N{U+E1}"');
461     ok $warn =~ /^\xE1 at $0 line /;
462
463     undef $warn;
464     Devel::PPPort::warn_sv("\xC3\xA1\n");
465     ok $warn, eval '"\N{U+C3}\N{U+A1}\n"';
466
467     undef $warn;
468     Devel::PPPort::warn_sv("\xC3\xA1");
469     ok $warn =~ eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
470
471     ok Devel::PPPort::mess_sv(eval('"\N{U+E1}\n"'), 0), eval '"\N{U+E1}\n"';
472     ok Devel::PPPort::mess_sv(do {my $tmp = eval '"\N{U+E1}\n"'}, 1), eval '"\N{U+E1}\n"';
473
474     ok Devel::PPPort::mess_sv(eval('"\N{U+E1}"'), 0) =~ eval 'qr/^\N{U+E1} at $0 line /';
475     ok Devel::PPPort::mess_sv(do {my $tmp = eval '"\N{U+E1}"'}, 1) =~ eval 'qr/^\N{U+E1} at $0 line /';
476
477     ok Devel::PPPort::mess_sv("\xC3\xA1\n", 0), eval '"\N{U+C3}\N{U+A1}\n"';
478     ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1\n"}, 1), eval '"\N{U+C3}\N{U+A1}\n"';
479
480     ok Devel::PPPort::mess_sv("\xC3\xA1", 0) =~ eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
481     ok Devel::PPPort::mess_sv(do {my $tmp = "\xC3\xA1"}, 1) =~ eval 'qr/^\N{U+C3}\N{U+A1} at $0 line /';
482 } else {
483     skip 'skip: no support for \N{U+..} syntax', 0 for 1..24;
484 }
485
486 if ($] ge '5.007003' or ($] ge '5.006001' and $] lt '5.007')) {
487     undef $die;
488     ok !defined eval { Devel::PPPort::croak_sv($scalar_ref) };
489     ok $@ == $scalar_ref;
490     ok $die == $scalar_ref;
491
492     undef $die;
493     ok !defined eval { Devel::PPPort::croak_sv($array_ref) };
494     ok $@ == $array_ref;
495     ok $die == $array_ref;
496
497     undef $die;
498     ok !defined eval { Devel::PPPort::croak_sv($hash_ref) };
499     ok $@ == $hash_ref;
500     ok $die == $hash_ref;
501
502     undef $die;
503     ok !defined eval { Devel::PPPort::croak_sv($obj) };
504     ok $@ == $obj;
505     ok $die == $obj;
506 } else {
507     skip 'skip: no support for exceptions', 0 for 1..12;
508 }
509
510 ok !defined eval { Devel::PPPort::croak_no_modify() };
511 ok $@ =~ /^Modification of a read-only value attempted at $0 line /;
512
513 ok !defined eval { Devel::PPPort::croak_memory_wrap() };
514 ok $@ =~ /^panic: memory wrap at $0 line /;
515
516 ok !defined eval { Devel::PPPort::croak_xs_usage("params") };
517 ok $@ =~ /^Usage: Devel::PPPort::croak_xs_usage\(params\) at $0 line /;