diff options
Diffstat (limited to 'Src/utils.c')
-rw-r--r-- | Src/utils.c | 641 |
1 files changed, 199 insertions, 442 deletions
diff --git a/Src/utils.c b/Src/utils.c index 32588b4c3..ba4f3dc9d 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -853,61 +853,131 @@ int resetneeded; int winchanged; #endif -/* check the size of the window and adjust if necessary. * - * The value of from: * - * 0: called from update_job or setupvals * - * 1: called from the SIGWINCH handler * - * 2: the user have just changed LINES manually * - * 3: the user have just changed COLUMNS manually */ - -/**/ -void -adjustwinsize(int from) +static int +adjustlines(int signalled) { - int oldcols = columns, oldrows = lines; + int oldlines = lines; #ifdef TIOCGWINSZ - static int userlines, usercols; - - if (SHTTY == -1) - return; - - if (from == 2) - userlines = lines > 0; - if (from == 3) - usercols = columns > 0; - - if (!ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize)) { - if (!userlines || from == 1) - lines = shttyinfo.winsize.ws_row; - if (!usercols || from == 1) - columns = shttyinfo.winsize.ws_col; + if (signalled || lines <= 0) + lines = shttyinfo.winsize.ws_row; + else + shttyinfo.winsize.ws_row = lines; +#endif /* TIOCGWINSZ */ + if (lines <= 0) { + DPUTS(signalled, "BUG: Impossible TIOCGWINSZ rows"); + lines = tclines > 0 ? tclines : 24; } -#endif /* TIOCGWINSZ */ - if (lines <= 0) - lines = tclines > 0 ? tclines : 24; - if (columns <= 0) - columns = tccolumns > 0 ? tccolumns : 80; if (lines > 2) termflags &= ~TERM_SHORT; else termflags |= TERM_SHORT; + + return (lines != oldlines); +} + +static int +adjustcolumns(int signalled) +{ + int oldcolumns = columns; + +#ifdef TIOCGWINSZ + if (signalled || columns <= 0) + columns = shttyinfo.winsize.ws_col; + else + shttyinfo.winsize.ws_col = columns; +#endif /* TIOCGWINSZ */ + if (columns <= 0) { + DPUTS(signalled, "BUG: Impossible TIOCGWINSZ cols"); + columns = tccolumns > 0 ? tccolumns : 80; + } + if (columns > 2) termflags &= ~TERM_NARROW; else termflags |= TERM_NARROW; + return (columns != oldcolumns); +} + +/* check the size of the window and adjust if necessary. * + * The value of from: * + * 0: called from update_job or setupvals * + * 1: called from the SIGWINCH handler * + * 2: called from the LINES parameter callback * + * 3: called from the COLUMNS parameter callback */ + +/**/ +void +adjustwinsize(int from) +{ + static int getwinsz = 1; + int ttyrows = shttyinfo.winsize.ws_row; + int ttycols = shttyinfo.winsize.ws_col; + int resetzle = 0; + + if (getwinsz || from == 1) { #ifdef TIOCGWINSZ - if (interact && from >= 2) { - shttyinfo.winsize.ws_row = lines; - shttyinfo.winsize.ws_col = columns; + if (SHTTY == -1) + return; + if (ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize) == 0) { + resetzle = (ttyrows != shttyinfo.winsize.ws_row || + ttycols != shttyinfo.winsize.ws_col); + if (from == 0 && resetzle && ttyrows && ttycols) + from = 1; /* Signal missed while a job owned the tty? */ + ttyrows = shttyinfo.winsize.ws_row; + ttycols = shttyinfo.winsize.ws_col; + } else { + /* Set to unknown on failure */ + shttyinfo.winsize.ws_row = 0; + shttyinfo.winsize.ws_col = 0; + resetzle = 1; + } +#else + resetzle = from == 1; +#endif /* TIOCGWINSZ */ + } /* else + return; */ + + switch (from) { + case 0: + case 1: + getwinsz = 0; + /* Calling setiparam() here calls this function recursively, but * + * because we've already called adjustlines() and adjustcolumns() * + * here, recursive calls are no-ops unless a signal intervenes. * + * The commented "else return;" above might be a safe shortcut, * + * but I'm concerned about what happens on race conditions; e.g., * + * suppose the user resizes his xterm during `eval $(resize)'? */ + if (adjustlines(from) && zgetenv("LINES")) + setiparam("LINES", lines); + if (adjustcolumns(from) && zgetenv("COLUMNS")) + setiparam("COLUMNS", columns); + getwinsz = 1; + break; + case 2: + resetzle = adjustlines(0); + break; + case 3: + resetzle = adjustcolumns(0); + break; + } + +#ifdef TIOCGWINSZ + if (interact && from >= 2 && + (shttyinfo.winsize.ws_row != ttyrows || + shttyinfo.winsize.ws_col != ttycols)) { + /* shttyinfo.winsize is already set up correctly */ ioctl(SHTTY, TIOCSWINSZ, (char *)&shttyinfo.winsize); } -#endif +#endif /* TIOCGWINSZ */ - if (zleactive && (from >= 2 || oldcols != columns || oldrows != lines)) { - resetneeded = winchanged = 1; + if (zleactive && resetzle) { +#ifdef TIOCGWINSZ + winchanged = +#endif /* TIOCGWINSZ */ + resetneeded = 1; zrefresh(); } } @@ -1733,13 +1803,12 @@ char * sepjoin(char **s, char *sep) { char *r, *p, **t; - int l, sl, elide = 0; + int l, sl; char sepbuf[3]; if (!*s) return ""; if (!sep) { - elide = 1; sep = sepbuf; sepbuf[0] = *ifs; sepbuf[1] = *ifs == Meta ? ifs[1] ^ 32 : '\0'; @@ -1853,329 +1922,21 @@ allocnode(int type) { struct node *n; - n = (struct node *) alloc(sizetab[type]); + n = (struct node *) ncalloc(sizetab[type]); memset((void *) n, 0, sizetab[type]); n->ntype = flagtab[type]; - if (useheap) - n->ntype |= NT_HEAP; return (void *) n; } + +/* duplicate a syntax tree */ /**/ void * dupstruct(void *a) { - struct node *n, *r; - - n = (struct node *) a; - if (!a || ((List) a) == &dummy_list) - return (void *) a; - - if ((n->ntype & NT_HEAP) && !useheap) { - HEAPALLOC { - n = (struct node *) dupstruct2((void *) n); - } LASTALLOC; - n = simplifystruct(n); - } - r = (struct node *)dupstruct2((void *) n); - - if (!(n->ntype & NT_HEAP) && useheap) - r = expandstruct(r, N_LIST); - - return (void *) r; -} - -/**/ -static struct node * -simplifystruct(struct node *n) -{ - if (!n || ((List) n) == &dummy_list) - return n; - - switch (NT_TYPE(n->ntype)) { - case N_LIST: - { - List l = (List) n; - - l->left = (Sublist) simplifystruct((struct node *)l->left); - if ((l->type & Z_SYNC) && !l->right) - return (struct node *)l->left; - } - break; - case N_SUBLIST: - { - Sublist sl = (Sublist) n; - - sl->left = (Pline) simplifystruct((struct node *)sl->left); - if (sl->type == END && !sl->flags && !sl->right) - return (struct node *)sl->left; - } - break; - case N_PLINE: - { - Pline pl = (Pline) n; - - pl->left = (Cmd) simplifystruct((struct node *)pl->left); - if (pl->type == END && !pl->right) - return (struct node *)pl->left; - } - break; - case N_CMD: - { - Cmd c = (Cmd) n; - int i = 0; - - if (empty(c->args)) - c->args = NULL, i++; - if (empty(c->redir)) - c->redir = NULL, i++; - if (empty(c->vars)) - c->vars = NULL, i++; - - c->u.list = (List) simplifystruct((struct node *)c->u.list); - if (i == 3 && !c->flags && - (c->type == CWHILE || c->type == CIF || - c->type == COND)) - return (struct node *)c->u.list; - } - break; - case N_FOR: - { - Forcmd f = (Forcmd) n; - - f->list = (List) simplifystruct((struct node *)f->list); - } - break; - case N_CASE: - { - struct casecmd *c = (struct casecmd *)n; - List *l; - - for (l = c->lists; *l; l++) - *l = (List) simplifystruct((struct node *)*l); - } - break; - case N_IF: - { - struct ifcmd *i = (struct ifcmd *)n; - List *l; - - for (l = i->ifls; *l; l++) - *l = (List) simplifystruct((struct node *)*l); - for (l = i->thenls; *l; l++) - *l = (List) simplifystruct((struct node *)*l); - } - break; - case N_WHILE: - { - struct whilecmd *w = (struct whilecmd *)n; - - w->cont = (List) simplifystruct((struct node *)w->cont); - w->loop = (List) simplifystruct((struct node *)w->loop); - } - } - - return n; -} - -/**/ -struct node * -expandstruct(struct node *n, int exp) -{ - struct node *m; - - if (!n || ((List) n) == &dummy_list) - return n; - - if (exp != N_COUNT && exp != NT_TYPE(n->ntype)) { - switch (exp) { - case N_LIST: - { - List l; - - m = (struct node *) allocnode(N_LIST); - l = (List) m; - l->type = Z_SYNC; - l->left = (Sublist) expandstruct(n, N_SUBLIST); - - return (struct node *)l; - } - case N_SUBLIST: - { - Sublist sl; - - m = (struct node *) allocnode(N_SUBLIST); - sl = (Sublist) m; - sl->type = END; - sl->left = (Pline) expandstruct(n, N_PLINE); - - return (struct node *)sl; - } - case N_PLINE: - { - Pline pl; - - m = (struct node *) allocnode(N_PLINE); - pl = (Pline) m; - pl->type = END; - pl->left = (Cmd) expandstruct(n, N_CMD); - - return (struct node *)pl; - } - case N_CMD: - { - Cmd c; - - m = (struct node *) allocnode(N_CMD); - c = (Cmd) m; - switch (NT_TYPE(n->ntype)) { - case N_WHILE: - c->type = CWHILE; - break; - case N_IF: - c->type = CIF; - break; - case N_COND: - c->type = COND; - } - c->u.list = (List) expandstruct(n, NT_TYPE(n->ntype)); - c->args = newlinklist(); - c->vars = newlinklist(); - c->redir = newlinklist(); - - return (struct node *)c; - } - } - } else - switch (NT_TYPE(n->ntype)) { - case N_LIST: - { - List l = (List) n; - - l->left = (Sublist) expandstruct((struct node *)l->left, - N_SUBLIST); - l->right = (List) expandstruct((struct node *)l->right, - N_LIST); - } - break; - case N_SUBLIST: - { - Sublist sl = (Sublist) n; - - sl->left = (Pline) expandstruct((struct node *)sl->left, - N_PLINE); - sl->right = (Sublist) expandstruct((struct node *)sl->right, - N_SUBLIST); - } - break; - case N_PLINE: - { - Pline pl = (Pline) n; - - pl->left = (Cmd) expandstruct((struct node *)pl->left, - N_CMD); - pl->right = (Pline) expandstruct((struct node *)pl->right, - N_PLINE); - } - break; - case N_CMD: - { - Cmd c = (Cmd) n; - - if (!c->args) - c->args = newlinklist(); - if (!c->vars) - c->vars = newlinklist(); - if (!c->redir) - c->redir = newlinklist(); - - switch (c->type) { - case CFOR: - case CSELECT: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_FOR); - break; - case CWHILE: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_WHILE); - break; - case CIF: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_IF); - break; - case CCASE: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_CASE); - break; - case COND: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_COND); - break; - case ZCTIME: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_SUBLIST); - break; - case AUTOFN: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_AUTOFN); - break; - default: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_LIST); - } - } - break; - case N_FOR: - { - Forcmd f = (Forcmd) n; - - f->list = (List) expandstruct((struct node *)f->list, - N_LIST); - } - break; - case N_CASE: - { - struct casecmd *c = (struct casecmd *)n; - List *l; - - for (l = c->lists; *l; l++) - *l = (List) expandstruct((struct node *)*l, N_LIST); - } - break; - case N_IF: - { - struct ifcmd *i = (struct ifcmd *)n; - List *l; - - for (l = i->ifls; *l; l++) - *l = (List) expandstruct((struct node *)*l, N_LIST); - for (l = i->thenls; *l; l++) - *l = (List) expandstruct((struct node *)*l, N_LIST); - } - break; - case N_WHILE: - { - struct whilecmd *w = (struct whilecmd *)n; - - w->cont = (List) expandstruct((struct node *)w->cont, - N_LIST); - w->loop = (List) expandstruct((struct node *)w->loop, - N_LIST); - } - } - - return n; -} - -/* duplicate a syntax tree */ - -/**/ -static void * -dupstruct2(void *a) -{ void **onodes, **nnodes, *ret, *n, *on; - int type, heap; + int type; size_t nodeoffs; if (!a || ((List) a) == &dummy_list) @@ -2183,53 +1944,33 @@ dupstruct2(void *a) type = *(int *)a; ret = alloc(sizetab[NT_TYPE(type)]); memcpy(ret, a, nodeoffs = offstab[NT_TYPE(type)]); - *(int*)ret = (type & ~NT_HEAP) | (useheap ? NT_HEAP : 0); onodes = (void **) ((char *)a + nodeoffs); nnodes = (void **) ((char *)ret + nodeoffs); - heap = type & NT_HEAP; for (type = (type & 0xffff00) >> 4; (type >>= 4); *nnodes++ = n) { if (!(on = *onodes++)) n = NULL; else { switch (type & 0xf) { case NT_NODE: - n = dupstruct2(on); + n = dupstruct(on); break; case NT_STR: n = dupstring(on); break; case NT_LIST | NT_NODE: - if (heap) { - if (useheap) - n = duplist(on, (VFunc) dupstruct2); - else - n = list2arr(on, (VFunc) dupstruct2); - } - else if (useheap) - n = arr2list(on, (VFunc) dupstruct2); - else - n = duparray(on, (VFunc) dupstruct2); + n = duplist(on, (VFunc) dupstruct); break; case NT_LIST | NT_STR: - if (heap) { - if (useheap) - n = duplist(on, (VFunc) dupstring); - else - n = list2arr(on, (VFunc) ztrdup); - } - else if (useheap) - n = arr2list(on, (VFunc) dupstring); - else - n = duparray(on, (VFunc) ztrdup); + n = duplist(on, (VFunc) (useheap ? dupstring : ztrdup)); break; case NT_NODE | NT_ARR: - n = duparray(on, (VFunc) dupstruct2); + n = duparray(on, (VFunc) dupstruct); break; case NT_STR | NT_ARR: n = duparray(on, (VFunc) (useheap ? dupstring : ztrdup)); break; default: - DPUTS(1, "BUG: bad node type in dupstruct2()"); + DPUTS(1, "BUG: bad node type in dupstruct()"); abort(); } } @@ -2237,19 +1978,46 @@ dupstruct2(void *a) return ret; } -/* free a syntax tree */ +/* Free a syntax tree. Now, freestruct() only registers everything that + * has to be freed. Later, freestructs() will be called to do the real + * work. This is to avoid having functions that are currently executed + * free themselves by re-defining themselves. */ + +static LinkList freeslist = NULL; /**/ void freestruct(void *a) { - void **nodes, *n; - int type, size; - if (!a || ((List) a) == &dummy_list) return; - type = * (int *) a; + PERMALLOC { + if (!freeslist) + freeslist = newlinklist(); + addlinknode(freeslist, a); + } LASTALLOC; +} + +/**/ +void +freestructs(void) +{ + void *a; + + if (freeslist) + while ((a = getlinknode(freeslist))) + ifreestruct(a); +} + +/**/ +static void +ifreestruct(void *a) +{ + void **nodes, *n; + int type, size; + + type = *(int *) a; nodes = (void **) ((char *)a + offstab[NT_TYPE(type)]); size = sizetab[NT_TYPE(type)]; for (type = (type & 0xffff00) >> 4; (type >>= 4);) { @@ -2262,6 +2030,8 @@ freestruct(void *a) zsfree((char *) n); break; case NT_LIST | NT_NODE: + freelinklist((LinkList) n, (FreeFunc) freestruct); + break; case NT_NODE | NT_ARR: { void **p = (void **) n; @@ -2272,6 +2042,8 @@ freestruct(void *a) break; } case NT_LIST | NT_STR: + freelinklist((LinkList) n, (FreeFunc) zsfree); + break; case NT_STR | NT_ARR: freearray((char **) n); break; @@ -2287,58 +2059,46 @@ freestruct(void *a) } /**/ -static LinkList -duplist(LinkList l, VFunc func) +LinkList +dupheaplist(LinkList l) { - LinkList ret; - LinkNode node; - - ret = newlinklist(); - for (node = firstnode(l); node; incnode(node)) - addlinknode(ret, func(getdata(node))); - return ret; -} - -/**/ -char ** -duparray(char **arr, VFunc func) -{ - char **ret, **rr; - - ret = (char **) alloc((arrlen(arr) + 1) * sizeof(char *)); - for (rr = ret; *arr;) - *rr++ = (char *)func(*arr++); - *rr = NULL; + if (!l) + return NULL; - return ret; + return duplist(l, (VFunc) dupstruct); } /**/ -static char ** -list2arr(LinkList l, VFunc func) +static LinkList +duplist(LinkList l, VFunc func) { - char **arr, **r; - LinkNode n; - - arr = r = (char **) alloc((countlinknodes(l) + 1) * sizeof(char *)); + if (l && nonempty(l)) { + LinkList ret; + LinkNode node; - for (n = firstnode(l); n; incnode(n)) - *r++ = (char *)func(getdata(n)); - *r = NULL; - - return arr; + ret = newlinklist(); + for (node = firstnode(l); node; incnode(node)) + addlinknode(ret, func(getdata(node))); + return ret; + } + return NULL; } /**/ -static LinkList -arr2list(char **arr, VFunc func) +char ** +duparray(char **arr, VFunc func) { - LinkList l = newlinklist(); + if (arr && *arr) { + char **ret, **rr, *p; - while (*arr) - addlinknode(l, func(*arr++)); + ret = (char **) alloc((arrlen(arr) + 1) * sizeof(char *)); + for (rr = ret; (p = *arr++);) + *rr++ = (char *)func(p); + *rr = NULL; - return l; + return ret; + } + return NULL; } /**/ @@ -2384,28 +2144,6 @@ equalsplit(char *s, char **t) return 0; } -/* see if the right side of a list is trivial */ - -/**/ -void -simplifyright(List l) -{ - Cmd c; - - if (l == &dummy_list || !l->right) - return; - if (l->right->right || l->right->left->right || - l->right->left->flags || l->right->left->left->right || - l->left->flags) - return; - c = l->left->left->left; - if (c->type != SIMPLE || nonempty(c->args) || nonempty(c->redir) - || nonempty(c->vars)) - return; - l->right = NULL; - return; -} - /* the ztypes table */ /**/ @@ -2470,6 +2208,25 @@ arrdup(char **s) return y; } +/* Duplicate a list of strings. */ + +/**/ +LinkList +listdup(LinkList l) +{ + if (!l) + return NULL; + else { + LinkList r = newlinklist(); + LinkNode n; + + for (n = firstnode(l); n; incnode(n)) + addlinknode(r, dupstring((char *) getdata(n))); + + return r; + } +} + /**/ char ** listarr(LinkList l) |