forked from alliedtelesis/apteryx-xml
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pyang-cpaths.py
172 lines (143 loc) · 5.67 KB
/
pyang-cpaths.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
"""
Output paths in C header file format
"""
import optparse
from pyang import plugin, statements
def pyang_plugin_init():
plugin.register_plugin(PathPlugin())
class PathPlugin(plugin.PyangPlugin):
def add_opts(self, optparser):
optlist = [
optparse.make_option("--prepend-prefix",
action="store_true",
dest="prefix_default",
default=False,
help="Add a model prefix to the generated header file."),
]
g = optparser.add_option_group(
"generate-prefix option")
g.add_options(optlist)
def add_output_format(self, fmts):
self.multiple_modules = True
fmts['cpaths'] = self
def emit(self, ctx, modules, fd):
self.prefix_default = ctx.opts.prefix_default
self.prefix = {}
if (self.prefix_default):
for module in modules:
pref = module.search_one('prefix')
if pref is not None:
self.prefix[module] = pref.arg
for module in modules:
prefix = self.prefix.get(module)
children = [child for child in module.i_children]
for child in children:
print_node(child, module, prefix, fd, ctx)
fd.write('\n')
def mk_path_str(s, prefix, level=0, strip=0, fd=None):
# print('LEVEL: ' + str(level) + ' STRIP:' + str(strip) + ' ' + s.arg)
if s.keyword in ['choice', 'case']:
return mk_path_str(s.parent, prefix, level, strip)
if level > strip:
p = mk_path_str(s.parent, prefix, level - 1, strip)
if p != "":
return p + "/" + s.arg
return s.arg
if level == strip:
if level == 0 and prefix is not None:
return prefix + ":" + s.arg
return s.arg
else:
return ""
def mk_path_str_define(s, prefix, level):
if s.parent.keyword in ['module', 'submodule']:
if level == 0 and prefix is not None:
return "/" + prefix + "/" + s.arg
return "/" + s.arg
else:
p = mk_path_str_define(s.parent, prefix, level)
return p + "/" + s.arg
def print_node(node, module, prefix, fd, ctx, level=0, strip=0):
# print('TYPE:' + node.keyword + 'LEVEL:' + str(level) + 'STRIP:' + str(strip))
# No need to include these nodes
if node.keyword in ['rpc', 'notification']:
return
# Strip all nodes from the path at list items
if node.parent.keyword == 'list':
strip = level
# Skip over choice and case
if node.keyword in ['choice', 'case']:
for child in node.i_children:
print_node(child, module, prefix, fd, ctx, level, strip)
return
# Create path value
value = mk_path_str(node, prefix, level, strip, fd)
if strip == 0:
value = "/" + value
# Create define
if node.keyword in ['choice', 'case']:
pathstr = mk_path_str_define(node, prefix, level)
else:
pathstr = statements.mk_path_str(node, False)
if prefix is not None:
pathstr = '_' + prefix + pathstr
if node.keyword == 'container' or node.keyword == 'list':
define = pathstr[1:].upper().replace('/', '_').replace('-', '_') + '_PATH'
else:
define = pathstr[1:].upper().replace('/', '_').replace('-', '_')
# Description
descr = node.search_one('description')
if descr is not None:
descr.arg = descr.arg.replace('\r', ' ').replace('\n', ' ')
fd.write('/* ' + descr.arg + ' */\n')
# Ouput define
fd.write('#define ' + define + ' "' + value + '"\n')
ntype = node.search_one('type')
if ntype is not None and ntype.arg in module.i_typedefs:
typedef = module.i_typedefs[ntype.arg].copy()
typedef.arg = node.arg
ndescr = node.search_one('description')
if ndescr is not None:
tdescr = typedef.search_one('description')
if tdescr is None:
typedef.substmts.append(ndescr)
else:
tdescr.arg = ndescr.arg
typedef.i_config = node.i_config
if node.i_default is not None:
typedef.i_default = node.i_default
typedef.i_default_str = node.i_default_str
typedef.keyword = node.keyword
node = typedef
ntype = node.search_one('type')
if ntype is not None:
if ntype.arg == 'boolean':
fd.write('#define ' + define + '_TRUE "true"\n')
fd.write('#define ' + define + '_FALSE "false"\n')
if ntype.arg == 'enumeration':
count = 0
for enum in ntype.substmts:
name = enum.arg.replace('-', '_').upper()
val = enum.search_one('value')
if val is not None:
fd.write('#define ' + define + '_' + name + ' ' + str(val.arg) + '\n')
try:
val_int = int(val.arg)
except ValueError:
val_int = None
if val_int is not None:
count = val_int
else:
fd.write('#define ' + define + '_' + name + ' ' + str(count) + '\n')
count = count + 1
# Default value
def_val = node.search_one('default')
if def_val is not None:
if ntype is not None and 'int' in ntype.arg:
fd.write('#define ' + define + '_DEFAULT ' + def_val.arg + '\n')
else:
fd.write('#define ' + define + '_DEFAULT "' + def_val.arg + '"\n')
# Process children
if hasattr(node, 'i_children'):
for child in node.i_children:
print_node(child, module, prefix, fd, ctx, level + 1, strip)