diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:53:30 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:53:30 +0000 |
commit | 2c7cac91ed6e7db0f6937923d2b57f97dbdbc337 (patch) | |
tree | c05dc0f8e6aa3accc84e3e5cffc933ed94941383 /yang/embedmodel.py | |
parent | Initial commit. (diff) | |
download | frr-2c7cac91ed6e7db0f6937923d2b57f97dbdbc337.tar.xz frr-2c7cac91ed6e7db0f6937923d2b57f97dbdbc337.zip |
Adding upstream version 8.4.4.upstream/8.4.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'yang/embedmodel.py')
-rw-r--r-- | yang/embedmodel.py | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/yang/embedmodel.py b/yang/embedmodel.py new file mode 100644 index 0000000..a77a813 --- /dev/null +++ b/yang/embedmodel.py @@ -0,0 +1,109 @@ +#!/usr/bin/python3 +# +# YANG module to C wrapper +# written 2018 by David Lamparter, placed in Public Domain. + +import sys +import os +import string +import re + +inname = sys.argv[1] +outname = sys.argv[2] + +outdir = os.path.dirname(os.path.abspath(outname)) +if not os.path.isdir(outdir): + os.makedirs(outdir) + +# these are regexes to avoid a compile-time/host dependency on yang-tools +# or python-yang. Cross-compiling FRR is already somewhat involved, no need +# to make it even harder. + +re_name = re.compile(r"\bmodule\s+([^\s]+)\s+\{") +re_subname = re.compile(r"\bsubmodule\s+([^\s]+)\s+\{") +re_mainname = re.compile(r"\bbelongs-to\s+([^\s]+)\s+\{") +re_rev = re.compile(r"\brevision\s+([\d-]+)\s+\{") + + +template = """/* autogenerated by embedmodel.py. DO NOT EDIT */ + +#include <zebra.h> +#include "yang.h" + +static const char model[] = +\t"%s"; + +static struct yang_module_embed embed = { +\t.mod_name = "%s", +\t.mod_rev = "%s", +\t.sub_mod_name = "%s", +\t.sub_mod_rev = "%s", +\t.data = model, +\t.format = %s, +}; + +static void embed_register(void) __attribute__((_CONSTRUCTOR(2000))); +static void embed_register(void) +{ +\tyang_module_embed(&embed); +} +""" + +passchars = set(string.printable) - set("\\'\"%\r\n\t\x0b\x0c") + + +def escapech(char): + if char in passchars: + return char + if char == "\n": + return "\\n" + if char == "\t": + return "\\t" + if char in "\"\\'": + return "\\" + char + return "\\x%02x" % (ord(char)) + + +def escape(line): + return "".join([escapech(i) for i in line]) + + +with open(inname, "r") as fd: + data = fd.read() + +sub_name = "" +rev = "" +sub_rev = "" + +# XML support isn't actively used currently, but it's here in case the need +# arises. It does avoid the regex'ing. +if "<?xml" in data: + from xml.etree import ElementTree + + xml = ElementTree.fromstring(data) + name = xml.get("name") + rev = xml.find("{urn:ietf:params:xml:ns:yang:yin:1}revision").get("date") + fmt = "LYS_YIN" +else: + search_name = re_name.search(data) + if search_name: + name = search_name.group(1) + rev = re_rev.search(data).group(1) + else: + search_name = re_subname.search(data) + sub_name = search_name.group(1) + name = re_mainname.search(data).group(1) + sub_rev = re_rev.search(data).group(1) + fmt = "LYS_IN_YANG" + +if name is None or rev is None: + raise ValueError("cannot determine YANG module name and revision") + +lines = [escape(row) for row in data.split("\n")] +text = '\\n"\n\t"'.join(lines) + +with open(outname, "w") as fd: + fd.write( + template + % (text, escape(name), escape(rev), escape(sub_name), escape(sub_rev), fmt) + ) |