add overloads for Error::all() and Error::one() that can point out the location of a faulty argument
This commit is contained in:
@ -103,7 +103,7 @@ void CreateAtoms::command(int narg, char **arg)
|
||||
style = REGION;
|
||||
if (narg < 3) utils::missing_cmd_args(FLERR, "create_atoms region", error);
|
||||
region = domain->get_region_by_id(arg[2]);
|
||||
if (!region) error->all(FLERR, "Create_atoms region {} does not exist", arg[2]);
|
||||
if (!region) error->all(FLERR, 2, "Create_atoms region {} does not exist", arg[2]);
|
||||
region->init();
|
||||
region->prematch();
|
||||
iarg = 3;
|
||||
@ -127,7 +127,7 @@ void CreateAtoms::command(int narg, char **arg)
|
||||
region = nullptr;
|
||||
else {
|
||||
region = domain->get_region_by_id(arg[4]);
|
||||
if (!region) error->all(FLERR, "Create_atoms region {} does not exist", arg[4]);
|
||||
if (!region) error->all(FLERR, 4, "Create_atoms region {} does not exist", arg[4]);
|
||||
region->init();
|
||||
region->prematch();
|
||||
}
|
||||
@ -138,7 +138,7 @@ void CreateAtoms::command(int narg, char **arg)
|
||||
meshfile = arg[2];
|
||||
iarg = 3;
|
||||
} else
|
||||
error->all(FLERR, "Unknown create_atoms command option {}", arg[1]);
|
||||
error->all(FLERR, 1, "Unknown create_atoms command option {}", arg[1]);
|
||||
|
||||
// process optional keywords
|
||||
|
||||
|
||||
@ -114,7 +114,7 @@ void Error::universe_warn(const std::string &file, int line, const std::string &
|
||||
force MPI_Abort if running in multi-partition mode
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Error::all(const std::string &file, int line, const std::string &str)
|
||||
void Error::all(const std::string &file, int line, int failed, const std::string &str)
|
||||
{
|
||||
MPI_Barrier(world);
|
||||
|
||||
@ -125,9 +125,11 @@ void Error::all(const std::string &file, int line, const std::string &str)
|
||||
|
||||
if (me == 0) {
|
||||
std::string mesg = "ERROR: " + str;
|
||||
|
||||
if (input && input->line) lastcmd = input->line;
|
||||
try {
|
||||
mesg += fmt::format(" ({}:{})\nLast command: {}\n", truncpath(file),line,lastcmd);
|
||||
if (failed > NOPOINTER) mesg += utils::point_to_error(input, failed);
|
||||
} catch (fmt::format_error &) {
|
||||
; // do nothing
|
||||
}
|
||||
@ -140,6 +142,7 @@ void Error::all(const std::string &file, int line, const std::string &str)
|
||||
if (update) update->whichflag = 0;
|
||||
|
||||
std::string msg = fmt::format("ERROR: {} ({}:{})\n", str, truncpath(file), line);
|
||||
if (failed > NOPOINTER) msg += utils::point_to_error(input, failed);
|
||||
|
||||
if (universe->nworlds > 1)
|
||||
throw LAMMPSAbortException(msg, universe->uworld);
|
||||
@ -154,15 +157,21 @@ void Error::all(const std::string &file, int line, const std::string &str)
|
||||
forces abort of entire world (and universe) if any proc in world calls
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Error::one(const std::string &file, int line, const std::string &str)
|
||||
void Error::one(const std::string &file, int line, int failed, const std::string &str)
|
||||
{
|
||||
int me;
|
||||
std::string lastcmd = "(unknown)";
|
||||
MPI_Comm_rank(world,&me);
|
||||
|
||||
if (input && input->line) lastcmd = input->line;
|
||||
std::string mesg = fmt::format("ERROR on proc {}: {} ({}:{})\nLast command: {}\n",
|
||||
me,str,truncpath(file),line,lastcmd);
|
||||
std::string mesg;
|
||||
try {
|
||||
mesg = fmt::format("ERROR on proc {}: {} ({}:{})\nLast command: {}\n",
|
||||
me,str,truncpath(file),line,lastcmd);
|
||||
if (failed > NOPOINTER) mesg += utils::point_to_error(input, failed);
|
||||
} catch (fmt::format_error &) {
|
||||
; // do nothing
|
||||
}
|
||||
utils::logmesg(lmp,mesg);
|
||||
|
||||
if (universe->nworlds > 1)
|
||||
@ -177,27 +186,27 @@ void Error::one(const std::string &file, int line, const std::string &str)
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
forward vararg version to single string version
|
||||
forward vararg versions to single string version
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Error::_all(const std::string &file, int line, fmt::string_view format,
|
||||
void Error::_all(const std::string &file, int line, int failed, fmt::string_view format,
|
||||
fmt::format_args args)
|
||||
{
|
||||
try {
|
||||
all(file,line,fmt::vformat(format, args));
|
||||
all(file, line, failed, fmt::vformat(format, args));
|
||||
} catch (fmt::format_error &e) {
|
||||
all(file,line,e.what());
|
||||
all(file, line, NOPOINTER, e.what());
|
||||
}
|
||||
exit(1); // to trick "smart" compilers into believing this does not return
|
||||
}
|
||||
|
||||
void Error::_one(const std::string &file, int line, fmt::string_view format,
|
||||
void Error::_one(const std::string &file, int line, int failed, fmt::string_view format,
|
||||
fmt::format_args args)
|
||||
{
|
||||
try {
|
||||
one(file,line,fmt::vformat(format, args));
|
||||
one(file, line, failed, fmt::vformat(format, args));
|
||||
} catch (fmt::format_error &e) {
|
||||
one(file,line,e.what());
|
||||
one(file, line, NOPOINTER, e.what());
|
||||
}
|
||||
exit(1); // to trick "smart" compilers into believing this does not return
|
||||
}
|
||||
|
||||
49
src/error.h
49
src/error.h
@ -27,18 +27,49 @@ class Error : protected Pointers {
|
||||
[[noreturn]] void universe_one(const std::string &, int, const std::string &);
|
||||
void universe_warn(const std::string &, int, const std::string &);
|
||||
|
||||
[[noreturn]] void all(const std::string &, int, const std::string &);
|
||||
template <typename... Args>
|
||||
[[noreturn]] void all(const std::string &file, int line, const std::string &format, Args &&...args)
|
||||
static constexpr int NOPOINTER = -2;
|
||||
|
||||
// regular error calls
|
||||
|
||||
[[noreturn]] void all(const std::string &file, int line, const std::string &str)
|
||||
{
|
||||
_all(file, line, format, fmt::make_format_args(args...));
|
||||
all(file, line, NOPOINTER, str);
|
||||
}
|
||||
|
||||
[[noreturn]] void one(const std::string &, int, const std::string &);
|
||||
template <typename... Args>
|
||||
[[noreturn]] void one(const std::string &file, int line, const std::string &format, Args &&...args)
|
||||
[[noreturn]] void all(const std::string &file, int line, const std::string &format,
|
||||
Args &&...args)
|
||||
{
|
||||
_one(file, line, format, fmt::make_format_args(args...));
|
||||
_all(file, line, NOPOINTER, format, fmt::make_format_args(args...));
|
||||
}
|
||||
|
||||
[[noreturn]] void one(const std::string &file, int line, const std::string &str)
|
||||
{
|
||||
one(file, line, NOPOINTER, str);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
[[noreturn]] void one(const std::string &file, int line, const std::string &format,
|
||||
Args &&...args)
|
||||
{
|
||||
_one(file, line, NOPOINTER, format, fmt::make_format_args(args...));
|
||||
}
|
||||
|
||||
// overloaded error calls indicating faulty argument in command line
|
||||
[[noreturn]] void all(const std::string &, int, int, const std::string &);
|
||||
template <typename... Args>
|
||||
[[noreturn]] void all(const std::string &file, int line, int failed, const std::string &format,
|
||||
Args &&...args)
|
||||
{
|
||||
_all(file, line, failed, format, fmt::make_format_args(args...));
|
||||
}
|
||||
|
||||
[[noreturn]] void one(const std::string &, int, int, const std::string &);
|
||||
template <typename... Args>
|
||||
[[noreturn]] void one(const std::string &file, int line, int failed, const std::string &format,
|
||||
Args &&...args)
|
||||
{
|
||||
_one(file, line, failed, format, fmt::make_format_args(args...));
|
||||
}
|
||||
|
||||
void warning(const std::string &, int, const std::string &);
|
||||
@ -72,8 +103,8 @@ class Error : protected Pointers {
|
||||
|
||||
int numwarn, maxwarn, allwarn;
|
||||
// internal versions that accept explicit fmtlib arguments
|
||||
[[noreturn]] void _all(const std::string &, int, fmt::string_view, fmt::format_args args);
|
||||
[[noreturn]] void _one(const std::string &, int, fmt::string_view, fmt::format_args args);
|
||||
[[noreturn]] void _all(const std::string &, int, int, fmt::string_view, fmt::format_args args);
|
||||
[[noreturn]] void _one(const std::string &, int, int, fmt::string_view, fmt::format_args args);
|
||||
void _warning(const std::string &, int, fmt::string_view, fmt::format_args args);
|
||||
void _message(const std::string &, int, fmt::string_view, fmt::format_args args);
|
||||
};
|
||||
|
||||
@ -28,6 +28,7 @@ class Input : protected Pointers {
|
||||
friend class SimpleCommandsTest_Echo_Test;
|
||||
|
||||
public:
|
||||
char *command; // ptr to current command
|
||||
int narg; // # of command args
|
||||
char **arg; // parsed args for command
|
||||
class Variable *variable; // defined variables
|
||||
@ -42,7 +43,6 @@ class Input : protected Pointers {
|
||||
int get_jump_skip() const { return jump_skip; }
|
||||
|
||||
protected:
|
||||
char *command; // ptr to current command
|
||||
int echo_screen; // 0 = no, 1 = yes
|
||||
int echo_log; // 0 = no, 1 = yes
|
||||
|
||||
|
||||
@ -132,6 +132,28 @@ void utils::missing_cmd_args(const std::string &file, int line, const std::strin
|
||||
if (error) error->all(file, line, "Illegal {} command: missing argument(s)", cmd);
|
||||
}
|
||||
|
||||
std::string utils::point_to_error(Input *input, int failedarg)
|
||||
{
|
||||
if (input) {
|
||||
std::string cmdline = "Preprocessed: ";
|
||||
int indicator = cmdline.size(); // error indicator points to command by default
|
||||
cmdline += input->command;
|
||||
cmdline += ' ';
|
||||
|
||||
// assemble pre-processed command line and update error indicator position, if needed.
|
||||
for (int i = 0; i < input->narg; ++i) {
|
||||
if (i == failedarg) indicator = cmdline.size();
|
||||
cmdline += input->arg[i];
|
||||
cmdline += ' ';
|
||||
}
|
||||
// construct and append error indicator line
|
||||
cmdline += '\n';
|
||||
cmdline += std::string(indicator, ' ');
|
||||
cmdline += "^\n";
|
||||
return cmdline;
|
||||
} else return std::string("(Failed command line text not available)");
|
||||
}
|
||||
|
||||
/* specialization for the case of just a single string argument */
|
||||
|
||||
void utils::logmesg(LAMMPS *lmp, const std::string &mesg)
|
||||
|
||||
10
src/utils.h
10
src/utils.h
@ -28,6 +28,7 @@ namespace LAMMPS_NS {
|
||||
|
||||
// forward declarations
|
||||
class Error;
|
||||
class Input;
|
||||
class LAMMPS;
|
||||
|
||||
namespace utils {
|
||||
@ -59,6 +60,15 @@ namespace utils {
|
||||
|
||||
void missing_cmd_args(const std::string &file, int line, const std::string &cmd, Error *error);
|
||||
|
||||
/*! Create string with last command after pre-processing and pointing to arg with error
|
||||
*
|
||||
* This function is a helper function for error messages. It creates
|
||||
*
|
||||
* \param input pointer to the Input class instance (for access to last command args)
|
||||
* \param failedarg index of the faulty argument (-1 to point to the command itself)
|
||||
* \return string with two lines: the pre-processed command and a '^' pointing to the faulty argument */
|
||||
std::string point_to_error(Input *input, int failedarg);
|
||||
|
||||
/*! Internal function handling the argument list for logmesg(). */
|
||||
|
||||
void fmtargs_logmesg(LAMMPS *lmp, fmt::string_view format, fmt::format_args args);
|
||||
|
||||
Reference in New Issue
Block a user