]>
Commit | Line | Data |
---|---|---|
3a11599c DL |
1 | #!/usr/bin/python3 |
2 | # | |
3 | # YANG module to C wrapper | |
4 | # written 2018 by David Lamparter, placed in Public Domain. | |
5 | ||
6 | import sys, string, re | |
7 | ||
8 | inname = sys.argv[1] | |
9 | outname = sys.argv[2] | |
10 | ||
11 | # these are regexes to avoid a compile-time/host dependency on yang-tools | |
12 | # or python-yang. Cross-compiling FRR is already somewhat involved, no need | |
13 | # to make it even harder. | |
14 | ||
15 | re_name = re.compile(r'\bmodule\s+([^\s]+)\s+\{') | |
16 | re_rev = re.compile(r'\brevision\s+([\d-]+)\s+\{') | |
17 | ||
18 | ||
19 | template = '''/* autogenerated by embedmodel.py. DO NOT EDIT */ | |
20 | ||
21 | #include <zebra.h> | |
22 | #include "yang.h" | |
23 | ||
24 | static const char model[] = | |
25 | \t"%s"; | |
26 | ||
27 | static struct yang_module_embed embed = { | |
28 | \t.mod_name = "%s", | |
29 | \t.mod_rev = "%s", | |
30 | \t.data = model, | |
31 | \t.format = %s, | |
32 | }; | |
33 | ||
34 | static void embed_register(void) __attribute__((_CONSTRUCTOR(2000))); | |
35 | static void embed_register(void) | |
36 | { | |
37 | \tyang_module_embed(&embed); | |
38 | } | |
39 | ''' | |
40 | ||
41 | passchars = set(string.printable) - set('\\\'"%\r\n\t\x0b\x0c') | |
42 | def escapech(char): | |
43 | if char in passchars: | |
44 | return char | |
45 | if char == '\n': | |
46 | return '\\n' | |
47 | if char == '\t': | |
48 | return '\\t' | |
49 | if char in '"\\\'': | |
50 | return '\\' + char | |
51 | return '\\x%02x' % (ord(char)) | |
52 | def escape(line): | |
53 | return ''.join([escapech(i) for i in line]) | |
54 | ||
55 | with open(inname, 'r') as fd: | |
56 | data = fd.read() | |
57 | ||
58 | # XML support isn't actively used currently, but it's here in case the need | |
59 | # arises. It does avoid the regex'ing. | |
60 | if '<?xml' in data: | |
61 | from xml.etree import ElementTree | |
62 | xml = ElementTree.fromstring(data) | |
63 | name = xml.get('name') | |
64 | rev = xml.find('{urn:ietf:params:xml:ns:yang:yin:1}revision').get('date') | |
65 | fmt = 'LYS_YIN' | |
66 | else: | |
67 | name = re_name.search(data).group(1) | |
68 | rev = re_rev.search(data).group(1) | |
69 | fmt = 'LYS_YANG' | |
70 | ||
71 | if name is None or rev is None: | |
72 | raise ValueError('cannot determine YANG module name and revision') | |
73 | ||
74 | lines = [escape(row) for row in data.split('\n')] | |
75 | text = '\\n"\n\t"'.join(lines) | |
76 | ||
77 | with open(outname, 'w') as fd: | |
78 | fd.write(template % (text, escape(name), escape(rev), fmt)) |