diff options
Diffstat (limited to 'yang/embedmodel.py')
| -rw-r--r-- | yang/embedmodel.py | 78 |
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)) |
