/* $Id: Gnuplot.h,v 1.7 2002/06/09 18:49:11 karim Exp $ Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This header should be included in one C file only! */ #include #include #include #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 /* Compatibility with the old gnuplot: */ extern FILE *outfile; FILE *outfile = NULL; extern FILE *gpoutfile; FILE *gpoutfile = NULL; static outfile_set; static void set_gpoutfile(void) { outfile = stdout; gpoutfile = stdout; } #define SET_OUTFILE (outfile_set++ ? 1 : (set_gpoutfile(), 1)) 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; double 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] = ""; /* New with 3.7.1: */ #define FIRST_Z_AXIS 0 #define FIRST_Y_AXIS 1 #define FIRST_X_AXIS 2 #define SECOND_Z_AXIS 4 /* for future expansion ;-) */ #define SECOND_Y_AXIS 5 #define SECOND_X_AXIS 6 /* extend list for datatype[] for t,u,v,r though IMHO * they are not relevant to time data [being parametric dummies] */ #define T_AXIS 3 /* fill gap */ #define R_AXIS 7 /* never used ? */ #define U_AXIS 8 #define V_AXIS 9 #define AXIS_ARRAY_SIZE 10 #define DATATYPE_ARRAY_SIZE 10 extern double base_array[], log_base_array[]; extern TBOOLEAN log_array[]; /* graphics.c */ extern TBOOLEAN is_3d_plot; double min_array[AXIS_ARRAY_SIZE], max_array[AXIS_ARRAY_SIZE], base_array[AXIS_ARRAY_SIZE], log_base_array[AXIS_ARRAY_SIZE]; TBOOLEAN log_array[AXIS_ARRAY_SIZE]; int xleft, xright, ybot, ytop; TBOOLEAN is_3d_plot; /* End of 3.7.1 additions */ /* 3.7.0-devel additions */ extern float surface_rot_z; extern TBOOLEAN polar; extern double base_log_x, base_log_y, base_log_z; extern TBOOLEAN is_log_x, is_log_y, is_log_z; extern double log_base_log_x2, log_base_log_y2; extern double base_z; extern TBOOLEAN screen_ok; float surface_rot_z = 30.0; TBOOLEAN polar = 0; TBOOLEAN is_log_x = 0; TBOOLEAN is_log_y = 0; TBOOLEAN is_log_z = 0; double base_log_x = 0.0; double base_log_y = 0.0; double base_log_z = 0.0; double log_base_log_x = 0.0; double log_base_log_y = 0.0; double log_base_log_z = 0.0; double base_z = 0.0; TBOOLEAN screen_ok; void map3d_xy (double x, double y, double z, unsigned int *xt, unsigned int *yt) { croak("Unsupported function map3d_xy called"); } /* End of 3.7.0-devel additions */ /* 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) { (void)usage; return malloc(size); } void* gp_realloc(void *old, unsigned long size, char *usage) { (void)usage; return realloc(old,size); } void bail_to_command_line() { croak("panic: gnuplot"); } #endif /* NO_JUNK_SMALL */ /* 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))) #ifdef DONT_POLLUTE_INIT # define gptable_init() CALL_G_METH0(init) #else # define init() CALL_G_METH0(init) # define gptable_init init #endif #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 setpointsize(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); #define TTABLE_STARTPLOT 0 #define TTABLE_ENDPLOT 1 #define TTABLE_STARTMPLOT 2 #define TTABLE_ENDMPLOT 3 #define TTABLE_INIT 4 #define TTABLE_LIST 5 #define TTABLE_COUNT 6 typedef void (*TSET_FP)(char *s); typedef void (*TST_END_FP)(void); typedef void (*SET_SIZES_t)(double x, double y); typedef double (*GET_SIZES_t)(int flag); typedef void (*SET_MOUSE_FEEDBACK_RECTAGLE_t)(int term_xmin, int term_xmax, int term_ymin, int term_ymax, double plot_xmin, double plot_xmax, double plot_ymin, double plot_ymax); struct t_ftable { int loaded; FUNC_PTR change_term_p; TSET_FP term_set_outputp; SET_SIZES_t set_sizesp; GET_SIZES_t get_sizesp; TST_END_FP term_funcs[TTABLE_COUNT]; SET_MOUSE_FEEDBACK_RECTAGLE_t mouse_feedback_func; }; #ifdef DYNAMIC_PLOTTING /* Can load plotting DLL later */ int UNKNOWN_null() { croak("gnuplot-like plotting environment not loaded yet"); return 0; } static void myterm_table_not_loaded_v(void); static void myterm_table_not_loaded(char*); static int myterm_table_not_loaded_u(); static void myterm_table_not_loaded_vdd(double x, double y); static double myterm_table_not_loaded_di(int flag); static void myterm_table_not_loaded_v4i4d(int term_xmin, int term_xmax, int term_ymin, int term_ymax, double plot_xmin, double plot_xmax, double plot_ymin, double plot_ymax); #if 0 static int ftable_warned; static void tmp_my_term_init { if (!warned++) warn("This runtime link with gnuplot-shim does not implement midlevel start/end functions"); shim_myinit(); } #endif static struct t_ftable my_term_ftable = { 0, &myterm_table_not_loaded_u, &myterm_table_not_loaded, &myterm_table_not_loaded_vdd, &myterm_table_not_loaded_di, {&myterm_table_not_loaded_v, &myterm_table_not_loaded_v, &myterm_table_not_loaded_v, &myterm_table_not_loaded_v, &myterm_table_not_loaded_v, &myterm_table_not_loaded_v}, myterm_table_not_loaded_v4i4d }; static struct t_ftable *my_term_ftablep = &my_term_ftable; static void myterm_table_not_loaded_v(void) { if (!my_term_ftablep->loaded) { UNKNOWN_null(); return; } croak("This runtime link with gnuplot-shim does not implement midlevel start/end functions"); } static void myterm_table_not_loaded(char *s) { myterm_table_not_loaded_v(); } static void myterm_table_not_loaded_vdd(double x, double y) { myterm_table_not_loaded_v(); } static double myterm_table_not_loaded_di(int flag) { myterm_table_not_loaded_v(); return 0; /* NOT REACHED */ } static int myterm_table_not_loaded_u() { myterm_table_not_loaded_v(); return 0; } void myterm_table_not_loaded_v4i4d(int term_xmin, int term_xmax, int term_ymin, int term_ymax, double plot_xmin, double plot_xmax, double plot_ymin, double plot_ymax) { myterm_table_not_loaded_v(); } # define change_term (*my_term_ftablep->change_term_p) # define term_set_output (*my_term_ftablep->term_set_outputp) # define term_start_plot (*my_term_ftablep->term_funcs[TTABLE_STARTPLOT]) # define term_end_plot (*my_term_ftablep->term_funcs[TTABLE_ENDPLOT]) # define term_start_multiplot (*my_term_ftablep->term_funcs[TTABLE_STARTMPLOT]) # define term_end_multiplot (*my_term_ftablep->term_funcs[TTABLE_ENDMPLOT]) # define term_init (*my_term_ftablep->term_funcs[TTABLE_INIT]) # define list_terms (*my_term_ftablep->term_funcs[TTABLE_LIST]) # define plotsizes_scale (*my_term_ftablep->set_sizesp) # define plotsizes_scale_get (*my_term_ftablep->get_sizesp) #ifdef USE_SET_FEEDBACK_RECTANGLE /* If DLL has it, but was compiled with older Gnuplot.h */ # define set_mouse_feedback_rectangle (*my_term_ftablep->mouse_feedback_func) #else # define set_mouse_feedback_rectangle(term_xmin, term_xmax, term_ymin, term_ymax, plot_xmin, plot_xmax, plot_ymin, plot_ymax) \ ((my_term_ftablep->loaded & 2) ? \ ((*my_term_ftablep->mouse_feedback_func)(term_xmin, term_xmax, term_ymin, term_ymax, plot_xmin, plot_xmax, plot_ymin, plot_ymax), 0) : 0) #endif /* defined USE_SET_FEEDBACK_RECTANGLE */ # define scaled_xmax() ((int)termprop(xmax)*plotsizes_scale_get(0)) # define scaled_ymax() ((int)termprop(ymax)*plotsizes_scale_get(1)) #define USE_FUNCTION_FROM_TABLE static struct termentry * my_change_term(char*s,int l) { SET_OUTFILE; if (!my_term_ftablep->change_term_p) UNKNOWN_null(); return term = (struct termentry *)(*my_term_ftablep->change_term_p)(s,l); } #if 0 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}, }; #endif #define set_term_funcp(change_p, term_p) set_term_funcp2((change_p), 0) /* #define set_term_funcp3(change_p, term_p, tchange) \ set_term_funcp2((change_p), (tchange)) */ /* This function should be called before any graphic code can be used... */ void set_term_funcp2(FUNC_PTR change_p, TSET_FP tchange) { SET_OUTFILE; my_term_ftable.change_term_p = change_p; my_term_ftable.loaded = 1; if (tchange) { my_term_ftable.term_set_outputp = tchange; } } /* Used from Math::Pari */ void set_term_funcp3(FUNC_PTR change_p, void *term_p, TSET_FP tchange) { set_term_funcp2(change_p, tchange); } void set_term_ftable(struct t_ftable *p) { SET_OUTFILE; my_term_ftablep = p; } extern struct t_ftable *get_term_ftable(); #else /* !DYNAMIC_PLOTTING */ #define set_mouse_feedback_rectangle mys_mouse_feedback_rectangle extern struct termentry term_tbl[]; extern double min_array[], max_array[]; extern int xleft, xright, ybot, ytop; void mys_mouse_feedback_rectangle(int term_xmin, int term_xmax, int term_ymin, int term_ymax, double plot_xmin, double plot_xmax, double plot_ymin, double plot_ymax) { xleft = term_xmin, xright = term_xmax; ybot = term_ymin, ytop = term_ymax; min_array[FIRST_X_AXIS] = min_array[SECOND_X_AXIS] = plot_xmin; max_array[FIRST_X_AXIS] = max_array[SECOND_X_AXIS] = plot_xmax; min_array[FIRST_Y_AXIS] = min_array[SECOND_Y_AXIS] = plot_ymin; max_array[FIRST_Y_AXIS] = max_array[SECOND_Y_AXIS] = plot_ymax; } # define my_change_term change_term # define my_term_tbl term_tbl extern void term_set_output(char *s); extern void term_start_plot(void); extern void term_end_plot(void); extern void term_start_multiplot(void); extern void term_end_multiplot(void); extern void term_init(void); extern void list_terms(void); static void plotsizes_scale(double x, double y) { xsize=x; ysize=y; } static double plotsizes_get(int flag) { return (flag ? ysize : xsize); } struct t_ftable my_term_ftable = { 2, /* bit 2 means it has mys_mouse_feedback_rectangle */ (FUNC_PTR)&change_term, &term_set_output, &plotsizes_scale, &plotsizes_get, {&term_start_plot, &term_end_plot, &term_start_multiplot, &term_end_multiplot, &term_init, &list_terms}, &mys_mouse_feedback_rectangle }; struct t_ftable *get_term_ftable() { SET_OUTFILE; return &my_term_ftable; } void set_term_ftable() { SET_OUTFILE; } void set_term_funcp3(FUNC_PTR change_p, void *term_p, TSET_FP tchange) { SET_OUTFILE; (void)term_p; my_term_ftable.change_term_p = change_p; my_term_ftable.loaded = 1; if (tchange) { my_term_ftable.term_set_outputp = tchange; } } #define scaled_xmax() ((int)termprop(xmax)*xsize) #define scaled_ymax() ((int)termprop(ymax)*ysize) #endif /* !DYNAMIC_PLOTTING */ #define int_get_term_ftable() ((IV)get_term_ftable()) #define int_set_term_ftable(a) (v_set_term_ftable((void*)a)) void v_set_term_ftable(void *a) { set_term_ftable((struct t_ftable*)a); } typedef void (*set_term_ftable_t)(struct t_ftable *p); typedef struct t_ftable *(get_term_ftable_t)(void); extern get_term_ftable_t *get_term_ftable_get(void); static int shim_set; void setup_gpshim(void) { #if 0 if (shim_set++) return; #endif if (!shim_set++) { #ifdef DYNAMIC_PLOTTING_RUNTIME_LINK get_term_ftable_t *f = get_term_ftable_get(); /* Resolve the getter */ if (f) v_set_term_ftable(f()); /* Get the external table */ #endif #ifdef DYNAMIC_PLOTTING_STATIC_LINK void *a = get_term_ftable(); /* Get the external one */ v_set_term_ftable(get_term_ftable()); #endif } SET_OUTFILE; } #ifdef SET_OPTIONS_FROM_STRING /* This sets the tokens for the options */ void set_tokens_string(char *start) { char *s = start; char *tstart; int is_real, is_integer, has_exp; num_tokens = 0; while (num_tokens < MAX_TOKENS) { while (*s == ' ' || *s == '\t' || *s == '\n') s++; if (!*s) return; tstart = s; if (*s == ',') { s++; is_integer = is_real = 0; goto process; } is_integer = is_real = ((*s) != 0); if (*s == '+' || *s == '-') s++; has_exp = 0; while (*s && !(*s == ' ' || *s == '\t' || *s == '\n')) { if (!(*s <= '9' && *s >= '0')) { if (*s == '.') { if (!is_integer) is_real = 0; else if (is_integer == 1 && !(s[1] <= '9' && s[1] >= '0')) is_real = 0; } else if (*s == 'e' || *s == 'E') { if (has_exp) is_real = 0; has_exp = 1; if (s[1] == '+' || s[1] == '-') s++; } else if (*s == ',' && (is_integer || is_real)) break; else is_real = 0; is_integer = 0; } else if (is_integer) is_integer++; s++; } process: token[num_tokens].start_index = tstart - input_line; token[num_tokens].length = s - tstart; if (is_integer) { token[num_tokens].is_token = 0; token[num_tokens].l_val.type = INTGR; token[num_tokens].l_val.v.int_val = atoi(tstart); } else if (is_real) { token[num_tokens].is_token = 0; token[num_tokens].l_val.type = CMPLX; token[num_tokens].l_val.v.cmplx_val.real = atof(tstart); token[num_tokens].l_val.v.cmplx_val.imag = 0; } else { token[num_tokens].is_token = 1; } num_tokens++; } if (num_tokens >= MAX_TOKENS) { char buf[80]; sprintf(buf, "panic: more than %d tokens for options", MAX_TOKENS); croak(buf); } } void set_options_from(char *s) { char *o = input_line; input_line = s; /* for error reports */ set_tokens_string(s); options(); input_line = o; c_token = num_tokens = 0; } #endif #ifdef GNUPLOT_OUTLINE_STDOUT int StartOutput() { return 0; } int EndOutput() { return 0; } int OutLine(char *s) { return fprintf(stdout, "%s", s); } #endif #ifdef __cplusplus } #endif