const char *file, int line)
{
const char *title = getErrorCodeString(retcode);
- internal::printFatalError(stderr, title, msg, NULL, file, line);
+ internal::printFatalErrorHeader(stderr, title, NULL, file, line);
+ internal::printFatalErrorMessageLine(stderr, msg, 0);
+ internal::printFatalErrorFooter(stderr);
std::exit(1);
}
* \author Teemu Murtola <teemu.murtola@cbr.su.se>
* \ingroup module_utility
*/
-#include "gromacs/utility/errorformat.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "errorformat.h"
+
+#include <cctype>
#include <cstdio>
+#include <cstring>
#include "gromacs/legacyheaders/copyrite.h"
namespace internal
{
-void printFatalError(FILE *fp, const char *title, const char *details,
- const char *func, const char *file, int line)
+void printFatalErrorHeader(FILE *fp, const char *title,
+ const char *func, const char *file, int line)
{
// In case ProgramInfo is not initialized and there is an issue with the
// initialization, fall back to "GROMACS".
}
std::fprintf(fp, "\n-------------------------------------------------------\n");
- std::fprintf(fp, "Program %s, %s\n", programName, GromacsVersion());
- if (func != NULL)
+ std::fprintf(fp, "Program: %s, %s\n", programName, GromacsVersion());
+ if (file != NULL)
{
- std::fprintf(fp, "In function: %s\n", func);
+ // TODO: Check whether this works on Windows. If it doesn't, perhaps
+ // add Path::startsWith().
+ if (startsWith(file, CMAKE_SOURCE_DIR))
+ {
+ file += std::strlen(CMAKE_SOURCE_DIR);
+ if (file[0] == '/' || file[0] == '\\')
+ {
+ ++file;
+ }
+ }
+ std::fprintf(fp, "Source file: %s (line %d)\n", file, line);
}
- // TODO: Strip away absolute paths from file names (CMake seems to generate those)
- if (file != NULL)
+ if (func != NULL)
{
- std::fprintf(fp, "Source file %s, line %d\n", file, line);
+ std::fprintf(fp, "Function: %s\n", func);
}
std::fprintf(fp, "\n");
std::fprintf(fp, "%s:\n", title);
- // TODO: Line wrapping
- std::fprintf(fp, "%s\n", details);
+}
+
+void printFatalErrorMessageLine(FILE *fp, const char *text, int indent)
+{
+ gmx::TextLineWrapper wrapper;
+ wrapper.settings().setLineLength(78 - indent);
+ size_t lineStart = 0;
+ size_t length = std::strlen(text);
+ while (lineStart < length)
+ {
+ size_t nextLineStart = wrapper.findNextLine(text, lineStart);
+ int lineLength = static_cast<int>(nextLineStart - lineStart);
+ while (lineLength > 0 && std::isspace(text[lineStart + lineLength - 1]))
+ {
+ --lineLength;
+ }
+ std::fprintf(fp, "%*s%.*s\n", indent, "", lineLength, text + lineStart);
+ lineStart = nextLineStart;
+ }
+}
+
+void printFatalErrorFooter(FILE *fp)
+{
+ std::fprintf(fp, "\n");
std::fprintf(fp, "For more information and tips for troubleshooting, please check the GROMACS\n"
"website at http://www.gromacs.org/Documentation/Errors");
std::fprintf(fp, "\n-------------------------------------------------------\n");
{
/*! \internal \brief
- * Formats common headers and footers for error messages.
+ * Formats a common header for fatal error messages.
*
* Does not throw.
*
* \ingroup module_utility
*/
-void printFatalError(FILE *fp, const char *title, const char *details,
- const char *func, const char *file, int line);
+void printFatalErrorHeader(FILE *fp, const char *title,
+ const char *func, const char *file, int line);
+/*! \internal \brief
+ * Formats a line of fatal error message text.
+ *
+ * Does not throw.
+ *
+ * \ingroup module_utility
+ */
+void printFatalErrorMessageLine(FILE *fp, const char *text, int indent);
+/*! \internal \brief
+ * Formats a common footer for fatal error messages.
+ *
+ * Does not throw.
+ *
+ * \ingroup module_utility
+ */
+void printFatalErrorFooter(FILE *fp);
} // namespace internal
//! \endcond
filePtr = boost::get_error_info<boost::throw_file>(*boostEx);
linePtr = boost::get_error_info<boost::throw_line>(*boostEx);
}
+ internal::printFatalErrorHeader(fp, title,
+ funcPtr != NULL ? *funcPtr : NULL,
+ filePtr != NULL ? *filePtr : NULL,
+ linePtr != NULL ? *linePtr : 0);
+ internal::printFatalErrorMessageLine(fp, ex.what(), 0);
// TODO: Treat errno information in boost exceptions
- internal::printFatalError(fp, title, ex.what(),
- funcPtr != NULL ? *funcPtr : NULL,
- filePtr != NULL ? *filePtr : NULL,
- linePtr != NULL ? *linePtr : 0);
+ internal::printFatalErrorFooter(fp);
}
} // namespace gmx
* \author Teemu Murtola <teemu.murtola@cbr.su.se>
* \ingroup module_utility
*/
-#include "gromacs/utility/gmxassert.h"
+#include "gmxassert.h"
#include <cstdio>
#include <cstdlib>
-#include <string>
-
-#include "gromacs/utility/stringutil.h"
-
#include "errorformat.h"
namespace gmx
void assertHandler(const char *condition, const char *msg,
const char *func, const char *file, int line)
{
- try
- {
- std::string title = formatString("Condition: %s\n%s", condition, msg);
- printFatalError(stderr, "Assertion failed", title.c_str(),
- func, file, line);
- }
- catch (const std::bad_alloc &)
- {
- printFatalError(stderr, "Assertion failed",
- "(memory allocation failed while formatting the error message)",
- func, file, line);
- }
+ printFatalErrorHeader(stderr, "Assertion failed", func, file, line);
+ std::fprintf(stderr, "Condition: %s\n", condition);
+ printFatalErrorMessageLine(stderr, msg, 0);
+ printFatalErrorFooter(stderr);
std::abort();
}
#ifndef GMX_UTILITY_STRINGUTIL_H
#define GMX_UTILITY_STRINGUTIL_H
+#include <cstring>
+
#include <string>
#include <vector>
{
return str.compare(0, prefix.length(), prefix) == 0;
}
+//! \copydoc startsWith(const std::string &, const std::string &)
+bool inline startsWith(const char *str, const char *prefix)
+{
+ return std::strncmp(str, prefix, std::strlen(prefix)) == 0;
+}
/*! \brief
* Tests whether a string ends with another string.
EXPECT_FALSE(gmx::startsWith("", "foobar"));
EXPECT_FALSE(gmx::startsWith("foo", "foobar"));
EXPECT_FALSE(gmx::startsWith("foobar", "oob"));
+ EXPECT_TRUE(gmx::startsWith(std::string("foobar"), "foo"));
+ EXPECT_TRUE(gmx::startsWith(std::string("foobar"), ""));
+ EXPECT_TRUE(gmx::startsWith(std::string(""), ""));
+ EXPECT_FALSE(gmx::startsWith(std::string(""), "foobar"));
+ EXPECT_FALSE(gmx::startsWith(std::string("foo"), "foobar"));
+ EXPECT_FALSE(gmx::startsWith(std::string("foobar"), "oob"));
}
TEST(StringUtilityTest, EndsWithWorks)