Ilya Zakharevich on Sat, 11 Apr 1998 21:41:14 +0200


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

Gnuplot plotting in PARI


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 only.  

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.  Note
that I do not check for the version of gnuplot library (how to do
it?), I just trust that it is good enough if present.  Currently
gnuplot is enabled only if X and friends are not found.

To support output file name, one may need to globally rename `outfile' to 
`pari_outfile', 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
(as of yesterday ;-), 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.)

Enjoy,
Ilya

--- ./Configure.preplot	Sat Feb 14 01:04:42 1998
+++ ./Configure	Sat Apr 11 15:02:26 1998
@@ -380,8 +380,35 @@ if test "$optimization" != profiling; th
       *) pth=$dftpth ;;
   esac
 
-#   LIB: GNU Plot (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";;
+	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"
@@ -472,7 +499,7 @@ EOT
 
   if test -n "$readline"; then completionfun="gp-complete2"; fi
   case $gnuplot in
-    /*) addgnuplot=gnuplot;;
+    /*|[c-z]:/*) addgnuplot=gnuplot;;
      *) addgnuplot=;;
   esac
 
@@ -552,6 +579,11 @@ EOT
   esac
   fi
   if test "$fastread" = yes -a \
+    "$which_graphic_lib" = none -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
@@ -989,7 +1021,7 @@ for variable in \
   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 \
-  config_dir src_dir emacs_dir perl_dir doc_dir \
+  config_dir src_dir emacs_dir perl_dir doc_dir gnuplot_libs \
   ; do
   eval "echo $variable=\'"'$'"$variable\'" \>\> $dflt_conf_file
 done
--- pari-2.0.5.alpha/config/Makefile.SH	Sat Feb  7 12:22:56 1998
+++ pari-2.0.5.alpha.my/config/Makefile.SH	Sat Apr 11 15:13:50 1998
@@ -64,6 +64,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=
@@ -149,6 +160,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"
 
@@ -194,11 +206,11 @@ EOT
 fi
 cat >> $file << EOT
 
-gp-sta: \$(OBJS) \$(OBJSGP)
-	\$(LD) -o gp-sta \$(LDFLAGS) \$(OBJS) \$(OBJSGP) \$(RUNPTH) \$(RLLIBS) \$(PLOTLIBS) \$(LIBS)
+gp-sta: \$(OBJS) \$(OBJSGP) \$(GNUPLOT_OBJS)
+	\$(LD) -o gp-sta \$(LDFLAGS) \$(OBJS) \$(OBJSGP) \$(GNUPLOT_OBJS) \$(RUNPTH) \$(RLLIBS) \$(PLOTLIBS) \$(LIBS)
 
-gp-dyn: \$(OBJSGP) libpari.$somake
-	\$(LD) -o \$@ \$(LDFLAGS) \$(OBJSGP) \$(RUNPTH) \$(TOPLDDYN) \$(LDDYN) \$(PLOTLIBS) \$(LIBS)
+gp-dyn: \$(OBJSGP) libpari.$somake \$(GNUPLOT_OBJS)
+	\$(LD) -o \$@ \$(LDFLAGS) \$(OBJSGP) \$(GNUPLOT_OBJS) \$(RUNPTH) \$(TOPLDDYN) \$(LDDYN) \$(PLOTLIBS) \$(LIBS)
 
 bench: $exec dobench
 test: $exec dotest
@@ -317,6 +329,14 @@ EOT
 	-\$(LN) libpari.$sodest libpari.$DLSUFFIX
 EOT
   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);