Now that I've found the core AFMs, I notice that they have a perfectly
[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;
12f0ee84 242 case err_cfginsufarg:
d4c7e130 243 fpos = *va_arg(ap, filepos *);
12f0ee84 244 sp = va_arg(ap, char *);
245 i = va_arg(ap, int);
246 sprintf(error, "\\cfg{%s} expects at least %d parameter%s", sp,
247 i, (i==1)?"":"s");
d4c7e130 248 flags = FILEPOS;
249 break;
f4551933 250 case err_infonodechar:
251 fpos = *va_arg(ap, filepos *);
252 c = (char)va_arg(ap, int);
253 sprintf(error, "info output format does not support '%c' in"
254 " node names; removing", c);
255 flags = FILEPOS;
256 break;
db662ca1 257 case err_text_codeline:
258 fpos = *va_arg(ap, filepos *);
259 i = va_arg(ap, int);
260 j = va_arg(ap, int);
261 sprintf(error, "warning: code paragraph line is %d chars wide, wider"
262 " than body width %d", i, j);
263 flags = FILEPOS;
264 break;
27bdc5ab 265 case err_htmlver:
266 fpos = *va_arg(ap, filepos *);
267 wsp = va_arg(ap, wchar_t *);
268 sp = utoa_locale_dup(wsp);
269 sprintf(error, "unrecognised HTML version keyword `%.200s'", sp);
270 sfree(sp);
271 flags = FILEPOS;
272 break;
0960a3d8 273 case err_charset:
274 fpos = *va_arg(ap, filepos *);
275 wsp = va_arg(ap, wchar_t *);
276 sp = utoa_locale_dup(wsp);
277 sprintf(error, "character set `%.200s' not recognised", sp);
278 flags = FILEPOS;
279 sfree(sp);
280 break;
d7482997 281 case err_whatever:
282 sp = va_arg(ap, char *);
283 vsprintf(error, sp, ap);
284 flags = PREFIX;
285 break;
286 }
287
288 if (flags & PREFIX)
289 fputs("halibut: ", stderr);
290 if (flags & FILEPOS) {
6a0b9d08 291 fprintf(stderr, "%s:", fpos.filename);
292 if (fpos.line > 0)
293 fprintf(stderr, "%d:", fpos.line);
d7482997 294 if (fpos.col > 0)
295 fprintf(stderr, "%d:", fpos.col);
296 fputc(' ', stderr);
297 }
298 fputs(error, stderr);
299 fputc('\n', stderr);
300}
301
302void fatal(int code, ...) {
303 va_list ap;
304 va_start(ap, code);
305 do_error(code, ap);
306 va_end(ap);
307 exit(EXIT_FAILURE);
308}
309
310void error(int code, ...) {
311 va_list ap;
312 va_start(ap, code);
313 do_error(code, ap);
314 va_end(ap);
315}