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 | |
16 | static 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 | |
300 | void 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 | |
308 | void error(int code, ...) { |
309 | va_list ap; |
310 | va_start(ap, code); |
311 | do_error(code, ap); |
312 | va_end(ap); |
313 | } |