#include "c.h"

static char rcsid[] = "$Id: error.nw,v 2.5 1997/05/05 18:19:01 drh Exp $";

static void printtoken(void);
int errcnt   = 0;
int errlimit = 20;
char kind[] = {
#define xx(a,b,c,d,e,f,g) f,
#define yy(a,b,c,d,e,f,g) f,
#include "token.h"
};
int wflag;              /* != 0 to suppress warning messages */

void test(int tok, char set[]) {
        if (t == tok)
                t = gettok();
        else {
                expect(tok);
                skipto(tok, set);
                if (t == tok)
                        t = gettok();
        }
}
void expect(int tok) {
        if (t == tok)
                t = gettok();
        else {
                error("syntax error; found");
                printtoken();
                fprint(stderr, " expecting `%k'\n", tok);
        }
}
void error(const char *fmt, ...) {
        va_list ap;

        if (errcnt++ >= errlimit) {
                errcnt = -1;
                error("too many errors\n");
                exit(1);
        }
        va_start(ap, fmt);
        if (firstfile != file && firstfile && *firstfile)
                fprint(stderr, "%s: ", firstfile);
        fprint(stderr, "%w: ", &src);
        vfprint(stderr, NULL, fmt, ap);
        va_end(ap);
}

void skipto(int tok, char set[]) {
        int n;
        char *s;

        assert(set);
        for (n = 0; t != EOI && t != tok; t = gettok()) {
                for (s = set; *s && kind[t] != *s; s++)
                        ;
                if (kind[t] == *s)
                        break;
                if (n++ == 0)
                        error("skipping");
                if (n <= 8)
                        printtoken();
                else if (n == 9)
                        fprint(stderr, " ...");
        }
        if (n > 8) {
                fprint(stderr, " up to");
                printtoken();
        }
        if (n > 0)
                fprint(stderr, "\n");
}
/* fatal - issue fatal error message and exit */
int fatal(const char *name, const char *fmt, int n) {
        print("\n");
        errcnt = -1;
        error("compiler error in %s--", name);
        fprint(stderr, fmt, n);
        exit(EXIT_FAILURE);
        return 0;
}

/* printtoken - print current token preceeded by a space */
static void printtoken(void) {
        switch (t) {
        case ID: fprint(stderr, " `%s'", token); break;
        case ICON:
                if (*token == '\'') {
                        char *s;
        case SCON:      fprint(stderr, " ");
                        for (s = token; *s && s - token < 20; s++)
                                if (*s < ' ' || *s >= 0177)
                                        fprint(stderr, "\\%o", *s);
                                else
                                        fprint(stderr, "%c", *s);
                        if (*s)
                                fprint(stderr, " ...");
                        else
                                fprint(stderr, "%c", *token);
                        break;
                } /* else fall thru */
        case FCON:
                fprint(stderr, " `%S'", token, (char*)cp - token);
                break;
        case '`': case '\'': fprint(stderr, " \"%k\"", t); break;
        default: fprint(stderr, " `%k'", t);
        }
}

/* warning - issue warning error message */
void warning(const char *fmt, ...) {
        va_list ap;

        va_start(ap, fmt);
        if (wflag == 0) {
                errcnt--;
                error("warning: ");
                vfprint(stderr, NULL, fmt, ap);
        }
        va_end(ap);
}
