about summary refs log tree commit diff
path: root/Src/builtin.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/builtin.c')
-rw-r--r--Src/builtin.c144
1 files changed, 89 insertions, 55 deletions
diff --git a/Src/builtin.c b/Src/builtin.c
index d74d9cd88..8fe112cb5 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -50,7 +50,7 @@ static struct builtin builtins[] =
     BUILTIN("cd", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL),
     BUILTIN("chdir", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL),
     BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL),
-    BUILTIN("declare", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafilrtux", NULL),
+    BUILTIN("declare", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafgilrtux", NULL),
     BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "v", NULL),
     BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmr", NULL),
     BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
@@ -60,7 +60,7 @@ static struct builtin builtins[] =
     BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmr", 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),
-    BUILTIN("export", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "LRTUZafilrtu", "x"),
+    BUILTIN("export", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "LRTUZafilrtu", "xg"),
     BUILTIN("false", 0, bin_false, 0, -1, 0, NULL, NULL),
     BUILTIN("fc", BINF_FCOPTS, bin_fc, 0, -1, BIN_FC, "nlreIRWAdDfEim", NULL),
     BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL),
@@ -74,7 +74,7 @@ static struct builtin builtins[] =
 #endif
 
     BUILTIN("history", 0, bin_fc, 0, -1, BIN_FC, "nrdDfEim", "l"),
-    BUILTIN("integer", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "lrtux", "i"),
+    BUILTIN("integer", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "glrtux", "i"),
     BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL),
     BUILTIN("kill", 0, bin_kill, 0, -1, 0, NULL, NULL),
     BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL),
@@ -93,7 +93,7 @@ static struct builtin builtins[] =
     BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL),
     BUILTIN("r", BINF_R, bin_fc, 0, -1, BIN_FC, "nrl", NULL),
     BUILTIN("read", 0, bin_read, 0, -1, 0, "rzu0123456789pkqecnAlE", NULL),
-    BUILTIN("readonly", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafiltux", "r"),
+    BUILTIN("readonly", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafgiltux", "r"),
     BUILTIN("rehash", 0, bin_hash, 0, 0, 0, "dfv", "r"),
     BUILTIN("return", BINF_PSPECIAL, bin_break, 0, 1, BIN_RETURN, NULL, NULL),
     BUILTIN("set", BINF_PSPECIAL, bin_set, 0, -1, 0, NULL, NULL),
@@ -107,7 +107,7 @@ static struct builtin builtins[] =
     BUILTIN("trap", BINF_PSPECIAL, bin_trap, 0, -1, 0, NULL, NULL),
     BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL),
     BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsw", "v"),
-    BUILTIN("typeset", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafilrtuxm", NULL),
+    BUILTIN("typeset", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafgilrtuxm", NULL),
     BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL),
     BUILTIN("unalias", 0, bin_unhash, 1, -1, 0, "m", "a"),
     BUILTIN("unfunction", 0, bin_unhash, 1, -1, 0, "m", "f"),
@@ -120,7 +120,9 @@ static struct builtin builtins[] =
     BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
 
 #ifdef DYNAMIC
-    BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcdipu", NULL),
+    BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcdipue", NULL),
+#else
+    BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "e", NULL),
 #endif
 };
 
