hush: convert exp/ro/local parameters to bitfields in one flag param
function old new delta helper_export_local 174 185 +11 set_local_var 424 420 -4 run_list 1048 1044 -4 set_vars_and_save_old 88 83 -5 set_local_var_from_halves 27 22 -5 run_pipe 1554 1549 -5 builtin_export 173 168 -5 set_pwd_var 40 34 -6 builtin_readonly 70 64 -6 expand_one_var 1625 1618 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/9 up/down: 11/-47) Total: -36 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
6b0695bb66
commit
3bab36b18b
81
shell/hush.c
81
shell/hush.c
@ -2057,25 +2057,20 @@ static const char* FAST_FUNC get_local_var_value(const char *name)
|
||||
|
||||
/* str holds "NAME=VAL" and is expected to be malloced.
|
||||
* We take ownership of it.
|
||||
* flg_export:
|
||||
* 0: do not change export flag
|
||||
* (if creating new variable, flag will be 0)
|
||||
* 1: set export flag and putenv the variable
|
||||
* -1: clear export flag and unsetenv the variable
|
||||
* flg_read_only is set only when we handle -R var=val
|
||||
*/
|
||||
static int set_local_var(char *str,
|
||||
int flg_export UNUSED_PARAM,
|
||||
int local_lvl UNUSED_PARAM,
|
||||
int flg_read_only UNUSED_PARAM)
|
||||
#define SETFLAG_EXPORT (1 << 0)
|
||||
#define SETFLAG_UNEXPORT (1 << 1)
|
||||
#define SETFLAG_MAKE_RO (1 << 2)
|
||||
#define SETFLAG_LOCAL_SHIFT 3
|
||||
static int set_local_var(char *str, unsigned flags)
|
||||
{
|
||||
struct variable **var_pp;
|
||||
struct variable *cur;
|
||||
char *free_me = NULL;
|
||||
char *eq_sign;
|
||||
int name_len;
|
||||
IF_HUSH_LOCAL(unsigned local_lvl = (flags >> SETFLAG_LOCAL_SHIFT);)
|
||||
|
||||
//bb_error_msg("set_local_var('%s',%d,%d,%d)", str, flg_export, local_lvl, flg_read_only);
|
||||
eq_sign = strchr(str, '=');
|
||||
if (!eq_sign) { /* not expected to ever happen? */
|
||||
free(str);
|
||||
@ -2096,7 +2091,7 @@ static int set_local_var(char *str,
|
||||
free(str);
|
||||
return -1;
|
||||
}
|
||||
if (flg_export == -1) { // "&& cur->flg_export" ?
|
||||
if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ?
|
||||
debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
|
||||
*eq_sign = '\0';
|
||||
unsetenv(str);
|
||||
@ -2120,7 +2115,7 @@ static int set_local_var(char *str,
|
||||
* z=z
|
||||
*/
|
||||
if (cur->flg_export)
|
||||
flg_export = 1;
|
||||
flags |= SETFLAG_EXPORT;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -2151,9 +2146,7 @@ static int set_local_var(char *str,
|
||||
|
||||
/* Not found - create new variable struct */
|
||||
cur = xzalloc(sizeof(*cur));
|
||||
#if ENABLE_HUSH_LOCAL
|
||||
cur->func_nest_level = local_lvl;
|
||||
#endif
|
||||
IF_HUSH_LOCAL(cur->func_nest_level = local_lvl;)
|
||||
cur->next = *var_pp;
|
||||
*var_pp = cur;
|
||||
|
||||
@ -2161,16 +2154,16 @@ static int set_local_var(char *str,
|
||||
cur->varstr = str;
|
||||
exp:
|
||||
#if !BB_MMU || ENABLE_HUSH_READONLY
|
||||
if (flg_read_only != 0) {
|
||||
cur->flg_read_only = flg_read_only;
|
||||
if (flags & SETFLAG_MAKE_RO) {
|
||||
cur->flg_read_only = 1;
|
||||
}
|
||||
#endif
|
||||
if (flg_export == 1)
|
||||
if (flags & SETFLAG_EXPORT)
|
||||
cur->flg_export = 1;
|
||||
if (name_len == 4 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S')
|
||||
cmdedit_update_prompt();
|
||||
if (cur->flg_export) {
|
||||
if (flg_export == -1) {
|
||||
if (flags & SETFLAG_UNEXPORT) {
|
||||
cur->flg_export = 0;
|
||||
/* unsetenv was already done */
|
||||
} else {
|
||||
@ -2187,10 +2180,9 @@ static int set_local_var(char *str,
|
||||
}
|
||||
|
||||
/* Used at startup and after each cd */
|
||||
static void set_pwd_var(int exp)
|
||||
static void set_pwd_var(unsigned flag)
|
||||
{
|
||||
set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)),
|
||||
/*exp:*/ exp, /*lvl:*/ 0, /*ro:*/ 0);
|
||||
set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag);
|
||||
}
|
||||
|
||||
static int unset_local_var_len(const char *name, int name_len)
|
||||
@ -2248,7 +2240,7 @@ static void unset_vars(char **strings)
|
||||
static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
|
||||
{
|
||||
char *var = xasprintf("%s=%s", name, val);
|
||||
set_local_var(var, /*flags:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
|
||||
set_local_var(var, /*flag:*/ 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2299,7 +2291,7 @@ static struct variable *set_vars_and_save_old(char **strings)
|
||||
var_p->next = old;
|
||||
old = var_p;
|
||||
}
|
||||
set_local_var(*s, /*exp:*/ 1, /*lvl:*/ 0, /*ro:*/ 0);
|
||||
set_local_var(*s, SETFLAG_EXPORT);
|
||||
}
|
||||
s++;
|
||||
}
|
||||
@ -5805,7 +5797,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
||||
val = NULL;
|
||||
} else {
|
||||
char *new_var = xasprintf("%s=%s", var, val);
|
||||
set_local_var(new_var, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
|
||||
set_local_var(new_var, /*flag:*/ 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7775,7 +7767,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
||||
if (new_env) {
|
||||
argv = new_env;
|
||||
while (*argv) {
|
||||
set_local_var(*argv, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
|
||||
set_local_var(*argv, /*flag:*/ 0);
|
||||
/* Do we need to flag set_local_var() errors?
|
||||
* "assignment to readonly var" and "putenv error"
|
||||
*/
|
||||
@ -7803,7 +7795,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
||||
fprintf(stderr, " %s", p);
|
||||
debug_printf_exec("set shell var:'%s'->'%s'\n",
|
||||
*argv, p);
|
||||
set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
|
||||
set_local_var(p, /*flag:*/ 0);
|
||||
/* Do we need to flag set_local_var() errors?
|
||||
* "assignment to readonly var" and "putenv error"
|
||||
*/
|
||||
@ -8215,7 +8207,7 @@ static int run_list(struct pipe *pi)
|
||||
}
|
||||
/* Insert next value from for_lcur */
|
||||
/* note: *for_lcur already has quotes removed, $var expanded, etc */
|
||||
set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
|
||||
set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*flag:*/ 0);
|
||||
continue;
|
||||
}
|
||||
if (rword == RES_IN) {
|
||||
@ -8600,7 +8592,7 @@ int hush_main(int argc, char **argv)
|
||||
putenv(shell_ver->varstr);
|
||||
|
||||
/* Export PWD */
|
||||
set_pwd_var(/*exp:*/ 1);
|
||||
set_pwd_var(SETFLAG_EXPORT);
|
||||
|
||||
#if BASH_HOSTNAME_VAR
|
||||
/* Set (but not export) HOSTNAME unless already set */
|
||||
@ -8770,7 +8762,7 @@ int hush_main(int argc, char **argv)
|
||||
}
|
||||
case 'R':
|
||||
case 'V':
|
||||
set_local_var(xstrdup(optarg), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ opt == 'R');
|
||||
set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0);
|
||||
break;
|
||||
# if ENABLE_HUSH_FUNCTIONS
|
||||
case 'F': {
|
||||
@ -9073,7 +9065,7 @@ static int FAST_FUNC builtin_cd(char **argv)
|
||||
* Note: do not enforce exporting. If PWD was unset or unexported,
|
||||
* set it again, but do not export. bash does the same.
|
||||
*/
|
||||
set_pwd_var(/*exp:*/ 0);
|
||||
set_pwd_var(/*flag:*/ 0);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -9312,10 +9304,7 @@ static void print_escaped(const char *s)
|
||||
#endif
|
||||
|
||||
#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL || ENABLE_HUSH_READONLY
|
||||
static int helper_export_local(char **argv,
|
||||
int exp UNUSED_PARAM,
|
||||
int ro UNUSED_PARAM,
|
||||
int lvl UNUSED_PARAM)
|
||||
static int helper_export_local(char **argv, unsigned flags)
|
||||
{
|
||||
do {
|
||||
char *name = *argv;
|
||||
@ -9329,7 +9318,7 @@ static int helper_export_local(char **argv,
|
||||
vpp = get_ptr_to_local_var(name, name_end - name);
|
||||
var = vpp ? *vpp : NULL;
|
||||
|
||||
if (exp == -1) { /* unexporting? */
|
||||
if (flags & SETFLAG_UNEXPORT) {
|
||||
/* export -n NAME (without =VALUE) */
|
||||
if (var) {
|
||||
var->flg_export = 0;
|
||||
@ -9338,7 +9327,7 @@ static int helper_export_local(char **argv,
|
||||
} /* else: export -n NOT_EXISTING_VAR: no-op */
|
||||
continue;
|
||||
}
|
||||
if (exp == 1) { /* exporting? */
|
||||
if (flags & SETFLAG_EXPORT) {
|
||||
/* export NAME (without =VALUE) */
|
||||
if (var) {
|
||||
var->flg_export = 1;
|
||||
@ -9349,9 +9338,8 @@ static int helper_export_local(char **argv,
|
||||
}
|
||||
# if ENABLE_HUSH_LOCAL
|
||||
/* Is this "local" bltin? */
|
||||
if (exp == 0
|
||||
IF_HUSH_READONLY(&& ro == 0) /* in !READONLY config, always true */
|
||||
) {
|
||||
if (!(flags & (SETFLAG_EXPORT|SETFLAG_UNEXPORT|SETFLAG_MAKE_RO))) {
|
||||
unsigned lvl = flags >> SETFLAG_LOCAL_SHIFT;
|
||||
if (var && var->func_nest_level == lvl) {
|
||||
/* "local x=abc; ...; local x" - ignore second local decl */
|
||||
continue;
|
||||
@ -9376,7 +9364,7 @@ static int helper_export_local(char **argv,
|
||||
/* (Un)exporting/making local NAME=VALUE */
|
||||
name = xstrdup(name);
|
||||
}
|
||||
set_local_var(name, /*exp:*/ exp, /*lvl:*/ lvl, /*ro:*/ ro);
|
||||
set_local_var(name, flags);
|
||||
} while (*++argv);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@ -9424,7 +9412,7 @@ static int FAST_FUNC builtin_export(char **argv)
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
return helper_export_local(argv, /*exp:*/ (opt_unexport ? -1 : 1), /*ro:*/ 0, /*lvl:*/ 0);
|
||||
return helper_export_local(argv, opt_unexport ? SETFLAG_UNEXPORT : SETFLAG_EXPORT);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -9436,14 +9424,15 @@ static int FAST_FUNC builtin_local(char **argv)
|
||||
return EXIT_FAILURE; /* bash compat */
|
||||
}
|
||||
argv++;
|
||||
return helper_export_local(argv, /*exp:*/ 0, /*ro:*/ 0, /*lvl:*/ G.func_nest_level);
|
||||
return helper_export_local(argv, G.func_nest_level << SETFLAG_LOCAL_SHIFT);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_HUSH_READONLY
|
||||
static int FAST_FUNC builtin_readonly(char **argv)
|
||||
{
|
||||
if (*++argv == NULL) {
|
||||
argv++;
|
||||
if (*argv == NULL) {
|
||||
/* bash: readonly [-p]: list all readonly VARs
|
||||
* (-p has no effect in bash)
|
||||
*/
|
||||
@ -9456,7 +9445,7 @@ static int FAST_FUNC builtin_readonly(char **argv)
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
return helper_export_local(argv, /*exp:*/ 0, /*ro:*/ 1, /*lvl:*/ 0);
|
||||
return helper_export_local(argv, SETFLAG_MAKE_RO);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user