mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-25 08:16:38 +00:00
274 lines
8.5 KiB
Python
Executable File
274 lines
8.5 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import re
|
|
import sys
|
|
import os
|
|
from pprint import pformat, pprint
|
|
|
|
|
|
class DEFUN(object):
|
|
|
|
def __init__(self, lines):
|
|
# name, name_cmd, command_string, help_strings, guts):
|
|
self.name = None
|
|
self.name_cmd = None
|
|
self.command_string = None
|
|
self.help_strings = []
|
|
self.guts = []
|
|
self.aliases = []
|
|
|
|
'''
|
|
DEFUN (no_bgp_maxmed_onstartup,
|
|
no_bgp_maxmed_onstartup_cmd,
|
|
"no bgp max-med on-startup",
|
|
NO_STR
|
|
BGP_STR
|
|
"Advertise routes with max-med\n"
|
|
"Effective on a startup\n")
|
|
|
|
'''
|
|
state = 'HEADER'
|
|
for (line_number, line) in enumerate(lines):
|
|
|
|
if state == 'HEADER':
|
|
if line_number == 0:
|
|
re_name = re.search('DEFUN \((.*),', line.strip())
|
|
self.name = re_name.group(1)
|
|
|
|
elif line_number == 1:
|
|
self.name_cmd = line.strip()[0:-1] # chop the trailing comma
|
|
|
|
elif line_number == 2:
|
|
self.command_string = line
|
|
state = 'HELP'
|
|
|
|
elif state == 'HELP':
|
|
if line.strip() == '{':
|
|
self.guts.append(line)
|
|
state = 'BODY'
|
|
else:
|
|
self.help_strings.append(line)
|
|
|
|
elif state == 'BODY':
|
|
if line.rstrip() == '}':
|
|
self.guts.append(line)
|
|
state = None
|
|
else:
|
|
self.guts.append(line)
|
|
|
|
else:
|
|
raise Exception("invalid state %s" % state)
|
|
|
|
# print "%d %7s: %s" % (line_number, state, line.rstrip())
|
|
|
|
assert self.command_string, "No command string for\n%s" % pformat(lines)
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
def dump(self):
|
|
lines = []
|
|
|
|
if self.aliases:
|
|
lines.append("/*\n")
|
|
lines.append(" * CHECK ME - The following ALIASes need to be implemented in this DEFUN\n")
|
|
|
|
for alias in self.aliases:
|
|
lines.append(" * %s\n" % alias.command_string.strip())
|
|
for line in alias.help_strings:
|
|
lines.append(" * %s\n" % line)
|
|
lines.append(" *\n")
|
|
|
|
lines.append(" */\n")
|
|
|
|
lines.append("DEFUN (%s,\n" % self.name)
|
|
lines.append(" %s,\n" % self.name_cmd)
|
|
lines.append(self.command_string)
|
|
lines.extend(self.help_strings)
|
|
lines.extend(self.guts)
|
|
return ''.join(lines)
|
|
|
|
|
|
class ALIAS(object):
|
|
|
|
def __init__(self, lines):
|
|
self.name = None
|
|
self.name_cmd = None
|
|
self.command_string = None
|
|
self.help_strings = []
|
|
|
|
'''
|
|
ALIAS (no_bgp_maxmed_onstartup,
|
|
no_bgp_maxmed_onstartup_period_cmd,
|
|
"no bgp max-med on-startup <5-86400>",
|
|
NO_STR
|
|
BGP_STR
|
|
"Advertise routes with max-med\n"
|
|
"Effective on a startup\n"
|
|
"Time (seconds) period for max-med\n")
|
|
'''
|
|
state = 'HEADER'
|
|
for (line_number, line) in enumerate(lines):
|
|
|
|
if state == 'HEADER':
|
|
if line_number == 0:
|
|
re_name = re.search('ALIAS \((.*),', line)
|
|
|
|
try:
|
|
self.name = re_name.group(1)
|
|
except AttributeError:
|
|
pprint(lines)
|
|
raise
|
|
|
|
elif line_number == 1:
|
|
self.name_cmd = line.strip()[0:-1] # chop the trailing comma
|
|
|
|
elif line_number == 2:
|
|
self.command_string = line
|
|
state = 'HELP'
|
|
|
|
elif state == 'HELP':
|
|
if line.strip() == '{':
|
|
raise Exception("should not see { in an ALIAS")
|
|
else:
|
|
line = line.strip()
|
|
if line.endswith(')'):
|
|
line = line[0:-1] # strip the trailing )
|
|
self.help_strings.append(line)
|
|
|
|
else:
|
|
raise Exception("invalid state %s" % state)
|
|
|
|
assert self.command_string, "No command string for\n%s" % pformat(lines)
|
|
|
|
def __str__(self):
|
|
return self.name_cmd
|
|
|
|
|
|
def alias_destroy(filename):
|
|
lines = []
|
|
defuns = {}
|
|
aliases = {}
|
|
|
|
with open(filename, 'r') as fh:
|
|
state = None
|
|
defun_lines = []
|
|
alias_lines = []
|
|
|
|
for (line_number, line) in enumerate(fh.readlines()):
|
|
|
|
if state is None:
|
|
if line.startswith('DEFUN ('):
|
|
assert line.count(',') == 1, "%d: Too many commas in\n%s" % (line_number, line)
|
|
defun_lines.append(line)
|
|
state = 'DEFUN_HEADER'
|
|
|
|
elif line.startswith('ALIAS ('):
|
|
assert line.count(',') == 1, "%d: Too many commas in\n%s" % (line_number, line)
|
|
alias_lines.append(line)
|
|
state = 'ALIAS_HEADER'
|
|
|
|
elif state == 'DEFUN_HEADER':
|
|
defun_lines.append(line)
|
|
|
|
if line.startswith('DEFUN'):
|
|
raise Exception("ERROR on line %d, found DEFUN inside DEFUN" % line_number)
|
|
|
|
elif line.startswith('ALIAS'):
|
|
raise Exception("ERROR on line %d, found ALIAS inside DEFUN" % line_number)
|
|
|
|
elif line.strip() == '{':
|
|
state = 'DEFUN_BODY'
|
|
|
|
elif state == 'ALIAS_HEADER':
|
|
alias_lines.append(line)
|
|
|
|
if line.startswith('ALIAS'):
|
|
raise Exception("ERROR on line %d, found ALIAS inside ALIAS" % line_number)
|
|
|
|
elif line.startswith('DEFUN'):
|
|
raise Exception("ERROR on line %d, found DEFUN inside ALIAS" % line_number)
|
|
|
|
if line.rstrip().endswith(')'):
|
|
new_alias = ALIAS(alias_lines)
|
|
aliases[new_alias.name_cmd] = new_alias
|
|
state = None
|
|
alias_lines = []
|
|
|
|
elif state == 'DEFUN_BODY':
|
|
defun_lines.append(line)
|
|
|
|
if line.rstrip() == '}':
|
|
new_defun = DEFUN(defun_lines)
|
|
defuns[new_defun.name] = new_defun
|
|
state = None
|
|
defun_lines = []
|
|
|
|
# uncomment to debug state machine
|
|
print "%5d %12s: %s" % (line_number, state, line.rstrip())
|
|
|
|
lines.append(line)
|
|
|
|
|
|
# At this point we know all of the aliases and all of the tokens
|
|
# Assign each ALIAS to its parent DEFUN
|
|
for alias in aliases.itervalues():
|
|
defun = defuns.get(alias.name)
|
|
assert defun, "Could not find DEFUN for %s" % alias
|
|
defun.aliases.append(alias)
|
|
|
|
# Now write the file but:
|
|
# - do not write any ALIASes
|
|
# - do not write the install_element for any ALIASes
|
|
# - when you write the DEFUN include a comment that contains the ALIAS command strings it needs to cover
|
|
with open(filename, 'w') as fh:
|
|
state = None
|
|
|
|
for line in lines:
|
|
|
|
if state is None:
|
|
if line.startswith('DEFUN ('):
|
|
state = 'DEFUN_HEADER'
|
|
re_name = re.search('DEFUN \((.*),', line.strip())
|
|
name = re_name.group(1)
|
|
defun = defuns.get(name)
|
|
fh.write(defun.dump())
|
|
|
|
elif line.startswith('ALIAS ('):
|
|
state = 'ALIAS_HEADER'
|
|
|
|
else:
|
|
if 'install_element' in line:
|
|
# install_element (CONFIG_NODE, &ip_community_list_name_standard_cmd);
|
|
re_install_element = re.search('install_element\s*\(\w+,\s*&(.*)\s*\)', line.strip())
|
|
|
|
if re_install_element:
|
|
cmd = re_install_element.group(1)
|
|
if cmd not in aliases:
|
|
fh.write(line)
|
|
else:
|
|
fh.write(line)
|
|
else:
|
|
fh.write(line)
|
|
|
|
elif state == 'DEFUN_HEADER':
|
|
if line.strip() == '{':
|
|
state = 'DEFUN_BODY'
|
|
|
|
elif state == 'ALIAS_HEADER':
|
|
if line.rstrip().endswith(')'):
|
|
state = None
|
|
|
|
elif state == 'DEFUN_BODY':
|
|
if line.rstrip() == '}':
|
|
state = None
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
filename = sys.argv[1]
|
|
if os.path.exists(filename):
|
|
alias_destroy(filename)
|
|
else:
|
|
print "ERROR: could not find file %s" % filename
|