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