From 9dd92c7315fffc251142bf1dd084a5e7cda6f784 Mon Sep 17 00:00:00 2001 From: arno Date: Tue, 7 Nov 2000 17:49:18 +0000 Subject: [PATCH] * com_history, com_alias, parser/cshpar.c, parser/complete.c: Applied patch by Michael Widlok. It fixes command completion and history list. In the process, Michael also fixed a memory leak. --- src/frontend/ChangeLog | 6 +++ src/frontend/com_alias.c | 17 ++---- src/frontend/com_history.c | 21 +++++--- src/frontend/parser/complete.c | 94 +++++++++++++++++++++------------- src/frontend/parser/cshpar.c | 12 ++--- 5 files changed, 83 insertions(+), 67 deletions(-) diff --git a/src/frontend/ChangeLog b/src/frontend/ChangeLog index 04c841c78..86c15baf3 100644 --- a/src/frontend/ChangeLog +++ b/src/frontend/ChangeLog @@ -1,3 +1,9 @@ +2000-11-07 Arno W. Peters + + * com_history, com_alias, parser/cshpar.c, parser/complete.c: + Applied patch by Michael Widlok. It fixes command completion and + history list. In the process, Michael also fixed a memory leak. + 2000-09-09 Arno W. Peters * commands.c: Use fourier.h. diff --git a/src/frontend/com_alias.c b/src/frontend/com_alias.c index 4d8960954..645dc004d 100644 --- a/src/frontend/com_alias.c +++ b/src/frontend/com_alias.c @@ -51,11 +51,13 @@ asubst(wordlist *wlist) +/* MW. This function should not use cp_lastone, see cp_parse in cpshar.c + * Many things are deleted here and memory leak closed */ wordlist * cp_doalias(wordlist *wlist) { int ntries; - wordlist *realw, *nwl, *nextc = NULL, *end = NULL; + wordlist *nwl, *nextc = NULL, *end = NULL; wordlist *comm; while (wlist && eq(wlist->wl_word, cp_csep)) @@ -66,7 +68,6 @@ cp_doalias(wordlist *wlist) * save a copy of what it really is and restore it after aliasing * is done. We have to do tricky things do get around the problems * with ; ... */ - realw = wl_copy(cp_lastone->hi_wlist); comm = wlist; do { end = comm->wl_prev; @@ -77,9 +78,7 @@ cp_doalias(wordlist *wlist) nextc->wl_prev->wl_next = NULL; break; } - - wl_free(cp_lastone->hi_wlist); - cp_lastone->hi_wlist = wl_copy(comm); + for (ntries = 21; ntries; ntries--) { nwl = asubst(comm); if (nwl == NULL) @@ -115,8 +114,6 @@ cp_doalias(wordlist *wlist) } } while (nextc); - wl_free(cp_lastone->hi_wlist); - cp_lastone->hi_wlist = realw; return (wlist); } @@ -130,14 +127,11 @@ cp_setalias(char *word, wordlist *wlist) cp_unalias(word); cp_addkword(CT_ALIASES, word); if (cp_aliases == NULL) { - /* printf("first one...\n"); */ al = cp_aliases = alloc(struct alias); al->al_next = NULL; al->al_prev = NULL; } else { - /* printf("inserting %s: %s ...\n", word, wlist->wl_word); */ for (al = cp_aliases; al->al_next; al = al->al_next) { - /* printf("checking %s...\n", al->al_name); */ if (strcmp(al->al_name, word) > 0) break; } @@ -165,9 +159,6 @@ cp_setalias(char *word, wordlist *wlist) * keyword lookup is done the alias is evaluated. Make everything * file completion, just in case... */ cp_addcomm(word, (long) 1, (long) 1, (long) 1, (long) 1); - /* printf("word %s, next = %s, prev = %s...\n", al->al_name, - al->al_next ? al->al_next->al_name : "(none)", - al->al_prev ? al->al_prev->al_name : "(none)"); */ return; } diff --git a/src/frontend/com_history.c b/src/frontend/com_history.c index bc37b75ca..d881c0c08 100644 --- a/src/frontend/com_history.c +++ b/src/frontend/com_history.c @@ -30,12 +30,12 @@ bool cp_didhsubst; static struct histent *histlist = NULL; static int histlength = 0; -/* First check for a ^ at the beginning - * of the line, and then search each word for !. Following this can be any - * of string, number, ?string, -number ; then there may be a word specifier, - * the same as csh, and then the : modifiers. For the :s modifier, - * the syntax is :sXoooXnnnX, where X is any character, and ooo and nnn are - * strings not containing X. +/* First check for a ^ at the beginning of the line, and then search + * each word for !. Following this can be any of string, number, + * ?string, -number ; then there may be a word specifier, the same as + * csh, and then the : modifiers. For the :s modifier, the syntax is + * :sXoooXnnnX, where X is any character, and ooo and nnn are strings + * not containing X. */ wordlist * @@ -328,9 +328,14 @@ hprefix(char *buf) void cp_addhistent(int event, wordlist *wlist) { - if (cp_lastone && !cp_lastone->hi_wlist) - fprintf(cp_err, "Internal error: bad history list\n"); + /* MW. This test is not needed if everything works right */ + if (cp_lastone && !cp_lastone->hi_wlist) + fprintf(cp_err, "Internal error: bad history list\n"); */ + if (cp_lastone == NULL) { +/* MW. the begging - initialize histlength*/ + histlength = 1; + cp_lastone = histlist = alloc(struct histent); cp_lastone->hi_prev = NULL; } else { diff --git a/src/frontend/parser/complete.c b/src/frontend/parser/complete.c index 595bc4f5d..3f059fc5e 100644 --- a/src/frontend/parser/complete.c +++ b/src/frontend/parser/complete.c @@ -73,7 +73,8 @@ static void printem(wordlist *wl); static wordlist * cctowl(struct ccom *cc, bool sib); static struct ccom * clookup(register char *word, struct ccom **dd, bool pref, bool create); -static void cdelete(struct ccom *node); +/* MW. I need top node in cdelete */ +static void cdelete(struct ccom *node, struct ccom **top); #ifdef TIOCSTI @@ -87,10 +88,7 @@ cp_ccom(wordlist *wlist, char *buf, bool esc) int i=0; int j, arg; -/* buf = cp_unquote(copy(buf)); DG: ugly*/ - s=cp_unquote(buf);/*DG*/ - strcpy(buf,s); - tfree(s); + buf = cp_unquote(copy(buf)); cp_wstrip(buf); if (wlist->wl_next) { /* Not the first word. */ cc = getccom(wlist->wl_word); @@ -197,7 +195,7 @@ static wordlist * ccfilec(char *buf) { DIR *wdir; - char *lcomp, *dir,*copydir; + char *lcomp, *dir; struct direct *de; wordlist *wl = NULL, *t; struct passwd *pw; @@ -234,10 +232,7 @@ ccfilec(char *buf) *lcomp = '\0'; lcomp++; if (*dir == cp_til) { - copydir=cp_tildexpand(dir);/*DG*/ - /*dir = cp_tildexpand(dir); very bad the last reference is lost: memory leak*/ - strcpy(dir,copydir); - tfree(copydir); + dir = cp_tildexpand(dir); if (dir == NULL) return (NULL); } @@ -266,9 +261,10 @@ ccfilec(char *buf) return (wl); } -/* See what keywords or commands match the prefix. Check extra also for - * matches, if it is non-NULL. Return a wordlist which is in alphabetical - * order. Note that we have to call this once for each class. +/* See what keywords or commands match the prefix. Check extra also + * for matches, if it is non-NULL. Return a wordlist which is in + * alphabetical order. Note that we have to call this once for each + * class. */ static wordlist * @@ -288,8 +284,8 @@ ccmatch(char *word, struct ccom **dbase) return (wl); } -/* Print the words in the wordlist in columns. They are already sorted... - * This is a hard thing to do with wordlists... +/* Print the words in the wordlist in columns. They are already + * sorted... This is a hard thing to do with wordlists... */ static void @@ -389,8 +385,8 @@ cp_ccon(bool on) ison = on; /* Set the terminal up -- make escape the break character, and - * make sure we aren't in raw or cbreak mode. Hope the (void) ioctl's - * won't fail. + * make sure we aren't in raw or cbreak mode. Hope the (void) + * ioctl's won't fail. */ (void) ioctl(fileno(cp_in), TIOCGETC, (char *) &tbuf); if (on) @@ -461,7 +457,8 @@ cp_comlook(char *word) return (FALSE); } -/* Add a command to the database, with the given keywords and filename flag. */ +/* Add a command to the database, with the given keywords and filename + * flag. */ void cp_addcomm(char *word, long int bits0, long int bits1, long int bits2, long int bits3) @@ -486,7 +483,7 @@ cp_remcomm(char *word) cc = clookup(word, &commands, FALSE, FALSE); if (cc) - cdelete(cc); + cdelete(cc, &commands); return; } @@ -516,13 +513,13 @@ cp_remkword(int class, char *word) struct ccom *cc; if ((class < 1) || (class >= NCLASSES)) { - fprintf(cp_err, "cp_addkword: Internal Error: bad class %d\n", + fprintf(cp_err, "cp_remkword: Internal Error: bad class %d\n", class); return; } cc = clookup(word, &keywords[class], FALSE, FALSE); if (cc) - cdelete(cc); + cdelete(cc, &keywords[class]); return; } @@ -567,10 +564,10 @@ throwaway(struct ccom *dbase) return; } -/* Look up a word in the database. Because of the - * way the tree is set up, this also works for looking up all words with - * a given prefix (if the pref arg is TRUE). If create is TRUE, then the - * node is created if it doesn't already exist. +/* Look up a word in the database. Because of the way the tree is set + * up, this also works for looking up all words with a given prefix + * (if the pref arg is TRUE). If create is TRUE, then the node is + * created if it doesn't already exist. */ static struct ccom * @@ -580,9 +577,6 @@ clookup(register char *word, struct ccom **dd, bool pref, bool create) int ind = 0, i; char buf[BSIZE_SP]; -/* printf("----- adding %s -----\n", word); */ -/* prcc(); */ - if (!place) { /* This is the first time we were called. */ if (!create) @@ -648,7 +642,6 @@ clookup(register char *word, struct ccom **dd, bool pref, bool create) /* place now points to that node that matches the word for * ind + 1 characters. */ -/* printf("place %s, word %s, ind %d\n", place->cc_name, word, ind); */ if (word[ind + 1]) { /* More to go... */ if (!place->cc_child) { /* No children, maybe make one and go on. */ @@ -681,16 +674,43 @@ clookup(register char *word, struct ccom **dd, bool pref, bool create) } /* Delete a node from the tree. Returns the new tree... */ +/* MW. It is quite difficoult to free() everything right, but... + * Anyway this could be more optimal, I think */ static void -cdelete(struct ccom *node) +cdelete(struct ccom *node, struct ccom **top) { - node->cc_invalid = 1; - tfree(node->cc_name); - tfree(node->cc_child); - tfree(node->cc_sibling); - tfree(node->cc_ysibling); - tfree(node->cc_parent); - return; + /* if cc_child exist only mark as deleted */ + node->cc_invalid = 1; + if (node->cc_child) + return; + + /* fix cc_sibling */ + if (node->cc_sibling) + node->cc_sibling->cc_ysibling = node->cc_ysibling; + if (node->cc_ysibling) + node->cc_ysibling->cc_sibling = node->cc_sibling; + + /* if we have cc_parent, check if it should not be removed too */ + if (node->cc_parent) { + + /* this node will be free() */ + if (node->cc_parent->cc_child == node) { + if (node->cc_ysibling) + node->cc_parent->cc_child = node->cc_ysibling; + else + node->cc_parent->cc_child = node->cc_sibling; + } + if (node->cc_parent->cc_invalid == 1) + /* free parent only if it is invalid */ + cdelete(node->cc_parent, top); + } + + /* now free() everything and check the top */ + if (node == *top) + *top = node->cc_sibling; + free(node->cc_name); + free(node); + return; } diff --git a/src/frontend/parser/cshpar.c b/src/frontend/parser/cshpar.c index 9ddf26857..28b8e2d2c 100644 --- a/src/frontend/parser/cshpar.c +++ b/src/frontend/parser/cshpar.c @@ -83,19 +83,13 @@ cp_parse(char *string) } /* Add the word list to the history. */ - if (*wlist->wl_word) + /* MW. If string==NULL we do not have to do this, and then play + * with cp_lastone is not needed, but watch out cp_doalias */ + if ((*wlist->wl_word) && !(string)) cp_addhistent(cp_event - 1, wlist); wlist = cp_doalias(wlist); pwlist(wlist, "After alias substitution"); - - if (string && cp_lastone) { - /* Don't put this one in... */ - cp_lastone = cp_lastone->hi_prev; - if (cp_lastone) - cp_lastone->hi_next = NULL; - } - pwlist(wlist, "Returning "); return (wlist); }