hush: we can't do without variable->value member, saving 25 bytes of code

and some runtime memory. Rename few variables.
This commit is contained in:
Denis Vlasenko 2007-05-25 02:46:01 +00:00
parent d76c049cc4
commit 28c0f0f4fe

View File

@ -286,8 +286,7 @@ struct close_me {
#define setenv(...) setenv_is_leaky_dont_use()
struct variable {
struct variable *next;
char *name; /* points to "name=" portion */
char *value; /* points directly after "=" */
char *varstr; /* points to "name=" portion */
int max_len; /* if > 0, name is part of initial env; else name is malloced */
smallint flg_export; /* putenv should be done on this var */
smallint flg_read_only;
@ -334,8 +333,7 @@ static const char version_str[] = "HUSH_VERSION="HUSH_VER_STR;
static const struct variable const_shell_ver = {
.next = NULL,
.name = (char*)version_str,
.value = (char*)version_str + sizeof("HUSH_VERSION=")-1,
.varstr = (char*)version_str,
.max_len = 1, /* 0 can provoke free(name) */
.flg_export = 1,
.flg_read_only = 1,
@ -554,8 +552,8 @@ static char **expand_strvec_to_strvec(char **argv);
static char *expand_strvec_to_string(char **argv);
/* used for expansion of right hand of assignments */
static char *expand_string_to_string(const char *str);
static struct variable *get_local_var(const char *var);
static int set_local_var(char *s, int flg_export);
static struct variable *get_local_var(const char *name);
static int set_local_var(char *str, int flg_export);
static void unset_local_var(const char *name);
/* Table of built-in functions. They can be forked or not, depending on
@ -831,7 +829,7 @@ static int builtin_export(char **argv)
var = get_local_var(name);
if (var) {
var->flg_export = 1;
putenv(var->name);
putenv(var->varstr);
}
/* bash does not return an error when trying to export
* an undefined variable. Do likewise. */
@ -976,7 +974,7 @@ static int builtin_set(char **argv)
if (temp == NULL)
for (e = top_var; e; e = e->next)
puts(e->name);
puts(e->varstr);
else
set_local_var(xstrdup(temp), 0);
@ -2676,39 +2674,39 @@ static char* expand_strvec_to_string(char **argv)
}
/* This is used to get/check local shell variables */
static struct variable *get_local_var(const char *s)
static struct variable *get_local_var(const char *name)
{
struct variable *cur;
int len;
if (!s)
if (!name)
return NULL;
len = strlen(s);
len = strlen(name);
for (cur = top_var; cur; cur = cur->next) {
if (strncmp(cur->name, s, len) == 0 && cur->name[len] == '=')
if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
return cur;
}
return NULL;
}
/* name holds "NAME=VAL" and is expected to be malloced.
/* str holds "NAME=VAL" and is expected to be malloced.
* We take ownership of it. */
static int set_local_var(char *name, int flg_export)
static int set_local_var(char *str, int flg_export)
{
struct variable *cur;
char *value;
int name_len;
value = strchr(name, '=');
value = strchr(str, '=');
if (!value) { /* not expected to ever happen? */
free(name);
free(str);
return -1;
}
name_len = value - name;
name_len = value - str;
cur = top_var; /* cannot be NULL (we have HUSH_VERSION and it's RO) */
while (1) {
if (strncmp(cur->name, name, name_len) != 0 || cur->name[name_len] != '=') {
if (strncmp(cur->varstr, str, name_len) != 0 || cur->varstr[name_len] != '=') {
if (!cur->next) {
/* cur points to last var in linked list */
break;
@ -2716,45 +2714,44 @@ static int set_local_var(char *name, int flg_export)
cur = cur->next;
continue;
}
/* We already have a var with this name */
/* We found an existing var with this name */
*value = '\0';
if (cur->flg_read_only) {
bb_error_msg("%s: readonly variable", name);
free(name);
bb_error_msg("%s: readonly variable", str);
free(str);
return -1;
}
*value = '\0';
unsetenv(name); /* just in case */
*value++ = '=';
if (strcmp(cur->value, value) == 0) {
unsetenv(str); /* just in case */
*value = '=';
if (strcmp(cur->varstr, str) == 0) {
free_and_exp:
free(name);
free(str);
goto exp;
}
if (cur->max_len >= strlen(name)) {
if (cur->max_len >= strlen(str)) {
/* This one is from startup env, reuse space */
strcpy(cur->name, name);
strcpy(cur->varstr, str);
goto free_and_exp;
}
/* max_len == 0 signifies "malloced" var, which we can
* (and has to) free */
if (!cur->max_len)
free(cur->name);
free(cur->varstr);
cur->max_len = 0;
goto set_name_and_exp;
goto set_str_and_exp;
}
/* Not found - create next variable struct */
cur->next = xzalloc(sizeof(*cur));
cur = cur->next;
set_name_and_exp:
cur->name = name;
set_str_and_exp:
cur->varstr = str;
exp:
cur->value = cur->name + name_len + 1;
if (flg_export)
cur->flg_export = 1;
if (cur->flg_export)
return putenv(cur->name);
return putenv(cur->varstr);
return 0;
}
@ -2769,7 +2766,7 @@ static void unset_local_var(const char *name)
name_len = strlen(name);
cur = top_var;
while (cur) {
if (strncmp(cur->name, name, name_len) == 0 && cur->name[name_len] == '=') {
if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') {
if (cur->flg_read_only) {
bb_error_msg("%s: readonly variable", name);
return;
@ -2777,9 +2774,9 @@ static void unset_local_var(const char *name)
/* prev is ok to use here because 1st variable, HUSH_VERSION,
* is ro, and we cannot reach this code on the 1st pass */
prev->next = cur->next;
unsetenv(cur->name);
unsetenv(cur->varstr);
if (!cur->max_len)
free(cur->name);
free(cur->varstr);
free(cur);
return;
}
@ -3256,7 +3253,7 @@ static const char *lookup_param(const char *src)
{
struct variable *var = get_local_var(src);
if (var)
return var->value;
return strchr(var->varstr, '=') + 1;
return NULL;
}
@ -3682,14 +3679,13 @@ int hush_main(int argc, char **argv)
if (value) { /* paranoia */
cur_var->next = xzalloc(sizeof(*cur_var));
cur_var = cur_var->next;
cur_var->name = *e;
cur_var->value = value + 1;
cur_var->varstr = *e;
cur_var->max_len = strlen(*e);
cur_var->flg_export = 1;
}
e++;
}
putenv(shell_ver.name);
putenv(shell_ver.varstr);
#if ENABLE_FEATURE_EDITING
line_input_state = new_line_input_t(FOR_SHELL);
@ -3827,7 +3823,7 @@ int hush_main(int argc, char **argv)
while (cur_var) {
struct variable *tmp = cur_var;
if (!cur_var->max_len)
free(cur_var->name);
free(cur_var->varstr);
cur_var = cur_var->next;
free(tmp);
}