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