#!/usr/bin/python3
+# SPDX-License-Identifier: NONE
#
# YANG module to C wrapper
# written 2018 by David Lamparter, placed in Public Domain.
-import sys, string, re
+import sys
+import os
+import string
+import re
inname = sys.argv[1]
outname = sys.argv[2]
+outdir = os.path.dirname(os.path.abspath(outname))
+try:
+ os.makedirs(outdir)
+except FileExistsError:
+ pass
+
# 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_rev = re.compile(r'\brevision\s+([\d-]+)\s+\{')
+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 */
+template = """/* autogenerated by embedmodel.py. DO NOT EDIT */
#include <zebra.h>
#include "yang.h"
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,
};
{
\tyang_module_embed(&embed);
}
-'''
+"""
+
+passchars = set(string.printable) - set("\\'\"%\r\n\t\x0b\x0c")
+
-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))
+ 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])
+ return "".join([escapech(i) for i in line])
+
-with open(inname, 'r') as fd:
+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:
+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'
+ name = xml.get("name")
+ rev = xml.find("{urn:ietf:params:xml:ns:yang:yin:1}revision").get("date")
+ fmt = "LYS_YIN"
else:
- name = re_name.search(data).group(1)
- rev = re_rev.search(data).group(1)
- fmt = 'LYS_YANG'
+ 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')
+ raise ValueError("cannot determine YANG module name and revision")
-lines = [escape(row) for row in data.split('\n')]
+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), fmt))
+with open(outname, "w") as fd:
+ fd.write(
+ template
+ % (text, escape(name), escape(rev), escape(sub_name), escape(sub_rev), fmt)
+ )