Once again syncing after too long an absence
[p5sagit/p5-mst-13.2.git] / warnings.pl
CommitLineData
599cee73 1#!/usr/bin/perl
2
0e06870b 3
4$VERSION = '1.00';
5
73f0cc2d 6BEGIN {
7 push @INC, './lib';
8}
599cee73 9use strict ;
10
11sub DEFAULT_ON () { 1 }
12sub DEFAULT_OFF () { 2 }
13
14my $tree = {
ee8c7f54 15
16'all' => {
e476b1b5 17 'io' => { 'pipe' => DEFAULT_OFF,
599cee73 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 29 'parenthesis' => DEFAULT_OFF,
30 'deprecated' => DEFAULT_OFF,
31 'printf' => DEFAULT_OFF,
e476b1b5 32 'prototype' => DEFAULT_OFF,
33 'qw' => DEFAULT_OFF,
599cee73 34 },
e476b1b5 35 'severe' => { 'inplace' => DEFAULT_ON,
0453d815 36 'internal' => DEFAULT_ON,
37 'debugging' => DEFAULT_ON,
e476b1b5 38 'malloc' => DEFAULT_ON,
0453d815 39 },
e476b1b5 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,
ee8c7f54 64 }
65} ;
599cee73 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 ;
ee8c7f54 79my $index ;
599cee73 80
81sub walk
82{
83 my $tre = shift ;
84 my @list = () ;
85 my ($k, $v) ;
86
95dfd3ab 87 foreach $k (sort keys %$tre) {
88 $v = $tre->{$k};
599cee73 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 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) {
0e06870b 110 $out[$i] = ".."
599cee73 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 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)
0e06870b 136 {
e476b1b5 137 print " " . "-" x ($max - length $k ) . "+\n" ;
0e06870b 138 printTree ($v, $prefix . "|" , $max + $indent - 1)
e476b1b5 139 }
140 else
141 { print "\n" }
142 }
143
144}
145
146###########################################################################
599cee73 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 168if (@ARGV && $ARGV[0] eq "tree")
169{
ee8c7f54 170 #print " all -+\n" ;
e476b1b5 171 printTree($tree, " ", 4) ;
172 exit ;
173}
599cee73 174
4438c4b7 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 179
180print WARN <<'EOM' ;
181/* !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
4438c4b7 182 This file is built by warnings.pl
599cee73 183 Any changes made here will be lost!
184*/
185
186
0453d815 187#define Off(x) ((x) / 8)
188#define Bit(x) (1 << ((x) % 8))
599cee73 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 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 197#define G_WARN_ALL_MASK (G_WARN_ALL_ON|G_WARN_ALL_OFF)
198
ee8c7f54 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
ee8c7f54 203#define specialWARN(x) ((x) == pWARN_STD || (x) == pWARN_ALL || \
204 (x) == pWARN_NONE)
599cee73 205EOM
206
ee8c7f54 207my $offset = 0 ;
208
209$index = $offset ;
210#@{ $list{"all"} } = walk ($tree) ;
211walk ($tree) ;
599cee73 212
599cee73 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
ee8c7f54 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 266
267EOM
268
269close WARN ;
270
271while (<DATA>) {
272 last if /^KEYWORDS$/ ;
273 print PM $_ ;
274}
275
ee8c7f54 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 289print PM "%Bits = (\n" ;
290foreach $k (sort keys %list) {
291
292 my $v = $list{$k} ;
293 my @list = sort { $a <=> $b } @$v ;
294
0e06870b 295 print PM tab(4, " '$k'"), '=> "',
296 # mkHex($warn_size, @list),
297 mkHex($warn_size, map $_ * 2 , @list),
599cee73 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
0e06870b 309 print PM tab(4, " '$k'"), '=> "',
310 # mkHex($warn_size, @list),
311 mkHex($warn_size, map $_ * 2 + 1 , @list),
599cee73 312 '", # [', mkRange(@list), "]\n" ;
313}
314
315print PM " );\n\n" ;
ee8c7f54 316print PM '$NONE = "', ('\0' x $warn_size) , "\";\n" ;
317print PM '$LAST_BIT = ' . "$index ;\n" ;
318print PM '$BYTES = ' . "$warn_size ;\n" ;
599cee73 319while (<DATA>) {
320 print PM $_ ;
321}
322
323close PM ;
324
325__END__
326
4438c4b7 327# This file was created by warnings.pl
599cee73 328# Any changes made here will be lost.
329#
330
4438c4b7 331package warnings;
599cee73 332
0e06870b 333our $VERSION = '1.00';
334
599cee73 335=head1 NAME
336
4438c4b7 337warnings - Perl pragma to control optional warnings
599cee73 338
339=head1 SYNOPSIS
340
4438c4b7 341 use warnings;
342 no warnings;
599cee73 343
4438c4b7 344 use warnings "all";
345 no warnings "all";
599cee73 346
ee8c7f54 347 use warnings::register;
348 if (warnings::enabled()) {
349 warnings::warn("some warning");
350 }
351
352 if (warnings::enabled("void")) {
e476b1b5 353 warnings::warn("void", "some warning");
354 }
355
22d4bb9c 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 364=head1 DESCRIPTION
365
0453d815 366If no import list is supplied, all possible warnings are either enabled
367or disabled.
599cee73 368
0e06870b 369A number of functions are provided to assist module authors.
e476b1b5 370
371=over 4
372
ee8c7f54 373=item use warnings::register
374
22d4bb9c 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.
415
416=item warnings::warn($object, $message)
ee8c7f54 417
22d4bb9c 418Print C<$message> to STDERR.
e476b1b5 419
22d4bb9c 420Use the name of the class for the object reference, C<$object>, as the
421warnings category.
e476b1b5 422
22d4bb9c 423If that warnings category has been set to "FATAL" in the scope where C<$object>
424is first used then die. Otherwise return.
e476b1b5 425
599cee73 426
22d4bb9c 427=item warnings::warnif($message)
e476b1b5 428
22d4bb9c 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) }
ee8c7f54 447
e476b1b5 448=back
449
4b19af01 450See L<perlmodlib/Pragmatic Modules> and L<perllexwarn>.
599cee73 451
452=cut
453
454use Carp ;
455
456KEYWORDS
457
ee8c7f54 458$All = "" ; vec($All, $Offsets{'all'}, 2) = 3 ;
459
599cee73 460sub bits {
461 my $mask ;
462 my $catmask ;
463 my $fatal = 0 ;
464 foreach my $word (@_) {
327afb7f 465 if ($word eq 'FATAL') {
466 $fatal = 1;
467 }
ee8c7f54 468 elsif ($catmask = $Bits{$word}) {
469 $mask |= $catmask ;
470 $mask |= $DeadBits{$word} if $fatal ;
599cee73 471 }
ee8c7f54 472 else
0e06870b 473 { croak("unknown warnings category '$word'")}
599cee73 474 }
475
476 return $mask ;
477}
478
479sub import {
480 shift;
22d4bb9c 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 487}
488
489sub unimport {
490 shift;
ee8c7f54 491 my $mask = ${^WARNING_BITS} ;
492 if (vec($mask, $Offsets{'all'}, 1)) {
22d4bb9c 493 $mask |= $Bits{'all'} ;
ee8c7f54 494 $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
495 }
496 ${^WARNING_BITS} = $mask & ~ (bits(@_ ? @_ : 'all') | $All) ;
599cee73 497}
498
22d4bb9c 499sub __chk
599cee73 500{
ee8c7f54 501 my $category ;
502 my $offset ;
22d4bb9c 503 my $isobj = 0 ;
ee8c7f54 504
505 if (@_) {
506 # check the category supplied.
507 $category = shift ;
22d4bb9c 508 if (ref $category) {
509 croak ("not an object")
510 if $category !~ /^([^=]+)=/ ;+
511 $category = $1 ;
512 $isobj = 1 ;
513 }
ee8c7f54 514 $offset = $Offsets{$category};
515 croak("unknown warnings category '$category'")
516 unless defined $offset;
517 }
518 else {
0e06870b 519 $category = (caller(1))[0] ;
ee8c7f54 520 $offset = $Offsets{$category};
521 croak("package '$category' not registered for warnings")
522 unless defined $offset ;
523 }
524
0e06870b 525 my $this_pkg = (caller(1))[0] ;
22d4bb9c 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 }
0e06870b 539 $i = 2
22d4bb9c 540 if !$pkg || $pkg eq $this_pkg ;
541 }
542
0e06870b 543 my $callers_bitmask = (caller($i))[9] ;
22d4bb9c 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 ;
ee8c7f54 555 return vec($callers_bitmask, $offset, 1) ||
556 vec($callers_bitmask, $Offsets{'all'}, 1) ;
599cee73 557}
558
ee8c7f54 559
e476b1b5 560sub warn
561{
ee8c7f54 562 croak("Usage: warnings::warn([category,] 'message')")
563 unless @_ == 2 || @_ == 1 ;
ee8c7f54 564
22d4bb9c 565 my $message = pop ;
566 my ($callers_bitmask, $offset, $i) = __chk(@_) ;
567 local $Carp::CarpLevel = $i ;
0e06870b 568 croak($message)
ee8c7f54 569 if vec($callers_bitmask, $offset+1, 1) ||
570 vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
e476b1b5 571 carp($message) ;
572}
573
22d4bb9c 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
0e06870b 583 return
22d4bb9c 584 unless defined $callers_bitmask &&
585 (vec($callers_bitmask, $offset, 1) ||
586 vec($callers_bitmask, $Offsets{'all'}, 1)) ;
587
0e06870b 588 croak($message)
22d4bb9c 589 if vec($callers_bitmask, $offset+1, 1) ||
590 vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
591
592 carp($message) ;
593}
599cee73 5941;