2018-09-28 17:54:21 +02:00
|
|
|
// OpenSTA, Static Timing Analyzer
|
2020-03-07 03:50:37 +01:00
|
|
|
// Copyright (c) 2020, Parallax Software, Inc.
|
2018-09-28 17:54:21 +02:00
|
|
|
//
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
2020-04-05 23:53:44 +02:00
|
|
|
#include "Report.hh"
|
2020-04-05 20:35:51 +02:00
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
#include <algorithm> // min
|
2020-12-26 17:29:43 +01:00
|
|
|
#include <cstdlib> // exit
|
2020-12-27 01:53:27 +01:00
|
|
|
#include <cstring> // strlen
|
2020-04-05 20:35:51 +02:00
|
|
|
|
2020-04-05 23:53:44 +02:00
|
|
|
#include "Error.hh"
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
namespace sta {
|
|
|
|
|
|
|
|
|
|
using std::min;
|
|
|
|
|
|
2020-12-14 02:21:35 +01:00
|
|
|
Report *Report::default_ = nullptr;
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
Report::Report() :
|
2019-03-13 01:25:53 +01:00
|
|
|
log_stream_(nullptr),
|
|
|
|
|
redirect_stream_(nullptr),
|
2018-09-28 17:54:21 +02:00
|
|
|
redirect_to_string_(false),
|
|
|
|
|
buffer_size_(1000),
|
|
|
|
|
buffer_(new char[buffer_size_]),
|
|
|
|
|
buffer_length_(0)
|
|
|
|
|
{
|
2020-12-14 02:21:35 +01:00
|
|
|
default_ = this;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Report::~Report()
|
|
|
|
|
{
|
|
|
|
|
delete [] buffer_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t
|
2020-12-20 01:27:29 +01:00
|
|
|
Report::printString(const char *buffer,
|
|
|
|
|
size_t length)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
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, printConsole(buffer, length));
|
|
|
|
|
if (log_stream_)
|
|
|
|
|
ret = min(ret, fwrite(buffer, sizeof(char), length, log_stream_));
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2020-12-20 01:27:29 +01:00
|
|
|
Report::vprint(const char *fmt,
|
|
|
|
|
va_list args)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2020-04-12 18:46:30 +02:00
|
|
|
std::unique_lock<std::mutex> lock(buffer_lock_);
|
2018-09-28 17:54:21 +02:00
|
|
|
printToBuffer(fmt, args);
|
|
|
|
|
printString(buffer_, buffer_length_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2020-12-28 18:04:57 +01:00
|
|
|
Report::reportLine(const char *fmt, ...)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
|
vprint(fmt, args);
|
2020-12-28 18:04:57 +01:00
|
|
|
printString("\n", 1);
|
2018-09-28 17:54:21 +02:00
|
|
|
va_end(args);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-26 01:55:46 +01:00
|
|
|
void
|
2020-12-28 18:04:57 +01:00
|
|
|
Report::reportLineString(const char *line)
|
2020-12-26 01:55:46 +01:00
|
|
|
{
|
|
|
|
|
printString(line, strlen(line));
|
|
|
|
|
printString("\n", 1);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-29 03:04:49 +01:00
|
|
|
void
|
|
|
|
|
Report::reportLine(const string &line)
|
|
|
|
|
{
|
|
|
|
|
printString(line.c_str(), line.length());
|
|
|
|
|
printString("\n", 1);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 02:21:35 +01:00
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2020-12-28 18:04:57 +01:00
|
|
|
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);
|
|
|
|
|
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_];
|
|
|
|
|
length = vsnprint(buffer_ + buffer_length_, buffer_size_, fmt, args_copy);
|
|
|
|
|
}
|
|
|
|
|
buffer_length_ += length;
|
|
|
|
|
va_end(args_copy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Report::printBuffer()
|
|
|
|
|
{
|
|
|
|
|
printString(buffer_, buffer_length_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
void
|
2020-12-14 02:21:35 +01:00
|
|
|
Report::warn(int /* id */,
|
|
|
|
|
const char *fmt,
|
|
|
|
|
...)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
2020-12-25 01:31:52 +01:00
|
|
|
printToBuffer("Warning: ");
|
|
|
|
|
printToBufferAppend(fmt, args);
|
|
|
|
|
printToBufferAppend("\n");
|
|
|
|
|
printBuffer();
|
2018-09-28 17:54:21 +02:00
|
|
|
va_end(args);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-25 23:00:11 +01:00
|
|
|
void
|
|
|
|
|
Report::vwarn(int /* id */,
|
|
|
|
|
const char *fmt,
|
|
|
|
|
va_list args)
|
|
|
|
|
{
|
|
|
|
|
printToBuffer("Warning: ");
|
|
|
|
|
printToBufferAppend(fmt, args);
|
|
|
|
|
printToBufferAppend("\n");
|
|
|
|
|
printBuffer();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
void
|
2020-12-14 02:21:35 +01:00
|
|
|
Report::fileWarn(int /* id */,
|
|
|
|
|
const char *filename,
|
|
|
|
|
int line,
|
|
|
|
|
const char *fmt,
|
|
|
|
|
...)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2020-12-14 02:21:35 +01:00
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
2020-12-25 23:00:11 +01:00
|
|
|
printToBuffer("Warning: %s line %d, ", filename, line);
|
2020-12-25 01:31:52 +01:00
|
|
|
printToBufferAppend(fmt, args);
|
|
|
|
|
printToBufferAppend("\n");
|
|
|
|
|
printBuffer();
|
2020-12-14 02:21:35 +01:00
|
|
|
va_end(args);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2020-12-14 02:21:35 +01:00
|
|
|
Report::vfileWarn(int /* id */,
|
|
|
|
|
const char *filename,
|
|
|
|
|
int line,
|
|
|
|
|
const char *fmt,
|
2020-12-25 23:00:11 +01:00
|
|
|
va_list args)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2020-12-25 23:00:11 +01:00
|
|
|
printToBuffer("Warning: %s line %d, ", filename, line);
|
2020-12-25 01:31:52 +01:00
|
|
|
printToBufferAppend(fmt, args);
|
|
|
|
|
printToBufferAppend("\n");
|
|
|
|
|
printBuffer();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-14 02:21:35 +01:00
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
void
|
2020-12-14 02:21:35 +01:00
|
|
|
Report::error(int /* id */,
|
|
|
|
|
const char *fmt, ...)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2020-12-14 02:21:35 +01:00
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
2020-12-25 01:31:52 +01:00
|
|
|
// No prefix msg, no \n.
|
|
|
|
|
printToBuffer(fmt, args);
|
2020-12-14 02:21:35 +01:00
|
|
|
va_end(args);
|
2020-12-25 01:31:52 +01:00
|
|
|
throw ExceptionMsg(buffer_);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-25 23:00:11 +01:00
|
|
|
void
|
|
|
|
|
Report::verror(int /* id */,
|
|
|
|
|
const char *fmt,
|
|
|
|
|
va_list args)
|
|
|
|
|
{
|
|
|
|
|
// No prefix msg, no \n.
|
|
|
|
|
printToBuffer(fmt, args);
|
|
|
|
|
throw ExceptionMsg(buffer_);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
void
|
2020-12-14 02:21:35 +01:00
|
|
|
Report::fileError(int /* id */,
|
|
|
|
|
const char *filename,
|
|
|
|
|
int line,
|
|
|
|
|
const char *fmt,
|
|
|
|
|
...)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
2020-12-25 01:31:52 +01:00
|
|
|
// No prefix msg, no \n.
|
2020-12-25 23:00:11 +01:00
|
|
|
printToBuffer("%s line %d, ", filename, line);
|
2020-12-25 01:31:52 +01:00
|
|
|
printToBufferAppend(fmt, args);
|
2018-09-28 17:54:21 +02:00
|
|
|
va_end(args);
|
2020-12-25 01:31:52 +01:00
|
|
|
throw ExceptionMsg(buffer_);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2020-12-14 02:21:35 +01:00
|
|
|
Report::vfileError(int /* id */,
|
|
|
|
|
const char *filename,
|
|
|
|
|
int line,
|
|
|
|
|
const char *fmt,
|
2020-12-25 01:31:52 +01:00
|
|
|
va_list args)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2020-12-25 01:31:52 +01:00
|
|
|
// No prefix msg, no \n.
|
2020-12-25 23:00:11 +01:00
|
|
|
printToBuffer("%s line %d, ", filename, line);
|
2020-12-25 01:31:52 +01:00
|
|
|
printToBufferAppend(fmt, args);
|
|
|
|
|
throw ExceptionMsg(buffer_);
|
2020-12-14 02:21:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
void
|
2020-12-14 02:21:35 +01:00
|
|
|
Report::critical(int /* id */,
|
|
|
|
|
const char *fmt,
|
|
|
|
|
...)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
2020-12-25 01:31:52 +01:00
|
|
|
printToBuffer("Critical: ");
|
|
|
|
|
printToBufferAppend(fmt, args);
|
|
|
|
|
printToBufferAppend("\n");
|
|
|
|
|
printBuffer();
|
2018-09-28 17:54:21 +02:00
|
|
|
va_end(args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2020-12-14 02:21:35 +01:00
|
|
|
Report::fileCritical(int /* id */,
|
|
|
|
|
const char *filename,
|
|
|
|
|
int line,
|
|
|
|
|
const char *fmt,
|
|
|
|
|
...)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2020-12-14 02:21:35 +01:00
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
2020-12-25 23:00:11 +01:00
|
|
|
printToBuffer("Critical: %s line %d, ", filename, line, fmt, args);
|
2020-12-25 01:31:52 +01:00
|
|
|
printToBufferAppend(fmt, args);
|
|
|
|
|
printToBufferAppend("\n");
|
2020-12-14 02:21:35 +01:00
|
|
|
va_end(args);
|
|
|
|
|
exit(1);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-14 02:21:35 +01:00
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
void
|
|
|
|
|
Report::logBegin(const char *filename)
|
|
|
|
|
{
|
|
|
|
|
log_stream_ = fopen(filename, "w");
|
2019-03-13 01:25:53 +01:00
|
|
|
if (log_stream_ == nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
throw FileNotWritable(filename);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Report::logEnd()
|
|
|
|
|
{
|
|
|
|
|
if (log_stream_)
|
|
|
|
|
fclose(log_stream_);
|
2019-03-13 01:25:53 +01:00
|
|
|
log_stream_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Report::redirectFileBegin(const char *filename)
|
|
|
|
|
{
|
|
|
|
|
redirect_stream_ = fopen(filename, "w");
|
2019-03-13 01:25:53 +01:00
|
|
|
if (redirect_stream_ == nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
throw FileNotWritable(filename);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Report::redirectFileAppendBegin(const char *filename)
|
|
|
|
|
{
|
|
|
|
|
redirect_stream_ = fopen(filename, "a");
|
2019-03-13 01:25:53 +01:00
|
|
|
if (redirect_stream_ == nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
throw FileNotWritable(filename);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Report::redirectFileEnd()
|
|
|
|
|
{
|
|
|
|
|
if (redirect_stream_)
|
|
|
|
|
fclose(redirect_stream_);
|
2019-03-13 01:25:53 +01:00
|
|
|
redirect_stream_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Report::redirectStringBegin()
|
|
|
|
|
{
|
|
|
|
|
redirect_to_string_ = true;
|
|
|
|
|
redirect_string_.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
Report::redirectStringEnd()
|
|
|
|
|
{
|
|
|
|
|
redirect_to_string_ = false;
|
|
|
|
|
return redirect_string_.c_str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2020-12-20 01:27:29 +01:00
|
|
|
Report::redirectStringPrint(const char *buffer,
|
|
|
|
|
size_t length)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
redirect_string_.append(buffer, length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|