/* Copyright (C) 1989-2020 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) This file is part of groff. groff 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. groff 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 . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "errarg.h" #include "error.h" extern void fatal_error_exit(); enum error_type { DEBUG, WARNING, ERROR, FATAL }; static void do_error_with_file_and_line(const char *filename, const char *source_filename, int lineno, error_type type, const char *format, const errarg &arg1, const errarg &arg2, const errarg &arg3) { bool need_space = false; if (program_name != 0 /* nullptr */) { fputs(program_name, stderr); fputc(':', stderr); need_space = true; } if (filename != 0 /* nullptr */) { if (strcmp(filename, "-") == 0) filename = ""; fputs(filename, stderr); if (source_filename != 0 /* nullptr */) { fputs(":(", stderr); fputs(source_filename, stderr); fputc(')', stderr); } if (lineno > 0) { fputc(':', stderr); errprint("%1", lineno); } fputc(':', stderr); need_space = true; } if (need_space) fputc(' ', stderr); switch (type) { case FATAL: fputs("fatal error", stderr); break; case ERROR: fputs("error", stderr); break; case WARNING: fputs("warning", stderr); break; case DEBUG: fputs("debug", stderr); break; } fputs(": ", stderr); errprint(format, arg1, arg2, arg3); fputc('\n', stderr); fflush(stderr); if (type == FATAL) fatal_error_exit(); } static void do_error(error_type type, const char *format, const errarg &arg1, const errarg &arg2, const errarg &arg3) { do_error_with_file_and_line(current_filename, current_source_filename, current_lineno, type, format, arg1, arg2, arg3); } void debug(const char *format, const errarg &arg1, const errarg &arg2, const errarg &arg3) { do_error(DEBUG, format, arg1, arg2, arg3); } void error(const char *format, const errarg &arg1, const errarg &arg2, const errarg &arg3) { do_error(ERROR, format, arg1, arg2, arg3); } void warning(const char *format, const errarg &arg1, const errarg &arg2, const errarg &arg3) { do_error(WARNING, format, arg1, arg2, arg3); } void fatal(const char *format, const errarg &arg1, const errarg &arg2, const errarg &arg3) { do_error(FATAL, format, arg1, arg2, arg3); } // Use the functions below when it's more costly to save and restore the // globals current_filename, current_source_filename, and current_lineno // than to specify additional arguments. For instance, a function that // would need to temporarily change their values and has multiple return // paths might prefer these to the simpler variants above. void debug_with_file_and_line(const char *filename, int lineno, const char *format, const errarg &arg1, const errarg &arg2, const errarg &arg3) { do_error_with_file_and_line(filename, 0 /* nullptr */, lineno, DEBUG, format, arg1, arg2, arg3); } void error_with_file_and_line(const char *filename, int lineno, const char *format, const errarg &arg1, const errarg &arg2, const errarg &arg3) { do_error_with_file_and_line(filename, 0 /* nullptr */, lineno, ERROR, format, arg1, arg2, arg3); } void warning_with_file_and_line(const char *filename, int lineno, const char *format, const errarg &arg1, const errarg &arg2, const errarg &arg3) { do_error_with_file_and_line(filename, 0 /* nullptr */, lineno, WARNING, format, arg1, arg2, arg3); } void fatal_with_file_and_line(const char *filename, int lineno, const char *format, const errarg &arg1, const errarg &arg2, const errarg &arg3) { do_error_with_file_and_line(filename, 0 /* nullptr */, lineno, FATAL, format, arg1, arg2, arg3); } // Local Variables: // fill-column: 72 // mode: C++ // End: // vim: set cindent noexpandtab shiftwidth=2 textwidth=72: