deref = ''
drop_str = False
+ canfail = True
class StringHandler(RenderHandler):
argtype = 'const char *'
decl = Template('const char *$varname = NULL;')
- code = Template('$varname = argv[_i]->arg;')
+ code = Template('$varname = (argv[_i]->type == WORD_TKN) ? argv[_i]->text : argv[_i]->arg;')
drop_str = True
+ canfail = False
class LongHandler(RenderHandler):
argtype = 'long'
def combine(self, other):
if type(self) == type(other):
return other
- if type(other) in [Prefix4Handler, Prefix6Handler, PrefixGenHandler]:
+ if isinstance(other, PrefixBase):
return PrefixGenHandler(None)
return StringHandler(None)
deref = '&'
argtype = 'const struct prefix_ipv6 *'
decl = Template('struct prefix_ipv6 $varname = { };')
code = Template('_fail = !str2prefix_ipv6(argv[_i]->arg, &$varname);')
+class PrefixEthHandler(PrefixBase):
+ argtype = 'struct prefix_eth *'
+ decl = Template('struct prefix_eth $varname = { };')
+ code = Template('_fail = !str2prefix_eth(argv[_i]->arg, &$varname);')
class PrefixGenHandler(PrefixBase):
argtype = 'const struct prefix *'
decl = Template('struct prefix $varname = { };')
code = Template('_fail = !inet_aton(argv[_i]->arg, &$varname);')
class IP6Handler(IPBase):
argtype = 'struct in6_addr'
- decl = Template('struct in6_addr $varname = IN6ADDR_ANY_INIT;')
+ decl = Template('struct in6_addr $varname = {};')
code = Template('_fail = !inet_pton(AF_INET6, argv[_i]->arg, &$varname);')
class IPGenHandler(IPBase):
argtype = 'const union sockunion *'
'IPV4_PREFIX_TKN': Prefix4Handler,
'IPV6_TKN': IP6Handler,
'IPV6_PREFIX_TKN': Prefix6Handler,
+ 'MAC_TKN': PrefixEthHandler,
+ 'MAC_PREFIX_TKN': PrefixEthHandler,
}
# core template invoked for each occurence of DEFPY.
+#
+# the "#if $..." bits are there to keep this template unified into one
+# common form, without requiring a more advanced template engine (e.g.
+# jinja2)
templ = Template('''/* $fnname => "$cmddef" */
DEFUN_CMD_FUNC_DECL($fnname)
#define funcdecl_$fnname static int ${fnname}_magic(\\
funcdecl_$fnname;
DEFUN_CMD_FUNC_TEXT($fnname)
{
+#if $nonempty /* anything to parse? */
int _i;
+#if $canfail /* anything that can fail? */
unsigned _fail = 0, _failcnt = 0;
+#endif
$argdecls
for (_i = 0; _i < argc; _i++) {
if (!argv[_i]->varname)
continue;
- _fail = 0;$argblocks
+#if $canfail /* anything that can fail? */
+ _fail = 0;
+#endif
+$argblocks
+#if $canfail /* anything that can fail? */
if (_fail)
vty_out (vty, "%% invalid input for %s: %s\\n",
argv[_i]->varname, argv[_i]->arg);
_failcnt += _fail;
+#endif
}
+#if $canfail /* anything that can fail? */
if (_failcnt)
return CMD_WARNING;
+#endif
+#endif
return ${fnname}_magic(self, vty, argc, argv$arglist);
}
filedata = clippy.parse(fn)
for entry in filedata['data']:
- if entry['type'] == 'DEFPY' or (all_defun and entry['type'].startswith('DEFUN')):
+ if entry['type'].startswith('DEFPY') or (all_defun and entry['type'].startswith('DEFUN')):
cmddef = entry['args'][2]
- for i in cmddef:
- assert i.startswith('"') and i.endswith('"')
cmddef = ''.join([i[1:-1] for i in cmddef])
graph = clippy.Graph(cmddef)
arglist = []
argblocks = []
doc = []
+ canfail = 0
def do_add(handler, varname, attr = ''):
argdefs.append(',\\\n\t%s %s%s' % (handler.argtype, varname, attr))
if handler is None: continue
do_add(handler, varname)
code = handler.code.substitute({'varname': varname}).replace('\n', '\n\t\t\t')
+ if handler.canfail:
+ canfail = 1
strblock = ''
if not handler.drop_str:
do_add(StringHandler(None), '%s_str' % (varname), ' __attribute__ ((unused))')
params['argdecls'] = ''.join(argdecls)
params['arglist'] = ''.join(arglist)
params['argblocks'] = ''.join(argblocks)
+ params['canfail'] = canfail
+ params['nonempty'] = len(argblocks)
ofd.write(templ.substitute(params))
if __name__ == '__main__':
process_file(args.cfile, ofd, dumpfd, args.all_defun)
if args.o is not None:
- clippy.wrdiff(args.o, ofd)
+ clippy.wrdiff(args.o, ofd, [args.cfile, os.path.realpath(__file__), sys.executable])