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