Mercurial > hg > octave-lojdl
changeset 581:bc813f5eb025
[project @ 1994-08-07 01:02:15 by jwe]
author | jwe |
---|---|
date | Sun, 07 Aug 1994 01:02:15 +0000 |
parents | b0204e676508 |
children | 129f0b19ab48 |
files | src/error.cc src/help.cc src/input.cc src/lex.l src/oct-hist.cc src/octave.cc src/pager.cc src/pager.h src/parse.y src/pt-base.h src/pt-cmd.cc src/pt-cmd.h src/pt-const.cc src/pt-const.h src/pt-exp-base.cc src/pt-exp-base.h src/pt-misc.cc src/pt-misc.h src/pt-plot.cc src/pt-plot.h src/tc-inlines.h src/tc-rep.cc src/tc-rep.h src/token.cc src/token.h src/utils.cc src/variables.cc src/variables.h |
diffstat | 28 files changed, 2926 insertions(+), 1678 deletions(-) [+] |
line wrap: on
line diff
--- a/src/error.cc +++ b/src/error.cc @@ -25,8 +25,7 @@ #include "config.h" #endif -#include <stdio.h> -#include <stdlib.h> +#include <strstream.h> #include <stdarg.h> #include "utils.h" @@ -42,12 +41,21 @@ static void verror (const char *name, const char *fmt, va_list args) { - if (name) - fprintf (stderr, "%s: ", name); + cerr << name << ": "; + cerr.vform (fmt, args); + cerr << endl; + + ostrstream output_buf; - vfprintf (stderr, fmt, args); - fprintf (stderr, "\n"); - fflush (stderr); + output_buf << name << ": "; + output_buf.vform (fmt, args); + output_buf << endl; + + char *msg = output_buf.str (); + + maybe_write_to_diary_file (msg); + + delete [] msg; } void
--- a/src/help.cc +++ b/src/help.cc @@ -30,7 +30,8 @@ #include <iostream.h> #include <strstream.h> -#include "tree.h" +#include "tree-expr.h" +#include "tree-const.h" #include "sighandlers.h" #include "user-prefs.h" #include "tree-expr.h" @@ -249,9 +250,8 @@ { 0, 0, }, }; -/* - * Return a copy of the operator or keyword names. - */ +// Return a copy of the operator or keyword names. + char ** names (help_list *lst, int& count) { @@ -556,8 +556,6 @@ { ostrstream output_buf; - char *fcn_file_name = 0; - symbol_record *sym_rec; help_list *op_help_list = operator_help (); help_list *kw_help_list = keyword_help (); @@ -574,7 +572,8 @@ if (help_from_list (output_buf, kw_help_list, *argv, 0)) continue; - sym_rec = curr_sym_tab->lookup (*argv, 0, 0); + symbol_record *sym_rec = lookup_by_name (*argv); + if (sym_rec) { char *h = sym_rec->help (); @@ -586,43 +585,8 @@ } } - sym_rec = global_sym_tab->lookup (*argv, 0, 0); - if (sym_rec && ! symbol_out_of_date (sym_rec)) - { - char *h = sym_rec->help (); - if (h && *h) - { - output_buf << "\n*** " << *argv << ":\n\n" - << h << "\n"; - continue; - } - } - -// Try harder to find function files that might not be defined yet, or -// that appear to be out of date. Don\'t execute commands from the -// file if it turns out to be a script file. - - fcn_file_name = fcn_file_in_path (*argv); - if (fcn_file_name) - { - sym_rec = global_sym_tab->lookup (*argv, 1, 0); - if (sym_rec) - { - tree_identifier tmp (sym_rec); - tmp.load_fcn_from_file (0); - char *h = sym_rec->help (); - if (h && *h) - { - output_buf << "\n*** " << *argv << ":\n\n" - << h << "\n"; - continue; - } - } - } - delete [] fcn_file_name; - output_buf << "\nhelp: sorry, `" << *argv - << "' is not documented\n"; + << "' is not documented\n"; } additional_help_message (output_buf); @@ -636,6 +600,193 @@ return retval; } +DEFUN_TEXT ("type", Ftype, Stype, -1, 1, + "type NAME ...]\n\ +\n\ +display the definition of each NAME that refers to a function") +{ + Octave_object retval; + + DEFINE_ARGV("type"); + + if (argc > 1) + { +// XXX FIXME XXX -- we should really use getopt () + int quiet = 0; + if (argv[1] && strcmp (argv[1], "-q") == 0) + { + quiet = 1; + argc--; + argv++; + } + + ostrstream output_buf; + + while (--argc > 0) + { + argv++; + + if (! *argv || ! **argv) + continue; + + symbol_record *sym_rec = lookup_by_name (*argv); + + if (sym_rec) + { + if (sym_rec->is_user_function ()) + { + tree_fvc *defn = sym_rec->def (); + + if (nargout == 0 && ! quiet) + output_buf << *argv << " is a user-defined function\n"; + + defn->print_code (output_buf); + } + +// XXX FIXME XXX -- this code should be shared with Fwhich + + else if (sym_rec->is_text_function ()) + output_buf << *argv << " is a builtin text-function\n"; + else if (sym_rec->is_builtin_function ()) + output_buf << *argv << " is a builtin function\n"; + else if (sym_rec->is_user_variable ()) + output_buf << *argv << " is a user-defined variable\n"; + else if (sym_rec->is_builtin_variable ()) + output_buf << *argv << " is a builtin variable\n"; + else + output_buf << "type: `" << *argv << "' has unknown type!\n"; + } + else + output_buf << "type: `" << *argv << "' undefined\n"; + } + + output_buf << ends; + + if (nargout == 0) + maybe_page_output (output_buf); + else + { + char *s = output_buf.str (); + retval = s; + delete s; + } + } + else + print_usage ("type"); + + DELETE_ARGV; + + return retval; +} + +DEFUN_TEXT ("which", Fwhich, Swhich, -1, 1, + "which NAME ...]\n\ +\n\ +display the type of each NAME. If NAME is defined from an function\n\ +file, print the full name of the file.") +{ + Octave_object retval; + + DEFINE_ARGV("which"); + + if (argc > 1) + { + if (nargout > 0) + retval.resize (argc-1, Matrix ()); + + ostrstream output_buf; + + for (int i = 0; i < argc-1; i++) + { + argv++; + + if (! *argv || ! **argv) + continue; + + symbol_record *sym_rec = lookup_by_name (*argv); + + if (sym_rec) + { + if (sym_rec->is_user_function ()) + { + tree_fvc *defn = sym_rec->def (); + char *fn = defn->fcn_file_name (); + if (fn) + { + char *ff = fcn_file_in_path (fn); + ff = ff ? ff : fn; + + if (nargout == 0) + output_buf << *argv + << " is the function defined from:\n" + << ff << "\n"; + else + retval(i) = ff; + } + else + { + if (nargout == 0) + output_buf << *argv << " is a user-defined function\n"; + else + retval(i) = "user-defined function"; + } + } + else if (sym_rec->is_text_function ()) + { + if (nargout == 0) + output_buf << *argv << " is a builtin text-function\n"; + else + retval(i) = "builtin text-function"; + } + else if (sym_rec->is_builtin_function ()) + { + if (nargout == 0) + output_buf << *argv << " is a builtin function\n"; + else + retval(i) = "builtin function"; + } + else if (sym_rec->is_user_variable ()) + { + if (nargout == 0) + output_buf << *argv << " is a user-defined variable\n"; + else + retval(i) = "user-defined variable"; + } + else if (sym_rec->is_builtin_variable ()) + { + if (nargout == 0) + output_buf << *argv << " is a builtin variable\n"; + else + retval(i) = "builtin variable"; + } + else + { + if (nargout == 0) + output_buf << "which: `" << *argv + << "' has unknown type\n"; + else + retval(i) = "unknown type"; + } + } + else + { + if (nargout == 0) + output_buf << "which: `" << *argv << "' is undefined\n"; + else + retval(i) = "undefined"; + } + } + output_buf << ends; + maybe_page_output (output_buf); + } + else + print_usage ("which"); + + DELETE_ARGV; + + return retval; +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/input.cc +++ b/src/input.cc @@ -48,10 +48,9 @@ extern char *xmalloc (); -/* - * Yes, this sucks, but it avoids a conflict with another readline - * function declared in iostream.h. - */ +// Yes, this sucks, but it avoids a conflict with another readline +// function declared in iostream.h. + #if 0 #define LINE_SIZE 8192 static int no_line_editing = 0; @@ -152,12 +151,11 @@ extern tree_constant eval_string (const char *string, int print, int ans_assign, int& parse_status); -/* - * Append SOURCE to TARGET at INDEX. SIZE is the current amount of - * space allocated to TARGET. SOURCE can be NULL, in which case - * nothing happens. Gets rid of SOURCE by free ()ing it. Returns - * TARGET in case the location has changed. - */ +// Append SOURCE to TARGET at INDEX. SIZE is the current amount of +// space allocated to TARGET. SOURCE can be NULL, in which case +// nothing happens. Gets rid of SOURCE by free ()ing it. Returns +// TARGET in case the location has changed. + static char * sub_append_string (char *source, char *target, int *index, int *size) { @@ -179,10 +177,9 @@ return target; } -/* - * Return the octal number parsed from STRING, or -1 to indicate that - * the string contained a bad number. - */ +// Return the octal number parsed from STRING, or -1 to indicate that +// the string contained a bad number. + int read_octal (const char *string) { @@ -201,24 +198,23 @@ return result; } -/* - * Return a string which will be printed as a prompt. The string may - * contain special characters which are decoded as follows: - * - * \t the time - * \d the date - * \n CRLF - * \s the name of the shell (program) - * \w the current working directory - * \W the last element of PWD - * \u your username - * \h the hostname - * \# the command number of this command - * \! the history number of this command - * \$ a $ or a # if you are root - * \<octal> character code in octal - * \\ a backslash - */ +// Return a string which will be printed as a prompt. The string may +// contain special characters which are decoded as follows: +// +// \t the time +// \d the date +// \n CRLF +// \s the name of the shell (program) +// \w the current working directory +// \W the last element of PWD +// \u your username +// \h the hostname +// \# the command number of this command +// \! the history number of this command +// \$ a $ or a # if you are root +// \<octal> character code in octal +// \\ a backslash + static char * decode_prompt_string (const char *string) { @@ -385,7 +381,7 @@ result = (char *)sub_append_string (temp, result, &result_index, &result_size); - temp = 0; /* Free ()'ed in sub_append_string (). */ + temp = 0; // Free ()'ed in sub_append_string (). result[result_index] = '\0'; break; } @@ -405,7 +401,7 @@ } #if 0 - /* I don't really think that this is a good idea. Do you? */ +// I don't really think that this is a good idea. Do you? if (! find_variable ("NO_PROMPT_VARS")) { WORD_LIST *expand_string (), *list; @@ -420,10 +416,10 @@ return result; } -/* - * Use GNU readline to get an input line and store it in the history - * list. - */ + +// Use GNU readline to get an input line and store it in the history +// list. + static char * octave_gets (void) { @@ -444,7 +440,10 @@ flush_output_to_pager (); } + maybe_write_to_diary_file (prompt); + octave_gets_line = gnu_readline (prompt); + delete [] prompt; } else @@ -456,6 +455,8 @@ { maybe_save_history (octave_gets_line); + maybe_write_to_diary_file (octave_gets_line); + if (echo_input) { if (! forced_interactive) @@ -464,12 +465,14 @@ cout << octave_gets_line << "\n"; } } + + maybe_write_to_diary_file ("\n"); + return octave_gets_line; } -/* - * Read a line from the input stream. - */ +// Read a line from the input stream. + int octave_read (char *buf, int max_size) { @@ -561,10 +564,9 @@ return status; } -/* - * Fix things up so that input can come from file `name', printing a - * warning if the file doesn't exist. - */ +// Fix things up so that input can come from file `name', printing a +// warning if the file doesn't exist. + FILE * get_input_from_file (char *name, int warn) { @@ -584,11 +586,10 @@ return instream; } -/* - * Fix things up so that input can come from the standard input. This - * may need to become much more complicated, which is why it's in a - * separate function. - */ +// Fix things up so that input can come from the standard input. This +// may need to become much more complicated, which is why it's in a +// separate function. + FILE * get_input_from_stdin (void) { @@ -643,11 +644,9 @@ return matches; } -/* - * The next two functions implement the equivalent of the K*rn shell - * C-o operate-and-get-next-history-line editing command. Stolen from - * the GNU Bourne Again SHell. - */ +// The next two functions implement the equivalent of the K*rn shell +// C-o operate-and-get-next-history-line editing command. Stolen from +// the GNU Bourne Again SHell. // ?? static int saved_history_line_to_use = 0; @@ -691,10 +690,10 @@ int where; extern int history_stifled, history_length, max_input_history; - /* Accept the current line. */ +// Accept the current line. rl_newline (); - /* Find the current line, and find the next line to use. */ +// Find the current line, and find the next line to use. where = where_history (); if (history_stifled && (history_length >= max_input_history)) @@ -736,6 +735,8 @@ return (strncmp (standard, tp, len) == 0); } +// If the user simply hits return, this will produce an empty matrix. + static Octave_object get_user_input (const Octave_object& args, int nargout, int debug = 0) { @@ -790,8 +791,13 @@ { int parse_status = 0; retval = eval_string (input_buf, 0, 0, parse_status); - if (debug && retval.is_defined ()) - retval.eval (1); + if (retval.is_defined ()) + { + if (debug) + retval.eval (1); + } + else + retval = tree_constant (Matrix ()); } } else
--- a/src/lex.l +++ b/src/lex.l @@ -423,7 +423,7 @@ convert_spaces_to_comma = 1; if (plotting && ! in_plot_range) past_plot_range = 1; - yylval.tok_val = new token (value, + yylval.tok_val = new token (value, yytext, input_line_number, current_input_column); token_stack.push (yylval.tok_val); @@ -444,7 +444,7 @@ convert_spaces_to_comma = 1; if (plotting && ! in_plot_range) past_plot_range = 1; - yylval.tok_val = new token (value, + yylval.tok_val = new token (value, yytext, input_line_number, current_input_column); token_stack.push (yylval.tok_val);
--- a/src/oct-hist.cc +++ b/src/oct-hist.cc @@ -38,7 +38,6 @@ #endif #include <fcntl.h> #include <stdlib.h> -#include <stdio.h> #include <string.h> #include <signal.h> #include <fstream.h> @@ -48,6 +47,7 @@ #include "utils.h" #include "error.h" #include "input.h" +#include "pager.h" #include "octave.h" #include "oct-obj.h" #include "user-prefs.h" @@ -79,10 +79,9 @@ // The number of history lines we've saved so far. static int history_lines_this_session = 0; -/* - * Get some default values, possibly reading them from the - * environment. - */ +// Get some default values, possibly reading them from the +// environment. + static int default_history_size (void) { @@ -119,9 +118,8 @@ return file; } -/* - * Prime the history list. - */ +// Prime the history list. + void initialize_history (void) { @@ -150,13 +148,12 @@ } } -/* - * Display, save, or load history. Stolen and modified from bash. - * - * Arg of -w FILENAME means write file, arg of -r FILENAME - * means read file, arg of -q means don't number lines. Arg of N - * means only display that many items. - */ +// Display, save, or load history. Stolen and modified from bash. +// +// Arg of -w FILENAME means write file, arg of -r FILENAME +// means read file, arg of -q means don't number lines. Arg of N +// means only display that many items. + void do_history (int argc, char **argv) { @@ -271,23 +268,28 @@ if ((i -= limit) < 0) i = 0; + ostrstream output_buf; + while (hlist[i]) { // QUIT; // in bash: (interrupt_state) throw_to_top_level (); if (numbered_output) - cerr.form ("%5d%c", i + history_base, hlist[i]->data ? '*' : ' '); - cerr << hlist[i]->line << "\n"; + output_buf.form ("%5d%c", i + history_base, + hlist[i]->data ? '*' : ' '); + output_buf << hlist[i]->line << "\n"; i++; } + + output_buf << ends; + maybe_page_output (output_buf); } } -/* - * Read the edited history lines from STREAM and return them - * one at a time. This can read unlimited length lines. The - * caller should free the storage. - */ +// Read the edited history lines from STREAM and return them +// one at a time. This can read unlimited length lines. The +// caller should free the storage. + static char * edit_history_readline (fstream& stream) { @@ -343,13 +345,12 @@ HIST_ENTRY *history_get (); } -/* - * Use `command' to replace the last entry in the history list, which, - * by this time, is `run_history blah...'. The intent is that the - * new command become the history entry, and that `fc' should never - * appear in the history list. This way you can do `run_history' to - * your heart's content. - */ +// Use `command' to replace the last entry in the history list, which, +// by this time, is `run_history blah...'. The intent is that the +// new command become the history entry, and that `fc' should never +// appear in the history list. This way you can do `run_history' to +// your heart's content. + static void edit_history_repl_hist (char *command) { @@ -365,8 +366,7 @@ ; // Count 'em. i--; - /* History_get () takes a parameter that should be - offset by history_base. */ +// History_get () takes a parameter that should be offset by history_base. // Don't free this. HIST_ENTRY *histent = history_get (history_base + i);
--- a/src/octave.cc +++ b/src/octave.cc @@ -171,9 +171,8 @@ { 0, 0, 0, 0 } }; -/* - * Initialize some global variables for later use. - */ +// Initialize some global variables for later use. + static void initialize_globals (char *name) { @@ -281,9 +280,8 @@ run_unwind_frame ("parse_and_execute_2"); } -/* - * Initialize by reading startup files. - */ +// Initialize by reading startup files. + static void execute_startup_files (void) { @@ -324,9 +322,8 @@ run_unwind_frame ("execute_startup_files"); } -/* - * Usage message with extra help. - */ +// Usage message with extra help. + static void verbose_usage (void) { @@ -351,9 +348,8 @@ exit (1); } -/* - * Terse usage messsage. - */ +// Terse usage messsage. + static void usage (void) { @@ -361,9 +357,8 @@ exit (1); } -/* - * Fix up things before exiting. - */ +// Fix up things before exiting. + void clean_up_and_exit (int retval) { @@ -373,6 +368,8 @@ close_plot_stream (); + close_diary_file (); + close_files (); cleanup_tmp_files (); @@ -398,9 +395,8 @@ exit (0); } -/* - * You guessed it. - */ +// You guessed it. + int main (int argc, char **argv) { @@ -466,18 +462,18 @@ atexit (cleanup_tmp_files); #endif + initialize_pager (); + initialize_history (); initialize_file_io (); - initialize_symbol_tables (); + initialize_symbol_tables (); install_builtins (); initialize_readline (); - initialize_pager (); - install_signal_handlers (); if (! inhibit_startup_message) @@ -768,9 +764,8 @@ return retval; } -/* - * Execute a shell command. - */ +// Execute a shell command. + DEFUN ("shell_cmd", Fshell_cmd, Sshell_cmd, 2, 1, "shell_cmd (string [, return_output]): execute shell commands") {
--- a/src/pager.cc +++ b/src/pager.cc @@ -27,17 +27,32 @@ #include <iostream.h> #include <strstream.h> +#include <fstream.h> #include <stdlib.h> #include "procstream.h" #include "user-prefs.h" +#include "oct-obj.h" +#include "error.h" +#include "defun.h" #include "input.h" #include "pager.h" +#include "utils.h" +#include "help.h" // Where we stash output headed for the screen. static ostrstream *pager_buf = 0; +// Nonzero means we write to the diary file. +static int write_to_diary_file = 0; + +// The name of the current diary file. +static char *diary_file = "diary"; + +// The diary file. +static ofstream diary_stream; + static int line_count (char *s) { @@ -52,13 +67,12 @@ return count; } -/* - * For now, use the variables from readline. It already handles - * SIGWINCH, so these values have a good chance of being correct even - * if the window changes size (they will be wrong if, for example, the - * luser changes the window size while the pager is running, and the - * signal is handled by the pager instead of us. - */ +// For now, use the variables from readline. It already handles +// SIGWINCH, so these values have a good chance of being correct even +// if the window changes size (they will be wrong if, for example, the +// luser changes the window size while the pager is running, and the +// signal is handled by the pager instead of us. + int terminal_columns (void) { @@ -116,6 +130,8 @@ return; } + maybe_write_to_diary_file (message); + int nlines = line_count (message); if (nlines > terminal_rows () - 2) @@ -142,6 +158,76 @@ initialize_pager (); } +static void +open_diary_file (void) +{ + if (diary_stream.is_open ()) + diary_stream.close (); + + diary_stream.open (diary_file, ios::app); + + if (! diary_stream) + error ("diary: can't open diary file `%s'", diary_file); +} + +void +close_diary_file (void) +{ + if (diary_stream) + diary_stream.close (); +} + +void +maybe_write_to_diary_file (const char *s) +{ + if (write_to_diary_file && diary_stream) + diary_stream << s; +} + +DEFUN_TEXT ("diary", Fdiary, Sdiary, -1, 1, + "diary [on|off]\n\ +diary [file]\n\ +\n\ +redirect all input and screen output to a file.") +{ + Octave_object retval; + + DEFINE_ARGV("diary"); + + switch (argc) + { + case 1: + write_to_diary_file = ! write_to_diary_file; + open_diary_file (); + break; + case 2: + { + char *arg = argv[1]; + if (strcmp (arg, "on") == 0) + { + write_to_diary_file = 1; + open_diary_file (); + } + else if (strcmp (arg, "off") == 0) + write_to_diary_file = 0; + else + { + delete [] diary_file; + diary_file = strsave (arg); + open_diary_file (); + } + } + break; + default: + print_usage ("diary"); + break; + } + + DELETE_ARGV; + + return retval; +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/pager.h +++ b/src/pager.h @@ -33,6 +33,9 @@ extern void maybe_page_output (ostrstream& msg_buf); extern void flush_output_to_pager (void); +extern void close_diary_file (void); +extern void maybe_write_to_diary_file (const char *s); + #endif /*
--- a/src/parse.y +++ b/src/parse.y @@ -32,25 +32,28 @@ #include "config.h" #endif +#include <strstream.h> + #include "SLStack.h" #include "Matrix.h" -#include "error.h" -#include "octave.h" -#include "variables.h" #include "octave-hist.h" #include "user-prefs.h" +#include "tree-const.h" +#include "tree-misc.h" +#include "variables.h" +#include "tree-plot.h" +#include "octave.h" +#include "symtab.h" +#include "parse.h" +#include "token.h" +#include "error.h" +#include "pager.h" #include "input.h" #include "utils.h" #include "tree.h" -#include "tree-misc.h" -#include "tree-plot.h" -#include "tree-const.h" -#include "symtab.h" -#include "parse.h" #include "lex.h" -#include "token.h" // Nonzero means we're in the middle of defining a function. int defining_func = 0; @@ -563,7 +566,7 @@ { tree_simple_assignment_expression *tmp_ass; tmp_ass = new tree_simple_assignment_expression - ($1, $3, 0, $2->line (), $2->column ()); + ($1, $3, 0, 0, $2->line (), $2->column ()); $$ = new tree_global (tmp_ass); } ; @@ -693,7 +696,7 @@ expression : variable '=' expression { $$ = new tree_simple_assignment_expression - ($1, $3, 0, $2->line (), $2->column ()); } + ($1, $3, 0, 0, $2->line (), $2->column ()); } | '[' screwed_again matrix_row SCREW_TWO '=' expression { @@ -784,15 +787,23 @@ ; simple_expr1 : NUM - { $$ = new tree_constant ($1->number ()); } + { + tree_constant *tmp = new tree_constant ($1->number ()); + tmp->stash_original_text ($1->text_rep ()); + $$ = tmp; + } | IMAG_NUM - { $$ = new tree_constant (Complex (0.0, $1->number ())); } + { + Complex c (0.0, $1->number ()); + tree_constant *tmp = new tree_constant (c); + tmp->stash_original_text ($1->text_rep ()); + $$ = tmp; + } | TEXT { $$ = new tree_constant ($1->string ()); } | '(' expression ')' { - if ($2->is_assignment_expression ()) - ((tree_assignment_expression *) $2) -> in_parens++; + $2->in_parens++; $$ = $2; } | word_list_cmd @@ -1129,13 +1140,16 @@ if (err_col == 0 && line) err_col = strlen (line) + 1; -// Print a message like `parse error'. - fprintf (stderr, "\n%s", s); +// Print a message like `parse error', maybe printing the line number +// and file name. + + ostrstream output_buf; -// Maybe print the line number and file name. + output_buf.form ("\n%s", s); + if (reading_fcn_file || reading_script_file) - fprintf (stderr, " near line %d of file %s.m", input_line_number, - curr_fcn_file_name); + output_buf.form (" near line %d of file %s.m", input_line_number, + curr_fcn_file_name); if (line) { @@ -1147,12 +1161,14 @@ } // Print the line, maybe with a pointer near the error token. if (err_col > len) - fprintf (stderr, ":\n\n %s\n\n", line); + output_buf.form (":\n\n %s\n\n", line); else - fprintf (stderr, ":\n\n %s\n %*s\n\n", line, err_col, "^"); + output_buf.form (":\n\n %s\n %*s\n\n", line, err_col, "^"); } else - fprintf (stderr, "\n\n"); + output_buf << "\n\n"; + + maybe_page_output (output_buf); } static void @@ -1252,7 +1268,7 @@ tree_identifier *ans = new tree_identifier (sr); - return new tree_simple_assignment_expression (ans, expr); + return new tree_simple_assignment_expression (ans, expr, 0, 1); } } @@ -1261,7 +1277,7 @@ { if (user_pref.warn_assign_as_truth_value && expr->is_assignment_expression () - && ((tree_assignment_expression *) expr) -> in_parens < 2) + && expr->in_parens < 2) { warning ("suggest parenthesis around assignment used as truth value"); }
--- a/src/pt-base.h +++ b/src/pt-base.h @@ -24,13 +24,42 @@ #if !defined (octave_tree_base_h) #define octave_tree_base_h 1 -class tree_constant; +class ostream; + +// How to print the code that the trees represent. + +class +tree_print_code +{ +public: + virtual ~tree_print_code (void) { } + + virtual void print_code (ostream& os) = 0; + + void reset_indent_level (void) + { curr_print_indent_level = 0; } + + void increment_indent_level (void) + { curr_print_indent_level += 2; } -/* - * Base class for the parse tree. - */ + void decrement_indent_level (void) + { curr_print_indent_level -= 2; } + + void print_code_new_line (ostream& os); + + void print_code_indent (ostream& os); + + void print_code_reset (void); + +private: + static int curr_print_indent_level; + static int beginning_of_line; +}; + +// Base class for the parse tree. + class -tree +tree : public tree_print_code { public: tree (int l = -1, int c = -1) @@ -39,11 +68,11 @@ column_num = c; } - virtual ~tree (void) { } + virtual int line (void) const + { return line_num; } - virtual int line (void) const { return line_num; } - - virtual int column (void) const { return column_num; } + virtual int column (void) const + { return column_num; } private: int line_num;
--- a/src/pt-cmd.cc +++ b/src/pt-cmd.cc @@ -114,6 +114,17 @@ line (), column ()); } +void +tree_global_command::print_code (ostream& os) +{ + print_code_indent (os); + + os << "global "; + + if (init_list) + init_list->print_code (os); +} + // While. tree_while_command::~tree_while_command (void) @@ -195,6 +206,30 @@ line (), column ()); } +void +tree_while_command::print_code (ostream& os) +{ + print_code_indent (os); + + os << "while "; + + if (expr) + expr->print_code (os); + + print_code_new_line (os); + + if (list) + { + increment_indent_level (); + list->print_code (os); + decrement_indent_level (); + } + + print_code_indent (os); + + os << "endwhile"; +} + // For. tree_for_command::~tree_for_command (void) @@ -342,6 +377,35 @@ quit = quit_loop_now (); } +void +tree_for_command::print_code (ostream& os) +{ + print_code_indent (os); + + os << "for "; + + if (id) + id->print_code (os); + + os << " = "; + + if (expr) + expr->print_code (os); + + print_code_new_line (os); + + if (list) + { + increment_indent_level (); + list->print_code (os); + decrement_indent_level (); + } + + print_code_indent (os); + + os << "endfor"; +} + // If. tree_if_command::~tree_if_command (void) @@ -360,6 +424,21 @@ line (), column ()); } +void +tree_if_command::print_code (ostream& os) +{ + print_code_indent (os); + + os << "if "; + + if (list) + list->print_code (os); + + print_code_indent (os); + + os << "endif"; +} + // Break. void @@ -369,6 +448,14 @@ breaking = 1; } +void +tree_break_command::print_code (ostream& os) +{ + print_code_indent (os); + + os << "break"; +} + // Continue. void @@ -378,6 +465,14 @@ continuing = 1; } +void +tree_continue_command::print_code (ostream& os) +{ + print_code_indent (os); + + os << "continue"; +} + // Return. void @@ -387,6 +482,14 @@ returning = 1; } +void +tree_return_command::print_code (ostream& os) +{ + print_code_indent (os); + + os << "return"; +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/pt-cmd.h +++ b/src/pt-cmd.h @@ -28,6 +28,8 @@ #pragma interface #endif +#include <iostream.h> + class tree_statement_list; class tree_global_init_list; class tree_if_command_list; @@ -73,6 +75,8 @@ void eval (void); + void print_code (ostream& os); + private: tree_global_init_list *init_list; }; @@ -110,6 +114,8 @@ void eval_error (void); + void print_code (ostream& os); + private: tree_expression *expr; // Expression to test. tree_statement_list *list; // List of commands to execute. @@ -143,6 +149,8 @@ void eval_error (void); + void print_code (ostream& os); + private: void do_for_loop_once (tree_constant *rhs, int& quit); @@ -170,6 +178,8 @@ void eval_error (void); + void print_code (ostream& os); + private: tree_if_command_list *list; }; @@ -185,6 +195,8 @@ ~tree_break_command (void) { } void eval (void); + + void print_code (ostream& os); }; // Continue. @@ -198,6 +210,8 @@ ~tree_continue_command (void) { } void eval (void); + + void print_code (ostream& os); }; // Return. @@ -211,6 +225,8 @@ ~tree_return_command (void) { } void eval (void); + + void print_code (ostream& os); }; #endif
--- a/src/pt-const.cc +++ b/src/pt-const.cc @@ -29,6 +29,8 @@ #pragma implementation #endif +#include <iostream.h> + #include "tree-const.h" #include "error.h" #include "gripes.h" @@ -65,10 +67,9 @@ } #endif -/* - * Construct return vector of empty matrices. Return empty matrices - * and/or gripe when appropriate. - */ +// Construct return vector of empty matrices. Return empty matrices +// and/or gripe when appropriate. + Octave_object vector_of_empties (int nargout, const char *fcn_name) { @@ -93,6 +94,21 @@ return retval; } +void +tree_constant::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + if (rep) + rep->print_code (os); + + if (in_parens) + os << ")"; +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/pt-const.h +++ b/src/pt-const.h @@ -28,6 +28,8 @@ #pragma interface #endif +#include <iostream.h> + #include <stdlib.h> #include "mx-base.h" @@ -42,55 +44,52 @@ struct Mapper_fcn; -/* - * Constants. - */ +// Constants. + class tree_constant : public tree_fvc { friend class tree_constant_rep; public: - tree_constant (void) + tree_constant (void) : tree_fvc () { rep = new tree_constant_rep (); rep->count = 1; } - tree_constant (double d) + tree_constant (double d) : tree_fvc () { rep = new tree_constant_rep (d); rep->count = 1; } - tree_constant (const Matrix& m) + tree_constant (const Matrix& m) : tree_fvc () { rep = new tree_constant_rep (m); rep->count = 1; } - tree_constant (const DiagMatrix& d) + tree_constant (const DiagMatrix& d) : tree_fvc () { rep = new tree_constant_rep (d); rep->count = 1; } - tree_constant (const RowVector& v, int pcv = -1) + tree_constant (const RowVector& v, int pcv = -1) : tree_fvc () { rep = new tree_constant_rep (v, pcv); rep->count = 1; } - tree_constant (const ColumnVector& v, int pcv = -1) + tree_constant (const ColumnVector& v, int pcv = -1) : tree_fvc () { rep = new tree_constant_rep (v, pcv); rep->count = 1; } - tree_constant (const Complex& c) + tree_constant (const Complex& c) : tree_fvc () { rep = new tree_constant_rep (c); rep->count = 1; } - tree_constant (const ComplexMatrix& m) + tree_constant (const ComplexMatrix& m) : tree_fvc () { rep = new tree_constant_rep (m); rep->count = 1; } - tree_constant (const ComplexDiagMatrix& d) + tree_constant (const ComplexDiagMatrix& d) : tree_fvc () { rep = new tree_constant_rep (d); rep->count = 1; } - tree_constant (const ComplexRowVector& v, int pcv = -1) - { rep = new tree_constant_rep (v, pcv); rep->count = 1; } - tree_constant (const ComplexColumnVector& v, int pcv = -1) - { rep = new tree_constant_rep (v, pcv); rep->count = 1; } + tree_constant (const ComplexRowVector& v, int pcv = -1) : tree_fvc () + { rep = new tree_constant_rep (v, pcv); rep->count = 1; } + tree_constant (const ComplexColumnVector& v, int pcv = -1) : tree_fvc () + { rep = new tree_constant_rep (v, pcv); rep->count = 1; } - tree_constant (const char *s) + tree_constant (const char *s) : tree_fvc () { rep = new tree_constant_rep (s); rep->count = 1; } - tree_constant (double base, double limit, double inc) + tree_constant (double base, double limit, double inc) : tree_fvc () { rep = new tree_constant_rep (base, limit, inc); rep->count = 1; } - tree_constant (const Range& r) + tree_constant (const Range& r) : tree_fvc () { rep = new tree_constant_rep (r); rep->count = 1; } - tree_constant (tree_constant_rep::constant_type t) + tree_constant (tree_constant_rep::constant_type t) : tree_fvc () { rep = new tree_constant_rep (t); rep->count = 1; } - tree_constant (const tree_constant& a) + tree_constant (const tree_constant& a) : tree_fvc () { rep = a.rep; rep->count++; } - tree_constant (tree_constant_rep& r) - { rep = &r; rep->count++; } ~tree_constant (void); @@ -134,6 +133,9 @@ ColumnVector to_vector (void) const { return rep->to_vector (); } Matrix to_matrix (void) const { return rep->to_matrix (); } + void stash_original_text (char *s) + { rep->stash_original_text (s); } + tree_constant_rep::constant_type force_numeric (int force_str_conv = 0) { return rep->force_numeric (force_str_conv); } @@ -283,6 +285,8 @@ return retval; } + void print_code (ostream& os); + private: tree_constant_rep *rep; };
--- a/src/pt-exp-base.cc +++ b/src/pt-exp-base.cc @@ -59,11 +59,6 @@ #include "lex.h" #include "defun.h" -extern "C" -{ -#include <readline/readline.h> -} - // Nonzero means we're returning from a function. extern int returning; @@ -136,9 +131,21 @@ return 0; } -// NOTE: functions for the tree_constant_rep and tree_constant classes -// are now defined in tree-const.cc. This should help speed up -// compilation when working only on the tree_constant class. +// Expressions. + +tree_constant +tree_expression::eval (int print) +{ + panic ("invalid evaluation of generic expression"); + return tree_constant (); +} + +Octave_object +tree_expression::eval (int print, int nargout, const Octave_object& args) +{ + panic ("invalid evaluation of generic expression"); + return Octave_object (); +} // General matrices. This list type is much more work to handle than // constant matrices, but it allows us to construct matrices from @@ -234,7 +241,7 @@ struct const_matrix_list { - tree_matrix::dir dir_next; + tree_matrix::dir direction; tree_constant elem; int nr; int nc; @@ -307,7 +314,8 @@ goto done; } - tree_constant tmp = elem->eval (0); + Octave_object otmp = elem->eval (0); + tree_constant tmp = otmp(0); if (error_state || tmp.is_undefined ()) { retval = tree_constant (); @@ -317,7 +325,7 @@ int nr = tmp.rows (); int nc = tmp.columns (); - dir direct = ptr->dir_next; + dir direct = ptr->direction; if (nr == 0 || nc == 0) { @@ -339,10 +347,10 @@ if (found_new_row_in_empties) { found_new_row_in_empties = 0; - list[len].dir_next = md_down; + list[len].direction = md_down; } else - list[len].dir_next = direct; + list[len].direction = direct; list[len].elem = tmp; list[len].nr = nr; @@ -369,7 +377,7 @@ for (i = 0; i < len; i++) { - dir direct = list[i].dir_next; + dir direct = list[i].direction; int nr = list[i].nr; int nc = list[i].nc; @@ -460,7 +468,7 @@ } else { - switch (list[i].dir_next) + switch (list[i].direction) { case md_right: put_col += prev_nc; @@ -565,6 +573,48 @@ return retval; } +void +tree_matrix::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + os << "["; + + tree_matrix *list = this; + + while (list) + { + list->element->print_code (os); + + list = list->next; + + if (list) + { + switch (list->direction) + { + case md_right: + os << ", "; + break; + case md_down: + os << "; "; + break; + default: + break; + } + } + } + + os << "]"; + + if (in_parens) + os << ")"; +} + +// A base class for objects that can be evaluated with argument lists. + tree_constant tree_fvc::assign (tree_constant& t, const Octave_object& args) { @@ -572,135 +622,26 @@ return tree_constant (); } -// Builtin functions. - -tree_builtin::tree_builtin (const char *nm) -{ - nargin_max = -1; - nargout_max = -1; - is_mapper = 0; - fcn = 0; - if (nm) - my_name = strsave (nm); -} - -tree_builtin::tree_builtin (int i_max, int o_max, Mapper_fcn& m_fcn, - const char *nm) -{ - nargin_max = i_max; - nargout_max = o_max; - mapper_fcn = m_fcn; - is_mapper = 1; - fcn = 0; - if (nm) - my_name = strsave (nm); -} - -tree_builtin::tree_builtin (int i_max, int o_max, Octave_builtin_fcn g_fcn, - const char *nm) -{ - nargin_max = i_max; - nargout_max = o_max; - is_mapper = 0; - fcn = g_fcn; - if (nm) - my_name = strsave (nm); -} - - -tree_constant -tree_builtin::eval (int print) -{ - tree_constant retval; - - if (error_state) - return retval; - - if (fcn) - { - Octave_object args; - args(0) = tree_constant (my_name); - Octave_object tmp = (*fcn) (args, 1); - if (tmp.length () > 0) - retval = tmp(0); - } - else // Assume mapper function - ::error ("%s: argument expected", my_name); - - return retval; -} - -Octave_object -tree_builtin::eval (int print, int nargout, const Octave_object& args) -{ - Octave_object retval; - - if (error_state) - return retval; - - int nargin = args.length (); - - if (fcn) - { - if (any_arg_is_magic_colon (args)) - ::error ("invalid use of colon in function argument list"); - else - retval = (*fcn) (args, nargout); - } - else if (is_mapper) - { - if (nargin > nargin_max) - ::error ("%s: too many arguments", my_name); - else if (nargin > 0 && args.length () > 0 && args(1).is_defined ()) - { - tree_constant tmp = args(1).mapper (mapper_fcn, 0); - retval.resize (1); - retval(0) = tmp; - } - } - else - panic_impossible (); - - return retval; -} - -int -tree_builtin::max_expected_args (void) -{ - int ea = nargin_max; - if (nargin_max < 0) - ea = INT_MAX; - else - ea = nargin_max; - return ea; -} - // Symbols from the symbol table. char * tree_identifier::name (void) const { - return sym->name (); + return sym ? sym->name () : 0; } tree_identifier * tree_identifier::define (tree_constant *t) { int status = sym->define (t); - if (status) - return this; - else - return 0; + return status ? this : 0; } tree_identifier * tree_identifier::define (tree_function *t) { int status = sym->define (t); - if (status) - return this; - else - return 0; + return status ? this : 0; } void @@ -806,180 +747,6 @@ } } -static void -gobble_leading_white_space (FILE *ffile) -{ - int in_comment = 0; - int c; - while ((c = getc (ffile)) != EOF) - { - if (in_comment) - { - if (c == '\n') - in_comment = 0; - } - else - { - if (c == ' ' || c == '\t' || c == '\n') - continue; - else if (c == '%' || c == '#') - in_comment = 1; - else - { - ungetc (c, ffile); - break; - } - } - } -} - -static int -is_function_file (FILE *ffile) -{ - int status = 0; - - gobble_leading_white_space (ffile); - - long pos = ftell (ffile); - - char buf [10]; - fgets (buf, 10, ffile); - int len = strlen (buf); - if (len > 8 && strncmp (buf, "function", 8) == 0 - && ! (isalnum (buf[8]) || buf[8] == '_')) - status = 1; - - fseek (ffile, pos, SEEK_SET); - - return status; -} - -int -tree_identifier::load_fcn_from_file (int exec_script) -{ - int script_file_executed = 0; - - curr_fcn_file_name = name (); - - char *oct_file = oct_file_in_path (curr_fcn_file_name); - - int loaded_oct_file = 0; - - if (oct_file) - { - cerr << "found: " << oct_file << "\n"; - - delete [] oct_file; - -// XXX FIXME XXX -- this is where we try to link to an external -// object... - loaded_oct_file = 1; - } - - if (! loaded_oct_file) - { - char *ff = fcn_file_in_path (curr_fcn_file_name); - - if (ff) - { - script_file_executed = parse_fcn_file (exec_script, ff); - delete [] ff; - } - - if (! (error_state || script_file_executed)) - { - char *foo = name (); - force_link_to_function (foo); - } - } - - return script_file_executed; -} - -int -tree_identifier::parse_fcn_file (int exec_script, char *ff) -{ - begin_unwind_frame ("parse_fcn_file"); - - int script_file_executed = 0; - - assert (ff); - -// Open function file and parse. - - int old_reading_fcn_file_state = reading_fcn_file; - - unwind_protect_ptr (rl_instream); - unwind_protect_ptr (ff_instream); - - unwind_protect_int (using_readline); - unwind_protect_int (input_line_number); - unwind_protect_int (current_input_column); - unwind_protect_int (reading_fcn_file); - - using_readline = 0; - reading_fcn_file = 1; - input_line_number = 0; - current_input_column = 1; - - FILE *ffile = get_input_from_file (ff, 0); - - if (ffile) - { -// Check to see if this file defines a function or is just a list of -// commands. - - if (is_function_file (ffile)) - { - unwind_protect_int (echo_input); - unwind_protect_int (saving_history); - unwind_protect_int (reading_fcn_file); - - echo_input = 0; - saving_history = 0; - reading_fcn_file = 1; - - YY_BUFFER_STATE old_buf = current_buffer (); - YY_BUFFER_STATE new_buf = create_buffer (ffile); - - add_unwind_protect (restore_input_buffer, (void *) old_buf); - add_unwind_protect (delete_input_buffer, (void *) new_buf); - - switch_to_buffer (new_buf); - - unwind_protect_ptr (curr_sym_tab); - - reset_parser (); - - int status = yyparse (); - - if (status != 0) - { - ::error ("parse error while reading function file %s", ff); - global_sym_tab->clear (curr_fcn_file_name); - } - } - else if (exec_script) - { -// The value of `reading_fcn_file' will be restored to the proper value -// when we unwind from this frame. - reading_fcn_file = old_reading_fcn_file_state; - - unwind_protect_int (reading_script_file); - reading_script_file = 1; - - parse_and_execute (ffile, 1); - - script_file_executed = 1; - } - fclose (ffile); - } - - run_unwind_frame ("parse_fcn_file"); - - return script_file_executed; -} - void tree_identifier::eval_undefined_error (void) { @@ -987,7 +754,7 @@ int l = line (); int c = column (); if (l == -1 && c == -1) - ::error ("`%s' undefined"); + ::error ("`%s' undefined", nm); else ::error ("`%s' undefined near line %d column %d", nm, l, c); } @@ -1012,29 +779,7 @@ { script_file_executed = 0; - if (! sym->is_linked_to_global ()) - { - if (sym->is_defined ()) - { - if (sym->is_function () && symbol_out_of_date (sym)) - { - script_file_executed = load_fcn_from_file (); - } - } - else if (! sym->is_formal_parameter ()) - { - link_to_builtin_or_function (sym); - - if (! sym->is_defined ()) - { - script_file_executed = load_fcn_from_file (); - } - else if (sym->is_function () && symbol_out_of_date (sym)) - { - script_file_executed = load_fcn_from_file (); - } - } - } + int script_file_executed = lookup (sym); tree_fvc *ans = 0; @@ -1085,6 +830,10 @@ { if (maybe_do_ans_assign && ! ans->is_constant ()) { + +// XXX FIXME XXX -- need a procedure to do this, probably in +// variables.cc, to isolate the code that does lookups... + symbol_record *sr = global_sym_tab->lookup ("ans", 1, 0); assert (sr); @@ -1093,7 +842,7 @@ tree_constant *tmp = new tree_constant (retval); - tree_simple_assignment_expression tmp_ass (ans_id, tmp); + tree_simple_assignment_expression tmp_ass (ans_id, tmp, 0, 1); tmp_ass.eval (print); @@ -1164,6 +913,10 @@ if (retval.length () > 0 && retval(0).is_defined ()) { + +// XXX FIXME XXX -- need a procedure to do this, probably in +// variables.cc, to isolate the code that does lookups... + symbol_record *sr = global_sym_tab->lookup ("ans", 1, 0); assert (sr); @@ -1172,7 +925,8 @@ tree_constant *tmp = new tree_constant (retval(0)); - tree_simple_assignment_expression tmp_ass (ans_id, tmp); + tree_simple_assignment_expression tmp_ass (ans_id, + tmp, 0, 1); tmp_ass.eval (print); @@ -1189,6 +943,1117 @@ return retval; } +void +tree_identifier::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + char *nm = name (); + os << (nm) ? nm : "(null)"; + + if (in_parens) + os << ")"; +} + +// Index expressions. + +tree_index_expression::~tree_index_expression (void) +{ + delete id; + delete list; +} + +tree_constant +tree_index_expression::eval (int print) +{ + tree_constant retval; + + if (error_state) + return retval; + + if (list) + { +// Extract the arguments into a simple vector. + Octave_object args = list->convert_to_const_vector (); +// Don't pass null arguments. + int nargin = args.length (); + if (error_state) + eval_error (); + else if (nargin > 1 && all_args_defined (args)) + { + Octave_object tmp = id->eval (print, 1, args); + + if (error_state) + eval_error (); + + if (tmp.length () > 0) + retval = tmp(0); + } + } + else + { + retval = id->eval (print); + if (error_state) + eval_error (); + } + + return retval; +} + +Octave_object +tree_index_expression::eval (int print, int nargout, const Octave_object& args) +{ + Octave_object retval; + + if (error_state) + return retval; + + if (list) + { +// Extract the arguments into a simple vector. + Octave_object args = list->convert_to_const_vector (); +// Don't pass null arguments. + if (error_state) + eval_error (); + else if (args.length () > 1 && all_args_defined (args)) + { + retval = id->eval (print, nargout, args); + if (error_state) + eval_error (); + } + } + else + { + Octave_object tmp_args; + retval = id->eval (print, nargout, tmp_args); + if (error_state) + eval_error (); + } + + return retval; +} + +void +tree_index_expression::eval_error (void) +{ + if (error_state > 0) + { + int l = line (); + int c = column (); + char *fmt; + if (l != -1 && c != -1) + { + if (list) + fmt = "evaluating index expression near line %d, column %d"; + else + fmt = "evaluating expression near line %d, column %d"; + + ::error (fmt, l, c); + } + else + { + if (list) + ::error ("evaluating index expression"); + else + ::error ("evaluating expression"); + } + } +} + +void +tree_index_expression::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + if (id) + id->print_code (os); + + if (list) + { + os << " ("; + list->print_code (os); + os << ")"; + } + + if (in_parens) + os << ")"; +} + +// Prefix expressions. + +tree_constant +tree_prefix_expression::eval (int print) +{ + tree_constant retval; + + if (error_state) + return retval; + + if (id) + { + id->bump_value (etype); + retval = id->eval (print); + if (error_state) + { + retval = tree_constant (); + if (error_state) + eval_error (); + } + } + return retval; +} + +char * +tree_prefix_expression::oper (void) const +{ + static char *op; + switch (etype) + { + case tree_expression::increment: op = "++"; break; + case tree_expression::decrement: op = "--"; break; + default: op = "unknown"; break; + } + return op; +} + +void +tree_prefix_expression::eval_error (void) +{ + if (error_state > 0) + { + char *op = oper (); + + ::error ("evaluating prefix operator `%s' near line %d, column %d", + op, line (), column ()); + } +} + +void +tree_prefix_expression::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + os << oper (); + + if (id) + id->print_code (os); + + if (in_parens) + os << ")"; +} + +// Postfix expressions. + +tree_constant +tree_postfix_expression::eval (int print) +{ + tree_constant retval; + + if (error_state) + return retval; + + if (id) + { + retval = id->eval (print); + id->bump_value (etype); + if (error_state) + { + retval = tree_constant (); + if (error_state) + eval_error (); + } + } + return retval; +} + +char * +tree_postfix_expression::oper (void) const +{ + static char *op; + switch (etype) + { + case tree_expression::increment: op = "++"; break; + case tree_expression::decrement: op = "--"; break; + default: op = "unknown"; break; + } + return op; +} + +void +tree_postfix_expression::eval_error (void) +{ + if (error_state > 0) + { + char *op = oper (); + + ::error ("evaluating postfix operator `%s' near line %d, column %d", + op, line (), column ()); + } +} + +void +tree_postfix_expression::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + if (id) + id->print_code (os); + + os << oper (); + + if (in_parens) + os << ")"; +} + +// Unary expressions. + +tree_constant +tree_unary_expression::eval (int print) +{ + if (error_state) + return tree_constant (); + + tree_constant ans; + + switch (etype) + { + case tree_expression::not: + case tree_expression::uminus: + case tree_expression::hermitian: + case tree_expression::transpose: + if (op) + { + Octave_object tmp = op->eval (0); + tree_constant u = tmp(0); + if (error_state) + eval_error (); + else if (u.is_defined ()) + { + ans = do_unary_op (u, etype); + if (error_state) + { + ans = tree_constant (); + if (error_state) + eval_error (); + } + } + } + break; + default: + ::error ("unary operator %d not implemented", etype); + break; + } + + return ans; +} + +char * +tree_unary_expression::oper (void) const +{ + static char *op; + switch (etype) + { + case tree_expression::not: op = "!"; break; + case tree_expression::uminus: op = "-"; break; + case tree_expression::hermitian: op = "'"; break; + case tree_expression::transpose: op = ".'"; break; + default: op = "unknown"; break; + } + return op; +} + +void +tree_unary_expression::eval_error (void) +{ + if (error_state > 0) + { + char *op = oper (); + + ::error ("evaluating unary operator `%s' near line %d, column %d", + op, line (), column ()); + } +} + +void +tree_unary_expression::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + switch (etype) + { + case tree_expression::not: + case tree_expression::uminus: + os << oper (); + if (op) + op->print_code (os); + break; + case tree_expression::hermitian: + case tree_expression::transpose: + if (op) + op->print_code (os); + os << oper (); + break; + default: + panic_impossible (); + break; + } + + if (in_parens) + os << ")"; +} + +// Binary expressions. + +tree_constant +tree_binary_expression::eval (int print) +{ + if (error_state) + return tree_constant (); + + tree_constant ans; + switch (etype) + { + case tree_expression::add: + case tree_expression::subtract: + case tree_expression::multiply: + case tree_expression::el_mul: + case tree_expression::divide: + case tree_expression::el_div: + case tree_expression::leftdiv: + case tree_expression::el_leftdiv: + case tree_expression::power: + case tree_expression::elem_pow: + case tree_expression::cmp_lt: + case tree_expression::cmp_le: + case tree_expression::cmp_eq: + case tree_expression::cmp_ge: + case tree_expression::cmp_gt: + case tree_expression::cmp_ne: + case tree_expression::and: + case tree_expression::or: + if (op1) + { + Octave_object tmp = op1->eval (0); + tree_constant a = tmp(0); + if (error_state) + eval_error (); + else if (a.is_defined () && op2) + { + tmp = op2->eval (0); + tree_constant b = tmp (0); + if (error_state) + eval_error (); + else if (b.is_defined ()) + { + ans = do_binary_op (a, b, etype); + if (error_state) + { + ans = tree_constant (); + if (error_state) + eval_error (); + } + } + } + } + break; + case tree_expression::and_and: + case tree_expression::or_or: + { + int result = 0; + if (op1) + { + Octave_object tmp = op1->eval (0); + tree_constant a = tmp(0); + if (error_state) + { + eval_error (); + break; + } + + int a_true = a.is_true (); + if (error_state) + { + eval_error (); + break; + } + + if (a_true) + { + if (etype == tree_expression::or_or) + { + result = 1; + goto done; + } + } + else + { + if (etype == tree_expression::and_and) + { + result = 0; + goto done; + } + } + + if (op2) + { + tmp = op2->eval (0); + tree_constant b = tmp(0); + if (error_state) + { + eval_error (); + break; + } + + result = b.is_true (); + if (error_state) + { + eval_error (); + break; + } + } + } + done: + ans = tree_constant ((double) result); + } + break; + default: + ::error ("binary operator %d not implemented", etype); + break; + } + + return ans; +} + +char * +tree_binary_expression::oper (void) const +{ + static char *op; + switch (etype) + { + case tree_expression::add: op = "+"; break; + case tree_expression::subtract: op = "-"; break; + case tree_expression::multiply: op = "*"; break; + case tree_expression::el_mul: op = ".*"; break; + case tree_expression::divide: op = "/"; break; + case tree_expression::el_div: op = "./"; break; + case tree_expression::leftdiv: op = "\\"; break; + case tree_expression::el_leftdiv: op = ".\\"; break; + case tree_expression::power: op = "^"; break; + case tree_expression::elem_pow: op = ".^"; break; + case tree_expression::cmp_lt: op = "<"; break; + case tree_expression::cmp_le: op = "<="; break; + case tree_expression::cmp_eq: op = "=="; break; + case tree_expression::cmp_ge: op = ">="; break; + case tree_expression::cmp_gt: op = ">"; break; + case tree_expression::cmp_ne: op = "!="; break; + case tree_expression::and_and: op = "&&"; break; + case tree_expression::or_or: op = "||"; break; + case tree_expression::and: op = "&"; break; + case tree_expression::or: op = "|"; break; + default: op = "unknown"; break; + } + return op; +} + +void +tree_binary_expression::eval_error (void) +{ + if (error_state > 0) + { + char *op = oper (); + + ::error ("evaluating binary operator `%s' near line %d, column %d", + op, line (), column ()); + } +} + +void +tree_binary_expression::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + if (op1) + op1->print_code (os); + + os << " " << oper () << " "; + + if (op2) + op2->print_code (os); + + if (in_parens) + os << ")"; +} + +// Assignment expressions. + +tree_constant +tree_assignment_expression::eval (int print) +{ + panic ("invalid evaluation of generic expression"); + return tree_constant (); +} + +// Simple assignment expressions. + +tree_simple_assignment_expression::~tree_simple_assignment_expression (void) +{ + if (! preserve) + { + delete lhs; + delete index; + } + delete rhs; +} + +tree_constant +tree_simple_assignment_expression::eval (int print) +{ + assert (etype == tree_expression::assignment); + + tree_constant ans; + tree_constant retval; + + if (error_state) + return retval; + + if (rhs) + { + Octave_object tmp = rhs->eval (0); + tree_constant rhs_val = tmp(0); + if (error_state) + { + if (error_state) + eval_error (); + } + else if (! index) + { + ans = lhs->assign (rhs_val); + if (error_state) + eval_error (); + } + else + { +// Extract the arguments into a simple vector. + Octave_object args = index->convert_to_const_vector (); + + int nargin = args.length (); + + if (error_state) + eval_error (); + else if (nargin > 1) + { + ans = lhs->assign (rhs_val, args); + if (error_state) + eval_error (); + } + } + } + + if (! error_state && ans.is_defined ()) + { + int pad_after = 0; + if (print && user_pref.print_answer_id_name) + { + if (print_as_scalar (ans)) + { + ostrstream output_buf; + output_buf << lhs->name () << " = " << ends; + maybe_page_output (output_buf); + } + else + { + pad_after = 1; + ostrstream output_buf; + output_buf << lhs->name () << " =\n\n" << ends; + maybe_page_output (output_buf); + } + } + + retval = ans.eval (print); + + if (print && pad_after) + { + ostrstream output_buf; + output_buf << "\n" << ends; + maybe_page_output (output_buf); + } + } + + return retval; +} + +void +tree_simple_assignment_expression::eval_error (void) +{ + if (error_state > 0) + { + int l = line (); + int c = column (); + if (l != -1 && c != -1) + ::error ("evaluating assignment expression near line %d, column %d", + l, c); +// else +// error ("evaluating assignment expression"); + } +} + +void +tree_simple_assignment_expression::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + if (! is_ans_assign ()) + { + if (lhs) + lhs->print_code (os); + + if (index) + { + os << " ("; + index->print_code (os); + os << ")"; + } + + os << " = "; + } + + if (rhs) + rhs->print_code (os); + + if (in_parens) + os << ")"; +} + +// Multi-valued assignmnt expressions. + +tree_multi_assignment_expression::~tree_multi_assignment_expression (void) +{ + delete lhs; + delete rhs; +} + +tree_constant +tree_multi_assignment_expression::eval (int print) +{ + tree_constant retval; + + if (error_state) + return retval; + + Octave_object tmp_args; + Octave_object result = eval (print, 1, tmp_args); + + if (result.length () > 0) + retval = result(0); + + return retval; +} + +Octave_object +tree_multi_assignment_expression::eval (int print, int nargout, + const Octave_object& args) +{ + assert (etype == tree_expression::multi_assignment); + + if (error_state || ! rhs) + return Octave_object (); + + nargout = lhs->length (); + Octave_object tmp_args; + Octave_object results = rhs->eval (0, nargout, tmp_args); + + if (error_state) + eval_error (); + + int ma_line = line (); + int ma_column = column (); + + if (results.length () > 0) + { + int i = 0; + int pad_after = 0; + int last_was_scalar_type = 0; + for (Pix p = lhs->first (); p != 0; lhs->next (p)) + { + tree_index_expression *lhs_expr = (*lhs) (p); + + if (i < nargout) + { +// XXX FIXME? XXX -- this is apparently the way Matlab works, but +// maybe we should have the option of skipping the assignment instead. + + tree_constant *tmp = 0; + if (results(i).is_undefined ()) + { + Matrix m; + tmp = new tree_constant (m); + } + else + tmp = new tree_constant (results(i)); + + tree_simple_assignment_expression tmp_expr + (lhs_expr, tmp, 1, 0, ma_line, ma_column); + + results(i) = tmp_expr.eval (0); // May change + + if (error_state) + break; + + if (print && pad_after) + { + ostrstream output_buf; + output_buf << "\n" << '\0'; + maybe_page_output (output_buf); + } + + if (print && user_pref.print_answer_id_name) + { + tree_identifier *tmp_id = lhs_expr->ident (); + char *tmp_nm = tmp_id->name (); + + if (print_as_scalar (results(i))) + { + ostrstream output_buf; + output_buf << tmp_nm << " = " << '\0'; + maybe_page_output (output_buf); + last_was_scalar_type = 1; + } + else + { + ostrstream output_buf; + output_buf << tmp_nm << " =\n\n" << '\0'; + maybe_page_output (output_buf); + last_was_scalar_type = 0; + } + } + + results(i).eval (print); + + pad_after++; + i++; + } + else + { + tree_simple_assignment_expression tmp_expr + (lhs_expr, 0, 1, 0, ma_line, ma_column); + + tmp_expr.eval (0); + + if (error_state) + break; + + if (last_was_scalar_type && i == 1) + pad_after = 0; + + break; + } + } + + if (print && pad_after) + { + ostrstream output_buf; + output_buf << "\n" << '\0'; + maybe_page_output (output_buf); + } + } + + return results; +} + +void +tree_multi_assignment_expression::eval_error (void) +{ + if (error_state > 0) + ::error ("evaluating assignment expression near line %d, column %d", + line (), column ()); +} + +void +tree_multi_assignment_expression::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + if (lhs) + { + int len = lhs->length (); + + if (len > 1) + os << "["; + + lhs->print_code (os); + + if (len > 1) + os << "]"; + } + + os << " = "; + + if (rhs) + rhs->print_code (os); + + if (in_parens) + os << ")"; +} + +// Colon expressions. + +tree_colon_expression * +tree_colon_expression::chain (tree_expression *t) +{ + tree_colon_expression *retval = 0; + if (! op1 || op3) + ::error ("invalid colon expression"); + else + { + op3 = op2; // Stupid syntax. + op2 = t; + + retval = this; + } + return retval; +} + +tree_constant +tree_colon_expression::eval (int print) +{ + tree_constant retval; + + if (error_state || ! op1 || ! op2) + return retval; + + Octave_object otmp = op1->eval (0); + tree_constant tmp = otmp(0); + + if (tmp.is_undefined ()) + { + eval_error ("invalid null value in colon expression"); + return retval; + } + + tmp = tmp.make_numeric (); + if (tmp.const_type () != tree_constant_rep::scalar_constant + && tmp.const_type () != tree_constant_rep::complex_scalar_constant) + { + eval_error ("base for colon expression must be a scalar"); + return retval; + } + double base = tmp.double_value (); + + otmp = op2->eval (0); + tmp = otmp(0); + + if (tmp.is_undefined ()) + { + eval_error ("invalid null value in colon expression"); + return retval; + } + + tmp = tmp.make_numeric (); + if (tmp.const_type () != tree_constant_rep::scalar_constant + && tmp.const_type () != tree_constant_rep::complex_scalar_constant) + { + eval_error ("limit for colon expression must be a scalar"); + return retval; + } + double limit = tmp.double_value (); + + double inc = 1.0; + if (op3) + { + otmp = op3->eval (0); + tmp = otmp(0); + + if (tmp.is_undefined ()) + { + eval_error ("invalid null value in colon expression"); + return retval; + } + + tmp = tmp.make_numeric (); + if (tmp.const_type () != tree_constant_rep::scalar_constant + && tmp.const_type () != tree_constant_rep::complex_scalar_constant) + { + eval_error ("increment for colon expression must be a scalar"); + return retval; + } + else + inc = tmp.double_value (); + } + + retval = tree_constant (base, limit, inc); + + if (error_state) + { + if (error_state) + eval_error ("evaluating colon expression"); + return tree_constant (); + } + + return retval; +} + +void +tree_colon_expression::eval_error (const char *s) +{ + if (error_state > 0) + ::error ("%s near line %d column %d", s, line (), column ()); +} + +void +tree_colon_expression::print_code (ostream& os) +{ + print_code_indent (os); + + if (in_parens) + os << "("; + + if (op1) + op1->print_code (os); + +// Stupid syntax. + + if (op3) + { + os << ":"; + op3->print_code (os); + } + + if (op2) + { + os << ":"; + op2->print_code (os); + } + + if (in_parens) + os << ")"; +} + +// Builtin functions. + +tree_builtin::tree_builtin (const char *nm) +{ + nargin_max = -1; + nargout_max = -1; + is_mapper = 0; + fcn = 0; + if (nm) + my_name = strsave (nm); +} + +tree_builtin::tree_builtin (int i_max, int o_max, Mapper_fcn& m_fcn, + const char *nm) +{ + nargin_max = i_max; + nargout_max = o_max; + mapper_fcn = m_fcn; + is_mapper = 1; + fcn = 0; + if (nm) + my_name = strsave (nm); +} + +tree_builtin::tree_builtin (int i_max, int o_max, Octave_builtin_fcn g_fcn, + const char *nm) +{ + nargin_max = i_max; + nargout_max = o_max; + is_mapper = 0; + fcn = g_fcn; + if (nm) + my_name = strsave (nm); +} + +tree_constant +tree_builtin::eval (int print) +{ + tree_constant retval; + + if (error_state) + return retval; + + if (fcn) + { + Octave_object args; + args(0) = tree_constant (my_name); + Octave_object tmp = (*fcn) (args, 1); + if (tmp.length () > 0) + retval = tmp(0); + } + else // Assume mapper function + ::error ("%s: argument expected", my_name); + + return retval; +} + +Octave_object +tree_builtin::eval (int print, int nargout, const Octave_object& args) +{ + Octave_object retval; + + if (error_state) + return retval; + + int nargin = args.length (); + + if (fcn) + { + if (any_arg_is_magic_colon (args)) + ::error ("invalid use of colon in function argument list"); + else + retval = (*fcn) (args, nargout); + } + else if (is_mapper) + { + if (nargin > nargin_max) + ::error ("%s: too many arguments", my_name); + else if (nargin > 0 && args.length () > 0 && args(1).is_defined ()) + { + tree_constant tmp = args(1).mapper (mapper_fcn, 0); + retval.resize (1); + retval(0) = tmp; + } + } + else + panic_impossible (); + + return retval; +} + +int +tree_builtin::max_expected_args (void) +{ + int ea = nargin_max; + if (nargin_max < 0) + ea = INT_MAX; + else + ea = nargin_max; + return ea; +} + // User defined functions. #if 0 @@ -1447,9 +2312,66 @@ } } +void +tree_function::print_code (ostream& os) +{ + print_code_reset (); + + print_code_indent (os); + + os << "function "; + + if (ret_list) + { + int len = ret_list->length (); + + if (len > 1) + os << "["; + + ret_list->print_code (os); + + if (len > 1) + os << "]"; + + os << " = "; + } + + os << (fcn_name ? fcn_name : "(null)") << " "; + + if (param_list) + { + int len = param_list->length (); + if (len > 0) + os << "("; + + param_list->print_code (os); + + if (len > 0) + { + os << ")"; + print_code_new_line (os); + } + } + else + { + os << "()"; + print_code_new_line (os); + } + + if (cmd_list) + { + increment_indent_level (); + cmd_list->print_code (os); + } + + os << "endfunction"; + + print_code_new_line (os); +} + DEFUN ("va_arg", Fva_arg, Sva_arg, 1, 1, "va_arg (): return next argument in a function that takes a\n\ -varible number of parameters") +variable number of parameters") { Octave_object retval; @@ -1505,785 +2427,6 @@ return retval; } -// Expressions. - -tree_constant -tree_expression::eval (int print) -{ - panic ("invalid evaluation of generic expression"); - return tree_constant (); -} - -Octave_object -tree_expression::eval (int print, int nargout, const Octave_object& args) -{ - panic ("invalid evaluation of generic expression"); - return Octave_object (); -} - -// Prefix expressions. - -tree_constant -tree_prefix_expression::eval (int print) -{ - tree_constant retval; - - if (error_state) - return retval; - - if (id) - { - id->bump_value (etype); - retval = id->eval (print); - if (error_state) - { - retval = tree_constant (); - if (error_state) - eval_error (); - } - } - return retval; -} - -void -tree_prefix_expression::eval_error (void) -{ - if (error_state > 0) - { - char *op; - switch (etype) - { - case tree_expression::increment: op = "++"; break; - case tree_expression::decrement: op = "--"; break; - default: op = "unknown"; break; - } - - ::error ("evaluating prefix operator `%s' near line %d, column %d", - op, line (), column ()); - } -} - -// Postfix expressions. - -tree_constant -tree_postfix_expression::eval (int print) -{ - tree_constant retval; - - if (error_state) - return retval; - - if (id) - { - retval = id->eval (print); - id->bump_value (etype); - if (error_state) - { - retval = tree_constant (); - if (error_state) - eval_error (); - } - } - return retval; -} - -void -tree_postfix_expression::eval_error (void) -{ - if (error_state > 0) - { - char *op; - switch (etype) - { - case tree_expression::increment: op = "++"; break; - case tree_expression::decrement: op = "--"; break; - default: op = "unknown"; break; - } - - ::error ("evaluating postfix operator `%s' near line %d, column %d", - op, line (), column ()); - } -} - -// Unary expressions. - -tree_constant -tree_unary_expression::eval (int print) -{ - if (error_state) - return tree_constant (); - - tree_constant ans; - - switch (etype) - { - case tree_expression::not: - case tree_expression::uminus: - case tree_expression::hermitian: - case tree_expression::transpose: - if (op) - { - tree_constant u = op->eval (0); - if (error_state) - eval_error (); - else if (u.is_defined ()) - { - ans = do_unary_op (u, etype); - if (error_state) - { - ans = tree_constant (); - if (error_state) - eval_error (); - } - } - } - break; - default: - ::error ("unary operator %d not implemented", etype); - break; - } - - return ans; -} - -void -tree_unary_expression::eval_error (void) -{ - if (error_state > 0) - { - char *op; - switch (etype) - { - case tree_expression::not: op = "!"; break; - case tree_expression::uminus: op = "-"; break; - case tree_expression::hermitian: op = "'"; break; - case tree_expression::transpose: op = ".'"; break; - default: op = "unknown"; break; - } - - ::error ("evaluating unary operator `%s' near line %d, column %d", - op, line (), column ()); - } -} - -// Binary expressions. - -tree_constant -tree_binary_expression::eval (int print) -{ - if (error_state) - return tree_constant (); - - tree_constant ans; - switch (etype) - { - case tree_expression::add: - case tree_expression::subtract: - case tree_expression::multiply: - case tree_expression::el_mul: - case tree_expression::divide: - case tree_expression::el_div: - case tree_expression::leftdiv: - case tree_expression::el_leftdiv: - case tree_expression::power: - case tree_expression::elem_pow: - case tree_expression::cmp_lt: - case tree_expression::cmp_le: - case tree_expression::cmp_eq: - case tree_expression::cmp_ge: - case tree_expression::cmp_gt: - case tree_expression::cmp_ne: - case tree_expression::and: - case tree_expression::or: - if (op1) - { - tree_constant a = op1->eval (0); - if (error_state) - eval_error (); - else if (a.is_defined () && op2) - { - tree_constant b = op2->eval (0); - if (error_state) - eval_error (); - else if (b.is_defined ()) - { - ans = do_binary_op (a, b, etype); - if (error_state) - { - ans = tree_constant (); - if (error_state) - eval_error (); - } - } - } - } - break; - case tree_expression::and_and: - case tree_expression::or_or: - { - int result = 0; - if (op1) - { - tree_constant a = op1->eval (0); - if (error_state) - { - eval_error (); - break; - } - - int a_true = a.is_true (); - if (error_state) - { - eval_error (); - break; - } - - if (a_true) - { - if (etype == tree_expression::or_or) - { - result = 1; - goto done; - } - } - else - { - if (etype == tree_expression::and_and) - { - result = 0; - goto done; - } - } - - if (op2) - { - tree_constant b = op2->eval (0); - if (error_state) - { - eval_error (); - break; - } - - result = b.is_true (); - if (error_state) - { - eval_error (); - break; - } - } - } - done: - ans = tree_constant ((double) result); - } - break; - default: - ::error ("binary operator %d not implemented", etype); - break; - } - - return ans; -} - -void -tree_binary_expression::eval_error (void) -{ - if (error_state > 0) - { - char *op; - switch (etype) - { - case tree_expression::add: op = "+"; break; - case tree_expression::subtract: op = "-"; break; - case tree_expression::multiply: op = "*"; break; - case tree_expression::el_mul: op = ".*"; break; - case tree_expression::divide: op = "/"; break; - case tree_expression::el_div: op = "./"; break; - case tree_expression::leftdiv: op = "\\"; break; - case tree_expression::el_leftdiv: op = ".\\"; break; - case tree_expression::power: op = "^"; break; - case tree_expression::elem_pow: op = ".^"; break; - case tree_expression::cmp_lt: op = "<"; break; - case tree_expression::cmp_le: op = "<="; break; - case tree_expression::cmp_eq: op = "=="; break; - case tree_expression::cmp_ge: op = ">="; break; - case tree_expression::cmp_gt: op = ">"; break; - case tree_expression::cmp_ne: op = "!="; break; - case tree_expression::and_and: op = "&&"; break; - case tree_expression::or_or: op = "||"; break; - case tree_expression::and: op = "&"; break; - case tree_expression::or: op = "|"; break; - default: op = "unknown"; break; - } - - ::error ("evaluating binary operator `%s' near line %d, column %d", - op, line (), column ()); - } -} - -// Assignment expressions. - -tree_constant -tree_assignment_expression::eval (int print) -{ - panic ("invalid evaluation of generic expression"); - return tree_constant (); -} - -// Simple assignment expressions. - -tree_simple_assignment_expression::~tree_simple_assignment_expression (void) -{ - if (! preserve) - { - delete lhs; - delete index; - } - delete rhs; -} - -tree_constant -tree_simple_assignment_expression::eval (int print) -{ - assert (etype == tree_expression::assignment); - - tree_constant ans; - tree_constant retval; - - if (error_state) - return retval; - - if (rhs) - { - tree_constant rhs_val = rhs->eval (0); - if (error_state) - { - if (error_state) - eval_error (); - } - else if (! index) - { - ans = lhs->assign (rhs_val); - if (error_state) - eval_error (); - } - else - { -// Extract the arguments into a simple vector. - Octave_object args = index->convert_to_const_vector (); - - int nargin = args.length (); - - if (error_state) - eval_error (); - else if (nargin > 1) - { - ans = lhs->assign (rhs_val, args); - if (error_state) - eval_error (); - } - } - } - - if (! error_state && ans.is_defined ()) - { - int pad_after = 0; - if (print && user_pref.print_answer_id_name) - { - if (print_as_scalar (ans)) - { - ostrstream output_buf; - output_buf << lhs->name () << " = " << ends; - maybe_page_output (output_buf); - } - else - { - pad_after = 1; - ostrstream output_buf; - output_buf << lhs->name () << " =\n\n" << ends; - maybe_page_output (output_buf); - } - } - - retval = ans.eval (print); - - if (print && pad_after) - { - ostrstream output_buf; - output_buf << "\n" << ends; - maybe_page_output (output_buf); - } - } - - return retval; -} - -void -tree_simple_assignment_expression::eval_error (void) -{ - if (error_state > 0) - { - int l = line (); - int c = column (); - if (l != -1 && c != -1) - ::error ("evaluating assignment expression near line %d, column %d", - l, c); -// else -// error ("evaluating assignment expression"); - } -} - -// Multi-valued assignmnt expressions. - -tree_multi_assignment_expression::~tree_multi_assignment_expression (void) -{ - delete lhs; - delete rhs; -} - -tree_constant -tree_multi_assignment_expression::eval (int print) -{ - tree_constant retval; - - if (error_state) - return retval; - - Octave_object tmp_args; - Octave_object result = eval (print, 1, tmp_args); - - if (result.length () > 0) - retval = result(0); - - return retval; -} - -Octave_object -tree_multi_assignment_expression::eval (int print, int nargout, - const Octave_object& args) -{ - assert (etype == tree_expression::multi_assignment); - - if (error_state || ! rhs) - return Octave_object (); - - nargout = lhs->length (); - Octave_object tmp_args; - Octave_object results = rhs->eval (0, nargout, tmp_args); - - if (error_state) - eval_error (); - - int ma_line = line (); - int ma_column = column (); - - if (results.length () > 0) - { - int i = 0; - int pad_after = 0; - int last_was_scalar_type = 0; - for (Pix p = lhs->first (); p != 0; lhs->next (p)) - { - tree_index_expression *lhs_expr = (*lhs) (p); - - if (i < nargout) - { -// XXX FIXME? XXX -- this is apparently the way Matlab works, but -// maybe we should have the option of skipping the assignment instead. - - tree_constant *tmp = 0; - if (results(i).is_undefined ()) - { - Matrix m; - tmp = new tree_constant (m); - } - else - tmp = new tree_constant (results(i)); - - tree_simple_assignment_expression tmp_expr - (lhs_expr, tmp, 1, ma_line, ma_column); - - results(i) = tmp_expr.eval (0); // May change - - if (error_state) - break; - - if (print && pad_after) - { - ostrstream output_buf; - output_buf << "\n" << '\0'; - maybe_page_output (output_buf); - } - - if (print && user_pref.print_answer_id_name) - { - tree_identifier *tmp_id = lhs_expr->ident (); - char *tmp_nm = tmp_id->name (); - - if (print_as_scalar (results(i))) - { - ostrstream output_buf; - output_buf << tmp_nm << " = " << '\0'; - maybe_page_output (output_buf); - last_was_scalar_type = 1; - } - else - { - ostrstream output_buf; - output_buf << tmp_nm << " =\n\n" << '\0'; - maybe_page_output (output_buf); - last_was_scalar_type = 0; - } - } - - results(i).eval (print); - - pad_after++; - i++; - } - else - { - tree_simple_assignment_expression tmp_expr - (lhs_expr, 0, 1, ma_line, ma_column); - - tmp_expr.eval (0); - - if (error_state) - break; - - if (last_was_scalar_type && i == 1) - pad_after = 0; - - break; - } - } - - if (print && pad_after) - { - ostrstream output_buf; - output_buf << "\n" << '\0'; - maybe_page_output (output_buf); - } - } - - return results; -} - -void -tree_multi_assignment_expression::eval_error (void) -{ - if (error_state > 0) - ::error ("evaluating assignment expression near line %d, column %d", - line (), column ()); -} - -// Colon expressions. - -tree_colon_expression * -tree_colon_expression::chain (tree_expression *t) -{ - tree_colon_expression *retval = 0; - if (! op1 || op3) - ::error ("invalid colon expression"); - else - { - op3 = op2; // Stupid syntax. - op2 = t; - - retval = this; - } - return retval; -} - -tree_constant -tree_colon_expression::eval (int print) -{ - tree_constant retval; - - if (error_state || ! op1 || ! op2) - return retval; - - tree_constant tmp; - - tmp = op1->eval (0); - - if (tmp.is_undefined ()) - { - eval_error ("invalid null value in colon expression"); - return retval; - } - - tmp = tmp.make_numeric (); - if (tmp.const_type () != tree_constant_rep::scalar_constant - && tmp.const_type () != tree_constant_rep::complex_scalar_constant) - { - eval_error ("base for colon expression must be a scalar"); - return retval; - } - double base = tmp.double_value (); - - tmp = op2->eval (0); - - if (tmp.is_undefined ()) - { - eval_error ("invalid null value in colon expression"); - return retval; - } - - tmp = tmp.make_numeric (); - if (tmp.const_type () != tree_constant_rep::scalar_constant - && tmp.const_type () != tree_constant_rep::complex_scalar_constant) - { - eval_error ("limit for colon expression must be a scalar"); - return retval; - } - double limit = tmp.double_value (); - - double inc = 1.0; - if (op3) - { - tmp = op3->eval (0); - - if (tmp.is_undefined ()) - { - eval_error ("invalid null value in colon expression"); - return retval; - } - - tmp = tmp.make_numeric (); - if (tmp.const_type () != tree_constant_rep::scalar_constant - && tmp.const_type () != tree_constant_rep::complex_scalar_constant) - { - eval_error ("increment for colon expression must be a scalar"); - return retval; - } - else - inc = tmp.double_value (); - } - - retval = tree_constant (base, limit, inc); - - if (error_state) - { - if (error_state) - eval_error ("evaluating colon expression"); - return tree_constant (); - } - - return retval; -} - -void -tree_colon_expression::eval_error (const char *s) -{ - if (error_state > 0) - ::error ("%s near line %d column %d", s, line (), column ()); -} - -// Index expressions. - -tree_index_expression::~tree_index_expression (void) -{ - delete id; - delete list; -} - -tree_constant -tree_index_expression::eval (int print) -{ - tree_constant retval; - - if (error_state) - return retval; - - if (list) - { -// Extract the arguments into a simple vector. - Octave_object args = list->convert_to_const_vector (); -// Don't pass null arguments. - int nargin = args.length (); - if (error_state) - eval_error (); - else if (nargin > 1 && all_args_defined (args)) - { - Octave_object tmp = id->eval (print, 1, args); - - if (error_state) - eval_error (); - - if (tmp.length () > 0) - retval = tmp(0); - } - } - else - { - retval = id->eval (print); - if (error_state) - eval_error (); - } - - return retval; -} - -Octave_object -tree_index_expression::eval (int print, int nargout, const Octave_object& args) -{ - Octave_object retval; - - if (error_state) - return retval; - - if (list) - { -// Extract the arguments into a simple vector. - Octave_object args = list->convert_to_const_vector (); -// Don't pass null arguments. - if (error_state) - eval_error (); - else if (args.length () > 1 && all_args_defined (args)) - { - retval = id->eval (print, nargout, args); - if (error_state) - eval_error (); - } - } - else - { - Octave_object tmp_args; - retval = id->eval (print, nargout, tmp_args); - if (error_state) - eval_error (); - } - - return retval; -} - -void -tree_index_expression::eval_error (void) -{ - if (error_state > 0) - { - int l = line (); - int c = column (); - char *fmt; - if (l != -1 && c != -1) - { - if (list) - fmt = "evaluating index expression near line %d, column %d"; - else - fmt = "evaluating expression near line %d, column %d"; - - ::error (fmt, l, c); - } - else - { - if (list) - ::error ("evaluating index expression"); - else - ::error ("evaluating expression"); - } - } -} - /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/pt-exp-base.h +++ b/src/pt-exp-base.h @@ -30,6 +30,7 @@ #include <time.h> #include <stdio.h> +#include <iostream.h> #include "variables.h" #include "mappers.h" @@ -67,6 +68,8 @@ tree_expression : public tree { public: + int in_parens; + enum type { unknown, @@ -105,7 +108,10 @@ }; tree_expression (int l = -1, int c = -1) : tree (l, c) - { etype = unknown; } + { + in_parens = 0; + etype = unknown; + } ~tree_expression (void) { } @@ -149,14 +155,14 @@ tree_matrix (void) { - dir_next = tree_matrix::md_none; + direction = tree_matrix::md_none; element = 0; next = 0; } tree_matrix (tree_expression *e, tree_matrix::dir d) { - dir_next = d; + direction = d; element = e; next = 0; } @@ -171,8 +177,10 @@ tree_constant eval (int print); + void print_code (ostream& os); + private: - tree_matrix::dir dir_next; // Direction to the next element. + tree_matrix::dir direction; // Direction from the previous element. tree_expression *element; tree_matrix *next; }; @@ -224,13 +232,13 @@ friend class tree_index_expression; public: - tree_identifier (int l = -1, int c = -1) + tree_identifier (int l = -1, int c = -1) : tree_fvc (l, c) { sym = 0; maybe_do_ans_assign = 0; } - tree_identifier (symbol_record *s, int l = -1, int c = -1) + tree_identifier (symbol_record *s, int l = -1, int c = -1) : tree_fvc (l, c) { sym = s; maybe_do_ans_assign = 0; @@ -255,10 +263,6 @@ void bump_value (tree_expression::type); - int load_fcn_from_file (int exec_script = 1); - - int parse_fcn_file (int exec_script = 1, char *ff = 0); - tree_fvc *do_lookup (int& script_file_executed); void link_to_global (void) @@ -278,6 +282,8 @@ void eval_undefined_error (void); + void print_code (ostream& os); + private: symbol_record *sym; int maybe_do_ans_assign; @@ -333,6 +339,8 @@ void eval_error (void); + void print_code (ostream& os); + private: tree_identifier *id; tree_argument_list *list; @@ -368,6 +376,10 @@ int is_prefix_expression (void) const { return 1; } + char *oper (void) const; + + void print_code (ostream& os); + private: tree_identifier *id; }; @@ -399,6 +411,10 @@ void eval_error (void); + char *oper (void) const; + + void print_code (ostream& os); + private: tree_identifier *id; }; @@ -430,6 +446,10 @@ void eval_error (void); + char *oper (void) const; + + void print_code (ostream& os); + private: tree_expression *op; }; @@ -466,6 +486,10 @@ void eval_error (void); + char *oper (void) const; + + void print_code (ostream& os); + private: tree_expression *op1; tree_expression *op2; @@ -477,14 +501,9 @@ tree_assignment_expression : public tree_expression { public: - int in_parens; - tree_assignment_expression (int l = -1, int c = -1) : tree_expression (l, c) - { - in_parens = 0; - etype = tree_expression::assignment; - } + { etype = tree_expression::assignment; } ~tree_assignment_expression (void) { } @@ -500,38 +519,42 @@ tree_simple_assignment_expression : public tree_assignment_expression { public: - tree_simple_assignment_expression (int plhs = 0, int l = -1, int c = -1) + void init (int plhs, int ans_assign) + { + etype = tree_expression::assignment; + lhs = 0; + index = 0; + rhs = 0; + preserve = plhs; + ans_ass = ans_assign; + } + + tree_simple_assignment_expression (int plhs = 0, int ans_assign = 0, + int l = -1, int c = -1) : tree_assignment_expression (l, c) - { - etype = tree_expression::assignment; - lhs = 0; - index = 0; - rhs = 0; - preserve = plhs; - } + { init (plhs, ans_assign); } tree_simple_assignment_expression (tree_identifier *i, tree_expression *r, - int plhs = 0, int l = -1, int c = -1) + int plhs = 0, int ans_assign = 0, + int l = -1, int c = -1) : tree_assignment_expression (l, c) { - etype = tree_expression::assignment; + init (plhs, ans_assign); lhs = i; - index = 0; rhs = r; - preserve = plhs; } tree_simple_assignment_expression (tree_index_expression *idx_expr, tree_expression *r, - int plhs = 0, int l = -1, int c = -1) + int plhs = 0, int ans_assign = 0, + int l = -1, int c = -1) : tree_assignment_expression (l, c) { - etype = tree_expression::assignment; + init (plhs, ans_assign); lhs = idx_expr->ident (); index = idx_expr->arg_list (); rhs = r; - preserve = plhs; } ~tree_simple_assignment_expression (void); @@ -539,15 +562,21 @@ tree_identifier *left_hand_side (void) { return lhs; } + int is_ans_assign (void) + { return ans_ass; } + tree_constant eval (int print); void eval_error (void); + void print_code (ostream& os); + private: tree_identifier *lhs; tree_argument_list *index; tree_expression *rhs; int preserve; + int ans_ass; }; // Multi-valued assignment expressions. @@ -582,6 +611,8 @@ void eval_error (void); + void print_code (ostream& os); + private: tree_return_list *lhs; tree_expression *rhs; @@ -624,6 +655,8 @@ void eval_error (const char *s); + void print_code (ostream& os); + private: tree_expression *op1; tree_expression *op2; @@ -660,6 +693,11 @@ int max_expected_args (void); + void print_code (ostream& os) + { + os << my_name << " can't be printed because it is a builtin function\n"; + } + private: int nargin_max; int nargout_max; @@ -745,6 +783,8 @@ void traceback_error (void); + void print_code (ostream& os); + private: int call_depth; tree_parameter_list *param_list;
--- a/src/pt-misc.cc +++ b/src/pt-misc.cc @@ -34,6 +34,8 @@ #include <unistd.h> #endif +#include <iostream.h> + #include "error.h" #include "tree.h" #include "tree-misc.h" @@ -59,6 +61,31 @@ delete expression; } +void +tree_statement::print_code (ostream& os) +{ + if (command) + { + command->print_code (os); + + if (! print_flag) + os << ";"; + + command->print_code_new_line (os); + } + else if (expression) + { + expression->print_code (os); + + if (! print_flag) + os << ";"; + + expression->print_code_new_line (os); + } + + +} + tree_constant tree_statement_list::eval (int print) { @@ -102,6 +129,18 @@ return retval; } +void +tree_statement_list::print_code (ostream& os) +{ + for (Pix p = first (); p != 0; next (p)) + { + tree_statement *elt = this->operator () (p); + + if (elt) + elt->print_code (os); + } +} + Octave_object tree_argument_list::convert_to_const_vector (void) { @@ -135,6 +174,27 @@ return args; } +void +tree_argument_list::print_code (ostream& os) +{ + Pix p = first (); + + while (p) + { + tree_expression *elt = this->operator () (p); + + next (p); + + if (elt) + { + elt->print_code (os); + + if (p) + os << ", "; + } + } +} + // Parameter lists. void @@ -225,6 +285,52 @@ } void +tree_parameter_list::print_code (ostream& os) +{ + Pix p = first (); + + while (p) + { + tree_identifier *elt = this->operator () (p); + + next (p); + + if (elt) + { + elt->print_code (os); + + if (p) + os << ", "; + } + } +} + +// Return lists. + +void +tree_return_list::print_code (ostream& os) +{ + Pix p = first (); + + while (p) + { + tree_index_expression *elt = this->operator () (p); + + next (p); + + if (elt) + { + elt->print_code (os); + + if (p) + os << ", "; + } + } +} + +// Global. + +void tree_global::eval (void) { if (ident) @@ -243,6 +349,18 @@ } void +tree_global::print_code (ostream& os) +{ + if (ident) + ident->print_code (os); + + if (assign_expr) + assign_expr->print_code (os); +} + +// Global initializer lists. + +void tree_global_init_list::eval (void) { for (Pix p = first (); p != 0; next (p)) @@ -252,6 +370,29 @@ } } +void +tree_global_init_list::print_code (ostream& os) +{ + Pix p = first (); + + while (p) + { + tree_global *elt = this->operator () (p); + + next (p); + + if (elt) + { + elt->print_code (os); + + if (p) + os << ", "; + } + } +} + +// If. + int tree_if_clause::eval (void) { @@ -309,6 +450,38 @@ } void +tree_if_clause::print_code (ostream& os) +{ + if (expr) + { + expr->print_code (os); + + print_code_new_line (os); + + increment_indent_level (); + } + else + { + print_code_indent (os); + + os << "else"; + + print_code_new_line (os); + + increment_indent_level (); + } + + if (list) + { + list->print_code (os); + + decrement_indent_level (); + } +} + +// List of if commands. + +void tree_if_command_list::eval (void) { for (Pix p = first (); p != 0; next (p)) @@ -320,6 +493,35 @@ } } +void +tree_if_command_list::print_code (ostream& os) +{ + Pix p = first (); + + int first_elt = 1; + + while (p) + { + tree_if_clause *elt = this->operator () (p); + + next (p); + + if (elt) + { + if (p && ! first_elt) + { + print_code_indent (os); + + os << "elseif "; + } + + elt->print_code (os); + } + + first_elt = 0; + } +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/pt-misc.h +++ b/src/pt-misc.h @@ -28,6 +28,7 @@ #pragma interface #endif +class ostream; class Octave_object; class tree_constant; class tree_command; @@ -54,7 +55,7 @@ // A list of expressions and commands to be executed. class -tree_statement +tree_statement : public tree_print_code { friend class tree_statement_list; @@ -85,6 +86,8 @@ void set_print_flag (int print) { print_flag = print; } + void print_code (ostream& os); + private: tree_command *command; // Command to execute. tree_expression *expression; // Command to execute. @@ -92,7 +95,7 @@ }; class -tree_statement_list : public SLList<tree_statement *> +tree_statement_list : public SLList<tree_statement *>, public tree_print_code { public: tree_statement_list (void) : SLList<tree_statement *> () { } @@ -109,13 +112,15 @@ } tree_constant eval (int print); + + void print_code (ostream& os); }; // Argument lists. Used to hold the list of expressions that are the // arguments in a function call or index expression. class -tree_argument_list : public SLList<tree_expression *> +tree_argument_list : public SLList<tree_expression *>, public tree_print_code { public: tree_argument_list (void) : SLList<tree_expression *> () { } @@ -132,6 +137,8 @@ } Octave_object convert_to_const_vector (void); + + void print_code (ostream& os); }; // Parameter lists. Used to hold the list of input and output @@ -139,7 +146,7 @@ // only. class -tree_parameter_list : public SLList<tree_identifier *> +tree_parameter_list : public SLList<tree_identifier *>, public tree_print_code { public: tree_parameter_list (void) : SLList<tree_identifier *> () { } @@ -177,6 +184,8 @@ Octave_object convert_to_const_vector (void); + void print_code (ostream& os); + private: int marked_for_varargs; }; @@ -185,7 +194,8 @@ // assignment expressions. class -tree_return_list : public SLList<tree_index_expression *> +tree_return_list : public SLList<tree_index_expression *>, + public tree_print_code { public: tree_return_list (void) : SLList<tree_index_expression *> () { } @@ -201,12 +211,14 @@ delete t; } } + + void print_code (ostream& os); }; // List of expressions that make up a global statement. class -tree_global +tree_global : public tree_print_code { public: tree_global (void) @@ -235,13 +247,15 @@ void eval (void); + void print_code (ostream& os); + private: tree_identifier *ident; tree_simple_assignment_expression *assign_expr; }; class -tree_global_init_list : public SLList<tree_global *> +tree_global_init_list : public SLList<tree_global *>, public tree_print_code { public: tree_global_init_list (void) : SLList<tree_global *> () { } @@ -258,10 +272,12 @@ } void eval (void); + + void print_code (ostream& os); }; class -tree_if_clause +tree_if_clause : public tree_print_code { public: tree_if_clause (void) @@ -290,13 +306,15 @@ int eval (void); + void print_code (ostream& os); + private: tree_expression *expr; tree_statement_list *list; }; class -tree_if_command_list : public SLList<tree_if_clause *> +tree_if_command_list : public SLList<tree_if_clause *>, public tree_print_code { public: tree_if_command_list (void) : SLList<tree_if_clause *> () { } @@ -313,6 +331,8 @@ } void eval (void); + + void print_code (ostream& os); }; #endif
--- a/src/pt-plot.cc +++ b/src/pt-plot.cc @@ -51,7 +51,7 @@ extern "C" { - char *tilde_expand (char *s); /* From readline's tilde.c */ +#include <readline/tilde.h> } // The number of lines we\'ve plotted so far. @@ -69,11 +69,9 @@ // Pipe to gnuplot. static oprocstream plot_stream; -/* - * Plotting, eh? - */ +// Plotting, eh? -tree_plot_command::tree_plot_command (void) +tree_plot_command::tree_plot_command (void) : tree_command () { range = 0; plot_list = 0; @@ -81,6 +79,7 @@ } tree_plot_command::tree_plot_command (subplot_list *plt, int nd) + : tree_command () { range = 0; plot_list = plt; @@ -89,6 +88,7 @@ tree_plot_command::tree_plot_command (subplot_list *plt, plot_limits *rng, int nd) + : tree_command () { range = rng; plot_list = plt; @@ -771,9 +771,6 @@ return retval; } -/* - * Set plotting options. - */ DEFUN_TEXT ("show", Fshow, Sshow, -1, 1, "show [options]\n\ \n\
--- a/src/pt-plot.h +++ b/src/pt-plot.h @@ -28,6 +28,8 @@ #pragma interface #endif +#include <iostream.h> + class tree_command; class tree_plot_command; class plot_limits; @@ -37,8 +39,6 @@ class subplot; class subplot_list; -class ostream; - #include <SLList.h> #include "tree.h" @@ -55,6 +55,11 @@ void eval (void); + void print_code (ostream& os) + { + os << "<plot command printing not implemented yet>"; + } + private: int ndim; plot_limits *range;
--- a/src/tc-inlines.h +++ b/src/tc-inlines.h @@ -139,18 +139,6 @@ return c; } -static inline int -valid_scalar_indices (const Octave_object& args) -{ - int nargin = args.length (); - int valid = ((nargin == 3 - && args(2).valid_as_scalar_index () - && args(1).valid_as_scalar_index ()) - || (nargin == 2 && args(1).valid_as_scalar_index ())); - - return valid; -} - /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/tc-rep.cc +++ b/src/tc-rep.cc @@ -51,9 +51,7 @@ #include "tc-inlines.cc" -/* - * How about a few macros? - */ +// How about a few macros? #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) @@ -67,14 +65,12 @@ #define ABS(x) (((x) < 0) ? (-x) : (x)) #endif -/* - * The following are used by some of the functions in the - * tree_constant_rep class that must deal with real and complex - * matrices. This was not done with overloaded or virtual functions - * from the Matrix class because there is no clean way to do that -- - * the necessary functions (like elem) need to return values of - * different types... - */ +// The following are used by some of the functions in the +// tree_constant_rep class that must deal with real and complex +// matrices. This was not done with overloaded or virtual functions +// from the Matrix class because there is no clean way to do that -- +// the necessary functions (like elem) need to return values of +// different types... // Given a tree_constant, and the names to be used for the real and // complex matrix and their dimensions, declare a real or complex @@ -231,20 +227,33 @@ return 0; } +static int +valid_scalar_indices (const Octave_object& args) +{ + int nargin = args.length (); + + return ((nargin == 3 + && args(2).valid_as_scalar_index () + && args(1).valid_as_scalar_index ()) + || (nargin == 2 + && args(1).valid_as_scalar_index ())); +} + // Now, the classes. -/* - * The real representation of constants. - */ +// The real representation of constants. + tree_constant_rep::tree_constant_rep (void) { type_tag = unknown_constant; + orig_text = 0; } tree_constant_rep::tree_constant_rep (double d) { scalar = d; type_tag = scalar_constant; + orig_text = 0; } tree_constant_rep::tree_constant_rep (const Matrix& m) @@ -259,6 +268,7 @@ matrix = new Matrix (m); type_tag = matrix_constant; } + orig_text = 0; } tree_constant_rep::tree_constant_rep (const DiagMatrix& d) @@ -273,6 +283,7 @@ matrix = new Matrix (d); type_tag = matrix_constant; } + orig_text = 0; } tree_constant_rep::tree_constant_rep (const RowVector& v, int @@ -307,6 +318,7 @@ type_tag = matrix_constant; } } + orig_text = 0; } tree_constant_rep::tree_constant_rep (const ColumnVector& v, @@ -341,12 +353,14 @@ type_tag = matrix_constant; } } + orig_text = 0; } tree_constant_rep::tree_constant_rep (const Complex& c) { complex_scalar = new Complex (c); type_tag = complex_scalar_constant; + orig_text = 0; } tree_constant_rep::tree_constant_rep (const ComplexMatrix& m) @@ -361,6 +375,7 @@ complex_matrix = new ComplexMatrix (m); type_tag = complex_matrix_constant; } + orig_text = 0; } tree_constant_rep::tree_constant_rep (const ComplexDiagMatrix& d) @@ -375,6 +390,7 @@ complex_matrix = new ComplexMatrix (d); type_tag = complex_matrix_constant; } + orig_text = 0; } tree_constant_rep::tree_constant_rep (const ComplexRowVector& v, @@ -409,6 +425,7 @@ type_tag = complex_matrix_constant; } } + orig_text = 0; } tree_constant_rep::tree_constant_rep (const ComplexColumnVector& v, @@ -443,12 +460,14 @@ type_tag = complex_matrix_constant; } } + orig_text = 0; } tree_constant_rep::tree_constant_rep (const char *s) { string = strsave (s); type_tag = string_constant; + orig_text = 0; } tree_constant_rep::tree_constant_rep (double b, double l, double i) @@ -482,6 +501,7 @@ else panic_impossible (); } + orig_text = 0; } tree_constant_rep::tree_constant_rep (const Range& r) @@ -503,13 +523,15 @@ } else panic_impossible (); + + orig_text = 0; } tree_constant_rep::tree_constant_rep (tree_constant_rep::constant_type t) { assert (t == magic_colon); - type_tag = magic_colon; + orig_text = 0; } tree_constant_rep::tree_constant_rep (const tree_constant_rep& t) @@ -544,6 +566,8 @@ panic_impossible (); break; } + + orig_text = strsave (t.orig_text); } tree_constant_rep::~tree_constant_rep (void) @@ -575,6 +599,8 @@ panic_impossible (); break; } + + delete [] orig_text; } #if defined (MDEBUG) @@ -815,6 +841,12 @@ return retval; } +void +tree_constant_rep::stash_original_text (char *s) +{ + orig_text = strsave (s); +} + tree_constant_rep::constant_type tree_constant_rep::force_numeric (int force_str_conv) { @@ -1315,6 +1347,127 @@ } } +static char * +undo_string_escapes (char c) +{ + static char retval[2]; + retval[1] = '\0'; + + if (! c) + return 0; + + switch (c) + { + case '\a': + return "\\a"; + case '\b': // backspace + return "\\b"; + case '\f': // formfeed + return "\\f"; + case '\n': // newline + return "\\n"; + case '\r': // carriage return + return "\\r"; + case '\t': // horizontal tab + return "\\t"; + case '\v': // vertical tab + return "\\v"; + case '\\': // backslash + return "\\\\"; + case '"': // double quote + return "\\\""; + default: + retval[0] = c; + return retval; + } +} + +void +tree_constant_rep::print_code (ostream& os) +{ + int nr = rows (); + int nc = columns (); + + switch (type_tag) + { + case scalar_constant: + if (orig_text) + os << orig_text; + else + os << scalar; + break; + case matrix_constant: + if (nr == 0 || nc == 0) + os << "[]"; + else + panic_impossible (); + break; + case complex_scalar_constant: + { + double re = complex_scalar->real (); + double im = complex_scalar->imag (); + +// We don't collapse Re +/- Im into a complex number yet, so if we get +// here, we had better have a pure imaginary number that's positive... + + assert (re == 0.0 && im > 0.0); + + if (orig_text) + os << orig_text; + else + os << im; + +#if 0 + int sign_printed = 0; + + if (re != 0.0) + { + os << re; + + if (im > 0.0) + { + os << " + "; + sign_printed = 1; + } + else if (im < 0.0) + { + os << " - "; + sign_printed = 1; + } + } + + if (im != 0.0) + os << (sign_printed ? (im < 0.0 ? -im : im) : im); +#endif + } + break; + case complex_matrix_constant: + if (nr == 0 || nc == 0) + os << "[]"; + else + panic_impossible (); + break; + case string_constant: + { + os << "\""; + char *s, *t = string; + while (s = undo_string_escapes (*t++)) + os << s; + os << "\""; + } + break; + case range_constant: + panic_impossible (); + break; + case magic_colon: + os << ":"; + break; + default: + panic_impossible (); + break; + } +} + tree_constant tree_constant_rep::do_index (const Octave_object& args) { @@ -1968,7 +2121,7 @@ } break; case string_constant: - retval = tree_constant (*this); + retval = string; break; case magic_colon: default: @@ -2653,11 +2806,10 @@ return retval; } -/* - * Top-level tree-constant function that handles assignments. Only - * decide if the left-hand side is currently a scalar or a matrix and - * hand off to other functions to do the real work. - */ +// Top-level tree-constant function that handles assignments. Only +// decide if the left-hand side is currently a scalar or a matrix and +// hand off to other functions to do the real work. + void tree_constant_rep::assign (const tree_constant& rhs, const Octave_object& args) { @@ -2693,10 +2845,9 @@ } } -/* - * Assignments to scalars. If resize_on_range_error is true, - * this can convert the left-hand side to a matrix. - */ +// Assignments to scalars. If resize_on_range_error is true, +// this can convert the left-hand side to a matrix. + void tree_constant_rep::do_scalar_assignment (const tree_constant& rhs, const Octave_object& args) @@ -2798,12 +2949,11 @@ ::error ("index invalid or out of range for scalar type"); } -/* - * Assignments to matrices (and vectors). - * - * For compatibility with Matlab, we allow assignment of an empty - * matrix to an expression with empty indices to do nothing. - */ +// Assignments to matrices (and vectors). +// +// For compatibility with Matlab, we allow assignment of an empty +// matrix to an expression with empty indices to do nothing. + void tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, const Octave_object& args) @@ -2874,9 +3024,8 @@ } } -/* - * Matrix assignments indexed by a single value. - */ +// Matrix assignments indexed by a single value. + void tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, const tree_constant& i_arg) @@ -2918,11 +3067,10 @@ ::error ("single index only valid for row or column vector"); } -/* - * Fortran-style assignments. Matrices are assumed to be stored in - * column-major order and it is ok to use a single index for - * multi-dimensional matrices. - */ +// Fortran-style assignments. Matrices are assumed to be stored in +// column-major order and it is ok to use a single index for +// multi-dimensional matrices. + void tree_constant_rep::fortran_style_matrix_assignment (const tree_constant& rhs, const tree_constant& i_arg) @@ -3083,9 +3231,8 @@ } } -/* - * Fortran-style assignment for vector index. - */ +// Fortran-style assignment for vector index. + void tree_constant_rep::fortran_style_matrix_assignment (const tree_constant& rhs, idx_vector& i) @@ -3128,9 +3275,8 @@ ::error ("number of rows and columns must match for indexed assignment"); } -/* - * Fortran-style assignment for colon index. - */ +// Fortran-style assignment for colon index. + void tree_constant_rep::fortran_style_matrix_assignment (const tree_constant& rhs, tree_constant_rep::constant_type mci) @@ -3176,11 +3322,10 @@ } } -/* - * Assignments to vectors. Hand off to other functions once we know - * what kind of index we have. For a colon, it is the same as - * assignment to a matrix indexed by two colons. - */ +// Assignments to vectors. Hand off to other functions once we know +// what kind of index we have. For a colon, it is the same as +// assignment to a matrix indexed by two colons. + void tree_constant_rep::vector_assignment (const tree_constant& rhs, const tree_constant& i_arg) @@ -3260,9 +3405,8 @@ } } -/* - * Check whether an indexed assignment to a vector is valid. - */ +// Check whether an indexed assignment to a vector is valid. + void tree_constant_rep::check_vector_assign (int rhs_nr, int rhs_nc, int ilen, const char *rm) @@ -3298,9 +3442,8 @@ panic_impossible (); } -/* - * Assignment to a vector with an integer index. - */ +// Assignment to a vector with an integer index. + void tree_constant_rep::do_vector_assign (const tree_constant& rhs, int i) { @@ -3356,9 +3499,8 @@ } } -/* - * Assignment to a vector with a vector index. - */ +// Assignment to a vector with a vector index. + void tree_constant_rep::do_vector_assign (const tree_constant& rhs, idx_vector& iv) @@ -3462,9 +3604,8 @@ panic_impossible (); } -/* - * Assignment to a vector with a range index. - */ +// Assignment to a vector with a range index. + void tree_constant_rep::do_vector_assign (const tree_constant& rhs, Range& ri) @@ -3561,20 +3702,19 @@ panic_impossible (); } -/* - * Matrix assignment indexed by two values. This function determines - * the type of the first arugment, checks as much as possible, and - * then calls one of a set of functions to handle the specific cases: - * - * M (integer, arg2) = RHS (MA1) - * M (vector, arg2) = RHS (MA2) - * M (range, arg2) = RHS (MA3) - * M (colon, arg2) = RHS (MA4) - * - * Each of those functions determines the type of the second argument - * and calls another function to handle the real work of doing the - * assignment. - */ +// Matrix assignment indexed by two values. This function determines +// the type of the first arugment, checks as much as possible, and +// then calls one of a set of functions to handle the specific cases: +// +// M (integer, arg2) = RHS (MA1) +// M (vector, arg2) = RHS (MA2) +// M (range, arg2) = RHS (MA3) +// M (colon, arg2) = RHS (MA4) +// +// Each of those functions determines the type of the second argument +// and calls another function to handle the real work of doing the +// assignment. + void tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, const tree_constant& i_arg, @@ -4212,23 +4352,21 @@ } } -/* - * Functions that actually handle assignment to a matrix using two - * index values. - * - * idx2 - * +---+---+----+----+ - * idx1 | i | v | r | c | - * ---------+---+---+----+----+ - * integer | 1 | 5 | 9 | 13 | - * ---------+---+---+----+----+ - * vector | 2 | 6 | 10 | 14 | - * ---------+---+---+----+----+ - * range | 3 | 7 | 11 | 15 | - * ---------+---+---+----+----+ - * colon | 4 | 8 | 12 | 16 | - * ---------+---+---+----+----+ - */ +// Functions that actually handle assignment to a matrix using two +// index values. +// +// idx2 +// +---+---+----+----+ +// idx1 | i | v | r | c | +// ---------+---+---+----+----+ +// integer | 1 | 5 | 9 | 13 | +// ---------+---+---+----+----+ +// vector | 2 | 6 | 10 | 14 | +// ---------+---+---+----+----+ +// range | 3 | 7 | 11 | 15 | +// ---------+---+---+----+----+ +// colon | 4 | 8 | 12 | 16 | +// ---------+---+---+----+----+ /* 1 */ void @@ -4648,12 +4786,11 @@ } } -/* - * Functions for deleting rows or columns of a matrix. These are used - * to handle statements like - * - * M (i, j) = [] - */ +// Functions for deleting rows or columns of a matrix. These are used +// to handle statements like +// +// M (i, j) = [] + void tree_constant_rep::delete_row (int idx) { @@ -5006,31 +5143,32 @@ panic_impossible (); } -/* - * Indexing functions. - */ +// Indexing functions. + int tree_constant_rep::valid_as_scalar_index (void) const { - int valid = type_tag == magic_colon - || (type_tag == scalar_constant && NINT (scalar) == 1) - || (type_tag == range_constant - && range->nelem () == 1 && NINT (range->base ()) == 1); - - return valid; + return (type_tag == magic_colon + || (type_tag == scalar_constant && NINT (scalar) == 1) + || (type_tag == range_constant + && range->nelem () == 1 && NINT (range->base ()) == 1)); } tree_constant tree_constant_rep::do_scalar_index (const Octave_object& args) const { + tree_constant retval; + if (valid_scalar_indices (args)) { if (type_tag == scalar_constant) - return tree_constant (scalar); + retval = scalar; else if (type_tag == complex_scalar_constant) - return tree_constant (*complex_scalar); + retval = *complex_scalar; else panic_impossible (); + + return retval; } else { @@ -5049,7 +5187,7 @@ idx_vector j (mj, user_pref.do_fortran_indexing, ""); if (! j) - return tree_constant (); + return retval; int len = j.length (); if (len == j.ones_count ()) @@ -5073,7 +5211,7 @@ idx_vector i (mi, user_pref.do_fortran_indexing, ""); if (! i) - return tree_constant (); + return retval; int len = i.length (); if (len == i.ones_count ()) @@ -5088,8 +5226,7 @@ else if (args(1).is_scalar_type () && NINT (args(1).double_value ()) == 0) { - Matrix m (0, 0); - return tree_constant (m); + return Matrix (); } else break; @@ -5107,13 +5244,11 @@ if (type_tag == scalar_constant) { - Matrix m (rows, cols, scalar); - return tree_constant (m); + return Matrix (rows, cols, scalar); } else if (type_tag == complex_scalar_constant) { - ComplexMatrix cm (rows, cols, *complex_scalar); - return tree_constant (cm); + return ComplexMatrix (rows, cols, *complex_scalar); } else panic_impossible (); @@ -6239,8 +6374,35 @@ tree_constant_rep::constant_type mcj) const { tree_constant retval; + assert (mci == magic_colon && mcj == magic_colon); - retval = tree_constant (*this); + + switch (type_tag) + { + case complex_scalar_constant: + retval = *complex_scalar; + break; + case scalar_constant: + retval = scalar; + break; + case complex_matrix_constant: + retval = *complex_matrix; + break; + case matrix_constant: + retval = *matrix; + break; + case range_constant: + retval = *range; + break; + case string_constant: + retval = string; + break; + case magic_colon: + default: + panic_impossible (); + break; + } + return retval; }
--- a/src/tc-rep.h +++ b/src/tc-rep.h @@ -39,27 +39,18 @@ struct Mapper_fcn; -/* - * Forward class declarations. - */ +// Forward class declarations. + class tree; class tree_constant; -/* - * The actual representation of the tree_constant. - */ +// The actual representation of the tree_constant. + class tree_constant_rep { friend class tree_constant; - enum force_orient - { - no_orient, - row_orient, - column_orient, - }; - public: enum constant_type { @@ -73,6 +64,14 @@ magic_colon, }; + enum force_orient + { + no_orient, + row_orient, + column_orient, + }; + +private: tree_constant_rep (void); tree_constant_rep (double d); @@ -155,6 +154,8 @@ ColumnVector to_vector (void) const; Matrix to_matrix (void) const; + void stash_original_text (char *s); + tree_constant_rep::constant_type force_numeric (int force_str_conv = 0); tree_constant make_numeric (int force_str_conv = 0) const; @@ -245,6 +246,8 @@ void maybe_mutate (void); void print (void); + void print_code (ostream& os); + tree_constant do_index (const Octave_object& args); tree_constant do_scalar_index (const Octave_object& args) const; @@ -330,7 +333,6 @@ tree_constant mapper (Mapper_fcn& m_fcn, int print) const; -private: int count; constant_type type_tag; union @@ -342,6 +344,7 @@ char *string; // A character string constant. Range *range; // A set of evenly spaced values. }; + char *orig_text; }; extern tree_constant do_binary_op (tree_constant& a, tree_constant& b,
--- a/src/token.cc +++ b/src/token.cc @@ -40,6 +40,7 @@ line_num = l; column_num = c; type_tag = generic_token; + orig_text = 0; } token::token (char *s, int l, int c) @@ -48,14 +49,16 @@ column_num = c; type_tag = string_token; str = strsave (s); + orig_text = 0; } -token::token (double d, int l, int c) +token::token (double d, char *s, int l, int c) { line_num = l; column_num = c; type_tag = double_token; num = d; + orig_text = strsave (s); } token::token (end_tok_type t, int l, int c) @@ -64,6 +67,7 @@ column_num = c; type_tag = ettype_token; et = t; + orig_text = 0; } token::token (plot_tok_type t, int l, int c) @@ -72,6 +76,7 @@ column_num = c; type_tag = pttype_token; pt = t; + orig_text = 0; } token::token (symbol_record *s, int l, int c) @@ -80,12 +85,14 @@ column_num = c; type_tag = sym_rec_token; sr = s; + orig_text = 0; } token::~token (void) { if (type_tag == string_token) delete [] str; + delete [] orig_text; } int @@ -135,6 +142,12 @@ return sr; } +char * +token::text_rep (void) +{ + return orig_text; +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/token.h +++ b/src/token.h @@ -62,7 +62,7 @@ token (int l = -1, int c = -1); token (char *s, int l = -1, int c = -1); - token (double d, int l = -1, int c = -1); + token (double d, char *s = 0, int l = -1, int c = -1); token (end_tok_type t, int l = -1, int c = -1); token (plot_tok_type t, int l = -1, int c = -1); token (symbol_record *s, int l = -1, int c = -1); @@ -78,6 +78,8 @@ plot_tok_type pttype (void); symbol_record *sym_rec (void); + char *text_rep (void); + private: int line_num; int column_num; @@ -90,6 +92,7 @@ plot_tok_type pt; symbol_record *sr; }; + char *orig_text; }; #endif
--- a/src/utils.cc +++ b/src/utils.cc @@ -47,8 +47,6 @@ #include <sys/param.h> #include <setjmp.h> #include <string.h> -#include <stdlib.h> -#include <stdio.h> #include <limits.h> #include <iostream.h> #include <strstream.h> @@ -75,7 +73,7 @@ LOSE! LOSE! #endif -char *tilde_expand (char *s); /* From readline's tilde.c */ +#include <readline/tilde.h> } // This mess suggested by the autoconf manual. @@ -118,9 +116,8 @@ // Top level context (?) extern jmp_buf toplevel; -/* - * Save a string. - */ +// Save a string. + char * strsave (const char *s) { @@ -133,9 +130,8 @@ return tmp; } -/* - * Concatenate two strings. - */ +// Concatenate two strings. + char * strconcat (const char *s, const char *t) { @@ -145,9 +141,8 @@ return strcat (tmp, t); } -/* - * Throw away input until a given character is read. - */ +// Throw away input until a given character is read. + void discard_until (istream& stream, char character) { @@ -211,9 +206,8 @@ return path; } -/* - * Return to the main command loop in octave.cc. - */ +// Return to the main command loop in octave.cc. + void jump_to_top_level (void) { @@ -236,9 +230,8 @@ : (strncasecmp (std, s, slen) == 0))); } -/* - * Ugh. - */ +// Ugh. + int keyword_almost_match (const char **std, int *min_len, const char *s, int min_toks_to_match, int max_toks) @@ -473,10 +466,9 @@ return argv; } -/* - * Format a list in neat columns. Mostly stolen from GNU ls. This - * should maybe be in utils.cc. - */ +// Format a list in neat columns. Mostly stolen from GNU ls. This +// should maybe be in utils.cc. + ostrstream& list_in_columns (ostrstream& os, char **list) { @@ -541,9 +533,8 @@ return os; } -/* - * See if the given file is in the path. - */ +// See if the given file is in the path. + char * file_in_path (const char *name, const char *suffix) { @@ -587,20 +578,18 @@ return retval; } -/* - * See if there is an function file in the path. If so, return the - * full path to the file. - */ +// See if there is an function file in the path. If so, return the +// full path to the file. + char * fcn_file_in_path (const char *name) { return file_in_path (name, ".m"); } -/* - * See if there is an octave file in the path. If so, return the - * full path to the file. - */ +// See if there is an octave file in the path. If so, return the +// full path to the file. + char * oct_file_in_path (const char *name) {
--- a/src/variables.cc +++ b/src/variables.cc @@ -36,55 +36,62 @@ #include <iostream.h> #include <strstream.h> -#include "statdefs.h" +#include "octave-hist.h" +#include "unwind-prot.h" +#include "user-prefs.h" #include "tree-const.h" #include "variables.h" -#include "mappers.h" -#include "user-prefs.h" +#include "statdefs.h" +#include "defaults.h" #include "version.h" -#include "symtab.h" -#include "defaults.h" +#include "mappers.h" +#include "oct-obj.h" +#include "sysdep.h" #include "dirfns.h" -#include "pager.h" -#include "sysdep.h" +#include "symtab.h" #include "octave.h" -#include "oct-obj.h" #include "error.h" +#include "pager.h" #include "utils.h" +#include "defun.h" +#include "input.h" +#include "parse.h" #include "tree.h" #include "help.h" -#include "defun.h" +#include "lex.h" extern "C" { +#include <readline/readline.h> #include <readline/tilde.h> #include "fnmatch.h" } // Symbol table for symbols at the top level. -symbol_table *top_level_sym_tab; +symbol_table *top_level_sym_tab = 0; // Symbol table for the current scope. -symbol_table *curr_sym_tab; +symbol_table *curr_sym_tab = 0; // Symbol table for global symbols. -symbol_table *global_sym_tab; +symbol_table *global_sym_tab = 0; void initialize_symbol_tables (void) { - global_sym_tab = new symbol_table (); + if (! global_sym_tab) + global_sym_tab = new symbol_table (); - top_level_sym_tab = new symbol_table (); + if (! top_level_sym_tab) + top_level_sym_tab = new symbol_table (); curr_sym_tab = top_level_sym_tab; } -/* - * Is there a corresponding function file that is newer than the - * symbol definition? - */ +// Is there a corresponding function file that is newer than the +// symbol definition? + int symbol_out_of_date (symbol_record *sr) { @@ -113,6 +120,227 @@ return 0; } +static void +gobble_leading_white_space (FILE *ffile) +{ + int in_comment = 0; + int c; + while ((c = getc (ffile)) != EOF) + { + if (in_comment) + { + if (c == '\n') + in_comment = 0; + } + else + { + if (c == ' ' || c == '\t' || c == '\n') + continue; + else if (c == '%' || c == '#') + in_comment = 1; + else + { + ungetc (c, ffile); + break; + } + } + } +} + +static int +is_function_file (FILE *ffile) +{ + int status = 0; + + gobble_leading_white_space (ffile); + + long pos = ftell (ffile); + + char buf [10]; + fgets (buf, 10, ffile); + int len = strlen (buf); + if (len > 8 && strncmp (buf, "function", 8) == 0 + && ! (isalnum (buf[8]) || buf[8] == '_')) + status = 1; + + fseek (ffile, pos, SEEK_SET); + + return status; +} + +static int +parse_fcn_file (int exec_script, char *ff) +{ + begin_unwind_frame ("parse_fcn_file"); + + int script_file_executed = 0; + + assert (ff); + +// Open function file and parse. + + int old_reading_fcn_file_state = reading_fcn_file; + + unwind_protect_ptr (rl_instream); + unwind_protect_ptr (ff_instream); + + unwind_protect_int (using_readline); + unwind_protect_int (input_line_number); + unwind_protect_int (current_input_column); + unwind_protect_int (reading_fcn_file); + + using_readline = 0; + reading_fcn_file = 1; + input_line_number = 0; + current_input_column = 1; + + FILE *ffile = get_input_from_file (ff, 0); + + if (ffile) + { +// Check to see if this file defines a function or is just a list of +// commands. + + if (is_function_file (ffile)) + { + unwind_protect_int (echo_input); + unwind_protect_int (saving_history); + unwind_protect_int (reading_fcn_file); + + echo_input = 0; + saving_history = 0; + reading_fcn_file = 1; + + YY_BUFFER_STATE old_buf = current_buffer (); + YY_BUFFER_STATE new_buf = create_buffer (ffile); + + add_unwind_protect (restore_input_buffer, (void *) old_buf); + add_unwind_protect (delete_input_buffer, (void *) new_buf); + + switch_to_buffer (new_buf); + + unwind_protect_ptr (curr_sym_tab); + + reset_parser (); + + int status = yyparse (); + + if (status != 0) + { + error ("parse error while reading function file %s", ff); + global_sym_tab->clear (curr_fcn_file_name); + } + } + else if (exec_script) + { +// The value of `reading_fcn_file' will be restored to the proper value +// when we unwind from this frame. + reading_fcn_file = old_reading_fcn_file_state; + + unwind_protect_int (reading_script_file); + reading_script_file = 1; + + parse_and_execute (ffile, 1); + + script_file_executed = 1; + } + fclose (ffile); + } + + run_unwind_frame ("parse_fcn_file"); + + return script_file_executed; +} + +int +load_fcn_from_file (symbol_record *sym_rec, int exec_script) +{ + int script_file_executed = 0; + + char *nm = sym_rec->name (); + + curr_fcn_file_name = nm; + + char *oct_file = oct_file_in_path (curr_fcn_file_name); + + int loaded_oct_file = 0; + + if (oct_file) + { + cerr << "found: " << oct_file << "\n"; + + delete [] oct_file; + +// XXX FIXME XXX -- this is where we try to link to an external +// object... + loaded_oct_file = 1; + } + + if (! loaded_oct_file) + { + char *ff = fcn_file_in_path (curr_fcn_file_name); + + if (ff) + { + script_file_executed = parse_fcn_file (exec_script, ff); + delete [] ff; + } + + if (! (error_state || script_file_executed)) + force_link_to_function (nm); + } + + return script_file_executed; +} + +int +lookup (symbol_record *sym_rec, int exec_script) +{ + int script_file_executed = 0; + + if (! sym_rec->is_linked_to_global ()) + { + if (sym_rec->is_defined ()) + { + if (sym_rec->is_function () && symbol_out_of_date (sym_rec)) + { + script_file_executed = load_fcn_from_file (sym_rec, exec_script); + } + } + else if (! sym_rec->is_formal_parameter ()) + { + link_to_builtin_or_function (sym_rec); + + if (! sym_rec->is_defined ()) + { + script_file_executed = load_fcn_from_file (sym_rec, exec_script); + } + else if (sym_rec->is_function () && symbol_out_of_date (sym_rec)) + { + script_file_executed = load_fcn_from_file (sym_rec, exec_script); + } + } + } + + return script_file_executed; +} + +// Get the symbol record for the given name that is visible in the +// current scope. Reread any function definitions that appear to be +// out of date. If a function is available in a file but is not +// currently loaded, this will load it and insert the name in the +// current symbol table. + +symbol_record * +lookup_by_name (const char *nm, int exec_script) +{ + symbol_record *sym_rec = curr_sym_tab->lookup (nm, 1, 0); + + lookup (sym_rec, exec_script); + + return sym_rec; +} + void document_symbol (const char *name, const char *help) { @@ -237,10 +465,9 @@ sr->protect (); } -/* - * Give a global variable a definition. This will insert the symbol - * in the global table if necessary. - */ +// Give a global variable a definition. This will insert the symbol +// in the global table if necessary. + void bind_builtin_variable (const char *varname, tree_constant *val, int protect, int eternal, sv_Function sv_fcn, @@ -274,10 +501,9 @@ sr->document (help); } -/* - * Look for the given name in the global symbol table. If it refers - * to a string, return a new copy. If not, return 0; - */ +// Look for the given name in the global symbol table. If it refers +// to a string, return a new copy. If not, return 0; + char * builtin_string_variable (const char *name) { @@ -306,11 +532,10 @@ return retval; } -/* - * Look for the given name in the global symbol table. If it refers - * to a real scalar, place the value in d and return 0. Otherwise, - * return -1. - */ +// Look for the given name in the global symbol table. If it refers +// to a real scalar, place the value in d and return 0. Otherwise, +// return -1. + int builtin_real_scalar_variable (const char *name, double& d) { @@ -338,11 +563,10 @@ return status; } -/* - * Make the definition of the symbol record sr be the same as the - * definition of the global variable of the same name, creating it if - * it doesn't already exist. - */ +// Make the definition of the symbol record sr be the same as the +// definition of the global variable of the same name, creating it if +// it doesn't already exist. + void link_to_global_variable (symbol_record *sr) { @@ -382,10 +606,9 @@ sr->mark_as_linked_to_global (); } -/* - * Make the definition of the symbol record sr be the same as the - * definition of the builtin variable of the same name. - */ +// Make the definition of the symbol record sr be the same as the +// definition of the builtin variable of the same name. + void link_to_builtin_variable (symbol_record *sr) { @@ -395,12 +618,11 @@ sr->alias (tmp_sym); } -/* - * Make the definition of the symbol record sr be the same as the - * definition of the builtin variable or function, or user function of - * the same name, provided that the name has not been used as a formal - * parameter. - */ +// Make the definition of the symbol record sr be the same as the +// definition of the builtin variable or function, or user function of +// the same name, provided that the name has not been used as a formal +// parameter. + void link_to_builtin_or_function (symbol_record *sr) { @@ -412,15 +634,14 @@ sr->alias (tmp_sym); } -/* - * Force a link to a function in the current symbol table. This is - * used just after defining a function to avoid different behavior - * depending on whether or not the function has been evaluated after - * being defined. - * - * Return without doing anything if there isn't a function with the - * given name defined in the global symbol table. - */ +// Force a link to a function in the current symbol table. This is +// used just after defining a function to avoid different behavior +// depending on whether or not the function has been evaluated after +// being defined. +// +// Return without doing anything if there isn't a function with the +// given name defined in the global symbol table. + void force_link_to_function (const char *id_name) { @@ -456,15 +677,14 @@ return retval; } -/* - * Extract a keyword and its value from a file. Input should look - * something like: - * - * #[ \t]*keyword[ \t]*:[ \t]*string-value\n - * - * Returns a pointer to new storage. The caller is responsible for - * deleting it. - */ +// Extract a keyword and its value from a file. Input should look +// something like: +// +// #[ \t]*keyword[ \t]*:[ \t]*string-value\n +// +// Returns a pointer to new storage. The caller is responsible for +// deleting it. + char * extract_keyword (istream& is, char *keyword) { @@ -558,9 +778,8 @@ return status; } -/* - * Skip trailing white space and - */ +// Skip trailing white space and + void skip_comments (istream& is) { @@ -583,9 +802,8 @@ } } -/* - * Is `s' a valid identifier? - */ +// Is `s' a valid identifier? + int valid_identifier (char *s) { @@ -646,9 +864,8 @@ return retval; } -/* - * Is this variable a builtin? - */ +// Is this variable a builtin? + int is_builtin_variable (const char *name) { @@ -656,9 +873,8 @@ return (sr && sr->is_builtin_variable ()); } -/* - * Is this tree_constant a valid function? - */ +// Is this tree_constant a valid function? + tree_fvc * is_valid_function (const tree_constant& arg, char *warn_for, int warn) { @@ -675,15 +891,11 @@ symbol_record *sr = global_sym_tab->lookup (fcn_name, 0, 0); if (sr && symbol_out_of_date (sr)) - { - tree_identifier tmp (sr); - tmp.load_fcn_from_file (0); - } + load_fcn_from_file (sr, 0); else { sr = global_sym_tab->lookup (fcn_name, 1, 0); - tree_identifier tmp (sr); - tmp.load_fcn_from_file (0); + load_fcn_from_file (sr, 0); } ans = sr->def (); @@ -698,9 +910,8 @@ return ans; } -/* - * Does this function take the right number of arguments? - */ +// Does this function take the right number of arguments? + int takes_correct_nargs (tree_fvc *fcn, int expected_nargin, char *warn_for, int warn) @@ -972,9 +1183,8 @@ "on IEEE machines, allow divide by zero errors to be suppressed"); } -/* - * List variable names. - */ +// List variable names. + static void print_symbol_info_line (ostrstream& output_buf, const symbol_record_info& s) { @@ -1375,9 +1585,8 @@ return retval; } -/* - * Return nonzero if PATTERN has any special globbing chars in it. - */ +// Return nonzero if PATTERN has any special globbing chars in it. + static int glob_pattern_p (char *pattern) { @@ -1530,16 +1739,11 @@ return retval; } -DEFUN_TEXT ("who", Fwho, Swho, -1, 1, - "who [-all] [-builtins] [-functions] [-long] [-variables]\n\ -\n\ -List currently defined symbol(s). Options may be shortened to one\n\ -character, but may not be combined.") +static Octave_object +do_who (int argc, char **argv, int nargout) { Octave_object retval; - DEFINE_ARGV("who"); - int show_builtins = 0; int show_functions = (curr_sym_tab == top_level_sym_tab); int show_variables = 1; @@ -1628,11 +1832,52 @@ output_buf << ends; maybe_page_output (output_buf); + return retval; +} + +DEFUN_TEXT ("who", Fwho, Swho, -1, 1, + "who [-all] [-builtins] [-functions] [-long] [-variables]\n\ +\n\ +List currently defined symbol(s). Options may be shortened to one\n\ +character, but may not be combined.") +{ + Octave_object retval; + + DEFINE_ARGV("who"); + + retval = do_who (argc, argv, nargout); + DELETE_ARGV; return retval; } +DEFUN_TEXT ("whos", Fwhos, Swhos, -1, 1, + "whos [-all] [-builtins] [-functions] [-long] [-variables]\n\ +\n\ +List currently defined symbol(s). Options may be shortened to one\n\ +character, but may not be combined.") +{ + Octave_object retval; + + Octave_object tmp_args = args; + tmp_args(args.length ()) = "-long"; + + int argc = tmp_args.length (); + char **argv = make_argv (tmp_args, "whos"); + + if (error_state) + return retval; + + retval = do_who (argc, argv, nargout); + + while (--argc >= 0) + delete [] argv[argc]; + delete [] argv; + + return retval; +} + // XXX FIXME XXX -- should these really be here? char * @@ -1685,15 +1930,14 @@ #endif } -/* - * Handle OCTAVE_PATH from the environment like TeX handles TEXINPUTS. - * If the path starts with `:', prepend the standard path. If it ends - * with `:' append the standard path. If it begins and ends with - * `:', do both (which is useless, but the luser asked for it...). - * - * This function may eventually be called more than once, so be - * careful not to create memory leaks. - */ +// Handle OCTAVE_PATH from the environment like TeX handles TEXINPUTS. +// If the path starts with `:', prepend the standard path. If it ends +// with `:' append the standard path. If it begins and ends with +// `:', do both (which is useless, but the luser asked for it...). +// +// This function may eventually be called more than once, so be +// careful not to create memory leaks. + char * default_path (void) {
--- a/src/variables.h +++ b/src/variables.h @@ -66,6 +66,12 @@ extern int symbol_out_of_date (symbol_record *sr); +extern int load_fcn_from_file (symbol_record *s, int exec_script = 1); + +extern int lookup (symbol_record *s, int exec_script = 1); + +extern symbol_record *lookup_by_name (const char *nm, int exec_script = 1); + extern void document_symbol (const char *name, const char *help); extern void install_builtin_mapper (builtin_mapper_function *mf);