rm printError, Report::error throws exception

This commit is contained in:
James Cherry 2020-12-24 16:31:52 -08:00
parent 6fb6c93847
commit 078d69fc8d
13 changed files with 163 additions and 185 deletions

View File

@ -17,7 +17,7 @@
#pragma once
#include <exception>
#include "DisallowCopyAssign.hh"
#include "Report.hh"
namespace sta {
@ -31,6 +31,16 @@ public:
virtual const char *what() const noexcept = 0;
};
class ExceptionMsg : public Exception
{
public:
ExceptionMsg(const char *msg);
virtual const char *what() const noexcept;
private:
string msg_;
};
class ExceptionLine : public Exception
{
public:

View File

@ -47,27 +47,7 @@ public:
va_list args);
void print(const string *str);
void print(const string &str);
// Print to debug stream (same as output stream).
virtual void printDebug(const char *fmt, ...)
__attribute__((format (printf, 2, 3)));
virtual void vprintDebug(const char *fmt,
va_list args);
// Print to error stream.
// Return the number of characters written.
virtual size_t printError(const char *buffer,
size_t length);
virtual void printError(const char *fmt, ...)
__attribute__((format (printf, 2, 3)));
virtual void vprintError(const char *fmt,
va_list args);
// Print to warning stream (same as error stream).
virtual void printWarn(const char *fmt, ...)
__attribute__((format (printf, 2, 3)));
virtual void vprintWarn(const char *fmt,
va_list args);
virtual void flush() {}
////////////////////////////////////////////////////////////////
@ -137,12 +117,15 @@ protected:
// Return the number of characters written.
virtual size_t printConsole(const char *buffer,
size_t length) = 0;
// Primitive to print warning, error, critical and debug output.
// Return the number of characters written.
virtual size_t printErrorConsole(const char *buffer,
size_t length) = 0;
void printToBuffer(const char *fmt,
...);
void printToBuffer(const char *fmt,
va_list args);
void printToBufferAppend(const char *fmt,
...);
void printToBufferAppend(const char *fmt,
va_list args);
void printBuffer();
void redirectStringPrint(const char *buffer,
size_t length);

View File

@ -46,7 +46,7 @@ public:
protected:
virtual size_t printConsole(const char *buffer, size_t length);
virtual size_t printErrorConsole(const char *buffer, size_t length);
void flush();
private:
DISALLOW_COPY_AND_ASSIGN(ReportTcl);

View File

