Pristine Ack-5.5
[Ack-5.5.git] / lang / pc / comp / error.c
1 /* E R R O R   A N D   D I A G N O S T I C   R O U T I N E S */
2
3 /*      This file contains the (non-portable) error-message and diagnostic
4         giving functions.  Be aware that they are called with a variable
5         number of arguments!
6 */
7
8 #include        "debug.h"
9 #include        "errout.h"
10
11 #if __STDC__
12 #include        <stdarg.h>
13 #else
14 #include        <varargs.h>
15 #endif
16 #include        <em_arith.h>
17 #include        <em_label.h>
18 #include        <em_code.h>
19 #include        <system.h>
20
21 #include        "LLlex.h"
22 #include        "f_info.h"
23 #include        "input.h"
24 #include        "main.h"
25 #include        "node.h"
26
27 /* error classes */
28 #define ERROR           1
29 #define WARNING         2
30 #define LEXERROR        3
31 #define LEXWARNING      4
32 #define CRASH           5
33 #define FATAL           6
34 #ifdef DEBUG
35 #define VDEBUG          7
36 #endif
37
38 int err_occurred;
39
40 extern char *symbol2str();
41
42 /*      There are three general error-message functions:
43                 lexerror()      lexical and pre-processor error messages
44                 error()         syntactic and pre-processor messagese
45                 node_error()    errors in nodes
46         The difference lies in the place where the file name and line
47         number come from.
48         Lexical errors report from the global variables LineNumber and
49         FileName, node errors get their information from the
50         node, whereas other errors use the information in the token.
51 */
52
53 #if __STDC__
54 #ifdef DEBUG
55 /*VARARGS*/
56 debug(char *fmt, ...)
57 {
58         va_list ap;
59
60         va_start(ap, fmt);
61         {
62                 _error(VDEBUG, NULLNODE, fmt, ap);
63         }
64         va_end(ap);
65 }
66 #endif /* DEBUG */
67
68 /*VARARGS*/
69 error(char *fmt, ...)
70 {
71         va_list ap;
72
73         va_start(ap, fmt);
74         {
75                 _error(ERROR, NULLNODE, fmt, ap);
76         }
77         va_end(ap);
78 }
79
80 /*VARARGS*/
81 node_error(struct node *node, char *fmt, ...)
82 {
83         va_list ap;
84
85         va_start(ap, fmt);
86         {
87                 _error(ERROR, node, fmt, ap);
88         }
89         va_end(ap);
90 }
91
92 /*VARARGS*/
93 warning(char *fmt, ...)
94 {
95         va_list ap;
96
97         va_start(ap, fmt);
98         {
99                 _error(WARNING, NULLNODE, fmt, ap);
100         }
101         va_end(ap);
102 }
103
104 /*VARARGS*/
105 node_warning(struct node *node, char *fmt, ...)
106 {
107         va_list ap;
108
109         va_start(ap, fmt);
110         {
111                 _error(WARNING, node, fmt, ap);
112         }
113         va_end(ap);
114 }
115
116 /*VARARGS*/
117 lexerror(char *fmt, ...)
118 {
119         va_list ap;
120
121         va_start(ap, fmt);
122         {
123                 _error(LEXERROR, NULLNODE, fmt, ap);
124         }
125         va_end(ap);
126 }
127
128 /*VARARGS*/
129 lexwarning(char *fmt, ...)
130 {
131         va_list ap;
132
133         va_start(ap, fmt);
134         {
135                 _error(LEXWARNING, NULLNODE, fmt, ap);
136         }
137         va_end(ap);
138 }
139
140 /*VARARGS*/
141 fatal(char *fmt, ...)
142 {
143         va_list ap;
144
145         va_start(ap, fmt);
146         {
147                 _error(FATAL, NULLNODE, fmt, ap);
148         }
149         va_end(ap);
150         sys_stop(S_EXIT);
151 }
152
153 /*VARARGS*/
154 crash(char *fmt, ...)
155 {
156         va_list ap;
157
158         va_start(ap, fmt);
159         {
160                 _error(CRASH, NULLNODE, fmt, ap);
161         }
162         va_end(ap);
163 #ifdef DEBUG
164         sys_stop(S_ABORT);
165 #else
166         sys_stop(S_EXIT);
167 #endif
168 }
169 #else
170 #ifdef DEBUG
171 /*VARARGS*/
172 debug(va_alist)
173         va_dcl
174 {
175         va_list ap;
176
177         va_start(ap);
178         {
179                 char *fmt = va_arg(ap, char *);
180                 _error(VDEBUG, NULLNODE, fmt, ap);
181         }
182         va_end(ap);
183 }
184 #endif /* DEBUG */
185
186 /*VARARGS*/
187 error(va_alist)
188         va_dcl
189 {
190         va_list ap;
191
192         va_start(ap);
193         {
194                 char *fmt = va_arg(ap, char *);
195                 _error(ERROR, NULLNODE, fmt, ap);
196         }
197         va_end(ap);
198 }
199
200 /*VARARGS*/
201 node_error(va_alist)
202         va_dcl
203 {
204         va_list ap;
205
206         va_start(ap);
207         {
208                 struct node *node = va_arg(ap, struct node *);
209                 char *fmt = va_arg(ap, char *);
210                 _error(ERROR, node, fmt, ap);
211         }
212         va_end(ap);
213 }
214
215 /*VARARGS*/
216 warning(va_alist)
217         va_dcl
218 {
219         va_list ap;
220
221         va_start(ap);
222         {
223                 char *fmt = va_arg(ap, char *);
224                 _error(WARNING, NULLNODE, fmt, ap);
225         }
226         va_end(ap);
227 }
228
229 /*VARARGS*/
230 node_warning(va_alist)
231         va_dcl
232 {
233         va_list ap;
234
235         va_start(ap);
236         {
237                 char *fmt = va_arg(ap, char *);
238                 struct node *node = va_arg(ap, struct node *);
239                 _error(WARNING, node, fmt, ap);
240         }
241         va_end(ap);
242 }
243
244 /*VARARGS*/
245 lexerror(va_alist)
246         va_dcl
247 {
248         va_list ap;
249
250         va_start(ap);
251         {
252                 char *fmt = va_arg(ap, char *);
253                 _error(LEXERROR, NULLNODE, fmt, ap);
254         }
255         va_end(ap);
256 }
257
258 /*VARARGS*/
259 lexwarning(va_alist)
260         va_dcl
261 {
262         va_list ap;
263
264         va_start(ap);
265         {
266                 char *fmt = va_arg(ap, char *);
267                 _error(LEXWARNING, NULLNODE, fmt, ap);
268         }
269         va_end(ap);
270 }
271
272 /*VARARGS*/
273 fatal(va_alist)
274         va_dcl
275 {
276         va_list ap;
277
278         va_start(ap);
279         {
280                 char *fmt = va_arg(ap, char *);
281                 _error(FATAL, NULLNODE, fmt, ap);
282         }
283         va_end(ap);
284         sys_stop(S_EXIT);
285 }
286
287 /*VARARGS*/
288 crash(va_alist)
289         va_dcl
290 {
291         va_list ap;
292
293         va_start(ap);
294         {
295                 char *fmt = va_arg(ap, char *);
296                 _error(CRASH, NULLNODE, fmt, ap);
297         }
298         va_end(ap);
299 #ifdef DEBUG
300         sys_stop(S_ABORT);
301 #else
302         sys_stop(S_EXIT);
303 #endif
304 }
305 #endif
306
307 _error(class, node, fmt, ap)
308         int class;
309         struct node *node;
310         char *fmt;
311         register va_list ap;
312 {
313         /*      _error attempts to limit the number of error messages
314                 for a given line to MAXERR_LINE.
315         */
316         static unsigned int last_ln = 0;
317         unsigned int ln = 0;
318         static char * last_fn = 0;
319         static int e_seen = 0, w_seen = 0;
320         register char *remark = 0;
321
322         /*      Since name and number are gathered from different places
323                 depending on the class, we first collect the relevant
324                 values and then decide what to print.
325         */
326         /* preliminaries */
327         switch( class ) {
328                 case ERROR:
329                 case LEXERROR:
330                 case CRASH:
331                 case FATAL:
332                         if( C_busy() ) C_ms_err();
333                         err_occurred = 1;
334                         break;
335         }
336
337         /* the remark */
338         switch( class ) {
339                 case WARNING:
340                 case LEXWARNING:
341                         if (options['w']) return;
342                         remark = "(warning)";
343                         break;
344                 case CRASH:
345                         remark = "CRASH\007";
346                         break;
347                 case FATAL:
348                         remark = "fatal error --";
349                         break;
350 #ifdef DEBUG
351                 case VDEBUG:
352                         remark = "(debug)";
353                         break;
354 #endif /* DEBUG */
355         }
356
357         /* the place */
358         switch( class ) {
359                 case ERROR:
360                 case WARNING:
361                         ln = node ? node->nd_lineno : dot.tk_lineno;
362                         break;
363                 case LEXWARNING:
364                 case LEXERROR:
365                 case CRASH:
366                 case FATAL:
367 #ifdef DEBUG
368                 case VDEBUG:
369 #endif /* DEBUG */
370                         ln = LineNumber;
371                         break;
372         }
373
374 #ifdef DEBUG
375         if( class != VDEBUG )   {
376 #endif
377         if( FileName == last_fn && ln == last_ln )      {
378                 /* we've seen this place before */
379                 if( class != WARNING && class != LEXWARNING ) {
380                         e_seen++;
381                         if( e_seen == MAXERR_LINE ) fmt = "etc ...";
382                         else if( e_seen > MAXERR_LINE )
383                                 /* and too often, I'd say ! */
384                                 return;
385                 }
386                 else {
387                         w_seen++;
388                         if( w_seen == MAXERR_LINE ) fmt = "etc ...";
389                         else if( w_seen > MAXERR_LINE )
390                                 return;
391                 }
392         }
393         else    {
394                 /* brand new place */
395                 last_ln = ln;
396                 last_fn = FileName;
397                 e_seen = w_seen = 0;
398         }
399 #ifdef DEBUG
400         }
401 #endif /* DEBUG */
402
403         if( FileName ) fprint(ERROUT, "\"%s\", line %u: ", FileName, ln);
404
405         if( remark ) fprint(ERROUT, "%s ", remark);
406
407         doprnt(ERROUT, fmt, ap);                /* contents of error */
408         fprint(ERROUT, "\n");
409 }