]> git.proxmox.com Git - mirror_frr.git/blobdiff - python/clidef.py
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / python / clidef.py
index b57a00fc892638e5dd6024c82bccd553685a2e9f..244a8205bf2d407123b2c292b8421118f126ff8b 100644 (file)
@@ -1,20 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
 # FRR CLI preprocessor (DEFPY)
 #
 # Copyright (C) 2017  David Lamparter for NetDEF, Inc.
-#
-# This program 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 2 of the License, or (at your option)
-# any later version.
-#
-# This program 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 this program; see the file COPYING; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
 import clippy, traceback, sys, os
 from collections import OrderedDict
@@ -64,6 +51,12 @@ _fail = (_end == argv[_i]->arg) || (*_end != '\\0');"""
     )
 
 
+class AsDotHandler(RenderHandler):
+    argtype = "as_t"
+    decl = Template("as_t $varname = 0;")
+    code = Template("_fail = !asn_str2asn(argv[_i]->arg, &$varname);")
+
+
 # A.B.C.D/M (prefix_ipv4) and
 # X:X::X:X/M (prefix_ipv6) are "compatible" and can merge into a
 # struct prefix:
@@ -165,6 +158,7 @@ handlers = {
     "IPV6_PREFIX_TKN": Prefix6Handler,
     "MAC_TKN": PrefixEthHandler,
     "MAC_PREFIX_TKN": PrefixEthHandler,
+    "ASNUM_TKN": AsDotHandler,
 }
 
 # core template invoked for each occurence of DEFPY.
@@ -241,24 +235,51 @@ def get_always_args(token, always_args, args=[], stack=[]):
 
 
 class Macros(dict):
+    def __init__(self):
+        super().__init__()
+        self._loc = {}
+
     def load(self, filename):
         filedata = clippy.parse(filename)
         for entry in filedata["data"]:
             if entry["type"] != "PREPROC":
                 continue
-            ppdir = entry["line"].lstrip().split(None, 1)
-            if ppdir[0] != "define" or len(ppdir) != 2:
-                continue
-            ppdef = ppdir[1].split(None, 1)
-            name = ppdef[0]
-            if "(" in name:
-                continue
-            val = ppdef[1] if len(ppdef) == 2 else ""
-
-            val = val.strip(" \t\n\\")
-            if name in self:
-                sys.stderr.write("warning: macro %s redefined!\n" % (name))
+            self.load_preproc(filename, entry)
+
+    def setup(self, key, val, where="built-in"):
+        self[key] = val
+        self._loc[key] = (where, 0)
+
+    def load_preproc(self, filename, entry):
+        ppdir = entry["line"].lstrip().split(None, 1)
+        if ppdir[0] != "define" or len(ppdir) != 2:
+            return
+        ppdef = ppdir[1].split(None, 1)
+        name = ppdef[0]
+        if "(" in name:
+            return
+        val = ppdef[1] if len(ppdef) == 2 else ""
+
+        val = val.strip(" \t\n\\")
+        if self.get(name, val) != val:
+            sys.stderr.write(
+                "%s:%d: warning: macro %s redefined!\n"
+                % (
+                    filename,
+                    entry["lineno"],
+                    name,
+                )
+            )
+            sys.stderr.write(
+                "%s:%d: note: previously defined here\n"
+                % (
+                    self._loc[name][0],
+                    self._loc[name][1],
+                )
+            )
+        else:
             self[name] = val
+            self._loc[name] = (filename, entry["lineno"])
 
 
 def process_file(fn, ofd, dumpfd, all_defun, macros):
@@ -283,6 +304,11 @@ def process_file(fn, ofd, dumpfd, all_defun, macros):
                 cond_stack.append(prev_line + line)
             elif tokens[0] in ["endif"]:
                 cond_stack.pop(-1)
+            elif tokens[0] in ["define"]:
+                if not cond_stack:
+                    macros.load_preproc(fn, entry)
+                elif len(cond_stack) == 1 and cond_stack[0] == "#ifdef CLIPPY\n":
+                    macros.load_preproc(fn, entry)
             continue
         if entry["type"].startswith("DEFPY") or (
             all_defun and entry["type"].startswith("DEFUN")
@@ -454,9 +480,9 @@ if __name__ == "__main__":
     macros.load(os.path.join(basepath, "lib/command.h"))
     macros.load(os.path.join(basepath, "bgpd/bgp_vty.h"))
     # sigh :(
-    macros["PROTO_REDIST_STR"] = "FRR_REDIST_STR_ISISD"
-    macros["PROTO_IP_REDIST_STR"] = "FRR_IP_REDIST_STR_ISISD"
-    macros["PROTO_IP6_REDIST_STR"] = "FRR_IP6_REDIST_STR_ISISD"
+    macros.setup("PROTO_REDIST_STR", "FRR_REDIST_STR_ISISD")
+    macros.setup("PROTO_IP_REDIST_STR", "FRR_IP_REDIST_STR_ISISD")
+    macros.setup("PROTO_IP6_REDIST_STR", "FRR_IP6_REDIST_STR_ISISD")
 
     errors = process_file(args.cfile, ofd, dumpfd, args.all_defun, macros)
     if errors != 0: