Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom / 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 /* $Id: error.c,v 3.20 1995/08/17 16:34:29 ceriel Exp $ */
6 /*      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        */
7
8 #include        "lint.h"
9 #if __STDC__
10 #include        <stdarg.h>
11 #else
12 #include        <varargs.h>
13 #endif
14 #include        <system.h>
15 #ifndef LINT
16 #include        <em.h>
17 #else
18 #include        "l_em.h"
19 #endif  /* LINT */
20
21 #include        "nopp.h"
22 #include        "errout.h"
23 #include        "debug.h"
24
25 #include        "tokenname.h"
26 #include        "arith.h"
27 #include        "label.h"
28 #include        "expr.h"
29 #include        "def.h"
30 #include        "LLlex.h"
31
32 /*      This file contains the error-message and diagnostic
33         functions.  Beware, they are called with a variable number of
34         arguments!
35 */
36
37 /* error classes */
38 #define WARNING         1
39 #define ERROR           2
40 #define CRASH           3
41 #define FATAL           4
42
43 int err_occurred = 0;
44
45 extern char options[];
46 #ifdef  LINT
47 extern char loptions[];
48 #endif  /* LINT */
49
50 /*      There are three general error-message functions:
51                 lexerror()      lexical and pre-processor error messages
52                 error()         syntactic and semantic error messages
53                 expr_error()    errors in expressions
54         The difference lies in the place where the file name and line
55         number come from.
56         Lexical errors report from the global variables LineNumber and
57         FileName, expression errors get their information from the
58         expression, whereas other errors use the information in the token.
59 */
60
61 static _error();
62
63 #if __STDC__
64 /*VARARGS*/
65 error(char *fmt, ...)
66 {
67         va_list ap;
68
69         va_start(ap, fmt);
70         {
71                 _error(ERROR, dot.tk_file, dot.tk_line, fmt, ap);
72         }
73         va_end(ap);
74 }
75
76 /*VARARGS*/
77 expr_error(struct expr *expr, char *fmt, ...)
78 {
79         va_list ap;
80
81         va_start(ap, fmt);
82         {
83                 if (!(expr->ex_flags & EX_ERROR)) {
84                         /* to prevent proliferation */
85                         _error(ERROR, expr->ex_file, expr->ex_line, fmt, ap);
86                         expr->ex_flags |= EX_ERROR;
87                 }
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, dot.tk_file, dot.tk_line, fmt, ap);
100         }
101         va_end(ap);
102 }
103
104 /*VARARGS*/
105 expr_warning(struct expr *expr, char *fmt, ...)
106 {
107         va_list ap;
108
109         va_start(ap, fmt);
110         {
111                 if (!(expr->ex_flags & EX_ERROR)) {
112                         /* to prevent proliferation */
113                         _error(WARNING, expr->ex_file, expr->ex_line, fmt, ap);
114                 }
115         }
116         va_end(ap);
117 }
118
119 #ifdef  LINT
120
121 /*VARARGS*/
122 def_warning(struct def *def, char *fmt, ...)
123 {
124         va_list ap;
125
126         va_start(ap, fmt);
127         {
128                 _error(WARNING, def->df_file, def->df_line, fmt, ap);
129         }
130         va_end(ap);
131 }
132
133
134 /*VARARGS*/
135 hwarning(char *fmt, ...)
136 {
137         va_list ap;
138
139         va_start(ap, fmt);
140         {
141                 if (loptions['h'])
142                         _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
143         }
144         va_end(ap);
145 }
146
147 /*VARARGS*/
148 awarning(char *fmt, ...)
149 {
150         va_list ap;
151
152         va_start(ap, fmt);
153         {
154                 if (loptions['a'])
155                         _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
156         }
157         va_end(ap);
158 }
159
160 #endif  /* LINT */
161
162 /*VARARGS*/
163 lexerror(char *fmt, ...)
164 {
165         va_list ap;
166
167         va_start(ap, fmt);
168         {
169                 _error(ERROR, FileName, LineNumber, fmt, ap);
170         }
171         va_end(ap);
172 }
173
174 #ifndef NOPP
175 /*VARARGS*/
176 lexwarning(char *fmt, ...)
177 {
178         va_list ap;
179
180         va_start(ap, fmt);
181         {
182                 _error(WARNING, FileName, LineNumber, fmt, ap);
183         }
184         va_end(ap);
185 }
186 #endif  /* NOPP */
187
188 /*VARARGS*/
189 crash(char *fmt, ...)
190 {
191         va_list ap;
192
193         va_start(ap, fmt);
194         {
195                 _error(CRASH, FileName, LineNumber, fmt, ap);
196         }
197         va_end(ap);
198
199         C_close();
200 #ifdef  DEBUG
201         sys_stop(S_ABORT);
202 #else   /* DEBUG */
203         sys_stop(S_EXIT);
204 #endif  /* DEBUG */
205         /* NOTREACHED */
206 }
207
208 /*VARARGS*/
209 fatal(char *fmt, ...)
210 {
211         va_list ap;
212
213         va_start(ap, fmt);
214         {
215                 _error(FATAL, FileName, LineNumber, fmt, ap);
216         }
217         va_end(ap);
218
219         if (C_busy()) C_close();
220         sys_stop(S_EXIT);
221         /*NOTREACHED*/
222 }
223 #else
224 /*VARARGS*/
225 error(va_alist)                         /* fmt, args */
226         va_dcl
227 {
228         va_list ap;
229
230         va_start(ap);
231         {
232                 char *fmt = va_arg(ap, char *);
233                 _error(ERROR, dot.tk_file, dot.tk_line, fmt, ap);
234         }
235         va_end(ap);
236 }
237
238 /*VARARGS*/
239 expr_error(va_alist)                    /* expr, fmt, args */
240         va_dcl
241 {
242         va_list ap;
243
244         va_start(ap);
245         {
246                 register struct expr *expr = va_arg(ap, struct expr *);
247                 char *fmt = va_arg(ap, char *);
248
249                 if (!(expr->ex_flags & EX_ERROR)) {
250                         /* to prevent proliferation */
251                         _error(ERROR, expr->ex_file, expr->ex_line, fmt, ap);
252                         expr->ex_flags |= EX_ERROR;
253                 }
254         }
255         va_end(ap);
256 }
257
258 /*VARARGS*/
259 warning(va_alist)                       /* fmt, args */
260         va_dcl
261 {
262         va_list ap;
263
264         va_start(ap);
265         {
266                 char *fmt = va_arg(ap, char *);
267                 _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
268         }
269         va_end(ap);
270 }
271
272 /*VARARGS*/
273 expr_warning(va_alist)                  /* expr, fmt, args */
274         va_dcl
275 {
276         va_list ap;
277
278         va_start(ap);
279         {
280                 struct expr *expr = va_arg(ap, struct expr *);
281                 char *fmt = va_arg(ap, char *);
282
283                 if (!(expr->ex_flags & EX_ERROR)) {
284                         /* to prevent proliferation */
285                         _error(WARNING, expr->ex_file, expr->ex_line, fmt, ap);
286                 }
287         }
288         va_end(ap);
289 }
290
291 #ifdef  LINT
292
293 /*VARARGS*/
294 def_warning(va_alist)                   /* def, fmt, args */
295         va_dcl
296 {
297         va_list ap;
298
299         va_start(ap);
300         {
301                 register struct def *def = va_arg(ap, struct def *);
302                 char *fmt = va_arg(ap, char *);
303
304                 _error(WARNING, def->df_file, def->df_line, fmt, ap);
305         }
306         va_end(ap);
307 }
308
309
310 /*VARARGS*/
311 hwarning(va_alist)                      /* fmt, args */
312         va_dcl
313 {
314         va_list ap;
315
316         va_start(ap);
317         {
318                 char *fmt = va_arg(ap, char *);
319                 if (loptions['h'])
320                         _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
321         }
322         va_end(ap);
323 }
324
325 /*VARARGS*/
326 awarning(va_alist)                      /* fmt, args */
327         va_dcl
328 {
329         va_list ap;
330
331         va_start(ap);
332         {
333                 char *fmt = va_arg(ap, char *);
334                 if (loptions['a'])
335                         _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
336         }
337         va_end(ap);
338 }
339
340 #endif  /* LINT */
341
342 /*VARARGS*/
343 lexerror(va_alist)                      /* fmt, args */
344         va_dcl
345 {
346         va_list ap;
347
348         va_start(ap);
349         {
350                 char *fmt = va_arg(ap, char *);
351                 _error(ERROR, FileName, LineNumber, fmt, ap);
352         }
353         va_end(ap);
354 }
355
356 #ifndef NOPP
357 /*VARARGS*/
358 lexwarning(va_alist)                    /* fmt, args */
359         va_dcl
360 {
361         va_list ap;
362
363         va_start(ap);
364         {
365                 char *fmt = va_arg(ap, char *);
366                 _error(WARNING, FileName, LineNumber, fmt, ap);
367         }
368         va_end(ap);
369 }
370 #endif  /* NOPP */
371
372 /*VARARGS*/
373 crash(va_alist)                         /* fmt, args */
374         va_dcl
375 {
376         va_list ap;
377
378         va_start(ap);
379         {
380                 char *fmt = va_arg(ap, char *);
381                 _error(CRASH, FileName, LineNumber, fmt, ap);
382         }
383         va_end(ap);
384
385         C_close();
386 #ifdef  DEBUG
387         sys_stop(S_ABORT);
388 #else   /* DEBUG */
389         sys_stop(S_EXIT);
390 #endif  /* DEBUG */
391         /* NOTREACHED */
392 }
393
394 /*VARARGS*/
395 fatal(va_alist)                         /* fmt, args */
396         va_dcl
397 {
398         va_list ap;
399
400         va_start(ap);
401         {
402                 char *fmt = va_arg(ap, char *);
403                 _error(FATAL, FileName, LineNumber, fmt, ap);
404         }
405         va_end(ap);
406
407         if (C_busy()) C_close();
408         sys_stop(S_EXIT);
409         /*NOTREACHED*/
410 }
411 #endif
412
413 static
414 _error(class, fn, ln, fmt, ap)
415         int class;
416         char *fn;
417         unsigned int ln;
418         char *fmt;
419         va_list ap;
420 {
421         char *remark;
422
423         /* check visibility of message */
424         switch (class)  {
425         case WARNING:
426         case ERROR:
427                 if (token_nmb < tk_nmb_at_last_syn_err + ERR_SHADOW)
428                         /* warning or error message overshadowed */
429                         return;
430                 break;
431         }
432
433         /*      Since name and number are gathered from different places
434                 depending on the class, we first collect the relevant
435                 values and then decide what to print.
436         */
437         /* preliminaries */
438         switch (class)  {
439         case WARNING:
440                 if (options['w'])
441                         return;
442                 break;
443
444         case ERROR:
445         case CRASH:
446         case FATAL:
447                 if (C_busy())
448                         C_ms_err();
449                 err_occurred = 1;
450                 break;
451         }
452
453         /* the remark */
454         switch (class)  {       
455         case WARNING:
456 #ifndef LINT
457                 remark = "(warning)";
458 #else   /* LINT */
459                 remark = 0;
460 #endif  /* LINT */
461                 break;
462
463         case ERROR:
464                 remark = 0;
465                 break;
466
467         case CRASH:
468                 remark = "CRASH\007";
469                 break;
470
471         case FATAL:
472                 remark = "fatal error --";
473                 break;
474         default:
475                 /*NOTREACHED*/;
476         }
477         
478 #ifdef  LINT
479         if (    /* there is a file name */
480                 fn
481         &&      /* the file name is global */
482                 fn[0] == '/'
483         &&      /* it is not a .c file */
484                 strcmp(&fn[strlen(fn)-2], ".c") != 0
485         ) {
486                 /* we skip this message */
487                 return;
488         }
489 #endif  /* LINT */
490         
491         if (fn)
492                 fprint(ERROUT, "\"%s\", line %u: ", fn, ln);
493         if (remark)
494                 fprint(ERROUT, "%s ", remark);
495         doprnt(ERROUT, fmt, ap);                /* contents of error */
496         fprint(ERROUT, "\n");
497 }