summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Zle/zle_keymap.c22
-rw-r--r--Src/init.c14
-rw-r--r--Src/input.c122
-rw-r--r--Src/patchlevel.h.release2
-rw-r--r--Src/prompt.c10
5 files changed, 149 insertions, 21 deletions
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index d13aed594..49b2a26ad 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -155,7 +155,7 @@ createkeymapnamtab(void)
keymapnamtab = newhashtable(7, "keymapnamtab", NULL);
keymapnamtab->hash = hasher;
- keymapnamtab->emptytable = emptyhashtable;
+ keymapnamtab->emptytable = emptykeymapnamtab;
keymapnamtab->filltable = NULL;
keymapnamtab->cmpnodes = strcmp;
keymapnamtab->addnode = addhashnode;
@@ -178,6 +178,26 @@ makekeymapnamnode(Keymap keymap)
return kmn;
}
+/**/
+static void
+emptykeymapnamtab(HashTable ht)
+{
+ struct hashnode *hn, *hp;
+ int i;
+
+ for (i = 0; i < ht->hsize; i++) {
+ for (hn = ht->nodes[i]; hn;) {
+ KeymapName kmn = (KeymapName) hn;
+ hp = hn->next;
+ zsfree(kmn->nam);
+ unrefkeymap(kmn->keymap);
+ zfree(kmn, sizeof(*kmn));
+ hn = hp;
+ }
+ ht->nodes[i] = NULL;
+ }
+ ht->ct = 0;
+}
/*
* Reference a keymap from a keymapname.
diff --git a/Src/init.c b/Src/init.c
index 04a5856ff..99ccc16cf 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -1222,7 +1222,7 @@ setupshin(char *runscript)
/*
* Finish setting up SHIN and its relatives.
*/
- bshin = SHIN ? fdopen(SHIN, "r") : stdin;
+ shinbufalloc();
if (isset(SHINSTDIN) && !SHIN && unset(INTERACTIVE)) {
#ifdef _IONBF
setvbuf(stdin, NULL, _IONBF, 0);
@@ -1377,9 +1377,9 @@ init_misc(char *cmd, char *zsh_name)
dosetopt(RESTRICTED, 1, 0, opts);
if (cmd) {
if (SHIN >= 10)
- fclose(bshin);
+ close(SHIN);
SHIN = movefd(open("/dev/null", O_RDONLY | O_NOCTTY));
- bshin = fdopen(SHIN, "r");
+ shinbufreset();
execstring(cmd, 0, 1, "cmdarg");
stopmsg = 1;
zexit((exit_pending || shell_exiting) ? exit_val : lastval, ZEXIT_NORMAL);
@@ -1402,7 +1402,6 @@ source(char *s)
int tempfd = -1, fd, cj;
zlong oldlineno;
int oldshst, osubsh, oloops;
- FILE *obshin;
char *old_scriptname = scriptname, *us;
char *old_scriptfilename = scriptfilename;
unsigned char *ocs;
@@ -1419,7 +1418,6 @@ source(char *s)
/* save the current shell state */
fd = SHIN; /* store the shell input fd */
- obshin = bshin; /* store file handle for buffered shell input */
osubsh = subsh; /* store whether we are in a subshell */
cj = thisjob; /* store our current job number */
oldlineno = lineno; /* store our current lineno */
@@ -1432,7 +1430,7 @@ source(char *s)
if (!prog) {
SHIN = tempfd;
- bshin = fdopen(SHIN, "r");
+ shinbufsave();
}
subsh = 0;
lineno = 1;
@@ -1500,10 +1498,10 @@ source(char *s)
if (prog)
freeeprog(prog);
else {
- fclose(bshin);
+ close(SHIN);
fdtable[SHIN] = FDT_UNUSED;
SHIN = fd; /* the shell input fd */
- bshin = obshin; /* file handle for buffered shell input */
+ shinbufrestore();
}
subsh = osubsh; /* whether we are in a subshell */
thisjob = cj; /* current job number */
diff --git a/Src/input.c b/Src/input.c
index e9989ffe4..18228b37d 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -80,11 +80,6 @@
/**/
int SHIN;
-/* buffered shell input for non-interactive shells */
-
-/**/
-FILE *bshin;
-
/* != 0 means we are reading input from a string */
/**/
@@ -129,7 +124,116 @@ static struct instacks *instack, *instacktop;
static int instacksz = INSTACK_INITIAL;
-/* Read a line from bshin. Convert tokens and *
+/* Size of buffer for non-interactive command input */
+
+#define SHINBUFSIZE 8192
+
+/* Input buffer for non-interactive command input */
+static char *shinbuffer;
+
+/* Pointer into shinbuffer */
+static char *shinbufptr;
+
+/* End of contents read into shinbuffer */
+static char *shinbufendptr;
+
+/* Entry on SHIN buffer save stack */
+struct shinsaveentry {
+ /* Next entry on stack */
+ struct shinsaveentry *next;
+ /* Saved shinbuffer */
+ char *buffer;
+ /* Saved shinbufptr */
+ char *ptr;
+ /* Saved shinbufendptr */
+ char *endptr;
+};
+
+/* SHIN buffer save stack */
+static struct shinsaveentry *shinsavestack;
+
+/* Reset the input buffer for SHIN, discarding any pending input */
+
+/**/
+void
+shinbufreset(void)
+{
+ shinbufendptr = shinbufptr = shinbuffer;
+}
+
+/* Allocate a new shinbuffer
+ *
+ * Only called at shell initialisation and when saving on the stack.
+ */
+
+/**/
+void
+shinbufalloc(void)
+{
+ shinbuffer = zalloc(SHINBUFSIZE);
+ shinbufreset();
+}
+
+/* Save entry on SHIN buffer save stack */
+
+/**/
+void
+shinbufsave(void)
+{
+ struct shinsaveentry *entry =
+ (struct shinsaveentry *)zalloc(sizeof(struct shinsaveentry));
+
+ entry->next = shinsavestack;
+ entry->buffer = shinbuffer;
+ entry->ptr = shinbufptr;
+ entry->endptr = shinbufendptr;
+
+ shinsavestack = entry;
+
+ shinbufalloc();
+}
+
+/* Restore entry from SHIN buffer save stack */
+
+/**/
+void
+shinbufrestore(void)
+{
+ struct shinsaveentry *entry = shinsavestack;
+
+ zfree(shinbuffer, SHINBUFSIZE);
+
+ shinbuffer = entry->buffer;
+ shinbufptr = entry->ptr;
+ shinbufendptr = entry->endptr;
+
+ shinsavestack = entry->next;
+ zfree(entry, sizeof(struct shinsaveentry));
+}
+
+/* Get a character from SHIN, -1 if none available */
+
+/**/
+static int
+shingetchar(void)
+{
+ int nread;
+
+ if (shinbufptr < shinbufendptr)
+ return STOUC(*shinbufptr++);
+
+ shinbufreset();
+ do {
+ errno = 0;
+ nread = read(SHIN, shinbuffer, SHINBUFSIZE);
+ } while (nread < 0 && errno == EINTR);
+ if (nread <= 0)
+ return -1;
+ shinbufendptr = shinbuffer + nread;
+ return STOUC(*shinbufptr++);
+}
+
+/* Read a line from SHIN. Convert tokens and *
* null characters to Meta c^32 character pairs. */
/**/
@@ -147,11 +251,7 @@ shingetline(void)
winch_unblock();
dont_queue_signals();
for (;;) {
- /* Can't fgets() here because we need to accept '\0' bytes */
- do {
- errno = 0;
- c = fgetc(bshin);
- } while (c < 0 && errno == EINTR);
+ c = shingetchar();
if (c < 0 || c == '\n') {
winch_block();
restore_queue_signals(q);
diff --git a/Src/patchlevel.h.release b/Src/patchlevel.h.release
index 229e2e564..e4475aae7 100644
--- a/Src/patchlevel.h.release
+++ b/Src/patchlevel.h.release
@@ -1 +1 @@
-#define ZSH_PATCHLEVEL "zsh-5.8-0-g77d203f"
+#define ZSH_PATCHLEVEL "zsh-5.8.1-0-g1a490c7"
diff --git a/Src/prompt.c b/Src/prompt.c
index b65bfb86b..91e21c8e9 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -244,6 +244,12 @@ parsecolorchar(zattr arg, int is_fg)
bv->fm += 2; /* skip over F{ */
if ((ep = strchr(bv->fm, '}'))) {
char oc = *ep, *col, *coll;
+ int ops = opts[PROMPTSUBST], opb = opts[PROMPTBANG];
+ int opp = opts[PROMPTPERCENT];
+
+ opts[PROMPTPERCENT] = 1;
+ opts[PROMPTSUBST] = opts[PROMPTBANG] = 0;
+
*ep = '\0';
/* expand the contents of the argument so you can use
* %v for example */
@@ -252,6 +258,10 @@ parsecolorchar(zattr arg, int is_fg)
arg = match_colour((const char **)&coll, is_fg, 0);
free(col);
bv->fm = ep;
+
+ opts[PROMPTSUBST] = ops;
+ opts[PROMPTBANG] = opb;
+ opts[PROMPTPERCENT] = opp;
} else {
arg = match_colour((const char **)&bv->fm, is_fg, 0);
if (*bv->fm != '}')