public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-7648] modula2: Fixes to the error format specifications
@ 2023-07-29 23:24 Gaius Mulley
  0 siblings, 0 replies; only message in thread
From: Gaius Mulley @ 2023-07-29 23:24 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:7a69e486e63c1e9f9d28b694d39030361a732144

commit r13-7648-g7a69e486e63c1e9f9d28b694d39030361a732144
Author: Gaius Mulley <gaiusmod2@gmail.com>
Date:   Sun Jul 30 00:24:06 2023 +0100

    modula2: Fixes to the error format specifications
    
    This patch contains a python3 script to check the meta format error
    specifications.  It also includes about 20 fixes to M2Quads.mod format
    specifications.
    
    gcc/m2/ChangeLog:
    
            * Make-lang.in (check-format-error): New rule.
            * gm2-compiler/M2MetaError.mod (op): Add calls InternalError if
            digits are detected.
            * gm2-compiler/M2Quads.mod (BuildForToByDo): Bugfix to format
            specifier.
            (BuildLengthFunction): Bugfix to format specifiers.
            (BuildOddFunction): Bugfix to format specifiers.
            (BuildAbsFunction): Bugfix to format specifiers.
            (BuildCapFunction): Bugfix to format specifiers.
            (BuildChrFunction): Bugfix to format specifiers.
            (BuildOrdFunction): Bugfix to format specifiers.
            (BuildMakeAdrFunction): Bugfix to format specifiers.
            (BuildSizeFunction): Bugfix to format specifiers.
            (BuildBitSizeFunction): Bugfix to format specifiers.
            * tools-src/checkmeta.py: New file.
    
    (cherry picked from commit c980eeb88f897e0c3cc2ed40577b22d8032480a9)
    
    Signed-off-by: Gaius Mulley <gaiusmod2@gmail.com>

Diff:
---
 gcc/m2/Make-lang.in                 |   7 ++
 gcc/m2/gm2-compiler/M2MetaError.mod |   6 +-
 gcc/m2/gm2-compiler/M2Quads.mod     |  58 ++++++++---------
 gcc/m2/tools-src/checkmeta.py       | 123 ++++++++++++++++++++++++++++++++++++
 4 files changed, 164 insertions(+), 30 deletions(-)

diff --git a/gcc/m2/Make-lang.in b/gcc/m2/Make-lang.in
index 57949ffdb1c..07fd054725f 100644
--- a/gcc/m2/Make-lang.in
+++ b/gcc/m2/Make-lang.in
@@ -591,6 +591,13 @@ m2/gm2-gcc/$(SRC_PREFIX)%.h: $(srcdir)/m2/gm2-gcc/%.def $(MCDEPS)
 	-test -d $(@D) || $(mkinstalldirs) $(@D)
 	$(MC) -o=$@ $(srcdir)/m2/gm2-gcc/$*.def
 
+ifeq ($(HAVE_PYTHON),yes)
+check-format-error:
+	$(PYTHON) $(srcdir)/m2/tools-src/checkmeta.py -s $(srcdir)/m2/gm2-compiler
+else
+check-format-error:
+endif
+
 # The following tables define the source files which are translated into C using mc
 # and defines the system interface C files.
 
diff --git a/gcc/m2/gm2-compiler/M2MetaError.mod b/gcc/m2/gm2-compiler/M2MetaError.mod
index 5f794a21d6e..97b56ccceb1 100644
--- a/gcc/m2/gm2-compiler/M2MetaError.mod
+++ b/gcc/m2/gm2-compiler/M2MetaError.mod
@@ -1529,7 +1529,11 @@ BEGIN
             DEC (eb.ini) |
       'u':  eb.quotes := FALSE |
       ':':  ifNonNulThen (eb, sym) ;
-            DEC (eb.ini)
+            DEC (eb.ini) |
+      '1':  InternalError ('incorrect format spec, expecting %1 rather than % spec 1') |
+      '2':  InternalError ('incorrect format spec, expecting %2 rather than % spec 2') |
+      '3':  InternalError ('incorrect format spec, expecting %3 rather than % spec 3') |
+      '4':  InternalError ('incorrect format spec, expecting %4 rather than % spec 4')
 
       ELSE
          InternalFormat (eb, 'expecting one of [akqtdnpsuCDEFKNOPQRSTUWXYZ:<>%]', __LINE__)
diff --git a/gcc/m2/gm2-compiler/M2Quads.mod b/gcc/m2/gm2-compiler/M2Quads.mod
index 399a09f32c9..a27c3e1971d 100644
--- a/gcc/m2/gm2-compiler/M2Quads.mod
+++ b/gcc/m2/gm2-compiler/M2Quads.mod
@@ -4411,18 +4411,18 @@ BEGIN
    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 ;
@@ -8290,7 +8290,7 @@ BEGIN
    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
@@ -8333,7 +8333,7 @@ BEGIN
             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
@@ -8427,13 +8427,13 @@ BEGIN
          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
@@ -8501,12 +8501,12 @@ BEGIN
          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 ;
@@ -8561,12 +8561,12 @@ BEGIN
          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 ;
@@ -8631,12 +8631,12 @@ BEGIN
          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 ;
@@ -8702,12 +8702,12 @@ BEGIN
          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 ;
@@ -8773,13 +8773,13 @@ BEGIN
       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
@@ -8846,7 +8846,7 @@ BEGIN
             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 ;
@@ -8858,7 +8858,7 @@ BEGIN
       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
@@ -8928,14 +8928,14 @@ BEGIN
          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)
@@ -9257,12 +9257,12 @@ BEGIN
       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
@@ -10095,14 +10095,14 @@ BEGIN
          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 ;
@@ -10165,7 +10165,7 @@ BEGIN
          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
@@ -10188,7 +10188,7 @@ BEGIN
       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
@@ -10252,7 +10252,7 @@ BEGIN
          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
@@ -10275,7 +10275,7 @@ BEGIN
       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
diff --git a/gcc/m2/tools-src/checkmeta.py b/gcc/m2/tools-src/checkmeta.py
new file mode 100644
index 00000000000..01e5883ca1a
--- /dev/null
+++ b/gcc/m2/tools-src/checkmeta.py
@@ -0,0 +1,123 @@
+#!/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()

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-07-29 23:24 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-29 23:24 [gcc r13-7648] modula2: Fixes to the error format specifications Gaius Mulley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).