@ -328,7 +328,7 @@ Genclks::ensureMaster(Clock *gclk)
iter.enqueueAdjacentVertices(vertex);
}
if (master_clk_count > 1)
report_->error(11, "generated clock %s is in the fanout of multiple clocks.",
report_->warn(11, "generated clock %s is in the fanout of multiple clocks.",
gclk->name());
}
else {
@ -379,7 +379,7 @@ Genclks::ensureMaster(Clock *gclk)
}
}
if (master_clk_count > 1)
report_->error(12,
report_->warn(12,
"generated clock %s pin %s is in the fanout of multiple clocks.",
gclk->name(),
network_->pathName(src_pin));

View File

@ -1383,7 +1383,7 @@ WritePathSpice::writeSubckts()
report_->error(28, "The following subkcts are missing from %s",
lib_subckt_filename_);
for (const char *cell_name : path_cell_names)
report_->printError(" %s\n", cell_name);
report_->print(" %s\n", cell_name);
}
}
else {

View File

@ -22,7 +22,7 @@
try { $function }
catch (std::bad_alloc &) {
fprintf(stderr, "Error: out of memory.\n");
exit(0);
exit(1);
}
catch (std::exception &excp) {
Tcl_ResetResult(interp);

View File

@ -324,11 +324,14 @@ pushPowerResultFloats(PowerResult &power,
////////////////////////////////////////////////////////////////
void
tclError(Tcl_Interp *interp,
tclArgError(Tcl_Interp *interp,
const char *msg,
const char *arg)
{
char *error = stringPrint(msg, arg);
// Swig does not add try/catch around arg parsing so this cannot use Report::error.
string error_msg = "Error: ";
error_msg += msg;
char *error = stringPrint(error_msg.c_str(), arg);
Tcl_SetResult(interp, error, TCL_VOLATILE);
stringDelete(error);
}
@ -867,7 +870,7 @@ using namespace sta;
floats->push_back(static_cast<float>(value));
else {
delete floats;
tclError(interp, "Error: %s is not a floating point number.", arg);
tclArgError(interp, "%s is not a floating point number.", arg);
return TCL_ERROR;
}
}
@ -915,7 +918,7 @@ using namespace sta;
ints->push_back(value);
else {
delete ints;
tclError(interp, "Error: %s is not an integer.", arg);
tclArgError(interp, "%s is not an integer.", arg);
return TCL_ERROR;
}
}
@ -930,7 +933,7 @@ using namespace sta;
if (min_max)
$1 = min_max;
else {
tclError(interp, "Error: %s not min or max.", arg);
tclArgError(interp, "%s not min or max.", arg);
return TCL_ERROR;
}
}
@ -950,7 +953,7 @@ using namespace sta;
if (min_max)
$1 = min_max;
else {
tclError(interp, "Error: %s not min, max or min_max.", arg);
tclArgError(interp, "%s not min, max or min_max.", arg);
return TCL_ERROR;
}
}
@ -965,7 +968,7 @@ using namespace sta;
if (min_max)
$1 = min_max;
else {
tclError(interp, "Error: %s not min, max or min_max.", arg);
tclArgError(interp, "%s not min, max or min_max.", arg);
return TCL_ERROR;
}
}
@ -986,7 +989,7 @@ using namespace sta;
|| stringEqual(arg, "max"))
$1 = MinMax::max();
else {
tclError(interp, "Error: %s not setup, hold, min or max.", arg);
tclArgError(interp, "%s not setup, hold, min or max.", arg);
return TCL_ERROR;
}
}
@ -1005,7 +1008,7 @@ using namespace sta;
|| stringEqual(arg, "min_max"))
$1 = SetupHoldAll::all();
else {
tclError(interp, "Error: %s not setup, hold, setup_hold, min, max or min_max.", arg);
tclArgError(interp, "%s not setup, hold, setup_hold, min, max or min_max.", arg);
return TCL_ERROR;
}
}
@ -1018,7 +1021,7 @@ using namespace sta;
if (early_late)
$1 = early_late;
else {
tclError(interp, "Error: %s not early/min or late/max.", arg);
tclArgError(interp, "%s not early/min, late/max or early_late/min_max.", arg);
return TCL_ERROR;
}
}
@ -1031,7 +1034,7 @@ using namespace sta;
if (early_late)
$1 = early_late;
else {
tclError(interp, "Error: %s not early/min, late/max or early_late/min_max.", arg);
tclArgError(interp, "%s not early/min, late/max or early_late/min_max.", arg);
return TCL_ERROR;
}
}
@ -1046,7 +1049,7 @@ using namespace sta;
else if (stringEq(arg, "cell_check"))
$1 = TimingDerateType::cell_check;
else {
tclError(interp, "Error: %s not clk or data.", arg);
tclArgError(interp, "%s not clk or data.", arg);
return TCL_ERROR;
}
}
@ -1059,7 +1062,7 @@ using namespace sta;
else if (stringEq(arg, "data"))
$1 = PathClkOrData::data;
else {
tclError(interp, "Error: %s not clk or data.", arg);
tclArgError(interp, "%s not clk or data.", arg);
return TCL_ERROR;
}
}
@ -1072,7 +1075,7 @@ using namespace sta;
else if (stringEq(arg, "slack"))
$1 = sort_by_slack;
else {
tclError(interp, "Error: %s not group or slack.", arg);
tclArgError(interp, "%s not group or slack.", arg);
return TCL_ERROR;
}
}
@ -1097,7 +1100,7 @@ using namespace sta;
else if (stringEq(arg, "json"))
$1 = ReportPathFormat::json;
else {
tclError(interp, "Error: unknown path type %s.", arg);
tclArgError(interp, "unknown path type %s.", arg);
return TCL_ERROR;
}
}
@ -1375,7 +1378,7 @@ using namespace sta;
else if (stringEq(arg, "none"))
$1 = ReducedParasiticType::none;
else {
tclError(interp, "Error: %s pi_elmore, pi_pole_residue2, or none.", arg);
tclArgError(interp, "%s pi_elmore, pi_pole_residue2, or none.", arg);
return TCL_ERROR;
}
}
@ -1978,7 +1981,7 @@ redirect_string_end()
}
void
log_begin(const char *filename)
log_begin_cmd(const char *filename)
{
Sta::sta()->report()->logBegin(filename);
}

