Line data Source code
1 : /* Copyright 1989-2020 Free Software Foundation, Inc.
2 : Written by James Clark (jjc@jclark.com)
3 :
4 : This file is part of groff, the GNU roff typesetting system.
5 :
6 : groff is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation, either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : groff is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 :
19 : #ifdef HAVE_CONFIG_H
20 : #include <config.h>
21 : #endif
22 :
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include <string.h>
26 : #include "errarg.h"
27 : #include "error.h"
28 :
29 : extern void fatal_error_exit();
30 :
31 : enum error_type { DEBUG, WARNING, ERROR, FATAL };
32 :
33 43 : static void do_error_with_file_and_line(const char *filename,
34 : const char *source_filename,
35 : int lineno,
36 : error_type type,
37 : const char *format,
38 : const errarg &arg1,
39 : const errarg &arg2,
40 : const errarg &arg3)
41 : {
42 43 : bool need_space = false;
43 43 : if (program_name != 0 /* nullptr */) {
44 43 : fputs(program_name, stderr);
45 43 : fputc(':', stderr);
46 43 : need_space = true;
47 : }
48 43 : if (filename != 0 /* nullptr */) {
49 34 : if (strcmp(filename, "-") == 0)
50 18 : filename = "<standard input>";
51 34 : fputs(filename, stderr);
52 34 : if (source_filename != 0 /* nullptr */) {
53 0 : fputs(":(", stderr);
54 0 : fputs(source_filename, stderr);
55 0 : fputc(')', stderr);
56 : }
57 34 : if (lineno > 0) {
58 33 : fputc(':', stderr);
59 33 : errprint("%1", lineno);
60 : }
61 34 : fputc(':', stderr);
62 34 : need_space = true;
63 : }
64 43 : if (need_space)
65 43 : fputc(' ', stderr);
66 43 : switch (type) {
67 4 : case FATAL:
68 4 : fputs("fatal error", stderr);
69 4 : break;
70 35 : case ERROR:
71 35 : fputs("error", stderr);
72 35 : break;
73 4 : case WARNING:
74 4 : fputs("warning", stderr);
75 4 : break;
76 0 : case DEBUG:
77 0 : fputs("debug", stderr);
78 0 : break;
79 : }
80 43 : fputs(": ", stderr);
81 43 : errprint(format, arg1, arg2, arg3);
82 43 : fputc('\n', stderr);
83 43 : fflush(stderr);
84 43 : if (type == FATAL)
85 4 : fatal_error_exit();
86 39 : }
87 :
88 33 : static void do_error(error_type type,
89 : const char *format,
90 : const errarg &arg1,
91 : const errarg &arg2,
92 : const errarg &arg3)
93 : {
94 33 : do_error_with_file_and_line(current_filename, current_source_filename,
95 : current_lineno, type, format, arg1, arg2,
96 : arg3);
97 29 : }
98 :
99 : // This function should have no callers in production builds.
100 0 : void debug(const char *format,
101 : const errarg &arg1,
102 : const errarg &arg2,
103 : const errarg &arg3)
104 : {
105 0 : do_error(DEBUG, format, arg1, arg2, arg3);
106 0 : }
107 :
108 26 : void error(const char *format,
109 : const errarg &arg1,
110 : const errarg &arg2,
111 : const errarg &arg3)
112 : {
113 26 : do_error(ERROR, format, arg1, arg2, arg3);
114 26 : }
115 :
116 3 : void warning(const char *format,
117 : const errarg &arg1,
118 : const errarg &arg2,
119 : const errarg &arg3)
120 : {
121 3 : do_error(WARNING, format, arg1, arg2, arg3);
122 3 : }
123 :
124 4 : void fatal(const char *format,
125 : const errarg &arg1,
126 : const errarg &arg2,
127 : const errarg &arg3)
128 : {
129 4 : do_error(FATAL, format, arg1, arg2, arg3);
130 0 : }
131 :
132 : // Use the functions below when it's more costly to save and restore the
133 : // globals current_filename, current_source_filename, and current_lineno
134 : // than to specify additional arguments. For instance, a function that
135 : // would need to temporarily change their values and has multiple return
136 : // paths might prefer these to the simpler variants above.
137 :
138 : // This function should have no callers in production builds.
139 0 : void debug_with_file_and_line(const char *filename,
140 : int lineno,
141 : const char *format,
142 : const errarg &arg1,
143 : const errarg &arg2,
144 : const errarg &arg3)
145 : {
146 0 : do_error_with_file_and_line(filename, 0 /* nullptr */, lineno,
147 : DEBUG, format, arg1, arg2, arg3);
148 0 : }
149 :
150 9 : void error_with_file_and_line(const char *filename,
151 : int lineno,
152 : const char *format,
153 : const errarg &arg1,
154 : const errarg &arg2,
155 : const errarg &arg3)
156 : {
157 9 : do_error_with_file_and_line(filename, 0 /* nullptr */, lineno,
158 : ERROR, format, arg1, arg2, arg3);
159 9 : }
160 :
161 1 : void warning_with_file_and_line(const char *filename,
162 : int lineno,
163 : const char *format,
164 : const errarg &arg1,
165 : const errarg &arg2,
166 : const errarg &arg3)
167 : {
168 1 : do_error_with_file_and_line(filename, 0 /* nullptr */, lineno,
169 : WARNING, format, arg1, arg2, arg3);
170 1 : }
171 :
172 0 : void fatal_with_file_and_line(const char *filename,
173 : int lineno,
174 : const char *format,
175 : const errarg &arg1,
176 : const errarg &arg2,
177 : const errarg &arg3)
178 : {
179 0 : do_error_with_file_and_line(filename, 0 /* nullptr */, lineno,
180 : FATAL, format, arg1, arg2, arg3);
181 0 : }
182 :
183 : // Local Variables:
184 : // fill-column: 72
185 : // mode: C++
186 : // End:
187 : // vim: set cindent noexpandtab shiftwidth=2 textwidth=72:
|