Browse Source

Refactoring of slow viewid mechanism

git-svn-id: https://klish.googlecode.com/svn/trunk@462 0eaa4687-2ee9-07dd-09d9-bcdd2d2dd5fb
Serj Kalichev 13 years ago
parent
commit
8e318602c2

+ 5 - 7
clish/shell.h

@@ -343,22 +343,20 @@ char *clish_shell_expand(const char *str, clish_shell_var_t vtype, clish_context
 /*-----------------
  * attributes
  *----------------- */
-const clish_view_t *clish_shell__get_view(const clish_shell_t * instance);
+clish_view_t *clish_shell__get_view(const clish_shell_t * instance);
 unsigned clish_shell__get_depth(const clish_shell_t * instance);
 const char *clish_shell__get_viewid(const clish_shell_t * instance);
 const char *clish_shell__get_overview(const clish_shell_t * instance);
 tinyrl_t *clish_shell__get_tinyrl(const clish_shell_t * instance);
 void *clish_shell__get_client_cookie(const clish_shell_t * instance);
 void
-clish_shell__set_pwd(clish_shell_t * instance, unsigned index,
-	const char * line, clish_view_t * view, char * viewid);
+clish_shell__set_pwd(clish_shell_t *instance, const char * line,
+	clish_view_t * view, char * viewid, clish_context_t *context);
 char *clish_shell__get_pwd_line(const clish_shell_t * instance,
-				 unsigned index);
+	 unsigned int index);
 char *clish_shell__get_pwd_full(const clish_shell_t * instance, unsigned depth);
 clish_view_t *clish_shell__get_pwd_view(const clish_shell_t * instance,
-				 unsigned index);
-char *clish_shell__get_pwd_viewid(const clish_shell_t * instance,
-				 unsigned index);
+	unsigned int index);
 konf_client_t *clish_shell__get_client(const clish_shell_t * instance);
 FILE *clish_shell__get_istream(const clish_shell_t * instance);
 FILE *clish_shell__get_ostream(const clish_shell_t * instance);

+ 11 - 8
clish/shell/private.h

