summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/cf-lex.l38
-rw-r--r--conf/conf.c17
-rw-r--r--conf/conf.h4
-rw-r--r--conf/confbase.Y10
-rw-r--r--conf/gen_keywords.m46
-rw-r--r--conf/gen_parser.m48
-rw-r--r--nest/cli.c50
-rw-r--r--nest/cli.h2
-rw-r--r--nest/config.Y5
9 files changed, 108 insertions, 32 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index 21727a9d..258ca7e9 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -34,14 +34,12 @@ static struct keyword {
static struct keyword *kw_hash[KW_HASH_SIZE];
static struct symbol **sym_hash;
-static int allow_new_symbols;
int conf_lino;
static int cf_hash(byte *c);
static struct symbol *cf_find_sym(byte *c, unsigned int h0);
-pool *cfg_pool;
linpool *cfg_mem;
int (*cf_read_hook)(byte *buf, unsigned int max);
@@ -54,7 +52,7 @@ int (*cf_read_hook)(byte *buf, unsigned int max);
%option noyywrap
-%x COMMENT CCOMM
+%x COMMENT CCOMM CLI
ALPHA [a-zA-Z_]
DIGIT [0-9]
@@ -121,6 +119,11 @@ WHITE [ \t]
return SYM;
}
+<CLI>! {
+ BEGIN(INITIAL);
+ return CLI_MARKER;
+}
+
[={}:;,()+*/%-<>~\[\]] {
return yytext[0];
}
@@ -174,17 +177,18 @@ static struct symbol *
cf_find_sym(byte *c, unsigned int h0)
{
unsigned int h = h0 & (SYM_HASH_SIZE-1);
- struct symbol *s = sym_hash[h];
+ struct symbol *s;
int l;
- while (s)
- {
- if (!strcmp(s->name, c))
- return s;
- s = s->next;
- }
- if (!allow_new_symbols)
- return NULL;
+ if (!sym_hash)
+ sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *));
+ else
+ for(s = sym_hash[h]; s; s=s->next)
+ {
+ if (!strcmp(s->name, c))
+ return s;
+ s = s->next;
+ }
l = strlen(c);
if (l > SYM_MAX_LEN)
cf_error("Symbol too long");
@@ -230,11 +234,15 @@ cf_define_symbol(struct symbol *sym, int type, void *def)
}
void
-cf_lex_init(int flag)
+cf_lex_init(int is_cli)
{
- if (allow_new_symbols = flag)
- sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *));
+ sym_hash = NULL;
conf_lino = 1;
+ yyrestart(NULL);
+ if (is_cli)
+ BEGIN(CLI);
+ else
+ BEGIN(INITIAL);
}
void
diff --git a/conf/conf.c b/conf/conf.c
index d9bf9d88..47d4db4e 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -39,15 +39,12 @@ config_alloc(byte *name)
int
config_parse(struct config *c)
{
- struct proto_config *p;
-
debug("Parsing configuration file `%s'\n", c->file_name);
new_config = c;
- cfg_pool = c->pool;
cfg_mem = c->mem;
if (setjmp(conf_jmpbuf))
return 0;
- cf_lex_init(1);
+ cf_lex_init(0);
cf_lex_init_tables();
protos_preconfig(c);
rt_preconfig(c);
@@ -61,6 +58,18 @@ config_parse(struct config *c)
return 1;
}
+int
+cli_parse(struct config *c)
+{
+ new_config = c;
+ cfg_mem = c->mem;
+ if (setjmp(conf_jmpbuf))
+ return 0;
+ cf_lex_init(1);
+ cf_parse();
+ return 1;
+}
+
void
config_free(struct config *c)
{
diff --git a/conf/conf.h b/conf/conf.h
index 4f6f030c..d62f1383 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -30,13 +30,13 @@ extern struct config *config, *new_config;
struct config *config_alloc(byte *name);
int config_parse(struct config *);
+int cli_parse(struct config *);
void config_free(struct config *);
void config_commit(struct config *);
void cf_error(char *msg, ...) NORET;
/* Pools */
-extern pool *cfg_pool;
extern linpool *cfg_mem;
#define cfg_alloc(size) lp_alloc(cfg_mem, size)
@@ -71,7 +71,7 @@ extern int conf_lino;
void cf_lex_init_tables(void);
int cf_lex(void);
-void cf_lex_init(int flag);
+void cf_lex_init(int is_cli);
struct symbol *cf_find_symbol(byte *c);
struct symbol *cf_default_name(char *prefix, int *counter);
void cf_define_symbol(struct symbol *symbol, int type, void *def);
diff --git a/conf/confbase.Y b/conf/confbase.Y
index b266d253..4a942878 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -16,8 +16,11 @@ CF_HDR
#include "nest/protocol.h"
#include "nest/iface.h"
#include "nest/route.h"
+#include "nest/cli.h"
#include "filter/filter.h"
+#define cli_msg(x...) cli_printf(this_cli, x)
+
CF_DECLS
%union {
@@ -34,7 +37,7 @@ CF_DECLS
struct password_item *p;
}
-%token END
+%token END CLI_MARKER
%token <i> NUM
%token <i32> RTRID
%token <a> IPA
@@ -54,9 +57,8 @@ CF_GRAMMAR
/* Basic config file structure */
-config: conf_entries END {
- return 0;
- }
+config: conf_entries END { return 0; }
+ | CLI_MARKER cli_cmd END { return 0; }
;
conf_entries:
diff --git a/conf/gen_keywords.m4 b/conf/gen_keywords.m4
index 8bbe4902..37b882b5 100644
--- a/conf/gen_keywords.m4
+++ b/conf/gen_keywords.m4
@@ -2,7 +2,7 @@ m4_divert(-1)m4_dnl
#
# BIRD -- Generator of Configuration Keyword List
#
-# (c) 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+# (c) 1998--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
#
# Can be freely distributed and used under the terms of the GNU GPL.
#
@@ -18,6 +18,10 @@ m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)CF_hand
m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token[[]]CF_toks
)DNL')
+# CLI commands generate keywords as well
+m4_define(CF_CLI, `CF_KEYWORDS(m4_translit($1, [[ ]], [[,]]))
+')
+
# As we are processing C source, we must access all M4 primitives via
# m4_* and also set different quoting convention: `[[' and ']]'
m4_changequote([[,]])
diff --git a/conf/gen_parser.m4 b/conf/gen_parser.m4
index a08b330c..8441c83b 100644
--- a/conf/gen_parser.m4
+++ b/conf/gen_parser.m4
@@ -2,7 +2,7 @@ m4_divert(-1)m4_dnl
#
# BIRD -- Generator of Configuration Grammar
#
-# (c) 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+# (c) 1998--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
#
# Can be freely distributed and used under the terms of the GNU GPL.
#
@@ -38,6 +38,12 @@ m4_define(CF_dyn_rules,)
m4_define(CF_ADDTO, `m4_define([[CF_rule_$1]],m4_ifdef([[CF_rule_$1]],CF_rule_$1 | ,[[m4_define([[CF_dyn_rules]],CF_dyn_rules[[CF_RULE($1)
]])]])$2)DNL')
+# CLI commands
+m4_define(CF_CLI, `m4_define([[CF_cmd]], cmd_[[]]m4_translit($1, [[ ]], _))DNL
+m4_divert(2)CF_KEYWORDS(m4_translit($1, [[ ]], [[,]]))
+m4_divert(3)CF_ADDTO(cli_cmd, CF_cmd)
+CF_cmd: $1 ')
+
# After all configuration templates end, we finally generate the grammar file.
m4_m4wrap(`
m4_divert(0)DNL
diff --git a/nest/cli.c b/nest/cli.c
index f094a7c4..41907b33 100644
--- a/nest/cli.c
+++ b/nest/cli.c
@@ -7,8 +7,9 @@
*/
#include "nest/bird.h"
-#include "lib/string.h"
#include "nest/cli.h"
+#include "conf/conf.h"
+#include "lib/string.h"
pool *cli_pool;
@@ -88,6 +89,47 @@ cli_free_out(cli *c)
}
}
+static byte *cli_rh_pos;
+static unsigned int cli_rh_len;
+static int cli_rh_trick_flag;
+struct cli *this_cli;
+
+static int
+cli_cmd_read_hook(byte *buf, unsigned int max)
+{
+ if (!cli_rh_trick_flag)
+ {
+ cli_rh_trick_flag = 1;
+ buf[0] = '!';
+ return 1;
+ }
+ if (max > cli_rh_len)
+ max = cli_rh_len;
+ memcpy(buf, cli_rh_pos, max);
+ cli_rh_pos += max;
+ cli_rh_len -= max;
+ return max;
+}
+
+static void
+cli_command(struct cli *c)
+{
+ struct config f;
+ int res;
+
+ f.pool = NULL;
+ f.mem = c->parser_pool;
+ cf_read_hook = cli_cmd_read_hook;
+ cli_rh_pos = c->rx_buf;
+ cli_rh_len = strlen(c->rx_buf);
+ cli_rh_trick_flag = 0;
+ this_cli = c;
+ res = cli_parse(&f);
+ lp_flush(c->parser_pool);
+ if (!res)
+ cli_printf(c, 9001, f.err_msg);
+}
+
static int
cli_event(void *data)
{
@@ -106,10 +148,7 @@ cli_event(void *data)
if (err < 0)
cli_printf(c, 9000, "Command too long");
else
- {
- cli_printf(c, -9001, "Parse error in:");
- cli_printf(c, 9001, c->rx_buf);
- }
+ cli_command(c);
}
if (cli_write(c))
{
@@ -133,6 +172,7 @@ cli_new(void *priv)
c->tx_buf = c->tx_pos = c->tx_write = NULL;
c->cont = cli_hello;
c->last_reply = 0;
+ c->parser_pool = lp_new(c->pool, 4096);
ev_schedule(c->event);
return c;
}
diff --git a/nest/cli.h b/nest/cli.h
index 9670f69a..d4413ffb 100644
--- a/nest/cli.h
+++ b/nest/cli.h
@@ -31,9 +31,11 @@ typedef struct cli {
void (*cont)(struct cli *c);
void *rover; /* Private to continuation routine */
int last_reply;
+ struct linpool *parser_pool; /* Pool used during parsing */
} cli;
extern pool *cli_pool;
+extern struct cli *this_cli; /* Used during parsing */
/* Functions to be called by command handlers */
diff --git a/nest/config.Y b/nest/config.Y
index 91cdad11..64594625 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -182,6 +182,11 @@ password_list:
}
;
+/* Core commands */
+
+CF_CLI(TEST LEDS, <N>, [[Flashes each LED <N> times]]) NUM { cli_msg(0, "%d", $3); } ;
+CF_CLI(TEST, 1, 2) { cli_msg(0, "OK"); }
+
CF_CODE
CF_END