Applied another bunch of patches sent by CDHW (Charles D.H. Williams). The patches

are aimed to close some leaks in the parser.
This commit is contained in:
pnenzi 2001-12-14 18:29:08 +00:00
parent 3b5502ab0c
commit 7583d1849e
8 changed files with 150 additions and 41 deletions

View File

@ -5,6 +5,7 @@
#include "control.h"
#include "streams.h"
#include "com_cdump.h"
static int indent;
@ -39,10 +40,10 @@ dodump(struct control *cc)
fprintf(cp_out, "while ");
wl_print(cc->co_cond, cp_out);
putc('\n', cp_out);
indent += 8;
indent += TABINDENT;
for (tc = cc->co_children; tc; tc = tc->co_next)
dodump(tc);
indent -= 8;
indent -= TABINDENT;
tab(indent);
fprintf(cp_out, "end\n");
break;
@ -50,13 +51,13 @@ dodump(struct control *cc)
tab(indent);
fprintf(cp_out, "repeat ");
if (cc->co_numtimes != -1)
fprintf(cp_out, "%d\n", cc->co_numtimes);
fprintf(cp_out, "%d (%d left to do)\n", cc->co_numtimes, cc->co_timestodo); /* CDHW */
else
putc('\n', cp_out);
indent += 8;
indent += TABINDENT;
for (tc = cc->co_children; tc; tc = tc->co_next)
dodump(tc);
indent -= 8;
indent -= TABINDENT;
tab(indent);
fprintf(cp_out, "end\n");
break;
@ -65,10 +66,10 @@ dodump(struct control *cc)
fprintf(cp_out, "dowhile ");
wl_print(cc->co_cond, cp_out);
putc('\n', cp_out);
indent += 8;
indent += TABINDENT;
for (tc = cc->co_children; tc; tc = tc->co_next)
dodump(tc);
indent -= 8;
indent -= TABINDENT;
tab(indent);
fprintf(cp_out, "end\n");
break;
@ -77,10 +78,10 @@ dodump(struct control *cc)
fprintf(cp_out, "if ");
wl_print(cc->co_cond, cp_out);
putc('\n', cp_out);
indent += 8;
indent += TABINDENT;
for (tc = cc->co_children; tc; tc = tc->co_next)
dodump(tc);
indent -= 8;
indent -= TABINDENT;
tab(indent);
fprintf(cp_out, "end\n");
break;
@ -89,10 +90,10 @@ dodump(struct control *cc)
fprintf(cp_out, "foreach %s ", cc->co_foreachvar);
wl_print(cc->co_text, cp_out);
putc('\n', cp_out);
indent += 8;
indent += TABINDENT;
for (tc = cc->co_children; tc; tc = tc->co_next)
dodump(tc);
indent -= 8;
indent -= TABINDENT;
tab(indent);
fprintf(cp_out, "end\n");
break;

View File

@ -2,5 +2,6 @@
#define _COM_CDUMP_H
void com_cdump(wordlist *wl);
#define TABINDENT 2 /* CDHW */ /* The orginal value was 8 */
#endif

View File