View File

@ -294,8 +294,13 @@ proc write_stats { filename } {
################################################################
# Begin/end logging all output to a file.
# Defined by StaTcl.i
define_cmd_args "log_begin" { filename }
proc log_begin { filename } {
log_begin_cmd [file nativename $filename]
}
# Defined by StaTcl.i
define_cmd_args "log_end" {}
# set_debug is NOT in the global namespace

View File

@ -145,9 +145,9 @@ proc run_test { test } {
incr errors(error)
# For some reason seg faults aren't echoed in the log - add them.
if [file exists $log_file] {
if { [llength $test_errors] > 1 && [file exists $log_file] } {
set log_ch [open $log_file "a"]
puts $log_ch "$test_errors"
puts $log_ch $test_errors
close $log_ch
}

View File

@ -108,7 +108,7 @@ Debug::print(const char *fmt,
{
va_list args;
va_start(args, fmt);
report_->vprintError(fmt, args);
report_->vprint(fmt, args);
va_end(args);
}

View File

@ -28,6 +28,18 @@ Exception::Exception() :
{
}
ExceptionMsg::ExceptionMsg(const char *msg) :
Exception(),
msg_(msg)
{
}
const char *
ExceptionMsg::what() const noexcept
{
return msg_.c_str();
}
ExceptionLine::ExceptionLine(const char *filename,
int line) :
Exception(),

View File

@ -44,21 +44,56 @@ Report::~Report()
void
Report::printToBuffer(const char *fmt,
...)
{
va_list args;
va_start(args, fmt);
printToBuffer(fmt, args);
va_end(args);
}
void
Report::printToBuffer(const char *fmt,
va_list args)
{
buffer_length_ = 0;
printToBufferAppend(fmt, args);
}
void
Report::printToBufferAppend(const char *fmt,
...)
{
va_list args;
va_start(args, fmt);
printToBufferAppend(fmt, args);
va_end(args);
}
void
Report::printToBufferAppend(const char *fmt,
va_list args)
{
// Copy args in case we need to grow the buffer.
va_list args_copy;
va_copy(args_copy, args);
buffer_length_ = vsnprint(buffer_, buffer_size_, fmt, args);
int length = vsnprint(buffer_ + buffer_length_, buffer_size_, fmt, args);
if (buffer_length_ >= buffer_size_) {
delete [] buffer_;
buffer_size_ = buffer_length_ * 2;
buffer_ = new char[buffer_size_];
buffer_length_ = vsnprint(buffer_, buffer_size_, fmt, args_copy);
length = vsnprint(buffer_ + buffer_length_, buffer_size_, fmt, args_copy);
}
buffer_length_ += length;
va_end(args_copy);
}
void
Report::printBuffer()
{
printString(buffer_, buffer_length_);
}
size_t
Report::printString(const char *buffer,
size_t length)
@ -107,86 +142,19 @@ Report::print(const char *fmt, ...)
va_end(args);
}
size_t
Report::printError(const char *buffer,
size_t length)
{
size_t ret = length;
if (redirect_to_string_)
redirectStringPrint(buffer, length);
else {
if (redirect_stream_)
ret = min(ret, fwrite(buffer, sizeof(char), length, redirect_stream_));
else
ret = min(ret, printErrorConsole(buffer, length));
if (log_stream_)
ret = min(ret, fwrite(buffer, sizeof(char), length, log_stream_));
}
return ret;
}
void
Report::vprintError(const char *fmt,
va_list args)
{
std::unique_lock<std::mutex> lock(buffer_lock_);
printToBuffer(fmt, args);
printError(buffer_, buffer_length_);
}
void
Report::printError(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintError(fmt, args);
va_end(args);
}
void
Report::printDebug(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprint(fmt, args);
va_end(args);
}
void
Report::vprintDebug(const char *fmt,
va_list args)
{
vprint(fmt, args);
}
////////////////////////////////////////////////////////////////
void
Report::printWarn(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintError(fmt, args);
va_end(args);
}
void
Report::vprintWarn(const char *fmt,
va_list args)
{
vprintError(fmt, args);
}
void
Report::warn(int /* id */,
const char *fmt,
...)
{
printWarn("Warning: ");
va_list args;
va_start(args, fmt);
vprintWarn(fmt, args);
printWarn("\n");
printToBuffer("Warning: ");
printToBufferAppend(fmt, args);
printToBufferAppend("\n");
printBuffer();
va_end(args);
}
@ -197,11 +165,12 @@ Report::fileWarn(int /* id */,
const char *fmt,
...)
{
printWarn("Warning: %s, line %d ", filename, line);
va_list args;
va_start(args, fmt);
vprintWarn(fmt, args);
printWarn("\n");
printToBuffer("Warning: %s, line %d ", filename, line);
printToBufferAppend(fmt, args);
printToBufferAppend("\n");
printBuffer();
va_end(args);
}
@ -212,9 +181,10 @@ Report::vfileWarn(int /* id */,
const char *fmt,
va_list args)
{
printWarn("Warning: %s, line %d ", filename, line);
vprintWarn(fmt, args);
printWarn("\n");
printToBuffer("Warning: %s, line %d ", filename, line);
printToBufferAppend(fmt, args);
printToBufferAppend("\n");
printBuffer();
}
////////////////////////////////////////////////////////////////
@ -223,12 +193,13 @@ void
Report::error(int /* id */,
const char *fmt, ...)
{
printError("Error: ");
flush();
va_list args;
va_start(args, fmt);
vprintError(fmt, args);
printWarn("\n");
// No prefix msg, no \n.
printToBuffer(fmt, args);
va_end(args);
throw ExceptionMsg(buffer_);
}
void
@ -238,12 +209,14 @@ Report::fileError(int /* id */,
const char *fmt,
...)
{
printError("Error: %s, line %d ", filename, line);
flush();
va_list args;
va_start(args, fmt);
vprintError(fmt, args);
printWarn("\n");
// No prefix msg, no \n.
printToBuffer("%s, line %d ", filename, line);
printToBufferAppend(fmt, args);
va_end(args);
throw ExceptionMsg(buffer_);
}
void
@ -253,9 +226,11 @@ Report::vfileError(int /* id */,
const char *fmt,
va_list args)
{
printError("Error: %s, line %d ", filename, line);
vprintError(fmt, args);
printWarn("\n");
flush();
// No prefix msg, no \n.
printToBuffer("%s, line %d ", filename, line);
printToBufferAppend(fmt, args);
throw ExceptionMsg(buffer_);
}
////////////////////////////////////////////////////////////////
@ -265,13 +240,13 @@ Report::critical(int /* id */,
const char *fmt,
...)
{
printError("Critical: ");
va_list args;
va_start(args, fmt);
vprintError(fmt, args);
printWarn("\n");
printToBuffer("Critical: ");
printToBufferAppend(fmt, args);
printToBufferAppend("\n");
printBuffer();
va_end(args);
exit(1);
}
void
@ -281,11 +256,11 @@ Report::fileCritical(int /* id */,
const char *fmt,
...)
{
printError("Critical: %s, line %d ", filename, line);
va_list args;
va_start(args, fmt);
vprintError(fmt, args);
printWarn("\n");
printToBuffer("Critical: %s, line %d ", filename, line, fmt, args);
printToBufferAppend(fmt, args);
printToBufferAppend("\n");
va_end(args);
exit(1);
}

View File

@ -277,8 +277,11 @@ Tcl_ChannelType tcl_encap_type_stderr = {
////////////////////////////////////////////////////////////////
ReportTcl::ReportTcl() :
Report(), interp_(nullptr), tcl_stdout_(nullptr), tcl_stderr_(nullptr),
tcl_encap_stdout_(nullptr), tcl_encap_stderr_(nullptr)
Report(), interp_(nullptr),
tcl_stdout_(nullptr),
tcl_stderr_(nullptr),
tcl_encap_stdout_(nullptr),
tcl_encap_stderr_(nullptr)
{
}
@ -318,13 +321,6 @@ ReportTcl::printConsole(const char *buffer,
return printTcl(tcl_stdout_, buffer, length);
}
size_t
ReportTcl::printErrorConsole(const char *buffer,
size_t length)
{
return printTcl(tcl_stderr_, buffer, length);
}
size_t
ReportTcl::printTcl(Tcl_Channel channel,
const char *buffer,
@ -340,69 +336,63 @@ ReportTcl::printTcl(Tcl_Channel channel,
&error_code);
}
void
ReportTcl::flush()
{
if (tcl_encap_stdout_)
Tcl_Flush(tcl_encap_stdout_);
if (tcl_encap_stderr_)
Tcl_Flush(tcl_encap_stderr_);
}
// Tcl_Main can eval multiple commands before the flushing the command
// output, so the log/redirect commands must force a flush.
void
ReportTcl::logBegin(const char *filename)
{
Tcl_Flush(tcl_encap_stdout_);
Tcl_Flush(tcl_encap_stderr_);
flush();
Report::logBegin(filename);
}
void
ReportTcl::logEnd()
{
if (tcl_encap_stdout_)
Tcl_Flush(tcl_encap_stdout_);
if (tcl_encap_stderr_)
Tcl_Flush(tcl_encap_stderr_);
flush();
Report::logEnd();
}
void
ReportTcl::redirectFileBegin(const char *filename)
{
Tcl_Flush(tcl_encap_stdout_);
Tcl_Flush(tcl_encap_stderr_);
flush();
Report::redirectFileBegin(filename);
}
void
ReportTcl::redirectFileAppendBegin(const char *filename)
{
Tcl_Flush(tcl_encap_stdout_);
Tcl_Flush(tcl_encap_stderr_);
flush();
Report::redirectFileAppendBegin(filename);
}
void
ReportTcl::redirectFileEnd()
{
if (tcl_encap_stdout_)
Tcl_Flush(tcl_encap_stdout_);
if (tcl_encap_stderr_)
Tcl_Flush(tcl_encap_stderr_);
flush();
Report::redirectFileEnd();
}
void
ReportTcl::redirectStringBegin()
{
if (tcl_encap_stdout_)
Tcl_Flush(tcl_encap_stdout_);
if (tcl_encap_stderr_)
Tcl_Flush(tcl_encap_stderr_);
flush();
Report::redirectStringBegin();
}
const char *
ReportTcl::redirectStringEnd()
{
if (tcl_encap_stdout_)
Tcl_Flush(tcl_encap_stdout_);
if (tcl_encap_stderr_)
Tcl_Flush(tcl_encap_stderr_);
flush();
return Report::redirectStringEnd();
}