Refactored cli-syntax code to use cligen pt_head instead (long overdue)
This commit is contained in:
parent
e1a8e0d40b
commit
b39ee078c4
7 changed files with 124 additions and 274 deletions
|
|
@ -65,6 +65,7 @@ Developers may need to change their code
|
||||||
|
|
||||||
### Minor features
|
### Minor features
|
||||||
|
|
||||||
|
* Refactored cli-syntax code to use cligen pt_head instead (long overdue)
|
||||||
* Modified backend exit strategy so that 2nd ^C actually exits
|
* Modified backend exit strategy so that 2nd ^C actually exits
|
||||||
* Performance: A change in the `merge` code made "co-located" config and non-config get retrieval go considerable faster. This is done by a specialized `xml_child_each_attr()` function.
|
* Performance: A change in the `merge` code made "co-located" config and non-config get retrieval go considerable faster. This is done by a specialized `xml_child_each_attr()` function.
|
||||||
* CLI: Added `show statistics` example code for backend and CLI memory stats
|
* CLI: Added `show statistics` example code for backend and CLI memory stats
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ struct cli_handle {
|
||||||
/* ------ end of common handle ------ */
|
/* ------ end of common handle ------ */
|
||||||
|
|
||||||
cligen_handle cl_cligen; /* cligen handle */
|
cligen_handle cl_cligen; /* cligen handle */
|
||||||
cli_syntax_t *cl_stx; /* CLI syntax structure */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Return a clicon handle for other CLICON API calls
|
/*! Return a clicon handle for other CLICON API calls
|
||||||
|
|
@ -121,14 +120,9 @@ int
|
||||||
cli_handle_exit(clicon_handle h)
|
cli_handle_exit(clicon_handle h)
|
||||||
{
|
{
|
||||||
cligen_handle ch = cligen(h);
|
cligen_handle ch = cligen(h);
|
||||||
struct cli_handle *cl = handle(h);
|
|
||||||
|
|
||||||
if (cl->cl_stx)
|
|
||||||
free(cl->cl_stx);
|
|
||||||
clicon_handle_exit(h); /* frees h and options */
|
clicon_handle_exit(h); /* frees h and options */
|
||||||
|
|
||||||
cligen_exit(ch);
|
cligen_exit(ch);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,28 +130,6 @@ cli_handle_exit(clicon_handle h)
|
||||||
* cli-specific handle access functions
|
* cli-specific handle access functions
|
||||||
*----------------------------------------------------------*/
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
/*! Get current syntax-group */
|
|
||||||
cli_syntax_t *
|
|
||||||
cli_syntax(clicon_handle h)
|
|
||||||
{
|
|
||||||
struct cli_handle *cl = handle(h);
|
|
||||||
return cl->cl_stx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Set current syntax-group */
|
|
||||||
int
|
|
||||||
cli_syntax_set(clicon_handle h,
|
|
||||||
cli_syntax_t *stx)
|
|
||||||
{
|
|
||||||
struct cli_handle *cl = handle(h);
|
|
||||||
|
|
||||||
if (cl->cl_stx)
|
|
||||||
free(cl->cl_stx);
|
|
||||||
cl->cl_stx = stx;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Return clicon handle */
|
/*! Return clicon handle */
|
||||||
cligen_handle
|
cligen_handle
|
||||||
cli_cligen(clicon_handle h)
|
cli_cligen(clicon_handle h)
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,4 @@ int cli_prompt_set(clicon_handle h, char *prompt);
|
||||||
|
|
||||||
int cli_logsyntax_set(clicon_handle h, int status);
|
int cli_logsyntax_set(clicon_handle h, int status);
|
||||||
|
|
||||||
/* Internal functions for handling cli groups */
|
|
||||||
cli_syntax_t *cli_syntax(clicon_handle h);
|
|
||||||
|
|
||||||
int cli_syntax_set(clicon_handle h, cli_syntax_t *stx);
|
|
||||||
|
|
||||||
#endif /* _CLI_HANDLE_H_ */
|
#endif /* _CLI_HANDLE_H_ */
|
||||||
|
|
|
||||||
|
|
@ -239,13 +239,18 @@ cli_interactive(clicon_handle h)
|
||||||
char *new_mode;
|
char *new_mode;
|
||||||
cligen_result result;
|
cligen_result result;
|
||||||
int ret;
|
int ret;
|
||||||
|
pt_head *ph;
|
||||||
|
|
||||||
/* Loop through all commands */
|
/* Loop through all commands */
|
||||||
while(!cligen_exiting(cli_cligen(h))) {
|
while(!cligen_exiting(cli_cligen(h))) {
|
||||||
new_mode = cli_syntax_mode(h);
|
if ((ph = cligen_pt_head_active_get(cli_cligen(h))) == NULL){
|
||||||
|
clicon_err(OE_UNIX, 0, "active tree not found");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
new_mode = cligen_ph_name_get(ph);
|
||||||
cmd = NULL;
|
cmd = NULL;
|
||||||
/* Read a CLI string, including expand handling */
|
/* Read a CLI string, including expand handling */
|
||||||
if ((ret = clicon_cliread(h, &cmd)) < 0)
|
if ((ret = clicon_cliread(h, ph, &cmd)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -686,7 +691,7 @@ main(int argc,
|
||||||
{
|
{
|
||||||
char *dir;
|
char *dir;
|
||||||
/* Load cli .so plugins before yangs are loaded (eg extension callbacks) and
|
/* Load cli .so plugins before yangs are loaded (eg extension callbacks) and
|
||||||
* before CLI is loaded by cli_syntax_load below */
|
* before CLI is loaded by clispec_load below */
|
||||||
if ((dir = clicon_cli_dir(h)) != NULL &&
|
if ((dir = clicon_cli_dir(h)) != NULL &&
|
||||||
clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
|
clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -752,7 +757,7 @@ main(int argc,
|
||||||
|
|
||||||
/* Initialize cli syntax.
|
/* Initialize cli syntax.
|
||||||
* Plugins have already been loaded by clixon_plugins_load above */
|
* Plugins have already been loaded by clixon_plugins_load above */
|
||||||
if (cli_syntax_load(h) < 0)
|
if (clispec_load(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Set syntax mode if specified from command-line or config-file. */
|
/* Set syntax mode if specified from command-line or config-file. */
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
|
|
||||||
***** END LICENSE BLOCK *****
|
***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
|
|
@ -80,117 +79,34 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! Find syntax mode named 'mode'. Create if specified
|
/*! Generate CLIgen parse tree for syntax mode
|
||||||
*/
|
*
|
||||||
static cli_syntaxmode_t *
|
|
||||||
syntax_mode_find(cli_syntax_t *stx,
|
|
||||||
const char *mode,
|
|
||||||
int create)
|
|
||||||
{
|
|
||||||
cli_syntaxmode_t *csm;
|
|
||||||
|
|
||||||
csm = stx->stx_modes;
|
|
||||||
if (csm) {
|
|
||||||
do {
|
|
||||||
if (strcmp(csm->csm_name, mode) == 0)
|
|
||||||
return csm;
|
|
||||||
csm = NEXTQ(cli_syntaxmode_t *, csm);
|
|
||||||
} while (csm && csm != stx->stx_modes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (create == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if ((csm = malloc(sizeof(cli_syntaxmode_t))) == NULL) {
|
|
||||||
clicon_err(OE_UNIX, errno, "malloc");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(csm, 0, sizeof(*csm));
|
|
||||||
if ((csm->csm_name = strdup(mode)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if ((csm->csm_prompt = strdup(CLI_DEFAULT_PROMPT)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if ((csm->csm_pt = pt_new()) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "pt_new");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
INSQ(csm, stx->stx_modes);
|
|
||||||
stx->stx_nmodes++;
|
|
||||||
|
|
||||||
return csm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Generate parse tree for syntax mode
|
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] m Syntax mode struct
|
* @param[in] m Syntax mode struct
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
gen_parse_tree(clicon_handle h,
|
gen_parse_tree(clicon_handle h,
|
||||||
cli_syntaxmode_t *m)
|
char *name,
|
||||||
|
parse_tree *pt,
|
||||||
|
pt_head **php)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
pt_head *ph;
|
pt_head *ph;
|
||||||
|
|
||||||
if ((ph = cligen_ph_add(cli_cligen(h), m->csm_name)) == NULL)
|
if ((ph = cligen_ph_add(cli_cligen(h), name)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (cligen_ph_parsetree_set(ph, m->csm_pt) < 0)
|
if (cligen_ph_parsetree_set(ph, pt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (cligen_ph_prompt_set(ph, CLI_DEFAULT_PROMPT) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "cligen_ph_prompt_set");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
*php = ph;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Append syntax
|
|
||||||
* @param[in] h Clicon handle
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
syntax_append(clicon_handle h,
|
|
||||||
cli_syntax_t *stx,
|
|
||||||
const char *name,
|
|
||||||
parse_tree *pt)
|
|
||||||
{
|
|
||||||
cli_syntaxmode_t *csm;
|
|
||||||
|
|
||||||
if ((csm = syntax_mode_find(stx, name, 1)) == NULL)
|
|
||||||
return -1;
|
|
||||||
if (cligen_parsetree_merge(csm->csm_pt, NULL, pt) < 0){
|
|
||||||
clicon_err(OE_PLUGIN, errno, "cligen_parsetree_merge");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Remove all cligen syntax modes
|
|
||||||
* @param[in] h Clicon handle
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
cli_syntax_unload(clicon_handle h)
|
|
||||||
{
|
|
||||||
cli_syntax_t *stx = cli_syntax(h);
|
|
||||||
cli_syntaxmode_t *csm;
|
|
||||||
|
|
||||||
if (stx == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while (stx->stx_nmodes > 0) {
|
|
||||||
csm = stx->stx_modes;
|
|
||||||
DELQ(csm, stx->stx_modes, cli_syntaxmode_t *);
|
|
||||||
if (csm){
|
|
||||||
if (csm->csm_name)
|
|
||||||
free(csm->csm_name);
|
|
||||||
if (csm->csm_prompt)
|
|
||||||
free(csm->csm_prompt);
|
|
||||||
free(csm);
|
|
||||||
}
|
|
||||||
stx->stx_nmodes--;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Dynamic linking loader string to function mapper
|
/*! Dynamic linking loader string to function mapper
|
||||||
*
|
*
|
||||||
* Maps strings from the CLI specification file to real funtions using dlopen
|
* Maps strings from the CLI specification file to real funtions using dlopen
|
||||||
|
|
@ -247,7 +163,7 @@ clixon_str2fn(char *name,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Load a file containing syntax and append to specified modes, also load C plugin
|
/*! Load a file containing clispec syntax and append to specified modes, also load C plugin
|
||||||
*
|
*
|
||||||
* First load CLIgen file,
|
* First load CLIgen file,
|
||||||
* Then find which .so to load by looking in the "CLICON_PLUGIN" variable in that file.
|
* Then find which .so to load by looking in the "CLICON_PLUGIN" variable in that file.
|
||||||
|
|
@ -257,13 +173,15 @@ clixon_str2fn(char *name,
|
||||||
* @param[in] filename Name of file where syntax is specified (in syntax-group dir)
|
* @param[in] filename Name of file where syntax is specified (in syntax-group dir)
|
||||||
* @param[in] dir Name of dir, or NULL
|
* @param[in] dir Name of dir, or NULL
|
||||||
* @param[out] ptall Universal CLIgen parse tree: apply to all modes
|
* @param[out] ptall Universal CLIgen parse tree: apply to all modes
|
||||||
|
* @param[out] modes Keep track of all modes
|
||||||
* @see clixon_plugins_load Where .so plugin code has been loaded prior to this
|
* @see clixon_plugins_load Where .so plugin code has been loaded prior to this
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cli_load_syntax_file(clicon_handle h,
|
clispec_load_file(clicon_handle h,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
const char *dir,
|
const char *dir,
|
||||||
parse_tree *ptall)
|
parse_tree *ptall,
|
||||||
|
cvec *modes)
|
||||||
{
|
{
|
||||||
void *handle = NULL; /* Handle to plugin .so module */
|
void *handle = NULL; /* Handle to plugin .so module */
|
||||||
char *mode = NULL; /* Name of syntax mode to append new syntax */
|
char *mode = NULL; /* Name of syntax mode to append new syntax */
|
||||||
|
|
@ -274,8 +192,10 @@ cli_load_syntax_file(clicon_handle h,
|
||||||
cvec *cvv = NULL;
|
cvec *cvv = NULL;
|
||||||
char *prompt = NULL;
|
char *prompt = NULL;
|
||||||
char **vec = NULL;
|
char **vec = NULL;
|
||||||
int i, nvec;
|
int i;
|
||||||
|
int nvec;
|
||||||
char *plgnam;
|
char *plgnam;
|
||||||
|
pt_head *ph;
|
||||||
#ifndef CLIXON_STATIC_PLUGINS
|
#ifndef CLIXON_STATIC_PLUGINS
|
||||||
clixon_plugin_t *cp;
|
clixon_plugin_t *cp;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -299,7 +219,7 @@ cli_load_syntax_file(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assuming this plugin is first in queue */
|
/* Assuming this plugin is first in queue */
|
||||||
if (cli_parse_file(h, f, filepath, pt, cvv) < 0){
|
if (clispec_parse_file(h, f, filepath, NULL, pt, cvv) < 0){
|
||||||
clicon_err(OE_PLUGIN, 0, "failed to parse cli file %s", filepath);
|
clicon_err(OE_PLUGIN, 0, "failed to parse cli file %s", filepath);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -309,6 +229,7 @@ cli_load_syntax_file(clicon_handle h,
|
||||||
* CLICON_MODE: which mode(s) this syntax applies to
|
* CLICON_MODE: which mode(s) this syntax applies to
|
||||||
* CLICON_PROMPT: Cli prompt in this mode (see cli_prompt_get)
|
* CLICON_PROMPT: Cli prompt in this mode (see cli_prompt_get)
|
||||||
* CLICON_PLUGIN: Name of C API plugin
|
* CLICON_PLUGIN: Name of C API plugin
|
||||||
|
* CLICON_PIPETREE: terminals are automatically expanded with this tree
|
||||||
* Note: the base case is that it is:
|
* Note: the base case is that it is:
|
||||||
* (1) a single mode or
|
* (1) a single mode or
|
||||||
* (2) "*" all modes or "m1:m2" - a list of modes
|
* (2) "*" all modes or "m1:m2" - a list of modes
|
||||||
|
|
@ -330,6 +251,7 @@ cli_load_syntax_file(clicon_handle h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Resolve callback names to function pointers. */
|
/* Resolve callback names to function pointers. */
|
||||||
if (cligen_callbackv_str2fn(pt, (cgv_str2fn_t*)clixon_str2fn, handle) < 0){
|
if (cligen_callbackv_str2fn(pt, (cgv_str2fn_t*)clixon_str2fn, handle) < 0){
|
||||||
clicon_err(OE_PLUGIN, 0, "Mismatch between CLIgen file '%s' and CLI plugin file '%s'. Some possible errors:\n\t1. A function given in the CLIgen file does not exist in the plugin (ie link error)\n\t2. The CLIgen spec does not point to the correct plugin .so file (CLICON_PLUGIN=\"%s\" is wrong)",
|
clicon_err(OE_PLUGIN, 0, "Mismatch between CLIgen file '%s' and CLI plugin file '%s'. Some possible errors:\n\t1. A function given in the CLIgen file does not exist in the plugin (ie link error)\n\t2. The CLIgen spec does not point to the correct plugin .so file (CLICON_PLUGIN=\"%s\" is wrong)",
|
||||||
|
|
@ -366,17 +288,42 @@ cli_load_syntax_file(clicon_handle h,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (i = 0; i < nvec; i++) {
|
for (i = 0; i < nvec; i++) {
|
||||||
if (syntax_append(h,
|
char *name = vec[i];
|
||||||
cli_syntax(h),
|
parse_tree *ptnew = NULL;
|
||||||
vec[i],
|
cg_var *cv;
|
||||||
pt) < 0) {
|
if ((ph = cligen_ph_find(cli_cligen(h), name)) == NULL){
|
||||||
|
if ((ptnew = pt_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "pt_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (gen_parse_tree(h, name, ptnew, &ph) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ph == NULL)
|
||||||
|
goto done;
|
||||||
|
if ((cv = cv_new(CGV_STRING)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cv_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cv_string_set(cv, name);
|
||||||
|
if (cvec_append_var(modes, cv) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "cvec_append_var");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (cv)
|
||||||
|
cv_free(cv);
|
||||||
|
}
|
||||||
|
if (cligen_parsetree_merge(cligen_ph_parsetree_get(ph), NULL, pt) < 0){
|
||||||
|
clicon_err(OE_PLUGIN, errno, "cligen_parsetree_merge");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (prompt)
|
if (prompt){
|
||||||
cli_set_prompt(h, vec[i], prompt);
|
if (cligen_ph_prompt_set(ph, prompt) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "cligen_ph_prompt_set");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cligen_parsetree_free(pt, 1);
|
cligen_parsetree_free(pt, 1);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -395,7 +342,7 @@ done:
|
||||||
* XXX The parsetree loading needs a rewrite for multiple parse-trees
|
* XXX The parsetree loading needs a rewrite for multiple parse-trees
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_syntax_load(clicon_handle h)
|
clispec_load(clicon_handle h)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *clispec_dir = NULL;
|
char *clispec_dir = NULL;
|
||||||
|
|
@ -403,37 +350,29 @@ cli_syntax_load(clicon_handle h)
|
||||||
int ndp;
|
int ndp;
|
||||||
int i;
|
int i;
|
||||||
struct dirent *dp = NULL;
|
struct dirent *dp = NULL;
|
||||||
cli_syntax_t *stx;
|
|
||||||
cli_syntaxmode_t *m;
|
|
||||||
cligen_susp_cb_t *fns = NULL;
|
cligen_susp_cb_t *fns = NULL;
|
||||||
cligen_interrupt_cb_t *fni = NULL;
|
cligen_interrupt_cb_t *fni = NULL;
|
||||||
clixon_plugin_t *cp;
|
clixon_plugin_t *cp;
|
||||||
parse_tree *ptall = NULL; /* Universal CLIgen parse tree all modes */
|
parse_tree *ptall = NULL; /* Universal CLIgen parse tree all modes */
|
||||||
|
cvec *modes = NULL; /* Keep track of created modes */
|
||||||
|
pt_head *ph;
|
||||||
|
cg_var *cv = NULL;
|
||||||
|
|
||||||
/* Syntax already loaded. XXX should we re-load?? */
|
|
||||||
if ((stx = cli_syntax(h)) != NULL)
|
|
||||||
return 0;
|
|
||||||
if ((ptall = pt_new()) == NULL){
|
if ((ptall = pt_new()) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "pt_new");
|
clicon_err(OE_UNIX, errno, "pt_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if ((modes = cvec_new(0)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cvec_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
/* Format plugin directory path */
|
/* Format plugin directory path */
|
||||||
clispec_dir = clicon_clispec_dir(h);
|
clispec_dir = clicon_clispec_dir(h);
|
||||||
clispec_file = clicon_option_str(h, "CLICON_CLISPEC_FILE");
|
clispec_file = clicon_option_str(h, "CLICON_CLISPEC_FILE");
|
||||||
|
|
||||||
/* Allocate plugin group object */
|
|
||||||
if ((stx = malloc(sizeof(*stx))) == NULL) {
|
|
||||||
clicon_err(OE_UNIX, errno, "malloc");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
memset(stx, 0, sizeof(*stx)); /* Zero out all */
|
|
||||||
|
|
||||||
cli_syntax_set(h, stx);
|
|
||||||
|
|
||||||
/* Load single specific clispec file */
|
/* Load single specific clispec file */
|
||||||
if (clispec_file){
|
if (clispec_file){
|
||||||
if (cli_load_syntax_file(h, clispec_file, NULL, ptall) < 0)
|
if (clispec_load_file(h, clispec_file, NULL, ptall, modes) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Load all clispec .cli files in directory */
|
/* Load all clispec .cli files in directory */
|
||||||
|
|
@ -443,33 +382,31 @@ cli_syntax_load(clicon_handle h)
|
||||||
goto done;
|
goto done;
|
||||||
/* Load the syntax parse trees into cli_syntax stx structure */
|
/* Load the syntax parse trees into cli_syntax stx structure */
|
||||||
for (i = 0; i < ndp; i++) {
|
for (i = 0; i < ndp; i++) {
|
||||||
clicon_debug(1, "DEBUG: Loading syntax '%.*s'",
|
clicon_debug(CLIXON_DBG_DEFAULT, "Loading clispec syntax: '%s/%s'",
|
||||||
(int)strlen(dp[i].d_name)-4, dp[i].d_name);
|
clispec_dir, dp[i].d_name);
|
||||||
if (cli_load_syntax_file(h, dp[i].d_name, clispec_dir, ptall) < 0)
|
if (clispec_load_file(h, dp[i].d_name, clispec_dir, ptall, modes) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Were any syntax modes successfully loaded? If not, leave */
|
/* Were any syntax modes successfully loaded? If not, leave */
|
||||||
if (stx->stx_nmodes <= 0) {
|
if (cvec_len(modes) == 0)
|
||||||
retval = 0;
|
goto ok;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Go thorugh all modes and :
|
/* Go thorugh all modes and :
|
||||||
* 1) Add the universal syntax
|
* 1) Add the universal syntax
|
||||||
* 2) add syntax tree (of those modes - "activate" syntax from stx to CLIgen)
|
* 2) add syntax tree (of those modes - "activate" syntax from stx to CLIgen)
|
||||||
*/
|
*/
|
||||||
m = stx->stx_modes;
|
cv = NULL;
|
||||||
do {
|
while ((cv = cvec_each(modes, cv)) != NULL){
|
||||||
if (cligen_parsetree_merge(m->csm_pt, NULL, ptall) < 0){
|
if ((ph = cligen_ph_find(cli_cligen(h), cv_string_get(cv))) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cligen_parsetree_merge(cligen_ph_parsetree_get(ph),
|
||||||
|
NULL,
|
||||||
|
ptall) < 0){
|
||||||
clicon_err(OE_PLUGIN, errno, "cligen_parsetree_merge");
|
clicon_err(OE_PLUGIN, errno, "cligen_parsetree_merge");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (gen_parse_tree(h, m) != 0)
|
}
|
||||||
goto done;
|
|
||||||
m = NEXTQ(cli_syntaxmode_t *, m);
|
|
||||||
} while (m && m != stx->stx_modes);
|
|
||||||
|
|
||||||
/* Set susp and interrupt callbacks into CLIgen */
|
/* Set susp and interrupt callbacks into CLIgen */
|
||||||
cp = NULL;
|
cp = NULL;
|
||||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||||
|
|
@ -480,29 +417,24 @@ cli_syntax_load(clicon_handle h)
|
||||||
if (cli_interrupt_hook(h, fni) < 0)
|
if (cli_interrupt_hook(h, fni) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
ok:
|
||||||
/* All good. We can now proudly return a new group */
|
/* All good. We can now proudly return a new group */
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (retval != 0) {
|
|
||||||
cli_syntax_unload(h);
|
|
||||||
cli_syntax_set(h, NULL);
|
|
||||||
}
|
|
||||||
cligen_parsetree_free(ptall, 1);
|
cligen_parsetree_free(ptall, 1);
|
||||||
|
if (modes)
|
||||||
|
cvec_free(modes);
|
||||||
if (dp)
|
if (dp)
|
||||||
free(dp);
|
free(dp);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Remove syntax modes and remove syntax
|
/*! Free resources in plugin
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_plugin_finish(clicon_handle h)
|
cli_plugin_finish(clicon_handle h)
|
||||||
{
|
{
|
||||||
/* Remove all cligen syntax modes */
|
|
||||||
cli_syntax_unload(h);
|
|
||||||
cli_syntax_set(h, NULL);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -556,8 +488,6 @@ clicon_parse(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *modename;
|
char *modename;
|
||||||
int ret;
|
int ret;
|
||||||
cli_syntax_t *stx = NULL;
|
|
||||||
cli_syntaxmode_t *csm;
|
|
||||||
parse_tree *pt; /* Orig */
|
parse_tree *pt; /* Orig */
|
||||||
cg_obj *match_obj = NULL;
|
cg_obj *match_obj = NULL;
|
||||||
cvec *cvv = NULL;
|
cvec *cvv = NULL;
|
||||||
|
|
@ -565,24 +495,16 @@ clicon_parse(clicon_handle h,
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *reason = NULL;
|
char *reason = NULL;
|
||||||
cligen_handle ch;
|
cligen_handle ch;
|
||||||
|
pt_head *ph;
|
||||||
|
|
||||||
ch = cli_cligen(h);
|
ch = cli_cligen(h);
|
||||||
if (clicon_get_logflags()&CLICON_LOG_STDOUT)
|
if (clicon_get_logflags()&CLICON_LOG_STDOUT)
|
||||||
f = stdout;
|
f = stdout;
|
||||||
else
|
else
|
||||||
f = stderr;
|
f = stderr;
|
||||||
stx = cli_syntax(h);
|
modename = *modenamep;
|
||||||
if ((modename = *modenamep) == NULL) {
|
ph = cligen_ph_find(cli_cligen(h), modename);
|
||||||
csm = stx->stx_active_mode;
|
if (ph != NULL){
|
||||||
modename = csm->csm_name;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ((csm = syntax_mode_find(stx, modename, 0)) == NULL) {
|
|
||||||
fprintf(f, "Can't find syntax mode '%s'\n", modename);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (csm != NULL){
|
|
||||||
if (cligen_ph_active_set_byname(ch, modename) < 0){
|
if (cligen_ph_active_set_byname(ch, modename) < 0){
|
||||||
fprintf(f, "No such parse-tree registered: %s\n", modename);
|
fprintf(f, "No such parse-tree registered: %s\n", modename);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -743,7 +665,9 @@ cli_prompt_get(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Read command from CLIgen's cliread() using current syntax mode.
|
/*! Read command from CLIgen's cliread() using current syntax mode.
|
||||||
|
*
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] ph Parse-tree head
|
||||||
* @param[out] stringp Pointer to command buffer or NULL on EOF
|
* @param[out] stringp Pointer to command buffer or NULL on EOF
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
* @retval 0 Fail but continue
|
* @retval 0 Fail but continue
|
||||||
|
|
@ -751,36 +675,35 @@ cli_prompt_get(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_cliread(clicon_handle h,
|
clicon_cliread(clicon_handle h,
|
||||||
|
pt_head *ph,
|
||||||
char **stringp)
|
char **stringp)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
char *name;
|
||||||
char *pfmt = NULL;
|
char *pfmt = NULL;
|
||||||
cli_syntaxmode_t *mode;
|
|
||||||
cli_syntax_t *stx;
|
|
||||||
cli_prompthook_t *fn;
|
cli_prompthook_t *fn;
|
||||||
clixon_plugin_t *cp;
|
clixon_plugin_t *cp;
|
||||||
char *promptstr;
|
char *promptstr;
|
||||||
|
|
||||||
stx = cli_syntax(h);
|
name = cligen_ph_name_get(ph);
|
||||||
mode = stx->stx_active_mode;
|
|
||||||
/* Get prompt from plugin callback? */
|
/* Get prompt from plugin callback? */
|
||||||
cp = NULL;
|
cp = NULL;
|
||||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_prompt) == NULL)
|
if ((fn = clixon_plugin_api_get(cp)->ca_prompt) == NULL)
|
||||||
continue;
|
continue;
|
||||||
pfmt = fn(h, mode->csm_name);
|
pfmt = fn(h, name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (clicon_quiet_mode(h))
|
if (clicon_quiet_mode(h))
|
||||||
cli_prompt_set(h, "");
|
cli_prompt_set(h, "");
|
||||||
else{
|
else{
|
||||||
if ((promptstr = cli_prompt_get(h, pfmt ? pfmt : mode->csm_prompt)) == NULL)
|
if ((promptstr = cli_prompt_get(h,
|
||||||
|
pfmt?pfmt:cligen_ph_prompt_get(ph)
|
||||||
|
)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
cli_prompt_set(h, promptstr);
|
cli_prompt_set(h, promptstr);
|
||||||
free(promptstr);
|
free(promptstr);
|
||||||
}
|
}
|
||||||
cligen_ph_active_set_byname(cli_cligen(h), mode->csm_name);
|
|
||||||
|
|
||||||
clicon_err_reset();
|
clicon_err_reset();
|
||||||
if (cliread(cli_cligen(h), stringp) < 0){
|
if (cliread(cli_cligen(h), stringp) < 0){
|
||||||
cli_handler_err(stdout);
|
cli_handler_err(stdout);
|
||||||
|
|
@ -807,17 +730,19 @@ clicon_cliread(clicon_handle h,
|
||||||
|
|
||||||
/*! Set syntax mode mode for existing current plugin group.
|
/*! Set syntax mode mode for existing current plugin group.
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
* @retval 1 OK
|
||||||
|
* @retval 0 Not found / error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_set_syntax_mode(clicon_handle h,
|
cli_set_syntax_mode(clicon_handle h,
|
||||||
const char *name)
|
char *name)
|
||||||
{
|
{
|
||||||
cli_syntaxmode_t *mode;
|
|
||||||
|
pt_head *ph;
|
||||||
if ((mode = syntax_mode_find(cli_syntax(h), name, 1)) == NULL)
|
|
||||||
|
if ((ph = cligen_ph_find(cli_cligen(h), name)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
cligen_pt_head_active_set(cli_cligen(h), ph);
|
||||||
cli_syntax(h)->stx_active_mode = mode;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -827,38 +752,10 @@ cli_set_syntax_mode(clicon_handle h,
|
||||||
char *
|
char *
|
||||||
cli_syntax_mode(clicon_handle h)
|
cli_syntax_mode(clicon_handle h)
|
||||||
{
|
{
|
||||||
cli_syntaxmode_t *csm;
|
pt_head *ph;
|
||||||
|
|
||||||
if ((csm = cli_syntax(h)->stx_active_mode) == NULL)
|
|
||||||
return NULL;
|
|
||||||
return csm->csm_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Callback from cli_set_prompt(). Set prompt format for syntax mode
|
|
||||||
* @param[in] h Clicon handle
|
|
||||||
* @param[in] name Name of syntax mode
|
|
||||||
* @param[in] prompt Prompt format
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cli_set_prompt(clicon_handle h,
|
|
||||||
const char *name,
|
|
||||||
const char *prompt)
|
|
||||||
{
|
|
||||||
cli_syntaxmode_t *csm;
|
|
||||||
|
|
||||||
if ((csm = syntax_mode_find(cli_syntax(h), name, 1)) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (csm->csm_prompt != NULL){
|
if ((ph = cligen_pt_head_active_get(cli_cligen(h))) == NULL)
|
||||||
free(csm->csm_prompt);
|
return NULL;
|
||||||
csm->csm_prompt = NULL;
|
return cligen_ph_name_get(ph);
|
||||||
}
|
|
||||||
if ((csm->csm_prompt = strdup(prompt)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,32 +45,12 @@
|
||||||
/* clicon generic callback pointer */
|
/* clicon generic callback pointer */
|
||||||
typedef void (clicon_callback_t)(clicon_handle h);
|
typedef void (clicon_callback_t)(clicon_handle h);
|
||||||
|
|
||||||
/* List of syntax modes
|
|
||||||
* XXX: syntax modes seem not needed, could be replaced by existing (new) cligen structures, such
|
|
||||||
* as pt_head and others. But code is arcane and difficult to modify.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
qelem_t csm_qelem; /* List header */
|
|
||||||
char *csm_name; /* Syntax mode name */
|
|
||||||
char *csm_prompt; /* Prompt for mode */
|
|
||||||
int csm_nsyntax; /* Num syntax specs registered by plugin */
|
|
||||||
parse_tree *csm_pt; /* CLIgen parse tree */
|
|
||||||
} cli_syntaxmode_t;
|
|
||||||
|
|
||||||
/* Plugin group object. Just a single object, not list. part of cli_handle
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int stx_nmodes; /* Number of syntax modes */
|
|
||||||
cli_syntaxmode_t *stx_active_mode; /* Current active syntax mode */
|
|
||||||
cli_syntaxmode_t *stx_modes; /* List of syntax modes */
|
|
||||||
} cli_syntax_t;
|
|
||||||
|
|
||||||
|
|
||||||
void *clixon_str2fn(char *name, void *handle, char **error);
|
void *clixon_str2fn(char *name, void *handle, char **error);
|
||||||
|
|
||||||
int clicon_parse(clicon_handle h, char *cmd, char **mode, cligen_result *result, int *evalres);
|
int clicon_parse(clicon_handle h, char *cmd, char **mode, cligen_result *result, int *evalres);
|
||||||
|
|
||||||
int clicon_cliread(clicon_handle h, char **stringp);
|
int clicon_cliread(clicon_handle h, pt_head *ph, char **stringp);
|
||||||
|
|
||||||
int cli_plugin_finish(clicon_handle h);
|
int cli_plugin_finish(clicon_handle h);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,11 @@ typedef enum autocli_listkw autocli_listkw_t;
|
||||||
* Function Declarations
|
* Function Declarations
|
||||||
*/
|
*/
|
||||||
/* cli_plugin.c */
|
/* cli_plugin.c */
|
||||||
int cli_set_syntax_mode(clicon_handle h, const char *mode);
|
int cli_set_syntax_mode(clicon_handle h, char *mode);
|
||||||
char *cli_syntax_mode(clicon_handle h);
|
char *cli_syntax_mode(clicon_handle h);
|
||||||
int cli_syntax_load(clicon_handle h);
|
int clispec_load(clicon_handle h);
|
||||||
int cli_handler_err(FILE *fd);
|
int cli_handler_err(FILE *fd);
|
||||||
int cli_set_prompt(clicon_handle h, const char *mode, const char *prompt);
|
int cli_set_prompt(clicon_handle h, char *mode, char *prompt);
|
||||||
int cli_ptpush(clicon_handle h, char *mode, char *string, char *op);
|
int cli_ptpush(clicon_handle h, char *mode, char *string, char *op);
|
||||||
int cli_ptpop(clicon_handle h, char *mode, char *op);
|
int cli_ptpop(clicon_handle h, char *mode, char *op);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue