github.com/osrg/gobgp@v2.0.0+incompatible/tools/pyang_plugins/bgpyang2golang.py (about) 1 # Copyright (C) 2014,2015 Nippon Telegraph and Telephone Corporation. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 # implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 16 from __future__ import print_function 17 18 import sys 19 from collections import namedtuple 20 21 from pyang import plugin 22 23 _COPYRIGHT_NOTICE = """ 24 // DO NOT EDIT 25 // generated by pyang using OpenConfig https://github.com/openconfig/public 26 // 27 // Copyright (C) 2014-2016 Nippon Telegraph and Telephone Corporation. 28 // 29 // Licensed under the Apache License, Version 2.0 (the "License"); 30 // you may not use this file except in compliance with the License. 31 // You may obtain a copy of the License at 32 // 33 // http://www.apache.org/licenses/LICENSE-2.0 34 // 35 // Unless required by applicable law or agreed to in writing, software 36 // distributed under the License is distributed on an "AS IS" BASIS, 37 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 38 // implied. 39 // See the License for the specific language governing permissions and 40 // limitations under the License. 41 42 """ 43 44 EQUAL_TYPE_LEAF = 0 45 EQUAL_TYPE_ARRAY = 1 46 EQUAL_TYPE_MAP = 2 47 EQUAL_TYPE_CONTAINER = 3 48 49 50 def pyang_plugin_init(): 51 plugin.register_plugin(GolangPlugin()) 52 53 54 class GolangPlugin(plugin.PyangPlugin): 55 56 def __init__(self, name=None): 57 super(GolangPlugin, self).__init__(name=name) 58 self.multiple_modules = True 59 60 def add_output_format(self, fmts): 61 fmts['golang'] = self 62 63 def emit(self, ctx, modules, fd): 64 ctx.golang_identity_map = {} 65 ctx.golang_typedef_map = {} 66 ctx.golang_struct_def = [] 67 ctx.golang_struct_names = {} 68 69 ctx.emitted_type_names = {} 70 71 ctx.prefix_rel = {} 72 ctx.module_deps = [] 73 for m in modules: 74 check_module_deps(ctx, m) 75 76 # visit yang statements 77 visit_modules(ctx) 78 79 # emit bgp_configs 80 emit_go(ctx, fd) 81 82 83 def visit_modules(ctx): 84 # visit typedef and identity 85 for mod in ctx.module_deps: 86 visit_typedef(ctx, mod) 87 visit_identity(ctx, mod) 88 89 # visit container 90 for mod in ctx.module_deps: 91 visit_children(ctx, mod, mod.i_children) 92 93 94 def emit_go(ctx, fd): 95 ctx.golang_struct_def.reverse() 96 done = set() 97 98 # emit 99 generate_header(fd) 100 generate_common_functions(fd) 101 102 for mod in ctx.module_deps: 103 if mod not in _module_excluded: 104 emit_typedef(ctx, mod, fd) 105 emit_identity(ctx, mod, fd) 106 107 for struct in ctx.golang_struct_def: 108 struct_name = struct.uniq_name 109 if struct_name in done: 110 continue 111 emit_class_def(ctx, struct, struct_name, struct.module_prefix, fd) 112 done.add(struct_name) 113 114 115 def check_module_deps(ctx, mod): 116 own_prefix = mod.i_prefix 117 for k, v in mod.i_prefixes.items(): 118 mod = ctx.get_module(v[0]) 119 if mod is None: 120 continue 121 122 if mod.i_prefix != own_prefix: 123 check_module_deps(ctx, mod) 124 125 ctx.prefix_rel[mod.i_prefix] = k 126 if (mod not in ctx.module_deps 127 and mod.i_modulename not in _module_excluded): 128 ctx.module_deps.append(mod) 129 130 131 def dig_leafref(type_obj): 132 reftype = type_obj.i_type_spec.i_target_node.search_one('type') 133 if is_leafref(reftype): 134 return dig_leafref(reftype) 135 else: 136 return reftype 137 138 139 def emit_class_def(ctx, stmt, struct_name, prefix, fd): 140 if len(stmt.i_children) == 1 and is_list(stmt.i_children[0]): 141 return 142 143 print('// struct for container %s:%s.' % (prefix, stmt.arg), file=fd) 144 emit_description(stmt, fd) 145 print('type %s struct {' % convert_to_golang(struct_name), file=fd) 146 147 equal_elems = [] 148 149 for child in stmt.i_children: 150 151 if child.path in _path_exclude: 152 continue 153 154 container_or_list_name = child.uniq_name 155 val_name_go = convert_to_golang(child.arg) 156 child_prefix = get_orig_prefix(child.i_orig_module) 157 tag_name = child.uniq_name.lower() 158 equal_type = EQUAL_TYPE_LEAF 159 equal_data = None 160 print('// original -> %s:%s' % (child_prefix, container_or_list_name), file=fd) 161 162 # case leaf 163 if is_leaf(child): 164 type_obj = child.search_one('type') 165 type_name = type_obj.arg 166 167 # case identityref 168 if is_identityref(type_obj): 169 emit_type_name = convert_to_golang(type_obj.search_one('base').arg.split(':')[-1]) 170 171 # case leafref 172 elif is_leafref(type_obj): 173 if type_obj.search_one('path').arg.startswith('../config'): 174 continue 175 t = dig_leafref(type_obj) 176 if is_translation_required(t): 177 print('// %s:%s\'s original type is %s.' % (child_prefix, container_or_list_name, t.arg), file=fd) 178 emit_type_name = translate_type(t.arg) 179 elif is_identityref(t): 180 emit_type_name = convert_to_golang(t.search_one('base').arg.split(':')[-1]) 181 else: 182 emit_type_name = t.arg 183 184 # case embeded enumeration 185 elif is_enum(type_obj): 186 emit_type_name = val_name_go 187 188 # case translation required 189 elif is_translation_required(type_obj): 190 print('// %s:%s\'s original type is %s.' % (child_prefix, container_or_list_name, type_name), file=fd) 191 emit_type_name = translate_type(type_name) 192 193 # case other primitives 194 elif is_builtin_type(type_obj): 195 emit_type_name = type_name 196 197 # default 198 else: 199 base_module = type_obj.i_orig_module.i_prefix 200 t = lookup_typedef(ctx, base_module, type_name) 201 # print(t.golang_name, file=sys.stderr) 202 emit_type_name = t.golang_name 203 204 # case 'case' 205 if is_case(child): 206 continue 207 208 if is_choice(child) and is_enum_choice(child): 209 emit_type_name = val_name_go 210 211 # case leaflist 212 if is_leaflist(child): 213 type_obj = child.search_one('type') 214 type_name = type_obj.arg 215 val_name_go = val_name_go + 'List' 216 tag_name += '-list' 217 equal_type = EQUAL_TYPE_ARRAY 218 219 # case leafref 220 if is_leafref(type_obj): 221 t = dig_leafref(type_obj) 222 emit_type_name = '[]' + t.arg 223 224 # case identityref 225 elif is_identityref(type_obj): 226 emit_type_name = '[]' + convert_to_golang(type_obj.search_one('base').arg.split(':')[-1]) 227 228 # case translation required 229 elif is_translation_required(type_obj): 230 print('// original type is list of %s' % type_obj.arg, file=fd) 231 emit_type_name = '[]' + translate_type(type_name) 232 233 # case other primitives 234 elif is_builtin_type(type_obj): 235 emit_type_name = '[]' + type_name 236 237 # default 238 else: 239 base_module = type_obj.i_orig_module.i_prefix 240 t = lookup_typedef(ctx, base_module, type_name) 241 emit_type_name = '[]' + t.golang_name 242 243 # case container 244 elif is_container(child) or (is_choice(child) and not is_enum_choice(child)): 245 key = child_prefix + ':' + container_or_list_name 246 t = ctx.golang_struct_names[key] 247 val_name_go = t.golang_name 248 if len(t.i_children) == 1 and is_list(t.i_children[0]): 249 c = t.i_children[0] 250 emit_type_name = '[]' + c.golang_name 251 equal_type = EQUAL_TYPE_MAP 252 equal_data = c.search_one('key').arg 253 leaf = c.search_one('leaf').search_one('type') 254 if leaf.arg == 'leafref' and leaf.search_one('path').arg.startswith('../config'): 255 equal_data = 'config.' + equal_data 256 else: 257 emit_type_name = t.golang_name 258 equal_type = EQUAL_TYPE_CONTAINER 259 260 # case list 261 elif is_list(child): 262 key = child_prefix + ':' + container_or_list_name 263 t = ctx.golang_struct_names[key] 264 val_name_go = val_name_go + 'List' 265 tag_name += '-list' 266 emit_type_name = '[]' + t.golang_name 267 equal_type = EQUAL_TYPE_MAP 268 equal_data = child.search_one('key').arg 269 270 if is_container(child): 271 name = emit_type_name 272 if name.startswith(convert_to_golang(struct_name)) and name.endswith("Config"): 273 tag_name = 'config' 274 val_name_go = 'Config' 275 elif name.startswith(convert_to_golang(struct_name)) and name.endswith("State"): 276 tag_name = 'state' 277 val_name_go = 'State' 278 279 emit_description(child, fd=fd) 280 print(' {0}\t{1} `mapstructure:"{2}" json:"{2},omitempty"`'.format(val_name_go, emit_type_name, tag_name), file=fd) 281 282 equal_elems.append((val_name_go, emit_type_name, equal_type, equal_data)) 283 284 print('}', file=fd) 285 286 if not struct_name.endswith('state'): 287 print('func (lhs *{0}) Equal(rhs *{0}) bool {{'.format(convert_to_golang(struct_name)), file=fd) 288 print('if lhs == nil || rhs == nil {', file=fd) 289 print('return false', file=fd) 290 print('}', file=fd) 291 292 for val_name, type_name, typ, elem in equal_elems: 293 if val_name == 'State': 294 continue 295 if typ == EQUAL_TYPE_LEAF: 296 if type_name == '[]byte': 297 print('if bytes.Compare(lhs.{0}, rhs.{0}) != 0 {{'.format(val_name), file=fd) 298 else: 299 print('if lhs.{0} != rhs.{0} {{'.format(val_name), file=fd) 300 print('return false', file=fd) 301 print('}', file=fd) 302 elif typ == EQUAL_TYPE_CONTAINER: 303 print('if !lhs.{0}.Equal(&(rhs.{0})) {{'.format(val_name), file=fd) 304 print('return false', file=fd) 305 print('}', file=fd) 306 elif typ == EQUAL_TYPE_ARRAY: 307 print('if len(lhs.{0}) != len(rhs.{0}) {{'.format(val_name), file=fd) 308 print('return false', file=fd) 309 print('}', file=fd) 310 print('for idx, l := range lhs.{0} {{'.format(val_name), file=fd) 311 if type_name == '[][]byte': 312 print('if bytes.Compare(l, rhs.{0}[idx]) != 0 {{'.format(val_name), file=fd) 313 else: 314 print('if l != rhs.{0}[idx] {{'.format(val_name), file=fd) 315 print('return false', file=fd) 316 print('}', file=fd) 317 print('}', file=fd) 318 elif typ == EQUAL_TYPE_MAP: 319 print('if len(lhs.{0}) != len(rhs.{0}) {{'.format(val_name), file=fd) 320 print('return false', file=fd) 321 print('}', file=fd) 322 print('{', file=fd) 323 print('lmap := make(map[string]*{0})'.format(type_name[2:]), file=fd) 324 print('for i, l := range lhs.{0} {{'.format(val_name), file=fd) 325 print('lmap[mapkey(i, string({0}))] = &lhs.{1}[i]'.format(' + '.join('l.{0}'.format(convert_to_golang(v)) for v in elem.split(' ')), val_name), file=fd) 326 print('}', file=fd) 327 print('for i, r := range rhs.{0} {{'.format(val_name), file=fd) 328 print('if l, y := lmap[mapkey(i, string({0}))]; !y {{'.format('+'.join('r.{0}'.format(convert_to_golang(v)) for v in elem.split(' '))), file=fd) 329 print('return false', file=fd) 330 print('} else if !r.Equal(l) {', file=fd) 331 print('return false', file=fd) 332 print('}', file=fd) 333 print('}', file=fd) 334 print('}', file=fd) 335 else: 336 sys.stderr.write("invalid equal type %s", typ) 337 338 print('return true', file=fd) 339 print('}', file=fd) 340 341 342 def get_orig_prefix(mod): 343 orig = mod.i_orig_module 344 if orig: 345 get_orig_prefix(orig) 346 else: 347 return mod.i_prefix 348 349 350 def get_path(c): 351 path = '' 352 if c.parent is not None: 353 p = '' 354 if hasattr(c, 'i_module'): 355 mod = c.i_module 356 prefix = mod.search_one('prefix') 357 if prefix: 358 p = prefix.arg + ":" 359 360 path = get_path(c.parent) + "/" + p + c.arg 361 return path 362 363 364 # define container embedded enums 365 def define_enum(ctx, mod, c): 366 prefix = mod.i_prefix 367 c.path = get_path(c) 368 c.golang_name = convert_to_golang(c.arg) 369 if prefix in ctx.golang_typedef_map: 370 ctx.golang_typedef_map[prefix][c.arg] = c 371 else: 372 ctx.golang_typedef_map[prefix] = {c.arg: c} 373 374 375 def visit_children(ctx, mod, children): 376 for c in children: 377 if is_case(c): 378 prefix = get_orig_prefix(c.parent.i_orig_module) 379 c.i_orig_module = c.parent.i_orig_module 380 else: 381 prefix = get_orig_prefix(c.i_orig_module) 382 383 c.uniq_name = c.arg 384 if c.arg == 'config': 385 c.uniq_name = c.parent.uniq_name + '-config' 386 387 elif c.arg == 'state': 388 c.uniq_name = c.parent.uniq_name + '-state' 389 390 elif c.arg == 'graceful-restart' and prefix == 'bgp-mp': 391 c.uniq_name = 'mp-graceful-restart' 392 393 if is_leaf(c) and is_enum(c.search_one('type')): 394 define_enum(ctx, mod, c) 395 396 elif is_list(c) or is_container(c) or is_choice(c): 397 c.golang_name = convert_to_golang(c.uniq_name) 398 399 if is_choice(c): 400 picks = pickup_choice(c) 401 c.i_children = picks 402 if is_enum_choice(c): 403 define_enum(ctx, mod, c) 404 continue 405 406 prefix_name = prefix + ':' + c.uniq_name 407 if prefix_name in ctx.golang_struct_names: 408 ext_c = ctx.golang_struct_names.get(prefix_name) 409 ext_c_child_count = len(getattr(ext_c, "i_children")) 410 current_c_child_count = len(getattr(c, "i_children")) 411 if ext_c_child_count < current_c_child_count: 412 c.module_prefix = prefix 413 ctx.golang_struct_names[prefix_name] = c 414 idx = ctx.golang_struct_def.index(ext_c) 415 ctx.golang_struct_def[idx] = c 416 else: 417 c.module_prefix = prefix 418 ctx.golang_struct_names[prefix_name] = c 419 ctx.golang_struct_def.append(c) 420 421 c.path = get_path(c) 422 # print(c.path, file=sys.stderr) 423 if hasattr(c, 'i_children'): 424 visit_children(ctx, mod, c.i_children) 425 426 427 def pickup_choice(c): 428 element = [] 429 for child in c.i_children: 430 if is_case(child): 431 element = element + child.i_children 432 433 return element 434 435 436 def get_type_spec(stmt): 437 for s in stmt.substmts: 438 if hasattr(s, 'i_type_spec'): 439 return s.i_type_spec.name 440 441 return None 442 443 444 def visit_typedef(ctx, mod): 445 prefix = mod.i_prefix 446 child_map = {} 447 for stmt in mod.substmts: 448 if is_typedef(stmt): 449 stmt.path = get_path(stmt) 450 # print('stmt.path = "%s"' % stmt.path, file=sys.stderr) 451 name = stmt.arg 452 stmt.golang_name = convert_to_golang(name) 453 # print('stmt.golang_name = "%s"' % stmt.golang_name, file=sys.stderr) 454 child_map[name] = stmt 455 456 ctx.golang_typedef_map[prefix] = child_map 457 # print('ctx.golang_typedef_map["%s"] = %s' % (prefix, child_map), file=sys.stderr) 458 prefix_rel = ctx.prefix_rel[prefix] 459 ctx.golang_typedef_map[prefix_rel] = child_map 460 # print('ctx.golang_typedef_map["%s"] = %s' % (prefix_rel, child_map)), file=sys.stderr) 461 462 463 def visit_identity(ctx, mod): 464 prefix = mod.i_prefix 465 child_map = {} 466 for stmt in mod.substmts: 467 if is_identity(stmt): 468 name = stmt.arg 469 stmt.golang_name = convert_to_golang(name) 470 # print('stmt.golang_name = "%s"' % stmt.golang_name, file=sys.stderr) 471 child_map[name] = stmt 472 473 base = stmt.search_one('base') 474 if base: 475 base_name = base.arg 476 if ':' in base_name: 477 base_prefix, base_name = base_name.split(':', 1) 478 if base_prefix in ctx.golang_identity_map: 479 ctx.golang_identity_map[base_prefix][base_name].substmts.append(stmt) 480 else: 481 child_map[base_name].substmts.append(stmt) 482 483 ctx.golang_identity_map[prefix] = child_map 484 # print('ctx.golang_identity_map["%s"] = %s\n' % (prefix, child_map), file=sys.stderr) 485 prefix_rel = ctx.prefix_rel[prefix] 486 ctx.golang_identity_map[prefix_rel] = child_map 487 # print('ctx.golang_identity_map["%s"] = %s\n' % (prefix_rel, child_map), file=sys.stderr) 488 489 490 def lookup_identity(ctx, default_prefix, identity_name): 491 result = lookup(ctx.golang_identity_map, default_prefix, identity_name) 492 return result 493 494 495 def lookup_typedef(ctx, default_prefix, type_name): 496 result = lookup(ctx.golang_typedef_map, default_prefix, type_name) 497 return result 498 499 500 def lookup(basemap, default_prefix, key): 501 if ':' in key: 502 pref, name = key.split(':') 503 else: 504 pref = default_prefix 505 name = key 506 507 if pref in basemap: 508 return basemap[pref].get(name, None) 509 else: 510 return key 511 512 513 def emit_description(stmt, fd): 514 desc = stmt.search_one('description') 515 if desc is None: 516 return None 517 desc_words = desc.arg if desc.arg.endswith('.') else desc.arg + '.' 518 print('// %s' % desc_words.replace('\n', '\n// '), file=fd) 519 520 521 def emit_enum(prefix, name, stmt, substmts, fd): 522 type_name_org = name 523 type_name = stmt.golang_name 524 print('// typedef for identity %s:%s.' % (prefix, type_name_org), file=fd) 525 emit_description(stmt, fd) 526 print('type %s string' % type_name, file=fd) 527 528 const_prefix = convert_const_prefix(type_name_org) 529 print('const (', file=fd) 530 m = {} 531 532 if is_choice(stmt) and is_enum_choice(stmt): 533 n = namedtuple('Statement', ['arg']) 534 n.arg = 'none' 535 substmts = [n] + substmts 536 537 for sub in substmts: 538 enum_name = '%s_%s' % (const_prefix, convert_const_prefix(sub.arg)) 539 m[sub.arg.lower()] = enum_name 540 print(' %s %s = "%s"' % (enum_name, type_name, sub.arg.lower()), file=fd) 541 print(')\n', file=fd) 542 543 print('var %sToIntMap = map[%s]int {' % (type_name, type_name), file=fd) 544 for i, sub in enumerate(substmts): 545 enum_name = '%s_%s' % (const_prefix, convert_const_prefix(sub.arg)) 546 print(' %s: %d,' % (enum_name, i), file=fd) 547 print('}\n', file=fd) 548 549 print('var IntTo%sMap = map[int]%s {' % (type_name, type_name), file=fd) 550 for i, sub in enumerate(substmts): 551 enum_name = '%s_%s' % (const_prefix, convert_const_prefix(sub.arg)) 552 print(' %d: %s,' % (i, enum_name), file=fd) 553 print('}\n', file=fd) 554 555 print('func (v %s) Validate() error {' % type_name, file=fd) 556 print('if _, ok := %sToIntMap[v]; !ok {' % type_name, file=fd) 557 print('return fmt.Errorf("invalid %s: %%s", v)' % type_name, file=fd) 558 print('}', file=fd) 559 print('return nil', file=fd) 560 print('}\n', file=fd) 561 562 if stmt.search_one('default'): 563 default = stmt.search_one('default') 564 print('func (v %s) Default() %s {' % (type_name, type_name), file=fd) 565 print('return %s' % m[default.arg.lower()], file=fd) 566 print('}\n', file=fd) 567 568 print('func (v %s) DefaultAsNeeded() %s {' % (type_name, type_name), file=fd) 569 print(' if string(v) == "" {', file=fd) 570 print(' return v.Default()', file=fd) 571 print('}', file=fd) 572 print(' return v', file=fd) 573 print('}', file=fd) 574 575 print('func (v %s) ToInt() int {' % type_name, file=fd) 576 print('_v := v.DefaultAsNeeded()') 577 print('i, ok := %sToIntMap[_v]' % type_name, file=fd) 578 579 else: 580 print('func (v %s) ToInt() int {' % type_name, file=fd) 581 print('i, ok := %sToIntMap[v]' % type_name, file=fd) 582 print('if !ok {', file=fd) 583 print('return -1', file=fd) 584 print('}', file=fd) 585 print('return i', file=fd) 586 print('}', file=fd) 587 588 589 def emit_typedef(ctx, mod, fd): 590 prefix = mod.i_prefix 591 t_map = ctx.golang_typedef_map[prefix] 592 for name, stmt in t_map.items(): 593 if stmt.path in _typedef_exclude: 594 continue 595 596 # skip identityref type because currently skip identity 597 if get_type_spec(stmt) == 'identityref': 598 continue 599 600 type_name_org = name 601 type_name = stmt.golang_name 602 if type_name in ctx.emitted_type_names: 603 print("warning %s: %s has already been emitted from %s." 604 % (prefix + ":" + type_name_org, type_name_org, ctx.emitted_type_names[type_name]), 605 file=sys.stderr) 606 continue 607 608 ctx.emitted_type_names[type_name] = prefix + ":" + type_name_org 609 610 t = stmt.search_one('type') 611 if not t and is_choice(stmt): 612 emit_enum(prefix, type_name_org, stmt, stmt.i_children, fd) 613 elif is_enum(t): 614 emit_enum(prefix, type_name_org, stmt, t.substmts, fd) 615 elif is_union(t): 616 print('// typedef for typedef %s:%s.' % (prefix, type_name_org), file=fd) 617 emit_description(t, fd) 618 print('type %s string' % type_name, file=fd) 619 else: 620 if is_leafref(t): 621 t = dig_leafref(t) 622 623 print('// typedef for typedef %s:%s.' % (prefix, type_name_org), file=fd) 624 if is_builtin_type(t): 625 emit_description(t, fd) 626 print('type %s %s' % (type_name, t.arg), file=fd) 627 elif is_translation_required(t): 628 print('// %s:%s\'s original type is %s.' % (prefix, name, t.arg), file=fd) 629 emit_description(t, fd) 630 print('type %s %s' % (type_name, translate_type(t.arg)), file=fd) 631 else: 632 m = ctx.golang_typedef_map 633 for k in t.arg.split(':'): 634 m = m[k] 635 emit_description(t, fd) 636 print('type %s %s' % (type_name, m.golang_name), file=fd) 637 638 639 def emit_identity(ctx, mod, fd): 640 prefix = mod.i_prefix 641 i_map = ctx.golang_identity_map[prefix] 642 for name, stmt in i_map.items(): 643 enums = stmt.search('identity') 644 if len(enums) > 0: 645 emit_enum(prefix, name, stmt, enums, fd) 646 647 648 def is_reference(s): 649 return s.arg in ['leafref', 'identityref'] 650 651 652 def is_leafref(s): 653 return s.arg in ['leafref'] 654 655 656 def is_identityref(s): 657 return s.arg in ['identityref'] 658 659 660 def is_enum(s): 661 return s.arg in ['enumeration'] 662 663 664 def is_union(s): 665 return s.arg in ['union'] 666 667 668 def is_typedef(s): 669 return s.keyword in ['typedef'] 670 671 672 def is_identity(s): 673 return s.keyword in ['identity'] 674 675 676 def is_leaf(s): 677 return s.keyword in ['leaf'] 678 679 680 def is_leaflist(s): 681 return s.keyword in ['leaf-list'] 682 683 684 def is_list(s): 685 return s.keyword in ['list'] 686 687 688 def is_container(s): 689 return s.keyword in ['container'] 690 691 692 def is_case(s): 693 return s.keyword in ['case'] 694 695 696 def is_choice(s): 697 return s.keyword in ['choice'] 698 699 700 def is_enum_choice(s): 701 return all(e.search_one('type').arg in _type_enum_case for e in s.i_children) 702 703 704 _type_enum_case = [ 705 'empty', 706 ] 707 708 709 def is_builtin_type(t): 710 return t.arg in _type_builtin 711 712 713 def is_translation_required(t): 714 return t.arg in list(_type_translation_map.keys()) 715 716 717 _type_translation_map = { 718 'union': 'string', 719 'decimal64': 'float64', 720 'boolean': 'bool', 721 'empty': 'bool', 722 'inet:ip-address': 'string', 723 'inet:ip-prefix': 'string', 724 'inet:ipv4-address': 'string', 725 'inet:as-number': 'uint32', 726 'bgp-set-community-option-type': 'string', 727 'inet:port-number': 'uint16', 728 'yang:timeticks': 'int64', 729 'ptypes:install-protocol-type': 'string', 730 'binary': '[]byte', 731 'route-family': 'bgp.RouteFamily', 732 'bgp-capability': 'bgp.ParameterCapabilityInterface', 733 'bgp-open-message': '*bgp.BGPMessage', 734 } 735 736 737 _type_builtin = [ 738 "union", 739 "int8", 740 "int16", 741 "int32", 742 "int64", 743 "string", 744 "uint8", 745 "uint16", 746 "uint32", 747 "uint64", 748 ] 749 750 751 _module_excluded = [ 752 "ietf-inet-types", 753 "ietf-yang-types", 754 ] 755 756 _path_exclude = [ 757 "/rpol:routing-policy/rpol:defined-sets/rpol:neighbor-sets/rpol:neighbor-set/rpol:neighbor", 758 "/rpol:routing-policy/rpol:defined-sets/bgp-pol:bgp-defined-sets/bgp-pol:community-sets/bgp-pol:community-set/bgp-pol:community-member", 759 "/rpol:routing-policy/rpol:defined-sets/bgp-pol:bgp-defined-sets/bgp-pol:ext-community-sets/bgp-pol:ext-community-set/bgp-pol:ext-community-member", 760 "/rpol:routing-policy/rpol:defined-sets/bgp-pol:bgp-defined-sets/bgp-pol:as-path-sets/bgp-pol:as-path-set/bgp-pol:as-path-set-member", 761 ] 762 763 _typedef_exclude = [ 764 "/gobgp:bgp-capability", 765 "/gobgp:bgp-open-message", 766 ] 767 768 769 def generate_header(fd): 770 print(_COPYRIGHT_NOTICE, file=fd) 771 print('package config', file=fd) 772 print('', file=fd) 773 print('import (', file=fd) 774 print('"fmt"', file=fd) 775 print('', file=fd) 776 print('"github.com/osrg/gobgp/pkg/packet/bgp"', file=fd) 777 print(')', file=fd) 778 print('', file=fd) 779 780 781 def generate_common_functions(fd): 782 print('func mapkey(index int, name string) string {', file=fd) 783 print('if name != "" {', file=fd) 784 print('return name', file=fd) 785 print('}', file=fd) 786 print('return fmt.Sprintf("%v", index)', file=fd) 787 print('}', file=fd) 788 789 790 def translate_type(key): 791 if key in _type_translation_map.keys(): 792 return _type_translation_map[key] 793 else: 794 return key 795 796 797 # 'hoge-hoge' -> 'HogeHoge' 798 def convert_to_golang(type_string): 799 a = type_string.split('.') 800 return '.'.join(''.join(t.capitalize() for t in x.split('-')) for x in a) 801 802 803 # 'hoge-hoge' -> 'HOGE_HOGE' 804 def convert_const_prefix(type_string): 805 return type_string.replace('-', '_').upper() 806 807 808 def chop_suf(s, suf): 809 if not s.endswith(suf): 810 return s 811 return s[:-len(suf)]