diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/common/Logger.cpp | 143 | ||||
| -rw-r--r-- | src/core/common/Logger.hpp | 61 | ||||
| -rw-r--r-- | src/core/common/SourceContextReader.cpp | 18 | ||||
| -rw-r--r-- | src/core/common/SourceContextReader.hpp | 20 | ||||
| -rw-r--r-- | src/core/frontend/Terminal.cpp (renamed from src/core/common/Terminal.cpp) | 20 | ||||
| -rw-r--r-- | src/core/frontend/Terminal.hpp (renamed from src/core/common/Terminal.hpp) | 14 | ||||
| -rw-r--r-- | src/core/frontend/TerminalLogger.cpp | 177 | ||||
| -rw-r--r-- | src/core/frontend/TerminalLogger.hpp | 79 | ||||
| -rw-r--r-- | src/core/resource/ResourceManager.cpp | 9 | ||||
| -rw-r--r-- | src/core/resource/ResourceManager.hpp | 20 | 
10 files changed, 361 insertions, 200 deletions
diff --git a/src/core/common/Logger.cpp b/src/core/common/Logger.cpp index aa61e6a..54156f2 100644 --- a/src/core/common/Logger.cpp +++ b/src/core/common/Logger.cpp @@ -20,8 +20,6 @@  #include <sstream>  #include "Logger.hpp" -#include "Terminal.hpp" -#include "Utils.hpp"  namespace ousia { @@ -118,49 +116,49 @@ void LoggerFork::commit()  	purge();  } -/* Class ScopedLogger */ +/* Class GuardedLogger */ -ScopedLogger::ScopedLogger(Logger &parent, SourceLocation loc) +GuardedLogger::GuardedLogger(Logger &parent, SourceLocation loc)      : parent(parent), depth(0)  {  	pushDefaultLocation(loc);  } -ScopedLogger::~ScopedLogger() +GuardedLogger::~GuardedLogger()  {  	while (depth > 0) {  		popDefaultLocation();  	}  } -void ScopedLogger::processMessage(const Message &msg) +void GuardedLogger::processMessage(const Message &msg)  {  	parent.processMessage(msg);  } -bool ScopedLogger::filterMessage(const Message &msg) +bool GuardedLogger::filterMessage(const Message &msg)  {  	return parent.filterMessage(msg);  } -void ScopedLogger::processPushDefaultLocation(const SourceLocation &loc) +void GuardedLogger::processPushDefaultLocation(const SourceLocation &loc)  {  	parent.processPushDefaultLocation(loc);  	depth++;  } -void ScopedLogger::processPopDefaultLocation() +void GuardedLogger::processPopDefaultLocation()  {  	depth--;  	parent.processPopDefaultLocation();  } -void ScopedLogger::processSetDefaultLocation(const SourceLocation &loc) +void GuardedLogger::processSetDefaultLocation(const SourceLocation &loc)  {  	parent.processSetDefaultLocation(loc);  } -void ScopedLogger::processSetSourceContextCallback( +void GuardedLogger::processSetSourceContextCallback(      SourceContextCallback sourceContextCallback)  {  	parent.processSetSourceContextCallback(sourceContextCallback); @@ -265,128 +263,5 @@ bool ConcreteLogger::hasFatalError()  	return getSeverityCount(Severity::FATAL_ERROR) > 0;  } -/* Class TerminalLogger */ - -void TerminalLogger::processMessage(const Message &msg) -{ -	Terminal t(useColor); - -	// Fetch filename, position and context -	const SourceContext ctx = messageContext(msg); - -	// Print the file name -	if (ctx.hasFile()) { -		os << t.bright() << ctx.filename << t.reset(); -	} - -	// Print line and column number -	if (ctx.hasLine()) { -		if (ctx.hasFile()) { -			os << ':'; -		} -		os << t.bright() << ctx.startLine << t.reset(); -		if (ctx.hasColumn()) { -			os << ':' << ctx.startColumn; -		} -	} - -	// Print the optional seperator -	if (ctx.hasFile() || ctx.hasLine()) { -		os << ": "; -	} - -	// Print the severity -	switch (msg.severity) { -		case Severity::DEBUG: -			break; -		case Severity::NOTE: -			os << t.color(Terminal::CYAN, true) << "note: "; -			break; -		case Severity::WARNING: -			os << t.color(Terminal::MAGENTA, true) << "warning: "; -			break; -		case Severity::ERROR: -			os << t.color(Terminal::RED, true) << "error: "; -			break; -		case Severity::FATAL_ERROR: -			os << t.color(Terminal::RED, true) << "fatal error: "; -			break; -	} -	os << t.reset(); - -	// Print the actual message -	os << msg.msg << std::endl; - -	// Print the error message context if available -	if (ctx.hasText()) { -		// Iterate over each line in the text -		std::vector<std::string> lines = Utils::split(ctx.text, '\n'); - -		const size_t relLen = ctx.relLen ? ctx.relLen : 1; -		const size_t relPos = ctx.relPos; -		const size_t pstart = relPos; -		const size_t pend = relPos + relLen; - -		size_t lstart = 0; -		size_t lend = 0; -		for (size_t n = 0; n < lines.size(); n++) { -			bool firstLine = n == 0; -			bool lastLine = n == lines.size() - 1; - -			// Indicate truncation and indent non-first lines -			if (ctx.truncatedStart && firstLine) { -				os << "[...] "; -			} -			if (!firstLine) { -				os << "\t"; -			} - -			// Print the actual line -			os << lines[n]; - -			// Indicate truncation -			if (ctx.truncatedEnd && lastLine) { -				os << " [...]"; -			} -			os << std::endl; - -			// Repeat truncation or indendation space in the next line -			if (ctx.truncatedStart && firstLine) { -				os << "      "; -			} -			if (!firstLine) { -				os << "\t"; -			} - -			// Print the position indicators -			lend = lastLine ? pend : lstart + lines[n].size(); -			for (size_t i = lstart; i < lend; i++) { -				if (i >= pstart && i < pend) { -					os << t.color(Terminal::GREEN); -					for (; i < std::min(lend, pend); i++) { -						if (relLen == 1) { -							os << '^'; -						} else { -							os << '~'; -						} -						if (i < ctx.text.size() && ctx.text[i] == '\t') { -							os << '\t'; -						} -					} -					os << t.reset(); -				} else { -					if (i < ctx.text.size() && ctx.text[i] == '\t') { -						os << '\t'; -					} else { -						os << ' '; -					} -				} -			} -			os << std::endl; - -			lstart = lend; -		} -	} -}  } diff --git a/src/core/common/Logger.hpp b/src/core/common/Logger.hpp index 85b1bb1..afe58be 100644 --- a/src/core/common/Logger.hpp +++ b/src/core/common/Logger.hpp @@ -19,9 +19,8 @@  /**   * @file Logger.hpp   * - * Contains classes for logging messages in Ousía. Provides a generic Logger - * class, and TerminalLogger, an extension of Logger which logs do an output - * stream. + * Contains classes for logging messages in Ousía. Provides various base Logger + * classes that allow to Fork logger instances or to create a GuardedLogger.   *   * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)   */ @@ -30,7 +29,6 @@  #define _OUSIA_LOGGER_HPP_  #include <cstdint> -#include <ostream>  #include <string>  #include <vector> @@ -109,7 +107,7 @@ inline MessageMode operator|(MessageMode a, MessageMode b)  // Forward declaration  class LoggerFork; -class ScopedLogger; +class GuardedLogger;  /**   * The Logger class is the base class the individual logging systems should @@ -123,7 +121,7 @@ class ScopedLogger;  class Logger {  public:  	friend LoggerFork; -	friend ScopedLogger; +	friend GuardedLogger;  	/**  	 * The message struct represents a single log message and all information @@ -611,12 +609,12 @@ public:  };  /** - * The ScopedLogger class can be used to automatically pop any pushed file from + * The GuardedLogger class can be used to automatically pop any pushed file from   * the File stack maintained by a Logger class (in a RAII manner). This   * simplifies managing pushing and popping files in case there are multiple   * return calls or exceptions thrown.   */ -class ScopedLogger : public Logger { +class GuardedLogger : public Logger {  private:  	/**  	 * Reference to the parent logger instance. @@ -668,20 +666,20 @@ protected:  public:  	/** -	 * Constructor of the ScopedLogger class, pushes a first file instance onto +	 * Constructor of the GuardedLogger class, pushes a first file instance onto  	 * the file stack.  	 *  	 * @param parent is the parent logger instance to which all calls should  	 * be relayed.  	 * @param loc specifies the first source location.  	 */ -	ScopedLogger(Logger &parent, SourceLocation loc = SourceLocation{}); +	GuardedLogger(Logger &parent, SourceLocation loc = SourceLocation{});  	/** -	 * Destructor of the ScopedLogger class, automatically unwinds the file +	 * Destructor of the GuardedLogger class, automatically unwinds the file  	 * stack.  	 */ -	~ScopedLogger(); +	~GuardedLogger();  };  /** @@ -818,45 +816,6 @@ public:  	bool hasFatalError();  }; -/** - * Class extending the Logger class and printing the log messages to the - * given - * stream. - */ -class TerminalLogger : public ConcreteLogger { -private: -	/** -	 * Reference to the target output stream. -	 */ -	std::ostream &os; - -	/** -	 * If true, the TerminalLogger will use colors to make the log messages -	 * prettier. -	 */ -	bool useColor; - -protected: -	void processMessage(const Message &msg) override; - -public: -	/** -	 * Constructor of the TerminalLogger class. -	 * -	 * @param os is the output stream the log messages should be logged to. -	 * Should be set to std::cerr in most cases. -	 * @param useColor if true, the TerminalLogger class will do its best to -	 * use ANSI/VT100 control sequences for colored log messages. -	 * @param minSeverity is the minimum severity below which log messages -	 *are -	 * discarded. -	 */ -	TerminalLogger(std::ostream &os, bool useColor = false, -	               Severity minSeverity = DEFAULT_MIN_SEVERITY) -	    : ConcreteLogger(minSeverity), os(os), useColor(useColor) -	{ -	} -};  }  #endif /* _OUSIA_LOGGER_HPP_ */ diff --git a/src/core/common/SourceContextReader.cpp b/src/core/common/SourceContextReader.cpp index 65a6281..d5d379c 100644 --- a/src/core/common/SourceContextReader.cpp +++ b/src/core/common/SourceContextReader.cpp @@ -56,8 +56,8 @@ SourceContext SourceContextReader::readContext(CharReader &reader,  	size_t offs = 0;  	auto it = std::lower_bound(cache.begin(), cache.end(), start);  	if (it != cache.begin()) { -		it--;  // Go to the previous entry -		offs = *it; // Read the corresponding byte offset +		it--;        // Go to the previous entry +		offs = *it;  // Read the corresponding byte offset  		size_t line = it - cache.begin() + 1;  		ctx.startLine = line;  		ctx.endLine = line; @@ -182,17 +182,23 @@ SourceContext SourceContextReader::readContext(CharReader &reader,  		}  		// Update the relative position and length, set the "truncated" flags -		size_t us = static_cast<size_t>(s), ue = static_cast<size_t>(e); -		ctx.relPos = start - lineBufStart - us; -		ctx.relLen = std::min(ctx.relLen, ue - us); +		ctx.relPos = std::max<ssize_t>(0, start - lineBufStart - s); +		ctx.relLen = std::min<ssize_t>(ctx.relLen, e - s);  		ctx.truncatedStart = s > ts || lastLineStart < lineBufStart;  		ctx.truncatedEnd = e < te;  		// Copy the selected area to the output string -		ctx.text = std::string{&lineBuf[s], ue - us}; +		ctx.text = std::string{&lineBuf[s], static_cast<size_t>(e - s)};  	}  	return ctx;  } + +SourceContext SourceContextReader::readContext(CharReader &reader, +                                               const SourceRange &range, +                                               const std::string &filename) +{ +	return readContext(reader, range, MAX_MAX_CONTEXT_LENGTH, filename); +}  } diff --git a/src/core/common/SourceContextReader.hpp b/src/core/common/SourceContextReader.hpp index 35e71b3..cd29880 100644 --- a/src/core/common/SourceContextReader.hpp +++ b/src/core/common/SourceContextReader.hpp @@ -82,7 +82,25 @@ public:  	 * @return a SourceContext instance describing the  	 */  	SourceContext readContext(CharReader &reader, const SourceRange &range, -	                          size_t maxContextLength = MAX_MAX_CONTEXT_LENGTH, +	                          size_t maxContextLength, +	                          const std::string &filename = ""); + +	/** +	 * Returns the context for the char reader and the given SourceRange. +	 * Returns an invalid source context if either the given range is invalid +	 * or the byte offset described in the SourceRange cannot be reached because +	 * the CharReader cannot be seeked back to this position. Does not limit +	 * the output context. +	 * +	 * @param reader is the CharReader instance from which the context should be +	 * read. +	 * @param range describes the Range within the source file for which the +	 * context should be extraced. +	 * @param filename is the filename that should be stored in the returned +	 * context. +	 * @return a SourceContext instance describing the +	 */ +	SourceContext readContext(CharReader &reader, const SourceRange &range,  	                          const std::string &filename = "");  };  } diff --git a/src/core/common/Terminal.cpp b/src/core/frontend/Terminal.cpp index 447e595..5664564 100644 --- a/src/core/common/Terminal.cpp +++ b/src/core/frontend/Terminal.cpp @@ -41,9 +41,23 @@ std::string Terminal::bright() const  	if (!useColor) {  		return std::string{};  	} -	std::stringstream ss; -	ss << "\x1b[1m"; -	return ss.str(); +	return "\x1b[1m"; +} + +std::string Terminal::italic() const +{ +	if (!useColor) { +		return std::string{}; +	} +	return "\x1b[3m"; +} + +std::string Terminal::underline() const +{ +	if (!useColor) { +		return std::string{}; +	} +	return "\x1b[4m";  }  std::string Terminal::reset() const diff --git a/src/core/common/Terminal.hpp b/src/core/frontend/Terminal.hpp index 730853d..90a2e6f 100644 --- a/src/core/common/Terminal.hpp +++ b/src/core/frontend/Terminal.hpp @@ -112,6 +112,20 @@ public:  	std::string bright() const;  	/** +	 * Makes the text italic. +	 * +	 * @return a control string to be included in the output stream. +	 */ +	std::string italic() const; + +	/** +	 * Underlines the text. +	 * +	 * @return a control string to be included in the output stream. +	 */ +	std::string underline() const; + +	/**  	 * Returns a control string for switching to the default mode.  	 *  	 * @return a control string to be included in the output stream. diff --git a/src/core/frontend/TerminalLogger.cpp b/src/core/frontend/TerminalLogger.cpp new file mode 100644 index 0000000..3bead06 --- /dev/null +++ b/src/core/frontend/TerminalLogger.cpp @@ -0,0 +1,177 @@ +/* +    Ousía +    Copyright (C) 2014, 2015  Benjamin Paaßen, Andreas Stöckel + +    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 <http://www.gnu.org/licenses/>. +*/ + +#include <core/common/Utils.hpp> + +#include "Terminal.hpp" +#include "TerminalLogger.hpp" + +namespace ousia { + +/* Class TerminalLogger */ + +void TerminalLogger::processMessage(const Message &msg) +{ +	Terminal t(useColor); + +	// Fetch filename, position and context +	const SourceContext ctx = messageContext(msg); + +	// Print the file name +	if (ctx.hasFile()) { +		os << t.bright() << ctx.filename << t.reset(); +	} + +	// Print line and column number +	if (ctx.hasLine()) { +		if (ctx.hasFile()) { +			os << ':'; +		} +		os << t.bright() << ctx.startLine << t.reset(); +		if (ctx.hasColumn()) { +			os << ':' << ctx.startColumn; +		} +	} + +	// Print the optional seperator +	if (ctx.hasFile() || ctx.hasLine()) { +		os << ": "; +	} + +	// Print the severity +	switch (msg.severity) { +		case Severity::DEBUG: +			break; +		case Severity::NOTE: +			os << t.color(Terminal::CYAN, true) << "note: "; +			break; +		case Severity::WARNING: +			os << t.color(Terminal::MAGENTA, true) << "warning: "; +			break; +		case Severity::ERROR: +			os << t.color(Terminal::RED, true) << "error: "; +			break; +		case Severity::FATAL_ERROR: +			os << t.color(Terminal::RED, true) << "fatal error: "; +			break; +	} +	os << t.reset(); + +	// Print the actual message +	os << msg.msg << std::endl; + +	// Print the error message context if available +	if (ctx.hasText()) { +		// Iterate over each line in the text +		std::vector<std::string> lines = Utils::split(ctx.text, '\n'); + +		const size_t relLen = ctx.relLen ? ctx.relLen : 1; +		const size_t relPos = ctx.relPos; +		const size_t pstart = relPos; +		const size_t pend = relPos + relLen; + +		size_t lstart = 0; +		size_t lend = 0; +		for (size_t n = 0; n < lines.size(); n++) { +			bool firstLine = n == 0; +			bool lastLine = n == lines.size() - 1; + +			// Indicate truncation and indent non-first lines +			if (ctx.truncatedStart && firstLine) { +				os << t.italic() << "[...] " << t.reset(); +			} +			if (!firstLine) { +				os << "\t"; +			} + +			// Print the actual line, replace tabs +			for (char c: lines[n]) { +				if (c == '\t') { +					os << "    "; +				} else { +					os << c; +				} +			} +			if (!lastLine) { +				os << t.color(Terminal::BLACK) << "¶" << t.reset(); +			} + +			// Indicate truncation +			if (ctx.truncatedEnd && lastLine) { +				os << t.italic() << " [...]" << t.reset(); +			} +			os << std::endl; + +			// Repeat truncation or indendation space in the next line +			if (ctx.truncatedStart && firstLine) { +				os << "      "; +			} +			if (!firstLine) { +				os << "\t"; +			} + +			// Print the position indicators +			lend = lastLine ? pend : lstart + lines[n].size(); +			bool inRegion = false; +			for (size_t i = lstart; i < lend + 1; i++) { +				if (i >= pstart && i < pend) { +					if (!inRegion) { +						os << t.color(Terminal::GREEN); +						inRegion = true; +					} +				} else { +					if (inRegion) { +						os << t.reset(); +						inRegion = false; +					} +				} +				char c = i < ctx.text.size() ? ctx.text[i] : ' '; +				if (c == '\t') { +					if (inRegion) { +						if (relLen == 1) { +							os << "^   "; +						} else { +							os << "~~~~"; +						} +					} else { +						os << "    "; +					} +				} else { +					if (inRegion) { +						if (relLen == 1) { +							os << "^"; +						} else { +							os << "~"; +						} +					} else { +						os << " "; +					} +				} +			} +			if (inRegion) { +				os << t.reset(); +			} +			os << std::endl; + +			lstart = lend + 1; // skip newline +		} +	} +} + +} + diff --git a/src/core/frontend/TerminalLogger.hpp b/src/core/frontend/TerminalLogger.hpp new file mode 100644 index 0000000..03930e9 --- /dev/null +++ b/src/core/frontend/TerminalLogger.hpp @@ -0,0 +1,79 @@ +/* +    Ousía +    Copyright (C) 2014, 2015  Benjamin Paaßen, Andreas Stöckel + +    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 <http://www.gnu.org/licenses/>. +*/ + +/** + * @file TerminalLogger.hpp + * + * Provides the TerminalLogger class, which is used to log messages to an output + * stream, possibly a Terminal. + * + * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de) + */ + +#ifndef _OUSIA_TERMINAL_LOGGER_HPP_ +#define _OUSIA_TERMINAL_LOGGER_HPP_ + +#include <ostream> + +#include <core/common/Logger.hpp> + +namespace ousia { + +/** + * Class extending the Logger class and printing (possibly colored) log messages + * to the given stream. + */ +class TerminalLogger : public ConcreteLogger { +private: +	/** +	 * Reference to the target output stream. +	 */ +	std::ostream &os; + +	/** +	 * If true, the TerminalLogger will use colors to make the log messages +	 * prettier. +	 */ +	bool useColor; + +protected: +	void processMessage(const Message &msg) override; + +public: +	/** +	 * Constructor of the TerminalLogger class. +	 * +	 * @param os is the output stream the log messages should be logged to. +	 * Should be set to std::cerr in most cases. +	 * @param useColor if true, the TerminalLogger class will do its best to +	 * use ANSI/VT100 control sequences for colored log messages. +	 * @param minSeverity is the minimum severity below which log messages +	 * are discarded. +	 */ +	TerminalLogger(std::ostream &os, bool useColor = false, +	               Severity minSeverity = DEFAULT_MIN_SEVERITY) +	    : ConcreteLogger(minSeverity), os(os), useColor(useColor) +	{ +	} +}; + +} + +#endif /* _OUSIA_TERMINAL_LOGGER_HPP_ */ + + diff --git a/src/core/resource/ResourceManager.cpp b/src/core/resource/ResourceManager.cpp index a5e76b0..184a16d 100644 --- a/src/core/resource/ResourceManager.cpp +++ b/src/core/resource/ResourceManager.cpp @@ -22,6 +22,7 @@  #include <core/common/Exceptions.hpp>  #include <core/common/Logger.hpp>  #include <core/common/Rtti.hpp> +#include <core/common/SourceContextReader.hpp>  #include <core/common/Utils.hpp>  #include <core/model/Node.hpp>  #include <core/parser/ParserContext.hpp> @@ -128,7 +129,7 @@ Rooted<Node> ResourceManager::parse(ParserContext &ctx, Resource &resource,  	Rooted<Node> node;  	try {  		// Set the current source id in the logger instance -		ScopedLogger logger(ctx.logger, SourceLocation{sourceId}); +		GuardedLogger logger(ctx.logger, SourceLocation{sourceId});  		// Fetch the input stream and create a char reader  		std::unique_ptr<std::istream> is = resource.stream(); @@ -280,5 +281,11 @@ SourceContext ResourceManager::readContext(const SourceLocation &location,  	}  	return SourceContext{};  } + +SourceContext ResourceManager::readContext(const SourceLocation &location) +{ +	return readContext(location, SourceContextReader::MAX_MAX_CONTEXT_LENGTH); +} +  } diff --git a/src/core/resource/ResourceManager.hpp b/src/core/resource/ResourceManager.hpp index d5381b9..221e2cc 100644 --- a/src/core/resource/ResourceManager.hpp +++ b/src/core/resource/ResourceManager.hpp @@ -34,7 +34,6 @@  #include <core/common/Location.hpp>  #include <core/common/Rtti.hpp> -#include <core/common/SourceContextReader.hpp>  #include <core/managed/Managed.hpp>  #include "Resource.hpp" @@ -230,9 +229,22 @@ public:  	 * @return a valid SourceContext if a valid SourceLocation was given or an  	 * invalid SourceContext if the location is invalid.  	 */ -	SourceContext readContext( -	    const SourceLocation &location, -	    size_t maxContextLength = SourceContextReader::MAX_MAX_CONTEXT_LENGTH); +	SourceContext readContext(const SourceLocation &location, +	                          size_t maxContextLength); +	/** +	 * Creates and returns a SourceContext structure containing information +	 * about the given SourceLocation (such as line and column number). Throws +	 * a LoggableException if an irrecoverable error occurs while looking up the +	 * context (such as a no longer existing resource). Does not limit the +	 * context length. +	 * +	 * @param location is the SourceLocation for which context information +	 * should be retrieved. This method is used by the Logger class to print +	 * pretty messages. +	 * @return a valid SourceContext if a valid SourceLocation was given or an +	 * invalid SourceContext if the location is invalid. +	 */ +	SourceContext readContext(const SourceLocation &location);  };  }  | 
