X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/blobdiff_plain/39ed44f15f44726e08401b23b65dbbdc8ec5db8b..05e9c3c2e7be6c54e31121132f43db83597381e8:/error.c diff --git a/error.c b/error.c index 00d007d..8aa83b5 100644 --- a/error.c +++ b/error.c @@ -13,408 +13,353 @@ #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 c; - int i, j; - char *sp, *sp2; - wchar_t *wsp, *wsp2; - unsigned wc; - filepos fpos, fpos2, *fposp; - 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_cmdcharset: - sp = va_arg(ap, char *); - sprintf(error, "character set `%.200s' not recognised", sp); - flags = PREFIX; - break; - case err_futileopt: - sp = va_arg(ap, char *); - sp2 = va_arg(ap, char *); - sprintf(error, "warning: option `-%s' has no effect%s", sp, sp2); - 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 = utoa_locale_dup(wsp); - fpos = *va_arg(ap, filepos *); - sprintf(error, "command `%.200s' unrecognised at start of" - " paragraph", sp); - flags = FILEPOS; - sfree(sp); - break; - case err_badmidcmd: - wsp = va_arg(ap, wchar_t *); - sp = utoa_locale_dup(wsp); - fpos = *va_arg(ap, filepos *); - sprintf(error, "command `%.200s' unexpected in mid-paragraph", sp); - flags = FILEPOS; - sfree(sp); - 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_codequote: - fpos = *va_arg(ap, filepos *); - sprintf(error, "unable to nest \\q{...} within \\c{...} or \\cw{...}"); - flags = FILEPOS; - break; - case err_missingrbrace: - fpos = *va_arg(ap, filepos *); - sprintf(error, "unclosed braces at end of paragraph"); - flags = FILEPOS; - break; - case err_missingrbrace2: - fpos = *va_arg(ap, filepos *); - sprintf(error, "unclosed braces at end of input file"); - 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_indexcase: - fpos = *va_arg(ap, filepos *); - wsp = va_arg(ap, wchar_t *); - sp = utoa_locale_dup(wsp); - fpos2 = *va_arg(ap, filepos *); - wsp2 = va_arg(ap, wchar_t *); - sp2 = utoa_locale_dup(wsp2); - sprintf(error, "warning: index tag `%.200s' used with ", sp); - sprintf(error + strlen(error), "different case (`%.200s') at %s:%d", - sp2, fpos2.filename, fpos2.line); - flags = FILEPOS; - sfree(sp); - sfree(sp2); - break; - case err_nosuchkw: - fpos = *va_arg(ap, filepos *); - wsp = va_arg(ap, wchar_t *); - sp = utoa_locale_dup(wsp); - sprintf(error, "unable to resolve cross-reference to `%.200s'", sp); - flags = FILEPOS; - sfree(sp); - break; - case err_multiBR: - fpos = *va_arg(ap, filepos *); - wsp = va_arg(ap, wchar_t *); - sp = utoa_locale_dup(wsp); - sprintf(error, "multiple `\\BR' entries given for `%.200s'", sp); - flags = FILEPOS; - sfree(sp); - break; - case err_nosuchidxtag: - fpos = *va_arg(ap, filepos *); - wsp = va_arg(ap, wchar_t *); - sp = utoa_locale_dup(wsp); - sprintf(error, "`\\IM' on unknown index tag `%.200s'", sp); - sfree(sp); - flags = FILEPOS; - 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 = utoa_locale_dup(wsp); - sprintf(error, "macro `%.200s' already defined", sp); - flags = FILEPOS; - sfree(sp); - 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 = utoa_locale_dup(wsp); - sprintf(error, "paragraph keyword `%.200s' already defined at ", sp); - sprintf(error + strlen(error), "%s:%d", fpos2.filename, fpos2.line); - flags = FILEPOS; - sfree(sp); - break; - case err_misplacedlcont: - fpos = *va_arg(ap, filepos *); - sprintf(error, "\\lcont is only expected after a list item"); - flags = FILEPOS; - break; - case err_sectmarkerinblock: - fpos = *va_arg(ap, filepos *); - sp = va_arg(ap, char *); - sprintf(error, "section headings are not supported within \\%.100s", - sp); - flags = FILEPOS; - break; - case err_cfginsufarg: - fpos = *va_arg(ap, filepos *); - sp = va_arg(ap, char *); - i = va_arg(ap, int); - sprintf(error, "\\cfg{%s} expects at least %d parameter%s", sp, - i, (i==1)?"":"s"); - flags = FILEPOS; - break; - case err_infonodechar: - fposp = va_arg(ap, filepos *); - c = (char)va_arg(ap, int); - sprintf(error, "info output format does not support '%c' in" - " node names; removing", c); - if (fposp) { - flags = FILEPOS; - fpos = *fposp; - } - break; - case err_text_codeline: - fpos = *va_arg(ap, filepos *); - i = va_arg(ap, int); - j = va_arg(ap, int); - sprintf(error, "warning: code paragraph line is %d chars wide, wider" - " than body width %d", i, j); - flags = FILEPOS; - break; - case err_htmlver: - fpos = *va_arg(ap, filepos *); - wsp = va_arg(ap, wchar_t *); - sp = utoa_locale_dup(wsp); - sprintf(error, "unrecognised HTML version keyword `%.200s'", sp); - sfree(sp); - flags = FILEPOS; - break; - case err_charset: - fpos = *va_arg(ap, filepos *); - wsp = va_arg(ap, wchar_t *); - sp = utoa_locale_dup(wsp); - sprintf(error, "character set `%.200s' not recognised", sp); - flags = FILEPOS; - sfree(sp); - break; - case err_nofont: - fpos = *va_arg(ap, filepos *); - wsp = va_arg(ap, wchar_t *); - sp = utoa_locale_dup(wsp); - sprintf(error, "font `%.200s' not recognised", sp); - flags = FILEPOS; - sfree(sp); - break; - case err_afmeof: - fpos = *va_arg(ap, filepos *); - sprintf(error, "AFM file ended unexpectedly"); - flags = FILEPOS; - break; - case err_afmkey: - fpos = *va_arg(ap, filepos *); - sp = va_arg(ap, char *); - sprintf(error, "required AFM key '%.200s' missing", sp); - flags = FILEPOS; - break; - case err_afmvers: - fpos = *va_arg(ap, filepos *); - sprintf(error, "unsupported AFM version"); - flags = FILEPOS; - break; - case err_afmval: - fpos = *va_arg(ap, filepos *); - sp = va_arg(ap, char *); - i = va_arg(ap, int); - if (i == 1) - sprintf(error, "AFM key '%.200s' requires a value", sp); - else - sprintf(error, "AFM key '%.200s' requires %d values", sp, i); - flags = FILEPOS; - break; - case err_pfeof: - fpos = *va_arg(ap, filepos *); - sprintf(error, "Type 1 font file ended unexpectedly"); - flags = FILEPOS; - break; - case err_pfhead: - fpos = *va_arg(ap, filepos *); - sprintf(error, "Type 1 font file header line invalid"); - flags = FILEPOS; - break; - case err_pfbad: - fpos = *va_arg(ap, filepos *); - sprintf(error, "Type 1 font file invalid"); - flags = FILEPOS; - break; - case err_pfnoafm: - fpos = *va_arg(ap, filepos *); - sp = va_arg(ap, char *); - sprintf(error, "no metrics available for Type 1 font '%.200s'", sp); - flags = FILEPOS; - break; - case err_chmnames: - sprintf(error, "only one of html-mshtmlhelp-chm and " - "html-mshtmlhelp-hhp found"); - flags = PREFIX; - break; - case err_sfntnotable: - fpos = *va_arg(ap, filepos *); - sp = va_arg(ap, char *); - sprintf(error, "font has no '%.4s' table", sp); - flags = FILEPOS; - break; - case err_sfntnopsname: - fpos = *va_arg(ap, filepos *); - sprintf(error, "font has no PostScript name"); - flags = FILEPOS; - break; - case err_sfntbadtable: - fpos = *va_arg(ap, filepos *); - sp = va_arg(ap, char *); - sprintf(error, "font has an invalid '%.4s' table", sp); - flags = FILEPOS; - break; - case err_sfntnounicmap: - fpos = *va_arg(ap, filepos *); - sprintf(error, "font has no UCS-2 character map"); - flags = FILEPOS; - break; - case err_sfnttablevers: - fpos = *va_arg(ap, filepos *); - sp = va_arg(ap, char *); - sprintf(error, "font has an unsupported '%.4s' table version", sp); - flags = FILEPOS; - break; - case err_sfntbadhdr: - fpos = *va_arg(ap, filepos *); - sprintf(error, "font has an invalid header"); - flags = FILEPOS; - break; - case err_sfntbadglyph: - fpos = *va_arg(ap, filepos *); - wc = va_arg(ap, unsigned); - sprintf(error, - "warning: character U+%04X references an non-existent glyph", - wc); - flags = FILEPOS; - break; - case err_whatever: - sp = va_arg(ap, char *); - vsprintf(error, sp, ap); - flags = PREFIX; - break; - } +static void do_error(const filepos *fpos, const char *fmt, ...) +{ + va_list ap; - if (flags & PREFIX) - fputs("halibut: ", stderr); - if (flags & FILEPOS) { - fprintf(stderr, "%s:", fpos.filename ? fpos.filename : ""); - if (fpos.line > 0) - fprintf(stderr, "%d:", fpos.line); - if (fpos.col > 0) - fprintf(stderr, "%d:", fpos.col); + if (fpos) { + fprintf(stderr, "%s:", + fpos->filename ? fpos->filename : ""); + if (fpos->line > 0) + fprintf(stderr, "%d:", fpos->line); + if (fpos->col > 0) + fprintf(stderr, "%d:", fpos->col); fputc(' ', stderr); + } else { + fputs("halibut: ", stderr); } - fputs(error, stderr); + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputc('\n', stderr); } -void fatal(int code, ...) { - va_list ap; - va_start(ap, code); - do_error(code, ap); - va_end(ap); +void fatalerr_nomemory(void) +{ + do_error(NULL, "out of memory"); exit(EXIT_FAILURE); } -void error(int code, ...) { - va_list ap; - va_start(ap, code); - do_error(code, ap); - va_end(ap); +void err_optnoarg(const char *sp) +{ + do_error(NULL, "option `-%s' requires an argument", sp); +} + +void err_nosuchopt(const char *sp) +{ + do_error(NULL, "unrecognised option `-%s'", sp); +} + +void err_cmdcharset(const char *sp) +{ + do_error(NULL, "character set `%s' not recognised", sp); +} + +void err_futileopt(const char *sp, const char *sp2) +{ + do_error(NULL, "warning: option `-%s' has no effect%s", sp, sp2); +} + +void err_noinput(void) +{ + do_error(NULL, "no input files"); +} + +void err_cantopen(const char *sp) +{ + do_error(NULL, "unable to open input file `%s'", sp); +} + +void err_nodata(void) +{ + do_error(NULL, "no data in input files"); +} + +void err_brokencodepara(const filepos *fpos) +{ + do_error(fpos, "every line of a code paragraph should begin `\\c'"); +} + +void err_kwunclosed(const filepos *fpos) +{ + do_error(fpos, "expected `}' after paragraph keyword"); +} + +void err_kwexpected(const filepos *fpos) +{ + do_error(fpos, "expected a paragraph keyword"); +} + +void err_kwillegal(const filepos *fpos) +{ + do_error(fpos, "expected no paragraph keyword"); +} + +void err_kwtoomany(const filepos *fpos) +{ + do_error(fpos, "expected only one paragraph keyword"); +} + +void err_bodyillegal(const filepos *fpos) +{ + do_error(fpos, "expected no text after paragraph keyword"); +} + +void err_badparatype(const wchar_t *wsp, const filepos *fpos) +{ + char *sp = utoa_locale_dup(wsp); + do_error(fpos, "command `%s' unrecognised at start of paragraph", sp); + sfree(sp); +} + +void err_badmidcmd(const wchar_t *wsp, const filepos *fpos) +{ + char *sp = utoa_locale_dup(wsp); + do_error(fpos, "command `%s' unexpected in mid-paragraph", sp); + sfree(sp); +} + +void err_unexbrace(const filepos *fpos) +{ + do_error(fpos, "brace character unexpected in mid-paragraph"); +} + +void err_explbr(const filepos *fpos) +{ + do_error(fpos, "expected `{' after command"); +} + +void err_commenteof(const filepos *fpos) +{ + do_error(fpos, "end of file unexpected inside `\\#{...}' comment"); +} + +void err_kwexprbr(const filepos *fpos) +{ + do_error(fpos, "expected `}' after cross-reference"); +} + +void err_codequote(const filepos *fpos) +{ + do_error(fpos, "unable to nest \\q{...} within \\c{...} or \\cw{...}"); +} + +void err_missingrbrace(const filepos *fpos) +{ + do_error(fpos, "unclosed braces at end of paragraph"); +} + +void err_missingrbrace2(const filepos *fpos) +{ + do_error(fpos, "unclosed braces at end of input file"); +} + +void err_nestedstyles(const filepos *fpos) +{ + do_error(fpos, "unable to nest text styles"); +} + +void err_nestedindex(const filepos *fpos) +{ + do_error(fpos, "unable to nest index markings"); +} + +void err_indexcase(const filepos *fpos, const wchar_t *wsp, + const filepos *fpos2, const wchar_t *wsp2) +{ + char *sp = utoa_locale_dup(wsp), *sp2 = utoa_locale_dup(wsp2); + do_error(fpos, "warning: index tag `%s' used with different " + "case (`%s') at %s:%d", + sp, sp2, fpos2->filename, fpos2->line); + sfree(sp); + sfree(sp2); +} + +void err_nosuchkw(const filepos *fpos, const wchar_t *wsp) +{ + char *sp = utoa_locale_dup(wsp); + do_error(fpos, "unable to resolve cross-reference to `%s'", sp); + sfree(sp); +} + +void err_multiBR(const filepos *fpos, const wchar_t *wsp) +{ + char *sp = utoa_locale_dup(wsp); + do_error(fpos, "multiple `\\BR' entries given for `%s'", sp); + sfree(sp); +} + +void err_nosuchidxtag(const filepos *fpos, const wchar_t *wsp) +{ + char *sp = utoa_locale_dup(wsp); + do_error(fpos, "`\\IM' on unknown index tag `%s'", sp); + sfree(sp); +} + +void err_cantopenw(const char *sp) +{ + do_error(NULL, "unable to open output file `%s'", sp); +} + +void err_macroexists(const filepos *fpos, const wchar_t *wsp) +{ + char *sp = utoa_locale_dup(wsp); + do_error(fpos, "macro `%s' already defined", sp); + sfree(sp); +} + +void err_sectjump(const filepos *fpos) +{ + do_error(fpos, "expected higher heading levels before this one"); +} + +void err_winhelp_ctxclash(const filepos *fpos, const char *sp, const char *sp2) +{ + do_error(fpos, "Windows Help context id `%s' clashes with " + "previously defined `%s'", sp, sp2); +} + +void err_multikw(const filepos *fpos, const filepos *fpos2, const wchar_t *wsp) +{ + char *sp = utoa_locale_dup(wsp); + do_error(fpos, "paragraph keyword `%s' already defined at %s:%d", + sp, fpos2->filename, fpos2->line); + sfree(sp); +} + +void err_misplacedlcont(const filepos *fpos) +{ + do_error(fpos, "\\lcont is only expected after a list item"); +} + +void err_sectmarkerinblock(const filepos *fpos, const char *sp) +{ + do_error(fpos, "section headings are not supported within \\%s", sp); +} + +void err_cfginsufarg(const filepos *fpos, const char *sp, int i) +{ + do_error(fpos, "\\cfg{%s} expects at least %d parameter%s", + sp, i, (i==1)?"":"s"); +} + +void err_infonodechar(const filepos *fpos, char c) /* fpos might be NULL */ +{ + do_error(fpos, "info output format does not support '%c' in" + " node names; removing", c); +} + +void err_text_codeline(const filepos *fpos, int i, int j) +{ + do_error(fpos, "warning: code paragraph line is %d chars wide, wider" + " than body width %d", i, j); +} + +void err_htmlver(const filepos *fpos, const wchar_t *wsp) +{ + char *sp = utoa_locale_dup(wsp); + do_error(fpos, "unrecognised HTML version keyword `%s'", sp); + sfree(sp); +} + +void err_charset(const filepos *fpos, const wchar_t *wsp) +{ + char *sp = utoa_locale_dup(wsp); + do_error(fpos, "character set `%s' not recognised", sp); + sfree(sp); +} + +void err_nofont(const filepos *fpos, const wchar_t *wsp) +{ + char *sp = utoa_locale_dup(wsp); + do_error(fpos, "font `%s' not recognised", sp); + sfree(sp); +} + +void err_afmeof(const filepos *fpos) +{ + do_error(fpos, "AFM file ended unexpectedly"); +} + +void err_afmkey(const filepos *fpos, const char *sp) +{ + do_error(fpos, "required AFM key '%s' missing", sp); +} + +void err_afmvers(const filepos *fpos) +{ + do_error(fpos, "unsupported AFM version"); +} + +void err_afmval(const filepos *fpos, const char *sp, int i) +{ + if (i == 1) + do_error(fpos, "AFM key '%s' requires a value", sp); + else + do_error(fpos, "AFM key '%s' requires %d values", sp, i); +} + +void err_pfeof(const filepos *fpos) +{ + do_error(fpos, "Type 1 font file ended unexpectedly"); +} + +void err_pfhead(const filepos *fpos) +{ + do_error(fpos, "Type 1 font file header line invalid"); +} + +void err_pfbad(const filepos *fpos) +{ + do_error(fpos, "Type 1 font file invalid"); +} + +void err_pfnoafm(const filepos *fpos, const char *sp) +{ + do_error(fpos, "no metrics available for Type 1 font '%s'", sp); +} + +void err_chmnames(void) +{ + do_error(NULL, "only one of html-mshtmlhelp-chm and " + "html-mshtmlhelp-hhp found"); +} + +void err_sfntnotable(const filepos *fpos, const char *sp) +{ + do_error(fpos, "font has no '%s' table", sp); +} + +void err_sfntnopsname(const filepos *fpos) +{ + do_error(fpos, "font has no PostScript name"); +} + +void err_sfntbadtable(const filepos *fpos, const char *sp) +{ + do_error(fpos, "font has an invalid '%s' table", sp); +} + +void err_sfntnounicmap(const filepos *fpos) +{ + do_error(fpos, "font has no UCS-2 character map"); +} + +void err_sfnttablevers(const filepos *fpos, const char *sp) +{ + do_error(fpos, "font has an unsupported '%s' table version", sp); +} + +void err_sfntbadhdr(const filepos *fpos) +{ + do_error(fpos, "font has an invalid header"); +} + +void err_sfntbadglyph(const filepos *fpos, unsigned wc) +{ + do_error(fpos, + "warning: character U+%04X references a non-existent glyph", + wc); }