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:
parent
3b5502ab0c
commit
7583d1849e
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -2,5 +2,6 @@
|
|||
#define _COM_CDUMP_H
|
||||
|
||||
void com_cdump(wordlist *wl);
|
||||
#define TABINDENT 2 /* CDHW */ /* The orginal value was 8 */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue