1 ###############################################################################
3 # Package: NaturalDocs::Error
5 ###############################################################################
7 # Manages all aspects of error handling in Natural Docs.
9 ###############################################################################
11 # This file is part of Natural Docs, which is Copyright © 2003-2010 Greg Valure
12 # Natural Docs is licensed under version 3 of the GNU Affero General Public License (AGPL)
13 # Refer to License.txt for the complete details
18 $SIG{'__DIE__'} = \&NaturalDocs::Error::CatchDeath;
21 package NaturalDocs::Error;
24 ###############################################################################
29 # handle: FH_CRASHREPORT
30 # The filehandle used for generating crash reports.
36 # The stack trace generated by <CatchDeath()>.
43 # Whether the program exited using <SoftDeath()>.
50 # What Natural Docs was doing when it crashed. This stores strings generated by functions like <OnStartParsing()>.
55 ###############################################################################
62 # Generates a "soft" death, which means the program exits like with Perl's die(), but no crash report will be generated.
66 # message - The error message to die with.
68 sub SoftDeath #(message)
70 my ($self, $message) = @_;
73 if ($message !~ /\n$/)
74 { $message .= "\n"; };
81 # Function: OnStartParsing
83 # Called whenever <NaturalDocs::Parser> starts parsing a source file.
85 sub OnStartParsing #(FileName file)
87 my ($self, $file) = @_;
88 $currentAction = 'Parsing ' . $file;
93 # Function: OnEndParsing
95 # Called whenever <NaturalDocs::Parser> is done parsing a source file.
97 sub OnEndParsing #(FileName file)
99 my ($self, $file) = @_;
100 $currentAction = undef;
105 # Function: OnStartBuilding
107 # Called whenever <NaturalDocs::Builder> starts building a source file.
109 sub OnStartBuilding #(FileName file)
111 my ($self, $file) = @_;
112 $currentAction = 'Building ' . $file;
117 # Function: OnEndBuilding
119 # Called whenever <NaturalDocs::Builder> is done building a source file.
121 sub OnEndBuilding #(FileName file)
123 my ($self, $file) = @_;
124 $currentAction = undef;
129 # Function: HandleDeath
131 # Should be called whenever Natural Docs dies out of execution.
137 my $reason = $::EVAL_ERROR;
138 $reason =~ s/[\n\r]+$//;
142 . "Natural Docs encountered the following error and was stopped:\n"
144 . " " . $reason . "\n"
147 . "You can get help at the following web site:\n"
149 . " " . NaturalDocs::Settings->AppURL() . "\n"
154 my $crashReport = $self->GenerateCrashReport();
159 "If sending an error report, please include the information found in the\n"
160 . "following file:\n"
162 . " " . $crashReport . "\n"
168 "If sending an error report, please include the following information:\n"
170 . " Natural Docs version: " . NaturalDocs::Settings->TextAppVersion() . "\n"
171 . " Perl version: " . $self->PerlVersion() . " on " . $::OSNAME . "\n"
180 ###############################################################################
181 # Group: Support Functions
185 # Function: PerlVersion
186 # Returns the current Perl version as a string.
195 { $perlVersion = sprintf('%vd', $^V); }
196 if (!$perlVersion || substr($perlVersion, 0, 1) eq '%')
197 { $perlVersion = $]; };
204 # Function: GenerateCrashReport
206 # Generates a report and returns the <FileName> it's located at. Returns undef if it could not generate one.
208 sub GenerateCrashReport
212 my $errorMessage = $::EVAL_ERROR;
213 $errorMessage =~ s/[\r\n]+$//;
215 my $reportDirectory = NaturalDocs::Settings->ProjectDirectory();
217 if (!$reportDirectory || !-d $reportDirectory)
220 my $file = NaturalDocs::File->JoinPaths($reportDirectory, 'LastCrash.txt');
222 open(FH_CRASHREPORT, '>' . $file) or return undef;
225 'Crash Message:' . "\n\n"
226 . ' ' . $errorMessage . "\n\n";
231 'Current Action:' . "\n\n"
232 . ' ' . $currentAction . "\n\n";
236 'Natural Docs version ' . NaturalDocs::Settings->TextAppVersion() . "\n"
237 . 'Perl version ' . $self->PerlVersion . ' on ' . $::OSNAME . "\n\n"
238 . 'Command Line:' . "\n\n"
239 . ' ' . join(' ', @ARGV) . "\n\n";
244 'Stack Trace:' . "\n\n"
250 'Stack Trace not available.' . "\n\n";
253 close(FH_CRASHREPORT);
258 ###############################################################################
259 # Group: Signal Handlers
263 # Function: CatchDeath
265 # Catches Perl die calls.
267 # *IMPORTANT:* This function is a signal handler and should not be called manually. Also, because of this, it does not have
272 # message - The error message to die with.
274 sub CatchDeath #(message)
276 # No $self because it's a signal handler.
279 if (!$NaturalDocs::Error::softDeath)
282 my ($lastPackage, $lastFile, $lastLine, $lastFunction);
284 while (my ($package, $file, $line, $function) = caller($i))
287 { $stackTrace .= ', called from' . "\n"; };
289 $stackTrace .= ' ' . $function;
291 if (defined $lastLine)
293 $stackTrace .= ', line ' . $lastLine;
295 if ($function !~ /^NaturalDocs::/)
296 { $stackTrace .= ' of ' . $lastFile; };
299 ($lastPackage, $lastFile, $lastLine, $lastFunction) = ($package, $file, $line, $function);