# HG changeset patch # User jwe # Date 1142531944 0 # Node ID cbc323d109e4a9e893b9af5f4a6e58b17fe9f75d # Parent 233d98d956595b9abd4014359fef1b1198d76d05 [project @ 2006-03-16 17:59:04 by jwe] diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -16,6 +16,10 @@ 2006-03-16 John W. Eaton * __gnuplot_raw__.l: Move here from DLD-FUNCTIONS/__gnuplot_raw__.l. + Use DEFUN, not DEFUN_DLD. Include defun.h, not defun-dld.h. + (gnuplot::do_init):Move guts to symbols_of___gnuplot_raw__. + (symbols_of___gnuplot_raw__): New function. + * Makefile.in (DLD_XSRC): Delete __gnuplot_raw__.l from the list. (DIST_SRC): Include __gnuplot_raw__.l in the list. (__gnuplot_raw__.cc): Depend on __gnuplot_raw__.l, not diff --git a/src/DLD-FUNCTIONS/__gnuplot_raw__.l b/src/DLD-FUNCTIONS/__gnuplot_raw__.l deleted file mode 100644 --- a/src/DLD-FUNCTIONS/__gnuplot_raw__.l +++ /dev/null @@ -1,1819 +0,0 @@ -/* - -Copyright (C) 2004 John W. Eaton and Teemu Ikonen - -This file is part of Octave. - -Octave 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; either version 2, or (at your option) any -later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octavee; see the file COPYING. If not, write to the Free -Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. - -*/ - -%option prefix="gpt" -%option noyywrap - -%{ -// PKG_ADD: mark_as_rawcommand ("__gnuplot_plot__"); -// PKG_ADD: mark_as_rawcommand ("__gnuplot_set__"); -// PKG_ADD: mark_as_rawcommand ("__gnuplot_splot__"); -// PKG_ADD: mark_as_rawcommand ("__gnuplot_replot__"); - -// PKG_ADD: mark_as_command ("__gnuplot_show__"); - -// PKG_ADD: atexit ("closeplot"); - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#include -#endif - -#include "file-ops.h" -#include "oct-env.h" - -#include "defun-dld.h" -#include "file-io.h" -#include "gripes.h" -#include "load-save.h" -#include "parse.h" -#include "procstream.h" -#include "sighandlers.h" -#include "utils.h" -#include "variables.h" - -enum _toktype - { - START_PAREN = 1, - END_PAREN, - START_BRACE, - END_BRACE, - START_BRACKET, - END_BRACKET, - COLON, - SEMICOLON, - COMMA, - QUOTE, - IDENT, - NUMBER, - BINOP, - UNOP, - STRING, - OTHER, - TITLE, - USING, - WITH, - AXES, - CLEAR - }; - -typedef bool (*pred) (const int); - -class -gpt_parse_error -{ -public: - gpt_parse_error (void) : msg () { } - gpt_parse_error (std::string errmsg) : msg (errmsg) { } - - std::string msg; -}; - -static bool gpt_quote_is_transpose; -static bool gpt_allow_plotkw; -static int gpt_parens; -static int gpt_brackets; -static int gpt_braces; - -static bool can_be_plotkw (void); - -static int is_plot_keyword (const std::string& s); - -static int handle_string (char delim); -static std::string strbuf; - -%} - -D [0-9] -S [ \t] -IDENT ([_a-zA-Z@][_a-zA-Z0-9]*) -EXPON ([DdEe][+-]?{D}+) -NUMBER (({D}+\.?{D}*{EXPON}?)|(\.{D}+{EXPON}?)|(0[xX][0-9a-fA-F]+)) -NOT ((\~)|(\!)) -/* NOT is not strictly a binary operator, but is close enough for us. */ -BINOP (({NOT})|(\.?([\*/\\^+-]|\*\*)=?)|([<=~!>&|]=)|([=&|<>]{1,2})|(<<=)|(>>=)|(\.)) -/* single quote (') transpose operator is handled separately. */ -UNOP ((\+\+)|(\-\-)|(\.')) - -%% - -"(" { - gpt_quote_is_transpose = false; - gpt_parens++; - return START_PAREN; - } - -")" { - gpt_quote_is_transpose = true; - gpt_parens--; - return END_PAREN; - } - -"{" { - gpt_quote_is_transpose = false; - gpt_braces++; - return START_BRACE; - } - -"}" { - gpt_quote_is_transpose = true; - gpt_braces--; - return END_BRACE; - } - -"[" { - gpt_quote_is_transpose = false; - gpt_brackets++; - return START_BRACKET; - } - -"]" { - gpt_quote_is_transpose = true; - gpt_brackets--; - return END_BRACKET; - } - -":" { - gpt_quote_is_transpose = false; - return COLON; - } - -";" { - gpt_quote_is_transpose = false; - return SEMICOLON; - } - -"," { - gpt_quote_is_transpose = false; - return COMMA; - } - -"'" { - if (gpt_quote_is_transpose) - { - gpt_allow_plotkw = true; - return QUOTE; - } - else - { - gpt_quote_is_transpose = true; - gpt_allow_plotkw = true; - return handle_string ('\''); - } - } - -"\"" { - return handle_string ('"'); - } - -{IDENT} { - int itok = 0; - if (can_be_plotkw () && (itok = is_plot_keyword (yytext))) - { - gpt_quote_is_transpose = false; - gpt_allow_plotkw = true; - return itok; - } - else if (std::string (yytext) == "function") - throw gpt_parse_error ("function keyword not allowed in plot commands"); - else - { - gpt_quote_is_transpose = true; - gpt_allow_plotkw = true; - return IDENT; - } - } - -{D}+/\.[\*/\\^'] | /* ' */ -{NUMBER} { - gpt_quote_is_transpose = true; - gpt_allow_plotkw = true; - return NUMBER; - } - -{BINOP} { - gpt_quote_is_transpose = false; - gpt_allow_plotkw = false; - return BINOP; - } - -{UNOP} { - gpt_quote_is_transpose = false; - gpt_allow_plotkw = true; - return UNOP; - } - -{S} { /* Ignore spaces and tabs outside of character strings. */ } - -. { - gpt_quote_is_transpose = false; - gpt_allow_plotkw = true; - warning ("unknown token = \"%s\" in plot command", yytext); - return OTHER; - } - -%% - -// ------------------------------------------------------------ -// Interface to external gnuplot process(es), including gnuplot -// command parser. -// ------------------------------------------------------------ - -// The name of the shell command to execute to start gnuplot. -static std::string Vgnuplot_binary; - -// Append -title "Figure NN" to the gnuplot command? -static bool Vgnuplot_use_title_option = octave_env::have_x11_display (); - -// Gnuplot command strings that we use. -static std::string Vgnuplot_command_plot; -static std::string Vgnuplot_command_replot; -static std::string Vgnuplot_command_splot; -static std::string Vgnuplot_command_using; -static std::string Vgnuplot_command_with; -static std::string Vgnuplot_command_axes; -static std::string Vgnuplot_command_title; -static std::string Vgnuplot_command_end; - -// If TRUE, a replot command is issued automatically each time a plot -// changes in some way. -static bool Vautomatic_replot; - -// Check if the parser state is such that a plot keyword can occur. - -static bool -can_be_plotkw (void) -{ - return (gpt_allow_plotkw - && (gpt_braces == 0) - && (gpt_brackets == 0) - && (gpt_parens == 0)); -} - -// Check to see if a character string matches any one of the plot -// option keywords. Don't match abbreviations for clear, since that's -// not a gnuplot keyword (users will probably only expect to be able -// to abbreviate actual gnuplot keywords). - -static int -is_plot_keyword (const std::string& s) -{ - if (almost_match ("title", s, 1)) - return TITLE; - else if (almost_match ("using", s, 1)) - return USING; - else if (almost_match ("with", s, 1)) - return WITH; - else if (almost_match ("axes", s, 2) || almost_match ("axis", s, 2)) - return AXES; - else if ("clear" == s) - return CLEAR; - else - return 0; -} - -// This is used to handle character strings. Kludge alert. - -static int -handle_string (char delim) -{ - int c; - bool escape_pending = false; - - strbuf = std::string (1, delim); - - while ((c = yyinput ()) != EOF) - { - if (c == '\\') - { - if (escape_pending) - { - strbuf += static_cast (c); - escape_pending = false; - } - else - { - strbuf += static_cast (c); - escape_pending = true; - } - continue; - } - else if (c == '\n') - { - error ("unterminated string constant"); - break; - } - else if (c == delim) - { - if (escape_pending) - strbuf += static_cast (c); - else - { - c = yyinput (); - - if (c == delim) - { - strbuf += static_cast (c); - strbuf += static_cast (c); - } - else - { - yyunput (c, yytext); - strbuf += static_cast (delim); - return STRING; - } - } - } - else - strbuf += static_cast (c); - - escape_pending = false; - } - - throw gpt_parse_error ("unterminated string"); - - return 0; -} - -// (Probably not necessesary, but current Matlab style plot functions -// break without this (they emit too short gnuplot commands)) - -static std::string -plot_style_token (const std::string& s) -{ - std::string retval; - - // XXX FIXME XXX -- specify minimum match length for these. - static const char *plot_styles[] = - { - "boxes", - "boxerrorbars", - "boxxyerrorbars", - "candlesticks", - "dots", - "errorbars", - "financebars", - "fsteps", - "histeps", - "impulses", - "lines", - "linespoints", - "points", - "steps", - "vector", - "xerrorbars", - "xyerrorbars", - "yerrorbars", - 0, - }; - - const char * const *tmp = plot_styles; - while (*tmp) - { - if (almost_match (*tmp, s.c_str ())) - { - retval = *tmp; - break; - } - - tmp++; - } - - return retval; -} - -// Some predicates on tokens - -// Return true for ":". - -static bool -colonp (const int tok) -{ - return (tok == COLON); -} - -// Return TRUE for "]". - -static bool -endbracketp (const int tok) -{ - return (tok == END_BRACKET); -} - -// Return TRUE for plot token, comma or end of input. - -static bool -plottok_or_end_p (const int tok) -{ - return (tok == TITLE - || tok == USING - || tok == WITH - || tok == AXES - || tok == CLEAR - || tok == COMMA - || tok == 0); -} - -// Equivalent to (colonp (tok) || plottok_or_end_p (tok)). - -static bool -colon_plottok_or_end_p (const int tok) -{ - return (tok == COLON || plottok_or_end_p (tok)); -} - -// read until test is true and delimiters are balanced, or end of input. -// Return the last token in lasttok - -static std::string -read_until (pred test, int& lasttok) throw (gpt_parse_error) -{ - int tok; - - // We have to maintain balanced delimiters per subexpression too. - int brackets = 0; - int parens = 0; - int braces = 0; - std::string s; - - tok = gptlex (); - - while (tok && ! (test (tok) - && brackets == 0 - && parens == 0 - && braces == 0)) - { - switch (tok) - { - case START_BRACKET: - brackets++; - break; - - case END_BRACKET: - brackets--; - break; - - case START_PAREN: - parens++; - break; - - case END_PAREN: - parens--; - break; - - case START_BRACE: - braces++; - break; - - case END_BRACE: - braces--; - break; - - default: - break; - } - - s += (tok == STRING ? strbuf : std::string (yytext)) + " "; - - tok = gptlex (); - } - - // Throw error only if we've reached the end token and the test - // doesn't accept it. - - if (! test (tok) && ! tok) - throw gpt_parse_error ("unexpected end of input"); - - lasttok = tok; - - return s; -} - -// Eval the two expressions giving limits of range and print it. - -static std::string -printrange (std::string starts, std::string ends) -{ - octave_value startv, endv; - int status; - std::string s; - OSSTREAM range_buf; - - range_buf << "["; - - if (! starts.empty ()) - { - startv = eval_string (starts, true, status); - if (! startv.is_real_scalar ()) - throw gpt_parse_error (); - startv.print_raw (range_buf); - } - - range_buf << ":"; - - if (! ends.empty ()) - { - endv = eval_string (ends, true, status); - if (! endv.is_real_scalar ()) - throw gpt_parse_error (); - endv.print_raw (range_buf); - } - - range_buf << "]"; - range_buf << OSSTREAM_ENDS; - - s = OSSTREAM_STR (range_buf); - - return s; -} - -// Handle plot parameters. - -// Parse, evaluate and print colon separated expressions in the using -// plot parameter. The use of trailing format string is not supported. - -static std::string -handle_using (int& lasttok) -{ - int tok; - std::string expr_str; - std::string retstr = Vgnuplot_command_using + " "; - bool out = false; - - octave_value tmp_data; - int status; - while (! out) - { - expr_str = read_until (colon_plottok_or_end_p, tok); - - tmp_data = eval_string (expr_str, true, status); - if (status != 0 || ! tmp_data.is_real_scalar ()) - throw gpt_parse_error (); - - OSSTREAM tmp_buf; - tmp_data.print_raw (tmp_buf); - tmp_buf << OSSTREAM_ENDS; - retstr += OSSTREAM_STR (tmp_buf); - - if (tok == COLON) - retstr += ":"; - else - out = true; - } - - lasttok = tok; - - return retstr; -} - -// Presently just passes the linewidth, pointtype etc. tokens as they are. - -static std::string -handle_style (int& lasttok) -{ - std::string retstr = Vgnuplot_command_with + " "; - std::string style; - - lasttok = gptlex (); - - if (lasttok != IDENT) - throw gpt_parse_error ("expected plot style token"); - - style = std::string (yytext); - style = plot_style_token (style); - - if (! style.empty ()) - retstr += style; - else - retstr += std::string (yytext); - - // XXX FIXME XXX -- should evaluate the remaining tokens, but this - // needs changes in the parser. - retstr += " " + read_until (plottok_or_end_p, lasttok); - - return retstr; -} - -// Axes has only one qualifier keyword, which is not evaluated. - -static std::string -handle_axes (int& lasttok) -{ - return Vgnuplot_command_axes + " " + read_until (plottok_or_end_p, lasttok); -} - -static std::string -save_in_tmp_file (const octave_value& t, int ndim = 2, bool parametric = false) -{ - std::string name = file_ops::tempnam ("", "oct-"); - - if (! name.empty ()) - { - std::ofstream file (name.c_str ()); - - if (file) - { - switch (ndim) - { - case 2: - save_ascii_data_for_plotting (file, t, name); - break; - - case 3: - save_three_d (file, t, parametric); - break; - - default: - gripe_2_or_3_dim_plot (); - break; - } - } - else - { - error ("couldn't open temporary output file `%s'", name.c_str ()); - name.resize (0); - } - } - - return name; -} - -static int -get_current_figure (void) -{ - int retval = 1; - - octave_value cf = get_global_value ("__current_figure__", true); - - if (cf.is_defined ()) - retval = cf.int_value (); - else - set_global_value ("__current_figure__", retval); - - return retval; -} - -class -gnuplot -{ -protected: - - gnuplot (void) - : plot_line_count (0), parametric_plot (false), - use_title_option (Vgnuplot_use_title_option), - gnuplot_exe (Vgnuplot_binary), - gnuplot_terminal_type (), plot_stream () - { do_init (); } - -public: - - ~gnuplot (void) { } - - static bool have_instance (void); - - static bool ensure_instance (void); - - static bool ensure_plot_stream (void); - - static void open (void); - - static void close (void); - - static void close_all (void); - - static bool plot_stream_event_handler (pid_t pid, int status); - - static void send (const std::string& cmd) - { - if (ensure_plot_stream ()) - instance->do_send (cmd); - } - - static void send_raw (const std::string& cmd) - { - if (ensure_plot_stream ()) - instance->do_send_raw (cmd); - } - - static void clear (void) - { - if (ensure_plot_stream ()) - instance->do_clear (); - } - - static void set (const string_vector& argv) - { - if (ensure_plot_stream ()) - instance->do_set (argv); - } - - static void show (const string_vector& argv) - { - if (ensure_plot_stream ()) - instance->do_show (argv); - } - - static void set_gnuplot_exe (const std::string& exe) - { - if (ensure_instance ()) - instance->do_set_gnuplot_exe (exe); - } - - static void set_gnuplot_use_title_option (bool opt) - { - if (ensure_instance ()) - instance->do_set_gnuplot_use_title_option (opt); - } - - // XXX FIXME XXX -- should only remove tmp files associated with - // gnuplot? - static void cleanup_tmp_files (void) { ::cleanup_tmp_files (); } - - static void plot (const string_vector& argv) - { - if (ensure_plot_stream ()) - instance->do_plot (argv); - } - -private: - - static gnuplot *instance; - - static std::map instance_map; - - // The number of lines we've plotted so far. - int plot_line_count; - - // Is this a parametric plot? Makes a difference for 3D plotting. - bool parametric_plot; - - // Should we append '-title "TITLE"' to the gnuplot command? - bool use_title_option; - - // The executable program to run. - std::string gnuplot_exe; - - // The gnuplot terminal type. - std::string gnuplot_terminal_type; - - // Pipe to gnuplot. - oprocstream *plot_stream; - - pid_t pid (void) const; - - static gnuplot *lookup_by_pid (pid_t pid); - - void do_open (void); - - void do_close (void); - - void delete_plot_stream (void); - - void reset_plot_stream (void); - - void do_send (const std::string& cmd); - - void do_send_raw (const std::string& cmd); - - void do_clear (void); - - void do_set (const string_vector& argv); - - void do_show (const string_vector& argv); - - void do_set_gnuplot_exe (const std::string& exe) { gnuplot_exe = exe; } - - void do_set_gnuplot_use_title_option (bool opt) { use_title_option = opt; } - - void do_plot (const string_vector& argv); - - void do_init (void); - - std::string - makeplot (std::string caller, std::string args) throw (gpt_parse_error); - - std::string handle_title (int& lasttok); -}; - -gnuplot *gnuplot::instance = 0; - -std::map gnuplot::instance_map; - -bool -gnuplot::have_instance (void) -{ - int current_figure = get_current_figure (); - - if (instance_map.find (current_figure) != instance_map.end ()) - { - instance = instance_map[current_figure]; - return true; - } - else - return false; -} - -bool -gnuplot::ensure_instance (void) -{ - if (! have_instance ()) - { - instance = new gnuplot (); - - if (! instance) - { - ::error ("unable to create gnuplot object!"); - - return false; - } - else - instance_map[get_current_figure ()] = instance; - } - - return true; -} - -bool -gnuplot::ensure_plot_stream (void) -{ - if (ensure_instance ()) - { - instance->do_open (); - - if (error_state) - return false; - } - - return true; -} - -void -gnuplot::close (void) -{ - if (have_instance ()) - { - instance->do_close (); - - instance_map.erase (get_current_figure ()); - } -} - -void -gnuplot::close_all (void) -{ - for (std::map::const_iterator p = instance_map.begin (); - p != instance_map.end (); - p++) - { - gnuplot *elt = p->second; - - elt->do_close (); - } -} - -pid_t -gnuplot::pid (void) const -{ - return plot_stream ? plot_stream->pid () : -1; -} - -gnuplot * -gnuplot::lookup_by_pid (pid_t pid) -{ - gnuplot *retval = 0; - - for (std::map::const_iterator p = instance_map.begin (); - p != instance_map.end (); - p++) - { - gnuplot *elt = p->second; - - if (elt && elt->pid () == pid) - { - retval = elt; - break; - } - } - - return retval; -} - -void -gnuplot::do_open (void) -{ - static bool initialized = false; - - if (plot_stream && ! *plot_stream) - do_close (); - - if (! plot_stream) - { - initialized = false; - - plot_line_count = 0; - - std::string cmd; - - if (gnuplot_exe.empty ()) - cmd = "gnuplot"; - else - cmd = "\"" + gnuplot_exe + "\""; - - // XXX FIXME XXX -- I'm not sure this is the right thing to do, - // but without it, C-c at the octave prompt will kill gnuplot... - -#if defined (HAVE_POSIX_SIGNALS) - sigset_t nset, oset; - sigemptyset (&nset); - sigaddset (&nset, SIGINT); - sigprocmask (SIG_BLOCK, &nset, &oset); -#else - volatile octave_interrupt_handler old_interrupt_handler - = octave_ignore_interrupts (); -#endif - - if (use_title_option) - { - OSSTREAM buf; - - buf << cmd - << " -title \"Figure " << get_current_figure () << "\"" - << OSSTREAM_ENDS; - - cmd = OSSTREAM_STR (buf); - - OSSTREAM_FREEZE (buf); - } - - plot_stream = new oprocstream (cmd.c_str ()); - - if (plot_stream && *plot_stream) - octave_child_list::insert (plot_stream->pid (), - plot_stream_event_handler); - else - { - delete_plot_stream (); - - error ("plot: unable to open pipe to `%s'", cmd.c_str ()); - } - -#if defined (HAVE_POSIX_SIGNALS) - sigprocmask (SIG_SETMASK, &oset, 0); -#else - octave_set_interrupt_handler (old_interrupt_handler); -#endif - } - - if (! error_state && plot_stream && *plot_stream && ! initialized) - { - initialized = true; - - do_send_raw ("set style data lines\n"); - - if (! gnuplot_terminal_type.empty ()) - do_send_raw ("set term " + gnuplot_terminal_type - + Vgnuplot_command_end + "\n"); - } -} - -void -gnuplot::delete_plot_stream (void) -{ - do_send_raw ("\nquit\n"); - - delete plot_stream; - plot_stream = 0; -} - -void -gnuplot::reset_plot_stream (void) -{ - delete_plot_stream (); - - plot_line_count = 0; - parametric_plot = false; -} - -void -gnuplot::do_close (void) -{ - if (plot_stream) - { - octave_child_list::remove (plot_stream->pid ()); - - delete_plot_stream (); - } - - plot_line_count = 0; -} - -bool -gnuplot::plot_stream_event_handler (pid_t pid, int status) -{ - bool retval = false; - - if (pid > 0) - { - if (WIFEXITED (status) || WIFSIGNALLED (status)) - { - gnuplot *plotter = gnuplot::lookup_by_pid (pid); - - // We should only print a warning or request removal of the - // process from the child list if the process died - // unexpectedly. If do_close is responsible for - // gnuplot's death, then plotter will be 0 here and we don't - // need to do anything. - - if (plotter) - { - plotter->reset_plot_stream (); - - warning ("connection to external plotter (pid = %d) lost --", pid); - // Request removal of this PID from the list of child - // processes. - - retval = true; - } - } - } - - return retval; -} - -void -gnuplot::do_send (const std::string& cmd) -{ - int replot_len = Vgnuplot_command_replot.length (); - - bool is_replot = (Vgnuplot_command_replot == cmd.substr (0, replot_len)); - - if (! (plot_line_count == 0 && is_replot)) - do_send_raw (cmd); -} - -void -gnuplot::do_send_raw (const std::string& cmd) -{ - if (plot_stream && *plot_stream) - { - *plot_stream << cmd; - - plot_stream->flush (); - } -} - -void -gnuplot::do_clear (void) -{ - do_send_raw ("clear\n"); - - // XXX FIXME XXX -- instead of just clearing these things, it would - // be nice if we could reset things to a user-specified default - // state. - - do_send_raw ("set title\n"); - do_send_raw ("set xlabel\n"); - do_send_raw ("set ylabel\n"); - do_send_raw ("set nogrid\n"); - do_send_raw ("set nolabel\n"); - - // This makes a simple `replot' not work after a `clearplot' command - // has been issued. - - plot_line_count = 0; -} - -void -gnuplot::do_set (const string_vector& argv) -{ - int argc = argv.length (); - - OSSTREAM plot_buf; - - if (argc > 1) - { - if (almost_match ("parametric", argv[1], 3)) - parametric_plot = true; - else if (almost_match ("noparametric", argv[1], 5)) - parametric_plot = false; - else if (almost_match ("term", argv[1], 1)) - { - gnuplot_terminal_type = ""; - OSSTREAM buf; - int i; - for (i = 2; i < argc-1; i++) - buf << argv[i] << " "; - if (i < argc) - buf << argv[i]; - buf << Vgnuplot_command_end << OSSTREAM_ENDS; - gnuplot_terminal_type = OSSTREAM_STR (buf); - OSSTREAM_FREEZE (buf); - } - } - - int i; - for (i = 0; i < argc-1; i++) - plot_buf << argv[i] << " "; - - if (i < argc) - plot_buf << argv[i]; - - plot_buf << Vgnuplot_command_end << OSSTREAM_ENDS; - - do_send_raw (OSSTREAM_STR (plot_buf)); - - OSSTREAM_FREEZE (plot_buf); -} - -void -gnuplot::do_show (const string_vector& argv) -{ - int argc = argv.length (); - - OSSTREAM plot_buf; - - int i; - for (i = 0; i < argc-1; i++) - plot_buf << argv[i] << " "; - if (i < argc) - plot_buf << argv[i]; - - plot_buf << Vgnuplot_command_end << OSSTREAM_ENDS; - - do_send (OSSTREAM_STR (plot_buf)); - - OSSTREAM_FREEZE (plot_buf); -} - -void -gnuplot::do_plot (const string_vector& argv) -{ - std::string s; - - for (int i = 1; i < argv.length (); i++) - s += argv[i] + " "; - - try - { - std::string cmd = makeplot (argv[0], s); - - do_send (cmd); - } - catch (gpt_parse_error& e) - { - if (e.msg.empty ()) - error ("could not parse plot command"); - else - error (e.msg.c_str ()); - } -} - -// Parse and evaluate parameter string and pass it to gnuplot pipe. - -std::string -gnuplot::makeplot (std::string caller, std::string args) - throw (gpt_parse_error) -{ - std::string retval; - - YY_BUFFER_STATE bstate; - - bstate = yy_scan_string (args.c_str ()); - yy_switch_to_buffer (bstate); - std::string outstr; - int ndim = 2; - - if (caller == "replot") - { - ndim = 1; - outstr += Vgnuplot_command_replot + " "; - } - else if (caller == "plot") - { - ndim = 2; - plot_line_count = 0; - outstr += Vgnuplot_command_plot + " "; - } - else if (caller == "splot") - { - ndim = 3; - plot_line_count = 0; - outstr += Vgnuplot_command_splot + " "; - } - else - throw gpt_parse_error ("unknown plot command"); - - gpt_quote_is_transpose = false; - gpt_allow_plotkw = false; - gpt_parens = 0; - gpt_braces = 0; - gpt_brackets = 0; - - int tok; - tok = gptlex (); - if (plottok_or_end_p (tok) && caller != "replot") - throw gpt_parse_error ("must have something to plot"); - - while (tok) - { - bool title_set = false; - bool using_set = false; - bool style_set = false; - bool axes_set = false; - - if (tok == START_BRACKET) - { - if (caller == "replot") - throw gpt_parse_error ("can't specify new plot ranges with `replot' or while hold is on"); - - std::string xrange_start_str = read_until (colonp, tok); - std::string xrange_end_str = read_until (endbracketp, tok); - outstr += printrange (xrange_start_str, xrange_end_str) + " "; - tok = gptlex (); - if (tok == START_BRACKET) - { - std::string yrange_start_str = read_until (colonp, tok); - std::string yrange_end_str = read_until (endbracketp, tok); - outstr += printrange (yrange_start_str, yrange_end_str) + " "; - tok = gptlex (); - if (tok == START_BRACKET && caller == "gsplot") - { - std::string zrange_start_str = read_until (colonp, tok); - std::string zrange_end_str = read_until (endbracketp, tok); - outstr += printrange (zrange_start_str, zrange_end_str) + " "; - tok = gptlex (); - } - } - } - - if (plottok_or_end_p (tok)) - return std::string (); - else - { - std::string file; - plot_line_count++; - - std::string plot_expr_str; - plot_expr_str += std::string (yytext) + " "; - plot_expr_str += read_until (plottok_or_end_p, tok); - - int status = 0; - octave_value tmp_data = eval_string (plot_expr_str, - true, status); - - if (status != 0 || ! tmp_data.is_defined ()) - throw gpt_parse_error (); - - OSSTREAM tmp_buf; - tmp_data.print_raw (tmp_buf); - tmp_buf << OSSTREAM_ENDS; - - if (tmp_data.is_string ()) - { - file = file_ops::tilde_expand (tmp_data.string_value ()); - // XXX FIXME XXX -- perhaps should check if the file exists? - outstr += file + " "; - } - else - { - switch (ndim) - { - case 2: - file = save_in_tmp_file (tmp_data, ndim); - break; - - case 3: - file = save_in_tmp_file (tmp_data, ndim, - parametric_plot); - break; - - default: - gripe_2_or_3_dim_plot (); - break; - } - - if (file.length () > 0) - { - mark_for_deletion (file); - outstr += "'" + file + "' "; - } - } - } - - std::string title_str; - std::string using_str; - std::string style_str; - std::string axes_str; - - bool out = false; - while (tok && ! out) - { - switch (tok) - { - case COMMA: - out = true; - break; - - case TITLE: - if (! title_set) - title_str += handle_title (tok) + " "; - else - throw gpt_parse_error ("only one title option may be specified"); - title_set = true; - break; - - case USING: - if (! using_set) - using_str += handle_using (tok) + " "; - else - throw gpt_parse_error ("only one using option may be specified"); - using_set = true; - break; - - case WITH: - if (! style_set) - style_str += handle_style (tok) + " "; - else - throw gpt_parse_error ("only one style option may be specified"); - style_set = true; - break; - - case AXES: - if (! axes_set) - axes_str += handle_axes (tok) + " "; - else - throw gpt_parse_error ("only one axes option may be specified"); - axes_set = true; - break; - - default: - tok = 0; - break; - } - } - - if (! title_set) - { - OSSTREAM tmp_buf; - tmp_buf << Vgnuplot_command_title << " \"line " - << plot_line_count << "\" " << OSSTREAM_ENDS; - title_str = OSSTREAM_STR (tmp_buf); - title_set = true; - } - - // Plot parameters have to be output in this order. - if (using_set) - outstr += using_str; - - if (axes_set) - outstr += axes_str; - - if (title_set) - outstr += title_str; - - if (style_set) - outstr += style_str; - - if (out) - { - // Saw comma on while loop. - outstr += ", "; - gpt_quote_is_transpose = false; - gpt_allow_plotkw = false; - gpt_parens = 0; - gpt_braces = 0; - gpt_brackets = 0; - tok = gptlex (); - } - } - - outstr += Vgnuplot_command_end; - - return outstr; -} - -// Title has one string expression which is evaluated and printed to the -// gnuplot command string. - -std::string -gnuplot::handle_title (int& lasttok) -{ - int tok; - std::string retstr = Vgnuplot_command_title + " "; - std::string title_expr_str; - - title_expr_str += read_until (plottok_or_end_p, tok); - - int status; - octave_value tmp_data = eval_string (title_expr_str, true, status); - - if (status != 0 || ! tmp_data.is_defined ()) - throw gpt_parse_error (); - - OSSTREAM tmp_buf; - if (tmp_data.is_string ()) - { - tmp_buf << '"'; - tmp_data.print_raw (tmp_buf); - tmp_buf << '"' << OSSTREAM_ENDS; - } - else - { - warning ("line title must be a string"); - tmp_buf << '"' << "line " << plot_line_count << '"'; - } - - retstr += OSSTREAM_STR (tmp_buf); - - lasttok = tok; - - return retstr; -} - -// The static instance of this class is here so that -// gnuplot::close_all will be called when the .oct file is unloaded. - -class -gnuplot_X -{ -public: - gnuplot_X (void) { } - ~gnuplot_X (void) { gnuplot::close_all (); } -}; - -static gnuplot_X X; - -static int -automatic_replot (void) -{ - Vautomatic_replot = check_preference ("automatic_replot"); - - return 0; -} - -static int -set_string_var (std::string& var, const char *nm) -{ - int retval = 0; - - std::string s = builtin_string_variable (nm); - - if (s.empty ()) - { - gripe_invalid_value_specified (nm); - retval = -1; - } - else - var = s; - - return retval; -} - -static int -gnuplot_binary (void) -{ - int status = set_string_var (Vgnuplot_binary, "gnuplot_binary"); - - if (status == 0) - gnuplot::set_gnuplot_exe (Vgnuplot_binary); - - return status; -} - -static int -gnuplot_command_plot (void) -{ - return set_string_var (Vgnuplot_command_plot, "gnuplot_command_plot"); -} - -static int -gnuplot_command_replot (void) -{ - return set_string_var (Vgnuplot_command_replot, "gnuplot_command_replot"); -} - -static int -gnuplot_command_splot (void) -{ - return set_string_var (Vgnuplot_command_splot, "gnuplot_command_splot"); -} - -static int -gnuplot_command_using (void) -{ - return set_string_var (Vgnuplot_command_using, "gnuplot_command_using"); -} - -static int -gnuplot_command_with (void) -{ - return set_string_var (Vgnuplot_command_with, "gnuplot_command_with"); -} - -static int -gnuplot_command_axes (void) -{ - return set_string_var (Vgnuplot_command_axes, "gnuplot_command_axes"); -} - -static int -gnuplot_command_title (void) -{ - return set_string_var (Vgnuplot_command_title, "gnuplot_command_title"); -} - -static int -gnuplot_command_end (void) -{ - return set_string_var (Vgnuplot_command_end, "gnuplot_command_end"); -} - -static int -gnuplot_use_title_option (void) -{ - Vgnuplot_use_title_option = check_preference ("gnuplot_use_title_option"); - - gnuplot::set_gnuplot_use_title_option (Vgnuplot_use_title_option); - - return 0; -} - -void -gnuplot::do_init (void) -{ - static bool gnuplot_initialized = false; - - if (gnuplot_initialized) - return; - - gnuplot_initialized = true; - - if (is_builtin_variable ("automatic_replot")) - automatic_replot (); - else - DEFVAR (automatic_replot, true, automatic_replot, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} automatic_replot\n\ -You can tell Octave to redisplay the plot each time anything about it\n\ -changes by setting the value of the builtin variable\n\ -@code{automatic_replot} to a nonzero value. Although it is fairly\n\ -inefficient, especially for large plots, the default value is 1 for\n\ -compatibility with Matlab.\n\ -@end defvr"); - - if (is_builtin_variable ("gnuplot_binary")) - gnuplot_binary (); - else - DEFVAR (gnuplot_binary, GNUPLOT_BINARY, gnuplot_binary, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_binary\n\ -The name of the program invoked by the plot command. The default value\n\ -is @code{\"gnuplot\"}. @xref{Installation}.\n\ -@end defvr"); - - if (is_builtin_variable ("gnuplot_command_plot")) - gnuplot_command_plot (); - else - DEFVAR (gnuplot_command_plot, "pl", gnuplot_command_plot, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_plot\n\ -@end defvr"); - - if (is_builtin_variable ("gnuplot_command_replot")) - gnuplot_command_replot (); - else - DEFVAR (gnuplot_command_replot, "rep", gnuplot_command_replot, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_replot\n\ -@end defvr"); - - if (is_builtin_variable ("gnuplot_command_splot")) - gnuplot_command_splot (); - else - DEFVAR (gnuplot_command_splot, "sp", gnuplot_command_splot, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_splot\n\ -@end defvr"); - - if (is_builtin_variable ("gnuplot_command_using")) - gnuplot_command_using (); - else - DEFVAR (gnuplot_command_using, "u", gnuplot_command_using, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_using\n\ -@end defvr"); - - if (is_builtin_variable ("gnuplot_command_with")) - gnuplot_command_with (); - else - DEFVAR (gnuplot_command_with, "w", gnuplot_command_with, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_with\n\ -@end defvr"); - - if (is_builtin_variable ("gnuplot_command_axes")) - gnuplot_command_axes (); - else - DEFVAR (gnuplot_command_axes, "ax", gnuplot_command_axes, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_axes\n\ -@end defvr"); - - if (is_builtin_variable ("gnuplot_command_title")) - gnuplot_command_title (); - else - DEFVAR (gnuplot_command_title, "t", gnuplot_command_title, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_title\n\ -@end defvr"); - - if (is_builtin_variable ("gnuplot_command_end")) - gnuplot_command_end (); - else - DEFVAR (gnuplot_command_end, "\n", gnuplot_command_end, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_end\n\ -@end defvr"); - - if (is_builtin_variable ("gnuplot_use_title_option")) - gnuplot_use_title_option (); - else - DEFVAR (gnuplot_use_title_option, octave_env::have_x11_display (), - gnuplot_use_title_option, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_use_title_option\n\ -If nonzero, append @samp{-title \"Figure NN\"} to the gnuplot command.\n\ -@end defvr"); - -} - -// ----------------------- -// User-callable functions -// ----------------------- - -DEFUN_DLD (clearplot, , , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} clearplot\n\ -@deftypefnx {Built-in Function} {} clg\n\ -Clear the plot window and any titles or axis labels. The name\n\ -@code{clg} is aliased to @code{clearplot} for compatibility with\n\ -@sc{Matlab}.\n\ -@end deftypefn") -{ - gnuplot::clear (); - - octave_value_list args; - - args(0) = "off"; - - feval ("hold", args); - - return octave_value_list (); -} - -DEFUN_DLD (closeplot, , , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} closeplot\n\ -Close stream to the @code{gnuplot} subprocess. If you are using X11,\n\ -this will close the plot window.\n\ -@end deftypefn") -{ - gnuplot::close (); - - return octave_value_list (); -} - -DEFUN_DLD (purge_tmp_files, , , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} purge_tmp_files\n\ -Delete the temporary files created by the plotting commands.\n\ -\n\ -Octave creates temporary data files for @code{gnuplot} and then sends\n\ -commands to @code{gnuplot} through a pipe. Octave will delete the\n\ -temporary files on exit, but if you are doing a lot of plotting you may\n\ -want to clean up in the middle of a session.\n\ -\n\ -A future version of Octave will eliminate the need to use temporary\n\ -files to hold the plot data.\n\ -@end deftypefn") -{ - gnuplot::cleanup_tmp_files (); - - return octave_value_list (); -} - -DEFUN_DLD (__gnuplot_raw__, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} __gnuplot_raw__ (@var{string})\n\ -Send @var{string} directly to gnuplot subprocess.\n\ -@end deftypefn") -{ - if (args.length () == 1 && args(0).is_string ()) - { - std::string cmd = args(0).string_value (); - - gnuplot::send_raw (cmd); - } - else - print_usage ("__gnuplot_raw__"); - - return octave_value_list (); -} - -DEFUN_DLD (__gnuplot_set__, args, , - "-*- texinfo -*-\n\ -@deffn {Command} __gnuplot_set__ options\n\ -Set plotting options for gnuplot\n\ -@end deffn") -{ - string_vector argv = args.make_argv ("set"); - - if (! error_state) - gnuplot::set (argv); - - return octave_value_list (); -} - -DEFUN_DLD (__gnuplot_show__, args, , - "-*- texinfo -*-\n\ -@deffn {Command} __gnuplot_show__ options\n\ -Show plotting options.\n\ -@end deffn") -{ - string_vector argv = args.make_argv ("show"); - - if (! error_state) - gnuplot::show (argv); - - return octave_value_list (); -} - -DEFUN_DLD (__gnuplot_plot__, args, , - "Plot with gnuplot.\n") -{ - string_vector argv = args.make_argv ("plot"); - - if (! error_state) - gnuplot::plot (argv); - - return octave_value_list (); -} - -DEFUN_DLD (__gnuplot_splot__, args, , - "Plot with gnuplot.\n") -{ - string_vector argv = args.make_argv ("splot"); - - if (! error_state) - gnuplot::plot (argv); - - return octave_value_list (); -} - -DEFUN_DLD (__gnuplot_replot__, args, , - "Plot with gnuplot.\n") -{ - string_vector argv = args.make_argv ("replot"); - - if (! error_state) - gnuplot::plot (argv); - - return octave_value_list (); -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/ diff --git a/src/__gnuplot_raw__.l b/src/__gnuplot_raw__.l --- a/src/__gnuplot_raw__.l +++ b/src/__gnuplot_raw__.l @@ -53,7 +53,7 @@ #include "file-ops.h" #include "oct-env.h" -#include "defun-dld.h" +#include "defun.h" #include "file-io.h" #include "gripes.h" #include "load-save.h" @@ -1572,6 +1572,12 @@ void gnuplot::do_init (void) { + // Do nothing. +} + +void +symbols_of___gnuplot_raw__ (void) +{ static bool gnuplot_initialized = false; if (gnuplot_initialized) @@ -1682,7 +1688,7 @@ // User-callable functions // ----------------------- -DEFUN_DLD (clearplot, , , +DEFUN (clearplot, , , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} clearplot\n\ @deftypefnx {Built-in Function} {} clg\n\ @@ -1702,7 +1708,7 @@ return octave_value_list (); } -DEFUN_DLD (closeplot, , , +DEFUN (closeplot, , , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} closeplot\n\ Close stream to the @code{gnuplot} subprocess. If you are using X11,\n\ @@ -1714,7 +1720,7 @@ return octave_value_list (); } -DEFUN_DLD (purge_tmp_files, , , +DEFUN (purge_tmp_files, , , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} purge_tmp_files\n\ Delete the temporary files created by the plotting commands.\n\ @@ -1733,7 +1739,7 @@ return octave_value_list (); } -DEFUN_DLD (__gnuplot_raw__, args, , +DEFUN (__gnuplot_raw__, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} __gnuplot_raw__ (@var{string})\n\ Send @var{string} directly to gnuplot subprocess.\n\ @@ -1751,7 +1757,7 @@ return octave_value_list (); } -DEFUN_DLD (__gnuplot_set__, args, , +DEFUN (__gnuplot_set__, args, , "-*- texinfo -*-\n\ @deffn {Command} __gnuplot_set__ options\n\ Set plotting options for gnuplot\n\ @@ -1765,7 +1771,7 @@ return octave_value_list (); } -DEFUN_DLD (__gnuplot_show__, args, , +DEFUN (__gnuplot_show__, args, , "-*- texinfo -*-\n\ @deffn {Command} __gnuplot_show__ options\n\ Show plotting options.\n\ @@ -1779,7 +1785,7 @@ return octave_value_list (); } -DEFUN_DLD (__gnuplot_plot__, args, , +DEFUN (__gnuplot_plot__, args, , "Plot with gnuplot.\n") { string_vector argv = args.make_argv ("plot"); @@ -1790,7 +1796,7 @@ return octave_value_list (); } -DEFUN_DLD (__gnuplot_splot__, args, , +DEFUN (__gnuplot_splot__, args, , "Plot with gnuplot.\n") { string_vector argv = args.make_argv ("splot"); @@ -1801,7 +1807,7 @@ return octave_value_list (); } -DEFUN_DLD (__gnuplot_replot__, args, , +DEFUN (__gnuplot_replot__, args, , "Plot with gnuplot.\n") { string_vector argv = args.make_argv ("replot");