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 
do_error(const filepos * fpos,const char * fmt,...)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 
fatalerr_nomemory(void)39 void fatalerr_nomemory(void)
40 {
41     do_error(NULL, "out of memory");
42     exit(EXIT_FAILURE);
43 }
44 
err_optnoarg(const char * sp)45 void err_optnoarg(const char *sp)
46 {
47     do_error(NULL, "option `-%s' requires an argument", sp);
48 }
49 
err_nosuchopt(const char * sp)50 void err_nosuchopt(const char *sp)
51 {
52     do_error(NULL, "unrecognised option `-%s'", sp);
53 }
54 
err_cmdcharset(const char * sp)55 void err_cmdcharset(const char *sp)
56 {
57     do_error(NULL, "character set `%s' not recognised", sp);
58 }
59 
err_futileopt(const char * sp,const char * sp2)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 
err_noinput(void)65 void err_noinput(void)
66 {
67     do_error(NULL, "no input files");
68 }
69 
err_cantopen(const char * sp)70 void err_cantopen(const char *sp)
71 {
72     do_error(NULL, "unable to open input file `%s'", sp);
73 }
74 
err_nodata(void)75 void err_nodata(void)
76 {
77     do_error(NULL, "no data in input files");
78 }
79 
err_brokencodepara(const filepos * fpos)80 void err_brokencodepara(const filepos *fpos)
81 {
82     do_error(fpos, "every line of a code paragraph should begin `\\c'");
83 }
84 
err_kwunclosed(const filepos * fpos)85 void err_kwunclosed(const filepos *fpos)
86 {
87     do_error(fpos, "expected `}' after paragraph keyword");
88 }
89 
err_kwexpected(const filepos * fpos)90 void err_kwexpected(const filepos *fpos)
91 {
92     do_error(fpos, "expected a paragraph keyword");
93 }
94 
err_kwillegal(const filepos * fpos)95 void err_kwillegal(const filepos *fpos)
96 {
97     do_error(fpos, "expected no paragraph keyword");
98 }
99 
err_kwtoomany(const filepos * fpos)100 void err_kwtoomany(const filepos *fpos)
101 {
102     do_error(fpos, "expected only one paragraph keyword");
103 }
104 
err_bodyillegal(const filepos * fpos)105 void err_bodyillegal(const filepos *fpos)
106 {
107     do_error(fpos, "expected no text after paragraph keyword");
108 }
109 
err_badparatype(const wchar_t * wsp,const filepos * fpos)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 
err_badmidcmd(const wchar_t * wsp,const filepos * fpos)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 
err_unexbrace(const filepos * fpos)124 void err_unexbrace(const filepos *fpos)
125 {
126     do_error(fpos, "brace character unexpected in mid-paragraph");
127 }
128 
err_explbr(const filepos * fpos)129 void err_explbr(const filepos *fpos)
130 {
131     do_error(fpos, "expected `{' after command");
132 }
133 
err_commenteof(const filepos * fpos)134 void err_commenteof(const filepos *fpos)
135 {
136     do_error(fpos, "end of file unexpected inside `\\#{...}' comment");
137 }
138 
err_kwexprbr(const filepos * fpos)139 void err_kwexprbr(const filepos *fpos)
140 {
141     do_error(fpos, "expected `}' after cross-reference");
142 }
143 
err_codequote(const filepos * fpos)144 void err_codequote(const filepos *fpos)
145 {
146     do_error(fpos, "unable to nest \\q{...} within \\c{...} or \\cw{...}");
147 }
148 
err_missingrbrace(const filepos * fpos)149 void err_missingrbrace(const filepos *fpos)
150 {
151     do_error(fpos, "unclosed braces at end of paragraph");
152 }
153 
err_missingrbrace2(const filepos * fpos)154 void err_missingrbrace2(const filepos *fpos)
155 {
156     do_error(fpos, "unclosed braces at end of input file");
157 }
158 
err_nestedstyles(const filepos * fpos)159 void err_nestedstyles(const filepos *fpos)
160 {
161     do_error(fpos, "unable to nest text styles");
162 }
163 
err_nestedindex(const filepos * fpos)164 void err_nestedindex(const filepos *fpos)
165 {
166     do_error(fpos, "unable to nest index markings");
167 }
168 
err_indexcase(const filepos * fpos,const wchar_t * wsp,const filepos * fpos2,const wchar_t * wsp2)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 
err_nosuchkw(const filepos * fpos,const wchar_t * wsp)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 
err_multiBR(const filepos * fpos,const wchar_t * wsp)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 
err_nosuchidxtag(const filepos * fpos,const wchar_t * wsp)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 
err_cantopenw(const char * sp)201 void err_cantopenw(const char *sp)
202 {
203     do_error(NULL, "unable to open output file `%s'", sp);
204 }
205 
err_macroexists(const filepos * fpos,const wchar_t * wsp)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 
err_sectjump(const filepos * fpos)213 void err_sectjump(const filepos *fpos)
214 {
215     do_error(fpos, "expected higher heading levels before this one");
216 }
217 
err_winhelp_ctxclash(const filepos * fpos,const char * sp,const char * sp2)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 
err_multikw(const filepos * fpos,const filepos * fpos2,const wchar_t * wsp)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 
err_misplacedlcont(const filepos * fpos)232 void err_misplacedlcont(const filepos *fpos)
233 {
234     do_error(fpos, "\\lcont is only expected after a list item");
235 }
236 
err_sectmarkerinblock(const filepos * fpos,const char * sp)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 
err_cfginsufarg(const filepos * fpos,const char * sp,int i)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 
err_infonodechar(const filepos * fpos,char c)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 
err_text_codeline(const filepos * fpos,int i,int j)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 
err_htmlver(const filepos * fpos,const wchar_t * wsp)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 
err_charset(const filepos * fpos,const wchar_t * wsp)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 
err_nofont(const filepos * fpos,const wchar_t * wsp)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 
err_afmeof(const filepos * fpos)281 void err_afmeof(const filepos *fpos)
282 {
283     do_error(fpos, "AFM file ended unexpectedly");
284 }
285 
err_afmkey(const filepos * fpos,const char * sp)286 void err_afmkey(const filepos *fpos, const char *sp)
287 {
288     do_error(fpos, "required AFM key '%s' missing", sp);
289 }
290 
err_afmvers(const filepos * fpos)291 void err_afmvers(const filepos *fpos)
292 {
293     do_error(fpos, "unsupported AFM version");
294 }
295 
err_afmval(const filepos * fpos,const char * sp,int i)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 
err_pfeof(const filepos * fpos)304 void err_pfeof(const filepos *fpos)
305 {
306     do_error(fpos, "Type 1 font file ended unexpectedly");
307 }
308 
err_pfhead(const filepos * fpos)309 void err_pfhead(const filepos *fpos)
310 {
311     do_error(fpos, "Type 1 font file header line invalid");
312 }
313 
err_pfbad(const filepos * fpos)314 void err_pfbad(const filepos *fpos)
315 {
316     do_error(fpos, "Type 1 font file invalid");
317 }
318 
err_pfnoafm(const filepos * fpos,const char * sp)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 
err_chmnames(void)324 void err_chmnames(void)
325 {
326     do_error(NULL, "only one of html-mshtmlhelp-chm and "
327              "html-mshtmlhelp-hhp found");
328 }
329 
err_sfntnotable(const filepos * fpos,const char * sp)330 void err_sfntnotable(const filepos *fpos, const char *sp)
331 {
332     do_error(fpos, "font has no '%s' table", sp);
333 }
334 
err_sfntnopsname(const filepos * fpos)335 void err_sfntnopsname(const filepos *fpos)
336 {
337     do_error(fpos, "font has no PostScript name");
338 }
339 
err_sfntbadtable(const filepos * fpos,const char * sp)340 void err_sfntbadtable(const filepos *fpos, const char *sp)
341 {
342     do_error(fpos, "font has an invalid '%s' table", sp);
343 }
344 
err_sfntnounicmap(const filepos * fpos)345 void err_sfntnounicmap(const filepos *fpos)
346 {
347     do_error(fpos, "font has no UCS-2 character map");
348 }
349 
err_sfnttablevers(const filepos * fpos,const char * sp)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 
err_sfntbadhdr(const filepos * fpos)355 void err_sfntbadhdr(const filepos *fpos)
356 {
357     do_error(fpos, "font has an invalid header");
358 }
359 
err_sfntbadglyph(const filepos * fpos,unsigned wc)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 }
366 
err_chm_badname(const filepos * fpos,const char * sp)367 void err_chm_badname(const filepos *fpos, const char *sp)
368 {
369     do_error(fpos, "CHM internal file name `%s' begins with"
370              " a reserved character", sp);
371 }
372