2005-05-30 22:28:29 +02:00
|
|
|
/*************
|
|
|
|
|
* streams.c
|
|
|
|
|
************/
|
|
|
|
|
|
2011-12-27 12:33:01 +01:00
|
|
|
#include "ngspice/config.h"
|
2011-12-11 19:05:00 +01:00
|
|
|
#include "ngspice/ngspice.h"
|
|
|
|
|
#include "ngspice/wordlist.h"
|
|
|
|
|
#include "ngspice/bool.h"
|
* frontend/Makefile.am: Updates for new files.
* frontend/breakp2.c, frontend/newcoms.c, frontend/postcoms.c,
frontend/resource.c, frontend/terminal.h, frontend/variable.c,
frontend/variable.h, frontend/com_compose.c,
frontend/com_display.c, frontend/com_setscale.c,
frontend/com_strcmp.c: Include files update.
* parser/var2.c, parser/var2.h: Empty files, removed.
* parser/Makefile.am: Updates for removed files.
* parser/lexical.c: Small adjustments
* parser/input.c, parser/input.h: Input, output and error streams
handled in the frontend. Moved to the frontend directory.
* frontend/streams.c: Its new home.
2000-07-07 16:09:06 +02:00
|
|
|
|
|
|
|
|
#include "variable.h"
|
|
|
|
|
#include "terminal.h"
|
|
|
|
|
#include "quote.h"
|
2011-12-11 19:05:00 +01:00
|
|
|
#include "ngspice/cpextern.h"
|
* frontend/Makefile.am: Updates for new files.
* frontend/breakp2.c, frontend/newcoms.c, frontend/postcoms.c,
frontend/resource.c, frontend/terminal.h, frontend/variable.c,
frontend/variable.h, frontend/com_compose.c,
frontend/com_display.c, frontend/com_setscale.c,
frontend/com_strcmp.c: Include files update.
* parser/var2.c, parser/var2.h: Empty files, removed.
* parser/Makefile.am: Updates for removed files.
* parser/lexical.c: Small adjustments
* parser/input.c, parser/input.h: Input, output and error streams
handled in the frontend. Moved to the frontend directory.
* frontend/streams.c: Its new home.
2000-07-07 16:09:06 +02:00
|
|
|
#include "streams.h"
|
|
|
|
|
|
|
|
|
|
bool cp_debug = FALSE;
|
|
|
|
|
char cp_gt = '>';
|
|
|
|
|
char cp_lt = '<';
|
|
|
|
|
char cp_amp = '&';
|
2005-09-09 19:53:45 +02:00
|
|
|
|
2005-09-08 11:43:48 +02:00
|
|
|
FILE *cp_in=NULL;
|
|
|
|
|
FILE *cp_out=NULL;
|
|
|
|
|
FILE *cp_err=NULL;
|
2005-09-09 19:53:45 +02:00
|
|
|
|
* frontend/Makefile.am: Updates for new files.
* frontend/breakp2.c, frontend/newcoms.c, frontend/postcoms.c,
frontend/resource.c, frontend/terminal.h, frontend/variable.c,
frontend/variable.h, frontend/com_compose.c,
frontend/com_display.c, frontend/com_setscale.c,
frontend/com_strcmp.c: Include files update.
* parser/var2.c, parser/var2.h: Empty files, removed.
* parser/Makefile.am: Updates for removed files.
* parser/lexical.c: Small adjustments
* parser/input.c, parser/input.h: Input, output and error streams
handled in the frontend. Moved to the frontend directory.
* frontend/streams.c: Its new home.
2000-07-07 16:09:06 +02:00
|
|
|
/* These are the fps that cp_ioreset resets the cp_* to. They are
|
|
|
|
|
* changed by the source routines. */
|
|
|
|
|
FILE *cp_curin = NULL;
|
|
|
|
|
FILE *cp_curout = NULL;
|
|
|
|
|
FILE *cp_curerr = NULL;
|
2005-09-09 19:53:45 +02:00
|
|
|
|
2005-05-30 22:28:29 +02:00
|
|
|
/* static functions */
|
|
|
|
|
static bool fileexists(char *name);
|
* frontend/Makefile.am: Updates for new files.
* frontend/breakp2.c, frontend/newcoms.c, frontend/postcoms.c,
frontend/resource.c, frontend/terminal.h, frontend/variable.c,
frontend/variable.h, frontend/com_compose.c,
frontend/com_display.c, frontend/com_setscale.c,
frontend/com_strcmp.c: Include files update.
* parser/var2.c, parser/var2.h: Empty files, removed.
* parser/Makefile.am: Updates for removed files.
* parser/lexical.c: Small adjustments
* parser/input.c, parser/input.h: Input, output and error streams
handled in the frontend. Moved to the frontend directory.
* frontend/streams.c: Its new home.
2000-07-07 16:09:06 +02:00
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
fileexists(char *name)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_ACCESS
|
|
|
|
|
if (access(name, 0) == 0)
|
|
|
|
|
return (TRUE);
|
|
|
|
|
#endif
|
|
|
|
|
return (FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This routine sets the cp_{in,out,err} pointers and takes the io
|
|
|
|
|
* directions out of the command line. */
|
|
|
|
|
wordlist *
|
|
|
|
|
cp_redirect(wordlist *wl)
|
|
|
|
|
{
|
|
|
|
|
bool gotinput = FALSE, gotoutput = FALSE, goterror = FALSE;
|
|
|
|
|
bool app = FALSE, erralso = FALSE;
|
|
|
|
|
wordlist *w, *bt, *nw;
|
2000-10-26 19:02:12 +02:00
|
|
|
char *s,*copyword;
|
* frontend/Makefile.am: Updates for new files.
* frontend/breakp2.c, frontend/newcoms.c, frontend/postcoms.c,
frontend/resource.c, frontend/terminal.h, frontend/variable.c,
frontend/variable.h, frontend/com_compose.c,
frontend/com_display.c, frontend/com_setscale.c,
frontend/com_strcmp.c: Include files update.
* parser/var2.c, parser/var2.h: Empty files, removed.
* parser/Makefile.am: Updates for removed files.
* parser/lexical.c: Small adjustments
* parser/input.c, parser/input.h: Input, output and error streams
handled in the frontend. Moved to the frontend directory.
* frontend/streams.c: Its new home.
2000-07-07 16:09:06 +02:00
|
|
|
FILE *tmpfp;
|
|
|
|
|
|
|
|
|
|
w = wl->wl_next; /* Don't consider empty commands. */
|
|
|
|
|
while (w) {
|
|
|
|
|
if (*w->wl_word == cp_lt) {
|
|
|
|
|
bt = w;
|
|
|
|
|
if (gotinput) {
|
|
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Error: ambiguous input redirect.\n");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
gotinput = TRUE;
|
|
|
|
|
w = w->wl_next;
|
|
|
|
|
if (w == NULL) {
|
|
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Error: missing name for input.\n");
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
if (*w->wl_word == cp_lt) {
|
|
|
|
|
/* Do reasonable stuff here... */
|
|
|
|
|
} else {
|
2000-10-26 19:02:12 +02:00
|
|
|
/*tmpfp = fopen(cp_unquote(w->wl_word), "r"); DG very bad: memory leak the string allocated by cp_unquote is lost*/
|
|
|
|
|
copyword=cp_unquote(w->wl_word);/*DG*/
|
|
|
|
|
tmpfp = fopen(copyword, "r");
|
|
|
|
|
tfree(copyword);
|
|
|
|
|
|
* frontend/Makefile.am: Updates for new files.
* frontend/breakp2.c, frontend/newcoms.c, frontend/postcoms.c,
frontend/resource.c, frontend/terminal.h, frontend/variable.c,
frontend/variable.h, frontend/com_compose.c,
frontend/com_display.c, frontend/com_setscale.c,
frontend/com_strcmp.c: Include files update.
* parser/var2.c, parser/var2.h: Empty files, removed.
* parser/Makefile.am: Updates for removed files.
* parser/lexical.c: Small adjustments
* parser/input.c, parser/input.h: Input, output and error streams
handled in the frontend. Moved to the frontend directory.
* frontend/streams.c: Its new home.
2000-07-07 16:09:06 +02:00
|
|
|
if (!tmpfp) {
|
|
|
|
|
perror(w->wl_word);
|
|
|
|
|
goto error;
|
|
|
|
|
} else
|
|
|
|
|
cp_in = tmpfp;
|
|
|
|
|
}
|
|
|
|
|
#ifdef CPDEBUG
|
|
|
|
|
if (cp_debug)
|
|
|
|
|
fprintf(cp_err, "Input file is %s...\n",
|
|
|
|
|
w->wl_word);
|
|
|
|
|
#endif
|
|
|
|
|
bt->wl_prev->wl_next = w->wl_next;
|
|
|
|
|
if (w->wl_next)
|
|
|
|
|
w->wl_next->wl_prev = bt->wl_prev;
|
|
|
|
|
nw = w->wl_next;
|
|
|
|
|
w->wl_next = NULL;
|
|
|
|
|
w = nw;
|
|
|
|
|
wl_free(bt);
|
|
|
|
|
} else if (*w->wl_word == cp_gt) {
|
|
|
|
|
bt = w;
|
|
|
|
|
if (gotoutput) {
|
|
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Error: ambiguous output redirect.\n");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
gotoutput = TRUE;
|
|
|
|
|
w = w->wl_next;
|
|
|
|
|
if (w == NULL) {
|
|
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Error: missing name for output.\n");
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
if (*w->wl_word == cp_gt) {
|
|
|
|
|
app = TRUE;
|
|
|
|
|
w = w->wl_next;
|
|
|
|
|
if (w == NULL) {
|
|
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Error: missing name for output.\n");
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (*w->wl_word == cp_amp) {
|
|
|
|
|
erralso = TRUE;
|
|
|
|
|
if (goterror) {
|
|
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Error: ambiguous error redirect.\n");
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
goterror = TRUE;
|
|
|
|
|
w = w->wl_next;
|
|
|
|
|
if (w == NULL) {
|
|
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Error: missing name for output.\n");
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
s = cp_unquote(w->wl_word);
|
|
|
|
|
if (cp_noclobber && fileexists(s)) {
|
|
|
|
|
fprintf(stderr, "Error: %s: file exists\n", s);
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
if (app)
|
|
|
|
|
tmpfp = fopen(s, "a");
|
|
|
|
|
else
|
|
|
|
|
tmpfp = fopen(s, "w+");
|
2000-10-26 19:02:12 +02:00
|
|
|
tfree(s);/*DG cp_unquote memory leak*/
|
* frontend/Makefile.am: Updates for new files.
* frontend/breakp2.c, frontend/newcoms.c, frontend/postcoms.c,
frontend/resource.c, frontend/terminal.h, frontend/variable.c,
frontend/variable.h, frontend/com_compose.c,
frontend/com_display.c, frontend/com_setscale.c,
frontend/com_strcmp.c: Include files update.
* parser/var2.c, parser/var2.h: Empty files, removed.
* parser/Makefile.am: Updates for removed files.
* parser/lexical.c: Small adjustments
* parser/input.c, parser/input.h: Input, output and error streams
handled in the frontend. Moved to the frontend directory.
* frontend/streams.c: Its new home.
2000-07-07 16:09:06 +02:00
|
|
|
if (!tmpfp) {
|
|
|
|
|
perror(w->wl_word);
|
|
|
|
|
goto error;
|
|
|
|
|
} else {
|
|
|
|
|
cp_out = tmpfp;
|
|
|
|
|
out_isatty = FALSE;
|
|
|
|
|
}
|
|
|
|
|
#ifdef CPDEBUG
|
|
|
|
|
if (cp_debug)
|
|
|
|
|
fprintf(cp_err, "Output file is %s... %s\n",
|
|
|
|
|
w->wl_word, app ? "(append)" : "");
|
|
|
|
|
#endif
|
|
|
|
|
bt->wl_prev->wl_next = w->wl_next;
|
|
|
|
|
if (w->wl_next)
|
|
|
|
|
w->wl_next->wl_prev = bt->wl_prev;
|
|
|
|
|
w = w->wl_next;
|
|
|
|
|
if (w)
|
|
|
|
|
w->wl_prev->wl_next = NULL;
|
|
|
|
|
wl_free(bt);
|
|
|
|
|
if (erralso)
|
|
|
|
|
cp_err = cp_out;
|
|
|
|
|
} else
|
|
|
|
|
w = w->wl_next;
|
|
|
|
|
}
|
|
|
|
|
return (wl);
|
|
|
|
|
|
|
|
|
|
error: wl_free(wl);
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Reset the cp_* FILE pointers to the standard ones. This is tricky,
|
|
|
|
|
* since if we are sourcing a command file, and io has been redirected
|
|
|
|
|
* from inside the file, we have to reset it back to what it was for
|
|
|
|
|
* the source, not for the top level. That way if you type "foo >
|
|
|
|
|
* bar" where foo is a script, and it has redirections of its own
|
|
|
|
|
* inside of it, none of the output from foo will get sent to
|
|
|
|
|
* stdout... */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
cp_ioreset(void)
|
|
|
|
|
{
|
|
|
|
|
if (cp_in != cp_curin) {
|
|
|
|
|
if (cp_in)
|
|
|
|
|
fclose(cp_in);
|
|
|
|
|
cp_in = cp_curin;
|
|
|
|
|
}
|
|
|
|
|
if (cp_out != cp_curout) {
|
|
|
|
|
if (cp_out)
|
|
|
|
|
fclose(cp_out);
|
|
|
|
|
cp_out = cp_curout;
|
|
|
|
|
}
|
|
|
|
|
if (cp_err != cp_curerr) {
|
|
|
|
|
if (cp_err)
|
|
|
|
|
fclose(cp_err);
|
|
|
|
|
cp_err = cp_curerr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** Minor bug here... */
|
|
|
|
|
out_isatty = TRUE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Do this only right before an exec, since we lose the old std*'s. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
fixdescriptors(void)
|
|
|
|
|
{
|
|
|
|
|
if (cp_in != stdin)
|
|
|
|
|
dup2(fileno(cp_in), fileno(stdin));
|
|
|
|
|
if (cp_out != stdout)
|
|
|
|
|
dup2(fileno(cp_out), fileno(stdout));
|
|
|
|
|
if (cp_err != stderr)
|
|
|
|
|
dup2(fileno(cp_err), fileno(stderr));
|
|
|
|
|
return;
|
|
|
|
|
}
|