commit 09002a15b090908284cc142939ea58573a8a2b76
Author: Alexander Zubkov <green@qrator.net>
Date:   Wed Jan 25 19:57:38 2023 +0100

    CLI: create alias symbols from CLI
    
    Make it possible to create alias symbols from CLI too using the same
    syntax as in the config.

diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index ec5eceec..8cb6b5ea 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -601,6 +601,34 @@ cf_new_symbol(const byte *c)
   return s;
 }
 
+/**
+ * cf_new_runtime_symbol - create a new symbol during runtime
+ *
+ * This function is used to create a new symbol after configuration is commited.
+ */
+struct symbol *
+cf_new_runtime_symbol(const byte *c)
+{
+  struct symbol *s;
+
+  uint l = strlen(c);
+  if (l > SYM_MAX_LEN)
+    cf_error("Symbol too long");
+
+  s = lp_allocz(config->mem, sizeof(struct symbol) + l + 1);
+  *s = (struct symbol) { .scope = config->root_scope, .class = SYM_VOID, };
+  strcpy(s->name, c);
+
+  if (!config->sym_hash.data)
+    HASH_INIT(config->sym_hash, config->pool, SYM_ORDER);
+
+  HASH_INSERT2(config->sym_hash, SYM, config->pool, s);
+
+  add_tail(&(config->symbols), &(s->n));
+
+  return s;
+}
+
 /**
  * cf_find_symbol - find a symbol by name
  * @cfg: specificed config
diff --git a/conf/conf.h b/conf/conf.h
index d7796c5c..3a54e1eb 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -193,6 +193,7 @@ 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);
 void cf_alias_symbol(struct symbol *sym, struct symbol *alias);
+struct symbol *cf_new_runtime_symbol(const byte *c);
 
 static inline int cf_symbol_is_local(struct symbol *sym)
 { return (sym->scope == conf_this_scope) && !conf_this_scope->soft_scopes; }
diff --git a/nest/cmds.c b/nest/cmds.c
index bcc8d6c2..6fa02797 100644
--- a/nest/cmds.c
+++ b/nest/cmds.c
@@ -142,3 +142,12 @@ cmd_eval(const struct f_line *expr)
 
   cli_msg(23, "%s", buf.start);
 }
+
+void
+cmd_alias_symbol(struct symbol *sym, struct symbol *alias)
+{
+  /* uniqueness is implicit by CF_SYM_UNDEFINED in CLI syntax */
+  struct symbol *newalias = cf_new_runtime_symbol(alias->name);
+  cf_alias_symbol(sym, newalias);
+  cli_msg(10, "ok");
+}
diff --git a/nest/cmds.h b/nest/cmds.h
index 194a9d7f..426501a1 100644
--- a/nest/cmds.h
+++ b/nest/cmds.h
@@ -19,3 +19,5 @@ void cmd_show_memory(void);
 
 struct f_line;
 void cmd_eval(const struct f_line *expr);
+
+void cmd_alias_symbol(struct symbol *sym, struct symbol *alias);
diff --git a/nest/config.Y b/nest/config.Y
index 10cb15cb..30fdbc22 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -934,6 +934,9 @@ proto_patt2:
 
 dynamic_attr: IGP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_GEN_IGP_METRIC); } ;
 
+CF_CLI_HELP(LINK, ..., [[Add alias symbol]])
+CF_CLI(LINK, CF_SYM_UNDEFINED TO CF_SYM_KNOWN, <alias> to <symbol>, [[Add alias symbol]])
+{ cmd_alias_symbol($4, $2); };
 
 CF_CODE
 
