version 1.15, 2013/11/22 15:47:35 |
version 1.16, 2016/10/23 14:54:14 |
|
|
#define VAR_APPEND 2 |
#define VAR_APPEND 2 |
#define VAR_SHELL 4 |
#define VAR_SHELL 4 |
#define VAR_OPT 8 |
#define VAR_OPT 8 |
|
#define VAR_LAZYSHELL 16 |
|
#define VAR_SUNSHELL 32 |
int type; |
int type; |
struct Name name; |
struct Name name; |
|
|
|
|
|
|
type = VAR_NORMAL; |
type = VAR_NORMAL; |
|
|
|
/* double operators (except for :) are forbidden */ |
|
/* OPT and APPEND don't match */ |
|
/* APPEND and LAZYSHELL can't really work */ |
while (*arg != '=') { |
while (*arg != '=') { |
/* Check operator type. */ |
/* Check operator type. */ |
switch (*arg++) { |
switch (*arg++) { |
case '+': |
case '+': |
if (type & (VAR_OPT|VAR_APPEND)) |
if (type & (VAR_OPT|VAR_LAZYSHELL|VAR_APPEND)) |
type = VAR_INVALID; |
type = VAR_INVALID; |
else |
else |
type |= VAR_APPEND; |
type |= VAR_APPEND; |
|
|
case ':': |
case ':': |
if (FEATURES(FEATURE_SUNSHCMD) && |
if (FEATURES(FEATURE_SUNSHCMD) && |
strncmp(arg, "sh", 2) == 0) { |
strncmp(arg, "sh", 2) == 0) { |
type = VAR_SHELL; |
type = VAR_SUNSHELL; |
arg += 2; |
arg += 2; |
while (*arg != '=' && *arg != '\0') |
while (*arg != '=' && *arg != '\0') |
arg++; |
arg++; |
|
|
break; |
break; |
|
|
case '!': |
case '!': |
if (type & VAR_SHELL) |
if (type & VAR_SHELL) { |
|
if (type & (VAR_APPEND)) |
|
type = VAR_INVALID; |
|
else |
|
type = VAR_LAZYSHELL; |
|
} else if (type & (VAR_LAZYSHELL|VAR_SUNSHELL)) |
type = VAR_INVALID; |
type = VAR_INVALID; |
else |
else |
type |= VAR_SHELL; |
type |= VAR_SHELL; |
|
|
VarName_Free(&name); |
VarName_Free(&name); |
return true; |
return true; |
} |
} |
if (type & VAR_SHELL) { |
if (type & (VAR_SHELL|VAR_SUNSHELL)) { |
char *err; |
char *err; |
|
|
if (strchr(arg, '$') != NULL) { |
if (strchr(arg, '$') != NULL) { |
|
|
Parse_Error(PARSE_WARNING, err, arg); |
Parse_Error(PARSE_WARNING, err, arg); |
arg = res1; |
arg = res1; |
} |
} |
|
if (type & VAR_LAZYSHELL) { |
|
if (strchr(arg, '$') != NULL) { |
|
/* There's a dollar sign in the command, so perform |
|
* variable expansion on the whole thing. */ |
|
arg = Var_Subst(arg, NULL, true); |
|
} |
|
} |
if (type & VAR_SUBST) { |
if (type & VAR_SUBST) { |
/* |
/* |
* Allow variables in the old value to be undefined, but leave |
* Allow variables in the old value to be undefined, but leave |
|
|
Var_Appendi_with_ctxt(name.s, name.e, arg, ctxt); |
Var_Appendi_with_ctxt(name.s, name.e, arg, ctxt); |
else |
else |
Var_Seti_with_ctxt(name.s, name.e, arg, ctxt); |
Var_Seti_with_ctxt(name.s, name.e, arg, ctxt); |
|
if (type & VAR_LAZYSHELL) |
|
Var_Mark(name.s, name.e, VAR_EXEC_LATER); |
|
|
VarName_Free(&name); |
VarName_Free(&name); |
free(res2); |
free(res2); |