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.
<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:
<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.
<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
0020 Configuration OK
0021 Undo requested
0022 Undo scheduled
+0023 Evaluation of expression
1000 BIRD version
1001 Interface list
8005 Protocol is down => cannot dump
8006 Reload failed
8007 Access denied
+8008 Evaluation runtime error
9000 Command too long
9001 Parse error
return CMP_ERROR;
}
-static void val_print(struct f_val v);
-
static void
tree_node_print(struct f_tree *t, char **sep)
{
/*
* val_print - format filter value
*/
-static void
+void
val_print(struct f_val v)
{
char buf2[1024];
#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
break;
case 'a': /* rta access */
{
+ ACCESS_RTE;
struct rta *rta = (*f_rte)->attrs;
res.type = what->aux;
switch(res.type) {
}
break;
case P('a','S'):
+ ACCESS_RTE;
ONEARG;
if (what->aux != v1.type)
runtime( "Attempt to set static attribute to incompatible type" );
}
break;
case P('e','a'): /* Access to extended attributes */
+ ACCESS_RTE;
{
eattr *e = NULL;
if (!(f_flags & FF_FORCE_TMPATTR))
}
break;
case P('e','S'):
+ ACCESS_RTE;
ONEARG;
{
struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
}
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" );
}
else
{
+ ACCESS_RTE;
v1.val.px.ip = (*f_rte)->net->n.prefix;
v1.val.px.len = (*f_rte)->net->n.pxlen;
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;
}
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);
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! */
#include "nest/cmds.h"
#include "lib/string.h"
#include "lib/resource.h"
+#include "filter/filter.h"
extern int shutting_down;
extern int configuring;
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();
+}
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);
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, "");
} ;
echo_mask:
ALL { $$ = ~0; }
| OFF { $$ = 0; }
- | NUM
+ | '{' log_mask_list '}' { $$ = $2; }
;
echo_size:
static char *log_buffer_pos;
static int log_buffer_remains;
+const char *log_buffer_ptr = log_buffer;
+
/**
* log_reset - reset the log buffer