]> git.proxmox.com Git - mirror_frr.git/blobdiff - python/clidef.py
Merge pull request #2055 from opensourcerouting/fix-pathspace
[mirror_frr.git] / python / clidef.py
index de3a764a0b0fc40f0e3dd608443864afe88f8763..2e5590964715b3db3c24b8211a9d1462db96c624 100644 (file)
@@ -36,12 +36,14 @@ class RenderHandler(object):
 
     deref = ''
     drop_str = False
+    canfail = True
 
 class StringHandler(RenderHandler):
     argtype = 'const char *'
     decl = Template('const char *$varname = NULL;')
     code = Template('$varname = argv[_i]->arg;')
     drop_str = True
+    canfail = False
 
 class LongHandler(RenderHandler):
     argtype = 'long'
@@ -59,7 +61,7 @@ class PrefixBase(RenderHandler):
     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 = '&'
@@ -71,6 +73,10 @@ class Prefix6Handler(PrefixBase):
     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 = { };')
@@ -121,9 +127,15 @@ handlers = {
     '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(\\
@@ -134,20 +146,31 @@ DEFUN_CMD_FUNC_DECL($fnname)
 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%s",
-                               argv[_i]->varname, argv[_i]->arg, VTY_NEWLINE);
+                       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);
 }
 
@@ -163,10 +186,8 @@ def process_file(fn, ofd, dumpfd, all_defun):
     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)
@@ -190,6 +211,7 @@ def process_file(fn, ofd, dumpfd, all_defun):
             arglist = []
             argblocks = []
             doc = []
+            canfail = 0
 
             def do_add(handler, varname, attr = ''):
                 argdefs.append(',\\\n\t%s %s%s' % (handler.argtype, varname, attr))
@@ -207,6 +229,8 @@ def process_file(fn, ofd, dumpfd, all_defun):
                 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))')
@@ -223,6 +247,8 @@ def process_file(fn, ofd, dumpfd, all_defun):
             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__':
@@ -251,4 +277,4 @@ 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__)])