Rewrite ustrftime(), so that (a) it uses wcsftime() where available,
[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;
d7482997 19 char *sp, *sp2;
20 wchar_t *wsp;
21 filepos fpos, fpos2;
22 int flags;
23
24 switch(code) {
25 case err_nomemory: /* no arguments */
26 sprintf(error, "out of memory");
27 flags = PREFIX;
28 break;
29 case err_optnoarg:
30 sp = va_arg(ap, char *);
31 sprintf(error, "option `-%.200s' requires an argument", sp);
32 flags = PREFIX;
33 break;
34 case err_nosuchopt:
35 sp = va_arg(ap, char *);
36 sprintf(error, "unrecognised option `-%.200s'", sp);
37 flags = PREFIX;
38 break;
39 case err_noinput: /* no arguments */
40 sprintf(error, "no input files");
41 flags = PREFIX;
42 break;
43 case err_cantopen:
44 sp = va_arg(ap, char *);
45 sprintf(error, "unable to open input file `%.200s'", sp);
46 flags = PREFIX;
47 break;
48 case err_nodata: /* no arguments */
49 sprintf(error, "no data in input files");
50 flags = PREFIX;
51 break;
52 case err_brokencodepara:
53 fpos = *va_arg(ap, filepos *);
54 sprintf(error, "every line of a code paragraph should begin `\\c'");
55 flags = FILEPOS;
56 break;
57 case err_kwunclosed:
58 fpos = *va_arg(ap, filepos *);
59 sprintf(error, "expected `}' after paragraph keyword");
60 flags = FILEPOS;
61 break;
62 case err_kwexpected:
63 fpos = *va_arg(ap, filepos *);
64 sprintf(error, "expected a paragraph keyword");
65 flags = FILEPOS;
66 break;
67 case err_kwillegal:
68 fpos = *va_arg(ap, filepos *);
69 sprintf(error, "expected no paragraph keyword");
70 flags = FILEPOS;
71 break;
72 case err_kwtoomany:
73 fpos = *va_arg(ap, filepos *);
74 sprintf(error, "expected only one paragraph keyword");
75 flags = FILEPOS;
76 break;
77 case err_bodyillegal:
78 fpos = *va_arg(ap, filepos *);
79 sprintf(error, "expected no text after paragraph keyword");
80 flags = FILEPOS;
81 break;
82 case err_badparatype:
83 wsp = va_arg(ap, wchar_t *);
7e976207 84 sp = utoa_locale_dup(wsp);
d7482997 85 fpos = *va_arg(ap, filepos *);
86 sprintf(error, "command `%.200s' unrecognised at start of"
87 " paragraph", sp);
88 flags = FILEPOS;
7e976207 89 sfree(sp);
d7482997 90 break;
91 case err_badmidcmd:
92 wsp = va_arg(ap, wchar_t *);
7e976207 93 sp = utoa_locale_dup(wsp);
d7482997 94 fpos = *va_arg(ap, filepos *);
95 sprintf(error, "command `%.200s' unexpected in mid-paragraph", sp);
96 flags = FILEPOS;
7e976207 97 sfree(sp);
d7482997 98 break;
99 case err_unexbrace:
100 fpos = *va_arg(ap, filepos *);
101 sprintf(error, "brace character unexpected in mid-paragraph");
102 flags = FILEPOS;
103 break;
104 case err_explbr:
105 fpos = *va_arg(ap, filepos *);
106 sprintf(error, "expected `{' after command");
107 flags = FILEPOS;
108 break;
109 case err_commenteof:
110 fpos = *va_arg(ap, filepos *);
111 sprintf(error, "end of file unexpected inside `\\#{...}' comment");
112 flags = FILEPOS;
113 break;
114 case err_kwexprbr:
115 fpos = *va_arg(ap, filepos *);
116 sprintf(error, "expected `}' after cross-reference");
117 flags = FILEPOS;
118 break;
119 case err_missingrbrace:
120 fpos = *va_arg(ap, filepos *);
121 sprintf(error, "unclosed braces at end of paragraph");
122 flags = FILEPOS;
123 break;
7136a6c7 124 case err_missingrbrace2:
125 fpos = *va_arg(ap, filepos *);
126 sprintf(error, "unclosed braces at end of input file");
127 flags = FILEPOS;
128 break;
d7482997 129 case err_nestedstyles:
130 fpos = *va_arg(ap, filepos *);
131 sprintf(error, "unable to nest text styles");
132 flags = FILEPOS;
133 break;
134 case err_nestedindex:
135 fpos = *va_arg(ap, filepos *);
136 sprintf(error, "unable to nest index markings");
137 flags = FILEPOS;
138 break;
139 case err_nosuchkw:
140 fpos = *va_arg(ap, filepos *);
141 wsp = va_arg(ap, wchar_t *);
7e976207 142 sp = utoa_locale_dup(wsp);
d7482997 143 sprintf(error, "unable to resolve cross-reference to `%.200s'", sp);
144 flags = FILEPOS;
7e976207 145 sfree(sp);
d7482997 146 break;
147 case err_multiBR:
148 fpos = *va_arg(ap, filepos *);
149 wsp = va_arg(ap, wchar_t *);
7e976207 150 sp = utoa_locale_dup(wsp);
d7482997 151 sprintf(error, "multiple `\\BR' entries given for `%.200s'", sp);
152 flags = FILEPOS;
7e976207 153 sfree(sp);
d7482997 154 break;
155 case err_nosuchidxtag:
7e976207 156 fpos = *va_arg(ap, filepos *);
d7482997 157 wsp = va_arg(ap, wchar_t *);
7e976207 158 sp = utoa_locale_dup(wsp);
d7482997 159 sprintf(error, "`\\IM' on unknown index tag `%.200s'", sp);
7e976207 160 sfree(sp);
161 flags = FILEPOS;
d7482997 162 break;
163 case err_cantopenw:
164 sp = va_arg(ap, char *);
165 sprintf(error, "unable to open output file `%.200s'", sp);
166 flags = PREFIX;
167 break;
168 case err_macroexists:
169 fpos = *va_arg(ap, filepos *);
170 wsp = va_arg(ap, wchar_t *);
7e976207 171 sp = utoa_locale_dup(wsp);
d7482997 172 sprintf(error, "macro `%.200s' already defined", sp);
173 flags = FILEPOS;
7e976207 174 sfree(sp);
d7482997 175 break;
176 case err_sectjump:
177 fpos = *va_arg(ap, filepos *);
178 sprintf(error, "expected higher heading levels before this one");
179 flags = FILEPOS;
180 break;
181 case err_winhelp_ctxclash:
182 fpos = *va_arg(ap, filepos *);
183 sp = va_arg(ap, char *);
184 sp2 = va_arg(ap, char *);
185 sprintf(error, "Windows Help context id `%.200s' clashes with "
186 "previously defined `%.200s'", sp, sp2);
187 flags = FILEPOS;
188 break;
189 case err_multikw:
190 fpos = *va_arg(ap, filepos *);
191 fpos2 = *va_arg(ap, filepos *);
192 wsp = va_arg(ap, wchar_t *);
7e976207 193 sp = utoa_locale_dup(wsp);
d7482997 194 sprintf(error, "paragraph keyword `%.200s' already defined at ", sp);
195 sprintf(error + strlen(error), "%s:%d", fpos2.filename, fpos2.line);
196 flags = FILEPOS;
7e976207 197 sfree(sp);
d7482997 198 break;
7136a6c7 199 case err_misplacedlcont:
200 fpos = *va_arg(ap, filepos *);
201 sprintf(error, "\\lcont is only expected after a list item");
202 flags = FILEPOS;
203 break;
2614b01d 204 case err_sectmarkerinblock:
7136a6c7 205 fpos = *va_arg(ap, filepos *);
2614b01d 206 sp = va_arg(ap, char *);
207 sprintf(error, "section headings are not supported within \\%.100s",
208 sp);
7136a6c7 209 flags = FILEPOS;
d4c7e130 210 break;
211 case err_infodirentry:
212 fpos = *va_arg(ap, filepos *);
213 sprintf(error, "\\cfg{info-dir-entry} expects at least three"
214 " parameters");
215 flags = FILEPOS;
216 break;
f4551933 217 case err_infonodechar:
218 fpos = *va_arg(ap, filepos *);
219 c = (char)va_arg(ap, int);
220 sprintf(error, "info output format does not support '%c' in"
221 " node names; removing", c);
222 flags = FILEPOS;
223 break;
d7482997 224 case err_whatever:
225 sp = va_arg(ap, char *);
226 vsprintf(error, sp, ap);
227 flags = PREFIX;
228 break;
229 }
230
231 if (flags & PREFIX)
232 fputs("halibut: ", stderr);
233 if (flags & FILEPOS) {
6a0b9d08 234 fprintf(stderr, "%s:", fpos.filename);
235 if (fpos.line > 0)
236 fprintf(stderr, "%d:", fpos.line);
d7482997 237 if (fpos.col > 0)
238 fprintf(stderr, "%d:", fpos.col);
239 fputc(' ', stderr);
240 }
241 fputs(error, stderr);
242 fputc('\n', stderr);
243}
244
245void fatal(int code, ...) {
246 va_list ap;
247 va_start(ap, code);
248 do_error(code, ap);
249 va_end(ap);
250 exit(EXIT_FAILURE);
251}
252
253void error(int code, ...) {
254 va_list ap;
255 va_start(ap, code);
256 do_error(code, ap);
257 va_end(ap);
258}