]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implements eval command and minor CLI cleanups.
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 25 Jul 2013 11:15:32 +0000 (13:15 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 25 Jul 2013 11:15:32 +0000 (13:15 +0200)
Implemented eval command can be used to evaluate expressions.

The patch also documents echo command and allows to use log classes
instead of integer as a mask for echo.

doc/bird.sgml
doc/reply_codes
filter/filter.c
filter/filter.h
nest/cmds.c
nest/cmds.h
nest/config.Y
sysdep/unix/log.c

index 27f8b8690e7b15caf67cb7deb46f65a5609e16af..a1d3dc2c02f9a37aa9eb856445745df41ee86a43 100644 (file)
@@ -282,7 +282,7 @@ protocol rip {
        <tag>include "<m/filename/"</tag> 
        This statement causes inclusion of a new file. The maximal depth is set to 5.
 
-       <tag>log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag> 
+       <tag><label id="dsc-log">log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag> 
        Set logging of messages having the given class (either <cf/all/ or <cf/{
        error, trace }/ etc.) into selected destination (a file specified as a filename string,
        syslog with optional name argument, or the stderr output). Classes are:
@@ -651,9 +651,6 @@ This argument can be omitted if there exists only a single instance.
 <p>Here is a brief list of supported functions:
 
 <descrip>
-       <tag>dump resources|sockets|interfaces|neighbors|attributes|routes|protocols</tag>
-       Dump contents of internal data structures to the debugging output.
-
        <tag>show status</tag>
        Show router status, that is BIRD version, uptime and time from last reconfiguration.
 
@@ -812,6 +809,17 @@ This argument can be omitted if there exists only a single instance.
 
        <tag>debug <m/protocol/|<m/pattern/|all all|off|{ states | routes | filters | events | packets }</tag>
        Control protocol debugging.
+
+       <tag>dump resources|sockets|interfaces|neighbors|attributes|routes|protocols</tag>
+       Dump contents of internal data structures to the debugging output.
+
+       <tag>echo all|off|{ <m/list of log classes/ } [ <m/buffer-size/ ]</tag>
+       Control echoing of log messages to the command-line output.
+       See <ref id="dsc-log" name="log option"> for a list of log classes.
+
+       <tag>eval <m/expr/</tag>
+       Evaluate given expression.
+
 </descrip>
 
 <chapt>Filters
index 58807241b23a26080b35f9f2a194f7aa54bb5b02..e9996eefc391f02fc5b695708194b6d82816e3da 100644 (file)
@@ -31,6 +31,7 @@ Reply codes of BIRD command-line interface
 0020   Configuration OK
 0021   Undo requested
 0022   Undo scheduled
+0023   Evaluation of expression
 
 1000   BIRD version
 1001   Interface list
@@ -61,6 +62,7 @@ Reply codes of BIRD command-line interface
 8005   Protocol is down => cannot dump
 8006   Reload failed
 8007   Access denied
+8008   Evaluation runtime error
 
 9000   Command too long
 9001   Parse error
index 432fa122e648f2a7466743e9f9198f7ab667c311..d784c253ac355cc3c261fe5de2c8499266769dcb 100644 (file)
@@ -440,8 +440,6 @@ val_in_range(struct f_val v1, struct f_val v2)
   return CMP_ERROR;
 }
 
-static void val_print(struct f_val v);
-
 static void
 tree_node_print(struct f_tree *t, char **sep)
 {
@@ -474,7 +472,7 @@ tree_print(struct f_tree *t)
 /*
  * val_print - format filter value
  */
-static void
+void
 val_print(struct f_val v)
 {
   char buf2[1024];
@@ -558,6 +556,8 @@ static struct rate_limit rl_runtime_err;
 #define TWOARGS_C TWOARGS \
                   if (v1.type != v2.type) \
                    runtime( "Can't operate with values of incompatible types" );
+#define ACCESS_RTE \
+  do { if (!f_rte) runtime("No route to access"); } while (0)
 
 /**
  * interpret
@@ -821,6 +821,7 @@ interpret(struct f_inst *what)
     break;
   case 'a':    /* rta access */
     {
+      ACCESS_RTE;
       struct rta *rta = (*f_rte)->attrs;
       res.type = what->aux;
       switch(res.type) {
@@ -845,6 +846,7 @@ interpret(struct f_inst *what)
     }
     break;
   case P('a','S'):
+    ACCESS_RTE;
     ONEARG;
     if (what->aux != v1.type)
       runtime( "Attempt to set static attribute to incompatible type" );
@@ -877,6 +879,7 @@ interpret(struct f_inst *what)
     }
     break;
   case P('e','a'):     /* Access to extended attributes */
+    ACCESS_RTE;
     {
       eattr *e = NULL;
       if (!(f_flags & FF_FORCE_TMPATTR))
@@ -944,6 +947,7 @@ interpret(struct f_inst *what)
     }
     break;
   case P('e','S'):
+    ACCESS_RTE;
     ONEARG;
     {
       struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
@@ -1021,10 +1025,12 @@ interpret(struct f_inst *what)
     }
     break;
   case 'P':
+    ACCESS_RTE;
     res.type = T_INT;
     res.val.i = (*f_rte)->pref;
     break;
   case P('P','S'):
+    ACCESS_RTE;
     ONEARG;
     if (v1.type != T_INT)
       runtime( "Can't set preference to non-integer" );
@@ -1246,6 +1252,7 @@ interpret(struct f_inst *what)
     }
     else
     {
+      ACCESS_RTE;
       v1.val.px.ip = (*f_rte)->net->n.prefix;
       v1.val.px.len = (*f_rte)->net->n.pxlen;
 
@@ -1478,22 +1485,27 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
   return res.val.i;
 }
 
-int
-f_eval_int(struct f_inst *expr)
+struct f_val
+f_eval(struct f_inst *expr, struct linpool *tmp_pool)
 {
-  /* Called independently in parse-time to eval expressions */
-  struct f_val res;
-
   f_flags = 0;
   f_tmp_attrs = NULL;
   f_rte = NULL;
-  f_pool = cfg_mem;
+  f_pool = tmp_pool;
 
   log_reset();
-  res = interpret(expr);
+  return interpret(expr);
+}
+
+int
+f_eval_int(struct f_inst *expr)
+{
+  /* Called independently in parse-time to eval expressions */
+  struct f_val res = f_eval(expr, cfg_mem);
 
   if (res.type != T_INT)
     cf_error("Integer expression expected");
+
   return res.val.i;
 }
 
index 2386fc9598c5db55723ecce5ccb960885dce7a7f..1d5150e72c01d2c16a0f8820f0779d042ed59173 100644 (file)
@@ -106,6 +106,7 @@ struct ea_list;
 struct rte;
 
 int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags);
+struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
 int f_eval_int(struct f_inst *expr);
 u32 f_eval_asn(struct f_inst *expr);
 
@@ -117,6 +118,8 @@ int i_same(struct f_inst *f1, struct f_inst *f2);
 int val_compare(struct f_val v1, struct f_val v2);
 int tree_compare(const void *p1, const void *p2);
 
+void val_print(struct f_val v);
+
 #define F_NOP 0
 #define F_NONL 1
 #define F_ACCEPT 2     /* Need to preserve ordering: accepts < rejects! */
index 54ace169af3e3db92e09af2c1dfda8a35b399f7c..9bdd66cd1bb644352b4e6a642b6f04648b43790a 100644 (file)
@@ -13,6 +13,7 @@
 #include "nest/cmds.h"
 #include "lib/string.h"
 #include "lib/resource.h"
+#include "filter/filter.h"
 
 extern int shutting_down;
 extern int configuring;
@@ -90,3 +91,22 @@ cmd_show_memory(void)
   print_size("Total:", rmemsize(&root_pool));
   cli_msg(0, "");
 }
