]> git.proxmox.com Git - mirror_frr.git/blame - yang/embedmodel.py
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / yang / embedmodel.py
CommitLineData
3a11599c 1#!/usr/bin/python3
47a3a827 2# SPDX-License-Identifier: NONE
3a11599c
DL
3#
4# YANG module to C wrapper
5# written 2018 by David Lamparter, placed in Public Domain.
6
261e7653
DL
7import sys
8import os
9import string
10import re
3a11599c
DL
11
12inname = sys.argv[1]
13outname = sys.argv[2]
14
261e7653 15outdir = os.path.dirname(os.path.abspath(outname))
05a13c2c 16try:
261e7653 17 os.makedirs(outdir)
05a13c2c
DL
18except FileExistsError:
19 pass
261e7653 20
3a11599c
DL
21# these are regexes to avoid a compile-time/host dependency on yang-tools
22# or python-yang. Cross-compiling FRR is already somewhat involved, no need
23# to make it even harder.
24
701a0192 25re_name = re.compile(r"\bmodule\s+([^\s]+)\s+\{")
26re_subname = re.compile(r"\bsubmodule\s+([^\s]+)\s+\{")
27re_mainname = re.compile(r"\bbelongs-to\s+([^\s]+)\s+\{")
28re_rev = re.compile(r"\brevision\s+([\d-]+)\s+\{")
3a11599c
DL
29
30
701a0192 31template = """/* autogenerated by embedmodel.py. DO NOT EDIT */
3a11599c
DL
32
33#include <zebra.h>
34#include "yang.h"
35
36static const char model[] =
37\t"%s";
38
39static struct yang_module_embed embed = {
40\t.mod_name = "%s",
41\t.mod_rev = "%s",
65de8bc8 42\t.sub_mod_name = "%s",
43\t.sub_mod_rev = "%s",
3a11599c
DL
44\t.data = model,
45\t.format = %s,
46};
47
48static void embed_register(void) __attribute__((_CONSTRUCTOR(2000)));
49static void embed_register(void)
50{
51\tyang_module_embed(&embed);
52}
701a0192 53"""
54
55passchars = set(string.printable) - set("\\'\"%\r\n\t\x0b\x0c")
56
3a11599c 57
3a11599c
DL
58def escapech(char):
59 if char in passchars:
60 return char
701a0192 61 if char == "\n":
62 return "\\n"
63 if char == "\t":
64 return "\\t"
65 if char in "\"\\'":
66 return "\\" + char
67 return "\\x%02x" % (ord(char))
68
69
3a11599c 70def escape(line):
701a0192 71 return "".join([escapech(i) for i in line])
72
3a11599c 73
701a0192 74with open(inname, "r") as fd:
3a11599c
DL
75 data = fd.read()
76
65de8bc8 77sub_name = ""
78rev = ""
79sub_rev = ""
80
3a11599c
DL
81# XML support isn't actively used currently, but it's here in case the need
82# arises. It does avoid the regex'ing.
701a0192 83if "<?xml" in data:
3a11599c 84 from xml.etree import ElementTree
701a0192 85
3a11599c 86 xml = ElementTree.fromstring(data)
701a0192 87 name = xml.get("name")
88 rev = xml.find("{urn:ietf:params:xml:ns:yang:yin:1}revision").get("date")
89 fmt = "LYS_YIN"
3a11599c 90else:
65de8bc8 91 search_name = re_name.search(data)
701a0192 92 if search_name:
93 name = search_name.group(1)
94 rev = re_rev.search(data).group(1)
95 else:
96 search_name = re_subname.search(data)
97 sub_name = search_name.group(1)
98 name = re_mainname.search(data).group(1)
99 sub_rev = re_rev.search(data).group(1)
3bb513c3 100 fmt = "LYS_IN_YANG"
3a11599c
DL
101
102if name is None or rev is None:
701a0192 103 raise ValueError("cannot determine YANG module name and revision")
3a11599c 104
701a0192 105lines = [escape(row) for row in data.split("\n")]
3a11599c
DL
106text = '\\n"\n\t"'.join(lines)
107
701a0192 108with open(outname, "w") as fd:
109 fd.write(
110 template
111 % (text, escape(name), escape(rev), escape(sub_name), escape(sub_rev), fmt)
112 )