--- /dev/null
+#!/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())
+ cmd = re_install_element.group(1)
+ if cmd not in aliases:
+ 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