@ -47,6 +47,14 @@ int stackp = 0;
* blown away every time we return -- probably every time we type
* source at the keyboard and every time a source returns to keyboard
* input is ok though -- use ft_controlreset. */
/* Notes by CDHW:
* This routine leaked like a sieve because each getcommand() created a
* wordlist that was never freed becuase it might have been added into
* the control structure. I've tackled this by making sure that everything
* put into the cend[stackp] is a copy. This means that wlist can be
* destroyed safely
*/
static char *noredirect[] = { "stop", NULL } ; /* Only one?? */
@ -79,6 +87,37 @@ pwlist(wordlist *wlist, char *name)
}
/* CDHW defined functions */
static void
pwlist_echo(wlist, name) /*CDHW used to perform function of set echo */
wordlist *wlist;
char *name;
{
wordlist *wl;
if ((!cp_echo)||cp_debug) /* cpdebug prints the same info */
return;
fprintf(cp_err, "%s ", name);
for (wl = wlist; wl; wl = wl->wl_next)
fprintf(cp_err, "%s ", wl->wl_word);
fprintf(cp_err, "\n");
return;
}
/*CDHW Remove control structure and free the memory its hogging CDHW*/
void ctl_free(struct control *ctrl) {
if (!ctrl) return;
wl_free(ctrl->co_cond); ctrl->co_cond = NULL;
tfree(ctrl->co_foreachvar); ctrl->co_foreachvar = NULL;
wl_free(ctrl->co_text); ctrl->co_text = NULL;
ctl_free(ctrl->co_children); ctrl->co_children = NULL;
ctl_free(ctrl->co_elseblock); ctrl->co_elseblock = NULL;
ctl_free(ctrl->co_next); ctrl->co_next = NULL;
tfree(ctrl); ctrl = NULL;
}
/* Note that we only do io redirection when we get to here - we also
* postpone some other things until now. */
@ -108,8 +147,10 @@ docommand(wordlist *wlist)
wlist = cp_doglob(wlist);
pwlist(wlist, "After globbing");
pwlist_echo(wlist, "Becomes >");
if (!wlist || !wlist->wl_word)
if (!wlist || !wlist->wl_word) /*CDHW need to free wlist in second case? CDHW*/
return;
/* Now loop through all of the commands given. */
@ -185,7 +226,7 @@ docommand(wordlist *wlist)
for (wl = wlist->wl_next; wl; wl = wl->wl_next)
nargs++;
if (command->co_stringargs) {
lcom = wl_flatten(wlist->wl_next);
lcom = wl_flatten(wlist->wl_next); /*CDHW lcom will need freeing CDHW*/
(*command->co_func) ((void *)(lcom));
} else {
if (nargs < command->co_minargs) {
@ -241,10 +282,17 @@ doblock(struct control *bl, int *num)
wordlist *wl;
char *i;
int nn;
nn = *num + 1 ; /*CDHW this is a guess... CDHW*/
switch (bl->co_type) {
case CO_WHILE:
if (!bl->co_children) {
fprintf(cp_err, "Warning: Executing empty 'while' block.\n");
fprintf(cp_err, " (Use a label statement as a no-op to suppress this warning.)\n");
}
while (bl->co_cond && cp_istrue(bl->co_cond)) {
if (!bl->co_children) cp_periodic(); /*CDHW*/
for (ch = bl->co_children; ch; ch = cn) {
cn = ch->co_next;
i = doblock(ch, &nn);
@ -316,10 +364,19 @@ doblock(struct control *bl, int *num)
break;
case CO_REPEAT:
while ((bl->co_numtimes > 0) ||
(bl->co_numtimes == -1)) {
if (bl->co_numtimes != -1)
bl->co_numtimes--;
if (!bl->co_children) {
fprintf(cp_err, "Warning: Executing empty 'repeat' block.\n");
fprintf(cp_err, " (Use a label statement as a no-op to suppress this warning.)\n");
}
if (!bl->co_timestodo) bl->co_timestodo = bl->co_numtimes;
/*...CDHW*/
while ((bl->co_timestodo > 0) ||
(bl->co_timestodo == -1)) {
if (!bl->co_children) cp_periodic(); /*CDHW*/
if (bl->co_timestodo != -1) bl->co_timestodo--;
for (ch = bl->co_children; ch; ch = cn) {
cn = ch->co_next;
i = doblock(ch, &nn);
@ -447,11 +504,12 @@ doblock(struct control *bl, int *num)
case CO_GOTO:
wl = cp_variablesubst(cp_bquote(cp_doglob(
wl_copy(bl->co_text))));
wl_copy(bl->co_text)))); /*CDHW Leak ? CDHW*/
return (wl->wl_word);
case CO_LABEL:
/* Do nothing. */
cp_periodic(); /*CDHW needed to avoid lock-ups when loop contains only a label CDHW*/
break;
case CO_STATEMENT:
@ -556,7 +614,9 @@ cp_evloop(char *string)
/* Add this to the control structure list. If cend->co_type is
* CO_UNFILLED, the last line was the beginning of a block,
* and this is the unfilled first statement. */
* and this is the unfilled first statement.
*/
if (cend[stackp] && (cend[stackp]->co_type != CO_UNFILLED)) {
cend[stackp]->co_next = alloc(struct control);
ZERO(cend[stackp]->co_next, struct control);
@ -574,7 +634,7 @@ cp_evloop(char *string)
cend[stackp]->co_cond = wlist->wl_next;
if (!cend[stackp]->co_cond) {
fprintf(stderr,
"Error: missing while condition.\n");
"Error: missing while condition, 'false' will be assumed.\n");
}
newblock;
} else if (eq(wlist->wl_word, "dowhile")) {
@ -582,7 +642,7 @@ cp_evloop(char *string)
cend[stackp]->co_cond = wlist->wl_next;
if (!cend[stackp]->co_cond) {
fprintf(stderr,
"Error: missing dowhile condition.\n");
"Error: missing dowhile condition, '???' will be assumed.\n");
}
newblock;
} else if (eq(wlist->wl_word, "repeat")) {
@ -592,10 +652,12 @@ cp_evloop(char *string)
} else {
char *s;
double *dd;
wlist = cp_variablesubst(cp_bquote(
cp_doglob(wl_copy(wlist))));
s = wlist->wl_next->wl_word;
struct wordlist *t; /*CDHW*/
/*CDHW wlist = cp_variablesubst(cp_bquote(cp_doglob(wl_copy(wlist)))); Wrong order? Leak? CDHW*/
t = cp_doglob(cp_bquote(cp_variablesubst(wl_copy(wlist)))); /*CDHW leak from cp_doglob? */
s = t->wl_next->wl_word;
dd = ft_numparse(&s, FALSE);
if (dd) {
if (*dd < 0) {
@ -607,9 +669,11 @@ cp_evloop(char *string)
} else
fprintf(cp_err,
"Error: bad repeat argument %s\n",
wlist->wl_next->wl_word);
t->wl_next->wl_word); /* CDHW */
wl_free(t); t = NULL; /* CDHW */
}
newblock;
} else if (eq(wlist->wl_word, "if")) {
cend[stackp]->co_type = CO_IF;
cend[stackp]->co_cond = wlist->wl_next;
@ -618,6 +682,7 @@ cp_evloop(char *string)
"Error: missing if condition.\n");
}
newblock;
} else if (eq(wlist->wl_word, "foreach")) {
cend[stackp]->co_type = CO_FOREACH;
if (wlist->wl_next) {
@ -628,7 +693,7 @@ cp_evloop(char *string)
} else
fprintf(stderr,
"Error: missing foreach variable.\n");
wlist = cp_doglob(wlist);
wlist = cp_doglob(wlist); /*CDHW Possible leak around here? */
cend[stackp]->co_text = wl_copy(wlist);
newblock;
} else if (eq(wlist->wl_word, "label")) {
@ -642,6 +707,7 @@ cp_evloop(char *string)
"Warning: ignored extra junk after label.\n");
} else
fprintf(stderr, "Error: missing label.\n");
} else if (eq(wlist->wl_word, "goto")) {
/* Incidentally, this won't work if the values 1 and 2 ever get
* to be valid character pointers -- I think it's reasonably
@ -685,12 +751,12 @@ cp_evloop(char *string)
cend[stackp]->co_prev->co_next = NULL;
x = cend[stackp];
cend[stackp] = cend[stackp]->co_parent;
tfree(x);
tfree(x); x=NULL;
} else {
x = cend[stackp];
cend[stackp] = cend[stackp]->co_parent;
cend[stackp]->co_children = NULL;
tfree(x);
tfree(x); x=NULL;
}
} else if (eq(wlist->wl_word, "else")) {
if (!cend[stackp]->co_parent ||
@ -708,25 +774,25 @@ cp_evloop(char *string)
}
} else {
cend[stackp]->co_type = CO_STATEMENT;
cend[stackp]->co_text = wlist;
cend[stackp]->co_text = wl_copy(wlist);
}
if (!cend[stackp]->co_parent) {
x = cend[stackp];
/* We have to toss this do-while loop in here so
* that gotos at the top level will work.
*/
do {
do { nn = 0; /* CDHW */
i = doblock(x, &nn);
switch (*i) {
case NORMAL:
break;
case BROKEN:
fprintf(cp_err,
"Error: break not in loop or too many break levels given\n");
"Error: break not in loop (or too many break levels given)\n");
break;
case CONTINUED:
fprintf(cp_err,
"Error: continue not in loop or too many continue levels given\n");
"Error: continue not in loop (or too many continue levels given)\n");
break;
default:
x = findlabel(i, control[stackp]);
@ -737,15 +803,18 @@ cp_evloop(char *string)
x = x->co_next;
} while (x);
}
wl_free(wlist); wlist = NULL;
if (string)
return (1); /* The return value is irrelevant. */
}
wl_free(wlist); wlist = NULL;
}
/* This blows away the control structures... */
void
cp_resetcontrol(void)
{
fprintf(cp_err, "Warning: clearing control structures\n");
if (cend[stackp] && cend[stackp]->co_parent)
fprintf(cp_err, "Warning: EOF before block terminated\n");
/* We probably should free the control structures... */
@ -797,5 +866,3 @@ cp_toplevel(void)
cend[stackp] = cend[stackp]->co_parent;
return;
}

