Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / 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 1.11 1995/08/17 16:51:09 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        "debug.h"
22 #include        "lint.h"
23 #include        "nopp.h"
24 #include        "errout.h"
25
26 #include        "tokenname.h"
27 #include        <flt_arith.h>
28 #include        "arith.h"
29 #include        "label.h"
30 #include        "expr.h"
31 #include        "def.h"
32 #include        "LLlex.h"
33
34 /*      This file contains the error-message and diagnostic
35         functions.  Beware, they are called with a variable number of
36         arguments!
37 */
38
39 /* error classes */
40 #define STRICT          1
41 #define WARNING         2
42 #define ERROR           3
43 #define CRASH           4
44 #define FATAL           5
45 #define DO_DEBUG        6
46
47 int err_occurred = 0;
48
49 extern char options[];
50 #ifdef  LINT
51 extern char loptions[];
52 #endif  /* LINT */
53
54 /*      There are three general error-message functions:
55                 lexerror()      lexical and pre-processor error messages
56                 error()         syntactic and semantic error messages
57                 expr_error()    errors in expressions
58         The difference lies in the place where the file name and line
59         number come from.
60         Lexical errors report from the global variables LineNumber and
61         FileName, expression errors get their information from the
62         expression, whereas other errors use the information in the token.
63 */
64
65 static _error();
66
67 #if __STDC__
68 /*VARARGS*/
69 error(char *fmt, ...)
70 {
71         va_list ap;
72
73         va_start(ap, fmt);
74         {
75                 _error(ERROR, dot.tk_file, dot.tk_line, fmt, ap);
76         }
77         va_end(ap);
78 }
79
80 /*VARARGS*/
81 expr_error(struct expr *expr, char *fmt, ...)
82 {
83         va_list ap;
84
85         va_start(ap, fmt);
86         {
87                 if (!(expr->ex_flags & EX_ERROR)) {
88                         /* to prevent proliferation */
89                         _error(ERROR, expr->ex_file, expr->ex_line, fmt, ap);
90                         expr->ex_flags |= EX_ERROR;
91                 }
92         }
93         va_end(ap);
94 }
95
96 /*VARARGS*/
97 lexstrict(char *fmt, ...)
98 {
99         va_list ap;
100
101         va_start(ap, fmt);
102         {
103                 _error(STRICT, FileName, LineNumber, fmt, ap);
104         }
105         va_end(ap);
106 }
107
108 /*VARARGS*/
109 strict(char *fmt, ...)
110 {
111         va_list ap;
112
113         va_start(ap, fmt);
114         {
115                 _error(STRICT, dot.tk_file, dot.tk_line, fmt, ap);
116         }
117         va_end(ap);
118 }
119
120 /*VARARGS*/
121 expr_strict(struct expr *expr, char *fmt, ...)
122 {
123         va_list ap;
124
125         va_start(ap, fmt);
126         {
127                 if (!(expr->ex_flags & EX_ERROR)) {
128                         /* to prevent proliferation */
129                         _error(STRICT, expr->ex_file, expr->ex_line, fmt, ap);
130                 }
131         }
132         va_end(ap);
133 }
134
135 #ifdef DEBUG
136 /*VARARGS*/
137 debug(char *fmt, ...)
138 {
139         va_list ap;
140
141         va_start(ap, fmt);
142         {
143                 _error(DO_DEBUG, dot.tk_file, dot.tk_line, fmt, ap);
144         }
145         va_end(ap);
146 }
147 #endif /* DEBUG */
148
149 /*VARARGS*/
150 warning(char *fmt, ...)
151 {
152         va_list ap;
153
154         va_start(ap, fmt);
155         {
156                 _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
157         }
158         va_end(ap);
159 }
160
161 /*VARARGS*/
162 expr_warning(struct expr *expr, char *fmt, ...)
163 {
164         va_list ap;
165
166         va_start(ap, fmt);
167         {
168                 if (!(expr->ex_flags & EX_ERROR)) {
169                         /* to prevent proliferation */
170                         _error(WARNING, expr->ex_file, expr->ex_line, fmt, ap);
171                 }
172         }
173         va_end(ap);
174 }
175
176 #ifdef  LINT
177
178 /*VARARGS*/
179 def_warning(struct def *def, char *fmt, ...)
180 {
181         va_list ap;
182
183         va_start(ap, fmt);
184         {
185                 _error(WARNING, def->df_file, def->df_line, fmt, ap);
186         }
187         va_end(ap);
188 }
189
190
191 /*VARARGS*/
192 hwarning(char *fmt, ...)
193 {
194         va_list ap;
195
196         va_start(ap, fmt);
197         {
198                 if (loptions['h'])
199                         _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
200         }
201         va_end(ap);
202 }
203
204 /*VARARGS*/
205 awarning(char *fmt, ...)
206 {
207         va_list ap;
208
209         va_start(ap, fmt);
210         {
211                 if (loptions['a'])
212                         _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
213         }
214         va_end(ap);
215 }
216
217 #endif  /* LINT */
218
219 /*VARARGS*/
220 lexerror(char *fmt, ...)
221 {
222         va_list ap;
223
224         va_start(ap, fmt);
225         {
226                 _error(ERROR, FileName, LineNumber, fmt, ap);
227         }
228         va_end(ap);
229 }
230
231 /*VARARGS*/
232 lexwarning(char *fmt, ...)
233 {
234         va_list ap;
235
236         va_start(ap, fmt);
237         {
238                 _error(WARNING, FileName, LineNumber, fmt, ap);
239         }
240         va_end(ap);
241 }
242
243 /*VARARGS*/
244 crash(char *fmt, ...)
245 {
246         va_list ap;
247
248         va_start(ap, fmt);
249         {
250                 _error(CRASH, FileName, LineNumber, fmt, ap);
251         }
252         va_end(ap);
253
254         C_close();
255 #ifdef  DEBUG
256         sys_stop(S_ABORT);
257 #else   /* DEBUG */
258         sys_stop(S_EXIT);
259 #endif  /* DEBUG */
260         /* NOTREACHED */
261 }
262
263 /*VARARGS*/
264 fatal(char *fmt, ...)
265 {
266         va_list ap;
267
268         va_start(ap, fmt);
269         {
270                 _error(FATAL, FileName, LineNumber, fmt, ap);
271         }
272         va_end(ap);
273
274         if (C_busy()) C_close();
275         sys_stop(S_EXIT);
276         /*NOTREACHED*/
277 }
278 #else
279 /*VARARGS*/
280 error(va_alist)                         /* fmt, args */
281         va_dcl
282 {
283         va_list ap;
284
285         va_start(ap);
286         {
287                 char *fmt = va_arg(ap, char *);
288                 _error(ERROR, dot.tk_file, dot.tk_line, fmt, ap);
289         }
290         va_end(ap);
291 }
292
293 /*VARARGS*/
294 expr_error(va_alist)                    /* expr, fmt, args */
295         va_dcl
296 {
297         va_list ap;
298
299         va_start(ap);
300         {
301                 register struct expr *expr = va_arg(ap, struct expr *);
302                 char *fmt = va_arg(ap, char *);
303
304                 if (!(expr->ex_flags & EX_ERROR)) {
305                         /* to prevent proliferation */
306                         _error(ERROR, expr->ex_file, expr->ex_line, fmt, ap);
307                         expr->ex_flags |= EX_ERROR;
308                 }
309         }
310         va_end(ap);
311 }
312
313 /*VARARGS*/
314 lexstrict(va_alist)
315         va_dcl
316 {
317         va_list ap;
318
319         va_start(ap);
320         {
321                 char *fmt = va_arg(ap, char *);
322                 _error(STRICT, FileName, LineNumber, fmt, ap);
323         }
324         va_end(ap);
325 }
326
327 /*VARARGS*/
328 strict(va_alist)
329         va_dcl
330 {
331         va_list ap;
332
333         va_start(ap);
334         {
335                 char *fmt = va_arg(ap, char *);
336                 _error(STRICT, dot.tk_file, dot.tk_line, fmt, ap);
337         }
338         va_end(ap);
339 }
340
341 /*VARARGS*/
342 expr_strict(va_alist)                   /* expr, fmt, args */
343         va_dcl
344 {
345         va_list ap;
346
347         va_start(ap);
348         {
349                 struct expr *expr = va_arg(ap, struct expr *);
350                 char *fmt = va_arg(ap, char *);
351
352                 if (!(expr->ex_flags & EX_ERROR)) {
353                         /* to prevent proliferation */
354                         _error(STRICT, expr->ex_file, expr->ex_line, fmt, ap);
355                 }
356         }
357         va_end(ap);
358 }
359
360 #ifdef DEBUG
361 /*VARARGS*/
362 debug(va_alist)
363         va_dcl
364 {
365         va_list ap;
366
367         va_start(ap);
368         {
369                 char *fmt = va_arg(ap, char *);
370                 _error(DO_DEBUG, dot.tk_file, dot.tk_line, fmt, ap);
371         }
372         va_end(ap);
373 }
374 #endif /* DEBUG */
375
376 /*VARARGS*/
377 warning(va_alist)
378         va_dcl
379 {
380         va_list ap;
381
382         va_start(ap);
383         {
384                 char *fmt = va_arg(ap, char *);
385                 _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
386         }
387         va_end(ap);
388 }
389
390 /*VARARGS*/
391 expr_warning(va_alist)                  /* expr, fmt, args */
392         va_dcl
393 {
394         va_list ap;
395
396         va_start(ap);
397         {
398                 struct expr *expr = va_arg(ap, struct expr *);
399                 char *fmt = va_arg(ap, char *);
400
401                 if (!(expr->ex_flags & EX_ERROR)) {
402                         /* to prevent proliferation */
403                         _error(WARNING, expr->ex_file, expr->ex_line, fmt, ap);
404                 }
405         }
406         va_end(ap);
407 }
408
409 #ifdef  LINT
410
411 /*VARARGS*/
412 def_warning(va_alist)                   /* def, fmt, args */
413         va_dcl
414 {
415         va_list ap;
416
417         va_start(ap);
418         {
419                 register struct def *def = va_arg(ap, struct def *);
420                 char *fmt = va_arg(ap, char *);
421
422                 _error(WARNING, def->df_file, def->df_line, fmt, ap);
423         }
424         va_end(ap);
425 }
426
427
428 /*VARARGS*/
429 hwarning(va_alist)                      /* fmt, args */
430         va_dcl
431 {
432         va_list ap;
433
434         va_start(ap);
435         {
436                 char *fmt = va_arg(ap, char *);
437                 if (loptions['h'])
438                         _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
439         }
440         va_end(ap);
441 }
442
443 /*VARARGS*/
444 awarning(va_alist)                      /* fmt, args */
445         va_dcl
446 {
447         va_list ap;
448
449         va_start(ap);
450         {
451                 char *fmt = va_arg(ap, char *);
452                 if (loptions['a'])
453                         _error(WARNING, dot.tk_file, dot.tk_line, fmt, ap);
454         }
455         va_end(ap);
456 }
457
458 #endif  /* LINT */
459
460 /*VARARGS*/
461 lexerror(va_alist)                      /* fmt, args */
462         va_dcl
463 {
464         va_list ap;
465
466         va_start(ap);
467         {
468                 char *fmt = va_arg(ap, char *);
469                 _error(ERROR, FileName, LineNumber, fmt, ap);
470         }
471         va_end(ap);
472 }
473
474 /*VARARGS*/
475 lexwarning(va_alist)                    /* fmt, args */
476         va_dcl
477 {
478         va_list ap;
479
480         va_start(ap);
481         {
482                 char *fmt = va_arg(ap, char *);
483                 _error(WARNING, FileName, LineNumber, fmt, ap);
484         }
485         va_end(ap);
486 }
487
488 /*VARARGS*/
489 crash(va_alist)                         /* fmt, args */
490         va_dcl
491 {
492         va_list ap;
493
494         va_start(ap);
495         {
496                 char *fmt = va_arg(ap, char *);
497                 _error(CRASH, FileName, LineNumber, fmt, ap);
498         }
499         va_end(ap);
500
501         C_close();
502 #ifdef  DEBUG
503         sys_stop(S_ABORT);
504 #else   /* DEBUG */
505         sys_stop(S_EXIT);
506 #endif  /* DEBUG */
507         /* NOTREACHED */
508 }
509
510 /*VARARGS*/
511 fatal(va_alist)                         /* fmt, args */
512         va_dcl
513 {
514         va_list ap;
515
516         va_start(ap);
517         {
518                 char *fmt = va_arg(ap, char *);
519                 _error(FATAL, FileName, LineNumber, fmt, ap);
520         }
521         va_end(ap);
522
523         if (C_busy()) C_close();
524         sys_stop(S_EXIT);
525         /*NOTREACHED*/
526 }
527 #endif
528
529 static
530 _error(class, fn, ln, fmt, ap)
531         int class;
532         char *fn;
533         unsigned int ln;
534         char *fmt;
535         va_list ap;
536 {
537         char *remark;
538         
539         /* check visibility of message */
540         switch (class)  {
541         case WARNING:
542         case ERROR:
543         case STRICT:
544                 if (token_nmb < tk_nmb_at_last_syn_err + ERR_SHADOW)
545                         /* warning or error message overshadowed */
546                         return;
547                 break;
548         }
549
550         /*      Since name and number are gathered from different places
551                 depending on the class, we first collect the relevant
552                 values and then decide what to print.
553         */
554         /* preliminaries */
555         switch (class)  {
556         case WARNING:
557                 if (options['w'])
558                         return;
559                 break;
560
561         case STRICT:
562                 if (options['s'])
563                         return;
564                 break;
565
566         case ERROR:
567         case CRASH:
568         case FATAL:
569                 if (C_busy())
570                         C_ms_err();
571                 err_occurred = 1;
572                 break;
573         }
574
575         /* the remark */
576         switch (class)  {       
577         case STRICT:
578                 remark = "(strict)";
579                 break;
580         case WARNING:
581 #ifndef LINT
582                 remark = "(warning)";
583 #else   /* LINT */
584                 remark = 0;
585 #endif  /* LINT */
586                 break;
587
588         case ERROR:
589                 remark = 0;
590                 break;
591
592         case CRASH:
593                 remark = "CRASH\007";
594                 break;
595
596         case FATAL:
597                 remark = "fatal error --";
598                 break;
599 #ifdef DEBUG
600         case DO_DEBUG:
601                 remark = "(debug)";
602                 break;
603 #endif /* DEBUG */
604         default:
605                 /*NOTREACHED*/;
606         }
607         
608 #ifdef  LINT
609         if (    /* there is a file name */
610                 fn
611         &&      /* the file name is global */
612                 fn[0] == '/'
613         &&      /* it is not a .c file */
614                 strcmp(&fn[strlen(fn)-2], ".c") != 0
615         ) {
616                 /* we skip this message */
617                 return;
618         }
619 #endif  /* LINT */
620         
621         if (fn)
622                 fprint(ERROUT, "\"%s\", line %u: ", fn, ln);
623         if (remark)
624                 fprint(ERROUT, "%s ", remark);
625         doprnt(ERROUT, fmt, ap);                /* contents of error */
626         fprint(ERROUT, "\n");
627 }