mirror of https://github.com/sipwise/klish.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
488 lines
13 KiB
488 lines
13 KiB
/*
|
|
* command.c
|
|
*
|
|
* This file provides the implementation of a command definition
|
|
*/
|
|
#include "private.h"
|
|
#include "clish/types.h"
|
|
#include "lub/bintree.h"
|
|
#include "lub/string.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
/*---------------------------------------------------------
|
|
* PRIVATE METHODS
|
|
*--------------------------------------------------------- */
|
|
static void
|
|
clish_command_init(clish_command_t *this, const char *name, const char *text)
|
|
{
|
|
/* initialise the node part */
|
|
this->name = lub_string_dup(name);
|
|
this->text = lub_string_dup(text);
|
|
|
|
/* Be a good binary tree citizen */
|
|
lub_bintree_node_init(&this->bt_node);
|
|
|
|
/* set up defaults */
|
|
this->link = NULL;
|
|
this->alias = NULL;
|
|
this->alias_view = NULL;
|
|
this->paramv = clish_paramv_new();
|
|
this->viewid = NULL;
|
|
this->viewname = NULL;
|
|
this->action = clish_action_new();
|
|
this->config = clish_config_new();
|
|
this->detail = NULL;
|
|
this->escape_chars = NULL;
|
|
this->regex_chars = NULL;
|
|
this->args = NULL;
|
|
this->pview = NULL;
|
|
this->lock = BOOL_TRUE;
|
|
this->interrupt = BOOL_FALSE;
|
|
this->dynamic = BOOL_FALSE;
|
|
this->access = NULL;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
static void clish_command_fini(clish_command_t * this)
|
|
{
|
|
lub_string_free(this->name);
|
|
lub_string_free(this->text);
|
|
|
|
/* Link need not full cleanup */
|
|
if (this->link)
|
|
return;
|
|
|
|
/* finalize each of the parameter instances */
|
|
clish_paramv_delete(this->paramv);
|
|
|
|
clish_action_delete(this->action);
|
|
clish_config_delete(this->config);
|
|
lub_string_free(this->alias);
|
|
lub_string_free(this->alias_view);
|
|
lub_string_free(this->viewname);
|
|
lub_string_free(this->viewid);
|
|
lub_string_free(this->detail);
|
|
lub_string_free(this->escape_chars);
|
|
lub_string_free(this->regex_chars);
|
|
lub_string_free(this->access);
|
|
if (this->args)
|
|
clish_param_delete(this->args);
|
|
}
|
|
|
|
/*---------------------------------------------------------
|
|
* PUBLIC META FUNCTIONS
|
|
*--------------------------------------------------------- */
|
|
size_t clish_command_bt_offset(void)
|
|
{
|
|
return offsetof(clish_command_t, bt_node);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
int clish_command_bt_compare(const void *clientnode, const void *clientkey)
|
|
{
|
|
const clish_command_t *this = clientnode;
|
|
const char *key = clientkey;
|
|
|
|
return lub_string_nocasecmp(this->name, key);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command_bt_getkey(const void *clientnode, lub_bintree_key_t * key)
|
|
{
|
|
const clish_command_t *this = clientnode;
|
|
|
|
/* fill out the opaque key */
|
|
strcpy((char *)key, this->name);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
clish_command_t *clish_command_new(const char *name, const char *help)
|
|
{
|
|
clish_command_t *this = malloc(sizeof(clish_command_t));
|
|
|
|
if (this)
|
|
clish_command_init(this, name, help);
|
|
|
|
return this;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
clish_command_t *clish_command_new_link(const char *name,
|
|
const char *help, const clish_command_t * ref)
|
|
{
|
|
if (!ref)
|
|
return NULL;
|
|
|
|
clish_command_t *this = malloc(sizeof(clish_command_t));
|
|
assert(this);
|
|
|
|
/* Copy all fields to the new command-link */
|
|
*this = *ref;
|
|
/* Initialise the name (other than original name) */
|
|
this->name = lub_string_dup(name);
|
|
/* Initialise the help (other than original help) */
|
|
this->text = lub_string_dup(help);
|
|
/* Be a good binary tree citizen */
|
|
lub_bintree_node_init(&this->bt_node);
|
|
/* It a link to command so set the link flag */
|
|
this->link = ref;
|
|
|
|
return this;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
clish_command_t * clish_command_alias_to_link(clish_command_t *this, clish_command_t *ref)
|
|
{
|
|
clish_command_t tmp;
|
|
|
|
if (!this || !ref)
|
|
return NULL;
|
|
if (ref->alias) /* The reference is a link too */
|
|
return NULL;
|
|
memcpy(&tmp, this, sizeof(tmp));
|
|
*this = *ref;
|
|
memcpy(&this->bt_node, &tmp.bt_node, sizeof(tmp.bt_node));
|
|
this->name = lub_string_dup(tmp.name);
|
|
this->text = lub_string_dup(tmp.text);
|
|
this->link = ref;
|
|
clish_command_fini(&tmp);
|
|
|
|
return this;
|
|
}
|
|
|
|
/*---------------------------------------------------------
|
|
* PUBLIC METHODS
|
|
*--------------------------------------------------------- */
|
|
void clish_command_delete(clish_command_t * this)
|
|
{
|
|
clish_command_fini(this);
|
|
free(this);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command_insert_param(clish_command_t * this, clish_param_t * param)
|
|
{
|
|
clish_paramv_insert(this->paramv, param);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
int clish_command_help(const clish_command_t *this)
|
|
{
|
|
this = this; /* Happy compiler */
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
clish_command_t *clish_command_choose_longest(clish_command_t * cmd1,
|
|
clish_command_t * cmd2)
|
|
{
|
|
unsigned len1 = (cmd1 ? strlen(clish_command__get_name(cmd1)) : 0);
|
|
unsigned len2 = (cmd2 ? strlen(clish_command__get_name(cmd2)) : 0);
|
|
|
|
if (len2 < len1) {
|
|
return cmd1;
|
|
} else if (len1 < len2) {
|
|
return cmd2;
|
|
} else {
|
|
/* let local view override */
|
|
return cmd1;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
int clish_command_diff(const clish_command_t * cmd1,
|
|
const clish_command_t * cmd2)
|
|
{
|
|
if (NULL == cmd1) {
|
|
if (NULL != cmd2)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
if (NULL == cmd2)
|
|
return -1;
|
|
|
|
return lub_string_nocasecmp(clish_command__get_name(cmd1),
|
|
clish_command__get_name(cmd2));
|
|
}
|
|
|
|
/*---------------------------------------------------------
|
|
* PUBLIC ATTRIBUTES
|
|
*--------------------------------------------------------- */
|
|
const char *clish_command__get_name(const clish_command_t * this)
|
|
{
|
|
if (!this)
|
|
return NULL;
|
|
return this->name;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
const char *clish_command__get_text(const clish_command_t * this)
|
|
{
|
|
return this->text;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
const char *clish_command__get_detail(const clish_command_t * this)
|
|
{
|
|
return this->detail;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_detail(clish_command_t * this, const char *detail)
|
|
{
|
|
assert(NULL == this->detail);
|
|
this->detail = lub_string_dup(detail);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
clish_action_t *clish_command__get_action(const clish_command_t *this)
|
|
{
|
|
return this->action;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
clish_config_t *clish_command__get_config(const clish_command_t *this)
|
|
{
|
|
return this->config;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_viewname(clish_command_t * this, const char *viewname)
|
|
{
|
|
assert(NULL == this->viewname);
|
|
clish_command__force_viewname(this, viewname);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__force_viewname(clish_command_t * this, const char *viewname)
|
|
{
|
|
if (this->viewname)
|
|
lub_string_free(this->viewname);
|
|
this->viewname = lub_string_dup(viewname);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
char *clish_command__get_viewname(const clish_command_t * this)
|
|
{
|
|
return this->viewname;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_viewid(clish_command_t * this, const char *viewid)
|
|
{
|
|
assert(NULL == this->viewid);
|
|
clish_command__force_viewid(this, viewid);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__force_viewid(clish_command_t * this, const char *viewid)
|
|
{
|
|
if (this->viewid)
|
|
lub_string_free(this->viewid);
|
|
this->viewid = lub_string_dup(viewid);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
char *clish_command__get_viewid(const clish_command_t * this)
|
|
{
|
|
return this->viewid;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
const clish_param_t *clish_command__get_param(const clish_command_t * this,
|
|
unsigned index)
|
|
{
|
|
return clish_paramv__get_param(this->paramv, index);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
const char *clish_command__get_suffix(const clish_command_t * this)
|
|
{
|
|
return lub_string_suffix(this->name);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void
|
|
clish_command__set_escape_chars(clish_command_t * this,
|
|
const char *escape_chars)
|
|
{
|
|
assert(!this->escape_chars);
|
|
this->escape_chars = lub_string_dup(escape_chars);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
const char *clish_command__get_escape_chars(const clish_command_t * this)
|
|
{
|
|
return this->escape_chars;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_regex_chars(clish_command_t *this,
|
|
const char *escape_chars)
|
|
{
|
|
assert(!this->regex_chars);
|
|
this->regex_chars = lub_string_dup(escape_chars);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
const char *clish_command__get_regex_chars(const clish_command_t *this)
|
|
{
|
|
return this->regex_chars;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_args(clish_command_t * this, clish_param_t * args)
|
|
{
|
|
assert(NULL == this->args);
|
|
this->args = args;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
clish_param_t *clish_command__get_args(const clish_command_t * this)
|
|
{
|
|
return this->args;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
unsigned int clish_command__get_param_count(const clish_command_t * this)
|
|
{
|
|
return clish_paramv__get_count(this->paramv);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
clish_paramv_t *clish_command__get_paramv(const clish_command_t * this)
|
|
{
|
|
return this->paramv;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_pview(clish_command_t * this, clish_view_t * view)
|
|
{
|
|
this->pview = view;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
clish_view_t *clish_command__get_pview(const clish_command_t * this)
|
|
{
|
|
return this->pview;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
int clish_command__get_depth(const clish_command_t * this)
|
|
{
|
|
if (!this->pview)
|
|
return 0;
|
|
return clish_view__get_depth(this->pview);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
clish_view_restore_e clish_command__get_restore(const clish_command_t * this)
|
|
{
|
|
if (!this->pview)
|
|
return CLISH_RESTORE_NONE;
|
|
return clish_view__get_restore(this->pview);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
const clish_command_t * clish_command__get_orig(const clish_command_t * this)
|
|
{
|
|
if (this->link)
|
|
return clish_command__get_orig(this->link);
|
|
return this;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
bool_t clish_command__get_lock(const clish_command_t * this)
|
|
{
|
|
return this->lock;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_lock(clish_command_t * this, bool_t lock)
|
|
{
|
|
this->lock = lock;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_alias(clish_command_t * this, const char * alias)
|
|
{
|
|
if (this->alias)
|
|
lub_string_free(this->alias);
|
|
this->alias = lub_string_dup(alias);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
const char * clish_command__get_alias(const clish_command_t * this)
|
|
{
|
|
return this->alias;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_alias_view(clish_command_t *this,
|
|
const char *alias_view)
|
|
{
|
|
if (this->alias_view)
|
|
lub_string_free(this->alias_view);
|
|
this->alias_view = lub_string_dup(alias_view);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
const char * clish_command__get_alias_view(const clish_command_t * this)
|
|
{
|
|
return this->alias_view;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_dynamic(clish_command_t * this, bool_t dynamic)
|
|
{
|
|
this->dynamic = dynamic;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
bool_t clish_command__get_dynamic(const clish_command_t * this)
|
|
{
|
|
return this->dynamic;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
const clish_command_t * clish_command__get_cmd(const clish_command_t * this)
|
|
{
|
|
if (!this->dynamic)
|
|
return this;
|
|
if (this->link)
|
|
return clish_command__get_cmd(this->link);
|
|
return NULL;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
bool_t clish_command__get_interrupt(const clish_command_t * this)
|
|
{
|
|
return this->interrupt;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_interrupt(clish_command_t * this, bool_t interrupt)
|
|
{
|
|
this->interrupt = interrupt;
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
void clish_command__set_access(clish_command_t *this, const char *access)
|
|
{
|
|
if (this->access)
|
|
lub_string_free(this->access);
|
|
this->access = lub_string_dup(access);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|
|
char *clish_command__get_access(const clish_command_t *this)
|
|
{
|
|
return this->access;
|
|
}
|