Mercurial > hg > octave-lyh
changeset 6171:4508e9d73ea1
[project @ 2006-11-15 20:03:18 by jwe]
author | jwe |
---|---|
date | Wed, 15 Nov 2006 20:03:18 +0000 |
parents | 033b9fd8012a |
children | 2de853a110df |
files | src/ChangeLog src/DLD-FUNCTIONS/__gnuplot_raw__.l src/__gnuplot_raw__.l src/ls-oct-ascii.cc |
diffstat | 4 files changed, 149 insertions(+), 1838 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,17 @@ +2006-11-15 John W. Eaton <jwe@octave.org> + + * DLD-FUNCTIONS/__gnuplot_raw__.l (write_data, write_inline_data): + New functions. + (save_in_tmp_file): Use write_data. + (gnuplot::send_inline_data, gnuplot_do_send_inline_data): + New functions. + (F__gnuplot_send_inline_data__, F__gnuplot_save_data__): + New functions. + + * ls-oct-ascii.cc (save_ascii_data_for_plotting): + Call save_ascii_data with precision = 4. + (save_three_d): Temporarily set precision to 4 for output stream. + 2006-11-15 Michael Goffioul <michael.goffioul@swing.be> * Cell.h (Cell): Tag class with OCTINTERP_API.
--- a/src/DLD-FUNCTIONS/__gnuplot_raw__.l +++ b/src/DLD-FUNCTIONS/__gnuplot_raw__.l @@ -643,8 +643,38 @@ return Vgnuplot_command_axes + " " + read_until (plottok_or_end_p, lasttok); } +static void +write_data (std::ostream& os, const octave_value& val, + int ndim = 2, bool parametric = false, + const std::string& name = std::string ()) +{ + switch (ndim) + { + case 2: + save_ascii_data_for_plotting (os, val, name); + break; + + case 3: + save_three_d (os, val, parametric); + break; + + default: + gripe_2_or_3_dim_plot (); + break; + } +} + +static void +write_inline_data (std::ostream& os, const octave_value& val, + int ndim = 2, bool parametric = false) +{ + write_data (os, val, ndim, parametric); + os << "e" << std::endl; +} + static std::string -save_in_tmp_file (const octave_value& t, int ndim = 2, bool parametric = false) +save_in_tmp_file (const octave_value& val, int ndim = 2, + bool parametric = false) { std::string name = file_ops::tempnam ("", "oct-"); @@ -653,22 +683,7 @@ 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; - } - } + write_data (file, val, ndim, parametric, name); else { error ("couldn't open temporary output file `%s'", name.c_str ()); @@ -679,6 +694,46 @@ return name; } +DEFUN_DLD (__gnuplot_save_data__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} __gnuplot_save_data__ (@var{data}, @var{ndim}, @var{parametric})\n\ +@end deftypefn") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin > 0 && nargin < 4) + { + int ndim = 2; + bool parametric = false; + + if (nargin > 1) + { + ndim = args(1).int_value (); + + if (! error_state) + { + if (nargin > 2) + parametric = args(2).bool_value (); + } + } + + if (! error_state) + { + std::string file = save_in_tmp_file (args(0), ndim, parametric); + + mark_for_deletion (file); + + retval = file; + } + } + else + print_usage (); + + return retval; +} + static int get_current_figure (void) { @@ -735,6 +790,13 @@ instance->do_send_raw (cmd); } + static void send_inline_data (const octave_value& val, int ndim, + bool parametric) + { + if (ensure_plot_stream ()) + instance->do_send_inline_data (val, ndim, parametric); + } + static void clear (void) { if (ensure_plot_stream ()) @@ -815,6 +877,9 @@ void do_send_raw (const std::string& cmd); + void do_send_inline_data (const octave_value& val, int ndim, + bool parametric); + void do_clear (void); void do_set (const string_vector& argv); @@ -1097,6 +1162,18 @@ } void +gnuplot::do_send_inline_data (const octave_value& val, int ndim, + bool parametric) +{ + if (plot_stream && *plot_stream) + { + write_inline_data (*plot_stream, val, ndim, parametric); + + plot_stream->flush (); + } +} + +void gnuplot::do_clear (void) { do_send_raw ("clear\n"); @@ -1648,6 +1725,41 @@ return octave_value_list (); } +DEFUN_DLD (__gnuplot_send_inline_data__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} __gnuplot_send_inline_data__ (@var{string})\n\ +Send @var{val} to gnuplot subprocess as inline data.\n\ +@end deftypefn") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin > 0 && nargin < 4) + { + int ndim = 2; + bool parametric = false; + + if (nargin > 1) + { + ndim = args(1).int_value (); + + if (! error_state) + { + if (nargin > 2) + parametric = args(2).bool_value (); + } + } + + if (! error_state) + gnuplot::send_inline_data (args(0), ndim, parametric); + } + else + print_usage (); + + return retval; +} + DEFUN_DLD (__gnuplot_set__, args, , "-*- texinfo -*-\n\ @deffn {Loadable Function} __gnuplot_set__ options\n\
deleted file mode 100644 --- a/src/__gnuplot_raw__.l +++ /dev/null @@ -1,1820 +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 <config.h> -#endif - -#include <map> -#include <string> -#include <fstream> -#include <iostream> -#include <sstream> - -#ifdef HAVE_UNISTD_H -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#include <unistd.h> -#endif - -#include "file-ops.h" -#include "oct-env.h" - -#include "defun.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<char> (c); - escape_pending = false; - } - else - { - strbuf += static_cast<char> (c); - escape_pending = true; - } - continue; - } - else if (c == '\n') - { - error ("unterminated string constant"); - break; - } - else if (c == delim) - { - if (escape_pending) - strbuf += static_cast<char> (c); - else - { - c = yyinput (); - - if (c == delim) - { - strbuf += static_cast<char> (c); - strbuf += static_cast<char> (c); - } - else - { - yyunput (c, yytext); - strbuf += static_cast<char> (delim); - return STRING; - } - } - } - else - strbuf += static_cast<char> (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; - - // FIXME -- 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; - std::ostringstream 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 << "]"; - - s = range_buf.str (); - - 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 (); - - std::ostringstream tmp_buf; - tmp_data.print_raw (tmp_buf); - retstr += tmp_buf.str (); - - 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); - - // FIXME -- 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); - } - - // FIXME -- 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<int, gnuplot *> 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<int, gnuplot *> 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<int, gnuplot *>::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<int, gnuplot *>::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 + "\""; - - // FIXME -- 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) - { - std::ostringstream buf; - - buf << cmd << " -title \"Figure " << get_current_figure () << "\""; - - cmd = buf.str (); - } - - 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"); - - // FIXME -- 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 (); - - std::ostringstream 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 = ""; - std::ostringstream buf; - int i; - for (i = 2; i < argc-1; i++) - buf << argv[i] << " "; - if (i < argc) - buf << argv[i]; - buf << Vgnuplot_command_end; - gnuplot_terminal_type = buf.str (); - } - } - - 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; - - do_send_raw (plot_buf.str ()); -} - -void -gnuplot::do_show (const string_vector& argv) -{ - int argc = argv.length (); - - std::ostringstream 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; - - do_send (plot_buf.str ()); -} - -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 (); - - std::ostringstream tmp_buf; - tmp_data.print_raw (tmp_buf); - - if (tmp_data.is_string ()) - { - file = file_ops::tilde_expand (tmp_data.string_value ()); - // FIXME -- 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) - { - std::ostringstream tmp_buf; - tmp_buf << Vgnuplot_command_title << " \"line " - << plot_line_count << "\" "; - title_str = tmp_buf.str (); - 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 (); - - std::ostringstream tmp_buf; - if (tmp_data.is_string ()) - { - tmp_buf << '"'; - tmp_data.print_raw (tmp_buf); - tmp_buf << '"'; - } - else - { - warning ("line title must be a string"); - tmp_buf << '"' << "line " << plot_line_count << '"'; - } - - retstr += tmp_buf.str (); - - 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) -{ - // Do nothing. -} - -void -symbols_of___gnuplot_raw__ (void) -{ - static bool gnuplot_initialized = false; - - if (gnuplot_initialized) - return; - - gnuplot_initialized = true; - - // This is temporary. - mark_as_rawcommand ("__gnuplot_plot__"); - mark_as_rawcommand ("__gnuplot_set__"); - mark_as_rawcommand ("__gnuplot_splot__"); - mark_as_rawcommand ("__gnuplot_replot__"); - - 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 (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 (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 (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 (__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 (); - - return octave_value_list (); -} - -DEFUN (__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 (); -} - -DEFCMD (__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 (__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 (__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 (__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: *** -*/
--- a/src/ls-oct-ascii.cc +++ b/src/ls-oct-ascii.cc @@ -350,7 +350,7 @@ { bool infnan_warned = true; - return save_ascii_data (os, t, name, infnan_warned, false, 0); + return save_ascii_data (os, t, name, infnan_warned, false, 4); } // Maybe this should be a static function in tree-plot.cc? @@ -374,6 +374,9 @@ << "# total rows: " << nr << "\n" << "# total columns: " << nc << "\n"; + long old_precision = os.precision (); + os.precision (4); + if (parametric) { octave_idx_type extras = nc % 3; @@ -402,6 +405,8 @@ os << "\n"; } } + + os.precision (old_precision); } else {