| 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);