Mercurial > hg > octave-nkf
changeset 5102:b04b30d30c66
[project @ 2004-12-28 01:59:05 by jwe]
author | jwe |
---|---|
date | Tue, 28 Dec 2004 01:59:05 +0000 |
parents | 9b1af8135ecd |
children | e2ed74b9bfa0 |
files | src/ChangeLog src/DLD-FUNCTIONS/gplot.l src/Makefile.in src/defun-int.h src/defun.h src/dirfns.cc src/file-io.cc src/file-io.h src/lex.h src/lex.l src/octave.cc src/octave.gperf src/parse.y src/pt-all.h src/pt-bp.cc src/pt-bp.h src/pt-check.cc src/pt-check.h src/pt-plot.cc src/pt-plot.h src/pt-pr-code.cc src/pt-pr-code.h src/pt-walk.h src/symtab.h src/toplev.cc src/variables.cc src/variables.h |
diffstat | 27 files changed, 2030 insertions(+), 2893 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,80 @@ +2004-12-27 John W. Eaton <jwe@octave.org> + + Merge of changes from Teemu Ikonen <tpikonen@pcu.helsinki.fi> to + remove gnuplot from main parser. + + * pt-plot.cc, pt-plot.h: Delete. + * Makefile.in (PT_SRC, PT_INCLUDES): Delete them from the lists. + + * DLD-FUNCTIONS/gplot.l: New file. + * Makefile.in: Include it in the DLD_XSRC list. + + * dirfns.cc (octave_change_to_directory): + Don't call do_external_plotter_cd. + + * symtab.h (symbol_record::TYPE): New element, RAWCOMMAND. + (symbol_record::symbol_def::mark_as_rawcommand, + symbol_record::symbol_def::unmark_rawcommand, + symbol_record::symbol_def::is_rawcommand): New functions. + (symbol_record::symbol_def::symbol_type): Bitfield is now 9 bits wide. + (symbol_record::mark_as_rawcommand, + symbol_record::unmark_rawcommand, symbol_record::is_rawcommand): + New functions. + (SYMTAB_ALL_TYPES): Include RAWCOMMAND. + + * parse.y (make_plot_command): Delete function. + (tree_plot_command_type, subplot_type, subplot_list_type, + plot_limits_type, plot_range_type, subplot_using_type, + subplot_style_type, subplot_axes_type): + Delete non-terminal type decls. + (PLOT, STYLE, AXES_TAG): Delete token types. + (title, plot_command, plot_command2, plot_options, plot_command1, + ranges, ranges1, using, using1, style, axes): Delete non-terminals. + + * toplev.cc (do_octave_atexit): Don't call close_plot_stream. + + * variables.cc (rawcommand_set): New static variable. + (is_marked_as_rawcommand, mark_as_rawcommand, unmark_rawcommand, + Fiscommand, Fmark_as_rawcommand, Funmark_rawcommand, + Fisrawcommand, is_rawcommand_name): New functions. + * variables.h: Provide decl for is_rawcommand_name. + + * pt-bp.cc, pt-bp.h, pt-check.cc, pt-check.h, pt-pr-code.cc, + pt-pr-code.h, pt-walk.h: Delete all declarations, definitions, and + uses of visit_subplot, visit_subplot_axes, visit_subplot_list, + visit_subplot_style, and visit_subplot_using methods. + + * lex.h (lexer_flags): New field, doing_rawcommand. + * lex.l (<COMMAND_START>[\;\,]): Also handle raw commands here. + (lexer_flags::init): Initialize doing_racommand to false. + (handle_identifier): Recognize raw commands ere. + (handle_string): Don't do string escape conversions on raw command + strings. + + * octave.gperf: Delete gplot_kw, gsplot_kw, replot_kw. + + * lex.h (lexer_flags): Delete fields cant_be_identifier, + doing_set, in_plot_range, in_plot_using, in_plot_style, + in_plot_axes, past_plot_range, and plotting. + * lex.l: Delete all uses of these lexer flags and remove all + special cases for plotting. + (plot_style_token, plot_axes_token, is_plot_keyword): Delete. + + * file-io.cc, file-io.h (tmp_files, mark_for_deletion, + cleanup_tmp_files): Move here. + * pt-plot.cc, pt-plot.h: From here. + + * Makefile.in (PKG_ADD): New target. + (all): Depend on PKG_ADD. + (install-oct): Depend on PKG_ADD. Install PKG_ADD file. + (gplot.cc): New target. + (stamp-prereq): Depend on gplot.cc. + (VAR): Don't include $(DLD_SRC) here. + (DLD_OBJ, DLD_DEF_FILES): Include .l files. + + * defun-int.h (DEFVAR, DEFCONST, DEFCONSTX): Move definition here. + * defun.h: From here. + 2004-12-22 John W. Eaton <jwe@octave.org> * ls-oct-ascii.cc (extract_keyword (std::istream&, const
new file mode 100644 --- /dev/null +++ b/src/DLD-FUNCTIONS/gplot.l @@ -0,0 +1,1582 @@ +%option prefix="gpt" +%option noyywrap + +%{ +// PKG_ADD: mark_as_rawcommand ("gplot"); +// PKG_ADD: mark_as_rawcommand ("gset"); +// PKG_ADD: mark_as_rawcommand ("gsplot"); + +// PKG_ADD: mark_as_rawcommand ("replot"); + +// PKG_ADD: mark_as_command ("gshow"); +// PKG_ADD: mark_as_command ("hold"); +// PKG_ADD: mark_as_command ("set"); +// PKG_ADD: mark_as_command ("show"); + +// PKG_ADD: __gplot_init__ (); + +// PKG_ADD: atexit ("closeplot"); + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string> +#include <fstream> +#include <iostream> + +#ifdef HAVE_UNISTD_H +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#include <unistd.h> +#endif + +#include "file-ops.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 int is_plot_keyword (const std::string& s); + +static int handle_string (char delim); + +static inline bool can_be_plotkw (void); + +static bool gpt_quote_is_transpose; +static bool gpt_allow_plotkw; +static int gpt_parens; +static int gpt_brackets; +static int gpt_braces; + +static int send_to_plot_stream (const std::string& cmd); + +// needed by handle_string +static char string_buf[256]; + +%} + +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})|(<<=)|(>>=)|(\.)) +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; + 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 ("The 'function' keyword is 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; + } + +%% + +// If TRUE, a replot command is issued automatically each time a plot +// changes in some way. +static bool Vautomatic_replot; + +// The name of the shell command to execute to start gnuplot. +static std::string Vgnuplot_binary; + +// TRUE if gnuplot appears to support multiple plot windows with X11. +static bool Vgnuplot_has_frames; + +// The number of lines we've plotted so far. +static int plot_line_count = 0; + +// Is this a parametric plot? Makes a difference for 3D plotting. +static bool parametric_plot = false; + +// The gnuplot terminal type. +static std::string gnuplot_terminal_type; + +// Should the graph window be cleared before plotting the next line? +static bool clear_before_plotting = true; + +// List of files to delete when we exit or crash. +// +// XXX FIXME XXX -- this should really be static, but that causes +// problems on some systems. +std::stack <std::string> tmp_files; + +// Pipe to gnuplot. +static oprocstream *plot_stream = 0; + +// ID of the plotter process. +static pid_t plot_stream_pid = 0; + +// 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; + +// (almost) copy-paste code from pt-plot.cc + +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 void +close_plot_stream (void) +{ + octave_child_list::remove (plot_stream_pid); + + if (plot_stream) + { + send_to_plot_stream ("\nquit\n"); + delete plot_stream; + plot_stream = 0; + } + + plot_line_count = 0; +} + +static void +plot_stream_death_handler (pid_t pid, int) +{ + close_plot_stream (); + + warning ("connection to external plotter (pid = %d) lost --", pid); + warning ("please try your plot command(s) again"); +} + +static void +open_plot_stream (void) +{ + static bool initialized = false; + + if (plot_stream && ! *plot_stream) + { + delete plot_stream; + plot_stream = 0; + } + + if (! plot_stream) + { + initialized = false; + + plot_line_count = 0; + + std::string plot_prog; + + if (Vgnuplot_binary.empty ()) + plot_prog = "gnuplot"; + else + plot_prog = "\"" + Vgnuplot_binary + "\""; + + // 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 set, oset; + sigemptyset (&set); + sigaddset (&set, SIGINT); + sigprocmask (SIG_BLOCK, &set, &oset); +#else + volatile octave_interrupt_handler old_interrupt_handler + = octave_ignore_interrupts (); +#endif + + plot_stream = new oprocstream (plot_prog.c_str ()); + + if (plot_stream) + { + if (! *plot_stream) + { + delete plot_stream; + plot_stream = 0; + + error ("plot: unable to open pipe to `%s'", plot_prog.c_str ()); + } + else + { + plot_stream_pid = plot_stream->pid (); + octave_child_list::insert (plot_stream_pid, + plot_stream_death_handler); + } + } + else + error ("plot: unable to open pipe to `%s'", plot_prog.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; + + *plot_stream << "set style data lines\n"; + + if (! gnuplot_terminal_type.empty ()) + *plot_stream << "set term " << gnuplot_terminal_type + << Vgnuplot_command_end << "\n"; + } +} + +static int +send_to_plot_stream (const std::string& cmd) +{ + if (! (plot_stream && *plot_stream)) + { + open_plot_stream (); + + if (error_state) + return -1; + } + + int replot_len = Vgnuplot_command_replot.length (); + int splot_len = Vgnuplot_command_splot.length (); + int plot_len = Vgnuplot_command_plot.length (); + + bool is_replot = (Vgnuplot_command_replot == cmd.substr (0, replot_len)); + bool is_splot = (Vgnuplot_command_splot == cmd.substr (0, splot_len)); + bool is_plot = (Vgnuplot_command_plot == cmd.substr (0, plot_len)); + + if (plot_line_count == 0 && is_replot) + error ("replot: no previous plot"); + else + { + *plot_stream << cmd; + + if (! (is_replot || is_splot || is_plot) + && plot_line_count > 0 + && Vautomatic_replot) + { + *plot_stream << Vgnuplot_command_replot << Vgnuplot_command_end; + } + + plot_stream->flush (); + } + + return 0; +} + +// Check if the parser state is such that a plot keyword can occur. +static inline bool +can_be_plotkw (void) +{ + return (gpt_allow_plotkw + && (gpt_braces == 0) + && (gpt_brackets == 0) + && (gpt_parens == 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; +} + +// This is used to handle single-quote delimited strings. Kludge alert. +static int +handle_string (char delim) +{ + int c; + char *pos = string_buf; + int escape_pending = 0; + + *pos++ = static_cast<char> (delim); + while ((c = yyinput ()) != EOF) + { + if (c == '\\') + { + if (escape_pending) + { + *pos++ = static_cast<char> (c); + escape_pending = 0; + } + else + { + *pos++ = static_cast<char> (c); + escape_pending = 1; + } + continue; + } + else if (c == '\n') + { + error ("unterminated string constant"); + break; + } + else if (c == delim) + { + if (escape_pending) + *pos++ = static_cast<char> (c); + else + { + c = yyinput (); + if (c == delim) + { + *pos++ = static_cast<char> (c); + *pos++ = static_cast<char> (c); + } + else + { + yyunput (c, yytext); + *pos++ = static_cast<char> (delim); + *pos++ = '\0'; + yytext = string_buf; + return STRING; + } + } + } + else + { + *pos++ = static_cast<char> (c); + } + + escape_pending = 0; + } + + throw gpt_parse_error ("Unterminated string?"); + + return 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) +{ + const char *t = s.c_str (); + if (almost_match ("title", t, 1)) + { + return TITLE; + } + else if (almost_match ("using", t, 1)) + { + return USING; + } + else if (almost_match ("with", t, 1)) + { + return WITH; + } + else if (almost_match ("axes", t, 2) || almost_match ("axis", t, 2)) + { + return AXES; + } + else if (strcmp ("clear", t) == 0) + { + return CLEAR; + } + else + { + return 0; + } +} + +// Some predicates on tokens + +// Return true for ":". +static inline bool +colonp (const int tok) +{ + return (tok == COLON); +} + +// Return TRUE for "]". +static inline bool +endbracketp (const int tok) +{ + return (tok == END_BRACKET); +} + +// Return TRUE for plot token, comma or end of input. +static inline 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 inline 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 += 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. + +// Title has one string expression which is evaluated and printed to the +// gnuplot command string. +static std::string +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; +} + +// 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); +} + +// Parse and evaluate parameter string and pass it to gnuplot pipe. +static int +makeplot (std::string caller, std::string args) throw (gpt_parse_error) +{ + 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; + if (clear_before_plotting || plot_line_count == 0) + { + plot_line_count = 0; + outstr += Vgnuplot_command_plot + " "; + } + else + outstr += Vgnuplot_command_replot + " "; + } + else if (caller == "splot") + { + ndim = 3; + if (clear_before_plotting || plot_line_count == 0) + { + plot_line_count = 0; + outstr += Vgnuplot_command_splot + " "; + } + else + outstr += Vgnuplot_command_replot + " "; + } + 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)) + throw gpt_parse_error ("must have something to plot"); + else + { + std::string file; + plot_line_count++; + + if (tok == STRING) + { + file = file_ops::tilde_expand (std::string (yytext)); + // XXX FIXME XXX -- perhaps should check if the file exists? + outstr += file + " "; + // Discard junk after the string. + read_until (plottok_or_end_p, tok); + } + else + { + std::string plot_expr_str; + plot_expr_str += std::string (yytext) + " "; + plot_expr_str += read_until (plottok_or_end_p, tok); + + int status; + 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; + + // Terrible kludge, but line count is destroyed when plot stream + // is opened for the first time. + int linesave = plot_line_count; + send_to_plot_stream (outstr); + plot_line_count = linesave; + + return 1; +} + +static void +doplot (std::string caller, octave_value_list args) +{ + std::string s; + int i = 0; + + while (i < args.length ()) + s += args (i++).string_value () + " "; + + try + { + makeplot (caller, s); + } + catch (gpt_parse_error e) + { + if (e.msg.empty ()) + error ("could not parse plot command"); + else + error (e.msg.c_str ()); + } +} + +DEFUN_DLD (gplot, args, , + "Plot with gnuplot.\n") +{ + doplot ("plot", args); + return octave_value_list (); +} + +DEFUN_DLD (gsplot, args, , + "Plot with gnuplot.\n") +{ + doplot ("splot", args); + return octave_value_list (); +} + +DEFUN_DLD (replot, args, , + "Plot with gnuplot.\n") +{ + doplot ("replot", args); + 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\ +\n\ +The commands @kbd{gplot clear}, @kbd{gsplot clear}, and @kbd{replot\n\ +clear} are equivalent to @code{clearplot}. (Previously, commands like\n\ +@kbd{gplot clear} would evaluate @code{clear} as an ordinary expression\n\ +and clear all the visible variables.)\n\ +@end deftypefn") +{ + octave_value_list retval; + + send_to_plot_stream ("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. + + send_to_plot_stream ("set title\n"); + send_to_plot_stream ("set xlabel\n"); + send_to_plot_stream ("set ylabel\n"); + send_to_plot_stream ("set nogrid\n"); + send_to_plot_stream ("set nolabel\n"); + + // This makes a simple `replot' not work after a `clearplot' command + // has been issued. + + plot_line_count = 0; + + return retval; +} + +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") +{ + octave_value_list retval; + close_plot_stream (); + return retval; +} + +DEFUN_DLD (hold, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} hold @var{args}\n\ +Tell Octave to `hold' the current data on the plot when executing\n\ +subsequent plotting commands. This allows you to execute a series of\n\ +plot commands and have all the lines end up on the same figure. The\n\ +default is for each new plot command to clear the plot device first.\n\ +For example, the command\n\ +\n\ +@example\n\ +hold on\n\ +@end example\n\ +\n\ +@noindent\n\ +turns the hold state on. An argument of @code{off} turns the hold state\n\ +off, and @code{hold} with no arguments toggles the current hold state.\n\ +@end deftypefn") +{ + octave_value_list retval; + + int argc = args.length () + 1; + + string_vector argv = args.make_argv ("hold"); + + if (error_state) + return retval; + + switch (argc) + { + case 1: + clear_before_plotting = ! clear_before_plotting; + break; + + case 2: + if (argv[1] == "on") + clear_before_plotting = false; + else if (argv[1] == "off") + clear_before_plotting = true; + else + print_usage ("hold"); + break; + + default: + print_usage ("hold"); + break; + } + + return retval; +} + +DEFUN_DLD (ishold, , , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} ishold\n\ +Return 1 if the next line will be added to the current plot, or 0 if\n\ +the plot device will be cleared before drawing the next line.\n\ +@end deftypefn") +{ + return octave_value (! clear_before_plotting); +} + +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") +{ + octave_value_list retval; + cleanup_tmp_files (); + return retval; +} + +DEFUN_DLD (graw, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} graw (@var{string})\n\ +Send @var{string} directly to gnuplot subprocess.\n\ +@end deftypefn") +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).is_string ()) + { + std::string cmd = args(0).string_value (); + + if (! (plot_stream && *plot_stream)) + open_plot_stream (); + + if (! error_state) + { + *plot_stream << cmd; + + plot_stream->flush (); + } + } + else + print_usage ("raw"); + + return retval; +} + +DEFUN_DLD (gset, args, , + "-*- texinfo -*-\n\ +@deffn {Command} gset options\n\ +Set plotting options for gnuplot\n\ +@end deffn") +{ + octave_value_list retval; + + int argc = args.length () + 1; + + string_vector argv = args.make_argv ("set"); + + if (error_state) + return retval; + + 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; + + send_to_plot_stream (OSSTREAM_STR (plot_buf)); + + OSSTREAM_FREEZE (plot_buf); + + return retval; +} + +DEFUN_DLD (set, args, nargout, + "-*- texinfo -*-\n\ +This command is has been replaced by @code{gset}.") +{ + warning ("set is obsolete -- use gset instead"); + return Fgset (args, nargout); +} + +DEFUN_DLD (gshow, args, , + "-*- texinfo -*-\n\ +@deffn {Command} gshow options\n\ +Show plotting options.\n\ +@end deffn") +{ + octave_value_list retval; + + int argc = args.length () + 1; + + string_vector argv = args.make_argv ("show"); + + if (error_state) + return retval; + + 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; + + send_to_plot_stream (OSSTREAM_STR (plot_buf)); + + OSSTREAM_FREEZE (plot_buf); + + return retval; +} + +DEFUN_DLD (show, args, nargout, + "-*- texinfo -*-\n\ +This command is has been replaced by @code{gshow}.") +{ + warning ("show is obsolete -- use gshow instead"); + return Fgshow (args, nargout); +} + +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) +{ + return set_string_var (Vgnuplot_binary, "gnuplot_binary"); +} + +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_has_frames (void) +{ + Vgnuplot_has_frames = check_preference ("gnuplot_has_frames"); + + return 0; +} + +DEFUN_DLD (__gplot_init__, , , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} __gplot_init__ ()\n\ +@end deftypefn") +{ + octave_value_list retval; + + static bool gplot_initialized = false; + + if (gplot_initialized) + return retval; + + gplot_initialized = true; + + 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"); + + 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"); + + DEFVAR (gnuplot_command_plot, "pl", gnuplot_command_plot, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} gnuplot_command_plot\n\ +@end defvr"); + + DEFVAR (gnuplot_command_replot, "rep", gnuplot_command_replot, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} gnuplot_command_replot\n\ +@end defvr"); + + DEFVAR (gnuplot_command_splot, "sp", gnuplot_command_splot, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} gnuplot_command_splot\n\ +@end defvr"); + + DEFVAR (gnuplot_command_using, "u", gnuplot_command_using, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} gnuplot_command_using\n\ +@end defvr"); + + DEFVAR (gnuplot_command_with, "w", gnuplot_command_with, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} gnuplot_command_with\n\ +@end defvr"); + + DEFVAR (gnuplot_command_axes, "ax", gnuplot_command_axes, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} gnuplot_command_axes\n\ +@end defvr"); + + DEFVAR (gnuplot_command_title, "t", gnuplot_command_title, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} gnuplot_command_title\n\ +@end defvr"); + + DEFVAR (gnuplot_command_end, "\n", gnuplot_command_end, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} gnuplot_command_end\n\ +@end defvr"); + +#if defined (GNUPLOT_HAS_FRAMES) + bool with_frames = true; +#else + bool with_frames = false; +#endif + + DEFVAR (gnuplot_has_frames, with_frames, gnuplot_has_frames, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} gnuplot_has_frames\n\ +If the value of this variable is nonzero, Octave assumes that your copy\n\ +of gnuplot has support for multiple frames that is included in recent\n\ +3.6beta releases. Its initial value is determined by configure, but it\n\ +can be changed in your startup script or at the command line in case\n\ +configure got it wrong, or if you upgrade your gnuplot installation.\n\ +@end defvr"); + + return retval; +}
--- a/src/Makefile.in +++ b/src/Makefile.in @@ -48,11 +48,12 @@ gcd.cc getgrent.cc getpwent.cc getrusage.cc givens.cc hess.cc \ inv.cc kron.cc lpsolve.cc lsode.cc lu.cc minmax.cc \ odessa.cc pinv.cc qr.cc quad.cc qz.cc rand.cc schur.cc \ - sort.cc sqrtm.cc svd.cc syl.cc time.cc + sort.cc sqrtm.cc svd.cc syl.cc time.cc gplot.l DLD_SRC := $(addprefix DLD-FUNCTIONS/, $(DLD_XSRC)) -DLD_OBJ := $(patsubst %.cc, %.o, $(DLD_XSRC)) +DLD_OBJ_1 := $(patsubst %.l, %.o, $(DLD_XSRC)) +DLD_OBJ := $(patsubst %.cc, %.o, $(DLD_OBJ_1)) ifeq ($(ENABLE_DYNAMIC_LINKING), true) OCT_FILES := $(patsubst %.o, %.oct, $(DLD_OBJ)) @@ -81,7 +82,7 @@ PT_INCLUDES := pt.h pt-all.h pt-arg-list.h pt-assign.h pt-binop.h \ pt-bp.h pt-cell.h pt-check.h pt-cmd.h pt-colon.h pt-const.h \ pt-decl.h pt-except.h pt-exp.h pt-fcn-handle.h pt-id.h pt-idx.h \ - pt-jump.h pt-loop.h pt-mat.h pt-misc.h pt-plot.h \ + pt-jump.h pt-loop.h pt-mat.h pt-misc.h \ pt-pr-code.h pt-select.h pt-stmt.h pt-unop.h pt-walk.h \ INCLUDES := Cell.h base-list.h c-file-ptr-stream.h comment-list.h \ @@ -136,7 +137,7 @@ pt-cell.cc pt-check.cc pt-cmd.cc pt-colon.cc pt-const.cc \ pt-decl.cc pt-except.cc pt-exp.cc pt-fcn-handle.cc pt-id.cc \ pt-idx.cc pt-jump.cc pt-loop.cc pt-mat.cc pt-misc.cc \ - pt-plot.cc pt-pr-code.cc pt-select.cc pt-stmt.cc pt-unop.cc + pt-pr-code.cc pt-select.cc pt-stmt.cc pt-unop.cc DIST_SRC := Cell.cc bitfcns.cc c-file-ptr-stream.cc comment-list.cc \ cutils.c data.cc debug.cc defaults.cc defun.cc dirfns.cc \ @@ -189,7 +190,8 @@ DEFUN_PATTERN = "^[ \t]*DEF(CONSTFUN|CMD|UN|UN_DLD|UN_TEXT|UN_MAPPER)[ \t]*\\(" -DLD_DEF_FILES := $(patsubst %.cc, %.df, $(DLD_XSRC)) +DLD_DEF_FILES_1 := $(patsubst %.l, %.df, $(DLD_XSRC)) +DLD_DEF_FILES := $(patsubst %.cc, %.df, $(DLD_DEF_FILES_1)) DEF_4 := $(addprefix $(srcdir)/, $(SOURCES)) DEF_3 := $(notdir $(shell egrep -l $(DEFUN_PATTERN) $(DEF_4))) @@ -199,8 +201,7 @@ DEFVAR_PATTERN = "^[ \t]*DEF(VAR|CONS(T|TX))[ \t]*\\(" -VAR_5 := $(SOURCES) $(DLD_SRC) -VAR_4 := $(addprefix $(srcdir)/, $(VAR_5)) +VAR_4 := $(addprefix $(srcdir)/, $(SOURCES)) VAR_3 := $(notdir $(shell egrep -l $(DEFVAR_PATTERN) $(VAR_4))) VAR_2 := $(patsubst %.y, %, $(VAR_3)) VAR_1 := $(patsubst %.l, %, $(VAR_2)) @@ -235,7 +236,7 @@ BINDISTFILES = octave $(OCT_FILES) endif -all: octave$(EXEEXT) stamp-oct-links DOCSTRINGS +all: octave$(EXEEXT) stamp-oct-links PKG_ADD DOCSTRINGS .PHONY: all objects: $(OBJECTS) @@ -284,7 +285,7 @@ fi touch stamp-oct-links -stamp-prereq: defaults.h oct-conf.h oct-gperf.h parse.cc lex.cc $(OPT_HANDLERS) +stamp-prereq: defaults.h oct-conf.h oct-gperf.h parse.cc lex.cc gplot.cc $(OPT_HANDLERS) touch stamp-prereq octave$(EXEEXT): stamp-prereq $(LIBRARIES) main.o $(DLD_STATIC_OBJ) @@ -322,6 +323,12 @@ @$(srcdir)/mkbuiltins def-files var-files > $@-t @$(top_srcdir)/move-if-change $@-t $@ +PKG_ADD: $(DLD_SRC) + $(SED) -n -e 's,^//* *PKG_ADD: *,,p' \ + -e 's,^/\* *PKG_ADD: *\(.*\) \*/$$,\1,p' \ + $(addprefix $(srcdir)/, $(DLD_SRC)) > PKG_ADD.t + mv PKG_ADD.t PKG_ADD + DOCSTRINGS: gendoc$(BUILD_EXEEXT) ./gendoc > $@-t mv $@-t $@ @@ -372,7 +379,7 @@ $(LN_S) octave-$(version)$(EXEEXT) $(DESTDIR)$(bindir)/octave$(EXEEXT) .PHONY: install-bin -install-oct: +install-oct: PKG_ADD if [ -n "$(OCT_FILES)" ]; then \ $(top_srcdir)/mkinstalldirs $(DESTDIR)$(octfiledir); \ xfiles="$(OCT_FILES)"; \ @@ -380,6 +387,7 @@ $(INSTALL_PROGRAM) $$f $(DESTDIR)$(octfiledir)/$$f; \ done; \ $(srcdir)/mk-oct-links $(DESTDIR)$(octfiledir) $(DLD_DEF_FILES); \ + $(INSTALL_DATA) PKG_ADD $(DESTDIR)$(octfiledir)/PKG_ADD; \ fi .PHONY: install-oct @@ -512,6 +520,9 @@ lex.cc : lex.l $(LEX) $(LFLAGS) $< > $(@F) +gplot.cc : DLD-FUNCTIONS/gplot.l + $(LEX) $(LFLAGS) $< > $(@F) + defaults.h: defaults.h.in ../Makeconf Makefile @$(do-subst-default-vals)
--- a/src/defun-int.h +++ b/src/defun-int.h @@ -92,6 +92,41 @@ return error_state ? false : true; \ } +// Define a builtin variable. +// +// name is the name of the variable, unquoted. +// +// defn is the initial value for the variable. +// +// protect is a flag that says whether it should be possible to give +// the variable a new value. +// +// eternal is a flag that says whether it should be possible to +// clear the variable. Most builtin variables are eternal, and +// cannot be cleared. +// +// chg_fcn is a pointer to a function that should be called whenever +// this variable is given a new value. It can be 0 if there is no +// function to call. See also the code in user-prefs.cc. +// +// doc is the simple help text for this variable. + +#define DEFVAR(name, defn, chg_fcn, doc) \ + DEFVAR_INTERNAL (#name, SBV_ ## name, defn, false, chg_fcn, doc) + +// Define a builtin constant `name' (which may be redefined, but will +// retain its original value when cleared) and also an alias to it +// called `__name__' (which may not be redefined). + +#define DEFCONST(name, defn, doc) \ + DEFCONST_INTERNAL (name, defn, doc) + +// This one can be used when `name' cannot be used directly (if it is +// already defined as a macro). In that case, name is already a +// quoted string, and the name of the structure must to be passed too. + +#define DEFCONSTX(name, sname, defn, doc) \ + DEFCONSTX_INTERNAL (name, sname, defn, doc) // MAKE_BUILTINS is defined to extract function names and related // information and create the *.df files that are eventually used to
--- a/src/defun.h +++ b/src/defun.h @@ -29,42 +29,6 @@ #include "defun-int.h" -// Define a builtin variable. -// -// name is the name of the variable, unquoted. -// -// defn is the initial value for the variable. -// -// protect is a flag that says whether it should be possible to give -// the variable a new value. -// -// eternal is a flag that says whether it should be possible to -// clear the variable. Most builtin variables are eternal, and -// cannot be cleared. -// -// chg_fcn is a pointer to a function that should be called whenever -// this variable is given a new value. It can be 0 if there is no -// function to call. See also the code in user-prefs.cc. -// -// doc is the simple help text for this variable. - -#define DEFVAR(name, defn, chg_fcn, doc) \ - DEFVAR_INTERNAL (#name, SBV_ ## name, defn, false, chg_fcn, doc) - -// Define a builtin constant `name' (which may be redefined, but will -// retain its original value when cleared) and also an alias to it -// called `__name__' (which may not be redefined). - -#define DEFCONST(name, defn, doc) \ - DEFCONST_INTERNAL (name, defn, doc) - -// This one can be used when `name' cannot be used directly (if it is -// already defined as a macro). In that case, name is already a -// quoted string, and the name of the structure must to be passed too. - -#define DEFCONSTX(name, sname, defn, doc) \ - DEFCONSTX_INTERNAL (name, sname, defn, doc) - // Define a builtin function. // // name is the name of the function, unqouted.
--- a/src/dirfns.cc +++ b/src/dirfns.cc @@ -46,6 +46,7 @@ #include "oct-env.h" #include "str-vec.h" +#include "Cell.h" #include "defun.h" #include "dir-ops.h" #include "dirfns.h" @@ -54,7 +55,6 @@ #include "oct-obj.h" #include "pager.h" #include "procstream.h" -#include "pt-plot.h" #include "sysdep.h" #include "toplev.h" #include "unwind-prot.h" @@ -71,7 +71,9 @@ int cd_ok = octave_env::chdir (newdir); if (cd_ok) - do_external_plotter_cd (newdir); + // XXX FIXME XXX -- this should be handled as a list of functions + // to call so users can add their own chdir handlers. + /* do_external_plotter_cd (newdir) */; else { using namespace std;
--- a/src/file-io.cc +++ b/src/file-io.cc @@ -52,11 +52,11 @@ #include <unistd.h> #endif +#include "error.h" #include "file-ops.h" +#include "lo-ieee.h" #include "defun.h" -#include "error.h" -#include "lo-ieee.h" #include "oct-fstrm.h" #include "oct-iostrm.h" #include "oct-map.h" @@ -65,7 +65,6 @@ #include "oct-stream.h" #include "oct-strstrm.h" #include "pager.h" -#include "pt-plot.h" #include "so-array.h" #include "sysdep.h" #include "utils.h" @@ -102,6 +101,29 @@ octave_stream_list::clear (); } +// List of files to delete when we exit or crash. +// +// XXX FIXME XXX -- this should really be static, but that causes +// problems on some systems. +std::stack <std::string> tmp_files; + +void +mark_for_deletion (const std::string& file) +{ + tmp_files.push (file); +} + +void +cleanup_tmp_files (void) +{ + while (! tmp_files.empty ()) + { + std::string filename = tmp_files.top (); + tmp_files.pop (); + unlink (filename.c_str ()); + } +} + static void maybe_warn_interface_change (const std::string& mode) {
--- a/src/file-io.h +++ b/src/file-io.h @@ -29,6 +29,10 @@ extern void close_files (void); +extern void mark_for_deletion (const std::string&); + +extern void cleanup_tmp_files (void); + #endif /*
--- a/src/lex.h +++ b/src/lex.h @@ -75,10 +75,6 @@ // function definition. bool beginning_of_function; - // Another context hack, this time for the plot command's `using', - // `title', and `with' keywords. - bool cant_be_identifier; - // TRUE means that we should convert spaces to a comma inside a // matrix definition. bool convert_spaces_to_comma; @@ -105,21 +101,9 @@ // GAG. Stupid kludge so that [[1,2][3,4]] will work. bool do_comma_insert; - // TRUE means we think we are looking at a set command. - bool doing_set; - - // TRUE means we're looking at the range part of a plot command. - bool in_plot_range; - - // TRUE means we're looking at the using part of a plot command. - bool in_plot_using; - - // TRUE means we're looking at the style part of a plot command. - bool in_plot_style; - - // TRUE means we're looking at the axes part of a plot command. - bool in_plot_axes; - + // TRUE means we're doing a raw input command. + bool doing_rawcommand; + // TRUE means we're looking at an indirect reference to a // structure element. bool looking_at_indirect_ref; @@ -134,13 +118,6 @@ // -1 ==> Yes, but it is the last one because we have seen EOF. int parsing_nested_function; - // TRUE means we've seen something that means we must be past the - // range part of a plot command. - bool past_plot_range; - - // TRUE means we're working on a plot command. - bool plotting; - // Return transpose or start a string? bool quote_is_transpose;
--- a/src/lex.l +++ b/src/lex.l @@ -121,7 +121,6 @@ { \ current_input_column += yyleng; \ lexer_flags.quote_is_transpose = false; \ - lexer_flags.cant_be_identifier = false; \ lexer_flags.convert_spaces_to_comma = true; \ COUNT_TOK_AND_RETURN (tok); \ } \ @@ -144,7 +143,6 @@ token_stack.push (yylval.tok_val); \ current_input_column += yyleng; \ lexer_flags.quote_is_transpose = false; \ - lexer_flags.cant_be_identifier = true; \ lexer_flags.convert_spaces_to_comma = convert; \ COUNT_TOK_AND_RETURN (tok); \ } \ @@ -240,11 +238,9 @@ static void fixup_column_count (char *s); static void do_comma_insert_check (void); -static int is_plot_keyword (const std::string& s); static int is_keyword_token (const std::string& s); static void prep_for_function (void); static void prep_for_nested_function (void); -static std::string plot_style_token (const std::string& s); static symbol_record *lookup_identifier (const std::string& s); static std::string grab_help_text (void); static bool match_any (char c, const char *s); @@ -312,24 +308,20 @@ BEGIN (INITIAL); current_input_column = 1; lexer_flags.quote_is_transpose = false; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = true; COUNT_TOK_AND_RETURN ('\n'); } <COMMAND_START>[\;\,] { - if (lexer_flags.doing_set && strcmp (yytext, ",") == 0) - { - TOK_PUSH_AND_RETURN (yytext, STRING); - } + if (lexer_flags.doing_rawcommand) + TOK_PUSH_AND_RETURN (yytext, STRING); + + BEGIN (INITIAL); + + if (strcmp (yytext, ",") == 0) + TOK_RETURN (','); else - { - BEGIN (INITIAL); - if (strcmp (yytext, ",") == 0) - TOK_RETURN (','); - else - TOK_RETURN (';'); - } + TOK_RETURN (';'); } <COMMAND_START>[\"\'] { @@ -384,7 +376,6 @@ int tmp = eat_continuation (); lexer_flags.quote_is_transpose = false; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = true; if ((tmp & ATE_NEWLINE) == ATE_NEWLINE) @@ -423,7 +414,6 @@ } lexer_flags.quote_is_transpose = false; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = true; maybe_warn_separator_insert (','); @@ -443,7 +433,6 @@ fixup_column_count (yytext); eat_whitespace (); lexer_flags.quote_is_transpose = false; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = true; COUNT_TOK_AND_RETURN (';'); } @@ -461,7 +450,6 @@ eat_whitespace (); lexer_flags.quote_is_transpose = false; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = true; if (nesting_level.none ()) @@ -475,46 +463,25 @@ } } -%{ -// Open and close bracket are handled differently if we are in the range -// part of a plot command. -// -%} - \[{S}* { nesting_level.bracket (); current_input_column += yyleng; lexer_flags.quote_is_transpose = false; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = true; promptflag--; eat_whitespace (); - if (lexer_flags.plotting && ! lexer_flags.past_plot_range) - { - lexer_flags.in_plot_range = true; - COUNT_TOK_AND_RETURN (OPEN_BRACE); - } - else - { - lexer_flags.bracketflag++; - BEGIN (MATRIX_START); - COUNT_TOK_AND_RETURN ('['); - } + lexer_flags.bracketflag++; + BEGIN (MATRIX_START); + COUNT_TOK_AND_RETURN ('['); } \] { nesting_level.remove (); - if (lexer_flags.plotting && ! lexer_flags.past_plot_range) - { - lexer_flags.in_plot_range = false; - TOK_RETURN (CLOSE_BRACE); - } - else - TOK_RETURN (']'); + TOK_RETURN (']'); } %{ @@ -606,7 +573,6 @@ "@" { current_input_column++; lexer_flags.quote_is_transpose = false; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = false; lexer_flags.looking_at_function_handle++; COUNT_TOK_AND_RETURN ('@'); @@ -621,7 +587,6 @@ {NL} { current_input_column = 1; lexer_flags.quote_is_transpose = false; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = true; if (nesting_level.none ()) @@ -660,19 +625,6 @@ } %{ -// The colon operator is handled differently if we are in the range -// part of a plot command. -%} - -":" { - if (lexer_flags.plotting - && (lexer_flags.in_plot_range || lexer_flags.in_plot_using)) - BIN_OP_RETURN (COLON, true); - else - BIN_OP_RETURN (':', false); - } - -%{ // Gobble comments. If closest nesting is inside parentheses, don't // return a new line. %} @@ -718,7 +670,6 @@ current_input_column = 1; lexer_flags.quote_is_transpose = false; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = true; maybe_gripe_matlab_incompatible_comment (yytext[0]); @@ -736,6 +687,8 @@ // Other operators. %} +":" { BIN_OP_RETURN (':', false); } + ".+" { XBIN_OP_RETURN (EPLUS, false); } ".-" { XBIN_OP_RETURN (EMINUS, false); } ".*" { BIN_OP_RETURN (EMUL, false); } @@ -755,6 +708,8 @@ "|" { BIN_OP_RETURN (EXPR_OR, false); } "<" { BIN_OP_RETURN (EXPR_LT, false); } ">" { BIN_OP_RETURN (EXPR_GT, false); } +"+" { BIN_OP_RETURN ('+', false); } +"-" { BIN_OP_RETURN ('-', false); } "*" { BIN_OP_RETURN ('*', false); } "/" { BIN_OP_RETURN ('/', false); } "\\" { BIN_OP_RETURN (LEFTDIV, false); } @@ -769,31 +724,14 @@ ">>" { XBIN_OP_RETURN (RSHIFT, false); } {NOT} { - if (lexer_flags.plotting && ! lexer_flags.in_plot_range) - lexer_flags.past_plot_range = true; - if (yytext[0] == '~') BIN_OP_RETURN (EXPR_NOT, false); else XBIN_OP_RETURN (EXPR_NOT, false); } -"+" { - if (lexer_flags.plotting && ! lexer_flags.in_plot_range) - lexer_flags.past_plot_range = true; - BIN_OP_RETURN ('+', false); - } - -"-" { - if (lexer_flags.plotting && ! lexer_flags.in_plot_range) - lexer_flags.past_plot_range = true; - BIN_OP_RETURN ('-', false); - } - "(" { lexer_flags.looking_at_indirect_ref = false; - if (lexer_flags.plotting && ! lexer_flags.in_plot_range) - lexer_flags.past_plot_range = true; nesting_level.paren (); promptflag--; TOK_RETURN ('('); @@ -801,18 +739,14 @@ ")" { nesting_level.remove (); - current_input_column++; - lexer_flags.cant_be_identifier = true; lexer_flags.quote_is_transpose = true; lexer_flags.convert_spaces_to_comma = nesting_level.is_bracket_or_brace (); do_comma_insert_check (); COUNT_TOK_AND_RETURN (')'); } -"." { - TOK_RETURN ('.'); - } +"." { TOK_RETURN ('.'); } "+=" { XBIN_OP_RETURN (ADD_EQ, false); } "-=" { XBIN_OP_RETURN (SUB_EQ, false); } @@ -836,7 +770,6 @@ current_input_column += yyleng; lexer_flags.quote_is_transpose = false; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = true; promptflag--; @@ -1026,124 +959,6 @@ delete_buffer (static_cast<YY_BUFFER_STATE> (buf)); } -// Check to see if a character string matches any of the possible line -// styles for plots. - -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; -} - -// Check to see if a character string matches any of the possible axes -// tags for plots. - -static std::string -plot_axes_token (const std::string& s) -{ - std::string retval; - - // XXX FIXME XXX -- specify minimum match length for these. - static const char *plot_axes[] = - { - "x1y1", - "x1y2", - "x2y1", - "x2y2", - 0, - }; - - const char **tmp = plot_axes; - while (*tmp) - { - if (almost_match (*tmp, s.c_str ())) - { - retval = *tmp; - break; - } - - tmp++; - } - - return retval; -} - -// 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) -{ - const char *t = s.c_str (); - if (almost_match ("title", t, 1)) - { - return TITLE; - } - else if (almost_match ("using", t, 1)) - { - lexer_flags.in_plot_using = true; - return USING; - } - else if (almost_match ("with", t, 1)) - { - lexer_flags.in_plot_style = true; - return WITH; - } - else if (almost_match ("axes", t, 2) || almost_match ("axis", t, 2)) - { - lexer_flags.in_plot_axes = true; - return AXES; - } - else if (strcmp ("clear", t) == 0) - { - return CLEAR; - } - else - { - return 0; - } -} - static void prep_for_function (void) { @@ -1183,34 +998,6 @@ int l = input_line_number; int c = current_input_column; - if (lexer_flags.plotting) - { - if (lexer_flags.in_plot_style) - { - std::string sty = plot_style_token (s); - - if (! sty.empty ()) - { - lexer_flags.in_plot_style = false; - yylval.tok_val = new token (sty, l, c); - token_stack.push (yylval.tok_val); - return STYLE; - } - } - else if (lexer_flags.in_plot_axes) - { - std::string axes = plot_axes_token (s); - - if (! axes.empty ()) - { - lexer_flags.in_plot_axes = false; - yylval.tok_val = new token (axes, l, c); - token_stack.push (yylval.tok_val); - return AXES_TAG; - } - } - } - int len = s.length (); const octave_kw *kw = octave_kw_hash::in_word_set (s.c_str (), len); @@ -1311,21 +1098,6 @@ promptflag--; break; - case gplot_kw: - lexer_flags.plotting = true; - yylval.tok_val = new token (token::two_dee, l, c); - break; - - case gsplot_kw: - lexer_flags.plotting = true; - yylval.tok_val = new token (token::three_dee, l, c); - break; - - case replot_kw: - lexer_flags.plotting = true; - yylval.tok_val = new token (token::replot, l, c); - break; - case function_kw: { if (lexer_flags.defining_func) @@ -1969,12 +1741,8 @@ assert (nread == 1); lexer_flags.quote_is_transpose = true; - lexer_flags.cant_be_identifier = true; lexer_flags.convert_spaces_to_comma = true; - if (lexer_flags.plotting && ! lexer_flags.in_plot_range) - lexer_flags.past_plot_range = true; - yylval.tok_val = new token (value, yytext, input_line_number, current_input_column); @@ -2199,22 +1967,27 @@ { c = yyinput (); if (c == delim) - buf << static_cast<char> (c); + { + buf << static_cast<char> (c); + if (lexer_flags.doing_rawcommand) + buf << static_cast<char> (c); + } else { + std::string s; yyunput (c, yytext); buf << OSSTREAM_ENDS; - std::string s = do_string_escapes (OSSTREAM_STR (buf)); + if (lexer_flags.doing_rawcommand) + s = OSSTREAM_STR (buf); + else + s = do_string_escapes (OSSTREAM_STR(buf)); OSSTREAM_FREEZE (buf); - if (text_style && lexer_flags.doing_set) - { - s = std::string (1, delim) + s + std::string (1, delim); - } + if (text_style && lexer_flags.doing_rawcommand) + s = std::string (1, delim) + s + std::string (1, delim); else { lexer_flags.quote_is_transpose = true; - lexer_flags.cant_be_identifier = true; lexer_flags.convert_spaces_to_comma = true; } @@ -2394,7 +2167,6 @@ } lexer_flags.quote_is_transpose = true; - lexer_flags.cant_be_identifier = false; lexer_flags.convert_spaces_to_comma = true; return retval; @@ -2454,12 +2226,6 @@ int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); - // It is almost always an error for an identifier to be followed - // directly by another identifier. Special cases are handled - // below. - - lexer_flags.cant_be_identifier = true; - // If we are expecting a structure element, avoid recognizing // keywords and other special names and return STRUCT_ELT, which is // a string that is also a valid identifier. But first, we have to @@ -2476,7 +2242,6 @@ token_stack.push (yylval.tok_val); - lexer_flags.cant_be_identifier = false; lexer_flags.quote_is_transpose = true; lexer_flags.convert_spaces_to_comma = true; @@ -2499,7 +2264,7 @@ TOK_PUSH_AND_RETURN (tok, FCN_HANDLE); } - // If we have a regular keyword, or a plot STYLE, return it. + // If we have a regular keyword, return it. // Keywords can be followed by identifiers (TOK_RETURN handles // that). @@ -2507,40 +2272,12 @@ { if (kw_token < 0) return kw_token; - else if (kw_token == STYLE) - { - current_input_column += yyleng; - lexer_flags.quote_is_transpose = false; - lexer_flags.convert_spaces_to_comma = true; - return kw_token; - } else TOK_RETURN (kw_token); } // See if we have a plot keyword (title, using, with, or clear). - if (lexer_flags.plotting) - { - // Yes, we really do need both of these plot_range variables. - // One is used to mark when we are past all possiblity of a plot - // range, the other is used to mark when we are actually between - // the square brackets that surround the range. - - if (! lexer_flags.in_plot_range) - lexer_flags.past_plot_range = true; - - // Option keywords can't appear in brackets, braces, or parentheses. - - int plot_option_kw = 0; - - if (nesting_level.none ()) - plot_option_kw = is_plot_keyword (tok); - - if (lexer_flags.cant_be_identifier && plot_option_kw) - TOK_RETURN (plot_option_kw); - } - int c1 = yyinput (); bool next_tok_is_paren = (c1 == '('); @@ -2591,9 +2328,12 @@ } else if (! next_tok_is_paren) { - if (tok == "gset") - lexer_flags.doing_set = true; - + BEGIN (COMMAND_START); + } + + if (is_rawcommand_name (tok)) + { + lexer_flags.doing_rawcommand = true; BEGIN (COMMAND_START); } } @@ -2661,22 +2401,13 @@ // Not parsing an object index. looking_at_object_index = 0; - // Next token can be identifier. - cant_be_identifier = false; - // No need to do comma insert or convert spaces to comma at // beginning of input. convert_spaces_to_comma = true; do_comma_insert = false; // Not initially doing any plotting or setting of plot attributes. - doing_set = false; - in_plot_range = false; - in_plot_style = false; - in_plot_axes = false; - in_plot_using = false; - past_plot_range = false; - plotting = false; + doing_rawcommand = false; // Not initially looking at indirect references. looking_at_indirect_ref = false;
--- a/src/octave.cc +++ b/src/octave.cc @@ -63,7 +63,6 @@ #include "ops.h" #include "toplev.h" #include "parse.h" -#include "pt-plot.h" #include "procstream.h" #include "prog-args.h" #include "sighandlers.h"
--- a/src/octave.gperf +++ b/src/octave.gperf @@ -21,13 +21,10 @@ for_kw, function_kw, global_kw, - gplot_kw, - gsplot_kw, if_kw, magic_file_kw, magic_line_kw, otherwise_kw, - replot_kw, return_kw, static_kw, switch_kw, @@ -63,12 +60,9 @@ for, FOR, for_kw function, FCN, function_kw global, GLOBAL, global_kw -gplot, PLOT, gplot_kw -gsplot, PLOT, gsplot_kw if, IF, if_kw otherwise, OTHERWISE, otherwise_kw persistent, STATIC, static_kw -replot, PLOT, replot_kw return, FUNC_RET, return_kw static, STATIC, static_kw switch, SWITCH, switch_kw
--- a/src/parse.y +++ b/src/parse.y @@ -168,10 +168,6 @@ static void maybe_warn_variable_switch_label (tree_expression *expr); -// Create a plot command. -static tree_plot_command * -make_plot_command (token *tok, plot_limits *range, subplot_list *list); - // Finish building a range. static tree_expression * finish_colon_expression (tree_colon_expression *e); @@ -391,14 +387,6 @@ tree_decl_command *tree_decl_command_type; tree_statement *tree_statement_type; tree_statement_list *tree_statement_list_type; - tree_plot_command *tree_plot_command_type; - subplot *subplot_type; - subplot_list *subplot_list_type; - plot_limits *plot_limits_type; - plot_range *plot_range_type; - subplot_using *subplot_using_type; - subplot_style *subplot_style_type; - subplot_axes *subplot_axes_type; octave_user_function *octave_user_function_type; } @@ -417,8 +405,7 @@ %token <tok_val> STRUCT_ELT %token <tok_val> NAME %token <tok_val> END -%token <tok_val> PLOT -%token <tok_val> STRING STYLE AXES_TAG +%token <tok_val> STRING %token <tok_val> FOR WHILE DO UNTIL %token <tok_val> IF ELSEIF ELSE %token <tok_val> SWITCH CASE OTHERWISE @@ -441,7 +428,7 @@ %type <tree_fcn_handle_type> fcn_handle %type <tree_matrix_type> matrix_rows matrix_rows1 %type <tree_cell_type> cell_rows cell_rows1 -%type <tree_expression_type> title matrix cell +%type <tree_expression_type> matrix cell %type <tree_expression_type> primary_expr postfix_expr prefix_expr binary_expr %type <tree_expression_type> simple_expr colon_expr assign_expr expression %type <tree_identifier_type> identifier fcn_name @@ -466,14 +453,6 @@ %type <tree_statement_type> statement %type <tree_statement_list_type> simple_list simple_list1 list list1 %type <tree_statement_list_type> opt_list input1 function4 -%type <tree_plot_command_type> plot_command -%type <subplot_type> plot_command2 plot_options -%type <subplot_list_type> plot_command1 -%type <plot_limits_type> ranges -%type <plot_range_type> ranges1 -%type <subplot_using_type> using using1 -%type <subplot_style_type> style -%type <subplot_axes_type> axes // Precedence and associativity. %left ';' ',' '\n' @@ -585,16 +564,6 @@ $$ = new tree_statement ($1, comment); } - | PLOT CLEAR - { - symbol_record *sr = lookup_by_name ("clearplot", 0); - tree_identifier *id = new tree_identifier (sr); - - octave_comment_list *comment - = octave_comment_buffer::get_comment (); - - $$ = new tree_statement (id, comment); - } ; // =========== @@ -963,8 +932,6 @@ { $$ = $1; } | function { $$ = $1; } - | plot_command - { $$ = $1; } ; // ===================== @@ -1365,161 +1332,6 @@ } ; -// ======== -// Plotting -// ======== - -plot_command : PLOT - { - if (! ($$ = make_plot_command ($1, 0, 0))) - ABORT_PARSE; - } - | PLOT ranges - { - if (! ($$ = make_plot_command ($1, $2, 0))) - ABORT_PARSE; - } - | PLOT plot_command1 - { - if (! ($$ = make_plot_command ($1, 0, $2))) - ABORT_PARSE; - } - | PLOT ranges plot_command1 - { - if (! ($$ = make_plot_command ($1, $2, $3))) - ABORT_PARSE; - } - ; - -ranges : ranges1 - { $$ = new plot_limits ($1); } - | ranges1 ranges1 - { $$ = new plot_limits ($1, $2); } - | ranges1 ranges1 ranges1 - { $$ = new plot_limits ($1, $2, $3); } - ; - -ranges1 : OPEN_BRACE expression COLON expression CLOSE_BRACE - { $$ = new plot_range ($2, $4); } - | OPEN_BRACE COLON expression CLOSE_BRACE - { $$ = new plot_range (0, $3); } - | OPEN_BRACE expression COLON CLOSE_BRACE - { $$ = new plot_range ($2, 0); } - | OPEN_BRACE COLON CLOSE_BRACE - { $$ = new plot_range (); } - | OPEN_BRACE CLOSE_BRACE - { $$ = new plot_range (); } - ; - -plot_command1 : plot_command2 - { $$ = new subplot_list ($1); } - | plot_command1 ',' plot_command2 - { - $1->append ($3); - $$ = $1; - } - ; - -plot_command2 : expression - { $$ = new subplot ($1); } - | expression plot_options - { $$ = $2->add_data ($1); } - ; - -plot_options : using - { - subplot *tmp = new subplot (); - $$ = tmp->add_clause ($1); - } - | title - { - subplot *tmp = new subplot (); - $$ = tmp->add_clause ($1); - } - | style - { - subplot *tmp = new subplot (); - $$ = tmp->add_clause ($1); - } - | axes - { - subplot *tmp = new subplot (); - $$ = tmp->add_clause ($1); - } - | plot_options using - { - if (! ($$ = $1->add_clause ($2))) - { - yyerror ("only one using option may be specified"); - ABORT_PARSE; - } - } - | plot_options title - { - if (! ($$ = $1->add_clause ($2))) - { - yyerror ("only one title option my be specified"); - ABORT_PARSE; - } - } - | plot_options style - { - if (! ($$ = $1->add_clause ($2))) - { - yyerror ("only one style option my be specified"); - ABORT_PARSE; - } - } - | plot_options axes - { - if (! ($$ = $1->add_clause ($2))) - { - yyerror ("only one axes option may be specified"); - ABORT_PARSE; - } - } - ; - -axes : AXES AXES_TAG - { - lexer_flags.in_plot_axes = false; - $$ = new subplot_axes ($2->text ()); - } - ; - -using : using1 - { - lexer_flags.in_plot_using = false; - $$ = $1; - } - | using1 expression - { - lexer_flags.in_plot_using = false; - $$ = $1->set_format ($2); - } - ; - -using1 : USING expression - { - subplot_using *tmp = new subplot_using (); - $$ = tmp->add_qualifier ($2); - } - | using1 COLON expression - { $$ = $1->add_qualifier ($3); } - ; - -title : TITLE expression - { $$ = $2; } - ; - -style : WITH STYLE - { $$ = new subplot_style ($2->text ()); } - | WITH STYLE expression - { $$ = new subplot_style ($2->text (), $3); } - | WITH STYLE expression expression - { $$ = new subplot_style ($2->text (), $3, $4); } - ; - // ============= // Miscellaneous // ============= @@ -1744,34 +1556,6 @@ } } -// Create a plot command. - -static tree_plot_command * -make_plot_command (token *tok, plot_limits *range, subplot_list *list) -{ - if (range) - { - if (tok->pttype () == token::replot) - { - yyerror ("cannot specify new ranges with replot"); - return 0; - } - } - else if (! list && tok->pttype () != token::replot) - { - yyerror ("must have something to plot"); - return 0; - } - - lexer_flags.plotting = false; - lexer_flags.past_plot_range = false; - lexer_flags.in_plot_range = false; - lexer_flags.in_plot_using = false; - lexer_flags.in_plot_style = false; - - return new tree_plot_command (list, range, tok->pttype ()); -} - static tree_expression * fold (tree_binary_expression *e) {
--- a/src/pt-all.h +++ b/src/pt-all.h @@ -43,7 +43,6 @@ #include "pt-mat.h" #include "pt-cell.h" #include "pt-misc.h" -#include "pt-plot.h" #include "pt-pr-code.h" #include "pt-select.h" #include "pt-stmt.h"
--- a/src/pt-bp.cc +++ b/src/pt-bp.cc @@ -469,31 +469,6 @@ } } -void -tree_breakpoint::visit_plot_command (tree_plot_command& cmd) -{ - if (found) - return; - - // Don't bother looking at the range plot list since they must be - // on the same line. - - if (cmd.line () >= line) - take_action (cmd); -} - -void -tree_breakpoint::visit_plot_limits (plot_limits&) -{ - // Do nothing. This case will be handled in visit_tree_plot_command. -} - -void -tree_breakpoint::visit_plot_range (plot_range&) -{ - // Do nothing. This case will be handled in visit_tree_plot_command. -} - void tree_breakpoint::visit_postfix_expression (tree_postfix_expression& expr) { @@ -596,36 +571,6 @@ } } -void -tree_breakpoint::visit_subplot (subplot&) -{ - // Do nothing. This case will be handled in visit_tree_plot_command. -} - -void -tree_breakpoint::visit_subplot_axes (subplot_axes&) -{ - // Do nothing. This caser will be handled in visit_tree_plot_command. -} - -void -tree_breakpoint::visit_subplot_list (subplot_list&) -{ - // Do nothing. This case will be handled in visit_tree_plot_command. -} - -void -tree_breakpoint::visit_subplot_style (subplot_style&) -{ - // Do nothing. This case will be handled in visit_tree_plot_command. -} - -void -tree_breakpoint::visit_subplot_using (subplot_using&) -{ - // Do nothing. This case will be handled in visit_tree_plot_command. -} - void tree_breakpoint::visit_switch_case (tree_switch_case& cmd) {
--- a/src/pt-bp.h +++ b/src/pt-bp.h @@ -103,12 +103,6 @@ void visit_parameter_list (tree_parameter_list&); - void visit_plot_command (tree_plot_command&); - - void visit_plot_limits (plot_limits&); - - void visit_plot_range (plot_range&); - void visit_postfix_expression (tree_postfix_expression&); void visit_prefix_expression (tree_prefix_expression&); @@ -123,16 +117,6 @@ void visit_statement_list (tree_statement_list&); - void visit_subplot (subplot&); - - void visit_subplot_axes (subplot_axes&); - - void visit_subplot_list (subplot_list&); - - void visit_subplot_style (subplot_style&); - - void visit_subplot_using (subplot_using&); - void visit_switch_case (tree_switch_case&); void visit_switch_case_list (tree_switch_case_list&);
--- a/src/pt-check.cc +++ b/src/pt-check.cc @@ -333,53 +333,6 @@ } void -tree_checker::visit_plot_command (tree_plot_command& cmd) -{ - plot_limits *range = cmd.limits (); - - if (range) - range->accept (*this); - - subplot_list *plot_list = cmd.subplots (); - - if (plot_list) - plot_list->accept (*this); -} - -void -tree_checker::visit_plot_limits (plot_limits& cmd) -{ - plot_range *x_range = cmd.x_limits (); - - if (x_range) - x_range->accept (*this); - - plot_range *y_range = cmd.y_limits (); - - if (y_range) - y_range->accept (*this); - - plot_range *z_range = cmd.z_limits (); - - if (z_range) - z_range->accept (*this); -} - -void -tree_checker::visit_plot_range (plot_range& cmd) -{ - tree_expression *lower = cmd.lower_bound (); - - if (lower) - lower->accept (*this); - - tree_expression *upper = cmd.upper_bound (); - - if (upper) - upper->accept (*this); -} - -void tree_checker::visit_postfix_expression (tree_postfix_expression& expr) { tree_expression *e = expr.operand (); @@ -462,87 +415,6 @@ } void -tree_checker::visit_subplot (subplot& cmd) -{ - tree_expression *sp_plot_data = cmd.plot_data (); - - if (sp_plot_data) - sp_plot_data->accept (*this); - - subplot_using *sp_using_clause = cmd.using_clause (); - - if (sp_using_clause) - sp_using_clause->accept (*this); - - tree_expression *sp_title_clause = cmd.title_clause (); - - if (sp_title_clause) - sp_title_clause->accept (*this); - - subplot_style *sp_style_clause = cmd.style_clause (); - - if (sp_style_clause) - sp_style_clause->accept (*this); -} - -void -tree_checker::visit_subplot_axes (subplot_axes&) -{ -} - -void -tree_checker::visit_subplot_list (subplot_list& lst) -{ - subplot_list::iterator p = lst.begin (); - - while (p != lst.end ()) - { - subplot *elt = *p++; - - if (elt) - elt->accept (*this); - } -} - -void -tree_checker::visit_subplot_style (subplot_style& cmd) -{ - tree_expression *sp_linetype = cmd.linetype (); - - if (sp_linetype) - sp_linetype->accept (*this); - - tree_expression *sp_pointtype = cmd.pointtype (); - - if (sp_pointtype) - sp_pointtype->accept (*this); -} - -void -tree_checker::visit_subplot_using (subplot_using& cmd) -{ - int qual_count = cmd.qualifier_count (); - - if (qual_count > 0) - { - tree_expression **x = cmd.qualifiers (); - - for (int i = 0; i < qual_count; i++) - { - if (x[i]) - x[i]->accept (*this); - } - } - else - { - tree_expression *scanf_fmt = cmd.scanf_format (); - - if (scanf_fmt) - scanf_fmt->accept (*this); - } -} - -void tree_checker::visit_switch_case (tree_switch_case& cs) { tree_expression *label = cs.case_label ();
--- a/src/pt-check.h +++ b/src/pt-check.h @@ -87,12 +87,6 @@ void visit_parameter_list (tree_parameter_list&); - void visit_plot_command (tree_plot_command&); - - void visit_plot_limits (plot_limits&); - - void visit_plot_range (plot_range&); - void visit_postfix_expression (tree_postfix_expression&); void visit_prefix_expression (tree_prefix_expression&); @@ -107,16 +101,6 @@ void visit_statement_list (tree_statement_list&); - void visit_subplot (subplot&); - - void visit_subplot_axes (subplot_axes&); - - void visit_subplot_list (subplot_list&); - - void visit_subplot_style (subplot_style&); - - void visit_subplot_using (subplot_using&); - void visit_switch_case (tree_switch_case&); void visit_switch_case_list (tree_switch_case_list&);
deleted file mode 100644 --- a/src/pt-plot.cc +++ /dev/null @@ -1,1378 +0,0 @@ -/* - -Copyright (C) 1996, 1997 John W. Eaton - -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 Octave; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <cstring> - -#include <fstream> -#include <iostream> -#include <string> -#include <stack> - -#ifdef HAVE_UNISTD_H -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#include <unistd.h> -#endif - -#include "procstream.h" - -#include "file-ops.h" -#include "lo-mappers.h" -#include "str-vec.h" - -#include "defun.h" -#include "error.h" -#include "gripes.h" -#include "load-save.h" -#include "oct-obj.h" -#include "pt-cmd.h" -#include "pt-exp.h" -#include "pt-plot.h" -#include "pt-walk.h" -#include "sighandlers.h" -#include "sysdep.h" -#include "unwind-prot.h" -#include "utils.h" -#include "variables.h" - -// If TRUE, a replot command is issued automatically each time a plot -// changes in some way. -static bool Vautomatic_replot; - -// The name of the shell command to execute to start gnuplot. -static std::string Vgnuplot_binary; - -// TRUE if gnuplot appears to support multiple plot windows with X11. -static bool Vgnuplot_has_frames; - -// The number of lines we've plotted so far. -static int plot_line_count = 0; - -// Is this a parametric plot? Makes a difference for 3D plotting. -static bool parametric_plot = false; - -// The gnuplot terminal type. -static std::string gnuplot_terminal_type; - -// Should the graph window be cleared before plotting the next line? -static bool clear_before_plotting = true; - -// List of files to delete when we exit or crash. -// -// XXX FIXME XXX -- this should really be static, but that causes -// problems on some systems. -std::stack <std::string> tmp_files; - -// Pipe to gnuplot. -static oprocstream *plot_stream = 0; - -// ID of the plotter process. -static pid_t plot_stream_pid = 0; - -// 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; - -static void -plot_stream_death_handler (pid_t pid, int) -{ - close_plot_stream (); - - warning ("connection to external plotter (pid = %d) lost --", pid); - warning ("please try your plot command(s) again"); -} - -static void -open_plot_stream (void) -{ - static bool initialized = false; - - if (plot_stream && ! *plot_stream) - { - delete plot_stream; - plot_stream = 0; - } - - if (! plot_stream) - { - initialized = false; - - plot_line_count = 0; - - std::string plot_prog; - - if (Vgnuplot_binary.empty ()) - plot_prog = "gnuplot"; - else - plot_prog = "\"" + Vgnuplot_binary + "\""; - - // 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 set, oset; - sigemptyset (&set); - sigaddset (&set, SIGINT); - sigprocmask (SIG_BLOCK, &set, &oset); -#else - volatile octave_interrupt_handler old_interrupt_handler - = octave_ignore_interrupts (); -#endif - - plot_stream = new oprocstream (plot_prog.c_str ()); - - if (plot_stream) - { - if (! *plot_stream) - { - delete plot_stream; - plot_stream = 0; - - error ("plot: unable to open pipe to `%s'", plot_prog.c_str ()); - } - else - { - plot_stream_pid = plot_stream->pid (); - octave_child_list::insert (plot_stream_pid, - plot_stream_death_handler); - } - } - else - error ("plot: unable to open pipe to `%s'", plot_prog.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; - *plot_stream << "set data style lines\n"; - - if (! gnuplot_terminal_type.empty ()) - *plot_stream << "set term " << gnuplot_terminal_type - << Vgnuplot_command_end; - } -} - -static int -send_to_plot_stream (const std::string& cmd) -{ - if (! (plot_stream && *plot_stream)) - { - open_plot_stream (); - - if (error_state) - return -1; - } - - int replot_len = Vgnuplot_command_replot.length (); - int splot_len = Vgnuplot_command_splot.length (); - int plot_len = Vgnuplot_command_plot.length (); - - bool is_replot = (Vgnuplot_command_replot == cmd.substr (0, replot_len)); - bool is_splot = (Vgnuplot_command_splot == cmd.substr (0, splot_len)); - bool is_plot = (Vgnuplot_command_plot == cmd.substr (0, plot_len)); - - if (plot_line_count == 0 && is_replot) - error ("replot: no previous plot"); - else - { - *plot_stream << cmd; - - octave_value mm = get_global_value ("__multiplot_mode__", true); - - bool is_multiplot_mode = mm.is_true (); - - if (! (is_replot || is_splot || is_plot || is_multiplot_mode) - && plot_line_count > 0 - && Vautomatic_replot) - *plot_stream << Vgnuplot_command_replot << Vgnuplot_command_end; - - plot_stream->flush (); - } - - return 0; -} - -// Plotting, eh? - -tree_plot_command::~tree_plot_command (void) -{ - delete range; - delete plot_list; -} - -void -tree_plot_command::eval (void) -{ - if (error_state) - return; - - open_plot_stream (); - - OSSTREAM plot_buf; - - switch (ndim) - { - case 1: - if (plot_line_count == 0) - { - if (plot_list) - plot_buf << Vgnuplot_command_plot; - else - { - ::error ("replot: must have something to plot"); - return; - } - } - else - plot_buf << Vgnuplot_command_replot; - break; - - case 2: - if (clear_before_plotting || plot_line_count == 0) - { - plot_line_count = 0; - plot_buf << Vgnuplot_command_plot; - } - else - plot_buf << Vgnuplot_command_replot; - break; - - case 3: - if (clear_before_plotting || plot_line_count == 0) - { - plot_line_count = 0; - plot_buf << Vgnuplot_command_splot; - } - else - plot_buf << Vgnuplot_command_replot; - break; - - default: - gripe_2_or_3_dim_plot (); - return; - } - - if (range) - { - if (plot_line_count == 0) - range->print (ndim, plot_buf); - else - warning ("can't specify new plot ranges with `replot' or while\ - hold is on"); - } - - if (error_state) - return; - - if (plot_list) - { - int status = plot_list->print (ndim, plot_buf); - - if (error_state || status < 0) - return; - } - - plot_buf << Vgnuplot_command_end << OSSTREAM_ENDS; - - // Just testing... - // char *message = plot_buf.str (); - // std::cout << "[*]" << message << "[*]\n"; - - std::string message = OSSTREAM_STR (plot_buf); - - if (parametric_plot && ndim == 2) - { - warning ("can't make 2D parametric plot -- setting noparametric..."); - send_to_plot_stream ("set noparametric\n"); - send_to_plot_stream (message); - send_to_plot_stream ("set parametric\n"); - } - else - send_to_plot_stream (message); - - OSSTREAM_FREEZE (plot_buf); -} - -void -tree_plot_command::accept (tree_walker& tw) -{ - tw.visit_plot_command (*this); -} - -plot_limits::~plot_limits (void) -{ - delete x_range; - delete y_range; - delete z_range; -} - -void -plot_limits::print (int ndim, OSSTREAM& plot_buf) -{ - if (ndim == 2 || ndim == 3) - { - if (x_range) - x_range->print (plot_buf); - else - return; - - if (y_range) - y_range->print (plot_buf); - else - return; - } - - if (ndim == 3 && z_range) - z_range->print (plot_buf); -} - -void -plot_limits::accept (tree_walker& tw) -{ - tw.visit_plot_limits (*this); -} - -plot_range::~plot_range (void) -{ - delete lower; - delete upper; -} - -void -plot_range::print (OSSTREAM& plot_buf) -{ - plot_buf << " ["; - - if (lower) - { - octave_value lower_val = lower->rvalue (); - - if (error_state) - { - ::error ("evaluating lower bound of plot range"); - return; - } - else - { - double lo = lower_val.double_value (); - plot_buf << lo; - } - } - - plot_buf << ":"; - - if (upper) - { - octave_value upper_val = upper->rvalue (); - - if (error_state) - { - ::error ("evaluating upper bound of plot range"); - return; - } - else - { - double hi = upper_val.double_value (); - plot_buf << hi; - } - } - - plot_buf << "]"; -} - -void -plot_range::accept (tree_walker& tw) -{ - tw.visit_plot_range (*this); -} - -subplot_using::~subplot_using (void) -{ - delete scanf_fmt; -} - -int -subplot_using::eval (int ndim, int n_max) -{ - if ((ndim == 2 && qual_count > 4) - || (ndim == 3 && qual_count > 3)) - return -1; - - if (qual_count > 0) - val.resize (qual_count); - - for (int i = 0; i < qual_count; i++) - { - if (x[i]) - { - octave_value tmp = x[i]->rvalue (); - - if (error_state) - { - ::error ("evaluating plot using command"); - return -1; - } - - double val_tmp; - if (tmp.is_defined ()) - { - val_tmp = tmp.double_value (); - - if (error_state) - return -1; - - if (xisnan (val_tmp)) - { - ::error ("NaN is invalid as a column specifier"); - return -1; - } - - int n = NINT (val_tmp); - - if (n < 1 || n_max > 0 && n > n_max) - { - ::error ("using: column %d out of range", n); - return -1; - } - else - val (i) = n; - } - else - return -1; - } - else - return -1; - } - - if (scanf_fmt) - warning ("ignoring scanf format in plot command"); - - return 0; -} - -ColumnVector -subplot_using::values (int ndim, int n_max) -{ - int status = eval (ndim, n_max); - - // XXX FIXME XXX -- is the following really right? - if (status < 0) - return ColumnVector (1, -1.0); - - return val; -} - -int -subplot_using::print (int ndim, int n_max, OSSTREAM& plot_buf) -{ - int status = eval (ndim, n_max); - - if (status < 0) - return -1; - - for (int i = 0; i < qual_count; i++) - { - if (i == 0) - plot_buf << " " << Vgnuplot_command_using << " "; - else - plot_buf << ":"; - - plot_buf << val (i); - } - - return 0; -} - -void -subplot_using::accept (tree_walker& tw) -{ - tw.visit_subplot_using (*this); -} - -subplot_style::~subplot_style (void) -{ - delete sp_linetype; - delete sp_pointtype; -} - -int -subplot_style::print (OSSTREAM& plot_buf) -{ - if (! sp_style.empty ()) - { - plot_buf << " " << Vgnuplot_command_with << " " << sp_style; - - if (sp_linetype) - { - octave_value tmp = sp_linetype->rvalue (); - - if (! error_state && tmp.is_defined ()) - { - double val = tmp.double_value (); - if (xisnan (val)) - { - ::error ("NaN is invalid a plotting line style"); - return -1; - } - else - plot_buf << " " << NINT (val); - } - else - { - ::error ("evaluating plot style command"); - return -1; - } - } - - if (sp_pointtype) - { - octave_value tmp = sp_pointtype->rvalue (); - - if (! error_state && tmp.is_defined ()) - { - double val = tmp.double_value (); - if (xisnan (val)) - { - ::error ("NaN is invalid a plotting point style"); - return -1; - } - else - plot_buf << " " << NINT (val); - } - else - { - ::error ("evaluating plot style command"); - return -1; - } - } - } - else - return -1; - - return 0; -} - -bool -subplot_style::columns_ok (int nc) -{ - bool retval = true; - - if ((almost_match ("boxes", sp_style, 5, 0) - && (! (nc == 2 || nc == 3))) - || (almost_match ("boxerrorbars", sp_style, 5, 0) - && (! (nc == 3 || nc == 4 || nc == 5))) - || ((almost_match ("boxxyerrorbars", sp_style, 4, 0) - || almost_match ("xyerrorbars", sp_style, 2, 0)) - && (! (nc == 4 || nc == 6 || nc == 7))) - || ((almost_match ("candlesticks", sp_style, 1, 0) - || almost_match ("financebars", sp_style, 2, 0)) - && nc != 5) - || ((almost_match ("errorbars", sp_style, 1, 0) - || almost_match ("xerrorbars", sp_style, 1, 0) - || almost_match ("yerrorbars", sp_style, 1, 0)) - && (! (nc == 3 || nc == 4)))) - { - error - ("invalid number of data columns = %d specified for plot style `%s'", - nc, sp_style.c_str ()); - - retval = false; - } - - return retval; -} - -void -subplot_style::accept (tree_walker& tw) -{ - tw.visit_subplot_style (*this); -} - -int -subplot_axes::print (OSSTREAM& plot_buf) -{ - if (! sp_axes.empty ()) - plot_buf << " " << Vgnuplot_command_axes << " " << sp_axes; - - return 0; -} - -void -subplot_axes::accept (tree_walker& tw) -{ - tw.visit_subplot_axes (*this); -} - -subplot::~subplot (void) -{ - delete sp_plot_data; - delete sp_using_clause; - delete sp_title_clause; - delete sp_style_clause; - delete sp_axes_clause; -} - -octave_value -subplot::extract_plot_data (int ndim, octave_value& data) -{ - octave_value retval; - - if (sp_using_clause) - { - ColumnVector val = sp_using_clause->values (ndim); - - octave_value_list args; - - args(1) = val; - args(0) = octave_value::magic_colon_t; - - retval = data.single_subsref ("(", args); - - if (error_state) - return octave_value (); - } - else - { - retval = data; - } - - int nc = retval.columns (); - - if (ndim == 2 && sp_style_clause && ! sp_style_clause->columns_ok (nc)) - return octave_value (); - - return retval; -} - -int -subplot::handle_plot_data (int ndim, OSSTREAM& plot_buf) -{ - if (sp_plot_data) - { - octave_value data = sp_plot_data->rvalue (); - - if (! error_state && data.is_defined ()) - { - std::string file; - - if (data.is_string ()) - { - // Should really try to look at data file to determine - // n_max. Can't do much about other arbitrary gnuplot - // commands though... - - int n_max = 0; - - file = file_ops::tilde_expand (data.string_value ()); - - std::ifstream ftmp (file.c_str ()); - - if (ftmp) - { - plot_buf << " '" << file << "'"; - } - else - { - file = ""; - - // Opening as a file failed. Let's try passing it - // along as a plot command. - - plot_buf << " " << data.string_value (); - } - - if (sp_using_clause) - { - int status = sp_using_clause->print (ndim, n_max, plot_buf); - - if (status < 0) - return -1; - } - } - else - { - octave_value tmp_data = extract_plot_data (ndim, data); - - if (tmp_data.is_defined ()) - { - 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); - - // Include the using clause so that plotting - // with timefmt will work. - - plot_buf << " '" << file << "' " - << Vgnuplot_command_using - << (ndim == 2 ? " 1:2" : " 1:2:3"); - } - } - } - } - else - return -1; - } - else - return -1; - - return 0; -} - -int -subplot::print (int ndim, OSSTREAM& plot_buf) -{ - int status = handle_plot_data (ndim, plot_buf); - - if (status < 0) - return -1; - - if (sp_axes_clause) - { - status = sp_axes_clause->print (plot_buf); - - if (status < 0) - return -1; - } - - if (sp_title_clause) - { - octave_value tmp = sp_title_clause->rvalue (); - - if (! error_state && tmp.is_string ()) - plot_buf << " " << Vgnuplot_command_title << " " - << '"' << tmp.string_value () << '"'; - else - { - warning ("line title must be a string"); - plot_buf << " " << Vgnuplot_command_title << " " - << '"' << "line " << plot_line_count << '"'; - } - } - else - plot_buf << " " << Vgnuplot_command_title << " " - << '"' << "line " << plot_line_count << '"'; - - if (sp_style_clause) - { - status = sp_style_clause->print (plot_buf); - - if (status < 0) - return -1; - } - - return 0; -} - -void -subplot::accept (tree_walker& tw) -{ - tw.visit_subplot (*this); -} - -int -subplot_list::print (int ndim, OSSTREAM& plot_buf) -{ - int status = 0; - - for (iterator p = begin (); p != end (); p++) - { - subplot *elt = *p; - - plot_line_count++; - - if (p != begin ()) - plot_buf << ",\\\n "; - - status = elt->print (ndim, plot_buf); - - if (status < 0) - break; - } - - return status; -} - -void -subplot_list::accept (tree_walker& tw) -{ - tw.visit_subplot_list (*this); -} - -std::string -save_in_tmp_file (const octave_value& t, int ndim, bool parametric) -{ - 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; -} - -void -mark_for_deletion (const std::string& file) -{ - tmp_files.push (file); -} - -void -cleanup_tmp_files (void) -{ - while (! tmp_files.empty ()) - { - std::string filename = tmp_files.top (); - tmp_files.pop (); - unlink (filename.c_str ()); - } -} - -void -close_plot_stream (void) -{ - octave_child_list::remove (plot_stream_pid); - - if (plot_stream) - { - send_to_plot_stream ("\nquit\n"); - delete plot_stream; - plot_stream = 0; - } - - plot_line_count = 0; -} - -void -do_external_plotter_cd (const std::string& newdir) -{ - if (plot_stream && *plot_stream) - { - OSSTREAM plot_buf; - plot_buf << "cd '" << newdir << "'" << Vgnuplot_command_end - << OSSTREAM_ENDS; - send_to_plot_stream (OSSTREAM_STR (plot_buf)); - OSSTREAM_FREEZE (plot_buf); - } -} - -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\ -\n\ -The commands @kbd{gplot clear}, @kbd{gsplot clear}, and @kbd{replot\n\ -clear} are equivalent to @code{clearplot}. (Previously, commands like\n\ -@kbd{gplot clear} would evaluate @code{clear} as an ordinary expression\n\ -and clear all the visible variables.)\n\ -@end deftypefn") -{ - octave_value_list retval; - - // We are clearing the plot window, so there is no need to redisplay - // after each incremental change to the title, labels, etc. - - unwind_protect_bool (Vautomatic_replot); - - Vautomatic_replot = false; - - // XXX FIXME XXX -- instead of just clearing these things, it would - // be nice if we could reset things to a user-specified default - // state. - - send_to_plot_stream ("set title\n"); - send_to_plot_stream ("set xlabel\n"); - send_to_plot_stream ("set ylabel\n"); - send_to_plot_stream ("set nogrid\n"); - send_to_plot_stream ("set nolabel\n"); - - // Clear the plot display last. - - send_to_plot_stream ("clear\n"); - - // Setting plot_line_count to zero makes a simple `replot' not work - // after a `clearplot' command has been issued. - - plot_line_count = 0; - - unwind_protect::run (); - - return retval; -} - -DEFALIAS (clg, clearplot); - -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") -{ - octave_value_list retval; - close_plot_stream (); - return retval; -} - -DEFCMD (hold, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} hold @var{args}\n\ -Tell Octave to `hold' the current data on the plot when executing\n\ -subsequent plotting commands. This allows you to execute a series of\n\ -plot commands and have all the lines end up on the same figure. The\n\ -default is for each new plot command to clear the plot device first.\n\ -For example, the command\n\ -\n\ -@example\n\ -hold on\n\ -@end example\n\ -\n\ -@noindent\n\ -turns the hold state on. An argument of @code{off} turns the hold state\n\ -off, and @code{hold} with no arguments toggles the current hold state.\n\ -@end deftypefn") -{ - octave_value_list retval; - - int argc = args.length () + 1; - - string_vector argv = args.make_argv ("hold"); - - if (error_state) - return retval; - - switch (argc) - { - case 1: - clear_before_plotting = ! clear_before_plotting; - break; - - case 2: - if (argv[1] == "on") - clear_before_plotting = false; - else if (argv[1] == "off") - clear_before_plotting = true; - else - print_usage ("hold"); - break; - - default: - print_usage ("hold"); - break; - } - - return retval; -} - -DEFUN (ishold, , , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} ishold\n\ -Return 1 if the next line will be added to the current plot, or 0 if\n\ -the plot device will be cleared before drawing the next line.\n\ -@end deftypefn") -{ - return octave_value (! clear_before_plotting); -} - -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") -{ - octave_value_list retval; - cleanup_tmp_files (); - return retval; -} - - -DEFUN (graw, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} graw (@var{string})\n\ -Send @var{string} directly to gnuplot subprocess.\n\ -@end deftypefn") -{ - octave_value_list retval; - - if (args.length () == 1 && args(0).is_string ()) - { - std::string cmd = args(0).string_value (); - - if (! (plot_stream && *plot_stream)) - open_plot_stream (); - - if (! error_state) - { - *plot_stream << cmd; - - plot_stream->flush (); - } - } - else - print_usage ("graw"); - - return retval; -} - -DEFCMD (gset, args, , - "-*- texinfo -*-\n\ -@deffn {Command} gset options\n\ -Set plotting options for gnuplot\n\ -@end deffn") -{ - octave_value_list retval; - - int argc = args.length () + 1; - - string_vector argv = args.make_argv ("set"); - - if (error_state) - return retval; - - 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; - - send_to_plot_stream (OSSTREAM_STR (plot_buf)); - - OSSTREAM_FREEZE (plot_buf); - - return retval; -} - -DEFCMD (set, args, nargout, - "-*- texinfo -*-\n\ -This command is has been replaced by @code{gset}.") -{ - warning ("set is obsolete -- use gset instead"); - return Fgset (args, nargout); -} - -DEFCMD (gshow, args, , - "-*- texinfo -*-\n\ -@deffn {Command} gshow options\n\ -Show plotting options.\n\ -@end deffn") -{ - octave_value_list retval; - - int argc = args.length () + 1; - - string_vector argv = args.make_argv ("show"); - - if (error_state) - return retval; - - 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; - - send_to_plot_stream (OSSTREAM_STR (plot_buf)); - - OSSTREAM_FREEZE (plot_buf); - - return retval; -} - -DEFCMD (show, args, nargout, - "-*- texinfo -*-\n\ -This command is has been replaced by @code{gshow}.") -{ - warning ("show is obsolete -- use gshow instead"); - return Fgshow (args, nargout); -} - -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) -{ - return set_string_var (Vgnuplot_binary, "gnuplot_binary"); -} - -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_has_frames (void) -{ - Vgnuplot_has_frames = check_preference ("gnuplot_has_frames"); - - return 0; -} - -void -symbols_of_pt_plot (void) -{ - 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"); - - 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"); - - DEFVAR (gnuplot_command_plot, "pl", gnuplot_command_plot, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_plot\n\ -@end defvr"); - - DEFVAR (gnuplot_command_replot, "rep", gnuplot_command_replot, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_replot\n\ -@end defvr"); - - DEFVAR (gnuplot_command_splot, "sp", gnuplot_command_splot, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_splot\n\ -@end defvr"); - - DEFVAR (gnuplot_command_using, "u", gnuplot_command_using, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_using\n\ -@end defvr"); - - DEFVAR (gnuplot_command_with, "w", gnuplot_command_with, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_with\n\ -@end defvr"); - - DEFVAR (gnuplot_command_axes, "ax", gnuplot_command_axes, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_axes\n\ -@end defvr"); - - DEFVAR (gnuplot_command_title, "t", gnuplot_command_title, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_title\n\ -@end defvr"); - - DEFVAR (gnuplot_command_end, "\n", gnuplot_command_end, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_command_end\n\ -@end defvr"); - -#if defined (GNUPLOT_HAS_FRAMES) - bool with_frames = true; -#else - bool with_frames = false; -#endif - - DEFVAR (gnuplot_has_frames, with_frames, gnuplot_has_frames, - "-*- texinfo -*-\n\ -@defvr {Built-in Variable} gnuplot_has_frames\n\ -If the value of this variable is nonzero, Octave assumes that your copy\n\ -of gnuplot has support for multiple frames that is included in recent\n\ -3.6beta releases. Its initial value is determined by configure, but it\n\ -can be changed in your startup script or at the command line in case\n\ -configure got it wrong, or if you upgrade your gnuplot installation.\n\ -@end defvr"); -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/
deleted file mode 100644 --- a/src/pt-plot.h +++ /dev/null @@ -1,446 +0,0 @@ -/* - -Copyright (C) 1996, 1997 John W. Eaton - -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 Octave; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#if !defined (octave_tree_plot_h) -#define octave_tree_plot_h 1 - -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma interface -#endif - -#include <iostream> - -#include "lo-sstream.h" - -class tree_expression; -class tree_plot_command; -class plot_limits; -class plot_range; -class subplot_using; -class subplot_style; -class subplot_axes; -class subplot; -class subplot_list; - -class tree_walker; - -#include <string> - -#include "dColVector.h" - -#include "base-list.h" -#include "pt-cmd.h" - -class -tree_plot_command : public tree_command -{ -public: - - tree_plot_command (subplot_list *plt = 0, plot_limits *rng = 0, int nd = 0) - : tree_command (), ndim (nd), range (rng), plot_list (plt) { } - - ~tree_plot_command (void); - - void eval (void); - - int num_dimensions (void) { return ndim; } - - plot_limits *limits (void) { return range; } - - subplot_list *subplots (void) { return plot_list; } - - void accept (tree_walker& tw); - -private: - - // The number of dimensions. 1 indicates a replot command. - int ndim; - - // The data ranges for the plot. - plot_limits *range; - - // The list of plots for this plot command. For example, the - // command "plot sin(x), cos(x)" has two subplot commands. - subplot_list *plot_list; - - // No copying! - - tree_plot_command (const tree_plot_command&); - - tree_plot_command& operator = (const tree_plot_command&); -}; - -class -plot_limits -{ -public: - - plot_limits (plot_range *xlim = 0, plot_range *ylim = 0, - plot_range *zlim = 0) - : x_range (xlim), y_range (ylim), z_range (zlim) { } - - ~plot_limits (void); - - void print (int ndim, OSSTREAM& plot_buf); - - plot_range *x_limits (void) { return x_range; } - plot_range *y_limits (void) { return y_range; } - plot_range *z_limits (void) { return z_range; } - - void accept (tree_walker& tw); - -private: - - // Specified limits of the x, y, and z axes we should display for - // this plot. - plot_range *x_range; - plot_range *y_range; - plot_range *z_range; - - // No copying! - - plot_limits (const plot_limits&); - - plot_limits& operator = (const plot_limits&); -}; - -class -plot_range -{ -public: - - plot_range (tree_expression *l = 0, tree_expression *u = 0) - : lower (l), upper (u) { } - - ~plot_range (void); - - void print (OSSTREAM& plot_buf); - - tree_expression *lower_bound (void) { return lower; } - - tree_expression *upper_bound (void) { return upper; } - - void accept (tree_walker& tw); - -private: - - // A range can specify a lower or upper bound or both. If neither - // is specified, the range to display is determined from the data. - tree_expression *lower; - tree_expression *upper; - - // No copying! - - plot_range (const plot_range&); - - plot_range& operator = (const plot_range&); -}; - -class -subplot_using -{ -public: - - subplot_using (tree_expression *fmt = 0) - : qual_count (0), scanf_fmt (fmt), val (4, -1) - { - x[0] = x[1] = x[2] = x[3] = 0; - } - - ~subplot_using (void); - - subplot_using *set_format (tree_expression *fmt) - { - scanf_fmt = fmt; - return this; - } - - subplot_using *add_qualifier (tree_expression *t) - { - if (qual_count < 4) - x[qual_count] = t; - - qual_count++; - - return this; - } - - int eval (int ndim, int n_max); - - ColumnVector values (int ndim, int n_max = 0); - - int print (int ndim, int n_max, OSSTREAM& plot_buf); - - int qualifier_count (void) { return qual_count; } - - tree_expression **qualifiers (void) { return x; } - - tree_expression *scanf_format (void) { return scanf_fmt; } - - void accept (tree_walker& tw); - -private: - - // The number of using qualifiers (in "using 1:2", 1 and 2 are the - // qualifiers). - int qual_count; - - // An optional scanf-style format. This is parsed and stored but - // not currently used. - tree_expression *scanf_fmt; - - // This is a cache for evaluated versions of the qualifiers stored - // in x. - ColumnVector val; - - // A vector to hold using qualifiers. - tree_expression *x[4]; - - // No copying! - - subplot_using (const subplot_using&); - - subplot_using& operator = (const subplot_using&); -}; - -class -subplot_style -{ -public: - - subplot_style (const std::string& s = std::string (), - tree_expression *lt = 0, tree_expression *pt = 0) - : sp_style (s), sp_linetype (lt), sp_pointtype (pt) { } - - ~subplot_style (void); - - int print (OSSTREAM& plot_buf); - - bool columns_ok (int nc); - - std::string style (void) { return sp_style; } - - tree_expression *linetype (void) { return sp_linetype; } - - tree_expression *pointtype (void) { return sp_pointtype; } - - void accept (tree_walker& tw); - -private: - - // The style we are using: `lines', `points', etc. - std::string sp_style; - - // The number of the line type to use. - tree_expression *sp_linetype; - - // The number of the point type to use. - tree_expression *sp_pointtype; - - // No copying! - - subplot_style (const subplot_style&); - - subplot_style& operator = (const subplot_style&); -}; - -class -subplot_axes -{ -public: - - subplot_axes (const std::string& s = std::string ()) - : sp_axes (s) { } - - ~subplot_axes (void) { } - - int print (OSSTREAM& plot_buf); - - std::string axes (void) { return sp_axes; } - - void accept (tree_walker& tw); - -private: - - // The axes we are using: `x1y1', `x1y2', etc. - std::string sp_axes; - - // No copying! - - subplot_axes (const subplot_axes&); - - subplot_axes& operator = (const subplot_axes&); -}; - -class -subplot -{ -public: - - subplot (tree_expression *data = 0) - : sp_plot_data (data), sp_using_clause (0), sp_title_clause (0), - sp_style_clause (0), sp_axes_clause (0) { } - - ~subplot (void); - - subplot *add_data (tree_expression *data) - { - sp_plot_data = data; - return this; - } - - subplot *add_clause (subplot_using *u) - { - if (! sp_using_clause) - { - sp_using_clause = u; - return this; - } - else - return 0; - } - - subplot *add_clause (tree_expression *t) - { - if (! sp_title_clause) - { - sp_title_clause = t; - return this; - } - else - return 0; - } - - subplot *add_clause (subplot_style *s) - { - if (! sp_style_clause) - { - sp_style_clause = s; - return this; - } - else - return 0; - } - - subplot *add_clause (subplot_axes *a) - { - if (! sp_axes_clause) - { - sp_axes_clause = a; - return this; - } - else - return 0; - } - - octave_value extract_plot_data (int ndim, octave_value& data); - - int handle_plot_data (int ndim, OSSTREAM& plot_buf); - - int print (int ndim, OSSTREAM& plot_buf); - - tree_expression *plot_data (void) { return sp_plot_data; } - - subplot_using *using_clause (void) { return sp_using_clause; } - - tree_expression *title_clause (void) { return sp_title_clause; } - - subplot_style *style_clause (void) { return sp_style_clause; } - - subplot_axes *axes_clause (void) { return sp_axes_clause; } - - void accept (tree_walker& tw); - -private: - - // The data to plot. - tree_expression *sp_plot_data; - - // The `using' option - subplot_using *sp_using_clause; - - // The `title' option - tree_expression *sp_title_clause; - - // The `style' option - subplot_style *sp_style_clause; - - // The `axes' option - subplot_axes *sp_axes_clause; - - // No copying! - - subplot (const subplot&); - - subplot& operator = (const subplot&); -}; - -class -subplot_list : public octave_base_list<subplot *> -{ -public: - - subplot_list (void) { } - - subplot_list (subplot *t) { append (t); } - - ~subplot_list (void) - { - while (! empty ()) - { - iterator p = begin (); - delete *p; - erase (p); - } - } - - int print (int ndim, OSSTREAM& plot_buf); - - void accept (tree_walker& tw); - -private: - - // No copying! - - subplot_list (const subplot_list&); - - subplot_list& operator = (const subplot_list&); -}; - -extern std::string save_in_tmp_file (const octave_value& t, int ndim = 2, - bool parametric = false); - -extern void mark_for_deletion (const std::string&); - -extern void cleanup_tmp_files (void); - -extern void close_plot_stream (void); - -extern void do_external_plotter_cd (const std::string& newdir); - -#endif - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/
--- a/src/pt-pr-code.cc +++ b/src/pt-pr-code.cc @@ -713,82 +713,6 @@ } void -tree_print_code::visit_plot_command (tree_plot_command& cmd) -{ - indent (); - - int ndim = cmd.num_dimensions (); - - switch (ndim) - { - case 1: - os << "replot"; - break; - - case 2: - os << "gplot"; - break; - - case 3: - os << "gsplot"; - break; - - default: - os << "<unkown plot command>"; - break; - } - - plot_limits *range = cmd.limits (); - - if (range) - range->accept (*this); - - subplot_list *plot_list = cmd.subplots (); - - if (plot_list) - plot_list->accept (*this); -} - -void -tree_print_code::visit_plot_limits (plot_limits& cmd) -{ - plot_range *x_range = cmd.x_limits (); - - if (x_range) - x_range->accept (*this); - - plot_range *y_range = cmd.y_limits (); - - if (y_range) - y_range->accept (*this); - - plot_range *z_range = cmd.z_limits (); - - if (z_range) - z_range->accept (*this); -} - -void -tree_print_code::visit_plot_range (plot_range& cmd) -{ - os << " ["; - - tree_expression *lower = cmd.lower_bound (); - - if (lower) - lower->accept (*this); - - os << ":"; - - tree_expression *upper = cmd.upper_bound (); - - if (upper) - upper->accept (*this); - - os << "]"; -} - -void tree_print_code::visit_postfix_expression (tree_postfix_expression& expr) { indent (); @@ -922,117 +846,6 @@ } void -tree_print_code::visit_subplot (subplot& cmd) -{ - tree_expression *sp_plot_data = cmd.plot_data (); - - if (sp_plot_data) - { - os << " "; - - sp_plot_data->accept (*this); - } - - subplot_axes *sp_axes_clause = cmd.axes_clause (); - - if (sp_axes_clause) - sp_axes_clause->accept (*this); - - subplot_using *sp_using_clause = cmd.using_clause (); - - if (sp_using_clause) - sp_using_clause->accept (*this); - - tree_expression *sp_title_clause = cmd.title_clause (); - - if (sp_title_clause) - sp_title_clause->accept (*this); - - subplot_style *sp_style_clause = cmd.style_clause (); - - if (sp_style_clause) - sp_style_clause->accept (*this); -} - -void -tree_print_code::visit_subplot_axes (subplot_axes& cmd) -{ - os << " axes " << cmd.axes (); -} - -void -tree_print_code::visit_subplot_list (subplot_list& lst) -{ - subplot_list::iterator p = lst.begin (); - - while (p != lst.end ()) - { - subplot *elt = *p++; - - if (elt) - { - elt->accept (*this); - - if (p != lst.end ()) - os << ","; - } - } -} - -void -tree_print_code::visit_subplot_style (subplot_style& cmd) -{ - os << " with " << cmd.style (); - - tree_expression *sp_linetype = cmd.linetype (); - - if (sp_linetype) - { - os << " "; - - sp_linetype->accept (*this); - } - - tree_expression *sp_pointtype = cmd.pointtype (); - - if (sp_pointtype) - { - os << " "; - - sp_pointtype->accept (*this); - } -} - -void -tree_print_code::visit_subplot_using (subplot_using& cmd) -{ - os << " using "; - - int qual_count = cmd.qualifier_count (); - - if (qual_count > 0) - { - tree_expression **x = cmd.qualifiers (); - - for (int i = 0; i < qual_count; i++) - { - if (i > 0) - os << ":"; - - if (x[i]) - x[i]->accept (*this); - } - } - else - { - tree_expression *scanf_fmt = cmd.scanf_format (); - - if (scanf_fmt) - scanf_fmt->accept (*this); - } -} - -void tree_print_code::visit_switch_case (tree_switch_case& cs) { print_comment_list (cs.leading_comment ());
--- a/src/pt-pr-code.h +++ b/src/pt-pr-code.h @@ -106,12 +106,6 @@ void visit_parameter_list (tree_parameter_list&); - void visit_plot_command (tree_plot_command&); - - void visit_plot_limits (plot_limits&); - - void visit_plot_range (plot_range&); - void visit_postfix_expression (tree_postfix_expression&); void visit_prefix_expression (tree_prefix_expression&); @@ -126,16 +120,6 @@ void visit_statement_list (tree_statement_list&); - void visit_subplot (subplot&); - - void visit_subplot_axes (subplot_axes&); - - void visit_subplot_list (subplot_list&); - - void visit_subplot_style (subplot_style&); - - void visit_subplot_using (subplot_using&); - void visit_switch_case (tree_switch_case&); void visit_switch_case_list (tree_switch_case_list&);
--- a/src/pt-walk.h +++ b/src/pt-walk.h @@ -49,9 +49,6 @@ class tree_constant; class tree_fcn_handle; class tree_parameter_list; -class tree_plot_command; -class plot_limits; -class plot_range; class tree_postfix_expression; class tree_prefix_expression; class tree_return_command; @@ -59,11 +56,6 @@ class tree_simple_assignment; class tree_statement; class tree_statement_list; -class subplot; -class subplot_axes; -class subplot_list; -class subplot_style; -class subplot_using; class tree_try_catch_command; class tree_unwind_protect_command; class tree_while_command; @@ -153,15 +145,6 @@ visit_parameter_list (tree_parameter_list&) = 0; virtual void - visit_plot_command (tree_plot_command&) = 0; - - virtual void - visit_plot_limits (plot_limits&) = 0; - - virtual void - visit_plot_range (plot_range&) = 0; - - virtual void visit_postfix_expression (tree_postfix_expression&) = 0; virtual void @@ -183,21 +166,6 @@ visit_statement_list (tree_statement_list&) = 0; virtual void - visit_subplot (subplot&) = 0; - - virtual void - visit_subplot_axes (subplot_axes&) = 0; - - virtual void - visit_subplot_list (subplot_list&) = 0; - - virtual void - visit_subplot_style (subplot_style&) = 0; - - virtual void - visit_subplot_using (subplot_using&) = 0; - - virtual void visit_try_catch_command (tree_try_catch_command&) = 0; virtual void
--- a/src/symtab.h +++ b/src/symtab.h @@ -76,9 +76,10 @@ DLD_FUNCTION = 4, BUILTIN_FUNCTION = 8, COMMAND = 16, - MAPPER_FUNCTION = 32, - BUILTIN_VARIABLE = 64, - BUILTIN_CONSTANT = 128 + RAWCOMMAND = 32, + MAPPER_FUNCTION = 64, + BUILTIN_VARIABLE = 128, + BUILTIN_CONSTANT = 256 }; private: @@ -128,6 +129,16 @@ bool is_command (void) const { return (symbol_type & symbol_record::COMMAND); } + void mark_as_rawcommand (void) + { symbol_type |= (symbol_record::COMMAND + | symbol_record::RAWCOMMAND); } + + void unmark_rawcommand (void) + { symbol_type &= ~symbol_record::RAWCOMMAND; } + + bool is_rawcommand (void) const + { return (symbol_type & symbol_record::RAWCOMMAND); } + bool is_mapper_function (void) const { return (symbol_type & symbol_record::MAPPER_FUNCTION); } @@ -214,7 +225,7 @@ static octave_allocator allocator; // The type of this symbol (see the enum above). - unsigned int symbol_type : 8; + unsigned int symbol_type : 9; // Nonzero means this variable cannot be cleared. unsigned int eternal : 1; @@ -284,6 +295,15 @@ bool is_command (void) const { return definition->is_command (); } + void mark_as_rawcommand (void) + { definition->mark_as_rawcommand (); } + + void unmark_rawcommand (void) + { definition->unmark_rawcommand (); } + + bool is_rawcommand (void) const + { return definition->is_rawcommand (); } + bool is_mapper_function (void) const { return definition->is_mapper_function (); } @@ -443,6 +463,7 @@ | symbol_record::DLD_FUNCTION \ | symbol_record::BUILTIN_FUNCTION \ | symbol_record::COMMAND \ + | symbol_record::RAWCOMMAND \ | symbol_record::MAPPER_FUNCTION \ | symbol_record::BUILTIN_VARIABLE \ | symbol_record::BUILTIN_CONSTANT)
--- a/src/toplev.cc +++ b/src/toplev.cc @@ -66,7 +66,6 @@ #include "procstream.h" #include "ov.h" #include "pt-jump.h" -#include "pt-plot.h" #include "pt-stmt.h" #include "sighandlers.h" #include "sysdep.h" @@ -559,8 +558,6 @@ command_history::clean_up_and_save (); - close_plot_stream (); - close_files (); cleanup_tmp_files ();
--- a/src/variables.cc +++ b/src/variables.cc @@ -144,7 +144,8 @@ "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} mark_as_command (@var{name})\n\ Enter @var{name} into the list of commands.\n\ -@end deftypefn") +@end deftypefn\n\ +@seealso{unmark_command, iscommand}") { octave_value_list retval; @@ -175,9 +176,10 @@ DEFCMD (unmark_command, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} mark_as_command (@var{name})\n\ +@deftypefn {Built-in Function} {} unmark_command (@var{name})\n\ Remove @var{name} from the list of commands.\n\ -@end deftypefn") +@end deftypefn\n\ +@seealso{mark_as_command, iscommand}") { octave_value_list retval; @@ -229,6 +231,215 @@ return retval; } +DEFCMD (iscommand, args, , +"-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} iscommand (@var{name})\n\ +Return true if @var{name} is a command style function. If @var{name}\n\ +is omitted, return a list of identifiers which are marked as commands with\n\ +mark_as_command.\n\ +@end deftypefn\n\ +@seealso{mark_as_command, unmark_command}") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin == 0) + { + string_vector lst (command_set.size ()); + + int i = 0; + for (std::set<std::string>::const_iterator p = command_set.begin (); + p != command_set.end (); p++) + lst[i++] = *p; + + retval = Cell (lst.qsort ()); + } + else if (nargin == 1) + { + string_vector argv = args.make_argv ("iscommand"); + + if (! error_state) + { + std::string s = argv[1]; + retval = is_command_name(s); + } + } + else + print_usage ("iscommand"); + + return retval; +} + +// Is this a raw input command? + +static std::set <std::string> rawcommand_set; + +static inline bool +is_marked_as_rawcommand (const std::string& s) +{ + return rawcommand_set.find (s) != rawcommand_set.end (); +} + +static inline void +mark_as_rawcommand (const std::string& s) +{ + command_set.insert (s); + rawcommand_set.insert (s); +} + +static inline void +unmark_rawcommand (const std::string& s) +{ + rawcommand_set.erase (s); + + symbol_record *sr = fbi_sym_tab->lookup (s); + + if (sr) + sr->unmark_rawcommand (); +} + +DEFCMD (mark_as_rawcommand, args, , +"-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} mark_as_rawcommand (@var{name})\n\ +Enter @var{name} into the list of raw input commands and to the list of\n\ +command style functions.\n\ +Raw input commands are like normal command style functions, but they\n\ +receive their input unprocessed (ie. strings still contain the quotes\n\ +and escapes they had when input). However, comments and continuations\n\ +are handled as usual, you cannot pass a token starting with a comment\n\ +character ('#' or '%') to your function, and the last token cannot be\n\ +a continuation token ('\\' or '...').\n\ +@end deftypefn\n\ +@seealso{unmark_rawcommand, israwcommand, iscommand, mark_as_command}") +{ + octave_value_list retval; + + if (at_top_level ()) + { + int nargin = args.length (); + + if (nargin > 0) + { + int argc = nargin + 1; + + string_vector argv = args.make_argv ("mark_as_rawcommand"); + + if (! error_state) + { + for (int i = 1; i < argc; i++) + mark_as_rawcommand (argv[i]); + } + } + else + print_usage ("mark_as_rawcommand"); + } + else + warning ("mark_as_rawcommand: invalid use inside function body"); + + return retval; +} + +DEFCMD (unmark_rawcommand, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} unmark_rawcommand (@var{name})\n\ +Remove @var{name} from the list of raw input commands.\n\ +Note that this does not remove @var{name} from the list of command style\n\ +functions.\n\ +@end deftypefn\n\ +@seealso{mark_as_rawcommand, israwcommand, iscommand, unmark_command}") +{ + octave_value_list retval; + + if (at_top_level ()) + { + int nargin = args.length (); + + if (nargin > 0) + { + int argc = nargin + 1; + + string_vector argv = args.make_argv ("unmark_rawcommand"); + + if (! error_state) + { + for (int i = 1; i < argc; i++) + unmark_rawcommand (argv[i]); + } + } + else + print_usage ("unmark_rawcommand"); + } + else + warning ("unmark_rawcommand: invalid use inside function body"); + + return retval; +} + +bool +is_rawcommand_name (const std::string& s) +{ + bool retval = false; + + symbol_record *sr = fbi_sym_tab->lookup (s); + + if (sr) + { + if (sr->is_rawcommand ()) + retval = true; + else if (is_marked_as_rawcommand (s)) + { + sr->mark_as_rawcommand (); + retval = true; + } + } + else + retval = is_marked_as_rawcommand (s); + + return retval; +} + +DEFCMD (israwcommand, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} israwcommand (@var{name})\n\ +Return true if @var{name} is a raw input command function.\n\ +If @var{name} is omitted, return a list of identifiers which are marked as\n\ +raw input commands with mark_as_rawcommand.\n\ +@end deftypefn\n\ +@seealso{mark_as_rawcommand, unmark_rawcommand}") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin == 0) + { + string_vector lst (rawcommand_set.size()); + + int i = 0; + for (std::set<std::string>::const_iterator p = rawcommand_set.begin (); + p != rawcommand_set.end (); + p++) + lst[i++] = *p; + + retval = Cell (lst.qsort ()); + } + else if (nargin == 1) + { + string_vector argv = args.make_argv ("israwcommand"); + + if (! error_state) + { + std::string s = argv[1]; + retval = is_rawcommand_name(s); + } + } + else + print_usage ("israwcommand"); + + return retval; +} + // Is this a built-in function? bool
--- a/src/variables.h +++ b/src/variables.h @@ -47,6 +47,7 @@ extern bool is_builtin_variable (const std::string&); extern bool is_command_name (const std::string&); +extern bool is_rawcommand_name (const std::string&); extern bool is_mapper_function_name (const std::string&); extern bool is_builtin_function_name (const std::string&); extern bool is_globally_visible (const std::string&);