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'
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 *'
}
# 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])