Introduce a configurable option to select the HTML flavour. Also
[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(int code, va_list ap) {
17 char error[1024];
18 char c;
19 int i, j;
20 char *sp, *sp2;
21 wchar_t *wsp, *wsp2;
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 *);
85 sp = utoa_locale_dup(wsp);
86 fpos = *va_arg(ap, filepos *);
87 sprintf(error, "command `%.200s' unrecognised at start of"
88 " paragraph", sp);
89 flags = FILEPOS;
90 sfree(sp);
91 break;
92 case err_badmidcmd:
93 wsp = va_arg(ap, wchar_t *);
94 sp = utoa_locale_dup(wsp);
95 fpos = *va_arg(ap, filepos *);
96 sprintf(error, "command `%.200s' unexpected in mid-paragraph", sp);
97 flags = FILEPOS;
98 sfree(sp);
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;
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;
125 case err_missingrbrace:
126 fpos = *va_arg(ap, filepos *);
127 sprintf(error, "unclosed braces at end of paragraph");
128 flags = FILEPOS;
129 break;
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;
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;
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;
159 case err_nosuchkw:
160 fpos = *va_arg(ap, filepos *);
161 wsp = va_arg(ap, wchar_t *);
162 sp = utoa_locale_dup(wsp);
163 sprintf(error, "unable to resolve cross-reference to `%.200s'", sp);
164 flags = FILEPOS;
165 sfree(sp);
166 break;
167 case err_multiBR:
168 fpos = *va_arg(ap, filepos *);
169 wsp = va_arg(ap, wchar_t *);
170 sp = utoa_locale_dup(wsp);
171 sprintf(error, "multiple `\\BR' entries given for `%.200s'", sp);
172 flags = FILEPOS;
173 sfree(sp);
174 break;
175 case err_nosuchidxtag:
176 fpos = *va_arg(ap, filepos *);
177 wsp = va_arg(ap, wchar_t *);
178 sp = utoa_locale_dup(wsp);
179 sprintf(error, "`\\IM' on unknown index tag `%.200s'", sp);
180 sfree(sp);
181 flags = FILEPOS;
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 *);
191 sp = utoa_locale_dup(wsp);
192 sprintf(error, "macro `%.200s' already defined", sp);
193 flags = FILEPOS;
194 sfree(sp);
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 *);
213 sp = utoa_locale_dup(wsp);
214 sprintf(error, "paragraph keyword `%.200s' already defined at ", sp);
215 sprintf(error + strlen(error), "%s:%d", fpos2.filename, fpos2.line);
216 flags = FILEPOS;
217 sfree(sp);
218 break;
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;
224 case err_sectmarkerinblock:
225 fpos = *va_arg(ap, filepos *);
226 sp = va_arg(ap, char *);
227 sprintf(error, "section headings are not supported within \\%.100s",
228 sp);
229 flags = FILEPOS;
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;
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;
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;
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;
260 case err_whatever:
261 sp = va_arg(ap, char *);
262 vsprintf(error, sp, ap);
263 flags = PREFIX;
264 break;
265 }
266
267 if (flags & PREFIX)
268 fputs("halibut: ", stderr);
269 if (flags & FILEPOS) {
270 fprintf(stderr, "%s:", fpos.filename);
271 if (fpos.line > 0)
272 fprintf(stderr, "%d:", fpos.line);
273 if (fpos.col > 0)
274 fprintf(stderr, "%d:", fpos.col);
275 fputc(' ', stderr);
276 }
277 fputs(error, stderr);
278 fputc('\n', stderr);
279 }
280
281 void fatal(int code, ...) {
282 va_list ap;
283 va_start(ap, code);
284 do_error(code, ap);
285 va_end(ap);
286 exit(EXIT_FAILURE);
287 }
288
289 void error(int code, ...) {
290 va_list ap;
291 va_start(ap, code);
292 do_error(code, ap);
293 va_end(ap);
294 }