# HG changeset patch # User jwe # Date 1134500755 0 # Node ID 7e008607a86ee68e1292547945414717c8a459bd # Parent 9b4d9dbe88f7a19ee052e6099e917dc642c3ff49 [project @ 2005-12-13 19:05:54 by jwe] diff --git a/doc/ChangeLog b/doc/ChangeLog --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2005-12-13 David Bateman + + * interpreter/sparse.txi: Add new gplot, etreeplot and treeplot + functions. + 2005-11-01 John W. Eaton * liboctave/Makefile.in (maintainer-clean): Also remove liboctave.pdf diff --git a/doc/interpreter/sparse.txi b/doc/interpreter/sparse.txi --- a/doc/interpreter/sparse.txi +++ b/doc/interpreter/sparse.txi @@ -890,13 +890,14 @@ @item etree Returns the elimination tree for the matrix S. @item etreeplot -@emph{Not implemented} +Plots the elimination tree of the matrix @var{s} or @code{@var{s}+@var{s}'} +if @var{s} in non-symmetric. @item gplot -@emph{Not implemented} +Plots a graph defined by @var{A} and @var{xy} in the graph theory sense. @item treelayout @emph{Not implemented} @item treeplot -@emph{Not implemented} +Produces a graph of a tree or forest. @end table @subsubsection Sparse matrix reordering @table @asis @@ -1020,8 +1021,12 @@ * dmperm:: Perfrom a Deulmage-Mendelsohn permutation on the sparse matrix S. * etree:: Returns the elimination tree for the matrix S. +* etreeplot:: Plots the elimination tree of the matrix @var{s} or + @code{@var{s}+@var{s}'} if @var{s} in non-symmetric. * full:: returns a full storage matrix from a sparse one See also: sparse +* gplot:: Plots a graph defined by @var{A} and @var{xy} in the graph + theory sense. * issparse:: Return 1 if the value of the expression EXPR is a sparse matrix. * luinc:: Produce the incomplete LU factorization of the sparse @@ -1084,6 +1089,7 @@ matrix S. * symrcm:: Returns the Reverse Cuthill McKee reordering of the sparse matrix S. +* treeplot:: Produces a graph of a tree or forest. @end menu @node colamd, ccolamd, , Function Reference @@ -1111,17 +1117,27 @@ @DOCSTRING(dmperm) -@node etree, full, dmperm, Function Reference +@node etree, etreeplot, dmperm, Function Reference @subsubsection etree @DOCSTRING(etree) -@node full, issparse, etree, Function Reference +@node etreeplot, full, etree, Function Reference +@subsubsection etreeplot + +@DOCSTRING(etreeplot) + +@node full, gplot, etreeplot, Function Reference @subsubsection full @DOCSTRING(full) -@node issparse, luinc, full, Function Reference +@node gplot, issparse, full, Function Reference +@subsubsection gplot + +@DOCSTRING(gplot) + +@node issparse, luinc, gplot, Function Reference @subsubsection issparse @DOCSTRING(issparse) @@ -1311,11 +1327,16 @@ @DOCSTRING(symbfact) -@node symrcm, , symbfact, Function Reference +@node symrcm, treeplot, symbfact, Function Reference @subsubsection symrcm @DOCSTRING(symrcm) +@node treeplot, ,symrcm, Function Reference +@subsubsection treeplot + +@DOCSTRING(treeplot) + @c Local Variables: *** @c Mode: texinfo *** @c End: *** diff --git a/scripts/ChangeLog b/scripts/ChangeLog --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,8 @@ +2005-12-13 Ivana Varekova + + * sparse/treeplot.m, sparse/etreeplot.m, sparse/gplot.m: + New graph theory functions. + 2005-12-13 John W. Eaton * general/blkdiag.m: Use "isempty" instead of @isempty. diff --git a/scripts/sparse/etreeplot.m b/scripts/sparse/etreeplot.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/etreeplot.m @@ -0,0 +1,29 @@ +## Copyright (C) 2005 Ivana Varekova +## +## This program 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 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +## 02110-1301 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {} etreeplot (@var{Tree}) +## @deftypefnx {Function File} {} etreeplot (@var{Tree}, @var{NodeStyle}, @var{EdgeStyle}) +## Plots the elimination tree of the matrix @var{s} or @code{@var{s}+@var{s}'} +## if @var{s} in non-symmetric. The optional parameters @var{LineStyle} and +## @var{EdgeStyle} define the output style. +## @end deftypefn +## @seealso{treeplot,gplot} + +function etreeplot (s, varargin) + treeplot (etree (s+s'), varargin{:}) +endfunction diff --git a/scripts/sparse/gplot.m b/scripts/sparse/gplot.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/gplot.m @@ -0,0 +1,54 @@ +## Copyright (C) 2005 Ivana Varekova +## +## This program 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 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +## 02110-1301 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {} gplot (@var{a}, @var{xy}) +## @deftypefnx {Function File} {} gplot (@var{a}, @var{xy}, @var{LineSpec}) +## @deftypefnx {Function File} {[@var{x}, @var{y}] =} gplot (@var{a}, @var{xy}) +## Plots a graph defined by @var{A} and @var{xy} in the graph theory sense. +## @var{A} is the adjacency matrix of the array to be plotted and @var{xy} is a +## @var{n}-by-2 matrix containing the coordinates of the nodes of the graph. +## +## If defined, @var{LineStyle} defines the output style for the plot. Called +## with no output arguments the graph is plotted directly. Called with output +## arguments the coordinates of the plot are returned in @var{x} and @var{y}, +## rather than being plotted. +## @end deftypefn +## @seealso{treeplot,etreeplot,spy} + +function [x, y] = gplot (A, xy, LineStyle) + + if (nargin < 2 || nargin > 3 || nargout > 2) + error ("gplot: wrong number of input/output arguments"); + endif + + if (nargin == 2) + LineStyle = "1;;"; + endif + + [i,j] = find(A); + xcoord = [xy(i,1), xy(j,1), NaN * ones(length(i),1)]'(:); + ycoord = [xy(i,2), xy(j,2), NaN * ones(length(i),1)]'(:); + + if (nargout == 0) + plot(xcoord,ycoord,LineStyle); + else + x = xcoord; + y = ycoord; + endif + +endfunction diff --git a/scripts/sparse/treeplot.m b/scripts/sparse/treeplot.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/treeplot.m @@ -0,0 +1,165 @@ +## Copyright (C) 2005 Ivana Varekova +## +## This program 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 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +## 02110-1301 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {} treeplot (@var{Tree}) +## @deftypefnx {Function File} {} treeplot (@var{Tree}, @var{LineStyle}, @var{EdgeStyle}) +## Produces a graph of tree or forest. The first argument is vector of +## predecessors, optional parametres @var{LineStyle} and @var{EdgeStyle} +## define the output style. The complexity of the algorithm is O(n) in +## terms of is time and memory requirements. +## @end deftypefn +## @seealso{etreeplot,gplot} + +function treeplot (Tree, NodeS, EdgeS) + + if (nargin < 1 || nargin > 3 || nargout > 0) + error ("treeplot: wrong number of input/output arguments"); + else + if (!ismatrix(Tree) || size(Tree)(1) != 1 || !isnumeric(Tree) + || !isvector(Tree) || any(Tree>length (Tree))) + error ("treeplot: the first input argument must be a vector of predecessors"); + else + + NodeStyle = "0*;;"; ## the inicialization of node end edge style + EdgeStyle = "1;;"; + if (nargin > 2) + EdgeStyle = EdgeS; + if (nargin > 1) + if ((length(findstr(NodeS,"*")) == 0) + && (length(findstr(NodeS,"+")) == 0) + && (length(findstr(NodeS,"x")) == 0) ) + NodeStyle = [NodeS,"o"]; + else + NodeStyle = NodeS; + endif + endif + endif + + Tree = Tree(:)'; ## make it a row vector + NodNumber = length (Tree); ## the count of nodes of the graph + ChildNumber = zeros (1,NodNumber+1); ## the number of childrens + + for i = 1:(NodNumber) ## VecOfChild is helping vector which is used to speed up the + ## choose of descendant nodes + + ChildNumber(Tree(i)+1) = ChildNumber(Tree(i)+1) + 1; + endfor + Pos = 1; + for i = 1:(NodNumber+1) + Start(i) = Pos; + Help(i) = Pos; + Pos = Pos + ChildNumber(i); + Stop(i) = Pos; + endfor + for i = 1:NodNumber + VecOfChild(Help(Tree(i)+1)) = i; + Help(Tree(i)+1)=Help(Tree(i)+1)+1; + endfor ## VecOfChild is helping vector which is used to speed up the + ## choose of descendant nodes + + ParNumber = 0; ## the number of "parent" (actual) node (it's descendants will + ## be browse in the next iteration) + LeftMost = 0; ## the x-coordinate of the left most descendant of "parent node" + ## this value is increased in each leaf + Level = NodNumber; ## the level of "parent" node (root level is NodNumber) + Max = NodNumber; ## NodNumber - Max is the height of this graph + St = [-1,0]; ## main stack - each item consists of two numbers - the number of node and + ## the number it's of parent node + ## on the top of stack there is "parent node" + Skelet = 0; ## stack which is use to draw the graph edge (it + ## have to be uninterupted line) + while (ParNumber!=-1) ## the top of the stack + if (Start(ParNumber+1) < Stop(ParNumber+1)) + idx = VecOfChild(Start(ParNumber+1):Stop(ParNumber+1)-1); + else + idx = zeros(1,0); + endif ## add to idx the vector of parent descendants + St = [St ; [idx', ones(fliplr(size(idx)))*ParNumber]]; + ## add to stack the records relevant to parent descandant s + if (ParNumber != 0) + Skelet = [Skelet ; ([ones(size(idx))*ParNumber; idx])(:)]; + endif + if (St(end,2) != ParNumber) ## if there is not any descendant of "parent node": + LeftMost = LeftMost + 1; + XCoordinateR(ParNumber) = LeftMost; + Max = min (Max, Level); + if ((length(St)>1) && (find((shift(St,1)-St) == 0) >1) && St(end,2) != St(end-1,2)) + ## return to the nearest branching + Position = (find((shift(St(:,2),1)-St(:,2)) == 0))(end)+1; ## the position to return + ## position is the position on the stack, where should be started + ## further search (there are two nodes which has the same parent node) + ParNumberVec = St(Position:end,2); + ## the vector of removed nodes (the content of stack form position to end) + Skelet = [Skelet; flipud(ParNumberVec)]; + Level = Level + length(ParNumberVec); + ## the level have to be decreased + XCoordinateR(ParNumberVec) = LeftMost; + St(Position:end,:) = []; + endif + St(end,:) = []; ## remove the next node from "searched branch" + ParNumber = St(end,1); ## choose new "parent node" + if (ParNumber != -1) ## if there is another branch start to search it + Skelet = [Skelet ; St(end,2); ParNumber]; + YCoordinate(ParNumber) = Level; + XCoordinateL(ParNumber) = LeftMost + 1; + endif + else ## there were descendants of "parent nod" + Level = Level - 1; ## choose the last of them and go on through it + ParNumber = St(end,1); + YCoordinate(ParNumber) = Level; + XCoordinateL(ParNumber) = LeftMost+1; + endif + endwhile + + XCoordinate = (XCoordinateL + XCoordinateR) / 2; ## calculate the x coordinates + ## (the known values are the position of most left and most right descendants) + + axis ([0.5 LeftMost+0.5 Max-0.5 NodNumber-0.5], "nolabel"); ## set axis and graph size + + plot (XCoordinate,YCoordinate,NodeStyle); ## plot grah nodes + hold on; + + Skelet = [Skelet; 0]; ## helping command - usable for plotting edges + + idx = find (Skelet == 0); ## draw graph edges + + for i = 2:length(idx) ## plot each tree component in one loop + istart = idx(i-1) + 1; ## tree component start + istop = idx(i) - 1; ## tree component end + if (istop - istart < 1) + continue; + endif + plot (XCoordinate(Skelet(istart:istop)), + YCoordinate(Skelet(istart:istop)), EdgeStyle) + endfor + + hold off; + + endif + endif + St; + Skelet; +endfunction + +%!demo +%! % Plot a simple tree plot +%! treeplot([2 4 2 0 6 4 6]) + +%!demo +%! % Plot a simple tree plot defining the edge and node styles +%! treeplot([2 4 2 0 6 4 6], "b+", "g") diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2005-12-13 David Bateman + + * Makefile.in: Change references to gplot.l to __gnuplot_raw__.l. + * DLD-FUNCTIONS/__gnuplot_raw__.l: Rename from DLD-FUNCTIONS/gplot.l. + Remove all references to deprecated gplot, gsplot, graw, gset and + gshow functions. + * help.cc (static help_list keywords[]): Remove gsplot and gplot. + + * ls-oct-ascii.cc (save_three_d): Don't strip Inf or NaN. + (save_ascii_data_for_plotting): Ditto. + 2005-12-13 John W. Eaton * oct-stream.cc (octave_stream_list::do_insert): Check open state diff --git a/src/DLD-FUNCTIONS/__gnuplot_raw__.l b/src/DLD-FUNCTIONS/__gnuplot_raw__.l new file mode 100644 --- /dev/null +++ b/src/DLD-FUNCTIONS/__gnuplot_raw__.l @@ -0,0 +1,1803 @@ +/* + +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: __gnuplot_init__ (); + +// 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 () + { } + +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 bool plot_stream_event_handler (pid_t pid, int status); + + static void init (void) + { + if (ensure_instance ()) + instance->do_init (); + } + + 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 ()); + } +} + +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; +} + +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 (__gnuplot_init__, , , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} __gnuplot_init__ ()\n\ +@end deftypefn") +{ + gnuplot::init (); + + return octave_value_list (); +} + +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 (); + + 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/DLD-FUNCTIONS/gplot.l b/src/DLD-FUNCTIONS/gplot.l deleted file mode 100644 --- a/src/DLD-FUNCTIONS/gplot.l +++ /dev/null @@ -1,1871 +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_rawcommand ("gplot"); -// PKG_ADD: mark_as_rawcommand ("gset"); -// PKG_ADD: mark_as_rawcommand ("gsplot"); - -// PKG_ADD: mark_as_command ("__gnuplot_show__"); - -// PKG_ADD: mark_as_command ("gshow"); - -// PKG_ADD: mark_as_command ("set"); -// PKG_ADD: mark_as_command ("show"); - -// PKG_ADD: __gnuplot_init__ (); - -// 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 () - { } - -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 bool plot_stream_event_handler (pid_t pid, int status); - - static void init (void) - { - if (ensure_instance ()) - instance->do_init (); - } - - 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 ()); - } -} - -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; -} - -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 (__gnuplot_init__, , , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} __gnuplot_init__ ()\n\ -@end deftypefn") -{ - gnuplot::init (); - - return octave_value_list (); -} - -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 (); - - 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 (); -} - -// -------------------- -// Deprecated functions -// -------------------- - -#define WARN_DEPRECATED(FOLD, FNEW) \ - do \ - { \ - static bool warned = false; \ - if (! warned) \ - { \ - warned = true; \ - warning (#FOLD " is deprecated and will be removed from a future"); \ - warning ("version of Octave."); \ - warning ("You should use the higher-level plot functions"); \ - warning ("(\"plot\", \"mesh\", \"semilogx\", etc.) instead"); \ - warning ("of the low-level plotting commands."); \ - warning ("If you absolutely must use this function, use the"); \ - warning ("internal version " #FNEW " instead."); \ - } \ - } \ - while (0) - -#define DEPRECATED_BODY(FOLD, FNEW) \ - WARN_DEPRECATED (FOLD, FNEW); \ - return feval (#FNEW, args) - -// We can't further simplify this by putting the DEFUN_DLD in a macro -// because then the mk-oct-links script will fail. - -DEFUN_DLD (gplot, args, , - "") -{ - DEPRECATED_BODY (gplot, __gnuplot_plot__); -} - -DEFUN_DLD (gsplot, args, , - "") -{ - DEPRECATED_BODY (gsplot, __gnuplot_splot__); -} - -DEFUN_DLD (graw, args, , - "") -{ - DEPRECATED_BODY (graw, __gnuplot_raw__); -} - -DEFUN_DLD (gset, args, , - "") -{ - DEPRECATED_BODY (gset, __gnuplot_set__); -} - -DEFUN_DLD (gshow, args, , - "") -{ - DEPRECATED_BODY (gshow, __gnuplot_show__); -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/ diff --git a/src/Makefile.in b/src/Makefile.in --- a/src/Makefile.in +++ b/src/Makefile.in @@ -51,7 +51,7 @@ lpsolve.cc lsode.cc lu.cc luinc.cc matrix_type.cc minmax.cc \ pinv.cc qr.cc quad.cc qz.cc rand.cc schur.cc sort.cc sparse.cc \ spchol.cc spdet.cc spkron.cc splu.cc spparms.cc sqrtm.cc svd.cc \ - syl.cc time.cc gplot.l __glpk__.cc __qp__.cc + syl.cc time.cc __gnuplot_raw__.l __glpk__.cc __qp__.cc DLD_SRC := $(addprefix DLD-FUNCTIONS/, $(DLD_XSRC)) @@ -256,7 +256,7 @@ DISTFILES = Makefile.in ChangeLog mkdefs mkops mkgendoc \ DOCSTRINGS mkbuiltins mk-errno-list mk-pkg-add \ defaults.h.in oct-conf.h.in oct-errno.cc.in octave.gperf oct-gperf.h \ - octave.cc parse.cc lex.cc y.tab.h gplot.cc \ + octave.cc parse.cc lex.cc y.tab.h __gnuplot_raw__.cc \ $(INCLUDES) $(DIST_SRC) $(OPT_HANDLERS) $(EXTRAS) all: octave$(EXEEXT) $(OCT_FILES) PKG_ADD DOCSTRINGS @@ -302,7 +302,7 @@ rm -f $@ $(SH_LD) $(SH_LDFLAGS) $(SONAME_FLAGS) -o $@ $^ $(OCTINTERP_LINK_DEPS) -stamp-prereq: defaults.h oct-conf.h oct-gperf.h parse.cc lex.cc gplot.cc $(OPT_HANDLERS) +stamp-prereq: defaults.h oct-conf.h oct-gperf.h parse.cc lex.cc __gnuplot_raw__.cc $(OPT_HANDLERS) touch stamp-prereq octave$(EXEEXT): stamp-prereq $(LIBRARIES) main.o $(DLD_STATIC_OBJ) @@ -491,7 +491,7 @@ maintainer-clean: distclean rm -f tags TAGS y.tab.c y.tab.h y.output yy.lex.c lex.cc parse.cc - rm -f oct-gperf.h gplot.cc $(OPT_HANDLERS) + rm -f oct-gperf.h __gnuplot_raw__.cc $(OPT_HANDLERS) .PHONY: maintainer-clean dist: parse.cc lex.cc oct-gperf.h @@ -530,7 +530,7 @@ lex.cc : lex.l $(LEX) $(LFLAGS) $< > $(@F) -gplot.cc : DLD-FUNCTIONS/gplot.l +__gnuplot_raw__.cc : DLD-FUNCTIONS/__gnuplot_raw__.l $(LEX) $(LFLAGS) $< > $(@F) defaults.h: defaults.h.in ../Makeconf Makefile diff --git a/src/help.cc b/src/help.cc --- a/src/help.cc +++ b/src/help.cc @@ -286,12 +286,6 @@ { "global", "Declare variables to have global scope.", }, - { "gplot", - "Produce 2-D plots using gnuplot-like command syntax.", }, - - { "gsplot", - "Produce 3-D plots using gnuplot-like command syntax.", }, - { "if", "-*- texinfo -*-\n\ @deffn Keyword if (@var{cond}) @dots{} endif\n\ diff --git a/src/ls-oct-ascii.cc b/src/ls-oct-ascii.cc --- a/src/ls-oct-ascii.cc +++ b/src/ls-oct-ascii.cc @@ -389,7 +389,7 @@ { bool infnan_warned = true; - return save_ascii_data (os, t, name, infnan_warned, true, false, 0); + return save_ascii_data (os, t, name, infnan_warned, false, false, 0); } // Maybe this should be a static function in tree-plot.cc? @@ -420,7 +420,6 @@ warning ("ignoring last %d columns", extras); Matrix tmp = tc.matrix_value (); - tmp = strip_infnan (tmp); nr = tmp.rows (); for (octave_idx_type i = 0; i < nc-extras; i += 3) @@ -433,7 +432,6 @@ else { Matrix tmp = tc.matrix_value (); - tmp = strip_infnan (tmp); nr = tmp.rows (); for (octave_idx_type i = 0; i < nc; i++)