|
@@ -1,8 +1,10 @@
|
|
|
|
|
|
- * shell_expand.c
|
|
|
+ * shell_var.c
|
|
|
*/
|
|
|
+
|
|
|
#include <stdlib.h>
|
|
|
#include <assert.h>
|
|
|
+#include <string.h>
|
|
|
|
|
|
#include "lub/string.h"
|
|
|
#include "private.h"
|
|
@@ -19,31 +21,292 @@ clish_var_t *clish_shell_find_var(clish_shell_t *this, const char *name)
|
|
|
return lub_bintree_find(&this->var_tree, name);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-char * clish_shell__expand_text(const clish_shell_t *this,
|
|
|
- clish_command_t *cmd, clish_pargv_t *pargv, const char *text)
|
|
|
+
|
|
|
+const char *clish_shell__get_viewid(const clish_shell_t *this)
|
|
|
{
|
|
|
assert(this);
|
|
|
- if (!text)
|
|
|
- return NULL;
|
|
|
- return clish_variable_expand(text, this->viewid, cmd, pargv);
|
|
|
+ return this->viewid;
|
|
|
}
|
|
|
|
|
|
|
|
|
-char * clish_shell__expand_variable(const clish_shell_t *this,
|
|
|
- clish_command_t *cmd, clish_pargv_t *pargv, const char *var)
|
|
|
+
|
|
|
+ * search the current viewid string for a variable
|
|
|
+ */
|
|
|
+static char *find_viewid_var(const char *name, const char *viewid)
|
|
|
{
|
|
|
- assert(this);
|
|
|
- if (!var)
|
|
|
+ char *result = NULL;
|
|
|
+ regex_t regex;
|
|
|
+ int status;
|
|
|
+ char *pattern = NULL;
|
|
|
+ regmatch_t pmatches[2];
|
|
|
+
|
|
|
+
|
|
|
+ lub_string_cat(&pattern, name);
|
|
|
+ lub_string_cat(&pattern, "[ ]*=([^;]*)");
|
|
|
+
|
|
|
+
|
|
|
+ status = regcomp(®ex, pattern, REG_EXTENDED);
|
|
|
+ assert(0 == status);
|
|
|
+ lub_string_free(pattern);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * lint seems to equate regmatch_t[] as being of type regmatch_t !!!
|
|
|
+ */
|
|
|
+ status = regexec(®ex, viewid, 2, pmatches, 0);
|
|
|
+
|
|
|
+ if (0 == status) {
|
|
|
+ regoff_t len = pmatches[1].rm_eo - pmatches[1].rm_so;
|
|
|
+ const char *value = &viewid[pmatches[1].rm_so];
|
|
|
+
|
|
|
+ result = lub_string_dupn(value, (unsigned)len);
|
|
|
+ }
|
|
|
+
|
|
|
+ regfree(®ex);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * expand context dependent fixed-name variables
|
|
|
+ */
|
|
|
+static char *find_context_var(const char *name, clish_context_t *this)
|
|
|
+{
|
|
|
+ char *result = NULL;
|
|
|
+
|
|
|
+ if (!this->cmd)
|
|
|
return NULL;
|
|
|
- return clish_variable__get_value(var, this->viewid, cmd, pargv);
|
|
|
+ if (!lub_string_nocasecmp(name, "__full_cmd")) {
|
|
|
+ result = lub_string_dup(clish_command__get_name(this->cmd));
|
|
|
+ } else if (!lub_string_nocasecmp(name, "__cmd")) {
|
|
|
+ result = lub_string_dup(clish_command__get_name(
|
|
|
+ clish_command__get_cmd(this->cmd)));
|
|
|
+ } else if (!lub_string_nocasecmp(name, "__orig_cmd")) {
|
|
|
+ result = lub_string_dup(clish_command__get_name(
|
|
|
+ clish_command__get_orig(this->cmd)));
|
|
|
+ } else if (!lub_string_nocasecmp(name, "__line")) {
|
|
|
+ if (this->pargv)
|
|
|
+ result = clish_shell__get_line(this->cmd, this->pargv);
|
|
|
+ } else if (!lub_string_nocasecmp(name, "__params")) {
|
|
|
+ if (this->pargv)
|
|
|
+ result = clish_shell__get_params(this->cmd, this->pargv);
|
|
|
+ } else if (lub_string_nocasestr(name, "__prefix") == name) {
|
|
|
+ int idx = 0;
|
|
|
+ int pnum = 0;
|
|
|
+ pnum = lub_argv_wordcount(clish_command__get_name(this->cmd)) -
|
|
|
+ lub_argv_wordcount(clish_command__get_name(
|
|
|
+ clish_command__get_cmd(this->cmd)));
|
|
|
+ idx = atoi(name + strlen("__prefix"));
|
|
|
+ if (idx < pnum) {
|
|
|
+ lub_argv_t *argv = lub_argv_new(
|
|
|
+ clish_command__get_name(this->cmd), 0);
|
|
|
+ result = lub_string_dup(lub_argv__get_arg(argv, idx));
|
|
|
+ lub_argv_delete(argv);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
|
|
|
-const char *clish_shell__get_viewid(const clish_shell_t *this)
|
|
|
+
|
|
|
+ * return the next segment of text from the provided string
|
|
|
+ * segments are delimited by variables within the string.
|
|
|
+ */
|
|
|
+static char *expand_nextsegment(const char **string, clish_context_t *this)
|
|
|
{
|
|
|
- assert(this);
|
|
|
- return this->viewid;
|
|
|
+ const char *p = *string;
|
|
|
+ char *result = NULL;
|
|
|
+ size_t len = 0;
|
|
|
+
|
|
|
+ if (p) {
|
|
|
+ if (*p && (p[0] == '$') && (p[1] == '{')) {
|
|
|
+
|
|
|
+ const char *tmp;
|
|
|
+ p += 2;
|
|
|
+ tmp = p;
|
|
|
+
|
|
|
+
|
|
|
+ * find the end of the variable
|
|
|
+ */
|
|
|
+ while (*p && p++[0] != '}') {
|
|
|
+ len++;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (p[-1] == '}') {
|
|
|
+ bool_t valid = BOOL_FALSE;
|
|
|
+ char *text, *q;
|
|
|
+ char *saveptr;
|
|
|
+
|
|
|
+
|
|
|
+ text = lub_string_dupn(tmp, len);
|
|
|
+
|
|
|
+ * tokenise this INTO ':' separated words
|
|
|
+ * and either expand or duplicate into the result string.
|
|
|
+ * Only return a result if at least
|
|
|
+ * of the words is an expandable variable
|
|
|
+ */
|
|
|
+ for (q = strtok_r(text, ":", &saveptr);
|
|
|
+ q; q = strtok_r(NULL, ":", &saveptr)) {
|
|
|
+ char *var = clish_shell_expand_var(q, this);
|
|
|
+
|
|
|
+
|
|
|
+ lub_string_cat(&result, var ? var : q);
|
|
|
+
|
|
|
+
|
|
|
+ if (var)
|
|
|
+ valid = BOOL_TRUE;
|
|
|
+ lub_string_free(var);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!valid) {
|
|
|
+
|
|
|
+ lub_string_free(result);
|
|
|
+ result = lub_string_dup("");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ lub_string_free(text);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+ while (*p) {
|
|
|
+ if ((p[0] == '$') && (p[1] == '{'))
|
|
|
+ break;
|
|
|
+ len++;
|
|
|
+ p++;
|
|
|
+ }
|
|
|
+ if (len > 0)
|
|
|
+ result = lub_string_dupn(*string, len);
|
|
|
+ }
|
|
|
+
|
|
|
+ *string = p;
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * This function builds a dynamic string based on that provided
|
|
|
+ * subtituting each occurance of a "${FRED}" type variable sub-string
|
|
|
+ * with the appropriate value.
|
|
|
+ */
|
|
|
+char *clish_shell_expand(const char *str, void *context)
|
|
|
+{
|
|
|
+ char *seg, *result = NULL;
|
|
|
+
|
|
|
+
|
|
|
+ while ((seg = expand_nextsegment(&str, context))) {
|
|
|
+ lub_string_cat(&result, seg);
|
|
|
+ lub_string_free(seg);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+char *clish_shell__get_params(const clish_command_t *cmd, clish_pargv_t *pargv)
|
|
|
+{
|
|
|
+ char *line = NULL;
|
|
|
+ unsigned i, cnt;
|
|
|
+ const clish_param_t *param;
|
|
|
+ const clish_parg_t *parg;
|
|
|
+
|
|
|
+ if (!pargv)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ cnt = clish_pargv__get_count(pargv);
|
|
|
+ for (i = 0; i < cnt; i++) {
|
|
|
+ const char *tmp;
|
|
|
+ char *space = NULL;
|
|
|
+ param = clish_pargv__get_param(pargv, i);
|
|
|
+ if (clish_param__get_hidden(param))
|
|
|
+ continue;
|
|
|
+ parg = clish_pargv__get_parg(pargv, i);
|
|
|
+ tmp = clish_parg__get_value(parg);
|
|
|
+ space = strchr(tmp, ' ');
|
|
|
+ if (line)
|
|
|
+ lub_string_cat(&line, " ");
|
|
|
+ if (space)
|
|
|
+ lub_string_cat(&line, "\\\"");
|
|
|
+ lub_string_cat(&line, tmp);
|
|
|
+ if (space)
|
|
|
+ lub_string_cat(&line, "\\\"");
|
|
|
+ }
|
|
|
+
|
|
|
+ return line;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+char *clish_shell__get_line(const clish_command_t *cmd, clish_pargv_t *pargv)
|
|
|
+{
|
|
|
+ char *line = NULL;
|
|
|
+ char *params = NULL;
|
|
|
+
|
|
|
+ lub_string_cat(&line, clish_command__get_name(
|
|
|
+ clish_command__get_cmd(cmd)));
|
|
|
+
|
|
|
+ if (!pargv)
|
|
|
+ return line;
|
|
|
+
|
|
|
+ params = clish_shell__get_params(cmd, pargv);
|
|
|
+ if (params) {
|
|
|
+ lub_string_cat(&line, " ");
|
|
|
+ lub_string_cat(&line, params);
|
|
|
+ }
|
|
|
+ lub_string_free(params);
|
|
|
+
|
|
|
+ return line;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+char *clish_shell_expand_var(const char *name, void *context)
|
|
|
+{
|
|
|
+ clish_shell_context_t *this = (clish_context_t *)context;
|
|
|
+ char *result = NULL;
|
|
|
+ const char *tmp = NULL;
|
|
|
+ const char *escape_chars = NULL;
|
|
|
+ char *string = NULL;
|
|
|
+ assert(name);
|
|
|
+
|
|
|
+
|
|
|
+ if (this && this->pargv) {
|
|
|
+ const clish_parg_t *parg =
|
|
|
+ clish_pargv_find_arg(this->pargv, name);
|
|
|
+
|
|
|
+ if (parg)
|
|
|
+ tmp = clish_parg__get_value(parg);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!tmp) {
|
|
|
+ if (this && this->cmd)
|
|
|
+ tmp = clish_paramv_find_default(
|
|
|
+ clish_command__get_paramv(this->cmd), name);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!tmp) {
|
|
|
+ if (this && this->shell->viewid)
|
|
|
+ tmp = string = find_viewid_var(name, this->shell->viewid);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!tmp)
|
|
|
+ tmp = string = find_context_var(name, this);
|
|
|
+
|
|
|
+ if (!tmp)
|
|
|
+ tmp = getenv(name);
|
|
|
+
|
|
|
+
|
|
|
+ if (this && this->cmd)
|
|
|
+ escape_chars = clish_command__get_escape_chars(this->cmd);
|
|
|
+ result = lub_string_encode(tmp, escape_chars);
|
|
|
+
|
|
|
+ if (string)
|
|
|
+ lub_string_free(string);
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
|