Ilya Zakharevich on Thu, 10 Sep 1998 00:26:54 -0400 (EDT)


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Newer gnuplot support patch


Hi, my previous gnuplot support patch did not make it into the
distribution.  Here is the improved version:

Do
  touch ./src/graph/Gnuplot.h
before applying this patch.

This is a very primitive variant of gnuplot support, it does not allow
setting terminal options and output files.  Tested on OS/2 and Solaris
only with libgnuplot.a of the build 340.

To use the new --graphic=gnuplot configure option, you need to have
libgnuplot.a in a location where PARI has a chance to find it.  If
gnuplot does not build a library on your architecture, just do

	ar cr libgnuplot.a *.o

in the gnuplot build directory, and copy it to, say, /opt/local/lib.

Example:
	plotterm("tex");
	ploth(X=1,3,sin(X));

Enjoy,
Ilya

P.S.

It will not work with gnuplot 3.5, since the C files were too intertwined
to separate them by un-ar-ing only, they needed a recompile with some 
#defines to do it.  The build 340 is much better, the interdependence of
files may be broken by just extracting them from the archive.

To support setting the output file name, one may need to globally
rename `outfile' to `pari_outfile' in the C source, and introduce new function
plotfile('str') which sets `outfile' - analoguous to the current
plotterm('str').

My version of Perl interface to Gnuplot low-level plotting supports
options, so it should not be hard to correct plotterm() to support
options.  Maybe later...

(Btw, note that gnuplot has nothing to do with GNU - I corrected one place
which looked like this.)

--- ./Configure.orig	Thu Jul 30 07:05:08 1998
+++ ./Configure	Wed Sep  9 23:31:00 1998
@@ -37,6 +37,7 @@ fastread=yes
 config_file=
 optimization=full
 prefix=/usr/local
+which_graphic_lib=none
 test -n "$GP_INSTALL_PREFIX" && prefix=$GP_INSTALL_PREFIX
 while test $# -gt 0; do
   case "$1" in
@@ -63,6 +64,10 @@ while test $# -gt 0; do
   -rdll)       DYNRELOC=yes;;
   -h|-help|-\?)error=true;;
   -v|-verbhelp)error=verb;;
+  -graphic)   shift; which_graphic_lib=$1; graph_cmd=yes ;;
+  --graphic=*|--graphi=*|--graph=*|--grap=*|--gra=*|--gr=*|--g=*)
+	       graph_cmd=yes 
+	       which_graphic_lib=`echo "$1" | sed -e 's/[-a-z]*=//'`;;
   *) echo "*** Unrecognized option $1." >&2; error=true;;
   esac
   shift
@@ -77,6 +82,7 @@ Options: names can be abbreviated to one
  -verbhelp       a longer help message
  -load           specify a default config file (default $dflt_conf_file)
  --prefix=<dir>  install files in <dir>/... (default $prefix)
+ --graphic=<gr>  which graphic library to use (none X11 sunview gnuplot)
 
 Additional developer options:
  -g              creates debugging version
@@ -355,7 +361,6 @@ echo "Building for architecture: $pretty
 #
 # Looking for libraries now
 #
-which_graphic_lib=none
 completionfun="gp-complete"
 if test "$optimization" != profiling; then
 # First, construct the PATHs
@@ -394,7 +400,7 @@ if test "$optimization" != profiling; th
 #   LIB: X11
   pth=$x11pth
   lib=X11;      . ./locatelib
-  if test -f $Xincroot/X11/Xos.h; then
+  if test -f $Xincroot/X11/Xos.h -a -z "$graph_cmd"; then
     which_graphic_lib=X11
     test -n "$extralib" && echo ..."Extra Libraries are $extralib"
     echo ..."Found X11 header files in $Xincroot/X11"; fi
@@ -404,8 +409,42 @@ if test "$optimization" != profiling; th
       *) pth=$dftpth ;;
   esac
 
-#   LIB: gnuplot (not yet supported).
-# lib=gnuplot;  . ./locatelib
+#   LIB: gnuplot
+  lib=gnuplot;  . ./locatelib
+  gnuplot_libs=
+  case $gnuplot in
+    /*|[c-z]:/*) 
+	lib=png;  . ./locatelib
+	case $png in
+	  /*|[c-z]:/*) 
+		gnuplot_libs="$gnuplot_libs -lpng"
+		lib=z;  . ./locatelib
+		case $z in
+		  /*|[c-z]:/*) 
+			gnuplot_libs="$gnuplot_libs -lz";;
+		esac
+		;;
+	esac
+	lib=gd;  . ./locatelib
+	case $gd in
+	  /*|[c-z]:/*) gnuplot_libs="$gnuplot_libs -lgd";;
+	esac
+	case "$osname" in
+	    os2)
+		lib=jmgraph;  . ./locatelib
+		lib=vesa;  . ./locatelib
+		case $jmgraph in
+		  /*|[c-z]:/*) 
+			case $vesa in
+			  /*|[c-z]:/*) 
+				gnuplot_libs="$gnuplot_libs -ljmgraph -lvesa";;
+			esac
+			;;
+		esac
+		;;
+	esac
+	;;
+  esac
 
 #   LIB: GNU ReadLine
   pth="$TOP/readline $pth"
@@ -520,7 +559,7 @@ EOT
 
   if test -n "$readline"; then completionfun="gp-complete2"; fi
   case $gnuplot in
-    /*) addgnuplot=gnuplot;;
+    /*|[c-z]:/*) addgnuplot=gnuplot;;
      *) addgnuplot=;;
   esac
 
@@ -600,6 +639,11 @@ EOT
   esac
   fi
   if test "$fastread" = yes -a \
+    "$which_graphic_lib" = none -a -z "$graph_cmd" -a ! -z "$gnuplot"; then
+    which_graphic_lib=gnuplot
+  fi
+
+  if test "$fastread" = yes -a \
     -z "$X11" -a -z "$gnuplot" -a -z "$readline"; then
     echo ...none
   fi
@@ -1080,7 +1124,7 @@ for variable in \
   sizeof_long endian has_exp2\
   has_getrusage has_times has_ulong has_ftime has_strftime\
   has_sigrelse has_sigsetmask has_dlopen has_TIOCGWINSZ\
-  gnuplot extralib X11 Xincroot which_graphic_lib \
+  gnuplot extralib X11 Xincroot which_graphic_lib gnuplot_libs \
   config_dir src_dir emacs_dir doc_dir \
   ; do
   eval "echo $variable=\'"'$'"$variable\'" \>\> $dflt_conf_file
--- ./config/Makefile.SH.orig	Wed Sep  9 21:38:02 1998
+++ ./config/Makefile.SH	Wed Sep  9 22:44:46 1998
@@ -70,6 +70,17 @@ none)
   PLOTLIBS=
   plotrunpath=
   ;;
+gnuplot)
+  PLOTFILE=plotgnuplot.c
+  PLOTCFLAGS=
+  GNUPLOT_OBJS="bitmap.o term.o util.o version.o"
+  PLOTLIBS="$gnuplot_libs"
+  plotrunpath=
+  case "$osname" in
+    os2) libgnuplot=$gnuplot/gnuplot.a;;
+    *) libgnuplot=$gnuplot/libgnuplot.a;;
+  esac
+  ;;
 sunview)
   PLOTFILE=plotsun.c
   PLOTCFLAGS=
@@ -165,6 +176,7 @@ INSTALL_DATA = \$(INSTALL) -m 644
 PLOTFILE   = $PLOTFILE
 PLOTCFLAGS = $PLOTCFLAGS
 PLOTLIBS   = $PLOTLIBS
+GNUPLOT_OBJS = $GNUPLOT_OBJS
 # Try uncommenting this line if you're using X11 and linking fails:
 #  PLOTLIBS=-L$X11 -lX11
 
@@ -217,17 +229,17 @@ EOT
 fi
 cat >> $file << EOT
 
-gp-sta: \$(OBJS) \$(OBJSGP)
+gp-sta: \$(OBJS) \$(OBJSGP) \$(GNUPLOT_OBJS)
 	\$(RM) \$@
-	\$(LD) -o \$@ \$(LDFLAGS) \$(OBJS) \$(OBJSGP) \$(RUNPTH) \$(RLLIBS) \$(PLOTLIBS) \$(LIBS)
+	\$(LD) -o \$@ \$(LDFLAGS) \$(OBJS) \$(OBJSGP) \$(GNUPLOT_OBJS) \$(RUNPTH) \$(RLLIBS) \$(PLOTLIBS) \$(LIBS)
 EOT
 
 if test -z "$DYNLIBS"; then
 cat >> $file << EOT
 
-gp-dyn: \$(OBJSGP) libpari.$somake
+gp-dyn: \$(OBJSGP) libpari.$somake \$(GNUPLOT_OBJS)
 	\$(RM) \$@
-	\$(LD) -o \$@ \$(LDFLAGS) \$(OBJSGP) \$(RUNPTH) \$(TOPLDDYN) \$(LDDYN) \$(PLOTLIBS) \$(LIBS)
+	\$(LD) -o \$@ \$(LDFLAGS) \$(OBJSGP) \$(GNUPLOT_OBJS) \$(RUNPTH) \$(TOPLDDYN) \$(LDDYN) \$(PLOTLIBS) \$(LIBS)
 EOT
 else
 cat >> $file << EOT
@@ -354,6 +366,14 @@ EOT
 EOT
     fi
   fi
+fi
+
+if test -n "$GNUPLOT_OBJS"; then
+cat >> $file << EOT
+\$(GNUPLOT_OBJS):
+	ar x $libgnuplot \$(GNUPLOT_OBJS)
+
+EOT
 fi
 
 if test -n "$emacs"; then
--- ./src/graph/Gnuplot.h.pre	Sat Apr 11 03:15:10 1998
+++ ./src/graph/Gnuplot.h	Sat Apr 11 03:47:18 1998
@@ -0,0 +1,305 @@
+/* This header should be included in one C file only! */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/* CAT2:
+ *      This macro catenates 2 tokens together.
+ */
+/* STRINGIFY:
+ *      This macro surrounds its token with double quotes.
+ */
+#ifndef CAT2
+# if 42 == 1
+#  define CAT2(a,b)a/**/b
+#  define CAT3(a,b,c)a/**/b/**/c
+#  define CAT4(a,b,c,d)a/**/b/**/c/**/d
+#  define CAT5(a,b,c,d,e)a/**/b/**/c/**/d/**/e
+#  define STRINGIFY(a)"a"
+                /* If you can get stringification with catify, tell me how! */
+# endif
+# if 42 == 42
+#  define CAT2(a,b)a ## b
+#  define CAT3(a,b,c)a ## b ## c
+#  define CAT4(a,b,c,d)a ## b ## c ## d
+#  define CAT5(a,b,c,d,e)a ## b ## c ## d ## e
+#  define StGiFy(a)# a
+#  define STRINGIFY(a)StGiFy(a)
+#  define SCAT2(a,b)StGiFy(a) StGiFy(b)
+#  define SCAT3(a,b,c)StGiFy(a) StGiFy(b) StGiFy(c)
+#  define SCAT4(a,b,c,d)StGiFy(a) StGiFy(b) StGiFy(c) StGiFy(d)
+#  define SCAT5(a,b,c,d,e)StGiFy(a) StGiFy(b) StGiFy(c) StGiFy(d) StGiFy(e)
+# endif
+# ifndef CAT2
+#   include "Bletch: How does this C preprocessor catenate tokens?"
+# endif
+#endif /* CAT2 */
+
+
+#define TERM_CAN_MULTIPLOT    1  /* tested if stdout not redirected */
+#define TERM_CANNOT_MULTIPLOT 2  /* tested if stdout is redirected  */
+#define TERM_BINARY           4  /* open output file with "b"       */
+
+#ifndef NO_JUNK_SMALL
+
+extern  FILE *outfile;
+#ifndef BITS_IN_HALFULONG /* In pari it is already defined. */
+FILE *outfile = stdout;
+#endif
+
+extern int encoding;
+int        encoding = 0;
+extern float                   xoffset;  /* x origin */
+extern float                   yoffset;  /* y origin */
+float                   xoffset = 0.0;  /* x origin */
+float                   yoffset = 0.0;  /* y origin */
+extern int		multiplot;
+int		multiplot		= 0;
+
+extern char *outstr;
+#define MAX_ID_LEN 50
+/* char        outstr[MAX_ID_LEN+1] = "STDOUT"; */
+char        *outstr = NULL;
+extern double ticscale; /* scale factor for tic marks (was (0..1])*/
+double        ticscale = 1.0; /* scale factor for tic mark */
+
+char *input_line = NULL;
+int inline_num;          /* from command.c */
+
+float xsize=1.0, ysize=1.0, pointsize=1.0;		/* During test! */
+
+int interactive;    /* from plot.c */
+char *infile_name;       /* from plot.c */
+extern char     default_font[]; 
+char            default_font[MAX_ID_LEN+1] = "\0"; /* Entry added by DJL */
+
+typedef int TBOOLEAN;
+
+enum DATA_TYPES {
+	INTGR, CMPLX
+};
+
+#if !(defined(ATARI)&&defined(__GNUC__)&&defined(_MATH_H)) &&  !(defined(MTOS)&&defined(__GNUC__)&&defined(_MATH_H)) /* FF's math.h has the type already */
+struct cmplx {
+	double real, imag;
+};
+#endif
+
+struct value {
+	enum DATA_TYPES type;
+	union {
+		int int_val;
+		struct cmplx cmplx_val;
+	} v;
+};
+
+struct lexical_unit {	/* produced by scanner */
+	TBOOLEAN is_token;	/* true if token, false if a value */ 
+	struct value l_val;
+	int start_index;	/* index of first char in token */
+	int length;			/* length of token in chars */
+};
+
+/* char *token; */
+#define MAX_TOKENS 20
+extern struct lexical_unit *token;
+struct lexical_unit tokens[MAX_TOKENS];	/* We only process options,
+					   there should not be many */
+struct lexical_unit *token = tokens;
+long c_token = 0, num_tokens = 0;
+char term_options[200] = "";
+
+/* Here are the only missing functions: */
+
+struct value*
+const_express(struct value*v) 
+{
+    if (token[c_token].is_token)
+	croak("Expect a number, got a string");
+    *v = token[c_token++].l_val;
+    return v;
+}
+
+void*
+gp_alloc(unsigned long size, char *usage) 
+{
+  return malloc(size);
+}
+
+void*
+gp_realloc(void *old, unsigned long size, char *usage) 
+{
+  return realloc(old,size);
+}
+
+void
+bail_to_command_line() 
+{
+  croak("panic: gnuplot");
+}
+
+#endif
+
+/* Cannot pull the whole plot.h, too many contradictions. */
+
+#ifdef __ZTC__
+typedef int (*FUNC_PTR)(...);
+#else
+typedef int (*FUNC_PTR)();
+#endif
+
+struct TERMENTRY {
+        char *name;
+#if defined(_Windows) && !defined(WIN32)
+        char GPFAR description[80];     /* to make text go in FAR segment */
+#else
+        char *description;
+#endif
+        unsigned int xmax,ymax,v_char,h_char,v_tic,h_tic;
+        FUNC_PTR options,init,reset,text,scale,graphics,move,vector,linetype,
+                put_text,text_angle,justify_text,point,arrow,set_font,
+		pointsize;
+	int flags;
+        FUNC_PTR suspend,resume,fillbox,linewidth;
+};
+
+#ifdef _Windows
+#  define termentry TERMENTRY far
+#else
+#  define termentry TERMENTRY
+#endif
+
+extern struct termentry *term;
+struct termentry *term;
+ 
+#define RETVOID 
+#define RETINT , 1
+
+#define F_0 void(*)()
+#define F_1 void(*)(int)
+#define F_1I int(*)(int)
+#define F_1D void(*)(double)
+#define F_1IP int(*)(char*)
+#define F_2 void(*)(unsigned int,unsigned int)
+#define F_2D int(*)(double,double)
+#define F_3 void(*)(unsigned int,unsigned int,int)
+#define F_3T void(*)(int,int,char*)
+#define F_4 void(*)(int,int,int,int)
+#define F_5 void(*)(int,int,int,int,int)
+
+#define CALL_G_METH0(method) CALL_G_METH(method,0,(),RETVOID)
+#define CALL_G_METH1(method,arg1) CALL_G_METH(method,1,(arg1),RETVOID)
+#define CALL_G_METH1I(method,arg1) CALL_G_METH(method,1I,(arg1),RETINT)
+#define CALL_G_METH1D(method,arg1) CALL_G_METH(method,1D,(arg1),RETVOID)
+#define CALL_G_METH1IP(method,arg1) CALL_G_METH(method,1IP,(arg1),RETINT)
+#define CALL_G_METH2(method,arg1,arg2) \
+		CALL_G_METH(method,2,((arg1),(arg2)),RETVOID)
+#define CALL_G_METH2D(method,arg1,arg2) \
+		CALL_G_METH(method,2D,((arg1),(arg2)),RETINT)
+#define CALL_G_METH3(method,arg1,arg2,arg3) \
+		CALL_G_METH(method,3,((arg1),(arg2),(arg3)),RETVOID)
+#define CALL_G_METH3T(method,arg1,arg2,arg3) \
+		CALL_G_METH(method,3T,((arg1),(arg2),(arg3)),RETVOID)
+#define CALL_G_METH4(method,arg1,arg2,arg3,arg4) \
+		CALL_G_METH(method,4,((arg1),(arg2),(arg3),(arg4)),RETVOID)
+#define CALL_G_METH5(method,arg1,arg2,arg3,arg4,arg5) \
+		CALL_G_METH(method,5,((arg1),(arg2),(arg3),(arg4),(arg5)),RETVOID)
+
+#define CALL_G_METH(method,mult,args,returnval)    (		\
+       (term==0) ? (						\
+	 croak("No terminal specified") returnval		\
+       ) :							\
+       (*(CAT2(F_,mult))term->method)args		\
+     )
+
+#define GET_G_FLAG(mask)    (		\
+       (term==0) ? (						\
+	 croak("No terminal specified") RETINT		\
+       ) :							\
+       (term->flags & (mask)))
+
+#define do_init()	CALL_G_METH0(init)
+#define reset()	CALL_G_METH0(reset)
+#define text()	CALL_G_METH0(text)
+#define options()	CALL_G_METH0(options)
+#define graphics()	CALL_G_METH0(graphics)
+#define linetype(lt)	CALL_G_METH1(linetype,lt)
+#define justify_text(mode)	CALL_G_METH1I(justify_text,mode)
+#define text_angle(ang)	CALL_G_METH1I(text_angle,ang)
+#define scale(xs,ys)	CALL_G_METH2D(scale,xs,ys)
+#define move(x,y)	CALL_G_METH2(move,x,y)
+#define vector(x,y)	CALL_G_METH2(vector,x,y)
+#define put_text(x,y,str)	CALL_G_METH3T(put_text,x,y,str)
+#define point(x,y,p)	CALL_G_METH3(point,x,y,p)
+#define arrow(sx,sy,ex,ey,head)	CALL_G_METH5(arrow,sx,sy,ex,ey,head)
+#define set_font(font)	CALL_G_METH1IP(set_font,font)
+#define pointsize(size)	CALL_G_METH1D(pointsize,size)
+#define suspend()	CALL_G_METH0(suspend)
+#define resume()	CALL_G_METH0(resume)
+#define fillbox(sx,sy,ex,ey,head)	CALL_G_METH5(fillbox,sx,sy,ex,ey,head)
+#define linewidth(size)	CALL_G_METH1D(linewidth,size)
+#define can_multiplot()	GET_G_FLAG(TERM_CAN_MULTIPLOT)
+#define cannot_multiplot()	GET_G_FLAG(TERM_CANNOT_MULTIPLOT)
+#define is_binary()	GET_G_FLAG(TERM_BINARY)
+
+#define termprop(prop) (term->prop)
+#define termset(term) my_change_term(term,strlen(term))
+struct termentry * change_term(char*,int);
+
+#ifdef DYNAMIC_PLOTTING			/* Can load plotting DLL later */
+
+UNKNOWN_null()
+{
+    err(talker,"gnuplot-like plotting environment not loaded yet");
+}
+
+static FUNC_PTR change_term_p;
+
+struct termentry *
+my_change_term(char*s,int l) 
+{
+    if (!change_term_p)
+	UNKNOWN_null();
+    return term = (struct termentry *)(*change_term_p)(s,l);
+}
+
+#  define change_term(p,l) my_change_term(p,l)
+#  define term_tbl (my_term_tbl)
+
+static struct termentry dummy_term_tbl[] = {
+    {"unknown", "Unknown terminal type - not a plotting device",
+	  100, 100, 1, 1,
+	  1, 1, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, 
+	  UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, 
+	  UNKNOWN_null, UNKNOWN_null, UNKNOWN_null,
+     UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, 0,
+	, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null},
+};
+static struct termentry *my_term_tbl = dummy_term_tbl;
+
+/* This function should be called before any graphic code can be used... */
+set_term_funcp(FUNC_PTR change_p, struct termentry *term_p)
+{
+    my_term_tbl = term_p;
+    change_term_p = change_p;
+}
+
+#else /* !DYNAMIC_PLOTTING */
+
+extern struct termentry term_tbl[];
+
+#  define my_change_term change_term
+#  define my_term_tbl term_tbl
+
+#endif /* DYNAMIC_PLOTTING */
+
+
+
+#ifdef __cplusplus
+  }
+#endif
--- ./src/graph/plotgnuplot.c.pree	Sat Feb  7 11:12:06 1998
+++ ./src/graph/plotgnuplot.c	Sat Apr 11 03:47:48 1998
@@ -119,20 +119,23 @@ rectdraw0(long *w, long *x, long *y, lon
 void
 PARI_get_plot()
 {
-  if (pari_plot.init) return;
-  term_set(DEF_TERM);
+  if (pari_plot.init) {
+    return;
+  }
+  term_set( DEF_TERM );
 }
 
+
 long
 term_set(char *s)
 {
-  if (!s) return 1;
   if (strlen(s) > PLOT_NAME_LEN) err(talker,"too long name for terminal");
-  if (*pari_plot.name && (strcmp(pari_plot.name,s) != 0)) reset();
-
+  if (*pari_plot.name && (strcmp(pari_plot.name,s) != 0)) {
+	reset();
+  }
   strcpy(pari_plot.name,s);
-  if (termset(s) <= 0) err(talker,"unknown terminal name");
-  init();  /* Init terminal. */
+  if (!termset( s )) err(talker,"unknown terminal name");
+  do_init();				/* Init terminal. */
 
   w_width = termprop(xmax);
   w_height = termprop(ymax);