summaryrefslogtreecommitdiff
path: root/yang/embedmodel.py
diff options
context:
space:
mode:
Diffstat (limited to 'yang/embedmodel.py')
-rw-r--r--yang/embedmodel.py78
1 files changed, 78 insertions, 0 deletions
diff --git a/yang/embedmodel.py b/yang/embedmodel.py
new file mode 100644
index 0000000000..52671f99a8
--- /dev/null
+++ b/yang/embedmodel.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python3
+#
+# YANG module to C wrapper
+# written 2018 by David Lamparter, placed in Public Domain.
+
+import sys, string, re
+
+inname = sys.argv[1]
+outname = sys.argv[2]
+
+# 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+\{')
+
+
+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.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()
+
+# 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:
+ name = re_name.search(data).group(1)
+ rev = re_rev.search(data).group(1)
+ fmt = 'LYS_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), fmt))