This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate perlio:
[perl5.git] / warnings.pl
CommitLineData
599cee73
PM
1#!/usr/bin/perl
2
0ca4541c
NIS
3
4$VERSION = '1.00';
b75c8c73 5
73f0cc2d
GS
6BEGIN {
7 push @INC, './lib';
8}
599cee73
PM
9use strict ;
10
11sub DEFAULT_ON () { 1 }
12sub DEFAULT_OFF () { 2 }
13
14my $tree = {
d3a7d8c7
GS
15
16'all' => {
e476b1b5 17 'io' => { 'pipe' => DEFAULT_OFF,
599cee73
PM
18 'unopened' => DEFAULT_OFF,
19 'closed' => DEFAULT_OFF,
20 'newline' => DEFAULT_OFF,
21 'exec' => DEFAULT_OFF,
599cee73 22 },
e476b1b5 23 'syntax' => { 'ambiguous' => DEFAULT_OFF,
599cee73 24 'semicolon' => DEFAULT_OFF,
e476b1b5 25 'precedence' => DEFAULT_OFF,
4673fc70 26 'bareword' => DEFAULT_OFF,
599cee73 27 'reserved' => DEFAULT_OFF,
627300f0 28 'digit' => DEFAULT_OFF,
599cee73
PM
29 'parenthesis' => DEFAULT_OFF,
30 'deprecated' => DEFAULT_OFF,
31 'printf' => DEFAULT_OFF,
e476b1b5
GS
32 'prototype' => DEFAULT_OFF,
33 'qw' => DEFAULT_OFF,
599cee73 34 },
e476b1b5 35 'severe' => { 'inplace' => DEFAULT_ON,
0453d815
PM
36 'internal' => DEFAULT_ON,
37 'debugging' => DEFAULT_ON,
e476b1b5 38 'malloc' => DEFAULT_ON,
0453d815 39 },
e476b1b5
GS
40 'void' => DEFAULT_OFF,
41 'recursion' => DEFAULT_OFF,
42 'redefine' => DEFAULT_OFF,
43 'numeric' => DEFAULT_OFF,
44 'uninitialized' => DEFAULT_OFF,
45 'once' => DEFAULT_OFF,
46 'misc' => DEFAULT_OFF,
47 'regexp' => DEFAULT_OFF,
48 'glob' => DEFAULT_OFF,
49 'y2k' => DEFAULT_OFF,
50 'chmod' => DEFAULT_OFF,
51 'umask' => DEFAULT_OFF,
52 'untie' => DEFAULT_OFF,
53 'substr' => DEFAULT_OFF,
54 'taint' => DEFAULT_OFF,
55 'signal' => DEFAULT_OFF,
56 'closure' => DEFAULT_OFF,
57 'overflow' => DEFAULT_OFF,
58 'portable' => DEFAULT_OFF,
59 'utf8' => DEFAULT_OFF,
60 'exiting' => DEFAULT_OFF,
61 'pack' => DEFAULT_OFF,
62 'unpack' => DEFAULT_OFF,
0453d815 63 #'default' => DEFAULT_ON,
d3a7d8c7
GS
64 }
65} ;
599cee73
PM
66
67
68###########################################################################
69sub tab {
70 my($l, $t) = @_;
71 $t .= "\t" x ($l - (length($t) + 1) / 8);
72 $t;
73}
74
75###########################################################################
76
77my %list ;
78my %Value ;
d3a7d8c7 79my $index ;
599cee73
PM
80
81sub walk
82{
83 my $tre = shift ;
84 my @list = () ;
85 my ($k, $v) ;
86
95dfd3ab
GS
87 foreach $k (sort keys %$tre) {
88 $v = $tre->{$k};
599cee73
PM
89 die "duplicate key $k\n" if defined $list{$k} ;
90 $Value{$index} = uc $k ;
91 push @{ $list{$k} }, $index ++ ;
92 if (ref $v)
93 { push (@{ $list{$k} }, walk ($v)) }
94 push @list, @{ $list{$k} } ;
95 }
96
97 return @list ;
599cee73
PM
98}
99
100###########################################################################
101
102sub mkRange
103{
104 my @a = @_ ;
105 my @out = @a ;
106 my $i ;
107
108
109 for ($i = 1 ; $i < @a; ++ $i) {
0ca4541c 110 $out[$i] = ".."
599cee73
PM
111 if $a[$i] == $a[$i - 1] + 1 && $a[$i] + 1 == $a[$i + 1] ;
112 }
113
114 my $out = join(",",@out);
115
116 $out =~ s/,(\.\.,)+/../g ;
117 return $out;
118}
119
120###########################################################################
e476b1b5
GS
121sub printTree
122{
123 my $tre = shift ;
124 my $prefix = shift ;
125 my $indent = shift ;
126 my ($k, $v) ;
127
128 my $max = (sort {$a <=> $b} map { length $_ } keys %$tre)[-1] ;
129
130 $prefix .= " " x $indent ;
131 foreach $k (sort keys %$tre) {
132 $v = $tre->{$k};
133 print $prefix . "|\n" ;
134 print $prefix . "+- $k" ;
135 if (ref $v)
0ca4541c 136 {
e476b1b5 137 print " " . "-" x ($max - length $k ) . "+\n" ;
0ca4541c 138 printTree ($v, $prefix . "|" , $max + $indent - 1)
e476b1b5
GS
139 }
140 else
141 { print "\n" }
142 }
143
144}
145
146###########################################################################
599cee73
PM
147
148sub mkHex
149{
150 my ($max, @a) = @_ ;
151 my $mask = "\x00" x $max ;
152 my $string = "" ;
153
154 foreach (@a) {
155 vec($mask, $_, 1) = 1 ;
156 }
157
158 #$string = unpack("H$max", $mask) ;
159 #$string =~ s/(..)/\x$1/g;
160 foreach (unpack("C*", $mask)) {
161 $string .= '\x' . sprintf("%2.2x", $_) ;
162 }
163 return $string ;
164}
165
166###########################################################################
167
e476b1b5
GS
168if (@ARGV && $ARGV[0] eq "tree")
169{
d3a7d8c7 170 #print " all -+\n" ;
e476b1b5
GS
171 printTree($tree, " ", 4) ;
172 exit ;
173}
599cee73 174
4438c4b7
JH
175#unlink "warnings.h";
176#unlink "lib/warnings.pm";
177open(WARN, ">warnings.h") || die "Can't create warnings.h: $!\n";
178open(PM, ">lib/warnings.pm") || die "Can't create lib/warnings.pm: $!\n";
599cee73
PM
179
180print WARN <<'EOM' ;
181/* !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
4438c4b7 182 This file is built by warnings.pl
599cee73
PM
183 Any changes made here will be lost!
184*/
185
186
0453d815
PM
187#define Off(x) ((x) / 8)
188#define Bit(x) (1 << ((x) % 8))
599cee73
PM
189#define IsSet(a, x) ((a)[Off(x)] & Bit(x))
190
0453d815 191
599cee73 192#define G_WARN_OFF 0 /* $^W == 0 */
0453d815 193#define G_WARN_ON 1 /* -w flag and $^W != 0 */
599cee73
PM
194#define G_WARN_ALL_ON 2 /* -W flag */
195#define G_WARN_ALL_OFF 4 /* -X flag */
0453d815 196#define G_WARN_ONCE 8 /* set if 'once' ever enabled */
599cee73
PM
197#define G_WARN_ALL_MASK (G_WARN_ALL_ON|G_WARN_ALL_OFF)
198
d3a7d8c7
GS
199#define pWARN_STD Nullsv
200#define pWARN_ALL (Nullsv+1) /* use warnings 'all' */
201#define pWARN_NONE (Nullsv+2) /* no warnings 'all' */
599cee73 202
d3a7d8c7
GS
203#define specialWARN(x) ((x) == pWARN_STD || (x) == pWARN_ALL || \
204 (x) == pWARN_NONE)
599cee73
PM
205EOM
206
d3a7d8c7
GS
207my $offset = 0 ;
208
209$index = $offset ;
210#@{ $list{"all"} } = walk ($tree) ;
211walk ($tree) ;
599cee73 212
599cee73
PM
213
214$index *= 2 ;
215my $warn_size = int($index / 8) + ($index % 8 != 0) ;
216
217my $k ;
218foreach $k (sort { $a <=> $b } keys %Value) {
219 print WARN tab(5, "#define WARN_$Value{$k}"), "$k\n" ;
220}
221print WARN "\n" ;
222
223print WARN tab(5, '#define WARNsize'), "$warn_size\n" ;
224#print WARN tab(5, '#define WARN_ALLstring'), '"', ('\377' x $warn_size) , "\"\n" ;
225print WARN tab(5, '#define WARN_ALLstring'), '"', ('\125' x $warn_size) , "\"\n" ;
226print WARN tab(5, '#define WARN_NONEstring'), '"', ('\0' x $warn_size) , "\"\n" ;
227
228print WARN <<'EOM';
229
d5a71f30
GS
230#define isLEXWARN_on (PL_curcop->cop_warnings != pWARN_STD)
231#define isLEXWARN_off (PL_curcop->cop_warnings == pWARN_STD)
232#define isWARN_ONCE (PL_dowarn & (G_WARN_ON|G_WARN_ONCE))
233#define isWARN_on(c,x) (IsSet(SvPVX(c), 2*(x)))
234#define isWARNf_on(c,x) (IsSet(SvPVX(c), 2*(x)+1))
235
236#define ckDEAD(x) \
237 ( ! specialWARN(PL_curcop->cop_warnings) && \
238 ( isWARNf_on(PL_curcop->cop_warnings, WARN_ALL) || \
239 isWARNf_on(PL_curcop->cop_warnings, x)))
240
241#define ckWARN(x) \
242 ( (isLEXWARN_on && PL_curcop->cop_warnings != pWARN_NONE && \
243 (PL_curcop->cop_warnings == pWARN_ALL || \
244 isWARN_on(PL_curcop->cop_warnings, x) ) ) \
245 || (isLEXWARN_off && PL_dowarn & G_WARN_ON) )
246
247#define ckWARN2(x,y) \
248 ( (isLEXWARN_on && PL_curcop->cop_warnings != pWARN_NONE && \
249 (PL_curcop->cop_warnings == pWARN_ALL || \
250 isWARN_on(PL_curcop->cop_warnings, x) || \
251 isWARN_on(PL_curcop->cop_warnings, y) ) ) \
252 || (isLEXWARN_off && PL_dowarn & G_WARN_ON) )
253
254#define ckWARN_d(x) \
255 (isLEXWARN_off || PL_curcop->cop_warnings == pWARN_ALL || \
256 (PL_curcop->cop_warnings != pWARN_NONE && \
257 isWARN_on(PL_curcop->cop_warnings, x) ) )
258
259#define ckWARN2_d(x,y) \
260 (isLEXWARN_off || PL_curcop->cop_warnings == pWARN_ALL || \
261 (PL_curcop->cop_warnings != pWARN_NONE && \
262 (isWARN_on(PL_curcop->cop_warnings, x) || \
263 isWARN_on(PL_curcop->cop_warnings, y) ) ) )
264
4438c4b7 265/* end of file warnings.h */
599cee73
PM
266
267EOM
268
269close WARN ;
270
271while (<DATA>) {
272 last if /^KEYWORDS$/ ;
273 print PM $_ ;
274}
275
d3a7d8c7
GS
276#$list{'all'} = [ $offset .. 8 * ($warn_size/2) - 1 ] ;
277
278#my %Keys = map {lc $Value{$_}, $_} keys %Value ;
279
280print PM "%Offsets = (\n" ;
281foreach my $k (sort { $a <=> $b } keys %Value) {
282 my $v = lc $Value{$k} ;
283 $k *= 2 ;
284 print PM tab(4, " '$v'"), "=> $k,\n" ;
285}
286
287print PM " );\n\n" ;
288
599cee73
PM
289print PM "%Bits = (\n" ;
290foreach $k (sort keys %list) {
291
292 my $v = $list{$k} ;
293 my @list = sort { $a <=> $b } @$v ;
294
0ca4541c
NIS
295 print PM tab(4, " '$k'"), '=> "',
296 # mkHex($warn_size, @list),
297 mkHex($warn_size, map $_ * 2 , @list),
599cee73
PM
298 '", # [', mkRange(@list), "]\n" ;
299}
300
301print PM " );\n\n" ;
302
303print PM "%DeadBits = (\n" ;
304foreach $k (sort keys %list) {
305
306 my $v = $list{$k} ;
307 my @list = sort { $a <=> $b } @$v ;
308
0ca4541c
NIS
309 print PM tab(4, " '$k'"), '=> "',
310 # mkHex($warn_size, @list),
311 mkHex($warn_size, map $_ * 2 + 1 , @list),
599cee73
PM
312 '", # [', mkRange(@list), "]\n" ;
313}
314
315print PM " );\n\n" ;
d3a7d8c7
GS
316print PM '$NONE = "', ('\0' x $warn_size) , "\";\n" ;
317print PM '$LAST_BIT = ' . "$index ;\n" ;
318print PM '$BYTES = ' . "$warn_size ;\n" ;
599cee73
PM
319while (<DATA>) {
320 print PM $_ ;
321}
322
323close PM ;
324
325__END__
326
4438c4b7 327# This file was created by warnings.pl
599cee73
PM
328# Any changes made here will be lost.
329#
330
4438c4b7 331package warnings;
599cee73 332
b75c8c73
MS
333our $VERSION = '1.00';
334
599cee73
PM
335=head1 NAME
336
4438c4b7 337warnings - Perl pragma to control optional warnings
599cee73
PM
338
339=head1 SYNOPSIS
340
4438c4b7
JH
341 use warnings;
342 no warnings;
599cee73 343
4438c4b7
JH
344 use warnings "all";
345 no warnings "all";
599cee73 346
d3a7d8c7
GS
347 use warnings::register;
348 if (warnings::enabled()) {
349 warnings::warn("some warning");
350 }
351
352 if (warnings::enabled("void")) {
e476b1b5
GS
353 warnings::warn("void", "some warning");
354 }
355
7e6d00f8
PM
356 if (warnings::enabled($object)) {
357 warnings::warn($object, "some warning");
358 }
359
360 warnif("some warning");
361 warnif("void", "some warning");
362 warnif($object, "some warning");
363
599cee73
PM
364=head1 DESCRIPTION
365
0453d815
PM
366If no import list is supplied, all possible warnings are either enabled
367or disabled.
599cee73 368
0ca4541c 369A number of functions are provided to assist module authors.
e476b1b5
GS
370
371=over 4
372
d3a7d8c7
GS
373=item use warnings::register
374
7e6d00f8
PM
375Creates a new warnings category with the same name as the package where
376the call to the pragma is used.
377
378=item warnings::enabled()
379
380Use the warnings category with the same name as the current package.
381
382Return TRUE if that warnings category is enabled in the calling module.
383Otherwise returns FALSE.
384
385=item warnings::enabled($category)
386
387Return TRUE if the warnings category, C<$category>, is enabled in the
388calling module.
389Otherwise returns FALSE.
390
391=item warnings::enabled($object)
392
393Use the name of the class for the object reference, C<$object>, as the
394warnings category.
395
396Return TRUE if that warnings category is enabled in the first scope
397where the object is used.
398Otherwise returns FALSE.
399
400=item warnings::warn($message)
401
402Print C<$message> to STDERR.
403
404Use the warnings category with the same name as the current package.
405
406If that warnings category has been set to "FATAL" in the calling module
407then die. Otherwise return.
408
409=item warnings::warn($category, $message)
410
411Print C<$message> to STDERR.
412
413If the warnings category, C<$category>, has been set to "FATAL" in the
414calling module then die. Otherwise return.
d3a7d8c7 415
7e6d00f8 416=item warnings::warn($object, $message)
e476b1b5 417
7e6d00f8 418Print C<$message> to STDERR.
e476b1b5 419
7e6d00f8
PM
420Use the name of the class for the object reference, C<$object>, as the
421warnings category.
e476b1b5 422
7e6d00f8
PM
423If that warnings category has been set to "FATAL" in the scope where C<$object>
424is first used then die. Otherwise return.
599cee73 425
e476b1b5 426
7e6d00f8
PM
427=item warnings::warnif($message)
428
429Equivalent to:
430
431 if (warnings::enabled())
432 { warnings::warn($message) }
433
434=item warnings::warnif($category, $message)
435
436Equivalent to:
437
438 if (warnings::enabled($category))
439 { warnings::warn($category, $message) }
440
441=item warnings::warnif($object, $message)
442
443Equivalent to:
444
445 if (warnings::enabled($object))
446 { warnings::warn($object, $message) }
d3a7d8c7 447
e476b1b5
GS
448=back
449
749f83fa 450See L<perlmodlib/Pragmatic Modules> and L<perllexwarn>.
599cee73
PM
451
452=cut
453
454use Carp ;
455
456KEYWORDS
457
d3a7d8c7
GS
458$All = "" ; vec($All, $Offsets{'all'}, 2) = 3 ;
459
599cee73
PM
460sub bits {
461 my $mask ;
462 my $catmask ;
463 my $fatal = 0 ;
464 foreach my $word (@_) {
327afb7f
GS
465 if ($word eq 'FATAL') {
466 $fatal = 1;
467 }
d3a7d8c7
GS
468 elsif ($catmask = $Bits{$word}) {
469 $mask |= $catmask ;
470 $mask |= $DeadBits{$word} if $fatal ;
599cee73 471 }
d3a7d8c7 472 else
0ca4541c 473 { croak("unknown warnings category '$word'")}
599cee73
PM
474 }
475
476 return $mask ;
477}
478
479sub import {
480 shift;
f1f33818
PM
481 my $mask = ${^WARNING_BITS} ;
482 if (vec($mask, $Offsets{'all'}, 1)) {
483 $mask |= $Bits{'all'} ;
484 $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
485 }
486 ${^WARNING_BITS} = $mask | bits(@_ ? @_ : 'all') ;
599cee73
PM
487}
488
489sub unimport {
490 shift;
d3a7d8c7
GS
491 my $mask = ${^WARNING_BITS} ;
492 if (vec($mask, $Offsets{'all'}, 1)) {
f1f33818 493 $mask |= $Bits{'all'} ;
d3a7d8c7
GS
494 $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
495 }
496 ${^WARNING_BITS} = $mask & ~ (bits(@_ ? @_ : 'all') | $All) ;
599cee73
PM
497}
498
7e6d00f8 499sub __chk
599cee73 500{
d3a7d8c7
GS
501 my $category ;
502 my $offset ;
7e6d00f8 503 my $isobj = 0 ;
d3a7d8c7
GS
504
505 if (@_) {
506 # check the category supplied.
507 $category = shift ;
7e6d00f8
PM
508 if (ref $category) {
509 croak ("not an object")
510 if $category !~ /^([^=]+)=/ ;+
511 $category = $1 ;
512 $isobj = 1 ;
513 }
d3a7d8c7
GS
514 $offset = $Offsets{$category};
515 croak("unknown warnings category '$category'")
516 unless defined $offset;
517 }
518 else {
0ca4541c 519 $category = (caller(1))[0] ;
d3a7d8c7
GS
520 $offset = $Offsets{$category};
521 croak("package '$category' not registered for warnings")
522 unless defined $offset ;
523 }
524
0ca4541c 525 my $this_pkg = (caller(1))[0] ;
7e6d00f8
PM
526 my $i = 2 ;
527 my $pkg ;
528
529 if ($isobj) {
530 while (do { { package DB; $pkg = (caller($i++))[0] } } ) {
531 last unless @DB::args && $DB::args[0] =~ /^$category=/ ;
532 }
533 $i -= 2 ;
534 }
535 else {
536 for ($i = 2 ; $pkg = (caller($i))[0] ; ++ $i) {
537 last if $pkg ne $this_pkg ;
538 }
0ca4541c 539 $i = 2
7e6d00f8
PM
540 if !$pkg || $pkg eq $this_pkg ;
541 }
542
0ca4541c 543 my $callers_bitmask = (caller($i))[9] ;
7e6d00f8
PM
544 return ($callers_bitmask, $offset, $i) ;
545}
546
547sub enabled
548{
549 croak("Usage: warnings::enabled([category])")
550 unless @_ == 1 || @_ == 0 ;
551
552 my ($callers_bitmask, $offset, $i) = __chk(@_) ;
553
554 return 0 unless defined $callers_bitmask ;
d3a7d8c7
GS
555 return vec($callers_bitmask, $offset, 1) ||
556 vec($callers_bitmask, $Offsets{'all'}, 1) ;
599cee73
PM
557}
558
d3a7d8c7 559
e476b1b5
GS
560sub warn
561{
d3a7d8c7
GS
562 croak("Usage: warnings::warn([category,] 'message')")
563 unless @_ == 2 || @_ == 1 ;
d3a7d8c7 564
7e6d00f8
PM
565 my $message = pop ;
566 my ($callers_bitmask, $offset, $i) = __chk(@_) ;
567 local $Carp::CarpLevel = $i ;
0ca4541c 568 croak($message)
d3a7d8c7
GS
569 if vec($callers_bitmask, $offset+1, 1) ||
570 vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
e476b1b5
GS
571 carp($message) ;
572}
573
7e6d00f8
PM
574sub warnif
575{
576 croak("Usage: warnings::warnif([category,] 'message')")
577 unless @_ == 2 || @_ == 1 ;
578
579 my $message = pop ;
580 my ($callers_bitmask, $offset, $i) = __chk(@_) ;
581 local $Carp::CarpLevel = $i ;
582
0ca4541c 583 return
7e6d00f8
PM
584 unless defined $callers_bitmask &&
585 (vec($callers_bitmask, $offset, 1) ||
586 vec($callers_bitmask, $Offsets{'all'}, 1)) ;
587
0ca4541c 588 croak($message)
7e6d00f8
PM
589 if vec($callers_bitmask, $offset+1, 1) ||
590 vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
591
592 carp($message) ;
593}
599cee73 5941;