From f5a60cee87abfc836f86c2d486da1f6d7fca82c0 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Wed, 24 Jul 2024 17:07:30 +0200 Subject: [PATCH] New: [CLI simple alias](https://github.com/clicon/cligen/issues/112) --- CHANGELOG.md | 5 ++ cligen_object.h | 2 +- cligen_syntax.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++ cligen_syntax.h | 2 + 4 files changed, 142 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff55d6f..6d7826b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ ## 7.2.0 Expected: October 2024 + +### Features + +* New: [CLI simple alias](https://github.com/clicon/cligen/issues/112) + ## 7.1.0 3 July 2024 diff --git a/cligen_object.h b/cligen_object.h index 40cf0c8..1ff8c41 100644 --- a/cligen_object.h +++ b/cligen_object.h @@ -122,6 +122,7 @@ typedef struct cg_varspec cg_varspec; #define CO_FLAGS_TOPOFTREE 0x04 /* This node is top of expanded sub-tree */ #define CO_FLAGS_OPTION 0x08 /* Generated from optional [] */ #define CO_FLAGS_MATCH 0x10 /* For sets: avoid selecting same more than once */ +#define CO_FLAGS_ALIAS 0x20 /* Added as an alias (see cligen_alias_cb) */ /* Flags for pt_copy and co_copy */ @@ -209,7 +210,6 @@ typedef struct cg_obj cg_obj; #define co_treeref_orig co_common.coc_treeref_orig #define co_value co_common.coc_value - /* Access fields for code traversing parse tree */ #define co_vtype u.cou_var.cgs_vtype #define co_show u.cou_var.cgs_show diff --git a/cligen_syntax.c b/cligen_syntax.c index da4338a..d5c0464 100644 --- a/cligen_syntax.c +++ b/cligen_syntax.c @@ -369,3 +369,137 @@ cligen_translate_str2fn(parse_tree *pt, done: return retval; } + +/*! Alias function + * + * @param[in] h CLIgen handle + * @param[in] cvv Vector of variables: function parameters + * @param[in] argv Arguments given at the callback: this is the command to be executed + * @retval 0 OK + * @retval -1 Error + * @see cliread_eval original fn + */ +int +cligen_alias_call(cligen_handle h, + cvec *cvv, + cvec *argv) +{ + int retval = -1; + parse_tree *pt; + cg_obj *matchobj = NULL; + cvec *cvv2 = NULL; + cligen_result result; + char *reason = NULL; + + if (argv == NULL || cvec_len(argv) != 1){ + errno = EINVAL; + goto done; + } + if ((pt = cligen_pt_active_get(h)) == NULL){ + errno = ENOENT; + goto done; + } + if (cliread_parse(h, cvec_i_str(argv, 0), pt, &matchobj, &cvv2, &result, &reason) < 0) + goto done; + if (result == CG_MATCH) + if (cligen_eval(h, matchobj, cvv2) < 0) + goto done; + retval = 0; + done: + if (matchobj) + co_free(matchobj, 0); + if (cvv2) + cvec_free(cvv2); + if (reason) + free(reason); + return retval; +} + +/*! Add cli alias given treename (or default), alias name, helpstring and command + * + * Check if old alias exists, if so replace it, parse new syntax and insert into + * top-level parse-tree, and mark as alias. + * @param[in] h CLIgen handle + * @param[in] phname CLIgen parse-tree header / tree name + * @param[in] name Alias name + * @param[in] helpstr Help string of alias + * @param[in] command Alias expanded command + * @param[in] callback Alias callback (default cligen_alias_call) + * @retval 0 OK + * @retval -1 Error + */ +int +cligen_alias_add(cligen_handle h, + char *phname, + char *name, + char *helpstr, + char *command, + cgv_fnstype_t *callback) +{ + int retval = -1; + cbuf *cb = NULL; + pt_head *ph; + parse_tree *pt; + cg_obj *co; + int i; + cg_callback *cc; + + if (phname == NULL) { + if ((ph = cligen_ph_active_get(h)) == NULL){ + errno = ENOENT; + goto done; + } + } + else { + if ((ph = cligen_ph_find(h, phname)) == NULL) { + errno = ENOENT; + goto done; + } + } + if ((pt = cligen_ph_parsetree_get(ph)) == NULL){ + errno = ENOENT; + goto done; + } + /* Remove old alias, cant use search since need i for delete */ + for (i=0; ico_command, name) != 0) + continue; + if (co_flags_get(co, CO_FLAGS_ALIAS) == 0){ + errno = EEXIST; + goto done; + } + pt_vec_i_delete(pt, i, 1); + break; + } + if ((cb = cbuf_new()) == NULL) + goto done; + cprintf(cb, "%s", name); + if (helpstr) + cprintf(cb, "(\"%s\")", helpstr); + cprintf(cb, ", cligen_alias_fn(\"%s\");", command); + if (clispec_parse_str(h, cbuf_get(cb), "Parsing alias command", NULL, pt, NULL) < 0){ + goto done; + } + /* Sanity check and add alias flag */ + if ((co = co_find_one(pt, name)) == NULL){ + errno = ENOENT; + goto done; + } + co_flags_set(co, CO_FLAGS_ALIAS); + { + + + if ((cc = co->co_callbacks) == NULL){ + fprintf(stderr, "No callback found\n"); + goto done; + } + co_callback_fn_set(cc, callback?callback:cligen_alias_call); + } + retval = 0; + done: + if (cb) + cbuf_free(cb); + return retval; +} diff --git a/cligen_syntax.h b/cligen_syntax.h index 3b5c043..1daf795 100644 --- a/cligen_syntax.h +++ b/cligen_syntax.h @@ -77,6 +77,8 @@ int cligen_callbackv_str2fn(parse_tree *pt, cgv_str2fn_t *str2fn, void *arg); int cligen_expandv_str2fn(parse_tree *pt, expandv_str2fn_t *str2fn, void *arg); int cligen_translate_str2fn(parse_tree *pt, translate_str2fn_t *str2fn, void *arg); int cligen_parse_debug(int d); +int cligen_alias_call(cligen_handle h, cvec *cvv, cvec *argv); +int cligen_alias_add(cligen_handle h, char *phname, char *name, char *helpstr, char *command, cgv_fnstype_t *callback); #endif /* _CLIGEN_SYNTAX_H_ */