summaryrefslogtreecommitdiff
path: root/Src/builtin.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/builtin.c')
-rw-r--r--Src/builtin.c100
1 files changed, 71 insertions, 29 deletions
diff --git a/Src/builtin.c b/Src/builtin.c
index 97022addf..01eb5b84c 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -58,7 +58,7 @@ static struct builtin builtins[] =
BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmprs", NULL),
BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
BUILTIN("echo", BINF_SKIPINVALID, bin_print, 0, -1, BIN_ECHO, "neE", "-"),
- BUILTIN("emulate", 0, bin_emulate, 0, -1, 0, "LR", NULL),
+ BUILTIN("emulate", 0, bin_emulate, 0, -1, 0, "lLR", NULL),
BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmprs", NULL),
BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL),
BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
@@ -2090,7 +2090,9 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
tc = 0; /* but don't do a normal conversion */
}
} else if (!setsecondstype(pm, on, off)) {
- if (asg->value.scalar && !(pm = setsparam(pname, ztrdup(asg->value.scalar))))
+ if (asg->value.scalar &&
+ !(pm = assignsparam(
+ pname, ztrdup(asg->value.scalar), 0)))
return NULL;
usepm = 1;
err = 0;
@@ -2202,12 +2204,13 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
} else if (pm->env && !(pm->node.flags & PM_HASHELEM))
delenv(pm);
DPUTS(ASG_ARRAYP(asg), "BUG: typeset got array value where scalar expected");
- if (asg->value.scalar && !(pm = setsparam(pname, ztrdup(asg->value.scalar))))
+ if (asg->value.scalar &&
+ !(pm = assignsparam(pname, ztrdup(asg->value.scalar), 0)))
return NULL;
} else if (asg->is_array) {
- if (!(pm = setaparam(pname, asg->value.array ?
+ if (!(pm = assignaparam(pname, asg->value.array ?
zlinklist2array(asg->value.array) :
- mkarray(NULL))))
+ mkarray(NULL), 0)))
return NULL;
}
pm->node.flags |= (on & PM_READONLY);
@@ -2331,7 +2334,8 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
} else if ((on & PM_LOCAL) && locallevel) {
*subscript = 0;
pm = (Param) (paramtab == realparamtab ?
- gethashnode2(paramtab, pname) :
+ /* getnode2() to avoid autoloading */
+ paramtab->getnode2(paramtab, pname) :
paramtab->getnode(paramtab, pname));
*subscript = '[';
if (!pm || pm->level != locallevel) {
@@ -2347,16 +2351,18 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
* creating a stray parameter along the way via createparam(),
* now called below in the isident() branch.
*/
- if (!(pm = setsparam(pname, ztrdup(asg->value.scalar ? asg->value.scalar : ""))))
+ if (!(pm = assignsparam(
+ pname,
+ ztrdup(asg->value.scalar ? asg->value.scalar : ""), 0)))
return NULL;
dont_set = 1;
asg->is_array = 0;
keeplocal = 0;
on = pm->node.flags;
} else if (PM_TYPE(on) == PM_ARRAY && ASG_ARRAYP(asg)) {
- if (!(pm = setaparam(pname, asg->value.array ?
- zlinklist2array(asg->value.array) :
- mkarray(NULL))))
+ if (!(pm = assignaparam(pname, asg->value.array ?
+ zlinklist2array(asg->value.array) :
+ mkarray(NULL), 0)))
return NULL;
dont_set = 1;
keeplocal = 0;
@@ -2432,14 +2438,30 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
if (ASG_VALUEP(asg) && !dont_set) {
Param ipm = pm;
if (pm->node.flags & (PM_ARRAY|PM_HASHED)) {
- DPUTS(!ASG_ARRAYP(asg), "BUG: inconsistent scalar value for array");
- if (!(pm=setaparam(pname, asg->value.array ?
- zlinklist2array(asg->value.array) :
- mkarray(NULL))))
+ char **arrayval;
+ if (!ASG_ARRAYP(asg)) {
+ /*
+ * Attempt to assign a scalar value to an array.
+ * This can happen if the array is special.
+ * We'll be lenient and guess what the user meant.
+ * This is how normal assigment works.
+ */
+ if (*asg->value.scalar) {
+ /* Array with one value */
+ arrayval = mkarray(ztrdup(asg->value.scalar));
+ } else {
+ /* Empty array */
+ arrayval = mkarray(NULL);
+ }
+ } else if (asg->value.array)
+ arrayval = zlinklist2array(asg->value.array);
+ else
+ arrayval = mkarray(NULL);
+ if (!(pm=assignaparam(pname, arrayval, 0)))
return NULL;
} else {
DPUTS(ASG_ARRAYP(asg), "BUG: inconsistent array value for scalar");
- if (!(pm = setsparam(pname, ztrdup(asg->value.scalar))))
+ if (!(pm = assignsparam(pname, ztrdup(asg->value.scalar), 0)))
return NULL;
}
if (pm != ipm) {
@@ -2687,9 +2709,10 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
/* Update join character */
tdp->joinchar = joinchar;
if (asg0.value.scalar)
- setsparam(asg0.name, ztrdup(asg0.value.scalar));
+ assignsparam(asg0.name, ztrdup(asg0.value.scalar), 0);
else if (asg->value.array)
- setaparam(asg->name, zlinklist2array(asg->value.array));
+ assignaparam(
+ asg->name, zlinklist2array(asg->value.array), 0);
return 0;
} else {
zwarnnam(name, "can't tie already tied scalar: %s",
@@ -2750,9 +2773,9 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
zsfree(apm->ename);
apm->ename = ztrdup(asg0.name);
if (asg->value.array)
- setaparam(asg->name, zlinklist2array(asg->value.array));
+ assignaparam(asg->name, zlinklist2array(asg->value.array), 0);
else if (oldval)
- setsparam(asg0.name, oldval);
+ assignsparam(asg0.name, oldval, 0);
unqueue_signals();
return 0;
@@ -2819,11 +2842,12 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
/* Take arguments literally. Don't glob */
while ((asg = getasg(&argv, assigns))) {
HashNode hn = (paramtab == realparamtab ?
- gethashnode2(paramtab, asg->name) :
+ /* getnode2() to avoid autoloading */
+ paramtab->getnode2(paramtab, asg->name) :
paramtab->getnode(paramtab, asg->name));
if (OPT_ISSET(ops,'p')) {
if (hn)
- printparamnode(hn, printflags);
+ paramtab->printnode(hn, printflags);
else {
zwarnnam(name, "no such variable: %s", asg->name);
returnval = 1;
@@ -3313,7 +3337,8 @@ bin_unset(char *name, char **argv, Options ops, int func)
*ss = 0;
}
pm = (Param) (paramtab == realparamtab ?
- gethashnode2(paramtab, s) :
+ /* getnode2() to avoid autoloading */
+ paramtab->getnode2(paramtab, s) :
paramtab->getnode(paramtab, s));
/*
* Unsetting an unset variable is not an error.
@@ -5419,10 +5444,11 @@ eval(char **argv)
/**/
int
-bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
+bin_emulate(char *nam, char **argv, Options ops, UNUSED(int func))
{
int opt_L = OPT_ISSET(ops, 'L');
int opt_R = OPT_ISSET(ops, 'R');
+ int opt_l = OPT_ISSET(ops, 'l');
int saveemulation, savehackchar;
int ret = 1, new_emulation;
unsigned int savepatterns;
@@ -5437,7 +5463,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
/* without arguments just print current emulation */
if (!shname) {
if (opt_L || opt_R) {
- zwarnnam("emulate", "not enough arguments");
+ zwarnnam(nam, "not enough arguments");
return 1;
}
@@ -5465,27 +5491,43 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
/* with single argument set current emulation */
if (!argv[1]) {
- emulate(shname, opt_R, &emulation, opts);
+ char *cmdopts;
+ if (opt_l) {
+ cmdopts = (char *)zhalloc(OPT_SIZE);
+ memcpy(cmdopts, opts, OPT_SIZE);
+ } else
+ cmdopts = opts;
+ emulate(shname, opt_R, &emulation, cmdopts);
if (opt_L)
- opts[LOCALOPTIONS] = opts[LOCALTRAPS] = opts[LOCALPATTERNS] = 1;
+ cmdopts[LOCALOPTIONS] = cmdopts[LOCALTRAPS] =
+ cmdopts[LOCALPATTERNS] = 1;
+ if (opt_l) {
+ list_emulate_options(cmdopts, opt_R);
+ return 0;
+ }
clearpatterndisables();
return 0;
}
+ if (opt_l) {
+ zwarnnam(nam, "too many arguments for -l");
+ return 1;
+ }
+
argv++;
memcpy(saveopts, opts, sizeof(opts));
memcpy(new_opts, opts, sizeof(opts));
savehackchar = keyboardhackchar;
emulate(shname, opt_R, &new_emulation, new_opts);
optlist = newlinklist();
- if (parseopts("emulate", &argv, new_opts, &cmd, optlist)) {
+ if (parseopts(nam, &argv, new_opts, &cmd, optlist)) {
ret = 1;
goto restore;
}
/* parseopts() has consumed anything that looks like an option */
if (*argv) {
- zwarnnam("emulate", "unknown argument %s", *argv);
+ zwarnnam(nam, "unknown argument %s", *argv);
goto restore;
}
@@ -5504,7 +5546,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
*/
if (cmd) {
if (opt_L) {
- zwarnnam("emulate", "option -L incompatible with -c");
+ zwarnnam(nam, "option -L incompatible with -c");
goto restore2;
}
*--argv = cmd; /* on stack, never free()d, see execbuiltin() */