-
Notifications
You must be signed in to change notification settings - Fork 8
/
error.c
149 lines (139 loc) · 3.79 KB
/
error.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* error.c: Copyright (C) 2011-2022 by Brian Raiter <[email protected]>
* License GPLv2+: GNU GPL version 2 or later.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "gen.h"
#include "error.h"
/* Persistent data needed to report and track errors.
*/
struct errhandler {
char const *file; /* a filename to prefix error messages with */
unsigned long lineno; /* a line number to accompany the filename */
int count; /* total number of errors seen */
enum errortype type; /* the most recent error */
};
/* There is only one error handler for the program.
*/
static struct errhandler err;
/* Sets the name of the file to report errors for.
*/
void seterrorfile(char const *file)
{
err.file = file;
err.lineno = 0;
err.type = errNone;
}
/* Sets the file's current line number.
*/
void seterrorline(unsigned long lineno)
{
err.lineno = lineno;
}
/* Increments the current line number.
*/
void nexterrorline(void)
{
++err.lineno;
}
/* Returns the current error count.
*/
int geterrormark(void)
{
return err.count;
}
/* Returns true if new errors have been recorded since the last
* retrieved count.
*/
int errorsincemark(int mark)
{
return err.count > mark;
}
/* Logs an error. The error is recorded in the error handler, and a
* formatted message is displayed to the user.
*/
void error(enum errortype type)
{
err.type = type;
if (type == errNone)
return;
++err.count;
if (err.file) {
if (err.lineno)
fprintf(stderr, "%s:%lu: ", err.file, err.lineno);
else
fprintf(stderr, "%s: ", err.file);
} else {
if (err.lineno)
fprintf(stderr, "line %lu: ", err.lineno);
else
fprintf(stderr, "error: ");
}
switch (type) {
case errSyntax:
fputs("preprocessor syntax error.", stderr);
break;
case errFileIO:
if (errno)
fputs(strerror(errno), stderr);
else
fputs("file I/O error.", stderr);
break;
case errIfsTooDeep:
fputs("too many nested #ifs.", stderr);
break;
case errDanglingElse:
fputs("#else not matched to any #if.", stderr);
break;
case errDanglingEnd:
fputs("#endif found without any #if.", stderr);
break;
case errOpenIf:
fputs("#if not closed.", stderr);
break;
case errElifWithIfdef:
fputs("#elif matched with #ifdef/#ifndef.", stderr);
break;
case errElifdefWithIf:
fputs("#elifdef/#elifndef matched with #if.", stderr);
break;
case errBadCharLiteral:
fputs("bad character literal.", stderr);
break;
case errOpenCharLiteral:
fputs("last character literal not closed.", stderr);
break;
case errOpenStringLiteral:
fputs("last string literal not closed.", stderr);
break;
case errOpenComment:
fputs("last comment not closed.", stderr);
break;
case errOpenParenthesis:
fputs("unmatched left parenthesis.", stderr);
break;
case errEmptyIf:
fputs("#if with no argument.", stderr);
break;
case errMissingOperand:
fputs("operator with missing expression.", stderr);
break;
case errZeroDiv:
fputs("division by zero in expression.", stderr);
break;
case errIfSyntax:
fputs("bad syntax in #if expression.", stderr);
break;
case errDefinedSyntax:
fputs("bad syntax in defined operator.", stderr);
break;
case errBrokenComment:
fputs("comment spans deleted line.", stderr);
break;
default:
fprintf(stderr, "unspecified error (%d).", type);
break;
}
fputc('\n', stderr);
}