@@ -351,7 +353,8 @@ execbuiltin(LinkList args, Builtin bn)
 
     /* display execution trace information, if required */
     if (xtr) {
-	fprintf(stderr, "%s%s", (prompt4) ? prompt4 : "", name);
+	printprompt4();
+	fprintf(stderr, "%s", name);
 	if (xarg)
 	    fprintf(stderr, " %s", xarg);
 	while (*oargv)
@@ -1349,7 +1352,7 @@ fclist(FILE *f, int n, int r, int D, int d, int first, int last, struct asgment
 	fclistdone = 1;
 
     ent = gethistent(first, first < last? GETHIST_DOWNWARD : GETHIST_UPWARD);
-    if (!ent || ent->histnum < first || ent->histnum > last) {
+    if (!ent || (first < last? ent->histnum > last : ent->histnum < last)) {
 	if (first == last)
 	    zwarnnam("fc", "no such event: %d", NULL, first);
 	else
@@ -1491,8 +1494,14 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 {
     int usepm, tc, keeplocal = 0;
 
-    /* use the existing pm? */
-    usepm = pm && !(pm->flags & (PM_UNSET | PM_AUTOLOAD));
+    /*
+     * Do we use the existing pm?  Note that this isn't the end of the
+     * story, because if we try and create a new pm at the same
+     * locallevel as an unset one we use the pm struct anyway: that's
+     * handled in createparam().  Here we just avoid using it for the
+     * present tests if it's unset.
+     */
+    usepm = pm && !(pm->flags & PM_UNSET);
 
     /* Always use an existing pm if special at current locallevel */
     if (pm && (pm->flags & PM_SPECIAL) && pm->level == locallevel)
@@ -1501,15 +1510,15 @@ typeset_single(char *cname, char *pname, Param pm, int func,
     /*
      * Don't use a non-special existing param if
      *   - the local level has changed, and
-     *   - the function is not `export'.
+     *   - we are really locallizing the parameter
      */
     if (usepm && !(pm->flags & PM_SPECIAL) &&
-	locallevel != pm->level && func != BIN_EXPORT)
+	locallevel != pm->level && (on & PM_LOCAL))
 	usepm = 0;
 
     /* attempting a type conversion, or making a tied colonarray? */
     if ((tc = usepm && (((off & pm->flags) | (on & ~pm->flags)) &
-			(PM_INTEGER|PM_HASHED|PM_ARRAY|PM_TIED))))
+			(PM_INTEGER|PM_HASHED|PM_ARRAY|PM_TIED|PM_AUTOLOAD))))
 	usepm = 0;
     if (tc && (pm->flags & PM_SPECIAL)) {
 	zerrnam(cname, "%s: can't change type of a special parameter",
@@ -1518,6 +1527,7 @@ typeset_single(char *cname, char *pname, Param pm, int func,
     }
 
     if (usepm) {
+	on &= ~PM_LOCAL;
 	if (!on && !roff && !value) {
 	    paramtab->printnode((HashNode)pm, 0);
 	    return pm;
@@ -1604,7 +1614,7 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 
     if (keeplocal)
 	pm->level = keeplocal;
-    else if (func != BIN_EXPORT)
+    else if (on & PM_LOCAL)
 	pm->level = locallevel;
     if (value && !(pm->flags & (PM_ARRAY|PM_HASHED)))
 	setsparam(pname, ztrdup(value));
@@ -1677,6 +1687,9 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 	return 0;
     }
 
+    if (!ops['g'])
+	on |= PM_LOCAL;
+
     if (on & PM_TIED) {
 	Param apm;
 	struct asgment asg0;
@@ -3073,7 +3086,7 @@ bin_emulate(char *nam, char **argv, char *ops, int func)
 {
     emulate(*argv, ops['R']);
     if (ops['L'])
-	dosetopt(LOCALOPTIONS, 1, 0);
+	opts[LOCALOPTIONS] = opts[LOCALTRAPS] = 1;
     return 0;
 }
 
@@ -3121,7 +3134,7 @@ bin_read(char *name, char **args, char *ops, int func)
     char *reply, *readpmpt;
     int bsiz, c = 0, gotnl = 0, al = 0, first, nchars = 1, bslash;
     int haso = 0;	/* true if /dev/tty has been opened specially */
-    int isem = !strcmp(term, "emacs");
+    int isem = !strcmp(term, "emacs"), izle = zleactive && getkeyptr;
     char *buf, *bptr, *firstarg, *zbuforig;
     LinkList readll = newlinklist();
 
@@ -3146,33 +3159,37 @@ bin_read(char *name, char **args, char *ops, int func)
 	return compctlread(name, args, ops, reply);
 
     if ((ops['k'] && !ops['u'] && !ops['p']) || ops['q']) {
-	if (SHTTY == -1) {
-	    /* need to open /dev/tty specially */
-	    SHTTY = open("/dev/tty", O_RDWR|O_NOCTTY);
-	    haso = 1;
-	}
-	/* We should have a SHTTY opened by now. */
-	if (SHTTY == -1) {
-	    /* Unfortunately, we didn't. */
-	    fprintf(stderr, "not interactive and can't open terminal\n");
-	    fflush(stderr);
-	    return 1;
+	if (!zleactive) {
+	    if (SHTTY == -1) {
+		/* need to open /dev/tty specially */
+		SHTTY = open("/dev/tty", O_RDWR|O_NOCTTY);
+		haso = 1;
+	    }
+	    /* We should have a SHTTY opened by now. */
+	    if (SHTTY == -1) {
+		/* Unfortunately, we didn't. */
+		fprintf(stderr, "not interactive and can't open terminal\n");
+		fflush(stderr);
+		return 1;
+	    }
+	    if (unset(INTERACTIVE))
+		gettyinfo(&shttyinfo);
+	    /* attach to the tty */
+	    attachtty(mypgrp);
+	    if (!isem && ops['k'])
+		setcbreak();
+	    readfd = SHTTY;
 	}
-	if (unset(INTERACTIVE))
-	    gettyinfo(&shttyinfo);
-	/* attach to the tty */
-	attachtty(mypgrp);
-	if (!isem && ops['k'])
-	    setcbreak();
-	readfd = SHTTY;
     } else if (ops['u'] && !ops['p']) {
 	/* -u means take input from the specified file descriptor. *
 	 * -up means take input from the coprocess.                */
 	for (readfd = 9; readfd && !ops[readfd + '0']; --readfd);
-    } else if (ops['p'])
+	izle = 0;
+    } else if (ops['p']) {
 	readfd = coprocin;
-    else
-	readfd = 0;
+	izle = 0;
+    } else
+	readfd = izle = 0;
 
     /* handle prompt */
     if (firstarg) {
@@ -3196,18 +3213,25 @@ bin_read(char *name, char **args, char *ops, int func)
 	bptr = buf = (char *)zalloc(nchars+1);
 
 	do {
-	    /* If read returns 0, is end of file */
-	    if ((val = read(readfd, bptr, nchars)) <= 0)
-		break;
+	    if (izle) {
+		if ((val = getkeyptr(0)) < 0)
+		    break;
+		*bptr++ = (char) val;
+		nchars--;
+	    } else {
+		/* If read returns 0, is end of file */
+		if ((val = read(readfd, bptr, nchars)) <= 0)
+		    break;
 	    
-	    /* decrement number of characters read from number required */
-	    nchars -= val;
+		/* decrement number of characters read from number required */
+		nchars -= val;
 
-	    /* increment pointer past read characters */
-	    bptr += val;
+		/* increment pointer past read characters */
+		bptr += val;
+	    }
 	} while (nchars > 0);
 	
-	if (!ops['u'] && !ops['p']) {
+	if (!izle && !ops['u'] && !ops['p']) {
 	    /* dispose of result appropriately, etc. */
 	    if (isem)
 		while (val > 0 && read(SHTTY, &d, 1) == 1 && d != '\n');
@@ -3236,14 +3260,19 @@ bin_read(char *name, char **args, char *ops, int func)
 	readbuf[1] = '\0';
 
 	/* get, and store, reply */
-	readbuf[0] = ((char)getquery(NULL, 0)) == 'y' ? 'y' : 'n';
+	if (izle) {
+	    int key = getkeyptr(0);
 
-	/* dispose of result appropriately, etc. */
-	if (haso) {
-	    close(SHTTY);
-	    SHTTY = -1;
-	}
+	    readbuf[0] = (key == 'y' ? 'y' : 'n');
+	} else {
+	    readbuf[0] = ((char)getquery(NULL, 0)) == 'y' ? 'y' : 'n';
 
+	    /* dispose of result appropriately, etc. */
+	    if (haso) {
+		close(SHTTY);
+		SHTTY = -1;
+	    }
+	}
 	if (ops['e'] || ops['E'])
 	    printf("%s\n", readbuf);
 	if (!ops['e'])
@@ -3265,7 +3294,7 @@ bin_read(char *name, char **args, char *ops, int func)
 	buf = bptr = (char *)zalloc(bsiz = 64);
 	/* get input, a character at a time */
 	while (!gotnl) {
-	    c = zread();
+	    c = zread(izle);
 	    /* \ at the end of a line indicates a continuation *
 	     * line, except in raw mode (-r option)            */
 	    if (bslash && c == '\n') {
@@ -3355,7 +3384,7 @@ bin_read(char *name, char **args, char *ops, int func)
     bslash = 0;
     if (!gotnl)
 	for (;;) {
-	    c = zread();
+	    c = zread(izle);
 	    /* \ at the end of a line introduces a continuation line, except in
 	    raw mode (-r option) */
 	    if (bslash && c == '\n') {
@@ -3419,10 +3448,15 @@ bin_read(char *name, char **args, char *ops, int func)
 
 /**/
 static int
-zread(void)
+zread(int izle)
 {
     char cc, retry = 0;
 
+    if (izle) {
+	int c = getkeyptr(0);
+
+	return (c < 0 ? EOF : c);
+    }
     /* use zbuf if possible */
     if (zbuf) {
 	/* If zbuf points to anything, it points to the next character in the
@@ -3618,7 +3652,7 @@ bin_trap(char *name, char **argv, char *ops, int func)
     arg = *argv++;
     if (!*arg)
 	l = NULL;
-    else if (!(l = parse_string(arg))) {
+    else if (!(l = parse_string(arg, 0))) {
 	zwarnnam(name, "couldn't parse trap command", NULL, 0);
 	return 1;
     }