]>
Commit | Line | Data |
---|---|---|
1eee94d3 GM |
1 | (* mcError.mod provides an interface between the string handling modules. |
2 | ||
a945c346 | 3 | Copyright (C) 2015-2024 Free Software Foundation, Inc. |
1eee94d3 GM |
4 | Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. |
5 | ||
6 | This file is part of GNU Modula-2. | |
7 | ||
8 | GNU Modula-2 is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3, or (at your option) | |
11 | any later version. | |
12 | ||
13 | GNU Modula-2 is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GNU Modula-2; see the file COPYING3. If not see | |
20 | <http://www.gnu.org/licenses/>. *) | |
21 | ||
22 | IMPLEMENTATION MODULE mcError ; | |
23 | ||
24 | FROM ASCII IMPORT nul, nl ; | |
25 | FROM DynamicStrings IMPORT String, InitString, InitStringCharStar, ConCat, ConCatChar, Mark, string, KillString, Dup ; | |
26 | FROM FIO IMPORT StdOut, WriteNBytes, Close, FlushBuffer ; | |
27 | FROM StrLib IMPORT StrLen, StrEqual ; | |
28 | FROM FormatStrings IMPORT Sprintf0, Sprintf1, Sprintf2, Sprintf3 ; | |
29 | FROM Storage IMPORT ALLOCATE, DEALLOCATE ; | |
30 | FROM M2RTS IMPORT ExitOnHalt ; | |
31 | FROM SYSTEM IMPORT ADDRESS ; | |
32 | IMPORT StdIO ; | |
33 | ||
34 | FROM nameKey IMPORT Name, keyToCharStar ; | |
35 | FROM mcLexBuf IMPORT findFileNameFromToken, tokenToLineNo, tokenToColumnNo, getTokenNo ; | |
36 | FROM mcPrintf IMPORT printf0, printf1, printf2 ; | |
37 | ||
38 | ||
39 | CONST | |
40 | Debugging = TRUE ; | |
41 | DebugTrace = FALSE ; | |
42 | Xcode = TRUE ; | |
43 | ||
44 | TYPE | |
45 | error = POINTER TO RECORD | |
46 | parent, | |
47 | child, | |
48 | next : error ; | |
49 | fatal : BOOLEAN ; | |
50 | s : String ; | |
51 | token : CARDINAL ; (* index of token causing the error *) | |
52 | END ; | |
53 | ||
54 | VAR | |
55 | head : error ; | |
56 | inInternal: BOOLEAN ; | |
57 | ||
58 | ||
59 | (* | |
60 | cast - casts a := b | |
61 | *) | |
62 | ||
63 | PROCEDURE cast (VAR a: ARRAY OF BYTE; b: ARRAY OF BYTE) ; | |
64 | VAR | |
65 | i: CARDINAL ; | |
66 | BEGIN | |
67 | IF HIGH(a)=HIGH(b) | |
68 | THEN | |
69 | FOR i := 0 TO HIGH(a) DO | |
70 | a[i] := b[i] | |
71 | END | |
72 | END | |
73 | END cast ; | |
74 | ||
75 | ||
76 | (* | |
77 | translateNameToString - takes a format specification string, a, and | |
78 | if they consist of of %a then this is translated | |
79 | into a String and %a is replaced by %s. | |
80 | *) | |
81 | ||
82 | PROCEDURE translateNameToCharStar (VAR a: ARRAY OF CHAR; | |
83 | n: CARDINAL) : BOOLEAN ; | |
84 | VAR | |
85 | argno, | |
86 | i, h : CARDINAL ; | |
87 | BEGIN | |
88 | argno := 1 ; | |
89 | i := 0 ; | |
90 | h := StrLen (a) ; | |
91 | WHILE i<h DO | |
92 | IF (a[i]='%') AND (i+1<h) | |
93 | THEN | |
94 | IF (a[i+1]='a') AND (argno=n) | |
95 | THEN | |
96 | a[i+1] := 's' ; | |
97 | RETURN TRUE | |
98 | END ; | |
99 | INC (argno) ; | |
100 | IF argno>n | |
101 | THEN | |
102 | (* all done *) | |
103 | RETURN FALSE | |
104 | END | |
105 | END ; | |
106 | INC (i) | |
107 | END ; | |
108 | RETURN FALSE | |
109 | END translateNameToCharStar ; | |
110 | ||
111 | ||
112 | (* | |
113 | outString - writes the contents of String to stdout. | |
114 | The string, s, is destroyed. | |
115 | *) | |
116 | ||
117 | PROCEDURE outString (file: String; line, col: CARDINAL; s: String) ; | |
118 | VAR | |
119 | leader : String ; | |
120 | p, q : POINTER TO CHAR ; | |
121 | space, | |
122 | newline: BOOLEAN ; | |
123 | BEGIN | |
124 | INC (col) ; | |
125 | IF Xcode | |
126 | THEN | |
127 | leader := Sprintf2(Mark(InitString('%s:%d:')), file, line) | |
128 | ELSE | |
129 | leader := Sprintf3(Mark(InitString('%s:%d:%d:')), file, line, col) | |
130 | END ; | |
131 | p := string(s) ; | |
132 | newline := TRUE ; | |
133 | space := FALSE ; | |
134 | WHILE (p#NIL) AND (p^#nul) DO | |
135 | IF newline | |
136 | THEN | |
137 | q := string (leader) ; | |
138 | WHILE (q#NIL) AND (q^#nul) DO | |
139 | StdIO.Write (q^) ; | |
140 | INC (q) | |
141 | END | |
142 | END ; | |
143 | newline := (p^=nl) ; | |
144 | space := (p^=' ') ; | |
145 | IF newline AND Xcode | |
146 | THEN | |
147 | printf1 ('(pos: %d)', col) | |
148 | END ; | |
149 | StdIO.Write (p^) ; | |
150 | INC (p) | |
151 | END ; | |
152 | IF NOT newline | |
153 | THEN | |
154 | IF Xcode | |
155 | THEN | |
156 | IF NOT space | |
157 | THEN | |
158 | StdIO.Write (' ') | |
159 | END ; | |
160 | printf1 ('(pos: %d)', col) | |
161 | END ; | |
162 | StdIO.Write (nl) | |
163 | END ; | |
164 | FlushBuffer (StdOut) ; | |
165 | IF NOT Debugging | |
166 | THEN | |
167 | s := KillString (s) ; | |
168 | leader := KillString (leader) | |
169 | END | |
170 | END outString ; | |
171 | ||
172 | ||
173 | (* | |
174 | internalError - displays an internal error message together with the compiler source | |
175 | file and line number. | |
176 | This function is not buffered and is used when the compiler is about | |
177 | to give up. | |
178 | *) | |
179 | ||
180 | PROCEDURE internalError (a: ARRAY OF CHAR; file: ARRAY OF CHAR; line: CARDINAL) ; | |
181 | BEGIN | |
182 | ExitOnHalt (1) ; | |
183 | IF NOT inInternal | |
184 | THEN | |
185 | inInternal := TRUE ; | |
186 | flushErrors ; | |
187 | outString (findFileNameFromToken (getTokenNo (), 0), | |
188 | tokenToLineNo (getTokenNo (), 0), | |
189 | tokenToColumnNo (getTokenNo (), 0), | |
190 | Mark(InitString ('*** fatal error ***'))) | |
191 | END ; | |
192 | outString (Mark (InitString (file)), line, 0, | |
193 | ConCat (Mark (InitString('*** internal error *** ')), Mark (InitString (a)))) ; | |
194 | HALT | |
195 | END internalError ; | |
196 | ||
197 | ||
198 | (* *************************************************************************** | |
199 | The following routines are used for normal syntax and semantic error reporting | |
200 | *************************************************************************** *) | |
201 | ||
202 | ||
203 | (* | |
204 | writeFormat0 - displays the source module and line together | |
205 | with the encapsulated format string. | |
206 | Used for simple error messages tied to the current token. | |
207 | *) | |
208 | ||
209 | PROCEDURE writeFormat0 (a: ARRAY OF CHAR) ; | |
210 | VAR | |
211 | e: error ; | |
212 | BEGIN | |
213 | e := newError (getTokenNo ()) ; | |
214 | WITH e^ DO | |
215 | s := Sprintf0 (Mark (InitString(a))) | |
216 | END | |
217 | END writeFormat0 ; | |
218 | ||
219 | ||
220 | (* | |
221 | WarnFormat0 - displays the source module and line together | |
222 | with the encapsulated format string. | |
223 | Used for simple warning messages tied to the current token. | |
224 | *) | |
225 | ||
226 | PROCEDURE warnFormat0 (a: ARRAY OF CHAR) ; | |
227 | VAR | |
228 | e: error ; | |
229 | BEGIN | |
230 | e := newWarning (getTokenNo()) ; | |
231 | WITH e^ DO | |
232 | s := Sprintf0 (Mark (InitString (a))) | |
233 | END | |
234 | END warnFormat0 ; | |
235 | ||
236 | ||
237 | (* | |
238 | DoFormat1 - | |
239 | *) | |
240 | ||
241 | PROCEDURE doFormat1 (a: ARRAY OF CHAR; w: ARRAY OF BYTE) : String ; | |
242 | VAR | |
243 | s: String ; | |
244 | n: Name ; | |
245 | BEGIN | |
246 | IF translateNameToCharStar(a, 1) | |
247 | THEN | |
248 | cast(n, w) ; | |
249 | s := Mark (InitStringCharStar (keyToCharStar (n))) ; | |
250 | s := Sprintf1 (Mark (InitString (a)), s) | |
251 | ELSE | |
252 | s := Sprintf1 (Mark (InitString (a)), w) | |
253 | END ; | |
254 | RETURN s | |
255 | END doFormat1 ; | |
256 | ||
257 | ||
258 | (* | |
259 | writeFormat1 - displays the source module and line together | |
260 | with the encapsulated format string. | |
261 | Used for simple error messages tied to the current token. | |
262 | *) | |
263 | ||
264 | PROCEDURE writeFormat1 (a: ARRAY OF CHAR; w: ARRAY OF BYTE) ; | |
265 | VAR | |
266 | e: error ; | |
267 | BEGIN | |
268 | e := newError (getTokenNo ()) ; | |
269 | e^.s := doFormat1 (a, w) | |
270 | END writeFormat1 ; | |
271 | ||
272 | ||
273 | (* | |
274 | warnFormat1 - displays the source module and line together | |
275 | with the encapsulated format string. | |
276 | Used for simple warning messages tied to the current token. | |
277 | *) | |
278 | ||
279 | PROCEDURE warnFormat1 (a: ARRAY OF CHAR; w: ARRAY OF BYTE) ; | |
280 | VAR | |
281 | e: error ; | |
282 | BEGIN | |
283 | e := newWarning (getTokenNo ()) ; | |
284 | e^.s := doFormat1 (a, w) | |
285 | END warnFormat1 ; | |
286 | ||
287 | ||
288 | (* | |
289 | doFormat2 - | |
290 | *) | |
291 | ||
292 | PROCEDURE doFormat2 (a: ARRAY OF CHAR; w1, w2: ARRAY OF BYTE) : String ; | |
293 | VAR | |
294 | n : Name ; | |
295 | s, | |
296 | s1, s2: String ; | |
297 | b : BITSET ; | |
298 | BEGIN | |
299 | b := {} ; | |
300 | IF translateNameToCharStar (a, 1) | |
301 | THEN | |
302 | cast (n, w1) ; | |
303 | s1 := Mark (InitStringCharStar (keyToCharStar (n))) ; | |
304 | INCL (b, 1) | |
305 | END ; | |
306 | IF translateNameToCharStar(a, 2) | |
307 | THEN | |
308 | cast (n, w2) ; | |
309 | s2 := Mark (InitStringCharStar (keyToCharStar(n))) ; | |
310 | INCL (b, 2) | |
311 | END ; | |
312 | CASE b OF | |
313 | ||
314 | {} : s := Sprintf2 (Mark (InitString (a)), w1, w2) | | |
315 | {1} : s := Sprintf2 (Mark (InitString (a)), s1, w2) | | |
316 | {2} : s := Sprintf2 (Mark (InitString (a)), w1, s2) | | |
317 | {1,2}: s := Sprintf2 (Mark (InitString (a)), s1, s2) | |
318 | ||
319 | ELSE | |
320 | HALT | |
321 | END ; | |
322 | RETURN s | |
323 | END doFormat2 ; | |
324 | ||
325 | ||
326 | (* | |
327 | writeFormat2 - displays the module and line together with the encapsulated | |
328 | format strings. | |
329 | Used for simple error messages tied to the current token. | |
330 | *) | |
331 | ||
332 | PROCEDURE writeFormat2 (a: ARRAY OF CHAR; w1, w2: ARRAY OF BYTE) ; | |
333 | VAR | |
334 | e: error ; | |
335 | BEGIN | |
336 | e := newError (getTokenNo()) ; | |
337 | e^.s := doFormat2 (a, w1, w2) | |
338 | END writeFormat2 ; | |
339 | ||
340 | ||
341 | PROCEDURE doFormat3 (a: ARRAY OF CHAR; w1, w2, w3: ARRAY OF BYTE) : String ; | |
342 | VAR | |
343 | n : Name ; | |
344 | s, s1, s2, s3: String ; | |
345 | b : BITSET ; | |
346 | BEGIN | |
347 | b := {} ; | |
348 | IF translateNameToCharStar (a, 1) | |
349 | THEN | |
350 | cast (n, w1) ; | |
351 | s1 := Mark (InitStringCharStar (keyToCharStar (n))) ; | |
352 | INCL(b, 1) | |
353 | END ; | |
354 | IF translateNameToCharStar (a, 2) | |
355 | THEN | |
356 | cast (n, w2) ; | |
357 | s2 := Mark (InitStringCharStar (keyToCharStar (n))) ; | |
358 | INCL (b, 2) | |
359 | END ; | |
360 | IF translateNameToCharStar (a, 3) | |
361 | THEN | |
362 | cast(n, w3) ; | |
363 | s3 := Mark (InitStringCharStar (keyToCharStar (n))) ; | |
364 | INCL (b, 3) | |
365 | END ; | |
366 | CASE b OF | |
367 | ||
368 | {} : s := Sprintf3 (Mark (InitString (a)), w1, w2, w3) | | |
369 | {1} : s := Sprintf3 (Mark (InitString (a)), s1, w2, w3) | | |
370 | {2} : s := Sprintf3 (Mark (InitString (a)), w1, s2, w3) | | |
371 | {1,2} : s := Sprintf3 (Mark (InitString (a)), s1, s2, w3) | | |
372 | {3} : s := Sprintf3 (Mark (InitString (a)), w1, w2, s3) | | |
373 | {1,3} : s := Sprintf3 (Mark (InitString (a)), s1, w2, s3) | | |
374 | {2,3} : s := Sprintf3 (Mark (InitString (a)), w1, s2, s3) | | |
375 | {1,2,3}: s := Sprintf3 (Mark (InitString (a)), s1, s2, s3) | |
376 | ||
377 | ELSE | |
378 | HALT | |
379 | END ; | |
380 | RETURN s | |
381 | END doFormat3 ; | |
382 | ||
383 | ||
384 | (* | |
385 | writeFormat3 - displays the module and line together with the encapsulated | |
386 | format strings. | |
387 | Used for simple error messages tied to the current token. | |
388 | *) | |
389 | ||
390 | PROCEDURE writeFormat3 (a: ARRAY OF CHAR; w1, w2, w3: ARRAY OF BYTE) ; | |
391 | VAR | |
392 | e: error ; | |
393 | BEGIN | |
394 | e := newError (getTokenNo ()) ; | |
395 | e^.s := doFormat3 (a, w1, w2, w3) | |
396 | END writeFormat3 ; | |
397 | ||
398 | ||
399 | (* | |
400 | newError - creates and returns a new error handle. | |
401 | *) | |
402 | ||
403 | PROCEDURE newError (atTokenNo: CARDINAL) : error ; | |
404 | VAR | |
405 | e, f: error ; | |
406 | BEGIN | |
407 | NEW (e) ; | |
408 | WITH e^ DO | |
409 | s := NIL ; | |
410 | token := atTokenNo ; | |
411 | next := NIL ; | |
412 | parent := NIL ; | |
413 | child := NIL ; | |
414 | fatal := TRUE | |
415 | END ; | |
416 | IF (head=NIL) OR (head^.token>atTokenNo) | |
417 | THEN | |
418 | e^.next := head ; | |
419 | head := e | |
420 | ELSE | |
421 | f := head ; | |
422 | WHILE (f^.next#NIL) AND (f^.next^.token<atTokenNo) DO | |
423 | f := f^.next | |
424 | END ; | |
425 | e^.next := f^.next ; | |
426 | f^.next := e | |
427 | END ; | |
428 | RETURN e | |
429 | END newError ; | |
430 | ||
431 | ||
432 | (* | |
433 | newWarning - creates and returns a new error handle suitable for a warning. | |
434 | A warning will not stop compilation. | |
435 | *) | |
436 | ||
437 | PROCEDURE newWarning (atTokenNo: CARDINAL) : error ; | |
438 | VAR | |
439 | e: error ; | |
440 | BEGIN | |
441 | e := newError (atTokenNo) ; | |
442 | e^.fatal := FALSE ; | |
443 | RETURN e | |
444 | END newWarning ; | |
445 | ||
446 | ||
447 | (* | |
448 | chainError - creates and returns a new error handle, this new error | |
449 | is associated with, e, and is chained onto the end of, e. | |
450 | If, e, is NIL then the result to NewError is returned. | |
451 | *) | |
452 | ||
453 | PROCEDURE chainError (atTokenNo: CARDINAL; e: error) : error ; | |
454 | VAR | |
455 | f: error ; | |
456 | BEGIN | |
457 | IF e=NIL | |
458 | THEN | |
459 | RETURN newError (atTokenNo) | |
460 | ELSE | |
461 | NEW (f) ; | |
462 | WITH f^ DO | |
463 | s := NIL ; | |
464 | token := atTokenNo ; | |
465 | next := e^.child ; | |
466 | parent := e ; | |
467 | child := NIL ; | |
468 | fatal := e^.fatal | |
469 | END ; | |
470 | e^.child := f | |
471 | END ; | |
472 | RETURN f | |
473 | END chainError ; | |
474 | ||
475 | ||
476 | (* | |
477 | errorFormat routines provide a printf capability for the error handle. | |
478 | *) | |
479 | ||
480 | PROCEDURE errorFormat0 (e: error; a: ARRAY OF CHAR) ; | |
481 | BEGIN | |
482 | WITH e^ DO | |
483 | IF s=NIL | |
484 | THEN | |
485 | s := Sprintf0 (Mark (InitString (a))) | |
486 | ELSE | |
487 | s := ConCat(s, Mark(Sprintf0 (Mark (InitString (a))))) | |
488 | END | |
489 | END | |
490 | END errorFormat0 ; | |
491 | ||
492 | ||
493 | PROCEDURE errorFormat1 (e: error; a: ARRAY OF CHAR; w: ARRAY OF BYTE) ; | |
494 | VAR | |
495 | s1: String ; | |
496 | BEGIN | |
497 | s1 := doFormat1 (a, w) ; | |
498 | WITH e^ DO | |
499 | IF s=NIL | |
500 | THEN | |
501 | s := s1 | |
502 | ELSE | |
503 | s := ConCat (s, Mark (s1)) | |
504 | END | |
505 | END | |
506 | END errorFormat1 ; | |
507 | ||
508 | ||
509 | PROCEDURE errorFormat2 (e: error; a: ARRAY OF CHAR; w1, w2: ARRAY OF BYTE) ; | |
510 | VAR | |
511 | s1: String ; | |
512 | BEGIN | |
513 | s1 := doFormat2 (a, w1, w2) ; | |
514 | WITH e^ DO | |
515 | IF s=NIL | |
516 | THEN | |
517 | s := s1 | |
518 | ELSE | |
519 | s := ConCat (s, Mark (s1)) | |
520 | END | |
521 | END | |
522 | END errorFormat2 ; | |
523 | ||
524 | ||
525 | PROCEDURE errorFormat3 (e: error; a: ARRAY OF CHAR; | |
526 | w1, w2, w3: ARRAY OF BYTE) ; | |
527 | VAR | |
528 | s1: String ; | |
529 | BEGIN | |
530 | s1 := doFormat3 (a, w1, w2, w3) ; | |
531 | WITH e^ DO | |
532 | IF s=NIL | |
533 | THEN | |
534 | s := s1 | |
535 | ELSE | |
536 | s := ConCat (s, Mark (s1)) | |
537 | END | |
538 | END | |
539 | END errorFormat3 ; | |
540 | ||
541 | ||
542 | PROCEDURE errorString (e: error; str: String) ; | |
543 | BEGIN | |
544 | WITH e^ DO | |
545 | s := str | |
546 | END | |
547 | END errorString ; | |
548 | ||
549 | ||
550 | (* | |
551 | init - initializes the error list. | |
552 | *) | |
553 | ||
554 | PROCEDURE init ; | |
555 | BEGIN | |
556 | head := NIL ; | |
557 | inInternal := FALSE | |
558 | END init ; | |
559 | ||
560 | ||
561 | (* | |
562 | checkIncludes - generates a sequence of error messages which determine the relevant | |
563 | included file and line number. | |
564 | For example: | |
565 | ||
566 | gcc a.c | |
567 | In file included from b.h:1, | |
568 | from a.c:1: | |
569 | c.h:1: parse error before `and' | |
570 | ||
571 | where a.c is: #include "b.h" | |
572 | b.h is: #include "c.h" | |
573 | c.h is: and this and that | |
574 | ||
575 | we attempt to follow the error messages that gcc issues. | |
576 | *) | |
577 | ||
578 | PROCEDURE checkIncludes (token: CARDINAL; depth: CARDINAL) ; | |
579 | VAR | |
580 | included: String ; | |
581 | lineno : CARDINAL ; | |
582 | BEGIN | |
583 | included := findFileNameFromToken (token, depth+1) ; | |
584 | IF included#NIL | |
585 | THEN | |
586 | lineno := tokenToLineNo (token, depth+1) ; | |
587 | IF depth=0 | |
588 | THEN | |
589 | printf2('In file included from %s:%d', included, lineno) | |
590 | ELSE | |
591 | printf2(' from %s:%d', included, lineno) | |
592 | END ; | |
593 | IF findFileNameFromToken (token, depth+2)=NIL | |
594 | THEN | |
595 | printf0(':\n') | |
596 | ELSE | |
597 | printf0(',\n') | |
598 | END ; | |
599 | checkIncludes (token, depth+1) | |
600 | END | |
601 | END checkIncludes ; | |
602 | ||
603 | ||
604 | (* | |
605 | flushAll - flushes all errors in list, e. | |
606 | *) | |
607 | ||
608 | PROCEDURE flushAll (e: error; FatalStatus: BOOLEAN) : BOOLEAN ; | |
609 | VAR | |
610 | f : error ; | |
611 | written: BOOLEAN ; | |
612 | BEGIN | |
613 | written := FALSE ; | |
614 | IF e#NIL | |
615 | THEN | |
616 | REPEAT | |
617 | WITH e^ DO | |
618 | IF (FatalStatus=fatal) AND (s#NIL) | |
619 | THEN | |
620 | checkIncludes (token, 0) ; | |
621 | IF fatal | |
622 | THEN | |
623 | s := ConCat (InitString (' error: '), Mark (s)) | |
624 | ELSE | |
625 | s := ConCat (InitString(' warning: '), Mark (s)) | |
626 | END ; | |
627 | outString (findFileNameFromToken (token, 0), | |
628 | tokenToLineNo (token, 0), tokenToColumnNo (token, 0), s) ; | |
629 | IF (child#NIL) AND flushAll (child, FatalStatus) | |
630 | THEN | |
631 | END ; | |
632 | s := NIL ; | |
633 | written := TRUE | |
634 | END | |
635 | END ; | |
636 | f := e ; | |
637 | e := e^.next ; | |
638 | IF NOT Debugging | |
639 | THEN | |
640 | WITH f^ DO | |
641 | s := KillString(s) | |
642 | END ; | |
643 | DISPOSE (f) | |
644 | END ; | |
645 | UNTIL e=NIL | |
646 | END ; | |
647 | RETURN written | |
648 | END flushAll ; | |
649 | ||
650 | ||
651 | (* | |
652 | flushErrors - switches the output channel to the error channel | |
653 | and then writes out all errors. | |
654 | *) | |
655 | ||
656 | PROCEDURE flushErrors ; | |
657 | BEGIN | |
658 | IF DebugTrace | |
659 | THEN | |
660 | printf0 ('\nFlushing all errors\n') ; | |
661 | printf0 ('===================\n') | |
662 | END ; | |
663 | IF flushAll (head, TRUE) | |
664 | THEN | |
665 | ExitOnHalt (1) ; | |
666 | HALT | |
667 | END | |
668 | END flushErrors ; | |
669 | ||
670 | ||
671 | (* | |
672 | flushWarnings - switches the output channel to the error channel | |
673 | and then writes out all warnings. | |
674 | If an error is present the compilation is terminated, | |
675 | if warnings only were emitted then compilation will | |
676 | continue. | |
677 | *) | |
678 | ||
679 | PROCEDURE flushWarnings ; | |
680 | BEGIN | |
681 | IF flushAll (head, FALSE) | |
682 | THEN | |
683 | END | |
684 | END flushWarnings ; | |
685 | ||
686 | ||
687 | (* | |
688 | errorStringsAt2 - given error strings, s1, and, s2, it places these | |
689 | strings at token positions, tok1 and tok2, respectively. | |
690 | Both strings are consumed. | |
691 | *) | |
692 | ||
693 | PROCEDURE errorStringsAt2 (s1, s2: String; tok1, tok2: CARDINAL) ; | |
694 | VAR | |
695 | e: error ; | |
696 | BEGIN | |
697 | IF s1=s2 | |
698 | THEN | |
699 | s2 := Dup (s1) | |
700 | END ; | |
701 | e := newError (tok1) ; | |
702 | errorString (e, s1) ; | |
703 | errorString (chainError (tok2, e), s2) | |
704 | END errorStringsAt2 ; | |
705 | ||
706 | ||
707 | (* | |
708 | errorStringAt2 - given an error string, s, it places this | |
709 | string at token positions, tok1 and tok2, respectively. | |
710 | The string is consumed. | |
711 | *) | |
712 | ||
713 | PROCEDURE errorStringAt2 (s: String; tok1, tok2: CARDINAL) ; | |
714 | BEGIN | |
715 | errorStringsAt2 (s, s, tok1, tok2) | |
716 | END errorStringAt2 ; | |
717 | ||
718 | ||
719 | (* | |
720 | errorStringAt - given an error string, s, it places this | |
721 | string at token position, tok. | |
722 | The string is consumed. | |
723 | *) | |
724 | ||
725 | PROCEDURE errorStringAt (s: String; tok: CARDINAL) ; | |
726 | VAR | |
727 | e: error ; | |
728 | BEGIN | |
729 | e := newError (tok) ; | |
730 | errorString (e, s) | |
731 | END errorStringAt ; | |
732 | ||
733 | ||
734 | (* | |
735 | warnStringsAt2 - given warning strings, s1, and, s2, it places these | |
736 | strings at token positions, tok1 and tok2, respectively. | |
737 | Both strings are consumed. | |
738 | *) | |
739 | ||
740 | PROCEDURE warnStringsAt2 (s1, s2: String; tok1, tok2: CARDINAL) ; | |
741 | VAR | |
742 | e: error ; | |
743 | BEGIN | |
744 | IF s1=s2 | |
745 | THEN | |
746 | s2 := Dup (s1) | |
747 | END ; | |
748 | e := newWarning (tok1) ; | |
749 | errorString (e, s1) ; | |
750 | errorString (chainError (tok2, e), s2) | |
751 | END warnStringsAt2 ; | |
752 | ||
753 | ||
754 | (* | |
755 | warnStringAt2 - given an warning string, s, it places this | |
756 | string at token positions, tok1 and tok2, respectively. | |
757 | The string is consumed. | |
758 | *) | |
759 | ||
760 | PROCEDURE warnStringAt2 (s: String; tok1, tok2: CARDINAL) ; | |
761 | BEGIN | |
762 | warnStringsAt2 (s, s, tok1, tok2) | |
763 | END warnStringAt2 ; | |
764 | ||
765 | ||
766 | (* | |
767 | warnStringAt - given an error string, s, it places this | |
768 | string at token position, tok. | |
769 | The string is consumed. | |
770 | *) | |
771 | ||
772 | PROCEDURE warnStringAt (s: String; tok: CARDINAL) ; | |
773 | VAR | |
774 | e: error ; | |
775 | BEGIN | |
776 | e := newWarning (tok) ; | |
777 | errorString (e, s) | |
778 | END warnStringAt ; | |
779 | ||
780 | ||
781 | (* | |
782 | errorAbort0 - aborts compiling, it flushes all warnings and errors before aborting. | |
783 | *) | |
784 | ||
785 | PROCEDURE errorAbort0 (a: ARRAY OF CHAR) ; | |
786 | BEGIN | |
787 | flushWarnings ; | |
788 | IF NOT StrEqual (a, '') | |
789 | THEN | |
790 | writeFormat0(a) | |
791 | END ; | |
792 | IF NOT flushAll(head, TRUE) | |
793 | THEN | |
794 | writeFormat0 ('unidentified error') ; | |
795 | IF flushAll (head, TRUE) | |
796 | THEN | |
797 | END | |
798 | END ; | |
799 | ExitOnHalt (1) ; | |
800 | HALT | |
801 | END errorAbort0 ; | |
802 | ||
803 | ||
804 | BEGIN | |
805 | init | |
806 | END mcError. |