diff --git a/src/frontend/com_cdump.c b/src/frontend/com_cdump.c index 3982e5fba..c066bef27 100644 --- a/src/frontend/com_cdump.c +++ b/src/frontend/com_cdump.c @@ -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; diff --git a/src/frontend/com_cdump.h b/src/frontend/com_cdump.h index ec6e5e145..c82d18eef 100644 --- a/src/frontend/com_cdump.h +++ b/src/frontend/com_cdump.h @@ -2,5 +2,6 @@ #define _COM_CDUMP_H void com_cdump(wordlist *wl); +#define TABINDENT 2 /* CDHW */ /* The orginal value was 8 */ #endif diff --git a/src/frontend/control.c b/src/frontend/control.c index 7b1a3e403..3dd6fbb5f 100644 --- a/src/frontend/control.c +++ b/src/frontend/control.c @@ -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; } - - diff --git a/src/frontend/control.h b/src/frontend/control.h index 7b5132193..d0c0d0ce5 100644 --- a/src/frontend/control.h +++ b/src/frontend/control.h @@ -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. */ diff --git a/src/frontend/parser/complete.c b/src/frontend/parser/complete.c index 2cd88696f..a49ca49fa 100644 --- a/src/frontend/parser/complete.c +++ b/src/frontend/parser/complete.c @@ -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); diff --git a/src/frontend/parser/lexical.c b/src/frontend/parser/lexical.c index 64e0c9e0b..23c5df429 100644 --- a/src/frontend/parser/lexical.c +++ b/src/frontend/parser/lexical.c @@ -10,6 +10,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #include #include "ngspice.h" #include "cpdefs.h" + #include #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); } diff --git a/src/frontend/variable.c b/src/frontend/variable.c index 39b57c0c4..8a0fbc8e2 100644 --- a/src/frontend/variable.c +++ b/src/frontend/variable.c @@ -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) diff --git a/src/frontend/variable.h b/src/frontend/variable.h index 161d6b90e..6c8b6ae9a 100644 --- a/src/frontend/variable.h +++ b/src/frontend/variable.h @@ -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);