+# 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
)
+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:
"IPV6_PREFIX_TKN": Prefix6Handler,
"MAC_TKN": PrefixEthHandler,
"MAC_PREFIX_TKN": PrefixEthHandler,
+ "ASNUM_TKN": AsDotHandler,
}
# core template invoked for each occurence of DEFPY.
# common form, without requiring a more advanced template engine (e.g.
# jinja2)
templ = Template(
- """/* $fnname => "$cmddef" */
+ """$cond_begin/* $fnname => "$cmddef" */
DEFUN_CMD_FUNC_DECL($fnname)
#define funcdecl_$fnname static int ${fnname}_magic(\\
const struct cmd_element *self __attribute__ ((unused)),\\
$argassert
return ${fnname}_magic(self, vty, argc, argv$arglist);
}
-
+$cond_end
"""
)
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):
errors = 0
filedata = clippy.parse(fn)
+ cond_stack = []
+
for entry in filedata["data"]:
+ if entry["type"] == "PREPROC":
+ line = entry["line"].lstrip()
+ tokens = line.split(maxsplit=1)
+ line = "#" + line + "\n"
+
+ if not tokens:
+ continue
+
+ if tokens[0] in ["if", "ifdef", "ifndef"]:
+ cond_stack.append(line)
+ elif tokens[0] in ["elif", "else"]:
+ prev_line = cond_stack.pop(-1)
+ 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")
):
else:
dumpfd.write('"%s":\n\t---- no magic arguments ----\n\n' % (cmddef))
+ params["cond_begin"] = "".join(cond_stack)
+ params["cond_end"] = "".join(["#endif\n"] * len(cond_stack))
params["argdefs"] = "".join(argdefs)
params["argdecls"] = "".join(argdecls)
params["arglist"] = "".join(arglist)
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: