| #include "c.h" |
| |
| static char rcsid[] = "$Id: error.c 355 2007-02-18 22:08:49Z drh $"; |
| |
| 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: |
| fprint(stderr, " `%s'", vtoa(tsym->type, tsym->u.c.v)); |
| break; |
| case SCON: { |
| int i, n; |
| if (ischar(tsym->type->type)) { |
| char *s = tsym->u.c.v.p; |
| n = tsym->type->size; |
| fprint(stderr, " \""); |
| for (i = 0; i < 20 && i < n && *s; s++, i++) |
| if (*s < ' ' || *s >= 0177) |
| fprint(stderr, "\\%o", *s); |
| else |
| fprint(stderr, "%c", *s); |
| } else { /* wchar_t string */ |
| unsigned int *s = tsym->u.c.v.p; |
| assert(tsym->type->type->size == widechar->size); |
| n = tsym->type->size/widechar->size; |
| fprint(stderr, " L\""); |
| for (i = 0; i < 20 && i < n && *s; s++, i++) |
| if (*s < ' ' || *s >= 0177) |
| fprint(stderr, "\\x%x", *s); |
| else |
| fprint(stderr, "%c", *s); |
| } |
| if (i < n) |
| fprint(stderr, " ..."); |
| else |
| fprint(stderr, "\""); |
| break; |
| } |
| 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); |
| } |