+
+extern const char *log_buffer_ptr;
+
+void
+cmd_eval(struct f_inst *expr)
+{
+  struct f_val v = f_eval(expr, this_cli->parser_pool);
+  log_reset();
+
+  if (v.type == T_RETURN)
+    {
+      cli_msg(8008, "runtime error");
+      return;
+    }
+
+  val_print(v);
+  cli_msg(23, "%s", log_buffer_ptr);
+  log_reset();
+}
index 8b0bff7e80721552e5b672269d4a27d443f6231b..4cf8fb1b8b03469fca0eb18cd46e1b09ac6e855f 100644 (file)
@@ -11,6 +11,9 @@ struct sym_show_data {
        struct symbol   *sym;
 };
 
+struct f_inst;
+
 void cmd_show_status(void);
 void cmd_show_symbols(struct sym_show_data *sym);
 void cmd_show_memory(void);
+void cmd_eval(struct f_inst *expr);
index b85a57336c9f1f2ff89e3c19203729605644a2cf..a6f13808b3bd6f61c9778a076c2f3e4802b3591c 100644 (file)
@@ -612,7 +612,11 @@ CF_CLI(DUMP ROUTES,,, [[Dump routing table]])
 CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
 { protos_dump_all(); cli_msg(0, ""); } ;
 
-CF_CLI(ECHO, echo_mask echo_size, [all | off | <mask>] [<buffer-size>], [[Configure echoing of log messages]]) {
+CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
+{ cmd_eval($2); } ;
+
+CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]])
+CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug | trace | info | remote | warning | error | auth }) [<buffer-size>], [[Control echoing of log messages]]) {
   cli_set_log_echo(this_cli, $2, $3);
   cli_msg(0, "");
 } ;
@@ -620,7 +624,7 @@ CF_CLI(ECHO, echo_mask echo_size, [all | off | <mask>] [<buffer-size>], [[Config
 echo_mask:
    ALL { $$ = ~0; }
  | OFF { $$ = 0; }
- | NUM
+ | '{' log_mask_list '}' { $$ = $2; }
  ;
 
 echo_size:
index 92f12f1e65af7a5775443170dc1368bbb3540674..f3a66f8b837e1ac7d2f9466a0b5dd16d462f7b9a 100644 (file)
@@ -70,6 +70,8 @@ static char log_buffer[LOG_BUFFER_SIZE];
 static char *log_buffer_pos;
 static int log_buffer_remains;
 
+const char *log_buffer_ptr = log_buffer;
+
 
 /**
  * log_reset - reset the log buffer