Revamp of the Halibut error handling mechanism.
[sgt/halibut] / error.c
1 /*
2 * error.c: Halibut error handling
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdarg.h>
8 #include "halibut.h"
9
10 /*
11 * Error flags
12 */
13 #define PREFIX 0x0001 /* give `halibut:' prefix */
14 #define FILEPOS 0x0002 /* give file position prefix */
15
16 static void do_error(const filepos *fpos, const char *fmt, ...)
17 {
18 va_list ap;
19
20 if (fpos) {
21 fprintf(stderr, "%s:",
22 fpos->filename ? fpos->filename : "<standard input>");
23 if (fpos->line > 0)
24 fprintf(stderr, "%d:", fpos->line);
25 if (fpos->col > 0)
26 fprintf(stderr, "%d:", fpos->col);
27 fputc(' ', stderr);
28 } else {
29 fputs("halibut: ", stderr);
30 }
31
32 va_start(ap, fmt);
33 vfprintf(stderr, fmt, ap);
34 va_end(ap);
35
36 fputc('\n', stderr);
37 }
38
39 void fatalerr_nomemory(void)
40 {
41 do_error(NULL, "out of memory");
42 exit(EXIT_FAILURE);
43 }
44
45 void err_optnoarg(const char *sp)
46 {
47 do_error(NULL, "option `-%s' requires an argument", sp);
48 }
49
50 void err_nosuchopt(const char *sp)
51 {
52 do_error(NULL, "unrecognised option `-%s'", sp);
53 }
54
55 void err_cmdcharset(const char *sp)
56 {
57 do_error(NULL, "character set `%s' not recognised", sp);
58 }
59
60 void err_futileopt(const char *sp, const char *sp2)
61 {
62 do_error(NULL, "warning: option `-%s' has no effect%s", sp, sp2);
63 }
64
65 void err_noinput(void)
66 {
67 do_error(NULL, "no input files");
68 }
69
70 void err_cantopen(const char *sp)
71 {
72 do_error(NULL, "unable to open input file `%s'", sp);
73 }
74
75 void err_nodata(void)
76 {
77 do_error(NULL, "no data in input files");
78 }
79
80 void err_brokencodepara(const filepos *fpos)
81 {
82 do_error(fpos, "every line of a code paragraph should begin `\\c'");
83 }
84
85 void err_kwunclosed(const filepos *fpos)
86 {
87 do_error(fpos, "expected `}' after paragraph keyword");
88 }
89
90 void err_kwexpected(const filepos *fpos)
91 {
92 do_error(fpos, "expected a paragraph keyword");
93 }
94
95 void err_kwillegal(const filepos *fpos)
96 {
97 do_error(fpos, "expected no paragraph keyword");
98 }
99
100 void err_kwtoomany(const filepos *fpos)
101 {
102 do_error(fpos, "expected only one paragraph keyword");
103 }
104
105 void err_bodyillegal(const filepos *fpos)
106 {
107 do_error(fpos, "expected no text after paragraph keyword");
108 }
109
110 void err_badparatype(const wchar_t *wsp, const filepos *fpos)
111 {
112 char *sp = utoa_locale_dup(wsp);
113 do_error(fpos, "command `%s' unrecognised at start of paragraph", sp);
114 sfree(sp);
115 }
116
117 void err_badmidcmd(const wchar_t *wsp, const filepos *fpos)
118 {
119 char *sp = utoa_locale_dup(wsp);
120 do_error(fpos, "command `%s' unexpected in mid-paragraph", sp);
121 sfree(sp);
122 }
123
124 void err_unexbrace(const filepos *fpos)
125 {
126 do_error(fpos, "brace character unexpected in mid-paragraph");
127 }
128
129 void err_explbr(const filepos *fpos)
130 {
131 do_error(fpos, "expected `{' after command");
132 }
133
134 void err_commenteof(const filepos *fpos)
135 {
136 do_error(fpos, "end of file unexpected inside `\\#{...}' comment");
137 }
138
139 void err_kwexprbr(const filepos *fpos)
140 {
141 do_error(fpos, "expected `}' after cross-reference");
142 }
143
144 void err_codequote(const filepos *fpos)
145 {
146 do_error(fpos, "unable to nest \\q{...} within \\c{...} or \\cw{...}");
147 }
148
149 void err_missingrbrace(const filepos *fpos)
150 {
151 do_error(fpos, "unclosed braces at end of paragraph");
152 }
153
154 void err_missingrbrace2(const filepos *fpos)
155 {
156 do_error(fpos, "unclosed braces at end of input file");
157 }
158
159 void err_nestedstyles(const filepos *fpos)
160 {
161 do_error(fpos, "unable to nest text styles");
162 }
163
164 void err_nestedindex(const filepos *fpos)
165 {
166 do_error(fpos, "unable to nest index markings");
167 }
168
169 void err_indexcase(const filepos *fpos, const wchar_t *wsp,
170 const filepos *fpos2, const wchar_t *wsp2)
171 {
172 char *sp = utoa_locale_dup(wsp), *sp2 = utoa_locale_dup(wsp2);
173 do_error(fpos, "warning: index tag `%s' used with different "
174 "case (`%s') at %s:%d",
175 sp, sp2, fpos2->filename, fpos2->line);
176 sfree(sp);
177 sfree(sp2);
178 }
179
180 void err_nosuchkw(const filepos *fpos, const wchar_t *wsp)
181 {
182 char *sp = utoa_locale_dup(wsp);
183 do_error(fpos, "unable to resolve cross-reference to `%s'", sp);
184 sfree(sp);
185 }
186
187 void err_multiBR(const filepos *fpos, const wchar_t *wsp)
188 {
189 char *sp = utoa_locale_dup(wsp);
190 do_error(fpos, "multiple `\\BR' entries given for `%s'", sp);
191 sfree(sp);
192 }
193
194 void err_nosuchidxtag(const filepos *fpos, const wchar_t *wsp)
195 {
196 char *sp = utoa_locale_dup(wsp);
197 do_error(fpos, "`\\IM' on unknown index tag `%s'", sp);
198 sfree(sp);
199 }
200
201 void err_cantopenw(const char *sp)
202 {
203 do_error(NULL, "unable to open output file `%s'", sp);
204 }
205
206 void err_macroexists(const filepos *fpos, const wchar_t *wsp)
207 {
208 char *sp = utoa_locale_dup(wsp);
209 do_error(fpos, "macro `%s' already defined", sp);
210 sfree(sp);
211 }
212
213 void err_sectjump(const filepos *fpos)
214 {
215 do_error(fpos, "expected higher heading levels before this one");
216 }
217
218 void err_winhelp_ctxclash(const filepos *fpos, const char *sp, const char *sp2)
219 {
220 do_error(fpos, "Windows Help context id `%s' clashes with "
221 "previously defined `%s'", sp, sp2);
222 }
223
224 void err_multikw(const filepos *fpos, const filepos *fpos2, const wchar_t *wsp)
225 {
226 char *sp = utoa_locale_dup(wsp);
227 do_error(fpos, "paragraph keyword `%s' already defined at %s:%d",
228 sp, fpos2->filename, fpos2->line);
229 sfree(sp);
230 }
231
232 void err_misplacedlcont(const filepos *fpos)
233 {
234 do_error(fpos, "\\lcont is only expected after a list item");
235 }
236
237 void err_sectmarkerinblock(const filepos *fpos, const char *sp)
238 {
239 do_error(fpos, "section headings are not supported within \\%s", sp);
240 }
241
242 void err_cfginsufarg(const filepos *fpos, const char *sp, int i)
243 {
244 do_error(fpos, "\\cfg{%s} expects at least %d parameter%s",
245 sp, i, (i==1)?"":"s");
246 }
247
248 void err_infonodechar(const filepos *fpos, char c) /* fpos might be NULL */
249 {
250 do_error(fpos, "info output format does not support '%c' in"
251 " node names; removing", c);
252 }
253
254 void err_text_codeline(const filepos *fpos, int i, int j)
255 {
256 do_error(fpos, "warning: code paragraph line is %d chars wide, wider"
257 " than body width %d", i, j);
258 }
259
260 void err_htmlver(const filepos *fpos, const wchar_t *wsp)
261 {
262 char *sp = utoa_locale_dup(wsp);
263 do_error(fpos, "unrecognised HTML version keyword `%s'", sp);
264 sfree(sp);
265 }
266
267 void err_charset(const filepos *fpos, const wchar_t *wsp)
268 {
269 char *sp = utoa_locale_dup(wsp);
270 do_error(fpos, "character set `%s' not recognised", sp);
271 sfree(sp);
272 }
273
274 void err_nofont(const filepos *fpos, const wchar_t *wsp)
275 {
276 char *sp = utoa_locale_dup(wsp);
277 do_error(fpos, "font `%s' not recognised", sp);
278 sfree(sp);
279 }
280
281 void err_afmeof(const filepos *fpos)
282 {
283 do_error(fpos, "AFM file ended unexpectedly");
284 }
285
286 void err_afmkey(const filepos *fpos, const char *sp)
287 {
288 do_error(fpos, "required AFM key '%s' missing", sp);
289 }
290
291 void err_afmvers(const filepos *fpos)
292 {
293 do_error(fpos, "unsupported AFM version");
294 }
295
296 void err_afmval(const filepos *fpos, const char *sp, int i)
297 {
298 if (i == 1)
299 do_error(fpos, "AFM key '%s' requires a value", sp);
300 else
301 do_error(fpos, "AFM key '%s' requires %d values", sp, i);
302 }
303
304 void err_pfeof(const filepos *fpos)
305 {
306 do_error(fpos, "Type 1 font file ended unexpectedly");
307 }
308
309 void err_pfhead(const filepos *fpos)
310 {
311 do_error(fpos, "Type 1 font file header line invalid");
312 }
313
314 void err_pfbad(const filepos *fpos)
315 {
316 do_error(fpos, "Type 1 font file invalid");
317 }
318
319 void err_pfnoafm(const filepos *fpos, const char *sp)
320 {
321 do_error(fpos, "no metrics available for Type 1 font '%s'", sp);
322 }
323
324 void err_chmnames(void)
325 {
326 do_error(NULL, "only one of html-mshtmlhelp-chm and "
327 "html-mshtmlhelp-hhp found");
328 }
329
330 void err_sfntnotable(const filepos *fpos, const char *sp)
331 {
332 do_error(fpos, "font has no '%s' table", sp);
333 }
334
335 void err_sfntnopsname(const filepos *fpos)
336 {
337 do_error(fpos, "font has no PostScript name");
338 }
339
340 void err_sfntbadtable(const filepos *fpos, const char *sp)
341 {
342 do_error(fpos, "font has an invalid '%s' table", sp);
343 }
344
345 void err_sfntnounicmap(const filepos *fpos)
346 {
347 do_error(fpos, "font has no UCS-2 character map");
348 }
349
350 void err_sfnttablevers(const filepos *fpos, const char *sp)
351 {
352 do_error(fpos, "font has an unsupported '%s' table version", sp);
353 }
354
355 void err_sfntbadhdr(const filepos *fpos)
356 {
357 do_error(fpos, "font has an invalid header");
358 }
359
360 void err_sfntbadglyph(const filepos *fpos, unsigned wc)
361 {
362 do_error(fpos,
363 "warning: character U+%04X references a non-existent glyph",
364 wc);
365 }