1 /* error.c - error output and modification routines */
2 /* (c) in 2002-2017 by Volker Barthelmann and Frank Wille */
3
4 #include <stdarg.h>
5 #include "vasm.h"
6
7 struct err_out general_err_out[]={
8 #include "general_errors.h"
9 };
10 int general_errors=sizeof(general_err_out)/sizeof(general_err_out[0]);
11
12 struct err_out syntax_err_out[]={
13 #include "syntax_errors.h"
14 };
15 int syntax_errors=sizeof(syntax_err_out)/sizeof(syntax_err_out[0]);
16
17 struct err_out cpu_err_out[]={
18 #include "cpu_errors.h"
19 };
20 int cpu_errors=sizeof(cpu_err_out)/sizeof(cpu_err_out[0]);
21
22 struct err_out output_err_out[]={
23 #include "output_errors.h"
24 };
25 int output_errors=sizeof(output_err_out)/sizeof(output_err_out[0]);
26
27 int errors;
28 int max_errors=5;
29 int no_warn=0;
30
31
print_source_line(FILE * f)32 static void print_source_line(FILE *f)
33 {
34 static char *buf = NULL;
35 static size_t bufsz = 0;
36 char c,*e,*p,*q;
37 int l;
38
39 /* allocate a sufficiently dimensioned line buffer */
40 if (cur_src->bufsize > bufsz) {
41 bufsz = cur_src->bufsize;
42 buf = myrealloc(buf,bufsz);
43 }
44
45 p = cur_src->text;
46 q = buf;
47 e = buf + bufsz - 1;
48 l = cur_src->line;
49
50 do {
51 c = *p++;
52 if (c=='\n' || c=='\r') {
53 if (*p == ((c=='\n') ? '\r' : '\n'))
54 p++;
55 if (--l == 0) {
56 /* terminate error line in buffer and print it */
57 *q = '\0';
58 fprintf(f,">%s\n",buf);
59 return;
60 }
61 q = buf; /* next line, start to fill buffer from the beginning */
62 }
63 else if (q < e)
64 *q++ = c;
65 }
66 while (*p);
67 ierror(0); /* line doesn't exist */
68 }
69
70
error(int n,va_list vl,struct err_out * errlist,int offset)71 static void error(int n,va_list vl,struct err_out *errlist,int offset)
72 {
73 static source *last_err_source = NULL;
74 static int last_err_no;
75 static int last_err_line;
76 FILE *f;
77 int flags=errlist[n].flags;
78
79 if ((flags&DONTWARN) || ((flags&WARNING) && no_warn))
80 return;
81
82 if ((flags&MESSAGE) && !(flags&(WARNING|ERROR|FATAL))) {
83 f = stdout; /* print messages to stdout */
84 }
85 else {
86 f = stderr; /* otherwise stderr */
87
88 if (last_err_source) {
89 /* avoid printing the same error again and again, which might happen
90 when a line is evaluated in multiple passes */
91 if (cur_src!=NULL && cur_src==last_err_source &&
92 cur_src->line==last_err_line &&
93 n+offset==last_err_no)
94 return;
95 }
96 }
97
98 if (cur_src) {
99 last_err_source = cur_src;
100 last_err_line = cur_src->line;
101 last_err_no = n + offset;
102 }
103 fprintf(f,"\n");
104
105 if (cur_listing)
106 cur_listing->error = n + offset;
107
108 if (flags & FATAL)
109 fprintf(f,"fatal ");
110 if (flags & ERROR) {
111 ++errors;
112 fprintf(f,"error");
113 }
114 else if (flags & WARNING)
115 fprintf(f,"warning");
116 else if (flags & MESSAGE)
117 fprintf(f,"message");
118 fprintf(f," %d",n+offset);
119 if (!(flags & NOLINE) && cur_src!=NULL)
120 fprintf(f," in line %d of \"%s\"",cur_src->line,cur_src->name);
121 fprintf(f,": ");
122 vfprintf(f,errlist[n].text,vl);
123 fprintf(f,"\n");
124
125 if (!(flags & NOLINE) && cur_src!=NULL) {
126 if (cur_src->parent != NULL) {
127 source *parent,*child;
128 int recurs;
129
130 child = cur_src;
131 while (parent = child->parent) {
132 if (child->num_params >= 0)
133 fprintf(f,"\tcalled"); /* macro called from */
134 else
135 fprintf(f,"\tincluded"); /* included from */
136 fprintf(f," from line %d of \"%s\"",child->parent_line,parent->name);
137
138 recurs = 1;
139 while (parent->parent!=NULL &&
140 child->parent_line==parent->parent_line &&
141 !strcmp(parent->name,parent->parent->name)) {
142 recurs++;
143 parent = parent->parent;
144 }
145
146 if (recurs > 1)
147 fprintf(f," %d times",recurs);
148 fprintf(f,"\n");
149 child = parent;
150 }
151 }
152 print_source_line(f);
153 }
154
155 if (flags & FATAL) {
156 fprintf(f,"aborting...\n");
157 leave();
158 }
159 if ((flags & ERROR) && max_errors!=0 && errors>=max_errors) {
160 fprintf(f,"***maximum number of errors reached!***\n");
161 leave();
162 }
163 }
164
165
general_error(int n,...)166 void general_error(int n,...)
167 {
168 va_list vl;
169 va_start(vl,n);
170 error(n,vl,general_err_out,FIRST_GENERAL_ERROR);
171 }
172
173
syntax_error(int n,...)174 void syntax_error(int n,...)
175 {
176 va_list vl;
177 va_start(vl,n);
178 error(n,vl,syntax_err_out,FIRST_SYNTAX_ERROR);
179 }
180
181
cpu_error(int n,...)182 void cpu_error(int n,...)
183 {
184 va_list vl;
185 va_start(vl,n);
186 error(n,vl,cpu_err_out,FIRST_CPU_ERROR);
187 }
188
189
output_error(int n,...)190 void output_error(int n,...)
191 {
192 va_list vl;
193 va_start(vl,n);
194 error(n,vl,output_err_out,FIRST_OUTPUT_ERROR);
195 }
196
197
output_atom_error(int n,atom * a,...)198 void output_atom_error(int n,atom *a,...)
199 {
200 source *old = cur_src;
201 va_list vl;
202
203 va_start(vl,a);
204 /* temporarily set the source text and line from the given atom */
205 cur_src = a->src;
206 cur_src->line = a->line;
207 error(n,vl,output_err_out,FIRST_OUTPUT_ERROR);
208 cur_src = old;
209 }
210
211
modify_errors(struct err_out * err,int flags,va_list vl)212 static void modify_errors(struct err_out *err,int flags,va_list vl)
213 {
214 int n;
215
216 while (n = va_arg(vl,int)) {
217 err[n].flags = flags;
218 }
219 va_end(vl);
220 }
221
222
modify_gen_err(int flags,...)223 void modify_gen_err(int flags,...)
224 {
225 va_list vl;
226 va_start(vl,flags);
227 modify_errors(general_err_out,flags,vl);
228 }
229
230
modify_syntax_err(int flags,...)231 void modify_syntax_err(int flags,...)
232 {
233 va_list vl;
234 va_start(vl,flags);
235 modify_errors(syntax_err_out,flags,vl);
236 }
237
238
modify_cpu_err(int flags,...)239 void modify_cpu_err(int flags,...)
240 {
241 va_list vl;
242 va_start(vl,flags);
243 modify_errors(cpu_err_out,flags,vl);
244 }
245
246
dontwarn(struct err_out * err,int errnum,int first,int max)247 static void dontwarn(struct err_out *err,int errnum,int first,int max)
248 {
249 int n = errnum-first;
250
251 if (n>=0 && n<max) {
252 if (err[n].flags & WARNING) {
253 err[n].flags |= DONTWARN;
254 return;
255 }
256 }
257 general_error(33,errnum);
258 }
259
260
disable_warning(int n)261 void disable_warning(int n)
262 {
263 if (n >= FIRST_OUTPUT_ERROR)
264 dontwarn(output_err_out,n,FIRST_OUTPUT_ERROR,output_errors);
265 else if (n >= FIRST_CPU_ERROR)
266 dontwarn(cpu_err_out,n,FIRST_CPU_ERROR,cpu_errors);
267 else if (n >= FIRST_SYNTAX_ERROR)
268 dontwarn(syntax_err_out,n,FIRST_SYNTAX_ERROR,syntax_errors);
269 else if (n >= FIRST_GENERAL_ERROR)
270 dontwarn(general_err_out,n,FIRST_GENERAL_ERROR,general_errors);
271 }
272