/* * error.c: Halibut error handling */ #include #include #include #include #include "halibut.h" /* * Error flags */ #define PREFIX 0x0001 /* give `halibut:' prefix */ #define FILEPOS 0x0002 /* give file position prefix */ static void do_error(int code, va_list ap) { char error[1024]; char auxbuf[256]; char *sp, *sp2; wchar_t *wsp; filepos fpos, fpos2; int flags=0; switch (code) { case err_nomemory: /* no arguments */ sprintf(error, "out of memory"); flags = PREFIX; break; case err_optnoarg: sp = va_arg(ap, char *); sprintf(error, "option `-%.200s' requires an argument", sp); flags = PREFIX; break; case err_nosuchopt: sp = va_arg(ap, char *); sprintf(error, "unrecognised option `-%.200s'", sp); flags = PREFIX; break; case err_noinput: /* no arguments */ sprintf(error, "no input files"); flags = PREFIX; break; case err_cantopen: sp = va_arg(ap, char *); sprintf(error, "unable to open input file `%.200s'", sp); flags = PREFIX; break; case err_nodata: /* no arguments */ sprintf(error, "no data in input files"); flags = PREFIX; break; case err_brokencodepara: fpos = *va_arg(ap, filepos *); sprintf(error, "every line of a code paragraph should begin `\\c'"); flags = FILEPOS; break; case err_kwunclosed: fpos = *va_arg(ap, filepos *); sprintf(error, "expected `}' after paragraph keyword"); flags = FILEPOS; break; case err_kwexpected: fpos = *va_arg(ap, filepos *); sprintf(error, "expected a paragraph keyword"); flags = FILEPOS; break; case err_kwillegal: fpos = *va_arg(ap, filepos *); sprintf(error, "expected no paragraph keyword"); flags = FILEPOS; break; case err_kwtoomany: fpos = *va_arg(ap, filepos *); sprintf(error, "expected only one paragraph keyword"); flags = FILEPOS; break; case err_bodyillegal: fpos = *va_arg(ap, filepos *); sprintf(error, "expected no text after paragraph keyword"); flags = FILEPOS; break; case err_badparatype: wsp = va_arg(ap, wchar_t *); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf)); fpos = *va_arg(ap, filepos *); sprintf(error, "command `%.200s' unrecognised at start of" " paragraph", sp); flags = FILEPOS; break; case err_badmidcmd: wsp = va_arg(ap, wchar_t *); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf)); fpos = *va_arg(ap, filepos *); sprintf(error, "command `%.200s' unexpected in mid-paragraph", sp); flags = FILEPOS; break; case err_unexbrace: fpos = *va_arg(ap, filepos *); sprintf(error, "brace character unexpected in mid-paragraph"); flags = FILEPOS; break; case err_explbr: fpos = *va_arg(ap, filepos *); sprintf(error, "expected `{' after command"); flags = FILEPOS; break; case err_commenteof: fpos = *va_arg(ap, filepos *); sprintf(error, "end of file unexpected inside `\\#{...}' comment"); flags = FILEPOS; break; case err_kwexprbr: fpos = *va_arg(ap, filepos *); sprintf(error, "expected `}' after cross-reference"); flags = FILEPOS; break; case err_missingrbrace: fpos = *va_arg(ap, filepos *); sprintf(error, "unclosed braces at end of paragraph"); flags = FILEPOS; break; case err_nestedstyles: fpos = *va_arg(ap, filepos *); sprintf(error, "unable to nest text styles"); flags = FILEPOS; break; case err_nestedindex: fpos = *va_arg(ap, filepos *); sprintf(error, "unable to nest index markings"); flags = FILEPOS; break; case err_nosuchkw: fpos = *va_arg(ap, filepos *); wsp = va_arg(ap, wchar_t *); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf)); sprintf(error, "unable to resolve cross-reference to `%.200s'", sp); flags = FILEPOS; break; case err_multiBR: fpos = *va_arg(ap, filepos *); wsp = va_arg(ap, wchar_t *); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf)); sprintf(error, "multiple `\\BR' entries given for `%.200s'", sp); flags = FILEPOS; break; case err_nosuchidxtag: wsp = va_arg(ap, wchar_t *); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf)); sprintf(error, "`\\IM' on unknown index tag `%.200s'", sp); flags = 0; /* FIXME: need to get a filepos to here somehow */ break; case err_cantopenw: sp = va_arg(ap, char *); sprintf(error, "unable to open output file `%.200s'", sp); flags = PREFIX; break; case err_macroexists: fpos = *va_arg(ap, filepos *); wsp = va_arg(ap, wchar_t *); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf)); sprintf(error, "macro `%.200s' already defined", sp); flags = FILEPOS; break; case err_sectjump: fpos = *va_arg(ap, filepos *); sprintf(error, "expected higher heading levels before this one"); flags = FILEPOS; break; case err_winhelp_ctxclash: fpos = *va_arg(ap, filepos *); sp = va_arg(ap, char *); sp2 = va_arg(ap, char *); sprintf(error, "Windows Help context id `%.200s' clashes with " "previously defined `%.200s'", sp, sp2); flags = FILEPOS; break; case err_multikw: fpos = *va_arg(ap, filepos *); fpos2 = *va_arg(ap, filepos *); wsp = va_arg(ap, wchar_t *); sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf)); sprintf(error, "paragraph keyword `%.200s' already defined at ", sp); sprintf(error + strlen(error), "%s:%d", fpos2.filename, fpos2.line); flags = FILEPOS; break; case err_whatever: sp = va_arg(ap, char *); vsprintf(error, sp, ap); flags = PREFIX; break; } if (flags & PREFIX) fputs("halibut: ", stderr); if (flags & FILEPOS) { fprintf(stderr, "%s:%d:", fpos.filename, fpos.line); if (fpos.col > 0) fprintf(stderr, "%d:", fpos.col); fputc(' ', stderr); } fputs(error, stderr); fputc('\n', stderr); } void fatal(int code, ...) { va_list ap; va_start(ap, code); do_error(code, ap); va_end(ap); exit(EXIT_FAILURE); } void error(int code, ...) { va_list ap; va_start(ap, code); do_error(code, ap); va_end(ap); }