@@ -33,7 +33,7 @@ struct clish_shell_file_s {
 typedef struct {
 	char *line;
 	clish_view_t *view;
-	char *viewid;
+	lub_bintree_t viewid;
 } clish_shell_pwd_t;
 
 struct clish_shell_s {
@@ -43,20 +43,19 @@ struct clish_shell_s {
 	const clish_shell_hooks_t *client_hooks;	/* Client callback hooks         */
 	void *client_cookie;	/* Client callback cookie        */
 	clish_view_t *global;	/* Reference to the global view. */
-	clish_view_t *view;	/* Reference to the current view. */
 	clish_command_t *startup;	/* This is the startup command   */
 	clish_shell_state_t state;	/* The current state               */
 	char *overview;		/* Overview text for this shell.  */
-	char *viewid;		/* The current view ID string     */
 	tinyrl_t *tinyrl;	/* Tiny readline instance          */
 	clish_shell_file_t *current_file;	/* file currently in use for input */
-	clish_shell_pwd_t **cfg_pwdv;	/* Levels for the config file structure */
-	unsigned cfg_pwdc;
+	clish_shell_pwd_t **pwdv;	/* Levels for the config file structure */
+	unsigned int pwdc;
+	int depth;
 	konf_client_t *client;
-	char * lockfile;
+	char *lockfile;
 	pthread_t pthread;
-	char * default_shebang;
-	char * fifo_name; /* The name of temporary fifo file. */
+	char *default_shebang;
+	char *fifo_name; /* The name of temporary fifo file. */
 	bool_t interactive; /* Is shell interactive. */
 
 	/* Static params for var expanding. The refactoring is needed. */
@@ -113,3 +112,7 @@ void clish_shell_param_generator(clish_shell_t * instance, lub_argv_t *matches,
 	const clish_command_t * cmd, const char *line, unsigned offset);
 char **clish_shell_tinyrl_completion(tinyrl_t * tinyrl,
 	const char *line, unsigned start, unsigned end);
+void clish_shell__expand_viewid(const char *viewid, lub_bintree_t *tree,
+	clish_context_t *context);
+void clish_shell__init_pwd(clish_shell_pwd_t *pwd);
+void clish_shell__fini_pwd(clish_shell_pwd_t *pwd);

+ 3 - 3
clish/shell/shell_command.c

@@ -23,7 +23,7 @@ const clish_command_t *clish_shell_resolve_command(const clish_shell_t * this,
 	clish_command_t *cmd, *result;
 
 	/* Search the current view */
-	result = clish_view_resolve_command(this->view, line, BOOL_TRUE);
+	result = clish_view_resolve_command(clish_shell__get_view(this), line, BOOL_TRUE);
 	/* Search the global view */
 	cmd = clish_view_resolve_command(this->global, line, BOOL_TRUE);
 
@@ -39,7 +39,7 @@ const clish_command_t *clish_shell_resolve_prefix(const clish_shell_t * this,
 	clish_command_t *cmd, *result;
 
 	/* Search the current view */
-	result = clish_view_resolve_prefix(this->view, line, BOOL_TRUE);
+	result = clish_view_resolve_prefix(clish_shell__get_view(this), line, BOOL_TRUE);
 	/* Search the global view */
 	cmd = clish_view_resolve_prefix(this->global, line, BOOL_TRUE);
 
@@ -55,7 +55,7 @@ const clish_command_t *clish_shell_find_next_completion(const clish_shell_t *
 	const clish_command_t *result, *cmd;
 
 	/* ask the local view for next command */
-	result = clish_view_find_next_completion(this->view,
+	result = clish_view_find_next_completion(clish_shell__get_view(this),
 		iter->last_cmd, line, iter->field, BOOL_TRUE);
 	/* ask the global view for next command */
 	cmd = clish_view_find_next_completion(this->global,

+ 13 - 48
clish/shell/shell_execute.c

@@ -101,8 +101,7 @@ static bool_t clish_source(clish_context_t *context, const lub_argv_t * argv)
  thread. Invoking a script in this way will cause the script to
  continue after command, but not script, errors.
 */
-static bool_t
-clish_source_nostop(clish_context_t *context, const lub_argv_t * argv)
+static bool_t clish_source_nostop(clish_context_t *context, const lub_argv_t * argv)
 {
 	return (clish_source_internal(context, argv, BOOL_FALSE));
 }
@@ -188,33 +187,21 @@ bool_t clish_shell_execute(clish_context_t *context, char **out)
 	int lock_fd = -1;
 	sigset_t old_sigs;
 	struct sigaction old_sigint, old_sigquit;
+	clish_view_t *cur_view = clish_shell__get_view(this);
 
 	assert(cmd);
 	action = clish_command__get_action(cmd);
 
 	/* Pre-change view if the command is from another depth/view */
         {
-		clish_view_t *view = NULL;
-		char *viewid = NULL;
 		clish_view_restore_t restore = clish_command__get_restore(cmd);
-
 		if ((CLISH_RESTORE_VIEW == restore) &&
-			(clish_command__get_pview(cmd) != this->view))
-			view = clish_command__get_pview(cmd);
-		else if ((CLISH_RESTORE_DEPTH == restore) &&
-			(clish_command__get_depth(cmd) <
-			clish_view__get_depth(this->view))) {
-			view = clish_shell__get_pwd_view(this,
-				clish_command__get_depth(cmd));
-			viewid = clish_shell__get_pwd_viewid(this,
-				clish_command__get_depth(cmd));
-		}
-
-		if (view) {
-			this->view = view;
-			/* cleanup */
-			lub_string_free(this->viewid);
-			this->viewid = lub_string_dup(viewid);
+			(clish_command__get_pview(cmd) != cur_view)) {
+			clish_view_t *view = clish_command__get_pview(cmd);
+			clish_shell__set_pwd(this, NULL, view, NULL, context);
+		} else if ((CLISH_RESTORE_DEPTH == restore) &&
+			(clish_command__get_depth(cmd) < this->depth)) {
+			this->depth = clish_command__get_depth(cmd);
 		}
 	}
 
@@ -295,22 +282,12 @@ bool_t clish_shell_execute(clish_context_t *context, char **out)
 	/* Move into the new view */
 	if (result) {
 		clish_view_t *view = clish_command__get_view(cmd);
-		char *viewid = clish_shell_expand(
-			clish_command__get_viewid(cmd), SHELL_VAR_ACTION, context);
+		/* Save the PWD */
 		if (view) {
-			/* Save the current config PWD */
 			char *line = clish_shell__get_line(context);
-			clish_shell__set_pwd(this,
-				clish_command__get_depth(cmd),
-				line, this->view, this->viewid);
+			clish_shell__set_pwd(this, line, view,
+				clish_command__get_viewid(cmd), context);
 			lub_string_free(line);
-			/* Change view */
-			this->view = view;
-		}
-		if (viewid || view) {
-			/* cleanup */
-			lub_string_free(this->viewid);
-			this->viewid = viewid;
 		}
 	}
 
@@ -360,30 +337,18 @@ bool_t clish_shell_exec_action(clish_action_t *action,
 static bool_t clish_nested_up(clish_context_t *context, const lub_argv_t * argv)
 {
 	clish_shell_t *this = context->shell;
-	clish_view_t *view = NULL;
-	char *viewid = NULL;
-	int depth = 0;
 
 	if (!this)
 		return BOOL_FALSE;
 
 	argv = argv; /* not used */
-	depth = clish_view__get_depth(this->view);
 
 	/* If depth=0 than exit */
-	if (0 == depth) {
+	if (0 == this->depth) {
 		this->state = SHELL_STATE_CLOSING;
 		return BOOL_TRUE;
 	}
-
-	depth--;
-	view = clish_shell__get_pwd_view(this, depth);
-	viewid = clish_shell__get_pwd_viewid(this, depth);
-	if (!view)
-		return BOOL_FALSE;
-	this->view = view;
-	lub_string_free(this->viewid);
-	this->viewid = viewid ? lub_string_dup(viewid) : NULL;
+	this->depth--;
 
 	return BOOL_TRUE;
 }

+ 7 - 12
clish/shell/shell_new.c

@@ -38,16 +38,15 @@ static void clish_shell_init(clish_shell_t * this,
 	/* set up defaults */
 	this->client_hooks = hooks;
 	this->client_cookie = cookie;
-	this->view = NULL;
-	this->viewid = NULL;
 	this->global = NULL;
 	this->startup = NULL;
 	this->state = SHELL_STATE_INITIALISING;
 	this->overview = NULL;
 	this->tinyrl = clish_shell_tinyrl_new(istream, ostream, 0);
 	this->current_file = NULL;
-	this->cfg_pwdv = NULL;
-	this->cfg_pwdc = 0;
+	this->pwdv = NULL;
+	this->pwdc = 0;
+	this->depth = -1; /* Current depth is undefined */
 	this->client = NULL;
 	this->lockfile = lub_string_dup(CLISH_LOCK_PATH);
 	this->default_shebang = lub_string_dup("/bin/sh");
@@ -113,7 +112,6 @@ static void clish_shell_fini(clish_shell_t * this)
 
 	/* free the textual details */
 	lub_string_free(this->overview);
-	lub_string_free(this->viewid);
 
 	/* remove the startup command */
 	if (this->startup)
@@ -124,15 +122,12 @@ static void clish_shell_fini(clish_shell_t * this)
 	clish_shell_tinyrl_delete(this->tinyrl);
 
 	/* finalize each of the pwd strings */
-	for (i = 0; i < this->cfg_pwdc; i++) {
-		lub_string_free(this->cfg_pwdv[i]->line);
-		lub_string_free(this->cfg_pwdv[i]->viewid);
-		free(this->cfg_pwdv[i]);
+	for (i = 0; i < this->pwdc; i++) {
+		clish_shell__fini_pwd(this->pwdv[i]);
+		free(this->pwdv[i]);
 	}
 	/* free the pwd vector */
-	free(this->cfg_pwdv);
-	this->cfg_pwdc = 0;
-	this->cfg_pwdv = NULL;
+	free(this->pwdv);
 	konf_client_free(this->client);
 
 	/* Free internal params */

+ 48 - 36
clish/shell/shell_pwd.c

@@ -8,49 +8,70 @@
 #include "private.h"
 
 /*--------------------------------------------------------- */
-void
-clish_shell__set_pwd(clish_shell_t * this, unsigned index,
-	const char * line, clish_view_t * view, char * viewid)
+void clish_shell__init_pwd(clish_shell_pwd_t *pwd)
+{
+	pwd->line = NULL;
+	pwd->view = NULL;
+	/* initialise the tree of vars */
+	lub_bintree_init(&pwd->viewid,
+		clish_var_bt_offset(),
+		clish_var_bt_compare, clish_var_bt_getkey);
+}
+
+/*--------------------------------------------------------- */
+void clish_shell__fini_pwd(clish_shell_pwd_t *pwd)
+{
+	clish_var_t *var;
+
+	lub_string_free(pwd->line);
+	pwd->view = NULL;
+	/* delete each VAR held  */
+	while ((var = lub_bintree_findfirst(&pwd->viewid))) {
+		lub_bintree_remove(&pwd->viewid, var);
+		clish_var_delete(var);
+	}
+}
+
+/*--------------------------------------------------------- */
+void clish_shell__set_pwd(clish_shell_t *this,
+	const char *line, clish_view_t *view, char *viewid, clish_context_t *context)
 {
 	clish_shell_pwd_t **tmp;
 	size_t new_size = 0;
 	unsigned i;
+	unsigned int index = clish_view__get_depth(view);
 
 	/* Create new element */
-	if (index >= this->cfg_pwdc) {
+	if (index >= this->pwdc) {
 		new_size = (index + 1) * sizeof(clish_shell_pwd_t *);
 		/* resize the pwd vector */
-		tmp = realloc(this->cfg_pwdv, new_size);
+		tmp = realloc(this->pwdv, new_size);
 		assert(tmp);
-		this->cfg_pwdv = tmp;
+		this->pwdv = tmp;
 		/* Initialize new elements */
-		for (i = this->cfg_pwdc; i <= index; i++) {
-			clish_shell_pwd_t *pwd;
-
-			pwd = malloc(sizeof(*pwd));
+		for (i = this->pwdc; i <= index; i++) {
+			clish_shell_pwd_t *pwd = malloc(sizeof(*pwd));
 			assert(pwd);
-			pwd->line = NULL;
-			pwd->view = NULL;
-			pwd->viewid = NULL;
-			this->cfg_pwdv[i] = pwd;
+			clish_shell__init_pwd(pwd);
+			this->pwdv[i] = pwd;
 		}
-		this->cfg_pwdc = index + 1;
+		this->pwdc = index + 1;
 	}
 
-	lub_string_free(this->cfg_pwdv[index]->line);
-	this->cfg_pwdv[index]->line = line ? lub_string_dup(line) : NULL;
-	this->cfg_pwdv[index]->view = view;
-	lub_string_free(this->cfg_pwdv[index]->viewid);
-	this->cfg_pwdv[index]->viewid = viewid ? lub_string_dup(viewid) : NULL;
+	clish_shell__fini_pwd(this->pwdv[index]);
+	this->pwdv[index]->line = line ? lub_string_dup(line) : NULL;
+	this->pwdv[index]->view = view;
+	clish_shell__expand_viewid(viewid, &this->pwdv[index]->viewid, context);
+	this->depth = index;
 }
 
 /*--------------------------------------------------------- */
-char *clish_shell__get_pwd_line(const clish_shell_t * this, unsigned index)
+char *clish_shell__get_pwd_line(const clish_shell_t *this, unsigned int index)
 {
-	if (index >= this->cfg_pwdc)
+	if (index >= this->pwdc)
 		return NULL;
 
-	return this->cfg_pwdv[index]->line;
+	return this->pwdv[index]->line;
 }
 
 /*--------------------------------------------------------- */
@@ -59,7 +80,7 @@ char *clish_shell__get_pwd_full(const clish_shell_t * this, unsigned depth)
 	char *pwd = NULL;
 	unsigned i;
 
-	for (i = 0; i < depth; i++) {
+	for (i = 1; i <= depth; i++) {
 		const char *str =
 			clish_shell__get_pwd_line(this, i);
 		/* Cannot get full path */
@@ -78,21 +99,12 @@ char *clish_shell__get_pwd_full(const clish_shell_t * this, unsigned depth)
 }
 
 /*--------------------------------------------------------- */
-clish_view_t *clish_shell__get_pwd_view(const clish_shell_t * this, unsigned index)
-{
-	if (index >= this->cfg_pwdc)
-		return NULL;
-
-	return this->cfg_pwdv[index]->view;
-}
-
-/*--------------------------------------------------------- */
-char *clish_shell__get_pwd_viewid(const clish_shell_t * this, unsigned index)
+clish_view_t *clish_shell__get_pwd_view(const clish_shell_t * this, unsigned int index)
 {
-	if (index >= this->cfg_pwdc)
+	if (index >= this->pwdc)
 		return NULL;
 
-	return this->cfg_pwdv[index]->viewid;
+	return this->pwdv[index]->view;
 }
 
 /*--------------------------------------------------------- */

+ 2 - 2
clish/shell/shell_tinyxml.cpp

@@ -652,7 +652,7 @@ static void process_var(clish_shell_t * shell, TiXmlElement * element, void *)
 
 	assert(name);
 	/* Check if this var doesn't already exist */
-	var = clish_shell_find_var(shell, name);
+	var = (clish_var_t *)lub_bintree_find(&shell->var_tree, name);
 	if (var) {
 		printf("DUPLICATE VAR: %s\n", name);
 		assert(!var);
@@ -660,7 +660,7 @@ static void process_var(clish_shell_t * shell, TiXmlElement * element, void *)
 
 	/* Create var instance */
 	var = clish_var_new(name);
-	clish_shell_insert_var(shell, var);
+	lub_bintree_insert(&shell->var_tree, var);
 
 	if (dynamic && (lub_string_nocasecmp(dynamic, "true") == 0))
 		clish_var__set_dynamic(var, BOOL_TRUE);

+ 43 - 56
clish/shell/shell_var.c

@@ -10,63 +10,36 @@
 #include "lub/string.h"
 #include "private.h"
 
-/*--------------------------------------------------------- */
-void clish_shell_insert_var(clish_shell_t *this, clish_var_t *var)
-{
-	(void)lub_bintree_insert(&this->var_tree, var);
-}
-
-/*--------------------------------------------------------- */
-clish_var_t *clish_shell_find_var(clish_shell_t *this, const char *name)
-{
-	return lub_bintree_find(&this->var_tree, name);
-}
-
-/*--------------------------------------------------------- */
-const char *clish_shell__get_viewid(const clish_shell_t *this)
-{
-	assert(this);
-	return this->viewid;
-}
-
 /*----------------------------------------------------------- */
 /*
  * search the current viewid string for a variable
  */
-static char *find_viewid_var(const char *name, const char *viewid)
+void clish_shell__expand_viewid(const char *viewid, lub_bintree_t *tree,
+	clish_context_t *context)
 {
-	char *result = NULL;
-	regex_t regex;
-	int status;
-	char *pattern = NULL;
-	regmatch_t pmatches[2];
-
-	/* build up the pattern to match */
-	lub_string_cat(&pattern, name);
-	lub_string_cat(&pattern, "[ ]*=([^;]*)");
-
-	/* compile the regular expression to find this variable */
-	status = regcomp(&regex, pattern, REG_EXTENDED);
-	assert(0 == status);
-	lub_string_free(pattern);
-
-	/* now perform the matching */
-	/*lint -e64 Type mismatch (arg. no. 4) */
-	/*
-	 * lint seems to equate regmatch_t[] as being of type regmatch_t !
-	 */
-	status = regexec(&regex, viewid, 2, pmatches, 0);
-	/*lint +e64 */
-	if (0 == status) {
-		regoff_t len = pmatches[1].rm_eo - pmatches[1].rm_so;
-		const char *value = &viewid[pmatches[1].rm_so];
-		/* found a match */
-		result = lub_string_dupn(value, (unsigned)len);
-	}
-	/* release the regular expression */
-	regfree(&regex);
+	char *expanded;
+	char *q, *saveptr;
 
-	return result;
+	expanded = clish_shell_expand(viewid, SHELL_VAR_NONE, context);
+	if (!expanded)
+		return;
+
+	for (q = strtok_r(expanded, ";", &saveptr);
+		q; q = strtok_r(NULL, ";", &saveptr)) {
+		char *value;
+		clish_var_t *var;
+
+		value = strchr(q, '=');
+		if (!value)
+			continue;
+		*value = '\0';
+		value++;
+		/* Create var instance */
+		var = clish_var_new(q);
+		lub_bintree_insert(tree, var);
+		clish_var__set_value(var, value);
+	}
+	lub_string_free(expanded);
 }
 
 /*----------------------------------------------------------- */
@@ -112,10 +85,9 @@ static char *find_context_var(const char *name, clish_context_t *this)
 }
 
 /*--------------------------------------------------------- */
-static char *find_global_var(const char *name, clish_context_t *context)
+static char *find_var(const char *name, lub_bintree_t *tree, clish_context_t *context)
 {
-	clish_shell_t *this = context->shell;
-	clish_var_t *var = clish_shell_find_var(this, name);
+	clish_var_t *var = lub_bintree_find(tree, name);
 	clish_action_t *action;
 	char *value;
 	char *script;
@@ -159,6 +131,21 @@ static char *find_global_var(const char *name, clish_context_t *context)
 	return res;
 }
 
+/*--------------------------------------------------------- */
+static char *find_global_var(const char *name, clish_context_t *context)
+{
+	return find_var(name, &context->shell->var_tree, context);
+}
+
+/*--------------------------------------------------------- */
+static char *find_viewid_var(const char *name, clish_context_t *context)
+{
+	int depth = clish_shell__get_depth(context->shell);
+	if (depth < 0)
+		return NULL;
+	return find_var(name, &context->shell->pwdv[depth]->viewid, context);
+}
+
 /*--------------------------------------------------------- */
 /*
  * return the next segment of text from the provided string
@@ -401,8 +388,8 @@ char *clish_shell_expand_var(const char *name, clish_context_t *context)
 		tmp = clish_paramv_find_default(
 			clish_command__get_paramv(cmd), name);
 	/* try and substitute a viewId variable */
-	if (!tmp && this && this->viewid)
-		tmp = string = find_viewid_var(name, this->viewid);
+	if (!tmp && this)
+		tmp = string = find_viewid_var(name, context);
 	/* try and substitute context fixed variable */
 	if (!tmp)
 		tmp = string = find_context_var(name, context);

+ 5 - 3
clish/shell/shell_view.c

@@ -38,17 +38,19 @@ void clish_shell_insert_view(clish_shell_t * this, clish_view_t * view)
 }
 
 /*--------------------------------------------------------- */
-const clish_view_t *clish_shell__get_view(const clish_shell_t * this)
+clish_view_t *clish_shell__get_view(const clish_shell_t * this)
 {
 	assert(this);
-	return this->view;
+	if (this->depth < 0)
+		return NULL;
+	return this->pwdv[this->depth]->view;
 }
 
 /*--------------------------------------------------------- */
 unsigned clish_shell__get_depth(const clish_shell_t * this)
 {
 	assert(this);
-	return clish_view__get_depth(this->view);
+	return this->depth;
 }
 
 /*--------------------------------------------------------- */