View File

@ -14,6 +14,7 @@ struct control {
wordlist *co_cond; /* if, while, dowhile */
char *co_foreachvar; /* foreach */
int co_numtimes; /* repeat, break & continue levels */
int co_timestodo; /* the number of times left during a repeat loop */
wordlist *co_text; /* Ordinary text and foreach values. */
struct control *co_parent; /* If this is inside a block. */
struct control *co_children; /* The contents of this block. */

View File

@ -123,6 +123,9 @@ cp_ccom(wordlist *wlist, char *buf, bool esc)
pmatches = ccmatch(buf, &commands);
i = strlen(buf);
}
tfree(buf); /*CDHW*/
if (!esc) {
printem(pmatches);
wl_free(pmatches);

View File

@ -10,6 +10,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include <config.h>
#include "ngspice.h"
#include "cpdefs.h"
#include <errno.h>
#ifdef HAVE_UNISTD_H
@ -45,6 +46,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
static void prompt(void);
extern bool cp_echo; /* For CDHW patches: defined in variable.c */
FILE *cp_inp_cur = NULL;
int cp_event = 1;
@ -77,6 +79,27 @@ static int numeofs = 0;
bzero(buf, BSIZE_SP); \
i = 0;
/* CDHW Debug function */
static void
pwlist_echo(wlist, name) /*CDHW used to perform function of set echo */
wordlist *wlist;
char *name;
{
wordlist *wl;
if ((!cp_echo)||cp_debug) /* cpdebug prints the same info */
return;
fprintf(cp_err, "%s ", name);
for (wl = wlist; wl; wl = wl->wl_next)
fprintf(cp_err, "%s ", wl->wl_word );
fprintf(cp_err, "\n");
return;
}
/* CDHW */
wordlist *
cp_lexer(char *string)
{
@ -86,10 +109,10 @@ cp_lexer(char *string)
char buf[BSIZE_SP], linebuf[BSIZE_SP], d;
int paren;
if (cp_inp_cur == NULL)
if (cp_inp_cur == NULL)
cp_inp_cur = cp_in;
if (!string && cp_interactive) {
if (!string && cp_interactive) {/* prompt for string if none is passed */
cp_ccon(TRUE);
prompt();
}
@ -261,6 +284,11 @@ gotchar:
newword;
break;
}
case ';': /*CDHW semicolon inside parentheses is part of expression CDHW*/
if (paren > 0) {
buf[i++]=c;
break;
}
default:
/* We have to remember the special case $<
* here
@ -280,6 +308,8 @@ gotchar:
}
}
done:
if (wlist->wl_word) pwlist_echo(wlist,"Command>");
return (wlist);
}

View File

@ -28,6 +28,7 @@ bool cp_noglob = TRUE;
bool cp_nonomatch = FALSE;
bool cp_noclobber = FALSE;
bool cp_ignoreeof = FALSE;
bool cp_echo = FALSE; /* CDHW */
struct variable *variables = NULL;
@ -156,6 +157,8 @@ cp_vset(char *varname, char type, char *value)
cp_maxhistlength = v->va_real;
else if (eq(copyvarname, "noclobber"))
cp_noclobber = TRUE;
else if (eq(varname, "echo")) /*CDHW*/
cp_echo = TRUE; /*CDHW*/
else if (eq(copyvarname, "prompt") && (type == VT_STRING))
cp_promptstring = copy(v->va_string);
else if (eq(copyvarname, "ignoreeof"))
@ -234,7 +237,7 @@ cp_vset(char *varname, char type, char *value)
return;
}
/*CDHW This needs leak checking carefully CDHW*/
struct variable *
cp_setparse(wordlist *wl)
{
@ -391,6 +394,8 @@ cp_remvar(char *varname)
cp_nonomatch = FALSE;
else if (eq(varname, "noclobber"))
cp_noclobber = FALSE;
else if (eq(varname, "echo")) /*CDHW*/
cp_echo = FALSE; /*CDHW*/
else if (eq(varname, "prompt")){
/* cp_promptstring = ""; Memory leak here the last allocated reference wil be lost*/
if(cp_promptstring) {
@ -557,7 +562,7 @@ cp_variablesubst(wordlist *wlist)
{
wordlist *wl, *nwl;
char *s, *t, buf[BSIZE_SP], wbuf[BSIZE_SP], tbuf[BSIZE_SP];
/* MW. tbuf holds curret word after wl_splice() calls free() on it */
/* MW. tbuf holds current word after wl_splice() calls free() on it */
int i;
for (wl = wlist; wl; wl = wl->wl_next) {
@ -591,7 +596,7 @@ cp_variablesubst(wordlist *wlist)
}
(void) strcpy(tbuf, t); /* MW. Save t*/
if (!(wl = wl_splice(wl, nwl)))
if (!(wl = wl_splice(wl, nwl))) /*CDHW this frees wl CDHW*/
return (NULL);
/* This is bad... */
for (wlist = wl; wlist->wl_prev; wlist = wlist->wl_prev)

View File

@ -42,6 +42,7 @@ extern bool cp_noglob;
extern bool cp_nonomatch;
extern bool cp_noclobber;
extern bool cp_ignoreeof;
extern bool cp_echo;
// extern struct variable *variables;
wordlist * cp_varwl(struct variable *var);