In bgpctl I am constantly hitting this annoying edgecase where adding
detail to a show rib command errors out:
        bgpctl show rib 192.0.2.1 detail
        unknown argument: detail
        valid commands/args:
          <cr>
          all
          longer-prefixes
          or-longer
          or-shorter

The problem is that the t_show_prefix token table can not fall back to
t_show_rib if an unknown token is seen.

This diff solves this issue with the introduction of ANYTOKEN.
ANYTOKEN matches if nothing previously matched and then redirects
the call to the next table (which is pointing back up).

To make show_valid_args() work nicely dump store the first table on
ANYTOKEN and dump the help for that one first. I don't think there is a
need to have a stack of tables since ANYTOKEN should be used sparingly.

With this 'bgpctl show rib 192.0.2.1 detail' works.
-- 
:wq Claudio

Index: parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/parser.c,v
retrieving revision 1.124
diff -u -p -r1.124 parser.c
--- parser.c    13 Apr 2023 11:52:43 -0000      1.124
+++ parser.c    15 Apr 2023 08:34:25 -0000
@@ -34,8 +34,9 @@
 #include "parser.h"
 
 enum token_type {
-       NOTOKEN,
        ENDTOKEN,
+       NOTOKEN,
+       ANYTOKEN,
        KEYWORD,
        ADDRESS,
        PEERADDRESS,
@@ -72,6 +73,8 @@ struct token {
        const struct token      *next;
 };
 
+static const struct token *prevtable;
+
 static const struct token t_main[];
 static const struct token t_show[];
 static const struct token t_show_summary[];
@@ -320,11 +323,11 @@ static const struct token t_show_mrt_as[
 };
 
 static const struct token t_show_prefix[] = {
-       { NOTOKEN,      "",             NONE,           NULL},
-       { FLAG,         "all",          F_LONGER,       NULL},
-       { FLAG,         "longer-prefixes", F_LONGER,    NULL},
-       { FLAG,         "or-longer",    F_LONGER,       NULL},
-       { FLAG,         "or-shorter",   F_SHORTER,      NULL},
+       { FLAG,         "all",          F_LONGER,       t_show_rib},
+       { FLAG,         "longer-prefixes", F_LONGER,    t_show_rib},
+       { FLAG,         "or-longer",    F_LONGER,       t_show_rib},
+       { FLAG,         "or-shorter",   F_SHORTER,      t_show_rib},
+       { ANYTOKEN,     "",             NONE,           t_show_rib},
        { ENDTOKEN,     "",             NONE,           NULL}
 };
 
@@ -533,6 +536,12 @@ parse(int argc, char *argv[])
                        show_valid_args(table);
                        return (NULL);
                }
+               if (match->type == ANYTOKEN) {
+                       if (prevtable == NULL)
+                               prevtable = table;
+                       table = match->next;
+                       continue;
+               }
 
                argc--;
                argv++;
@@ -571,6 +580,13 @@ match_token(int *argc, char **argv[], co
                                t = &table[i];
                        }
                        break;
+               case ANYTOKEN:
+                       /* match anything if nothing else matched before */
+                       if (match == 0) {
+                               match++;
+                               t = &table[i];
+                       }
+                       break;
                case KEYWORD:
                        if (word != NULL && strncmp(word, table[i].keyword,
                            wordlen) == 0) {
@@ -842,10 +858,19 @@ show_valid_args(const struct token table
 {
        int     i;
 
+       if (prevtable != NULL) {
+               const struct token *t = prevtable;
+               prevtable = NULL;
+               show_valid_args(t);
+               fprintf(stderr, "or any of\n");
+       }
+
        for (i = 0; table[i].type != ENDTOKEN; i++) {
                switch (table[i].type) {
                case NOTOKEN:
                        fprintf(stderr, "  <cr>\n");
+                       break;
+               case ANYTOKEN:
                        break;
                case KEYWORD:
                case FLAG:

Reply via email to