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