[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Texmacs-dev] New and improved gnuplot plugin filter
From: |
Igor Khavkine |
Subject: |
Re: [Texmacs-dev] New and improved gnuplot plugin filter |
Date: |
Tue, 27 Apr 2004 00:01:06 -0400 |
Sorry for a garbled attachment. Here is the source code.
Igor
____________________________________________________________
Find what you are looking for with the Lycos Yellow Pages
http://r.lycos.com/r/yp_emailfooter/http://yellowpages.lycos.com/default.asp?SRC=lycos10
/*
Filter for gnuplot for a corresponding TeXmacs plugin.
Copyright (C) 2004 Igor Khavkine <igor.khavkine at utoronto.ca>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
char *gnuplot = "gnuplot";
char *prompt = "gnuplot> ";
char data_begin = 2;
char data_end = 5;
char data_escape = 27;
struct timespec delay = { /* seconds */ 0, /* nanoseconds */ 10*1000 };
int main ()
{
FILE *fgp_in, *fgp_out, *fgp_err;
int err;
int gp_out[2], gp_err[2], gp_in[2];
pid_t gp_pid;
char *input = NULL;
size_t input_len = 0;
char *idx;
char buff[128];
ssize_t buff_read;
int i, isPS, retry, max_retry = 5, eof = 0;
/* open pipes to communicated with child */
err = pipe (gp_out);
err = pipe (gp_in);
err = pipe (gp_err);
gp_pid = fork ();
if (gp_pid == 0) {
/* we are in the child */
close (gp_in[1]);
close (gp_out[0]);
close (gp_err[0]);
dup2 (gp_in[0], STDIN_FILENO); /* redirect stdin */
dup2 (gp_out[1], STDOUT_FILENO); /* stdout */
dup2 (gp_out[1], STDERR_FILENO); /* stderr */
close (gp_in[0]);
close (gp_out[1]);
close (gp_err[1]);
/* replace process with gnuplot */
execlp (gnuplot, "gnuplot", NULL);
/* NOT REACHED */
}
close (gp_in[0]);
close (gp_out[1]);
close (gp_err[1]);
fgp_in = fdopen (gp_in[1], "w");
/* set non-blocking IO */
fcntl (gp_out[0], F_SETFL, O_NONBLOCK);
fcntl (gp_err[0], F_SETFL, O_NONBLOCK);
/* set unbuffered IO */
setvbuf (fgp_in, NULL, _IONBF, 0);
setvbuf (stdout, NULL, _IONBF, 0);
setvbuf (stderr, NULL, _IONBF, 0);
/* set some gnuplot defaults */
fprintf (fgp_in, "set size 1,1\n");
fprintf (fgp_in, "set autoscale\n");
fprintf (fgp_in, "set term postscript eps enhanced\n");
/* begin session */
printf ("%c", data_begin);
printf ("verbatim:This is a TeXmacs interface for GNUplot.\n");
while (1) {
/* print the prompt */
printf ("%c" "prompt#" "%s" "%c", data_begin, prompt, data_end);
/* end verbatim section and allow input from TeXmacs */
printf ("%c", data_end);
/* read a line from input */
getline (&input, &input_len, stdin);
/* replace `~' by `\n' for compatibility with older script */
idx = input;
do {
idx = strchr (idx, '~');
if (idx != NULL) *idx++ = '\n';
} while (idx != NULL);
/* begin verbatim section */
printf ("%c", data_begin);
printf ("verbatim:");
/* send command to gnuplot */
fprintf (fgp_in, "%s\n", input);
/* read from gnuplot's stderr */
buff_read = sizeof (buff);
do {
/* delay to help with non-blocking IO */
nanosleep (&delay, NULL);
if (buff_read != sizeof (buff))
retry++;
else
retry = 0;
buff_read = read (gp_err[0], buff, sizeof (buff));
for (i=0; i<buff_read; i++)
{
/* escape control characters */
if (buff[i] == data_begin
|| buff[i] == data_end
|| buff[i] == data_escape)
{
fputc (data_escape, stderr);
}
fputc (buff[i], stderr);
}
} while (buff_read == sizeof (buff) || retry < max_retry);
/* read from gnuplot's stdout */
isPS = 0;
buff_read = sizeof (buff);
do {
/* delay to help with non-blocking IO */
nanosleep (&delay, NULL);
if (buff_read != sizeof (buff))
retry++;
else
retry = 0;
buff_read = read (gp_out[0], buff, sizeof (buff));
/* check for errors and EOF */
if (buff_read == 0)
{
/* gnuplot process quit */
eof = 1; /* time to bail */
break;
}
else if (buff_read == -1 && errno != EAGAIN)
{
printf ("%c\n", data_end);
perror ("reading from gnuplot");
exit (errno);
}
/* is output a postcript file? */
if (buff_read >= 4
&& buff[0] == '%'
&& buff[1] == '!'
&& buff[2] == 'P'
&& buff[3] == 'S')
{
isPS = 1;
/* begin postscript section */
/* force eventual termination of postscript
output */
fprintf (fgp_in, "set output\n");
printf ("%c" "ps:", data_begin);
}
for (i=0; i<buff_read; i++)
{
/* escape control characters */
if (buff[i] == data_begin
|| buff[i] == data_end
|| buff[i] == data_escape)
{
fputc (data_escape, stdout);
}
fputc (buff[i], stdout);
}
} while (buff_read == sizeof (buff) || retry < max_retry);
if (eof)
break;
if (isPS)
{
/* end postscript section */
printf ("%c\n", data_end);
}
}
/* we are here because the gnuplot process terminated */
printf ("%c", data_end); /* terminate verbatim section */
/* clean up */
free (input);
fclose (fgp_in);
close (gp_out[0]);
close (gp_err[0]);
return 0;
}