Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

549 lines
14 KiB

  1. @rem = '--*-Perl-*--
  2. @echo off
  3. if "%OS%" == "Windows_NT" goto WinNT
  4. perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
  5. goto endofperl
  6. :WinNT
  7. perl -x -S "%0" %*
  8. if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
  9. if %errorlevel% == 9009 echo You do not have Perl in your PATH.
  10. goto endofperl
  11. @rem ';
  12. #!perl
  13. #line 14
  14. eval 'exec P:\Apps\ActivePerl\temp\bin\MSWin32-x86-object\perl.exe -S $0 ${1+"$@"}'
  15. if $running_under_some_shell;
  16. =head1 NAME
  17. diagnostics - Perl compiler pragma to force verbose warning diagnostics
  18. splain - standalone program to do the same thing
  19. =head1 SYNOPSIS
  20. As a pragma:
  21. use diagnostics;
  22. use diagnostics -verbose;
  23. enable diagnostics;
  24. disable diagnostics;
  25. Aa a program:
  26. perl program 2>diag.out
  27. splain [-v] [-p] diag.out
  28. =head1 DESCRIPTION
  29. =head2 The C<diagnostics> Pragma
  30. This module extends the terse diagnostics normally emitted by both the
  31. perl compiler and the perl interpreter, augmenting them with the more
  32. explicative and endearing descriptions found in L<perldiag>. Like the
  33. other pragmata, it affects the compilation phase of your program rather
  34. than merely the execution phase.
  35. To use in your program as a pragma, merely invoke
  36. use diagnostics;
  37. at the start (or near the start) of your program. (Note
  38. that this I<does> enable perl's B<-w> flag.) Your whole
  39. compilation will then be subject(ed :-) to the enhanced diagnostics.
  40. These still go out B<STDERR>.
  41. Due to the interaction between runtime and compiletime issues,
  42. and because it's probably not a very good idea anyway,
  43. you may not use C<no diagnostics> to turn them off at compiletime.
  44. However, you may control there behaviour at runtime using the
  45. disable() and enable() methods to turn them off and on respectively.
  46. The B<-verbose> flag first prints out the L<perldiag> introduction before
  47. any other diagnostics. The $diagnostics::PRETTY variable can generate nicer
  48. escape sequences for pagers.
  49. =head2 The I<splain> Program
  50. While apparently a whole nuther program, I<splain> is actually nothing
  51. more than a link to the (executable) F<diagnostics.pm> module, as well as
  52. a link to the F<diagnostics.pod> documentation. The B<-v> flag is like
  53. the C<use diagnostics -verbose> directive.
  54. The B<-p> flag is like the
  55. $diagnostics::PRETTY variable. Since you're post-processing with
  56. I<splain>, there's no sense in being able to enable() or disable() processing.
  57. Output from I<splain> is directed to B<STDOUT>, unlike the pragma.
  58. =head1 EXAMPLES
  59. The following file is certain to trigger a few errors at both
  60. runtime and compiletime:
  61. use diagnostics;
  62. print NOWHERE "nothing\n";
  63. print STDERR "\n\tThis message should be unadorned.\n";
  64. warn "\tThis is a user warning";
  65. print "\nDIAGNOSTIC TESTER: Please enter a <CR> here: ";
  66. my $a, $b = scalar <STDIN>;
  67. print "\n";
  68. print $x/$y;
  69. If you prefer to run your program first and look at its problem
  70. afterwards, do this:
  71. perl -w test.pl 2>test.out
  72. ./splain < test.out
  73. Note that this is not in general possible in shells of more dubious heritage,
  74. as the theoretical
  75. (perl -w test.pl >/dev/tty) >& test.out
  76. ./splain < test.out
  77. Because you just moved the existing B<stdout> to somewhere else.
  78. If you don't want to modify your source code, but still have on-the-fly
  79. warnings, do this:
  80. exec 3>&1; perl -w test.pl 2>&1 1>&3 3>&- | splain 1>&2 3>&-
  81. Nifty, eh?
  82. If you want to control warnings on the fly, do something like this.
  83. Make sure you do the C<use> first, or you won't be able to get
  84. at the enable() or disable() methods.
  85. use diagnostics; # checks entire compilation phase
  86. print "\ntime for 1st bogus diags: SQUAWKINGS\n";
  87. print BOGUS1 'nada';
  88. print "done with 1st bogus\n";
  89. disable diagnostics; # only turns off runtime warnings
  90. print "\ntime for 2nd bogus: (squelched)\n";
  91. print BOGUS2 'nada';
  92. print "done with 2nd bogus\n";
  93. enable diagnostics; # turns back on runtime warnings
  94. print "\ntime for 3rd bogus: SQUAWKINGS\n";
  95. print BOGUS3 'nada';
  96. print "done with 3rd bogus\n";
  97. disable diagnostics;
  98. print "\ntime for 4th bogus: (squelched)\n";
  99. print BOGUS4 'nada';
  100. print "done with 4th bogus\n";
  101. =head1 INTERNALS
  102. Diagnostic messages derive from the F<perldiag.pod> file when available at
  103. runtime. Otherwise, they may be embedded in the file itself when the
  104. splain package is built. See the F<Makefile> for details.
  105. If an extant $SIG{__WARN__} handler is discovered, it will continue
  106. to be honored, but only after the diagnostics::splainthis() function
  107. (the module's $SIG{__WARN__} interceptor) has had its way with your
  108. warnings.
  109. There is a $diagnostics::DEBUG variable you may set if you're desperately
  110. curious what sorts of things are being intercepted.
  111. BEGIN { $diagnostics::DEBUG = 1 }
  112. =head1 BUGS
  113. Not being able to say "no diagnostics" is annoying, but may not be
  114. insurmountable.
  115. The C<-pretty> directive is called too late to affect matters.
  116. You have to do this instead, and I<before> you load the module.
  117. BEGIN { $diagnostics::PRETTY = 1 }
  118. I could start up faster by delaying compilation until it should be
  119. needed, but this gets a "panic: top_level" when using the pragma form
  120. in Perl 5.001e.
  121. While it's true that this documentation is somewhat subserious, if you use
  122. a program named I<splain>, you should expect a bit of whimsy.
  123. =head1 AUTHOR
  124. Tom Christiansen <F<[email protected]>>, 25 June 1995.
  125. =cut
  126. require 5.001;
  127. use Carp;
  128. use Config;
  129. ($privlib, $archlib) = @Config{qw(privlibexp archlibexp)};
  130. if ($^O eq 'VMS') {
  131. require VMS::Filespec;
  132. $privlib = VMS::Filespec::unixify($privlib);
  133. $archlib = VMS::Filespec::unixify($archlib);
  134. }
  135. @trypod = ("$archlib/pod/perldiag.pod",
  136. "$privlib/pod/perldiag-$].pod",
  137. "$privlib/pod/perldiag.pod");
  138. # handy for development testing of new warnings etc
  139. unshift @trypod, "./pod/perldiag.pod" if -e "pod/perldiag.pod";
  140. ($PODFILE) = ((grep { -e } @trypod), $trypod[$#trypod])[0];
  141. $DEBUG ||= 0;
  142. my $WHOAMI = ref bless []; # nobody's business, prolly not even mine
  143. $| = 1;
  144. local $_;
  145. CONFIG: {
  146. $opt_p = $opt_d = $opt_v = $opt_f = '';
  147. %HTML_2_Troff = %HTML_2_Latin_1 = %HTML_2_ASCII_7 = ();
  148. %exact_duplicate = ();
  149. unless (caller) {
  150. $standalone++;
  151. require Getopt::Std;
  152. Getopt::Std::getopts('pdvf:')
  153. or die "Usage: $0 [-v] [-p] [-f splainpod]";
  154. $PODFILE = $opt_f if $opt_f;
  155. $DEBUG = 2 if $opt_d;
  156. $VERBOSE = $opt_v;
  157. $PRETTY = $opt_p;
  158. }
  159. if (open(POD_DIAG, $PODFILE)) {
  160. warn "Happy happy podfile from real $PODFILE\n" if $DEBUG;
  161. last CONFIG;
  162. }
  163. if (caller) {
  164. INCPATH: {
  165. for $file ( (map { "$_/$WHOAMI.pm" } @INC), $0) {
  166. warn "Checking $file\n" if $DEBUG;
  167. if (open(POD_DIAG, $file)) {
  168. while (<POD_DIAG>) {
  169. next unless /^__END__\s*# wish diag dbase were more accessible/;
  170. print STDERR "podfile is $file\n" if $DEBUG;
  171. last INCPATH;
  172. }
  173. }
  174. }
  175. }
  176. } else {
  177. print STDERR "podfile is <DATA>\n" if $DEBUG;
  178. *POD_DIAG = *main::DATA;
  179. }
  180. }
  181. if (eof(POD_DIAG)) {
  182. die "couldn't find diagnostic data in $PODFILE @INC $0";
  183. }
  184. %HTML_2_Troff = (
  185. 'amp' => '&', # ampersand
  186. 'lt' => '<', # left chevron, less-than
  187. 'gt' => '>', # right chevron, greater-than
  188. 'quot' => '"', # double quote
  189. "Aacute" => "A\\*'", # capital A, acute accent
  190. # etc
  191. );
  192. %HTML_2_Latin_1 = (
  193. 'amp' => '&', # ampersand
  194. 'lt' => '<', # left chevron, less-than
  195. 'gt' => '>', # right chevron, greater-than
  196. 'quot' => '"', # double quote
  197. "Aacute" => "\xC1" # capital A, acute accent
  198. # etc
  199. );
  200. %HTML_2_ASCII_7 = (
  201. 'amp' => '&', # ampersand
  202. 'lt' => '<', # left chevron, less-than
  203. 'gt' => '>', # right chevron, greater-than
  204. 'quot' => '"', # double quote
  205. "Aacute" => "A" # capital A, acute accent
  206. # etc
  207. );
  208. *HTML_Escapes = do {
  209. if ($standalone) {
  210. $PRETTY ? \%HTML_2_Latin_1 : \%HTML_2_ASCII_7;
  211. } else {
  212. \%HTML_2_Latin_1;
  213. }
  214. };
  215. *THITHER = $standalone ? *STDOUT : *STDERR;
  216. $transmo = <<EOFUNC;
  217. sub transmo {
  218. local \$^W = 0; # recursive warnings we do NOT need!
  219. study;
  220. EOFUNC
  221. ### sub finish_compilation { # 5.001e panic: top_level for embedded version
  222. print STDERR "FINISHING COMPILATION for $_\n" if $DEBUG;
  223. ### local
  224. $RS = '';
  225. local $_;
  226. while (<POD_DIAG>) {
  227. #s/(.*)\n//;
  228. #$header = $1;
  229. unescape();
  230. if ($PRETTY) {
  231. sub noop { return $_[0] } # spensive for a noop
  232. sub bold { my $str =$_[0]; $str =~ s/(.)/$1\b$1/g; return $str; }
  233. sub italic { my $str = $_[0]; $str =~ s/(.)/_\b$1/g; return $str; }
  234. s/[BC]<(.*?)>/bold($1)/ges;
  235. s/[LIF]<(.*?)>/italic($1)/ges;
  236. } else {
  237. s/[BC]<(.*?)>/$1/gs;
  238. s/[LIF]<(.*?)>/$1/gs;
  239. }
  240. unless (/^=/) {
  241. if (defined $header) {
  242. if ( $header eq 'DESCRIPTION' &&
  243. ( /Optional warnings are enabled/
  244. || /Some of these messages are generic./
  245. ) )
  246. {
  247. next;
  248. }
  249. s/^/ /gm;
  250. $msg{$header} .= $_;
  251. }
  252. next;
  253. }
  254. unless ( s/=item (.*)\s*\Z//) {
  255. if ( s/=head1\sDESCRIPTION//) {
  256. $msg{$header = 'DESCRIPTION'} = '';
  257. }
  258. next;
  259. }
  260. # strip formatting directives in =item line
  261. ($header = $1) =~ s/[A-Z]<(.*?)>/$1/g;
  262. if ($header =~ /%[sd]/) {
  263. $rhs = $lhs = $header;
  264. #if ($lhs =~ s/(.*?)%d(?!%d)(.*)/\Q$1\E\\d+\Q$2\E\$/g) {
  265. if ($lhs =~ s/(.*?)%d(?!%d)(.*)/\Q$1\E\\d+\Q$2\E/g) {
  266. $lhs =~ s/\\%s/.*?/g;
  267. } else {
  268. # if i had lookbehind negations, i wouldn't have to do this \377 noise
  269. $lhs =~ s/(.*?)%s/\Q$1\E.*?\377/g;
  270. #$lhs =~ s/\377([^\377]*)$/\Q$1\E\$/;
  271. $lhs =~ s/\377([^\377]*)$/\Q$1\E/;
  272. $lhs =~ s/\377//g;
  273. $lhs =~ s/\.\*\?$/.*/; # Allow %s at the end to eat it all
  274. }
  275. $transmo .= " s{^$lhs}\n {\Q$rhs\E}s\n\t&& return 1;\n";
  276. } else {
  277. $transmo .= " m{^\Q$header\E} && return 1;\n";
  278. }
  279. print STDERR "$WHOAMI: Duplicate entry: \"$header\"\n"
  280. if $msg{$header};
  281. $msg{$header} = '';
  282. }
  283. close POD_DIAG unless *main::DATA eq *POD_DIAG;
  284. die "No diagnostics?" unless %msg;
  285. $transmo .= " return 0;\n}\n";
  286. print STDERR $transmo if $DEBUG;
  287. eval $transmo;
  288. die $@ if $@;
  289. $RS = "\n";
  290. ### }
  291. if ($standalone) {
  292. if (!@ARGV and -t STDIN) { print STDERR "$0: Reading from STDIN\n" }
  293. while (defined ($error = <>)) {
  294. splainthis($error) || print THITHER $error;
  295. }
  296. exit;
  297. } else {
  298. $old_w = 0; $oldwarn = ''; $olddie = '';
  299. }
  300. sub import {
  301. shift;
  302. $old_w = $^W;
  303. $^W = 1; # yup, clobbered the global variable; tough, if you
  304. # want diags, you want diags.
  305. return if $SIG{__WARN__} eq \&warn_trap;
  306. for (@_) {
  307. /^-d(ebug)?$/ && do {
  308. $DEBUG++;
  309. next;
  310. };
  311. /^-v(erbose)?$/ && do {
  312. $VERBOSE++;
  313. next;
  314. };
  315. /^-p(retty)?$/ && do {
  316. print STDERR "$0: I'm afraid it's too late for prettiness.\n";
  317. $PRETTY++;
  318. next;
  319. };
  320. warn "Unknown flag: $_";
  321. }
  322. $oldwarn = $SIG{__WARN__};
  323. $olddie = $SIG{__DIE__};
  324. $SIG{__WARN__} = \&warn_trap;
  325. $SIG{__DIE__} = \&death_trap;
  326. }
  327. sub enable { &import }
  328. sub disable {
  329. shift;
  330. $^W = $old_w;
  331. return unless $SIG{__WARN__} eq \&warn_trap;
  332. $SIG{__WARN__} = $oldwarn;
  333. $SIG{__DIE__} = $olddie;
  334. }
  335. sub warn_trap {
  336. my $warning = $_[0];
  337. if (caller eq $WHOAMI or !splainthis($warning)) {
  338. print STDERR $warning;
  339. }
  340. &$oldwarn if defined $oldwarn and $oldwarn and $oldwarn ne \&warn_trap;
  341. };
  342. sub death_trap {
  343. my $exception = $_[0];
  344. # See if we are coming from anywhere within an eval. If so we don't
  345. # want to explain the exception because it's going to get caught.
  346. my $in_eval = 0;
  347. my $i = 0;
  348. while (1) {
  349. my $caller = (caller($i++))[3] or last;
  350. if ($caller eq '(eval)') {
  351. $in_eval = 1;
  352. last;
  353. }
  354. }
  355. splainthis($exception) unless $in_eval;
  356. if (caller eq $WHOAMI) { print STDERR "INTERNAL EXCEPTION: $exception"; }
  357. &$olddie if defined $olddie and $olddie and $olddie ne \&death_trap;
  358. # We don't want to unset these if we're coming from an eval because
  359. # then we've turned off diagnostics. (Actually what does this next
  360. # line do? -PSeibel)
  361. $SIG{__DIE__} = $SIG{__WARN__} = '' unless $in_eval;
  362. local($Carp::CarpLevel) = 1;
  363. confess "Uncaught exception from user code:\n\t$exception";
  364. # up we go; where we stop, nobody knows, but i think we die now
  365. # but i'm deeply afraid of the &$olddie guy reraising and us getting
  366. # into an indirect recursion loop
  367. };
  368. sub splainthis {
  369. local $_ = shift;
  370. local $\;
  371. ### &finish_compilation unless %msg;
  372. s/\.?\n+$//;
  373. my $orig = $_;
  374. # return unless defined;
  375. if ($exact_duplicate{$_}++) {
  376. return 1;
  377. }
  378. s/, <.*?> (?:line|chunk).*$//;
  379. $real = s/(.*?) at .*? (?:line|chunk) \d+.*/$1/;
  380. s/^\((.*)\)$/$1/;
  381. return 0 unless &transmo;
  382. $orig = shorten($orig);
  383. if ($old_diag{$_}) {
  384. autodescribe();
  385. print THITHER "$orig (#$old_diag{$_})\n";
  386. $wantspace = 1;
  387. } else {
  388. autodescribe();
  389. $old_diag{$_} = ++$count;
  390. print THITHER "\n" if $wantspace;
  391. $wantspace = 0;
  392. print THITHER "$orig (#$old_diag{$_})\n";
  393. if ($msg{$_}) {
  394. print THITHER $msg{$_};
  395. } else {
  396. if (0 and $standalone) {
  397. print THITHER " **** Error #$old_diag{$_} ",
  398. ($real ? "is" : "appears to be"),
  399. " an unknown diagnostic message.\n\n";
  400. }
  401. return 0;
  402. }
  403. }
  404. return 1;
  405. }
  406. sub autodescribe {
  407. if ($VERBOSE and not $count) {
  408. print THITHER &{$PRETTY ? \&bold : \&noop}("DESCRIPTION OF DIAGNOSTICS"),
  409. "\n$msg{DESCRIPTION}\n";
  410. }
  411. }
  412. sub unescape {
  413. s {
  414. E<
  415. ( [A-Za-z]+ )
  416. >
  417. } {
  418. do {
  419. exists $HTML_Escapes{$1}
  420. ? do { $HTML_Escapes{$1} }
  421. : do {
  422. warn "Unknown escape: E<$1> in $_";
  423. "E<$1>";
  424. }
  425. }
  426. }egx;
  427. }
  428. sub shorten {
  429. my $line = $_[0];
  430. if (length($line) > 79 and index($line, "\n") == -1) {
  431. my $space_place = rindex($line, ' ', 79);
  432. if ($space_place != -1) {
  433. substr($line, $space_place, 1) = "\n\t";
  434. }
  435. }
  436. return $line;
  437. }
  438. # have to do this: RS isn't set until run time, but we're executing at compile time
  439. $RS = "\n";
  440. 1 unless $standalone; # or it'll complain about itself
  441. __END__ # wish diag dbase were more accessible
  442. __END__
  443. :endofperl