1 (* Copyright (C) 2015-2024 Free Software Foundation, Inc. *)
2 (* This file is part of GNU Modula-2.
4 GNU Modula-2 is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 3, or (at your option) any later
9 GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License along
15 with gm2; see the file COPYING. If not, write to the Free Software
16 Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *)
18 IMPLEMENTATION MODULE mcMetaError ;
21 FROM nameKey IMPORT Name, keyToCharStar, NulName ;
22 FROM StrLib IMPORT StrLen ;
23 FROM mcLexBuf IMPORT getTokenNo ;
24 FROM mcError IMPORT error, newError, newWarning, errorString, internalError, chainError, flushErrors ;
25 FROM FIO IMPORT StdOut, WriteLine ;
26 FROM SFIO IMPORT WriteS ;
27 FROM StringConvert IMPORT ctos ;
28 FROM varargs IMPORT vararg ;
32 FROM DynamicStrings IMPORT String, InitString, InitStringCharStar,
33 ConCat, ConCatChar, Mark, string, KillString,
34 Dup, char, Length, Mult ;
36 FROM decl IMPORT node, isType, isTemporary, getType, getSymName, getScope, isDef,
37 isExported, isZtype, isRtype, skipType, getDeclaredMod, getDeclaredDef,
38 getFirstUsed, isLiteral, isConst, isConstSet, isArray, isVar,
39 isEnumeration, isEnumerationField, isUnbounded, isProcType, isProcedure,
40 isPointer, isParameter, isVarParam, isRecord, isRecordField,
41 isVarient, isModule, isImp, isSet, isSubrange ;
44 errorType = (newerror, newwarning, chained) ;
54 percent := '%' anych % copy anych %
57 lbra := '{' [ '!' ] percenttoken '}' =:
62 | '2' % doOperand(2) %
64 | '3' % doOperand(3) %
66 | '4' % doOperand(4) %
71 op := {'a'|'q'|'t'|'d'|'n'|'s'|'D'|'I'|'U'|'E'|'W'} then =:
73 then := [ ':' ebnf ] =:
78 internalFormat - produces an informative internal error.
81 PROCEDURE internalFormat (s: String; i: INTEGER; m: ARRAY OF CHAR) ;
85 e := newError (getTokenNo()) ;
86 s := WriteS (StdOut, s) ;
93 s := Mult (InitString (' '), i) ;
94 s := ConCatChar (s, '^') ;
95 s := WriteS (StdOut, s) ;
97 internalError (m, __FILE__, __LINE__)
102 x - checks to see that a=b.
105 PROCEDURE x (a, b: String) : String ;
109 internalError('different string returned', __FILE__, __LINE__)
116 isWhite - returns TRUE if, ch, is a space.
119 PROCEDURE isWhite (ch: CHAR) : BOOLEAN ;
126 then := [ ':' ebnf ] =:
129 PROCEDURE then (VAR e: error; VAR t: errorType;
130 VAR r: String; s: String;
132 VAR i: INTEGER; l: INTEGER;
133 o: String; positive: BOOLEAN) ;
138 ebnf (e, t, r, s, sym, i, l) ;
139 IF (i<l) AND (char (s, i) # '}')
141 internalFormat (s, i, 'expecting to see }')
151 PROCEDURE doNumber (bol: CARDINAL;
152 sym: vararg; o: String;
153 VAR quotes: BOOLEAN) : String ;
162 varargs.next (sym, bol) ;
163 varargs.arg (sym, c) ;
164 RETURN ConCat (o, ctos (c, 0, ' '))
173 PROCEDURE doCount (bol: CARDINAL;
174 sym: vararg; o: String;
175 VAR quotes: BOOLEAN) : String ;
184 varargs.next (sym, bol) ;
185 varargs.arg (sym, c) ;
186 o := ConCat (o, ctos (c, 0, ' ')) ;
189 11..13: o := ConCat (o, Mark (InitString ('th')))
194 1: o := ConCat (o, Mark (InitString ('st'))) |
195 2: o := ConCat (o, Mark (InitString ('nd'))) |
196 3: o := ConCat (o, Mark (InitString ('rd')))
199 o := ConCat (o, Mark (InitString ('th')))
207 PROCEDURE doAscii (bol: CARDINAL; sym: vararg; o: String) : String ;
211 varargs.next (sym, bol) ;
212 varargs.arg (sym, n) ;
213 IF (Length (o) > 0) OR isTemporary (n)
217 RETURN ConCat (o, InitStringCharStar (keyToCharStar (getSymName (n))))
222 PROCEDURE doName (bol: CARDINAL; sym: vararg; o: String; VAR quotes: BOOLEAN) : String ;
226 varargs.next (sym, bol) ;
227 varargs.arg (sym, n) ;
228 IF (Length (o) > 0) OR isTemporary (n)
235 RETURN ConCat (o, Mark (InitString ('the ZType')))
239 RETURN ConCat (o, Mark (InitString ('the RType')))
240 ELSIF getSymName (n) # NulName
242 RETURN ConCat (o, InitStringCharStar (keyToCharStar (getSymName (n))))
250 PROCEDURE doQualified (bol: CARDINAL; sym: vararg; o: String) : String ;
255 varargs.next (sym, bol) ;
256 varargs.arg (sym, n) ;
257 IF (Length (o) > 0) OR isTemporary (n)
262 mod := varargs.start1 (s) ;
263 IF isDef(s) AND isExported(n)
265 o := x (o, doAscii (0, mod, o)) ;
266 o := x (o, ConCatChar (o, '.')) ;
267 o := x (o, ConCat (o, InitStringCharStar (keyToCharStar (getSymName (n)))))
269 o := x (o, doAscii (bol, sym, o))
278 doType - returns a string containing the type name of
279 sym. It will skip pseudonym types. It also
280 returns the type symbol found.
283 PROCEDURE doType (bol: CARDINAL;
284 VAR sym: vararg; o: String) : String ;
288 varargs.next (sym, bol) ;
289 varargs.arg (sym, n) ;
290 IF (Length (o) > 0) OR (getType (n) = NIL)
294 n := skipType (getType (n)) ;
295 varargs.next (sym, bol) ;
296 varargs.replace (sym, n) ;
297 RETURN x (o, doAscii (bol, sym, o))
303 doSkipType - will skip all pseudonym types. It also
304 returns the type symbol found and name.
307 PROCEDURE doSkipType (bol: CARDINAL; VAR sym: vararg; o: String) : String ;
311 varargs.next (sym, bol) ;
312 varargs.arg (sym, n) ;
317 n := skipType (getType (n)) ;
318 varargs.next (sym, bol) ;
319 varargs.replace (sym, n) ;
320 IF getSymName(n) = NulName
324 RETURN x (o, doAscii (bol, sym, o))
330 PROCEDURE doKey (bol: CARDINAL; sym: vararg; o: String) : String ;
338 varargs.next (sym, bol) ;
339 varargs.arg (sym, n) ;
340 RETURN ConCat (o, InitStringCharStar (keyToCharStar (n)))
346 doError - creates and returns an error note.
349 PROCEDURE doError (e: error; t: errorType; tok: CARDINAL) : error ;
355 internalError ('should not be chaining an error onto an empty error note', __FILE__, __LINE__)
357 e := chainError (tok, e)
365 e := newWarning (tok)
369 internalError ('unexpected enumeration value', __FILE__, __LINE__)
376 doDeclaredDef - creates an error note where sym[bol] was declared.
379 PROCEDURE doDeclaredDef (e: error; t: errorType;
381 sym: vararg) : error ;
385 IF bol <= varargs.nargs (sym)
387 varargs.next (sym, bol) ;
388 varargs.arg (sym, n) ;
389 e := doError (e, t, getDeclaredDef (n))
396 doDeclaredMod - creates an error note where sym[bol] was declared.
399 PROCEDURE doDeclaredMod (e: error; t: errorType;
401 sym: vararg) : error ;
405 IF bol <= varargs.nargs (sym)
407 varargs.next (sym, bol) ;
408 varargs.arg (sym, n) ;
409 e := doError (e, t, getDeclaredMod (n))
416 doUsed - creates an error note where sym[bol] was first used.
419 PROCEDURE doUsed (e: error; t: errorType;
421 sym: vararg) : error ;
425 IF bol <= varargs.nargs (sym)
427 varargs.next (sym, bol) ;
428 varargs.arg (sym, n) ;
429 e := doError (e, t, getFirstUsed (n))
436 ConCatWord - joins sentances, a, b, together.
439 PROCEDURE ConCatWord (a, b: String) : String ;
441 IF (Length(a) = 1) AND (char (a, 0) = 'a')
443 a := x (a, ConCatChar (a, 'n'))
444 ELSIF (Length(a) > 1) AND (char (a, -1) = 'a') AND isWhite (char (a, -2))
446 a := x (a, ConCatChar (a, 'n'))
448 IF (Length(a) > 0) AND (NOT isWhite (char (a, -1)))
450 a := x (a, ConCatChar (a, ' '))
452 RETURN x (a, ConCat (a, b))
460 PROCEDURE symDesc (n: node; o: String) : String ;
464 RETURN ConCatWord (o, Mark (InitString ('literal')))
467 RETURN ConCatWord (o, Mark (InitString ('constant set')))
469 ELSIF IsConstructor(n)
471 RETURN( ConCatWord (o, Mark (InitString ('constructor'))) )
475 RETURN ConCatWord (o, Mark (InitString ('constant')))
478 RETURN ConCatWord (o, Mark (InitString ('array')))
481 RETURN ConCatWord (o, Mark (InitString ('variable')))
482 ELSIF isEnumeration (n)
484 RETURN ConCatWord (o, Mark (InitString ('enumeration type')))
485 ELSIF isEnumerationField (n)
487 RETURN ConCatWord (o, Mark (InitString ('enumeration field')))
488 ELSIF isUnbounded (n)
490 RETURN ConCatWord (o, Mark (InitString ('unbounded parameter')))
493 RETURN ConCatWord (o, Mark (InitString ('procedure type')))
494 ELSIF isProcedure (n)
496 RETURN ConCatWord (o, Mark (InitString ('procedure')))
499 RETURN ConCatWord (o, Mark (InitString ('pointer')))
500 ELSIF isParameter (n)
504 RETURN ConCatWord (o, Mark (InitString ('var parameter')))
506 RETURN ConCatWord (o, Mark (InitString ('parameter')))
510 RETURN ConCatWord (o, Mark (InitString ('type')))
513 RETURN ConCatWord (o, Mark (InitString ('record')))
514 ELSIF isRecordField (n)
516 RETURN ConCatWord (o, Mark (InitString ('record field')))
519 RETURN ConCatWord (o, Mark (InitString ('varient record')))
522 RETURN ConCatWord (o, Mark (InitString ('module')))
525 RETURN ConCatWord (o, Mark (InitString ('definition module')))
528 RETURN ConCatWord (o, Mark (InitString ('implementation module')))
531 RETURN ConCatWord(o, Mark (InitString ('set')))
534 RETURN ConCatWord(o, Mark (InitString ('subrange')))
545 PROCEDURE doDesc (bol: CARDINAL;
546 sym: vararg; o: String;
547 VAR quotes: BOOLEAN) : String ;
553 varargs.next (sym, bol) ;
554 varargs.arg (sym, n) ;
555 o := symDesc (n, o) ;
566 addQuoted - if, o, is not empty then add it to, r.
569 PROCEDURE addQuoted (r, o: String; quotes: BOOLEAN) : String ;
573 IF NOT isWhite (char (r, -1))
575 r := x (r, ConCatChar (r, " "))
579 r := x (r, ConCatChar (r, "'"))
581 r := x (r, ConCat (r, o)) ;
584 r := x (r, ConCatChar (r, "'"))
592 op := {'a'|'q'|'t'|'d'|'k'|'n'|'s'|'D'|'I'|'U'|'E'|'W'} then =:
595 PROCEDURE op (VAR e: error; VAR t: errorType;
596 VAR r: String; s: String;
598 VAR i: INTEGER; l: INTEGER;
599 bol: CARDINAL; positive: BOOLEAN) ;
605 c := varargs.copy (sym) ;
606 o := InitString ('') ;
608 WHILE (i<l) AND (char (s, i)#'}') DO
611 'a': o := x(o, doName (bol, sym, o, quotes)) |
612 'q': o := x(o, doQualified (bol, sym, o)) |
613 't': o := x(o, doType (bol, sym, o)) |
614 'd': o := x(o, doDesc (bol, sym, o, quotes)) |
615 'n': o := x(o, doNumber (bol, sym, o, quotes)) |
616 'N': o := x(o, doCount (bol, sym, o, quotes)) |
617 's': o := x(o, doSkipType (bol, sym, o)) |
618 'k': o := x(o, doKey (bol, sym, o)) |
619 'D': e := doDeclaredDef (e, t, bol, sym) |
620 'M': e := doDeclaredMod (e, t, bol, sym) |
621 'U': e := doUsed (e, t, bol, sym) |
623 'W': t := newwarning |
624 ':': varargs.end (sym) ;
625 sym := varargs.copy (c) ;
626 then (e, t, r, s, sym, i, l, o, positive) ;
627 o := KillString (o) ;
628 o := InitString ('') ;
629 IF (i<l) AND (char (s, i) # '}')
631 internalFormat (s, i, 'expecting to see }')
636 internalFormat (s, i, 'expecting one of [aqtdnNsDUEW:]')
640 r := x (r, addQuoted (r, o, quotes)) ;
646 percenttoken := '%' (
649 | '2' % doOperand(2) %
651 | '3' % doOperand(3) %
653 | '4' % doOperand(4) %
659 PROCEDURE percenttoken (VAR e: error; t: errorType;
660 VAR r: String; s: String;
662 VAR i: INTEGER; l: INTEGER; positive: BOOLEAN) ;
670 op (e, t, r, s, sym, i, l, 0, positive) |
672 op (e, t, r, s, sym, i, l, 1, positive) |
674 op (e, t, r, s, sym, i, l, 2, positive) |
676 op (e, t, r, s, sym, i, l, 3, positive)
679 internalFormat (s, i, 'expecting one of [123]')
681 IF (i<l) AND (char (s, i) # '}')
683 internalFormat (s, i, 'expecting to see }')
690 percent := '%' anych % copy anych %
694 PROCEDURE percent (VAR r: String; s: String;
696 VAR i: INTEGER; l: INTEGER) ;
703 r := x (r, ConCatChar (r, char (s, i))) ;
711 lbra := '{' [ '!' ] percenttoken '}' =:
714 PROCEDURE lbra (VAR e: error; VAR t: errorType;
715 VAR r: String; s: String;
717 VAR i: INTEGER; l: INTEGER) ;
732 internalFormat (s, i, 'expecting to see %')
734 percenttoken (e, t, r, s, sym, i, l, positive) ;
735 IF (i<l) AND (char (s, i) # '}')
737 internalFormat (s, i, 'expecting to see }')
743 PROCEDURE stop ; BEGIN END stop ;
753 PROCEDURE ebnf (VAR e: error; VAR t: errorType;
754 VAR r: String; s: String;
756 VAR i: INTEGER; l: INTEGER) ;
761 '%': percent (r, s, sym, i, l) |
762 '{': lbra (e, t, r, s, sym, i, l) ;
763 IF (i<l) AND (char (s, i) # '}')
765 internalFormat (s, i, 'expecting to see }')
770 IF ((isWhite (char(s, i)) AND (Length (r) > 0) AND (NOT isWhite (char (r, -1)))) OR
771 (NOT isWhite (char (s, i))))
773 r := x (r, ConCatChar (r, char (s, i)))
785 PROCEDURE doFormat (VAR e: error; VAR t: errorType;
786 s: String; sym: vararg) : String ;
791 r := InitString ('') ;
794 ebnf (e, t, r, s, sym, i, l) ;
795 s := KillString (s) ;
800 PROCEDURE metaErrorStringT1 (tok: CARDINAL; m: String; s: ARRAY OF BYTE) ;
808 sym := varargs.start1 (s) ;
810 str := doFormat (e, t, m, sym) ;
811 e := doError (e, t, tok) ;
812 errorString (e, str) ;
814 END metaErrorStringT1 ;
817 PROCEDURE metaErrorT1 (tok: CARDINAL; m: ARRAY OF CHAR; s: ARRAY OF BYTE) ;
819 metaErrorStringT1 (tok, InitString (m), s)
823 PROCEDURE metaErrorStringT2 (tok: CARDINAL; m: String; s1, s2: ARRAY OF BYTE) ;
831 sym := varargs.start2 (s1, s2) ;
833 str := doFormat (e, t, m, sym) ;
834 e := doError (e, t, tok) ;
835 errorString (e, str) ;
837 END metaErrorStringT2 ;
840 PROCEDURE metaErrorT2 (tok: CARDINAL; m: ARRAY OF CHAR; s1, s2: ARRAY OF BYTE) ;
842 metaErrorStringT2 (tok, InitString (m), s1, s2)
846 PROCEDURE metaErrorStringT3 (tok: CARDINAL; m: String; s1, s2, s3: ARRAY OF BYTE) ;
854 sym := varargs.start3 (s1, s2, s3) ;
856 str := doFormat (e, t, m, sym) ;
857 e := doError (e, t, tok) ;
858 errorString (e, str) ;
860 END metaErrorStringT3 ;
863 PROCEDURE metaErrorT3 (tok: CARDINAL; m: ARRAY OF CHAR; s1, s2, s3: ARRAY OF BYTE) ;
865 metaErrorStringT3 (tok, InitString (m), s1, s2, s3)
869 PROCEDURE metaErrorStringT4 (tok: CARDINAL; m: String; s1, s2, s3, s4: ARRAY OF BYTE) ;
877 sym := varargs.start4 (s1, s2, s3, s4) ;
879 str := doFormat (e, t, m, sym) ;
880 e := doError (e, t, tok) ;
881 errorString (e, str) ;
883 END metaErrorStringT4 ;
886 PROCEDURE metaErrorT4 (tok: CARDINAL; m: ARRAY OF CHAR;
887 s1, s2, s3, s4: ARRAY OF BYTE) ;
889 metaErrorStringT4 (tok, InitString (m), s1, s2, s3, s4)
893 PROCEDURE metaError1 (m: ARRAY OF CHAR; s: ARRAY OF BYTE) ;
895 metaErrorT1 (getTokenNo (), m, s)
899 PROCEDURE metaError2 (m: ARRAY OF CHAR; s1, s2: ARRAY OF BYTE) ;
901 metaErrorT2 (getTokenNo (), m, s1, s2)
905 PROCEDURE metaError3 (m: ARRAY OF CHAR; s1, s2, s3: ARRAY OF BYTE) ;
907 metaErrorT3 (getTokenNo (), m, s1, s2, s3)
911 PROCEDURE metaError4 (m: ARRAY OF CHAR; s1, s2, s3, s4: ARRAY OF BYTE) ;
913 metaErrorT4 (getTokenNo (), m, s1, s2, s3, s4)
921 PROCEDURE wrapErrors (tok: CARDINAL;
922 m1, m2: ARRAY OF CHAR;
931 str := doFormat (e, t, InitString(m1), sym) ;
932 e := doError (e, t, tok) ;
933 errorString (e, str) ;
936 str := doFormat (f, t, InitString (m2), sym) ;
940 f := doError (e, t, tok)
946 PROCEDURE metaErrorsT1 (tok: CARDINAL; m1, m2: ARRAY OF CHAR; s: ARRAY OF BYTE) ;
950 sym := varargs.start1 (s) ;
951 wrapErrors (tok, m1, m2, sym) ;
956 PROCEDURE metaErrorsT2 (tok: CARDINAL; m1, m2: ARRAY OF CHAR; s1, s2: ARRAY OF BYTE) ;
960 sym := varargs.start2 (s1, s2) ;
961 wrapErrors (tok, m1, m2, sym) ;
966 PROCEDURE metaErrorsT3 (tok: CARDINAL; m1, m2: ARRAY OF CHAR; s1, s2, s3: ARRAY OF BYTE) ;
970 sym := varargs.start3 (s1, s2, s3) ;
971 wrapErrors (tok, m1, m2, sym) ;
976 PROCEDURE metaErrorsT4 (tok: CARDINAL; m1, m2: ARRAY OF CHAR; s1, s2, s3, s4: ARRAY OF BYTE) ;
980 sym := varargs.start4 (s1, s2, s3, s4) ;
981 wrapErrors (tok, m1, m2, sym) ;
986 PROCEDURE metaErrors1 (m1, m2: ARRAY OF CHAR; s: ARRAY OF BYTE) ;
988 metaErrorsT1 (getTokenNo (), m1, m2, s)
992 PROCEDURE metaErrors2 (m1, m2: ARRAY OF CHAR; s1, s2: ARRAY OF BYTE) ;
994 metaErrorsT2 (getTokenNo (), m1, m2, s1, s2)
998 PROCEDURE metaErrors3 (m1, m2: ARRAY OF CHAR; s1, s2, s3: ARRAY OF BYTE) ;
1000 metaErrorsT3 (getTokenNo (), m1, m2, s1, s2, s3)
1004 PROCEDURE metaErrors4 (m1, m2: ARRAY OF CHAR; s1, s2, s3, s4: ARRAY OF BYTE) ;
1006 metaErrorsT4 (getTokenNo (), m1, m2, s1, s2, s3, s4)
1010 PROCEDURE metaErrorString1 (m: String; s: ARRAY OF BYTE) ;
1012 metaErrorStringT1 (getTokenNo (), m, s)
1013 END metaErrorString1 ;
1016 PROCEDURE metaErrorString2 (m: String; s1, s2: ARRAY OF BYTE) ;
1018 metaErrorStringT2 (getTokenNo (), m, s1, s2)
1019 END metaErrorString2 ;
1022 PROCEDURE metaErrorString3 (m: String; s1, s2, s3: ARRAY OF BYTE) ;
1024 metaErrorStringT3 (getTokenNo (), m, s1, s2, s3)
1025 END metaErrorString3 ;
1028 PROCEDURE metaErrorString4 (m: String; s1, s2, s3, s4: ARRAY OF BYTE) ;
1030 metaErrorStringT4 (getTokenNo (), m, s1, s2, s3, s4)
1031 END metaErrorString4 ;