IdSym := RequestSym (idtok, Id) ;
IF NOT IsExpressionCompatible (GetSType (e1), GetSType (e2))
THEN
- MetaError2 ('incompatible types found in {%EkFOR} loop header, initial expression {%E1tsad} and final expression {%E2tsad}',
+ MetaError2 ('incompatible types found in {%EkFOR} loop header, initial expression {%1tsad} and final expression {%2tsad}',
e1, e2) ;
CheckExpressionCompatible (idtok, GetSType (e1), GetSType (e2))
END ;
IF NOT IsExpressionCompatible( GetSType (e1), ByType)
THEN
- MetaError2 ('incompatible types found in {%EkFOR} loop header, initial expression {%E1tsad} and {%kBY} {%E2tsad}',
+ MetaError2 ('incompatible types found in {%EkFOR} loop header, initial expression {%1tsad} and {%kBY} {%2tsad}',
e2, BySym) ;
CheckExpressionCompatible (e1tok, GetSType (e1), ByType)
ELSIF NOT IsExpressionCompatible (GetSType (e2), ByType)
THEN
- MetaError2 ('incompatible types found in {%EkFOR} loop header, final expression {%E1tsad} and {%kBY} {%E2tsad}',
+ MetaError2 ('incompatible types found in {%EkFOR} loop header, final expression {%1tsad} and {%kBY} {%2tsad}',
e2, BySym) ;
CheckExpressionCompatible (e1tok, GetSType (e2), ByType)
END ;
Type := GetSType (Param) ; (* get the type from the symbol, not the stack *)
IF NoOfParam # 1
THEN
- MetaErrorT1 (functok, 'base procedure {%E1kLENGTH} expects 1 parameter, seen {%1En} parameters', NoOfParam)
+ MetaErrorT1 (functok, 'base procedure {%1EkLENGTH} expects 1 parameter, seen {%1n} parameters', NoOfParam)
END ;
IF NoOfParam >= 1
THEN
PopT (NoOfParam) ;
PopN (NoOfParam + 1) ;
PushTtok (MakeConstLit (combinedtok, MakeKey ('0'), Cardinal), combinedtok) ;
- MetaErrorT0 (functok, 'no procedure Length found for substitution to the standard function {%E1kLENGTH} which is required to calculate non constant string lengths')
+ MetaErrorT0 (functok, 'no procedure Length found for substitution to the standard function {%1EkLENGTH} which is required to calculate non constant string lengths')
END
END
ELSE
PushTtok (Res, combinedtok)
ELSE
MetaErrorT1 (combinedtok,
- 'the parameter to {%E1kODD} must be a variable or constant, seen {%E1ad}',
+ 'the parameter to {%1EkODD} must be a variable or constant, seen {%1ad}',
Var) ;
PushTtok (False, combinedtok)
END
ELSE
MetaErrorT1 (functok,
- 'the pseudo procedure {%E1kODD} only has one parameter, seen {%E1n} parameters',
+ 'the pseudo procedure {%1EkODD} only has one parameter, seen {%1n} parameters',
NoOfParam) ;
PushTtok (False, functok)
END
PushTFtok (Res, GetSType (Var), combinedtok)
ELSE
MetaErrorT1 (combinedtok,
- 'the parameter to {%A1kABS} must be a variable or constant, seen {%1ad}',
+ 'the parameter to {%AkABS} must be a variable or constant, seen {%1ad}',
Var)
END
ELSE
MetaErrorT1 (functok,
- 'the pseudo procedure {%A1kABS} only has one parameter, seen {%E1n} parameters',
+ 'the pseudo procedure {%AkABS} only has one parameter, seen {%1n} parameters',
NoOfParam)
END
END BuildAbsFunction ;
PushTFtok (Res, Char, combinedtok)
ELSE
MetaErrorT1 (functok,
- 'the parameter to {%A1kCAP} must be a variable or constant, seen {%E1ad}',
+ 'the parameter to {%AkCAP} must be a variable or constant, seen {%1ad}',
Var)
END
ELSE
MetaErrorT1 (functok,
- 'the pseudo procedure {%A1kCAP} only has one parameter, seen {%E1n} parameters',
+ 'the pseudo procedure {%AkCAP} only has one parameter, seen {%1n} parameters',
NoOfParam)
END
END BuildCapFunction ;
BuildConvertFunction
ELSE
MetaErrorT1 (functok,
- 'the parameter to {%A1kCHR} must be a variable or constant, seen {%E1ad}',
+ 'the parameter to {%AkCHR} must be a variable or constant, seen {%1ad}',
Var)
END
ELSE
MetaErrorT1 (functok,
- 'the pseudo procedure {%A1kCHR} only has one parameter, seen {%E1n} parameters',
+ 'the pseudo procedure {%AkCHR} only has one parameter, seen {%1n} parameters',
NoOfParam)
END
END BuildChrFunction ;
BuildConvertFunction
ELSE
MetaErrorT2 (functok,
- 'the parameter to {%A1k%a} must be a variable or constant, seen {%2ad}',
+ 'the parameter to {%1Ak%a} must be a variable or constant, seen {%2ad}',
Sym, Var)
END
ELSE
MetaErrorT2 (functok,
- 'the pseudo procedure {%A1k%a} only has one parameter, seen {%2n} parameters',
+ 'the pseudo procedure {%1Ak%a} only has one parameter, seen {%2n} parameters',
Sym, NoOfParam)
END
END BuildOrdFunction ;
ELSE
combinedtok := MakeVirtualTok (functok, optok, optok) ;
MetaErrorT2 (combinedtok,
- 'the parameter to {%E1k%a} must be a variable or constant, seen {%2ad}',
+ 'the parameter to {%1Ek%a} must be a variable or constant, seen {%2ad}',
Sym, Var) ;
PushTtok (combinedtok, MakeConstLit (combinedtok, MakeKey ('0'), ZType))
END
ELSE
MetaErrorT2 (functok,
- 'the pseudo procedure {%E1k%a} only has one parameter, seen {%2n} parameters',
+ 'the pseudo procedure {%1Ek%a} only has one parameter, seen {%2n} parameters',
Sym, NoOfParam) ;
PushTtok (functok, MakeConstLit (functok, MakeKey ('0'), ZType))
END
AreConst := FALSE ;
ELSIF NOT IsConst (OperandT (i))
THEN
- MetaError1 ('problem in the {%E1N} argument for {%EkMAKEADR}, all arguments to {%EkMAKEADR} must be either variables or constants', i)
+ MetaError1 ('problem in the {%1EN} argument for {%kMAKEADR}, all arguments to {%kMAKEADR} must be either variables or constants', i)
END ;
INC (i)
END ;
PopN (NoOfParameters+1) ;
PushTFtok (ReturnVar, GetSType (MakeAdr), resulttok)
ELSE
- MetaError1 ('the pseudo procedure {%EkMAKEADR} requires at least one parameter, seen {%E1n}', NoOfParameters) ;
+ MetaError1 ('the pseudo procedure {%EkMAKEADR} requires at least one parameter, seen {%1n}', NoOfParameters) ;
PopN (1) ;
PushTFtok (Nil, GetSType (MakeAdr), functok)
END
GenQuad (LogicalShiftOp, returnVar, varSet, derefExp) ;
PushTFtok (returnVar, GetSType (varSet), combinedtok)
ELSE
- MetaError1 ('SYSTEM procedure {%E1kSHIFT} expects a constant or variable which has a type of SET as its first parameter, seen {%E1ad}',
+ MetaError1 ('SYSTEM procedure {%1EkSHIFT} expects a constant or variable which has a type of SET as its first parameter, seen {%1ad}',
varSet) ;
PushTFtok (MakeConstLit (combinedtok, MakeKey ('0'), Cardinal), Cardinal, combinedtok)
END
ELSE
combinedtok := MakeVirtualTok (functok, functok, paramtok) ;
MetaErrorT1 (functok,
- 'the pseudo procedure {%EkSHIFT} requires at least two parameters, seen {%E1n}',
+ 'the pseudo procedure {%kSHIFT} requires at least two parameters, seen {%1En}',
NoOfParam) ;
PopN (NoOfParam + 1) ;
PushTFtok (MakeConstLit (combinedtok, MakeKey ('0'), Cardinal), Cardinal, combinedtok)
IF IsUnknown (Type)
THEN
(* we cannot recover if we dont have a type. *)
- MetaErrorT1 (typetok, 'undeclared type {%A1ad} found in {%kCONVERT}', Type)
+ MetaErrorT1 (typetok, 'undeclared type {%1Aad} found in {%kCONVERT}', Type)
(* non recoverable error. *)
ELSIF IsUnknown (Exp)
THEN
(* we cannot recover if we dont have a type. *)
- MetaErrorT1 (typetok, 'unknown {%A1d} {%1ad} found in {%kCONVERT}', Exp)
+ MetaErrorT1 (typetok, 'unknown {%1Ad} {%1ad} found in {%kCONVERT}', Exp)
(* non recoverable error. *)
ELSIF (IsSet (Type) OR IsEnumeration (Type) OR IsSubrange (Type) OR
IsType (Type) OR IsPointer (Type) OR IsProcType (Type) OR IsRecord (Type)) AND
IF Type = NulSym
THEN
MetaErrorT1 (resulttok,
- 'cannot get the type and size of {%E1ad}', OperandT (1))
+ 'cannot get the type and size of {%1Ead}', OperandT (1))
END ;
GenQuadO (resulttok, SizeOp, ReturnVar, NulSym, Type, TRUE)
END
ELSE
resulttok := functok ;
MetaErrorT1 (resulttok,
- '{%E}SYSTEM procedure {%kSIZE} expects a variable as its parameter, seen {%E1d}',
+ '{%E}SYSTEM procedure {%kSIZE} expects a variable as its parameter, seen {%1Ed}',
OperandT (1)) ;
ReturnVar := MakeConstLit (resulttok, MakeKey('0'), Cardinal)
END ;
GenQuadO (resulttok, SizeOp, ReturnVar, NulSym, GetSType (OperandT (1)), FALSE)
ELSE
MetaErrorT1 (resulttok,
- '{%E}SYSTEM procedure function {%kTSIZE} expects a variable as its first parameter, seen {%E1d}',
+ '{%E}SYSTEM procedure function {%kTSIZE} expects a variable as its first parameter, seen {%1Ed}',
OperandT (1)) ;
ReturnVar := MakeConstLit (resulttok, MakeKey ('0'), Cardinal)
END
ELSE
resulttok := MakeVirtualTok (functok, functok, paramtok) ;
MetaErrorT1 (resulttok,
- '{%E}SYSTEM procedure function {%kTSIZE} expects the first parameter to be a record type, seen {%E1d}',
+ '{%E}SYSTEM procedure function {%kTSIZE} expects the first parameter to be a record type, seen {%1d}',
Record) ;
ReturnVar := MakeConstLit (resulttok, MakeKey ('0'), Cardinal)
END
GenQuadO (resulttok, StandardFunctionOp, ReturnVar, ProcSym, OperandT(1), FALSE)
ELSE
MetaErrorT1 (resulttok,
- '{%E}SYSTEM procedure function {%kTBITSIZE} expects a variable as its first parameter, seen {%E1d}',
+ '{%E}SYSTEM procedure function {%kTBITSIZE} expects a variable as its first parameter, seen {%1d}',
OperandT (1)) ;
ReturnVar := MakeConstLit (resulttok, MakeKey ('0'), Cardinal)
END
ELSE
resulttok := MakeVirtualTok (functok, functok, paramtok) ;
MetaErrorT1 (resulttok,
- '{%E}SYSTEM procedure function {%kTBITSIZE} expects the first parameter to be a record type, seen {%E1d}',
+ '{%E}SYSTEM procedure function {%kTBITSIZE} expects the first parameter to be a record type, seen {%1d}',
Record) ;
ReturnVar := MakeConstLit (resulttok, MakeKey ('0'), Cardinal)
END
--- /dev/null
+#!/usr/bin/env python3
+
+# utility to check meta errors for simple format spec mistakes.
+
+# Copyright (C) 2016-2023 Free Software Foundation, Inc.
+#
+# This file is part of GNU Modula-2.
+#
+# GNU Modula-2 is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Modula-2 is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Modula-2; see the file COPYING. If not, write to the
+# Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+import argparse
+import os
+import pathlib
+import sys
+
+
+exit_code = 0
+
+
+def visit_dir(directory, ext, func):
+ # visit_dir - call func for each file below, dir, matching extension, ext.
+ list_of_files = os.listdir(directory)
+ list_of_files.sort()
+ for filename in list_of_files:
+ path = pathlib.Path(filename)
+ full = os.path.join(directory, filename)
+ if path.suffix == ext:
+ func(full)
+
+
+def check_format_spec(filename, line, no):
+ global exit_code
+
+ percent = line.find('%')
+ if percent >= 0:
+ specifier = False
+ for ch in line[percent:]:
+ if ch in ['{', '%']:
+ pass
+ elif ch in ['1', '2', '3', '4']:
+ if specifier:
+ sys.stderr.write('%s:%d: format specifier error, the symbol position digit must be before the specifier: %s\n' % (filename, no, line))
+ exit_code = 1
+ else:
+ specifier = True
+
+
+def search_format(filename, line, no):
+ cbra = line.find('{')
+ while cbra >= 0:
+ colon = line.find(':', cbra)
+ end = line.find('}', cbra)
+ if end >= 0:
+ if (colon >= 0) and (colon < end):
+ end = colon
+ check_format_spec(filename, line[cbra:end], no)
+ cbra = line.find('{', end)
+ else:
+ return
+
+
+def check_string_quote (filename, line, no, quote):
+ end = line.find(quote, 1)
+ if end > 0:
+ search_format(filename, line[1:end], no)
+
+
+def check_string (filename, line, no):
+ quote = line.find("'")
+ if quote >= 0:
+ check_string_quote(filename, line[quote:], no, "'")
+ quote = line.find('"')
+ if quote >= 0:
+ check_string_quote(filename, line[quote:], no, '"')
+
+
+def check_meta_spec (filename):
+ lines = open(filename).readlines()
+ extra = 0
+ for no, line in enumerate(lines):
+ if extra > 0:
+ extra -= 1
+ check_string(filename, line, no+1)
+ elif "Meta" in line:
+ meta = line.find("Meta")
+ if meta >= 0:
+ bra = line.find("(", meta)
+ if bra >= 0:
+ check_string(filename, line[bra:], no+1)
+ extra = 1
+
+
+def handle_arguments():
+ # handle_arguments create and return the args object.
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-s', '--srcdir',
+ help='set source directory.',
+ default='.', action='store')
+ args = parser.parse_args()
+ return args
+
+
+def main():
+ args = handle_arguments()
+ visit_dir(args.srcdir, '.mod', check_meta_spec)
+ visit_dir(args.srcdir, '.bnf', check_meta_spec)
+ sys.exit(exit_code)
+
+
+main()