Move contact details inside <address> to make validator.w3.org happy.
[sgt/halibut] / error.c
CommitLineData
d7482997 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
16static void do_error(int code, va_list ap) {
17 char error[1024];
f4551933 18 char c;
db662ca1 19 int i, j;
d7482997 20 char *sp, *sp2;
da090173 21 wchar_t *wsp, *wsp2;
d7482997 22 filepos fpos, fpos2;
23 int flags;
24
25 switch(code) {
26 case err_nomemory: /* no arguments */
27 sprintf(error, "out of memory");
28 flags = PREFIX;
29 break;
30 case err_optnoarg:
31 sp = va_arg(ap, char *);
32 sprintf(error, "option `-%.200s' requires an argument", sp);
33 flags = PREFIX;
34 break;
35 case err_nosuchopt:
36 sp = va_arg(ap, char *);
37 sprintf(error, "unrecognised option `-%.200s'", sp);
38 flags = PREFIX;
39 break;
675958c3 40 case err_cmdcharset:
41 sp = va_arg(ap, char *);
42 sprintf(error, "character set `%.200s' not recognised", sp);
43 flags = PREFIX;
44 break;
45 case err_futileopt:
46 sp = va_arg(ap, char *);
47 sp2 = va_arg(ap, char *);
48 sprintf(error, "warning: option `-%s' has no effect%s", sp, sp2);
49 flags = PREFIX;
50 break;
d7482997 51 case err_noinput: /* no arguments */
52 sprintf(error, "no input files");
53 flags = PREFIX;
54 break;
55 case err_cantopen:
56 sp = va_arg(ap, char *);
57 sprintf(error, "unable to open input file `%.200s'", sp);
58 flags = PREFIX;
59 break;
60 case err_nodata: /* no arguments */
61 sprintf(error, "no data in input files");
62 flags = PREFIX;
63 break;
64 case err_brokencodepara:
65 fpos = *va_arg(ap, filepos *);
66 sprintf(error, "every line of a code paragraph should begin `\\c'");
67 flags = FILEPOS;
68 break;
69 case err_kwunclosed:
70 fpos = *va_arg(ap, filepos *);
71 sprintf(error, "expected `}' after paragraph keyword");
72 flags = FILEPOS;
73 break;
74 case err_kwexpected:
75 fpos = *va_arg(ap, filepos *);
76 sprintf(error, "expected a paragraph keyword");
77 flags = FILEPOS;
78 break;
79 case err_kwillegal:
80 fpos = *va_arg(ap, filepos *);
81 sprintf(error, "expected no paragraph keyword");
82 flags = FILEPOS;
83 break;
84 case err_kwtoomany:
85 fpos = *va_arg(ap, filepos *);
86 sprintf(error, "expected only one paragraph keyword");
87 flags = FILEPOS;
88 break;
89 case err_bodyillegal:
90 fpos = *va_arg(ap, filepos *);
91 sprintf(error, "expected no text after paragraph keyword");
92 flags = FILEPOS;
93 break;
94 case err_badparatype:
95 wsp = va_arg(ap, wchar_t *);
7e976207 96 sp = utoa_locale_dup(wsp);
d7482997 97 fpos = *va_arg(ap, filepos *);
98 sprintf(error, "command `%.200s' unrecognised at start of"
99 " paragraph", sp);
100 flags = FILEPOS;
7e976207 101 sfree(sp);
d7482997 102 break;
103 case err_badmidcmd:
104 wsp = va_arg(ap, wchar_t *);
7e976207 105 sp = utoa_locale_dup(wsp);
d7482997 106 fpos = *va_arg(ap, filepos *);
107 sprintf(error, "command `%.200s' unexpected in mid-paragraph", sp);
108 flags = FILEPOS;
7e976207 109 sfree(sp);
d7482997 110 break;
111 case err_unexbrace:
112 fpos = *va_arg(ap, filepos *);
113 sprintf(error, "brace character unexpected in mid-paragraph");
114 flags = FILEPOS;
115 break;
116 case err_explbr:
117 fpos = *va_arg(ap, filepos *);
118 sprintf(error, "expected `{' after command");
119 flags = FILEPOS;
120 break;
121 case err_commenteof:
122 fpos = *va_arg(ap, filepos *);
123 sprintf(error, "end of file unexpected inside `\\#{...}' comment");
124 flags = FILEPOS;
125 break;
126 case err_kwexprbr:
127 fpos = *va_arg(ap, filepos *);
128 sprintf(error, "expected `}' after cross-reference");
129 flags = FILEPOS;
130 break;
6ff15f2b 131 case err_codequote:
132 fpos = *va_arg(ap, filepos *);
133 sprintf(error, "unable to nest \\q{...} within \\c{...} or \\cw{...}");
134 flags = FILEPOS;
135 break;
d7482997 136 case err_missingrbrace:
137 fpos = *va_arg(ap, filepos *);
138 sprintf(error, "unclosed braces at end of paragraph");
139 flags = FILEPOS;
140 break;
7136a6c7 141 case err_missingrbrace2:
142 fpos = *va_arg(ap, filepos *);
143 sprintf(error, "unclosed braces at end of input file");
144 flags = FILEPOS;
145 break;
d7482997 146 case err_nestedstyles:
147 fpos = *va_arg(ap, filepos *);
148 sprintf(error, "unable to nest text styles");
149 flags = FILEPOS;
150 break;
151 case err_nestedindex:
152 fpos = *va_arg(ap, filepos *);
153 sprintf(error, "unable to nest index markings");
154 flags = FILEPOS;
155 break;
da090173 156 case err_indexcase:
157 fpos = *va_arg(ap, filepos *);
158 wsp = va_arg(ap, wchar_t *);
159 sp = utoa_locale_dup(wsp);
160 fpos2 = *va_arg(ap, filepos *);
161 wsp2 = va_arg(ap, wchar_t *);
162 sp2 = utoa_locale_dup(wsp2);
163 sprintf(error, "warning: index tag `%.200s' used with ", sp);
164 sprintf(error + strlen(error), "different case (`%.200s') at %s:%d",
165 sp2, fpos2.filename, fpos2.line);
166 flags = FILEPOS;
167 sfree(sp);
168 sfree(sp2);
169 break;
d7482997 170 case err_nosuchkw:
171 fpos = *va_arg(ap, filepos *);
172 wsp = va_arg(ap, wchar_t *);
7e976207 173 sp = utoa_locale_dup(wsp);
d7482997 174 sprintf(error, "unable to resolve cross-reference to `%.200s'", sp);
175 flags = FILEPOS;
7e976207 176 sfree(sp);
d7482997 177 break;
178 case err_multiBR:
179 fpos = *va_arg(ap, filepos *);
180 wsp = va_arg(ap, wchar_t *);
7e976207 181 sp = utoa_locale_dup(wsp);
d7482997 182 sprintf(error, "multiple `\\BR' entries given for `%.200s'", sp);
183 flags = FILEPOS;
7e976207 184 sfree(sp);
d7482997 185 break;
186 case err_nosuchidxtag:
7e976207 187 fpos = *va_arg(ap, filepos *);
d7482997 188 wsp = va_arg(ap, wchar_t *);
7e976207 189 sp = utoa_locale_dup(wsp);
d7482997 190 sprintf(error, "`\\IM' on unknown index tag `%.200s'", sp);
7e976207 191 sfree(sp);
192 flags = FILEPOS;
d7482997 193 break;
194 case err_cantopenw:
195 sp = va_arg(ap, char *);
196 sprintf(error, "unable to open output file `%.200s'", sp);
197 flags = PREFIX;
198 break;
199 case err_macroexists:
200 fpos = *va_arg(ap, filepos *);
201 wsp = va_arg(ap, wchar_t *);
7e976207 202 sp = utoa_locale_dup(wsp);
d7482997 203 sprintf(error, "macro `%.200s' already defined", sp);
204 flags = FILEPOS;
7e976207 205 sfree(sp);
d7482997 206 break;
207 case err_sectjump:
208 fpos = *va_arg(ap, filepos *);
209 sprintf(error, "expected higher heading levels before this one");
210 flags = FILEPOS;
211 break;
212 case err_winhelp_ctxclash:
213 fpos = *va_arg(ap, filepos *);
214 sp = va_arg(ap, char *);
215 sp2 = va_arg(ap, char *);
216 sprintf(error, "Windows Help context id `%.200s' clashes with "
217 "previously defined `%.200s'", sp, sp2);
218 flags = FILEPOS;
219 break;
220 case err_multikw:
221 fpos = *va_arg(ap, filepos *);
222 fpos2 = *va_arg(ap, filepos *);
223 wsp = va_arg(ap, wchar_t *);
7e976207 224 sp = utoa_locale_dup(wsp);
d7482997 225 sprintf(error, "paragraph keyword `%.200s' already defined at ", sp);
226 sprintf(error + strlen(error), "%s:%d", fpos2.filename, fpos2.line);
227 flags = FILEPOS;
7e976207 228 sfree(sp);
d7482997 229 break;
7136a6c7 230 case err_misplacedlcont:
231 fpos = *va_arg(ap, filepos *);
232 sprintf(error, "\\lcont is only expected after a list item");
233 flags = FILEPOS;
234 break;
2614b01d 235 case err_sectmarkerinblock:
7136a6c7 236 fpos = *va_arg(ap, filepos *);
2614b01d 237 sp = va_arg(ap, char *);
238 sprintf(error, "section headings are not supported within \\%.100s",
239 sp);
7136a6c7 240 flags = FILEPOS;
d4c7e130 241 break;
242 case err_infodirentry:
243 fpos = *va_arg(ap, filepos *);
244 sprintf(error, "\\cfg{info-dir-entry} expects at least three"
245 " parameters");
246 flags = FILEPOS;
247 break;
f4551933 248 case err_infonodechar:
249 fpos = *va_arg(ap, filepos *);
250 c = (char)va_arg(ap, int);
251 sprintf(error, "info output format does not support '%c' in"
252 " node names; removing", c);
253 flags = FILEPOS;
254 break;
db662ca1 255 case err_text_codeline:
256 fpos = *va_arg(ap, filepos *);
257 i = va_arg(ap, int);
258 j = va_arg(ap, int);
259 sprintf(error, "warning: code paragraph line is %d chars wide, wider"
260 " than body width %d", i, j);
261 flags = FILEPOS;
262 break;
27bdc5ab 263 case err_htmlver:
264 fpos = *va_arg(ap, filepos *);
265 wsp = va_arg(ap, wchar_t *);
266 sp = utoa_locale_dup(wsp);
267 sprintf(error, "unrecognised HTML version keyword `%.200s'", sp);
268 sfree(sp);
269 flags = FILEPOS;
270 break;
0960a3d8 271 case err_charset:
272 fpos = *va_arg(ap, filepos *);
273 wsp = va_arg(ap, wchar_t *);
274 sp = utoa_locale_dup(wsp);
275 sprintf(error, "character set `%.200s' not recognised", sp);
276 flags = FILEPOS;
277 sfree(sp);
278 break;
d7482997 279 case err_whatever:
280 sp = va_arg(ap, char *);
281 vsprintf(error, sp, ap);
282 flags = PREFIX;
283 break;
284 }
285
286 if (flags & PREFIX)
287 fputs("halibut: ", stderr);
288 if (flags & FILEPOS) {
6a0b9d08 289 fprintf(stderr, "%s:", fpos.filename);
290 if (fpos.line > 0)
291 fprintf(stderr, "%d:", fpos.line);
d7482997 292 if (fpos.col > 0)
293 fprintf(stderr, "%d:", fpos.col);
294 fputc(' ', stderr);
295 }
296 fputs(error, stderr);
297 fputc('\n', stderr);
298}
299
300void fatal(int code, ...) {
301 va_list ap;
302 va_start(ap, code);
303 do_error(code, ap);
304 va_end(ap);
305 exit(EXIT_FAILURE);
306}
307
308void error(int code, ...) {
309 va_list ap;
310 va_start(ap, code);
311 do_error(code, ap);
312 va_end(ap);
313}