texmacs-dev
[Top][All Lists]
Advanced

[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;
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]