Commit 064b59d1 authored by Maria Matejka's avatar Maria Matejka
Browse files

Config: Allow keyword redefinition

When you redefine a keyword, a warning is issued. It is recommended to
abstain from redefining keywords as it may yield lots of strange parse
errors in config.

It is not possible to use a keyword as a protocol or template name due
to collisions in config language.
parent fd9f0c06
Loading
Loading
Loading
Loading
+7 −13
Original line number Diff line number Diff line
@@ -51,12 +51,6 @@
#include "lib/string.h"
#include "lib/hash.h"

struct keyword {
  byte *name;
  int value;
  struct keyword *next;
};

#include "conf/keywords.h"

/* Could be defined by Bison in cf-parse.tab.h, inteferes with SYM hash */
@@ -618,18 +612,20 @@ cf_get_symbol(const byte *c)
 * for purposes of cf_define_symbol().
 */
struct symbol *
cf_localize_symbol(struct symbol *sym)
cf_localize_symbol(const byte *c)
{
  struct symbol *sym = cf_find_symbol(new_config, c);

  /* If the symbol type is void, it has been recently allocated just in this scope. */
  if (!sym->class)
  if (sym && !sym->class)
    return sym;
  
  /* If the scope is the current, it is already defined in this scope. */
  if (sym->scope == conf_this_scope)
  if (sym && (sym->scope == conf_this_scope))
    cf_error("Symbol already defined");

  /* Not allocated here yet, doing it now. */
  return cf_new_symbol(sym->name);
  return cf_new_symbol(c);
}

struct symbol *
@@ -665,14 +661,12 @@ cf_lex_symbol(const char *data)
  struct keyword *k = HASH_FIND(kw_hash, KW, data);
  if (k)
  {
    cf_lval.kw = *k;
    if (k->value > 0)
      return k->value;
    else
    {
      cf_lval.i = -k->value;
      return ENUM;
  }
  }

  /* OK, undefined symbol */
  cf_lval.s = sym;
+9 −3
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ struct symbol *cf_find_symbol(const struct config *cfg, const byte *c);

struct symbol *cf_get_symbol(const byte *c);
struct symbol *cf_default_name(char *template, int *counter);
struct symbol *cf_localize_symbol(struct symbol *sym);
struct symbol *cf_localize_symbol(const byte *c);

/**
 * cf_define_symbol - define meaning of a symbol
@@ -198,8 +198,8 @@ struct symbol *cf_localize_symbol(struct symbol *sym);
 * Result: Pointer to the newly defined symbol. If we are in the top-level
 * scope, it's the same @sym as passed to the function.
 */
#define cf_define_symbol(osym_, type_, var_, def_) ({ \
    struct symbol *sym_ = cf_localize_symbol(osym_); \
#define cf_define_symbol(name_, type_, var_, def_) ({ \
    struct symbol *sym_ = cf_localize_symbol(name_); \
    sym_->class = type_; \
    sym_->var_ = def_; \
    sym_; })
@@ -208,6 +208,12 @@ void cf_push_scope(struct symbol *);
void cf_pop_scope(void);
char *cf_symbol_class_name(struct symbol *sym);

struct keyword {
  byte *name;
  int value;
  struct keyword *next;
};

/* Parser */

extern char *cf_text;
+20 −4
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ CF_HDR
#include "nest/cli.h"
#include "filter/filter.h"

extern struct keyword keyword_list[];
extern struct sym_scope *conf_this_scope;

/* FIXME: Turn on YYERROR_VERBOSE and work around lots of bison bugs? */

CF_DEFINES
@@ -90,12 +93,14 @@ CF_DECLS
  struct channel_limit cl;
  struct timeformat *tf;
  mpls_label_stack *mls;
  struct keyword kw;
}

%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
%token GEQ LEQ NEQ AND OR
%token PO PC
%token <i> NUM ENUM
%token <kw> ENUM
%token <i> NUM
%token <ip4> IP4
%token <ip6> IP6
%token <i64> VPN_RD
@@ -110,8 +115,9 @@ CF_DECLS
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
%type <mls> label_stack_start label_stack

%type <t> text opttext
%type <t> text opttext token_def
%type <s> symbol
%type <kw> token keyword

%nonassoc PREFIX_DUMMY
%left AND OR
@@ -146,7 +152,7 @@ conf: ';' ;
conf: definition ;

definition:
   DEFINE symbol '=' term ';' {
   DEFINE token_def '=' term ';' {
     struct f_val *val = cfg_alloc(sizeof(struct f_val));
     if (f_eval(f_linearize($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
     cf_define_symbol($2, SYM_CONSTANT | val->type, val, val);
@@ -194,7 +200,7 @@ ipa:

ipa_scope:
   /* empty */ { $$ = NULL; }
 | '%' symbol { $$ = if_get_by_name($2->name); }
 | '%' token { $$ = if_get_by_name($2.name); }
 ;


@@ -379,6 +385,16 @@ opttext:
 | /* empty */ { $$ = NULL; }
 ;

token:
   symbol { $$ = (struct keyword) { .name = $1->name, }; }
 | keyword { $$ = $1; }
 | ENUM { $$ = $1; }
 ;

token_def:
   symbol { $$ = $1->name; }
 | keyword { log(L_WARN "Redefining a keyword: \"%s\"", $1.name); $$ = $1.name; }
 | ENUM { log(L_WARN "Redefining a keyword: \"%s\"", $1.name); $$ = $1.name; }

CF_CODE

+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ m4_define(CF_ENUM_PX, `m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_
# After all configuration templates end, we generate the 
m4_m4wrap(`
m4_divert(0)
static struct keyword keyword_list[] = {
struct keyword keyword_list[] = {
m4_undivert(1){ NULL, -1, NULL } };
')

+5 −8
Original line number Diff line number Diff line
@@ -25,14 +25,11 @@ m4_define(CF_GRAMMAR, `CF_ZONE(3, Grammar)')
m4_define(CF_CODE, `CF_ZONE(4, C Code)')
m4_define(CF_END, `m4_divert(-1)')

# Simple iterator
m4_define(CF_itera, `m4_ifelse($#, 1, [[CF_iter($1)]], [[CF_iter($1)[[]]CF_itera(m4_shift($@))]])')
m4_define(CF_iterate, `m4_define([[CF_iter]], m4_defn([[$1]]))CF_itera($2)')

# Keywords act as untyped %token
m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)m4_define([[CF_toks]],CF_toks $1)]])')
m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token[[]]CF_toks
)DNL')
# Keywords act as a %token <kw> + added to a keyword: rule
m4_define(CF_KEYWORDS, `m4_ifelse($#,1,,[[CF_KEYWORDS(m4_shift($@))]])DNL
m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)m4_divert(2)%token <kw> $1
m4_divert(3)keyword: $1 ;
m4_divert(2)]])')

# CLI commands
m4_define(CF_CLI, `m4_define([[CF_cmd]], cmd_[[]]m4_translit($1, [[ ]], _))DNL
Loading