# HG changeset patch # User jwe # Date 774731948 0 # Node ID 7ea224e713cd98e2327927cec9a57c466352592f # Parent e1e6e33e26f8f75419950f5ee17ec6451abbd6fe [project @ 1994-07-20 18:54:27 by jwe] diff --git a/src/Makefile.in b/src/Makefile.in --- a/src/Makefile.in +++ b/src/Makefile.in @@ -22,7 +22,7 @@ %.cc : %.y $(YACC) $(YFLAGS) $< - mv y.tab.c $(@F) + @$(top_srcdir)/move-if-change y.tab.c $(@F) # Likewise for .c from .l. @@ -31,69 +31,100 @@ %.cc : %.l $(LEX) $(LFLAGS) $< > $(@F) -INCLUDES = arith-ops.h builtins.h dynamic-ld.h defaults.h.in \ - defaults.h error.h f-balance.h f-chol.h f-colloc.h f-dassl.h \ - f-det.h f-eig.h f-expm.h f-fft.h f-fsolve.h f-fsqp.h f-givens.h \ - f-hess.h f-ifft.h f-inv.h f-lpsolve.h f-lsode.h f-lu.h \ - f-npsol.h f-qpsol.h f-qr.h f-quad.h f-qzval.h f-rand.h \ - f-schur.h f-svd.h f-syl.h file-io.h fnmatch.h g-builtins.h \ - getopt.h gripes.h help.h idx-vector.h input.h lex.h mappers.h \ - missing-math.h octave.h octave-hist.h oct-obj.h pager.h parse.h \ - pr-output.h procstream.h sighandlers.h statdefs.h symtab.h \ - sysdep.h t-builtins.h token.h tree.h tree-cmd.h tree-const.h \ - tree-expr.h tree-plot.h tc-rep.h unwind-prot.h user-prefs.h \ - utils.h variables.h version.h xdiv.h xpow.h SLStack.h Stack.h +%.def : %.cc + @echo making $@ from $< + @$(CXXCPP) -c $(CPPFLAGS) $(ALL_CXXFLAGS) -DMAKE_BUILTINS $< \ + | $(srcdir)/mkdefs > $@.tmp + @mv $@.tmp $@ + +DLD_SRC = f-balance.cc f-chol.cc f-colloc.cc f-dassl.cc f-det.cc \ + f-eig.cc f-expm.cc f-fft.cc f-find.cc \ + f-fsolve.cc f-fsqp.cc f-givens.cc f-hess.cc f-ifft.cc \ + f-inv.cc f-log.cc f-lpsolve.cc f-lsode.cc f-lu.cc \ + f-minmax.cc f-npsol.cc f-qpsol.cc f-qr.cc f-quad.cc f-qzval.cc \ + f-rand.cc f-schur.cc f-sort.cc f-svd.cc f-syl.cc + + +DLD_OBJ = f-balance.o f-chol.o f-colloc.o f-dassl.o f-det.o f-eig.o \ + f-expm.o f-fft.o f-find.o f-fsolve.o \ + f-fsqp.o f-givens.o f-hess.o f-ifft.o f-inv.o \ + f-log.o f-lpsolve.o f-lsode.o f-lu.o f-minmax.o f-npsol.o \ + f-qpsol.o f-qr.o f-quad.o f-qzval.o f-rand.o f-schur.o \ + f-sort.o f-svd.o f-syl.o -SOURCES = arith-ops.cc builtins.cc dynamic-ld.cc error.cc f-chol.cc \ - f-colloc.cc f-balance.cc f-dassl.cc f-det.cc f-eig.cc \ - f-expm.cc f-fft.cc f-fsolve.cc f-fsqp.cc f-givens.cc \ - f-hess.cc f-ifft.cc f-inv.cc f-lpsolve.cc f-lsode.cc f-lu.cc \ - f-npsol.cc f-qpsol.cc f-qr.cc f-quad.cc f-qzval.cc f-rand.cc \ - f-schur.cc f-svd.cc f-syl.cc file-io.cc fnmatch.c \ - g-builtins.cc getopt.c getopt1.c gripes.cc help.cc \ - idx-vector.cc input.cc lex.l mappers.cc octave.cc \ - octave-hist.cc pager.cc parse.y pr-output.cc procstream.cc \ - sighandlers.cc strcasecmp.c strncase.c symtab.cc sysdep.cc \ - t-builtins.cc token.cc tree-cmd.cc tree-const.cc tree-expr.cc \ - tree-plot.cc tc-rep.cc unwind-prot.cc user-prefs.cc utils.cc \ - variables.cc xdiv.cc xpow.cc SLStack.cc +INCLUDES = arith-ops.h builtins.h defaults.h.in defun.h defun-dld.h \ + defun-int.h dirfns.h dynamic-ld.h error.h file-io.h fnmatch.h \ + getopt.h gripes.h help.h idx-vector.h input.h lex.h mappers.h \ + missing-math.h octave.h octave-hist.h \ + oct-obj.h pager.h parse.h pr-output.h procstream.h \ + sighandlers.h statdefs.h symtab.h sysdep.h token.h tree.h \ + tree-base.h tree-cmd.h tree-const.h tree-expr.h tree-plot.h \ + tc-rep.h unwind-prot.h user-prefs.h utils.h variables.h \ + version.h xdiv.h xpow.h SLStack.h Stack.h -DEP_SOURCES_2 = $(patsubst %.l, %.cc, $(SOURCES)) +SOURCES = arith-ops.cc data.cc dirfns.cc dynamic-ld.cc \ + error.cc file-io.cc fnmatch.c getopt.c getopt1.c gripes.cc \ + help.cc idx-vector.cc input.cc lex.l mappers.cc octave.cc \ + oct-obj.cc octave-hist.cc pager.cc parse.y pr-output.cc \ + procstream.cc sighandlers.cc strcasecmp.c strncase.c symtab.cc \ + sysdep.cc tc-rep.cc timefns.cc token.cc tree-cmd.cc \ + tree-const.cc tree-expr.cc tree-plot.cc unwind-prot.cc \ + user-prefs.cc utils.cc variables.cc xdiv.cc xpow.cc SLStack.cc \ + $(DLD_SRC) + +# Ugh. + +DEP_SOURCES_2 = $(patsubst %.l, %.cc, $(SOURCES)) builtins.cc DEP_SOURCES_1 = $(patsubst %.y, %.cc, $(DEP_SOURCES_2)) DEP_SOURCES = $(patsubst %.c, %.d, $(DEP_SOURCES_1)) MAKEDEPS = $(patsubst %.cc, %.d, $(DEP_SOURCES)) -DLD_OBJECTS = f-balance.o f-chol.o f-colloc.o f-dassl.o f-det.o \ - f-eig.o f-expm.o f-fft.o f-fsolve.o f-fsqp.o f-givens.o \ - f-hess.o f-ifft.o f-inv.o f-lpsolve.o f-lsode.o f-lu.o \ - f-npsol.o f-qpsol.o f-qr.o f-quad.o f-qzval.o f-rand.o \ - f-schur.o f-svd.o f-syl.o +DEF_FILES_4 = $(addprefix $(srcdir)/, $(SOURCES)) +DEF_FILES_3 = $(notdir $(shell grep -l "^DEFUN" $(DEF_FILES_4))) +DEF_FILES_2 = $(patsubst %.y, %.def, $(DEF_FILES_3)) +DEF_FILES_1 = $(patsubst %.l, %.def, $(DEF_FILES_2)) +DEF_FILES = $(patsubst %.cc, %.def, $(DEF_FILES_1)) + +# XXX FIXME XXX -- Should these be generated automatically from the +# list of source files? -OBJECTS = arith-ops.o builtins.o error.o file-io.o fnmatch.o \ - g-builtins.o getopt.o getopt1.o gripes.o help.o idx-vector.o \ - input.o lex.o mappers.o octave.o octave-hist.o pager.o \ - parse.o pr-output.o procstream.o sighandlers.o strcasecmp.o \ - strncase.o symtab.o sysdep.o t-builtins.o token.o tree-cmd.o \ - tree-const.o tree-expr.o tree-plot.o tc-rep.o unwind-prot.o \ - user-prefs.o utils.o variables.o xdiv.o xpow.o SLStack.o \ +OBJECTS = arith-ops.o builtins.o data.o dirfns.o error.o \ + file-io.o fnmatch.o getopt.o getopt1.o gripes.o help.o \ + idx-vector.o input.o lex.o mappers.o octave.o octave-hist.o \ + oct-obj.o pager.o parse.o pr-output.o procstream.o sighandlers.o \ + strcasecmp.o strncase.o symtab.o sysdep.o tc-rep.o timefns.o \ + token.o tree-cmd.o tree-const.o tree-expr.o tree-plot.o \ + unwind-prot.o user-prefs.o utils.o variables.o xdiv.o xpow.o \ + SLStack.o \ @DYNAMIC_LD_OBJ@ -OCTAVE_LIBS = ../liboctave.a ../libcruft.a ../libinfo.a \ +OCTAVE_LIBS = @LIBOCTDLD@ ../liboctave.a ../libcruft.a ../libinfo.a \ ../libreadline.a @LIBDLD@ -DISTFILES = Makefile.in move-if-change parse.cc lex.cc y.tab.h \ - $(INCLUDES) $(SOURCES) +DISTFILES = Makefile.in mkdefs mkbuiltins \ + parse.cc lex.cc y.tab.h $(INCLUDES) $(SOURCES) all: defaults.h octave .PHONY: all -octave: $(DLD_OBJECTS) $(OBJECTS) $(OCTAVE_LIBS) $(LIBOBJS) +octave: $(OBJECTS) $(DLD_OBJ) $(LIBOBJS) $(OCTAVE_LIBS) ../liboctdld.a $(CXX) $(CPPFLAGS) $(ALL_CXXFLAGS) $(ALL_LDFLAGS) -o octave \ - $(OBJECTS) @DLD_OBJECTS@ \ + $(OBJECTS) \ $(OCTAVE_LIBS) \ $(LIBOBJS) \ $(FLIBS) $(LEXLIB) -ltermcap -lm -lg++ +../liboctdld.a: $(DLD_OBJ) + $(AR) $(ARFLAGS) ../liboctdld.a $(DLD_OBJ) + $(RANLIB) ../liboctdld.a + +builtins.cc: $(DEF_FILES) mkbuiltins + @echo making $@ from $(DEF_FILES) + @$(srcdir)/mkbuiltins $(DEF_FILES) > $@.tmp + @$(top_srcdir)/move-if-change $@.tmp $@ + +$(DEF_FILES): mkdefs + check: all .PHONY: check @@ -115,7 +146,7 @@ etags $(SOURCES) clean: - rm -f *.a *.o + rm -f *.a *.o *.def builtins.cc .PHONY: clean mostlyclean: @@ -142,13 +173,13 @@ # Special rules -- these files need special things to be defined. -defaults.h: ../Makeconf Makefile defaults.h.in - @echo "Making defaults.h from defaults.h.in..." - @(sed < $(srcdir)/defaults.h.in > defaults.h.tmp \ +defaults.h: defaults.h.in ../Makeconf Makefile + @echo "making defaults.h from defaults.h.in" + @(sed < $< > $@.tmp \ -e 's;%DEFAULT_PAGER%;\"${DEFAULT_PAGER}\";' \ -e 's;%OCTAVE_HOME%;\"${OCTAVE_HOME}\";' \ -e 's;%OCTAVE_LIB_DIR%;\"${OCTAVE_LIB_DIR}\";' \ -e 's;%OCTAVE_INFO_DIR%;\"${OCTAVE_INFO_DIR}\";') - @$(srcdir)/move-if-change defaults.h.tmp defaults.h + @$(top_srcdir)/move-if-change $@.tmp $@ include $(MAKEDEPS) diff --git a/src/builtins.h b/src/builtins.h --- a/src/builtins.h +++ b/src/builtins.h @@ -1,4 +1,4 @@ -// Builtin function support. -*- C++ -*- +// builtins.h -*- C++ -*- /* Copyright (C) 1992, 1993, 1994 John W. Eaton @@ -24,69 +24,7 @@ #if !defined (octave_builtins_h) #define octave_builtins_h 1 -class ostrstream; -class Complex; -struct help_list; - -typedef double (*d_d_Mapper)(double); -typedef double (*d_c_Mapper)(const Complex&); -typedef Complex (*c_c_Mapper)(const Complex&); - -// If can_return_complex_for_real_arg is 1, lower_limit and -// upper_limit specify the range of values for which a real arg -// returns a real value. Outside that range, we have to convert args -// to complex, and call the complex valued function. -// -// If can_return_complex_for_real_arg is 0, lower_limit and -// upper_limit are ignored. - -struct Mapper_fcn -{ - int can_return_complex_for_real_arg; - double lower_limit; - double upper_limit; - d_d_Mapper d_d_mapper; - d_c_Mapper d_c_mapper; - c_c_Mapper c_c_mapper; -}; - -struct builtin_mapper_functions -{ - char *name; - int can_return_complex_for_real_arg; - double lower_limit; - double upper_limit; - d_d_Mapper d_d_mapper; - d_c_Mapper d_c_mapper; - c_c_Mapper c_c_mapper; - char *help_string; -}; - -typedef int (*sv_Function)(void); - -struct builtin_string_variables -{ - char *name; - char *value; - sv_Function sv_function; - char *help_string; -}; - extern void install_builtins (void); -extern int is_text_function_name (const char *s); - -extern help_list *builtin_mapper_functions_help (void); -extern help_list *builtin_general_functions_help (void); -extern help_list *builtin_text_functions_help (void); -extern help_list *builtin_variables_help (void); - -extern int help_from_list (ostrstream& output_buf, - const help_list *list, const char *string, - int usage); - -extern void additional_help_message (ostrstream& output_buf); - -extern void print_usage (const char *s, int just_usage = 0); #endif diff --git a/src/file-io.cc b/src/file-io.cc --- a/src/file-io.cc +++ b/src/file-io.cc @@ -46,8 +46,10 @@ #include "error.h" #include "utils.h" #include "pager.h" +#include "defun.h" #include "sysdep.h" #include "mappers.h" +#include "variables.h" // keeps a count of how many files are open and in the file list static int file_count = 0; @@ -84,9 +86,9 @@ file_info::file_info (void) { file_number = -1; - file_name = (char *) NULL; - file_fptr = (FILE *) NULL; - file_mode = (char *) NULL; + file_name = 0; + file_fptr = 0; + file_mode = 0; } file_info::file_info (int n, const char *nm, FILE *t, const char *md) @@ -209,7 +211,7 @@ else error ("inapproriate file specifier"); - return (Pix) NULL; + return 0; } static Pix @@ -219,7 +221,7 @@ char *file_name = arg.string_value (); FILE *file_ptr = fopen (file_name, mode); - if (file_ptr != (FILE *) NULL) + if (file_ptr) { file_info file (++file_count, file_name, file_ptr, mode); file_list.append (file); @@ -238,7 +240,7 @@ error ("%s: unable to open file `%s'", warn_for, file_name); - return (Pix) NULL; + return 0; } static Pix @@ -247,7 +249,7 @@ { Pix p = return_valid_file (arg); - if (p == (Pix) NULL) + if (! p) { if (arg.is_string_type ()) { @@ -275,6 +277,21 @@ return p; } +DEFUN ("fclose", Ffclose, Sfclose, 2, 1, + "fclose (FILENAME or FILENUM): close a file") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2) + print_usage ("fclose"); + else + retval = fclose_internal (args); + + return retval; +} + Octave_object fclose_internal (const Octave_object& args) { @@ -282,7 +299,7 @@ Pix p = return_valid_file (args(1)); - if (p == (Pix) NULL) + if (! p) return retval; file_info file = file_list (p); @@ -309,6 +326,21 @@ return retval; } +DEFUN ("fflush", Ffflush, Sfflush, 2, 1, + "fflush (FILENAME or FILENUM): flush buffered data to output file") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2) + print_usage ("fflush"); + else + retval = fflush_internal (args); + + return retval; +} + Octave_object fflush_internal (const Octave_object& args) { @@ -316,7 +348,7 @@ Pix p = return_valid_file (args(1)); - if (p == (Pix) NULL) + if (! p) return retval; file_info file = file_list (p); @@ -349,7 +381,7 @@ static int valid_mode (const char *mode) { - if (mode != (char *) NULL) + if (mode) { char m = mode[0]; if (m == 'r' || m == 'w' || m == 'a') @@ -361,6 +393,23 @@ return 0; } +DEFUN ("fgets", Ffgets, Sfgets, 3, 2, + "[STRING, LENGTH] = fgets (FILENAME or FILENUM, LENGTH)\n\ +\n\ +read a string from a file") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 3) + print_usage ("fgets"); + else + retval = fgets_internal (args, nargout); + + return retval; +} + Octave_object fgets_internal (const Octave_object& args, int nargout) { @@ -368,7 +417,7 @@ Pix p = file_io_get_file (args(1), "r", "fgets"); - if (p == (Pix) NULL) + if (! p) return retval; int length = 0; @@ -387,7 +436,7 @@ char string[length+1]; char *success = fgets (string, length+1, file.fptr ()); - if (success == (char *) NULL) + if (! success) { retval.resize (1); retval(0) = tree_constant (-1.0); @@ -407,6 +456,31 @@ return retval; } +DEFUN ("fopen", Ffopen, Sfopen, 3, 1, + "FILENUM = fopen (FILENAME, MODE): open a file\n\ +\n\ + Valid values for mode include:\n\ +\n\ + r : open text file for reading\n\ + w : open text file for writing; discard previous contents if any\n\ + a : append; open or create text file for writing at end of file\n\ + r+ : open text file for update (i.e., reading and writing)\n\ + w+ : create text file for update; discard previous contents if any\n\ + a+ : append; open or create text file for update, writing at end\n\n\ + Update mode permits reading from and writing to the same file.") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 3) + print_usage ("fopen"); + else + retval = fopen_internal (args); + + return retval; +} + Octave_object fopen_internal (const Octave_object& args) { @@ -421,7 +495,7 @@ p = return_valid_file (args(1)); - if (p != (Pix) NULL) + if (p) { file_info file = file_list (p); @@ -455,7 +529,7 @@ FILE *file_ptr = fopen (name, mode); - if (file_ptr == (FILE *) NULL) + if (! file_ptr) { error ("fopen: unable to open file `%s'", name); return retval; @@ -472,6 +546,21 @@ return retval; } +DEFUN ("freport", Ffreport, Sfreport, 1, 1, + "freport (): list open files and their status") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin > 1) + warning ("freport: ignoring extra arguments"); + + retval = freport_internal (); + + return retval; +} + Octave_object freport_internal (void) { @@ -495,6 +584,21 @@ return retval; } +DEFUN ("frewind", Ffrewind, Sfrewind, 2, 1, + "frewind (FILENAME or FILENUM): set file position at beginning of file") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2) + print_usage ("frewind"); + else + retval = frewind_internal (args); + + return retval; +} + Octave_object frewind_internal (const Octave_object& args) { @@ -502,7 +606,7 @@ Pix p = file_io_get_file (args(1), "a+", "frewind"); - if (p != (Pix) NULL) + if (p) { file_info file = file_list (p); rewind (file.fptr ()); @@ -511,6 +615,23 @@ return retval; } +DEFUN ("fseek", Ffseek, Sfseek, 4, 1, + "fseek (FILENAME or FILENUM, OFFSET [, ORIGIN])\n\ +\n\ +set file position for reading or writing") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 3 && nargin != 4) + print_usage ("fseek"); + else + retval = fseek_internal (args); + + return retval; +} + Octave_object fseek_internal (const Octave_object& args) { @@ -520,7 +641,7 @@ Pix p = file_io_get_file (args(1), "a+", "fseek"); - if (p == (Pix) NULL) + if (! p) return retval; long origin = SEEK_SET; @@ -567,6 +688,24 @@ return retval; } +/* + * Tell current position of file. + */ +DEFUN ("ftell", Fftell, Sftell, 2, 1, + "POSITION = ftell (FILENAME or FILENUM): returns the current file position") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2) + print_usage ("ftell"); + else + retval = ftell_internal (args); + + return retval; +} + Octave_object ftell_internal (const Octave_object& args) { @@ -574,7 +713,7 @@ Pix p = file_io_get_file (args(1), "a+", "ftell"); - if (p != (Pix) NULL) + if (p) { file_info file = file_list (p); long offset = ftell (file.fptr ()); @@ -807,6 +946,60 @@ } +/* + * Formatted printing to a file. + */ +DEFUN ("fprintf", Ffprintf, Sfprintf, -1, 1, + "fprintf (FILENAME or FILENUM, FORMAT, ...)") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin < 3) + print_usage ("fprintf"); + else + retval = do_printf ("fprintf", args, nargout); + + return retval; +} + +/* + * Formatted printing. + */ +DEFUN ("printf", Fprintf, Sprintf, -1, 1, + "printf (FORMAT, ...)") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin < 2) + print_usage ("printf"); + else + retval = do_printf ("printf", args, nargout); + + return retval; +} + +/* + * Formatted printing to a string. + */ +DEFUN ("sprintf", Fsprintf, Ssprintf, -1, 1, + "s = sprintf (FORMAT, ...)") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin < 2) + print_usage ("sprintf"); + else + retval = do_printf ("sprintf", args, nargout); + + return retval; +} + Octave_object do_printf (const char *type, const Octave_object& args, int nargout) { @@ -830,7 +1023,7 @@ Pix p = file_io_get_file (args(1), "a+", type); - if (p == (Pix) NULL) + if (! p) return retval; file = file_list (p); @@ -1070,14 +1263,68 @@ return -1; } +/* + * Formatted reading from a file. + */ +DEFUN ("fscanf", Ffscanf, Sfscanf, 3, -1, + "[A, B, C, ...] = fscanf (FILENAME or FILENUM, FORMAT)") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2 && nargin != 3) + print_usage ("fscanf"); + else + retval = do_scanf ("fscanf", args, nargout); + + return retval; +} + +/* + * Formatted reading. + */ +DEFUN ("scanf", Fscanf, Sscanf, 2, -1, + "[A, B, C, ...] = scanf (FORMAT)") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2) + print_usage ("scanf"); + else + retval = do_scanf ("scanf", args, nargout); + + return retval; +} + +/* + * Formatted reading from a string. + */ +DEFUN ("sscanf", Fsscanf, Ssscanf, 3, -1, + "[A, B, C, ...] = sscanf (STRING, FORMAT)") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 3) + print_usage ("sscanf"); + else + retval = do_scanf ("sscanf", args, nargout); + + return retval; +} + Octave_object do_scanf (const char *type, const Octave_object& args, int nargout) { Octave_object retval; - char *scanf_fmt = (char *) NULL; - char *tmp_file = (char *) NULL; + char *scanf_fmt = 0; + char *tmp_file = 0; int tmp_file_open = 0; - FILE *fptr = (FILE *) NULL; + FILE *fptr = 0; file_info file; fmt_arg_count = 0; @@ -1099,7 +1346,7 @@ { Pix p = file_io_get_file (args(1), "r", type); - if (p == (Pix) NULL) + if (! p) return retval; file = file_list (p); @@ -1113,7 +1360,7 @@ fptr = file.fptr (); } - if ((fptr == (FILE *) NULL && args(1).is_string_type ()) + if ((! fptr && args(1).is_string_type ()) || (doing_fscanf && file.number () == 0)) { char *string; @@ -1131,10 +1378,10 @@ else string = args(1).string_value (); - tmp_file = tmpnam ((char *) NULL); + tmp_file = tmpnam (0); fptr = fopen (tmp_file, "w+"); - if (fptr == (FILE *) NULL) + if (! fptr) { error ("%s: error opening temporary file", type); return retval; @@ -1142,7 +1389,7 @@ tmp_file_open = 1; unlink (tmp_file); - if (string == (char *) NULL) + if (! string) panic_impossible (); int success = fputs (string, fptr); @@ -1249,6 +1496,33 @@ return len / size; } +DEFUN ("fread", Ffread, Sfread, 4, 2, + "[DATA, COUNT] = fread (FILENUM, SIZE, PRECISION)\n\ +\n\ + Reads data in binary form of type PRECISION from a file.\n\ +\n\ + FILENUM : file number from fopen\n\ + SIZE : size specification for the Data matrix\n\ + PRECISION : type of data to read, valid types are\n\ +\n\ + 'char', 'schar', 'short', 'int', 'long', 'float'\n\ + 'double', 'uchar', 'ushort', 'uint', 'ulong'\n\ +\n\ + DATA : matrix in which the data is stored\n\ + COUNT : number of elements read") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin < 2 || nargin > 4) + print_usage ("fread"); + else + retval = fread_internal (args, nargout); + + return retval; +} + /* * Read binary data from a file. * @@ -1281,7 +1555,7 @@ Pix p = file_io_get_file (args(1), "r", "fread"); - if (p == (Pix) NULL) + if (! p) return retval; // Get type and number of bytes per element to read. @@ -1392,6 +1666,32 @@ return retval; } +DEFUN ("fwrite", Ffwrite, Sfwrite, 4, 1, + "COUNT = fwrite (FILENUM, DATA, PRECISION)\n\ +\n\ + Writes data to a file in binary form of size PRECISION\n\ +\n\ + FILENUM : file number from fopen\n\ + DATA : matrix of elements to be written\n\ + PRECISION : type of data to read, valid types are\n\ +\n\ + 'char', 'schar', 'short', 'int', 'long', 'float'\n\ + 'double', 'uchar', 'ushort', 'uint', 'ulong'\n\ +\n\ + COUNT : number of elements written") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin < 3 || nargin > 4) + print_usage ("fwrite"); + else + retval = fwrite_internal (args, nargout); + + return retval; +} + /* * Write binary data to a file. * @@ -1417,7 +1717,7 @@ Pix p = file_io_get_file (args(1), "a+", "fwrite"); - if (p == (Pix) NULL) + if (! p) return retval; // Get type and number of bytes per element to read. @@ -1445,6 +1745,24 @@ return retval; } +DEFUN ("feof", Ffeof, Sfeof, 2, 1, + "ERROR = feof (FILENAME or FILENUM)\n\ +\n\ + Returns a non zero value for an end of file condition for the\n\ + file specified by FILENAME or FILENUM from fopen") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2) + print_usage ("feof"); + else + retval = feof_internal (args, nargout); + + return retval; +} + /* * Check for an EOF condition on a file opened by fopen. * @@ -1461,13 +1779,31 @@ // Get file info. Pix p = return_valid_file (args(1)); - if (p == (Pix) NULL) + if (! p) return retval; file_info file = file_list (p); retval.resize (1); - retval(0) = tree_constant (feof (file.fptr ())); + retval(0) = (double) feof (file.fptr ()); + + return retval; +} + +DEFUN ("ferror", Fferror, Sferror, 2, 1, + "ERROR = ferror (FILENAME or FILENUM)\n\ +\n\ + Returns a non zero value for an error condition on the\n\ + file specified by FILENAME or FILENUM from fopen") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2) + print_usage ("ferror"); + else + retval = ferror_internal (args, nargout); return retval; } @@ -1489,7 +1825,7 @@ // Get file info. Pix p = return_valid_file (args(1)); - if (p == (Pix) NULL) + if (! p) return retval; file_info file = file_list (p); diff --git a/src/help.cc b/src/help.cc --- a/src/help.cc +++ b/src/help.cc @@ -25,11 +25,42 @@ #include "config.h" #endif +#include +#include #include +#include -#include "builtins.h" +#include "tree.h" +#include "sighandlers.h" +#include "user-prefs.h" +#include "tree-expr.h" +#include "variables.h" +#include "oct-obj.h" +#include "symtab.h" +#include "octave.h" +#include "dirfns.h" +#include "pager.h" +#include "error.h" #include "utils.h" #include "help.h" +#include "defun.h" + +extern "C" +{ +#include "info/info.h" +#include "info/dribble.h" +#include "info/terminal.h" + +extern int initialize_info_session (); +extern int index_entry_exists (); +extern int do_info_index_search (); +extern void finish_info_session (); +extern char *replace_in_documentation (); + +// XXX FIXME XXX +#undef __FUNCTION_DEF +#include +} static help_list operators[] = { @@ -159,7 +190,7 @@ { "~=", "Logical not equals operator. See also `<>' and `!='.\n", }, - { (char *) NULL, (char *) NULL, }, + { 0, 0, }, }; static help_list keywords[] = @@ -215,7 +246,7 @@ { "while", "Begin a while loop.\n", }, - { (char *) NULL, (char *) NULL, }, + { 0, 0, }, }; /* @@ -226,26 +257,26 @@ { count = 0; help_list *ptr = lst; - while (ptr->name != (char *) NULL) + while (ptr->name) { count++; ptr++; } if (count == 0) - return (char **) NULL; + return 0; char **name_list = new char * [count+1]; ptr = lst; int i = 0; - while (ptr->name != (char *) NULL) + while (ptr->name) { name_list[i++] = strsave (ptr->name); ptr++; } - name_list[i] = (char *) NULL; + name_list[i] = 0; return name_list; } @@ -261,6 +292,267 @@ return keywords; } +static void +help_syms_list (ostrstream& output_buf, help_list *list, + const char *desc) +{ + int count = 0; + char **symbols = names (list, count); + output_buf << "\n*** " << desc << ":\n\n"; + if (symbols && count > 0) + list_in_columns (output_buf, symbols); + delete [] symbols; +} + +static void +simple_help (void) +{ + ostrstream output_buf; + + help_syms_list (output_buf, operator_help (), "operators"); + + help_syms_list (output_buf, keyword_help (), "reserved words"); + + help_syms_list (output_buf, builtin_text_functions_help (), + "text functions (these names are also reserved)"); + + help_syms_list (output_buf, builtin_mapper_functions_help (), + "mapper functions"); + + help_syms_list (output_buf, builtin_general_functions_help (), + "general functions"); + + help_syms_list (output_buf, builtin_variables_help (), + "builtin variables"); + +// Also need to list variables and currently compiled functions from +// the symbol table, if there are any. + +// Also need to search octave_path for script files. + + char **path = pathstring_to_vector (user_pref.loadpath); + + char **ptr = path; + if (ptr) + { + while (*ptr) + { + int count; + char **names = get_fcn_file_names (count, *ptr, 0); + output_buf << "\n*** function files in " + << make_absolute (*ptr, the_current_working_directory) + << ":\n\n"; + if (names && count > 0) + list_in_columns (output_buf, names); + delete [] names; + ptr++; + } + } + + additional_help_message (output_buf); + output_buf << ends; + maybe_page_output (output_buf); +} + +static int +try_info (const char *string, int force = 0) +{ + int status = 0; + + char *directory_name = strsave (user_pref.info_file); + char *temp = filename_non_directory (directory_name); + + if (temp != directory_name) + { + *temp = 0; + info_add_path (directory_name, INFOPATH_PREPEND); + } + + delete [] directory_name; + + NODE *initial_node = info_get_node (user_pref.info_file, 0); + + if (! initial_node) + { + warning ("can't find info file!\n"); + status = -1; + } + else + { + status = initialize_info_session (initial_node, 0); + + if (status == 0 && (force || index_entry_exists (windows, string))) + { + terminal_clear_screen (); + + terminal_prep_terminal (); + + display_update_display (windows); + + info_last_executed_command = 0; + + if (! force) + do_info_index_search (windows, 0, string); + + char *format = replace_in_documentation + ("Type \"\\[quit]\" to quit, \"\\[get-help-window]\" for help."); + + window_message_in_echo_area (format); + + info_read_and_dispatch (); + + terminal_goto_xy (0, screenheight - 1); + + terminal_clear_to_eol (); + + terminal_unprep_terminal (); + + status = 1; + } + + finish_info_session (initial_node, 0); + } + + return status; +} + +DEFUN_TEXT ("help", Fhelp, Shelp, -1, 1, + "help [-i] [topic ...]\n\ +\n\ +print cryptic yet witty messages") +{ + Octave_object retval; + + DEFINE_ARGV("help"); + + if (argc == 1) + { + simple_help (); + } + else + { + if (argv[1] && strcmp (argv[1], "-i") == 0) + { + argc--; + argv++; + + if (argc == 1) + { + volatile sig_handler *old_sigint_handler; + old_sigint_handler = signal (SIGINT, SIG_IGN); + + try_info (0, 1); + + signal (SIGINT, old_sigint_handler); + } + else + { + while (--argc > 0) + { + argv++; + + if (! *argv || ! **argv) + continue; + + volatile sig_handler *old_sigint_handler; + old_sigint_handler = signal (SIGINT, SIG_IGN); + + if (! try_info (*argv)) + { + message ("help", + "sorry, `%s' is not indexed in the manual", + *argv); + sleep (2); + } + + signal (SIGINT, old_sigint_handler); + } + } + } + else + { + 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 (); + + while (--argc > 0) + { + argv++; + + if (! *argv || ! **argv) + continue; + + if (help_from_list (output_buf, op_help_list, *argv, 0)) + continue; + + if (help_from_list (output_buf, kw_help_list, *argv, 0)) + continue; + + sym_rec = curr_sym_tab->lookup (*argv, 0, 0); + if (sym_rec) + { + char *h = sym_rec->help (); + if (h && *h) + { + output_buf << "\n*** " << *argv << ":\n\n" + << h << "\n"; + continue; + } + } + + 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.parse_fcn_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"; + } + + additional_help_message (output_buf); + output_buf << ends; + maybe_page_output (output_buf); + } + } + + DELETE_ARGV; + + return retval; +} + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/src/input.cc b/src/input.cc --- a/src/input.cc +++ b/src/input.cc @@ -27,6 +27,11 @@ #include "config.h" #endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include #include #include #include @@ -49,7 +54,7 @@ */ #if 0 #define LINE_SIZE 8192 -static int no_line_editing = 1; +static int no_line_editing = 0; #endif char * @@ -57,7 +62,7 @@ { #if 0 static int state = 0; - static char *line_from_stdin = (char *) NULL; + static char *line_from_stdin = 0; if (no_line_editing) { if (! state) @@ -75,20 +80,38 @@ } } -#include "variables.h" +#include "help.h" #include "error.h" #include "utils.h" #include "input.h" #include "pager.h" -#include "help.h" +#include "parse.h" +#include "dirfns.h" +#include "octave.h" +#include "variables.h" +#include "tree-const.h" #include "octave-hist.h" #include "sighandlers.h" -#include "parse.h" #include "user-prefs.h" -#include "builtins.h" +#include "oct-obj.h" +#include "defun.h" + +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +// The size that strings change by. +#ifndef DEFAULT_ARRAY_SIZE +#define DEFAULT_ARRAY_SIZE 512 +#endif + +// The growth rate for the prompt string. +#ifndef PROMPT_GROWTH +#define PROMPT_GROWTH 50 +#endif // Global pointer for eval(). -const char *current_eval_string = (char *) NULL; +const char *current_eval_string = 0; // Nonzero means get input from current_eval_string. int get_input_from_eval_string = 0; @@ -97,13 +120,13 @@ int reading_fcn_file = 0; // Simple name of function file we are reading. -char *curr_fcn_file_name = (char *) NULL; +char *curr_fcn_file_name = 0; // Nonzero means we're parsing a script file. int reading_script_file = 0; // If we are reading from an M-file, this is it. -FILE *ff_instream = (FILE *) NULL; +FILE *ff_instream = 0; // Nonzero means we are using readline. int using_readline = 1; @@ -121,11 +144,282 @@ int promptflag = 1; // The current line of input, from wherever. -char *current_input_line = (char *) NULL; +char *current_input_line = 0; // A line of input from readline. -static char *octave_gets_line = (char *) NULL; +static char *octave_gets_line = 0; + +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. + */ +static char * +sub_append_string (char *source, char *target, int *index, int *size) +{ + if (source) + { + while ((int)strlen (source) >= (int)(*size - *index)) + { + char *tmp = new char [*size += DEFAULT_ARRAY_SIZE]; + strcpy (tmp, target); + delete [] target; + target = tmp; + } + + strcat (target, source); + *index += strlen (source); + + delete [] source; + } + return target; +} + +/* + * Return the octal number parsed from STRING, or -1 to indicate that + * the string contained a bad number. + */ +int +read_octal (const char *string) +{ + int result = 0; + int digits = 0; + + while (*string && *string >= '0' && *string < '8') + { + digits++; + result = (result * 8) + *string++ - '0'; + } + + if (! digits || result > 0777 || *string) + result = -1; + + 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 + * \ character code in octal + * \\ a backslash + */ +static char * +decode_prompt_string (const char *string) +{ + int result_size = PROMPT_GROWTH; + int result_index = 0; + char *result = new char [PROMPT_GROWTH]; + int c; + char *temp = 0; + + result[0] = 0; + while (c = *string++) + { + if (c == '\\') + { + c = *string; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + char octal_string[4]; + int n; + + strncpy (octal_string, string, 3); + octal_string[3] = '\0'; + + n = read_octal (octal_string); + + temp = strsave ("\\"); + if (n != -1) + { + string += 3; + temp[0] = n; + } + + c = 0; + goto add_string; + } + + case 't': + case 'd': + /* Make the current time/date into a string. */ + { + time_t the_time = time (0); + char *ttemp = ctime (&the_time); + temp = strsave (ttemp); + + if (c == 't') + { + strcpy (temp, temp + 11); + temp[8] = '\0'; + } + else + temp[10] = '\0'; + + goto add_string; + } + case 'n': + if (! no_line_editing) + temp = strsave ("\r\n"); + else + temp = strsave ("\n"); + goto add_string; + + case 's': + { + temp = base_pathname (prog_name); + temp = strsave (temp); + goto add_string; + } + + case 'w': + case 'W': + { + char t_string[MAXPATHLEN]; +#define EFFICIENT +#ifdef EFFICIENT + +// Use the value of PWD because it is much more effecient. + + temp = user_pref.pwd; + + if (! temp) + getcwd (t_string, MAXPATHLEN); + else + strcpy (t_string, temp); +#else + getcwd (t_string, MAXPATHLEN); +#endif /* EFFICIENT */ + + if (c == 'W') + { + char *dir = strrchr (t_string, '/'); + if (dir && dir != t_string) + strcpy (t_string, dir + 1); + temp = strsave (t_string); + } + else + temp = strsave (polite_directory_format (t_string)); + goto add_string; + } + + case 'u': + { + temp = strsave (user_name); + + goto add_string; + } + + case 'h': + { + char *t_string; + + temp = strsave (host_name); + if (t_string = strchr (temp, '.')) + *t_string = '\0'; + + goto add_string; + } + + case '#': + { + char number_buffer[128]; + sprintf (number_buffer, "%d", current_command_number); + temp = strsave (number_buffer); + goto add_string; + } + + case '!': + { + char number_buffer[128]; + int num = current_history_number (); + if (num > 0) + sprintf (number_buffer, "%d", num); + else + strcpy (number_buffer, "!"); + temp = strsave (number_buffer); + goto add_string; + } + + case '$': + temp = strsave (geteuid () == 0 ? "#" : "$"); + goto add_string; + + case '\\': + temp = strsave ("\\"); + goto add_string; + + default: + temp = strsave ("\\ "); + temp[1] = c; + + add_string: + if (c) + string++; + result = + (char *)sub_append_string (temp, result, + &result_index, &result_size); + temp = 0; /* Free ()'ed in sub_append_string (). */ + result[result_index] = '\0'; + break; + } + } + else + { + while (3 + result_index > result_size) + { + char *tmp = new char [result_size += PROMPT_GROWTH]; + strcpy (tmp, result); + delete [] result; + result = tmp; + } + result[result_index++] = c; + result[result_index] = '\0'; + } + } + +#if 0 + /* I don't really think that this is a good idea. Do you? */ + if (! find_variable ("NO_PROMPT_VARS")) + { + WORD_LIST *expand_string (), *list; + char *string_list (); + + list = expand_string (result, 1); + free (result); + result = string_list (list); + dispose_words (list); + } +#endif + + return result; +} /* * Use GNU readline to get an input line and store it in the history * list. @@ -133,10 +427,10 @@ static char * octave_gets (void) { - if (octave_gets_line != NULL) + if (octave_gets_line) { free (octave_gets_line); - octave_gets_line = (char *) NULL; + octave_gets_line = 0; } if (interactive || forced_interactive) @@ -181,7 +475,7 @@ { int status = 0; - static char *stashed_line = (char *) NULL; + static char *stashed_line = 0; if (get_input_from_eval_string) { @@ -205,7 +499,7 @@ else if (using_readline) { char *cp = octave_gets (); - if (cp != (char *) NULL) + if (cp) { int len = strlen (cp); if (len >= max_size) @@ -226,12 +520,12 @@ if (reading_fcn_file || reading_script_file) curr_stream = ff_instream; - assert (curr_stream != (FILE *) NULL); + assert (curr_stream); // Why is this required? buf[0] = '\0'; - if (fgets (buf, max_size, curr_stream) != (char *) NULL) + if (fgets (buf, max_size, curr_stream)) { int len = strlen (buf); if (len > max_size - 2) @@ -272,14 +566,14 @@ * warning if the file doesn't exist. */ FILE * -get_input_from_file (char *name, int warn = 1) +get_input_from_file (char *name, int warn) { - FILE *instream = (FILE *) NULL; + FILE *instream = 0; if (name && *name) instream = fopen (name, "r"); - if (instream == (FILE *) NULL && warn) + if (! instream && warn) warning ("%s: no such file or directory", name); if (reading_fcn_file || reading_script_file) @@ -308,14 +602,14 @@ static int len = 0; static int list_index = 0; - static char **name_list = (char **) NULL; + static char **name_list = 0; if (state == 0) { list_index = 0; len = strlen (text); - if (name_list != (char **) NULL) + if (name_list) { char **ptr = name_list; while (ptr && *ptr) @@ -327,7 +621,7 @@ } char *name; - while ((name = name_list[list_index]) != (char *) NULL) + while ((name = name_list[list_index]) != 0) { list_index++; if (strncmp (name, text, len) == 0) @@ -338,13 +632,13 @@ } } - return (char *) NULL; + return 0; } static char ** command_completer (char *text, int start, int end) { - char **matches = (char **) NULL; + char **matches = 0; matches = completion_matches (text, command_generator); return matches; } @@ -359,7 +653,7 @@ static int saved_history_line_to_use = 0; // ?? -static Function *old_rl_startup_hook = (Function *) NULL; +static Function *old_rl_startup_hook = 0; static void set_saved_history (void) @@ -382,7 +676,7 @@ if (rl_undo_list) { free_undo_list (); - rl_undo_list = (UNDO_LIST *) NULL; + rl_undo_list = 0; } } } @@ -426,6 +720,124 @@ (Function *) operate_and_get_next, CTRL ('O')); } +static int +match_sans_spaces (const char *standard, const char *test) +{ + const char *tp = test; + while (*tp == ' ' || *tp == '\t') + tp++; + + const char *ep = test + strlen (test) - 1; + while (*ep == ' ' || *ep == '\t') + ep--; + + int len = ep - tp + 1; + + return (strncmp (standard, tp, len) == 0); +} + +static Octave_object +get_user_input (const Octave_object& args, int nargout, int debug = 0) +{ + tree_constant retval; + + int nargin = args.length (); + + int read_as_string = 0; + + if (nargin == 3) + read_as_string++; + + char *prompt = "debug> "; + if (nargin > 1) + { + if (args(1).is_string_type ()) + prompt = args(1).string_value (); + else + { + error ("input: unrecognized argument"); + return retval; + } + } + + again: + + flush_output_to_pager (); + + char *input_buf = gnu_readline (prompt); + + if (input_buf) + { + maybe_save_history (input_buf); + + int len = strlen (input_buf); + + if (len < 1) + { + if (debug) + goto again; + else + return retval; + } + + if (match_sans_spaces ("exit", input_buf) + || match_sans_spaces ("quit", input_buf) + || match_sans_spaces ("return", input_buf)) + return tree_constant (); + else if (read_as_string) + retval = input_buf; + else + { + int parse_status = 0; + retval = eval_string (input_buf, 0, 0, parse_status); + if (debug && retval.is_defined ()) + retval.eval (1); + } + } + else + error ("input: reading user-input failed!"); + + if (debug) + goto again; + + return retval; +} + +DEFUN ("input", Finput, Sinput, 3, 1, + "input (PROMPT [, S])\n\ +\n\ +Prompt user for input. If the second argument is present, return +value as a string.") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin == 2 || nargin == 3) + retval = get_user_input (args, nargout); + else + print_usage ("input"); + + return retval; +} + +DEFUN ("keyboard", Fkeyboard, Skeyboard, 2, 1, + "keyboard (PROMPT)\n\ +\n\ +maybe help in debugging function files") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin == 1 || nargin == 2) + retval = get_user_input (args, nargout, 1); + else + print_usage ("keyboard"); + + return retval; +} + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/src/mappers.cc b/src/mappers.cc --- a/src/mappers.cc +++ b/src/mappers.cc @@ -28,8 +28,11 @@ #include #include +#include "missing-math.h" +#include "variables.h" #include "mappers.h" #include "utils.h" +#include "defun.h" #if defined (_AIX) && defined (__GNUG__) #undef finite @@ -272,6 +275,102 @@ return retval; } +void +install_mapper_functions (void) +{ + DEFUN_MAPPER ("abs", Sabs, 0, 0.0, 0.0, fabs, abs, 0, + "abs (X): compute abs (X) for each element of X"); + + DEFUN_MAPPER ("acos", Sacos, 1, -1.0, 1.0, acos, 0, acos, + "acos (X): compute acos (X) for each element of X"); + + DEFUN_MAPPER ("acosh", Sacosh, 1, 1.0, DBL_MAX, acosh, 0, acosh, + "acosh (X): compute acosh (X) for each element of X"); + + DEFUN_MAPPER ("angle", Sangle, 0, 0.0, 0.0, arg, arg, 0, + "angle (X): compute arg (X) for each element of X"); + + DEFUN_MAPPER ("arg", Sarg, 0, 0.0, 0.0, arg, arg, 0, + "arg (X): compute arg (X) for each element of X"); + + DEFUN_MAPPER ("asin", Sasin, 1, -1.0, 1.0, asin, 0, asin, + "asin (X): compute asin (X) for each element of X"); + + DEFUN_MAPPER ("asinh", Sasinh, 0, 0.0, 0.0, asinh, 0, asinh, + "asinh (X): compute asinh (X) for each element of X"); + + DEFUN_MAPPER ("atan", Satan, 0, 0.0, 0.0, atan, 0, atan, + "atan (X): compute atan (X) for each element of X"); + + DEFUN_MAPPER ("atanh", Satanh, 1, -1.0, 1.0, atanh, 0, atanh, + "atanh (X): compute atanh (X) for each element of X"); + + DEFUN_MAPPER ("ceil", Sceil, 0, 0.0, 0.0, ceil, 0, ceil, + "ceil (X): round elements of X toward +Inf"); + + DEFUN_MAPPER ("conj", Sconj, 0, 0.0, 0.0, conj, 0, conj, + "conj (X): compute complex conjugate for each element of X"); + + DEFUN_MAPPER ("cos", Scos, 0, 0.0, 0.0, cos, 0, cos, + "cos (X): compute cos (X) for each element of X"); + + DEFUN_MAPPER ("cosh", Scosh, 0, 0.0, 0.0, cosh, 0, cosh, + "cosh (X): compute cosh (X) for each element of X"); + + DEFUN_MAPPER ("exp", Sexp, 0, 0.0, 0.0, exp, 0, exp, + "exp (X): compute exp (X) for each element of X"); + + DEFUN_MAPPER ("finite", Sfinite, 0, 0.0, 0.0, xfinite, xfinite, 0, + "finite (X): return 1 for finite elements of X"); + + DEFUN_MAPPER ("fix", Sfix, 0, 0.0, 0.0, fix, 0, fix, + "fix (X): round elements of X toward zero"); + + DEFUN_MAPPER ("floor", Sfloor, 0, 0.0, 0.0, floor, 0, floor, + "floor (X): round elements of X toward -Inf"); + + DEFUN_MAPPER ("isinf", Sisinf, 0, 0.0, 0.0, xisinf, xisinf, 0, + "isinf (X): return 1 for elements of X infinite"); + + DEFUN_MAPPER ("imag", Simag, 0, 0.0, 0.0, imag, imag, 0, + "imag (X): return imaginary part for each elements of X"); + +#ifdef HAVE_ISNAN + DEFUN_MAPPER ("isnan", Sisnan, 0, 0.0, 0.0, xisnan, xisnan, 0, + "isnan (X): return 1 where elements of X are NaNs"); +#endif + + DEFUN_MAPPER ("log", Slog, 1, 0.0, DBL_MAX, log, 0, log, + "log (X): compute log (X) for each element of X"); + + DEFUN_MAPPER ("log10", Slog10, 1, 0.0, DBL_MAX, log10, 0, log10, + "log10 (X): compute log10 (X) for each element of X"); + + DEFUN_MAPPER ("real", Sreal, 0, 0.0, 0.0, real, real, 0, + "real (X): return real part for each element of X"); + + DEFUN_MAPPER ("round", Sround, 0, 0.0, 0.0, round, 0, round, + "round (X): round elements of X to nearest integer"); + + DEFUN_MAPPER ("sign", Ssign, 0, 0.0, 0.0, signum, 0, signum, + "sign (X): apply signum function to elements of X"); + + DEFUN_MAPPER ("sin", Ssin, 0, 0.0, 0.0, sin, 0, sin, + "sin (X): compute sin (X) for each element of X"); + + DEFUN_MAPPER ("sinh", Ssinh, 0, 0.0, 0.0, sinh, 0, sinh, + "sinh (X): compute sinh (X) for each element of X"); + + DEFUN_MAPPER ("sqrt", Ssqrt, 1, 0.0, DBL_MAX, sqrt, 0, sqrt, + "sqrt (X): compute sqrt (X) for each element of X"); + + DEFUN_MAPPER ("tan", Stan, 0, 0.0, 0.0, tan, 0, tan, + "tan (X): compute tan (X) for each element of X"); + + DEFUN_MAPPER ("tanh", Stanh, 0, 0.0, 0.0, tanh, 0, tanh, + "tanh (X): compute tanh (X) for each element of X"); +} + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/src/mappers.h b/src/mappers.h --- a/src/mappers.h +++ b/src/mappers.h @@ -26,7 +26,39 @@ class Complex; -#include "missing-math.h" +typedef double (*d_d_Mapper)(double); +typedef double (*d_c_Mapper)(const Complex&); +typedef Complex (*c_c_Mapper)(const Complex&); + +// If can_return_complex_for_real_arg is 1, lower_limit and +// upper_limit specify the range of values for which a real arg +// returns a real value. Outside that range, we have to convert args +// to complex, and call the complex valued function. +// +// If can_return_complex_for_real_arg is 0, lower_limit and +// upper_limit are ignored. + +struct Mapper_fcn +{ + int can_return_complex_for_real_arg; + double lower_limit; + double upper_limit; + d_d_Mapper d_d_mapper; + d_c_Mapper d_c_mapper; + c_c_Mapper c_c_mapper; +}; + +struct builtin_mapper_function +{ + char *name; + int can_return_complex_for_real_arg; + double lower_limit; + double upper_limit; + d_d_Mapper d_d_mapper; + d_c_Mapper d_c_mapper; + c_c_Mapper c_c_mapper; + char *help_string; +}; extern double arg (double x); extern double conj (double x); @@ -35,13 +67,13 @@ extern double real (double x); extern double round (double x); extern double signum (double x); +extern double xisnan (double x); extern double xfinite (double x); extern double xisinf (double x); -extern double xisnan (double x); +extern double xisnan (const Complex& x); extern double xfinite (const Complex& x); extern double xisinf (const Complex& x); -extern double xisnan (const Complex& x); extern Complex acos (const Complex& x); extern Complex acosh (const Complex& x); @@ -58,6 +90,8 @@ extern Complex tan (const Complex& x); extern Complex tanh (const Complex& x); +extern void install_mapper_functions (void); + #endif /* diff --git a/src/oct-hist.cc b/src/oct-hist.cc --- a/src/oct-hist.cc +++ b/src/oct-hist.cc @@ -49,10 +49,12 @@ #include "error.h" #include "input.h" #include "octave.h" +#include "oct-obj.h" #include "user-prefs.h" #include "unwind-prot.h" #include "octave-hist.h" #include "sighandlers.h" +#include "defun.h" extern "C" { @@ -86,7 +88,7 @@ { int size = 1024; char *env_size = getenv ("OCTAVE_HISTSIZE"); - if (env_size != (char *) NULL) + if (env_size) { int val; if (sscanf (env_size, "%d", &val) == 1) @@ -98,24 +100,21 @@ static char * default_history_file (void) { - char *file = (char *) NULL;; + char *file = 0; char *env_file = getenv ("OCTAVE_HISTFILE"); - if (env_file != (char *) NULL) + if (env_file) { fstream f (env_file, (ios::in | ios::out)); - if (f != 0) + if (f) { file = strsave (env_file); f.close (); } } - if (file == (char *) NULL) - { - if (home_directory != NULL) - file = strconcat (home_directory, "/.octave_hist"); - } + if (! file && home_directory) + file = strconcat (home_directory, "/.octave_hist"); return file; } @@ -260,7 +259,7 @@ if (hlist) { - for (int i = 0; hlist[i] != (HIST_ENTRY *) NULL; i++) + for (int i = 0; hlist[i]; i++) ; // Do nothing. if (limit < 0) @@ -321,7 +320,7 @@ if (! lindex) { delete [] line; - return (char *) NULL; + return 0; } if (lindex + 2 >= line_len) @@ -354,12 +353,12 @@ static void edit_history_repl_hist (char *command) { - if (command == (char *) NULL || *command == '\0') + if (! command || ! *command) return; HIST_ENTRY **hlist = history_list (); - if (hlist == (HIST_ENTRY **) NULL) + if (! hlist) return; for (int i = 0; hlist[i]; i++) @@ -371,11 +370,11 @@ // Don't free this. HIST_ENTRY *histent = history_get (history_base + i); - if (histent == (HIST_ENTRY *) NULL) + if (! histent) return; - char *data = (char *) NULL; - if (histent->data != (char *) NULL) + char *data = 0; + if (histent->data) { int len = strlen (histent->data); data = (char *) malloc (len); @@ -387,12 +386,12 @@ if (command[n - 1] == '\n') command[n - 1] = '\0'; - if (command != (char *) NULL && *command != '\0') + if (command && *command) { HIST_ENTRY *discard = replace_history_entry (i, command, data); - if (discard != (HIST_ENTRY *) NULL) + if (discard) { - if (discard->line != (char *) NULL) + if (discard->line) free (discard->line); free ((char *) discard); @@ -403,7 +402,7 @@ static void edit_history_add_hist (char *line) { - if (line != (char *) NULL) + if (line) { int len = strlen (line); if (len > 0 && line[len-1] == '\n') @@ -425,7 +424,7 @@ int hist_count = 0; - while (hlist[hist_count++] != (HIST_ENTRY *) NULL) + while (hlist[hist_count++]) ; // Find the number of items in the history list. // The current command line is already part of the history list by the @@ -474,13 +473,13 @@ || hist_end > hist_count) { error ("%s: history specification out of range", warn_for); - return (char *) NULL; + return 0; } if (usage_error) { usage ("%s [first] [last]", warn_for); - return (char *) NULL; + return 0; } if (hist_end < hist_beg) @@ -491,14 +490,14 @@ reverse = 1; } - char *name = tmpnam ((char *) NULL); + char *name = tmpnam (0); fstream file (name, ios::out); if (! file) { error ("%s: couldn't open temporary file `%s'", warn_for, name); - return (char *) NULL; + return 0; } if (reverse) @@ -522,7 +521,7 @@ { char *name = mk_tmp_hist_file (argc, argv, 0, "edit_history"); - if (name == (char *) NULL) + if (! name) return; // Call up our favorite editor on the file of commands. @@ -545,7 +544,7 @@ char *line; int first = 1; - while ((line = edit_history_readline (file)) != NULL) + while ((line = edit_history_readline (file)) != 0) { // Skip blank lines @@ -592,7 +591,7 @@ { char *name = mk_tmp_hist_file (argc, argv, 1, "run_history"); - if (name == (char *) NULL) + if (! name) return; // Turn on command echo, so the output from this will make better sense. @@ -627,6 +626,54 @@ } +DEFUN_TEXT ("edit_history", Fedit_history, Sedit_history, -1, 1, + "edit_history [first] [last]\n\ +\n\ +edit commands from the history list") +{ + Octave_object retval; + + DEFINE_ARGV("edit_history"); + + do_edit_history (argc, argv); + + DELETE_ARGV; + + return retval; +} + +DEFUN_TEXT ("history", Fhistory, Shistory, -1, 1, + "history [N] [-w file] [-r file] [-q]\n\ +\n\ +display, save, or load command history") +{ + Octave_object retval; + + DEFINE_ARGV("history"); + + do_history (argc, argv); + + DELETE_ARGV; + + return retval; +} + +DEFUN_TEXT ("run_history", Frun_history, Srun_history, -1, 1, + "run_history [first] [last]\n\ +\n\ +run commands from the history list") +{ + Octave_object retval; + + DEFINE_ARGV("run_history"); + + do_run_history (argc, argv); + + DELETE_ARGV; + + return retval; +} + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/src/octave.cc b/src/octave.cc --- a/src/octave.cc +++ b/src/octave.cc @@ -40,6 +40,7 @@ #include #include #include +#include #include #include "getopt.h" @@ -50,8 +51,8 @@ #include "variables.h" #include "error.h" #include "tree-const.h" +#include "tree-plot.h" #include "utils.h" -#include "builtins.h" #include "input.h" #include "pager.h" #include "lex.h" @@ -59,9 +60,11 @@ #include "parse.h" #include "unwind-prot.h" #include "octave-hist.h" +#include "builtins.h" #include "version.h" #include "file-io.h" #include "sysdep.h" +#include "defun.h" #if !defined (HAVE_ATEXIT) && defined (HAVE_ON_EXIT) extern "C" { int on_exit (); } @@ -69,31 +72,31 @@ #endif // argv[0] for this program. -char *raw_prog_name = (char *) NULL; +char *raw_prog_name = 0; // Cleaned-up name of this program, not including path information. -char *prog_name = (char *) NULL; +char *prog_name = 0; // Login name for user running this program. -char *user_name = (char *) NULL; +char *user_name = 0; // Name of the host we are running on. -char *host_name = (char *) NULL; +char *host_name = 0; // User's home directory. -char *home_directory = (char *) NULL; +char *home_directory = 0; // Guess what? -char *the_current_working_directory = (char *) NULL; +char *the_current_working_directory = 0; // Load path specified on command line. -char *load_path = (char *) NULL; +char *load_path = 0; // Name of the info file specified on command line. -char *info_file = (char *) NULL; +char *info_file = 0; // Name of the editor to be invoked by the edit_history command. -char *editor = (char *) NULL; +char *editor = 0; // If nonzero, don't do fancy line editing. int no_line_editing = 0; @@ -105,10 +108,10 @@ int quitting_gracefully = 0; // Current command to execute. -tree *global_command = (tree *) NULL; +tree *global_command = 0; // Pointer to function that is currently being evaluated. -tree_function *curr_function = (tree_function *) NULL; +tree_function *curr_function = 0; // Nonzero means input is coming from startup file. int input_from_startup_file = 0; @@ -182,10 +185,10 @@ host_name = strsave (hostname); char *hd = getenv ("HOME"); - if (hd == (char *) NULL) - home_directory = strsave ("I have no home~!"); + if (hd) + home_directory = strsave (hd); else - home_directory = strsave (hd); + home_directory = strsave ("I have no home!"); raw_prog_name = strsave (name); prog_name = strsave ("octave"); @@ -225,7 +228,7 @@ { reset_parser (); retval = yyparse (); - if (retval == 0 && global_command != NULL_TREE) + if (retval == 0 && global_command) { global_command->eval (print); delete global_command; @@ -246,7 +249,7 @@ reading_script_file = 1; FILE *f = get_input_from_file (s, 0); - if (f != (FILE *) NULL) + if (f) { unwind_protect_int (input_line_number); unwind_protect_int (current_input_column); @@ -281,8 +284,8 @@ // Try to execute commands from $HOME/.octaverc and ./.octaverc. - char *home_rc = (char *) NULL; - if (home_directory != NULL) + char *home_rc = 0; + if (home_directory) { home_rc = strconcat (home_directory, "/.octaverc"); parse_and_execute (home_rc, 0); @@ -416,7 +419,7 @@ forced_interactive = 1; break; case 'p': - if (optarg != (char *) NULL) + if (optarg) load_path = strsave (optarg); break; case 'q': @@ -429,7 +432,7 @@ print_version_and_exit (); break; case INFO_FILE_OPTION: - if (optarg != (char *) NULL) + if (optarg) info_file = strsave (optarg); break; default: @@ -479,13 +482,13 @@ else if (remaining_args == 1) { FILE *infile = get_input_from_file (argv[optind]); - if (infile == (FILE *) NULL) - clean_up_and_exit (1); - else + if (infile) { rl_blink_matching_paren = 0; switch_to_buffer (create_buffer (infile)); } + else + clean_up_and_exit (1); } else { @@ -544,7 +547,7 @@ retval = yyparse (); - if (retval == 0 && global_command != NULL_TREE) + if (retval == 0 && global_command) { global_command->eval (1); delete global_command; @@ -556,6 +559,196 @@ clean_up_and_exit (retval); } +DEFUN_TEXT ("casesen", Fcasesen, Scasesen, 2, 1, + "casesen [on|off]") +{ + Octave_object retval; + + DEFINE_ARGV("casesen"); + + if (argc == 1 || (argc > 1 && strcmp (argv[1], "off") == 0)) + warning ("casesen: sorry, Octave is always case sensitive"); + else if (argc > 1 && strcmp (argv[1], "on") == 0) + ; // ok. + else + print_usage ("casesen"); + + DELETE_ARGV; + + return retval; +} + +DEFALIAS (exit, quit) + +DEFUN ("flops", Fflops, Sflops, 2, 1, + "flops (): count floating point operations") +{ + int nargin = args.length (); + + if (nargin > 2) + print_usage ("flops"); + + warning ("flops is a flop, always returning zero"); + + return 0.0; +} + +DEFUN ("quit", Fquit, Squit, 1, 0, + "quit (): exit Octave gracefully") +{ + Octave_object retval; + quitting_gracefully = 1; + clean_up_and_exit (0); + return retval; +} + +DEFUN ("warranty", Fwarranty, Swarranty, 1, 0, + "warranty (): describe copying conditions") +{ + Octave_object retval; + + ostrstream output_buf; + output_buf << "\n Octave, version " << version_string + << ". Copyright (C) 1992, 1993, 1994 John W. Eaton\n" + << "\n\ + This program is free software; you can redistribute it and/or modify\n\ + it under the terms of the GNU General Public License as published by\n\ + the Free Software Foundation; either version 2 of the License, or\n\ + (at your option) any later version.\n\ +\n\ + This program is distributed in the hope that it will be useful,\n\ + but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ + GNU General Public License for more details.\n\ +\n\ + You should have received a copy of the GNU General Public License\n\ + along with this program. If not, write to the Free Software\n\ + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n\ +\n"; + + output_buf << ends; + maybe_page_output (output_buf); + + return retval; +} + +// XXX FIXME XXX -- this may not be the best place for these... + +Octave_object +feval (const Octave_object& args, int nargout) +{ + Octave_object retval; + + tree_fvc *fcn = is_valid_function (args(1), "feval", 1); + if (fcn) + { + int nargin = args.length () - 1; + Octave_object tmp_args (nargin); + for (int i = 0; i < nargin; i++) + tmp_args(i) = args(i+1); + retval = fcn->eval (0, nargout, tmp_args); + } + + return retval; +} + +DEFUN ("feval", Ffeval, Sfeval, -1, 1, + "feval (NAME, ARGS, ...)\n\ +\n\ +evaluate NAME as a function, passing ARGS as its arguments") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin > 1) + retval = feval (args, nargout); + else + print_usage ("feval"); + + return retval; +} + +tree_constant +eval_string (const char *string, int print, int ans_assign, + int& parse_status) +{ + begin_unwind_frame ("eval_string"); + + unwind_protect_int (get_input_from_eval_string); + unwind_protect_ptr (global_command); + unwind_protect_ptr (current_eval_string); + + get_input_from_eval_string = 1; + current_eval_string = string; + + YY_BUFFER_STATE old_buf = current_buffer (); + YY_BUFFER_STATE new_buf = create_buffer (0); + + 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 (); + + parse_status = yyparse (); + +// Important to reset the idea of where input is coming from before +// trying to eval the command we just parsed -- it might contain the +// name of an function file that still needs to be parsed! + + tree *command = global_command; + + run_unwind_frame ("eval_string"); + + tree_constant retval; + + if (parse_status == 0 && command) + { + retval = command->eval (print); + delete command; + } + + return retval; +} + +tree_constant +eval_string (const tree_constant& arg, int& parse_status) +{ + if (! arg.is_string_type ()) + { + error ("eval: expecting string argument"); + return -1; + } + + char *string = arg.string_value (); + +// Yes Virginia, we always print here... + + return eval_string (string, 1, 1, parse_status); +} + +DEFUN ("eval", Feval, Seval, 2, 1, + "eval (STRING): evaluate STRING as octave code") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin == 2) + { + int parse_status = 0; + retval = eval_string (args(1), parse_status); + } + else + print_usage ("eval"); + + return retval; +} + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/src/pager.cc b/src/pager.cc --- a/src/pager.cc +++ b/src/pager.cc @@ -1,7 +1,7 @@ // pager.cc -*- C++ -*- /* -Copyright (C) 1992, 1993 John W. Eaton +Copyright (C) 1992, 1993, 1994 John W. Eaton This file is part of Octave. @@ -36,13 +36,13 @@ #include "pager.h" // Where we stash output headed for the screen. -static ostrstream *pager_buf = (ostrstream *) NULL; +static ostrstream *pager_buf = 0; static int line_count (char *s) { int count = 0; - if (s != (char *) NULL) + if (s) { char c; while ((c = *s++) != '\0') @@ -89,7 +89,7 @@ if (interactive && user_pref.page_screen_output - && user_pref.pager_binary != (char *) NULL) + && user_pref.pager_binary) { *pager_buf << message; delete [] message; @@ -109,7 +109,7 @@ char *message = pager_buf->str (); - if (message == (char *) NULL || *message == '\0') + if (! message || ! *message) { delete [] message; initialize_pager (); @@ -121,7 +121,7 @@ if (nlines > terminal_rows () - 2) { char *pgr = user_pref.pager_binary; - if (pgr != (char *) NULL) + if (pgr) { oprocstream pager_stream (pgr); if (pager_stream) diff --git a/src/pr-output.cc b/src/pr-output.cc --- a/src/pr-output.cc +++ b/src/pr-output.cc @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -45,13 +44,14 @@ #include "pager.h" #include "error.h" #include "utils.h" +#include "defun.h" // Current format string for real numbers and the real part of complex // numbers. -static char *curr_real_fmt = (char *) NULL; +static char *curr_real_fmt = 0; // Current format string for the imaginary part of complex numbers. -static char *curr_imag_fmt = (char *) NULL; +static char *curr_imag_fmt = 0; // Nonzero means don\'t do any fancy formatting. static int free_format = 0; @@ -184,8 +184,8 @@ static void set_format (double d, int& fw) { - curr_real_fmt = (char *) NULL; - curr_imag_fmt = (char *) NULL; + curr_real_fmt = 0; + curr_imag_fmt = 0; if (free_format) return; @@ -275,8 +275,8 @@ static void set_format (const Matrix& m, int& fw) { - curr_real_fmt = (char *) NULL; - curr_imag_fmt = (char *) NULL; + curr_real_fmt = 0; + curr_imag_fmt = 0; if (free_format) return; @@ -389,8 +389,8 @@ static void set_format (const Complex& c, int& r_fw, int& i_fw) { - curr_real_fmt = (char *) NULL; - curr_imag_fmt = (char *) NULL; + curr_real_fmt = 0; + curr_imag_fmt = 0; if (free_format) return; @@ -528,8 +528,8 @@ static void set_format (const ComplexMatrix& cm, int& r_fw, int& i_fw) { - curr_real_fmt = (char *) NULL; - curr_imag_fmt = (char *) NULL; + curr_real_fmt = 0; + curr_imag_fmt = 0; if (free_format) return; @@ -678,8 +678,8 @@ static void set_format (const Range& r, int& fw) { - curr_real_fmt = (char *) NULL; - curr_imag_fmt = (char *) NULL; + curr_real_fmt = 0; + curr_imag_fmt = 0; if (free_format) return; @@ -790,9 +790,7 @@ if (d == -0.0) d = 0.0; - if (fmt == (char *) NULL) - os << d; - else + if (fmt) { if (xisinf (d)) { @@ -817,6 +815,8 @@ else os.form (fmt, d); } + else + os << d; } static inline void @@ -1130,6 +1130,21 @@ } } +DEFUN ("disp", Fdisp, Sdisp, 3, 1, + "disp (X): display value without name tag") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin == 2) + args(1).eval (1); + else + print_usage ("disp"); + + return retval; +} + static void init_format_state (void) { @@ -1143,7 +1158,7 @@ static void set_output_prec_and_fw (int prec, int fw) { - tree_constant *tmp = NULL_TREE_CONST; + tree_constant *tmp = 0; tmp = new tree_constant ((double) prec); bind_builtin_variable ("output_precision", tmp); @@ -1253,6 +1268,22 @@ } } +DEFUN_TEXT ("format", Fformat, Sformat, -1, 1, + "format [style]\n\ +\n\ +set output formatting style") +{ + Octave_object retval; + + DEFINE_ARGV("format"); + + set_format_style (argc, argv); + + DELETE_ARGV; + + return retval; +} + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/src/pt-base.h b/src/pt-base.h --- a/src/pt-base.h +++ b/src/pt-base.h @@ -1,4 +1,4 @@ -// tree.h -*- C++ -*- +// tree-base.h -*- C++ -*- /* Copyright (C) 1992, 1993, 1994 John W. Eaton @@ -24,24 +24,7 @@ #if !defined (octave_tree_base_h) #define octave_tree_base_h 1 -#include -#include -#include - -#ifndef NULL_TREE -#define NULL_TREE (tree *)NULL -#endif - -#ifndef NULL_TREE_CONST -#define NULL_TREE_CONST (tree_constant *)NULL -#endif - -class tree; -class tree_fvc; -class ostream; class tree_constant; -class tree_identifier; -class tree_argument_list; /* * Base class for the parse tree. diff --git a/src/pt-cmd.cc b/src/pt-cmd.cc --- a/src/pt-cmd.cc +++ b/src/pt-cmd.cc @@ -1,4 +1,4 @@ -// Tree class. -*- C++ -*- +// tree-cmd.cc -*- C++ -*- /* Copyright (C) 1992, 1993, 1994 John W. Eaton @@ -31,9 +31,6 @@ #include -// For NULL. -#include - #include "user-prefs.h" #include "variables.h" #include "symtab.h" @@ -102,16 +99,16 @@ */ tree_command_list::tree_command_list (void) { - command = NULL_TREE; + command = 0; print_flag = 1; - next = (tree_command_list *) NULL; + next = 0; } tree_command_list::tree_command_list (tree *t) { command = t; print_flag = 1; - next = (tree_command_list *) NULL; + next = 0; } tree_command_list::~tree_command_list (void) @@ -139,9 +136,9 @@ { tree_command_list *list = this; tree_command_list *next; - tree_command_list *prev = (tree_command_list *) NULL; + tree_command_list *prev = 0; - while (list != (tree_command_list *) NULL) + while (list) { next = list->next; list->next = prev; @@ -160,8 +157,7 @@ if (error_state) return retval; - tree_command_list *list; - for (list = this; list != (tree_command_list *) NULL; list = list->next) + for (tree_command_list *list = this; list; list = list->next) { if (print == 0) pf = 0; @@ -169,7 +165,7 @@ pf = list->print_flag; tree *cmd = list->command; - if (cmd == NULL_TREE) + if (! cmd) retval = tree_constant (); else { @@ -191,34 +187,33 @@ /* * Global. */ -tree_global_command::tree_global_command (int l = -1, int c = -1) +tree_global_command::tree_global_command (int l, int c) { line_num = l; column_num = c; - sr = (symbol_record *) NULL; - rhs = (tree_expression *) NULL; - next = (tree_global_command *) NULL; + sr = 0; + rhs = 0; + next = 0; } -tree_global_command::tree_global_command (symbol_record *s, - int l = -1, int c = -1) +tree_global_command::tree_global_command (symbol_record *s, int l, int c) { line_num = l; column_num = c; sr = s; - rhs = (tree_expression *) NULL; - next = (tree_global_command *) NULL; + rhs = 0; + next = 0; } tree_global_command::tree_global_command (symbol_record *s, tree_expression *e, - int l = -1, int c = -1) + int l, int c) { line_num = l; column_num = c; sr = s; rhs = e; - next = (tree_global_command *) NULL; + next = 0; } tree_global_command::~tree_global_command (void) @@ -227,7 +222,7 @@ } tree_global_command * -tree_global_command::chain (symbol_record *s, int l = -1, int c = -1) +tree_global_command::chain (symbol_record *s, int l, int c) { tree_global_command *tmp = new tree_global_command (s, l, c); tmp->next = this; @@ -236,7 +231,7 @@ tree_global_command * tree_global_command::chain (symbol_record *s, tree_expression *e, - int l = -1, int c = -1) + int l, int c) { tree_global_command *tmp = new tree_global_command (s, e, l, c); tmp->next = this; @@ -248,9 +243,9 @@ { tree_global_command *list = this; tree_global_command *next; - tree_global_command *prev = (tree_global_command *) NULL; + tree_global_command *prev = 0; - while (list != (tree_global_command *) NULL) + while (list) { next = list->next; list->next = prev; @@ -267,7 +262,7 @@ link_to_global_variable (sr); - if (rhs != NULL_TREE) + if (rhs) { tree_identifier *id = new tree_identifier (sr); tree_constant tmp_rhs = rhs->eval (0); @@ -295,7 +290,7 @@ } } - if (next != (tree_global_command *) NULL) + if (next) next->eval (print); return retval; @@ -312,25 +307,24 @@ /* * While. */ -tree_while_command::tree_while_command (int l = -1, int c = -1) +tree_while_command::tree_while_command (int l, int c) { line_num = l; column_num = c; - expr = (tree_expression *) NULL; - list = NULL_TREE; + expr = 0; + list = 0; } -tree_while_command::tree_while_command (tree_expression *e, - int l = -1, int c = -1) +tree_while_command::tree_while_command (tree_expression *e, int l, int c) { line_num = l; column_num = c; expr = e; - list = NULL_TREE; + list = 0; } tree_while_command::tree_while_command (tree_expression *e, tree *lst, - int l = -1, int c = -1) + int l, int c) { line_num = l; column_num = c; @@ -355,7 +349,7 @@ for (;;) { int expr_value = 0; - if (expr == (tree_expression *) NULL) + if (! expr) return tree_constant (); tree_constant t1 = expr->eval (0); @@ -393,7 +387,7 @@ if (expr_value) { - if (list != NULL_TREE) + if (list) { retval = list->eval (1); if (error_state) @@ -423,18 +417,18 @@ /* * For. */ -tree_for_command::tree_for_command (int l = -1, int c = -1) +tree_for_command::tree_for_command (int l, int c) { line_num = l; column_num = c; - id = (tree_index_expression *) NULL; - expr = (tree_expression *) NULL; - list = NULL_TREE; + id = 0; + expr = 0; + list = 0; } tree_for_command::tree_for_command (tree_index_expression *ident, tree_expression *e, tree *lst, - int l = -1, int c = -1) + int l, int c) { line_num = l; column_num = c; @@ -455,7 +449,7 @@ { tree_constant retval; - if (error_state || expr == (tree_expression *) NULL) + if (error_state || ! expr) return retval; tree_constant tmp_expr = expr->eval (0); @@ -580,7 +574,7 @@ return tree_constant (); } - if (list != NULL_TREE) + if (list) { retval = list->eval (1); if (error_state) @@ -599,32 +593,32 @@ /* * If. */ -tree_if_command::tree_if_command (int l = -1, int c = -1) +tree_if_command::tree_if_command (int l, int c) { line_num = l; column_num = c; - expr = (tree_expression *) NULL; - list = NULL_TREE; - next = (tree_if_command *) NULL; + expr = 0; + list = 0; + next = 0; } -tree_if_command::tree_if_command (tree *lst, int l = -1, int c = -1) +tree_if_command::tree_if_command (tree *lst, int l, int c) { line_num = l; column_num = c; - expr = (tree_expression *) NULL; + expr = 0; list = lst; - next = (tree_if_command *) NULL; + next = 0; } tree_if_command::tree_if_command (tree_expression *e, tree *lst, - int l = -1, int c = -1) + int l, int c) { line_num = l; column_num = c; expr = e; list = lst; - next = (tree_if_command *) NULL; + next = 0; } tree_if_command::~tree_if_command (void) @@ -635,7 +629,7 @@ } tree_if_command * -tree_if_command::chain (tree *lst, int l = -1, int c = -1) +tree_if_command::chain (tree *lst, int l, int c) { tree_if_command *tmp = new tree_if_command (lst, l, c); tmp->next = this; @@ -643,7 +637,7 @@ } tree_if_command * -tree_if_command::chain (tree_expression *e, tree *lst, int l = -1, int c = -1) +tree_if_command::chain (tree_expression *e, tree *lst, int l, int c) { tree_if_command *tmp = new tree_if_command (e, lst, l, c); tmp->next = this; @@ -655,9 +649,9 @@ { tree_if_command *list = this; tree_if_command *next; - tree_if_command *prev = (tree_if_command *) NULL; + tree_if_command *prev = 0; - while (list != (tree_if_command *) NULL) + while (list) { next = list->next; list->next = prev; @@ -676,13 +670,13 @@ if (error_state) return retval; - tree_if_command *lst; - for (lst = this; lst != (tree_if_command *) NULL; lst = lst->next) + + for (tree_if_command *lst = this; lst; lst = lst->next) { - if (lst->expr != (tree_expression *) NULL) + if (lst->expr) { tree_expression *tmp = lst->expr; - if (tmp == (tree_expression *) NULL) + if (! tmp) return tree_constant (); tree_constant t1 = tmp->eval (0); if (error_state || t1.is_undefined ()) @@ -720,7 +714,7 @@ if (expr_value) { - if (lst->list != NULL_TREE) + if (lst->list) retval = lst->list->eval (1); else ::error ("if: empty command list"); @@ -733,7 +727,7 @@ } else { - if (lst->list != NULL_TREE) + if (lst->list) retval = lst->list->eval (1); else ::error ("if: empty command list"); @@ -759,7 +753,7 @@ /* * Break. Is this overkill, or what? */ -tree_break_command::tree_break_command (int l = -1, int c = -1) +tree_break_command::tree_break_command (int l, int c) { line_num = l; column_num = c; @@ -780,7 +774,7 @@ /* * Continue. */ -tree_continue_command::tree_continue_command (int l = -1, int c = -1) +tree_continue_command::tree_continue_command (int l, int c) { line_num = l; column_num = c; @@ -801,7 +795,7 @@ /* * Return. */ -tree_return_command::tree_return_command (int l = -1, int c = -1) +tree_return_command::tree_return_command (int l, int c) { line_num = l; column_num = c; diff --git a/src/pt-cmd.h b/src/pt-cmd.h --- a/src/pt-cmd.h +++ b/src/pt-cmd.h @@ -1,4 +1,4 @@ -// Tree classes. -*- C++ -*- +// tree-cmd.h -*- C++ -*- /* Copyright (C) 1992, 1993, 1994 John W. Eaton diff --git a/src/pt-const.cc b/src/pt-const.cc --- a/src/pt-const.cc +++ b/src/pt-const.cc @@ -1,4 +1,4 @@ -// The constants for the tree class. -*- C++ -*- +// tree-const.cc -*- C++ -*- /* Copyright (C) 1992, 1993, 1994 John W. Eaton @@ -29,35 +29,10 @@ #pragma implementation #endif -#include -#include -#include -#include -#include - -#include "EIG.h" - -#include "unwind-prot.h" #include "tree-const.h" -#include "user-prefs.h" -#include "variables.h" -#include "octave.h" #include "error.h" #include "gripes.h" -#include "input.h" -#include "octave-hist.h" -#include "pager.h" -#include "utils.h" -#include "parse.h" -#include "lex.h" - -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif +#include "user-prefs.h" tree_constant::~tree_constant (void) { @@ -110,7 +85,7 @@ Matrix m; retval.resize (nargout ? nargout : 1); for (int i = 0; i < nargout; i++) - retval(i) = tree_constant (m); + retval(i) = m; } else gripe_empty_arg (fcn_name, 1); @@ -118,1375 +93,6 @@ return retval; } -Matrix -max (const Matrix& a, const Matrix& b) -{ - int nr = a.rows (); - int nc = a.columns (); - if (nr != b.rows () || nc != b.columns ()) - { - error ("two-arg max expecting args of same size"); - return Matrix (); - } - - Matrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - { - double a_elem = a.elem (i, j); - double b_elem = b.elem (i, j); - result.elem (i, j) = MAX (a_elem, b_elem); - } - - return result; -} - -ComplexMatrix -max (const ComplexMatrix& a, const ComplexMatrix& b) -{ - int nr = a.rows (); - int nc = a.columns (); - if (nr != b.rows () || nc != b.columns ()) - { - error ("two-arg max expecting args of same size"); - return ComplexMatrix (); - } - - ComplexMatrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - { - double abs_a_elem = abs (a.elem (i, j)); - double abs_b_elem = abs (b.elem (i, j)); - if (abs_a_elem > abs_b_elem) - result.elem (i, j) = a.elem (i, j); - else - result.elem (i, j) = b.elem (i, j); - } - - return result; -} - -Matrix -min (const Matrix& a, const Matrix& b) -{ - int nr = a.rows (); - int nc = a.columns (); - if (nr != b.rows () || nc != b.columns ()) - { - error ("two-arg min expecting args of same size"); - return Matrix (); - } - - Matrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - { - double a_elem = a.elem (i, j); - double b_elem = b.elem (i, j); - result.elem (i, j) = MIN (a_elem, b_elem); - } - - return result; -} - -ComplexMatrix -min (const ComplexMatrix& a, const ComplexMatrix& b) -{ - int nr = a.rows (); - int nc = a.columns (); - if (nr != b.rows () || nc != b.columns ()) - { - error ("two-arg min expecting args of same size"); - return ComplexMatrix (); - } - - ComplexMatrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - { - double abs_a_elem = abs (a.elem (i, j)); - double abs_b_elem = abs (b.elem (i, j)); - if (abs_a_elem < abs_b_elem) - result.elem (i, j) = a.elem (i, j); - else - result.elem (i, j) = b.elem (i, j); - } - - return result; -} - -static void -get_dimensions (const tree_constant& a, const char *warn_for, - int& nr, int& nc) -{ - tree_constant tmpa = a.make_numeric (); - - if (tmpa.is_scalar_type ()) - { - double tmp = tmpa.double_value (); - nr = nc = NINT (tmp); - } - else - { - nr = tmpa.rows (); - nc = tmpa.columns (); - - if ((nr == 1 && nc == 2) || (nr == 2 && nc == 1)) - { - ColumnVector v = tmpa.to_vector (); - - nr = NINT (v.elem (0)); - nc = NINT (v.elem (1)); - } - else - warning ("%s (A): use %s (size (A)) instead", warn_for, warn_for); - } - - check_dimensions (nr, nc, warn_for); // May set error_state. -} - -static void -get_dimensions (const tree_constant& a, const tree_constant& b, - const char *warn_for, int& nr, int& nc) -{ - tree_constant tmpa = a.make_numeric (); - tree_constant tmpb = b.make_numeric (); - - if (tmpa.is_scalar_type () && tmpb.is_scalar_type ()) - { - nr = NINT (tmpa.double_value ()); - nc = NINT (tmpb.double_value ()); - - check_dimensions (nr, nc, warn_for); // May set error_state. - } - else - error ("%s: expecting two scalar arguments", warn_for); -} - -tree_constant -fill_matrix (const tree_constant& a, double val, const char *warn_for) -{ - int nr, nc; - get_dimensions (a, warn_for, nr, nc); - - if (error_state) - return tree_constant (); - - Matrix m (nr, nc, val); - - return tree_constant (m); -} - -tree_constant -fill_matrix (const tree_constant& a, const tree_constant& b, - double val, const char *warn_for) -{ - int nr, nc; - get_dimensions (a, b, warn_for, nr, nc); // May set error_state. - - if (error_state) - return tree_constant (); - - Matrix m (nr, nc, val); - - return tree_constant (m); -} - -tree_constant -identity_matrix (const tree_constant& a) -{ - int nr, nc; - get_dimensions (a, "eye", nr, nc); // May set error_state. - - if (error_state) - return tree_constant (); - - Matrix m (nr, nc, 0.0); - - if (nr > 0 && nc > 0) - { - int n = MIN (nr, nc); - for (int i = 0; i < n; i++) - m.elem (i, i) = 1.0; - } - - return tree_constant (m); -} - -tree_constant -identity_matrix (const tree_constant& a, const tree_constant& b) -{ - int nr, nc; - get_dimensions (a, b, "eye", nr, nc); // May set error_state. - - if (error_state) - return tree_constant (); - - Matrix m (nr, nc, 0.0); - - if (nr > 0 && nc > 0) - { - int n = MIN (nr, nc); - for (int i = 0; i < n; i++) - m.elem (i, i) = 1.0; - } - - return tree_constant (m); -} - -static Octave_object -find_to_fortran_idx (const ColumnVector i_idx, const ColumnVector j_idx, - const tree_constant& val, int nr, int nc, int nargout) -{ - Octave_object retval (nargout); - - switch (nargout) - { - case 1: - { - int count = i_idx.length (); - ColumnVector tmp (count); - for (int i = 0; i < count; i++) - tmp (i) = nr * (j_idx (i) - 1.0) + i_idx (i); - retval(0) = tree_constant (tmp, 1); -// If you want this to work more like Matlab, use the following line -// instead of the previous one. -// retval(0) = tree_constant (tmp, (nr != 1)); - } - break; - case 3: - retval(2) = val; - case 2: - retval(0) = tree_constant (i_idx, 1); -// If you want this to work more like Matlab, use the following line -// instead of the previous one. -// retval(0) = tree_constant (i_idx, (nr != 1)); - retval(1) = tree_constant (j_idx, 1); - break; - default: - panic_impossible (); - break; - } - - return retval; -} - -static Octave_object -find_nonzero_elem_idx (const Matrix& m, int nargout) -{ - int count = 0; - int m_nr = m.rows (); - int m_nc = m.columns (); - - int i, j; - for (j = 0; j < m_nc; j++) - for (i = 0; i < m_nr; i++) - if (m.elem (i, j) != 0.0) - count++; - - Matrix result; - Octave_object retval (nargout, result); - - if (count == 0) - return retval; - - ColumnVector i_idx (count); - ColumnVector j_idx (count); - ColumnVector v (count); - - count = 0; - for (j = 0; j < m_nc; j++) - for (i = 0; i < m_nr; i++) - { - double d = m.elem (i, j); - if (d != 0.0) - { - i_idx (count) = i + 1; - j_idx (count) = j + 1; - v (count) = d; - count++; - } - } - - tree_constant tmp (v, 1); - return find_to_fortran_idx (i_idx, j_idx, tmp, m_nr, m_nc, nargout); -} - -static Octave_object -find_nonzero_elem_idx (const ComplexMatrix& m, int nargout) -{ - int count = 0; - int m_nr = m.rows (); - int m_nc = m.columns (); - - int i, j; - for (j = 0; j < m_nc; j++) - for (i = 0; i < m_nr; i++) - if (m.elem (i, j) != 0.0) - count++; - - Matrix result; - Octave_object retval (nargout, result); - - if (count == 0) - return retval; - - ColumnVector i_idx (count); - ColumnVector j_idx (count); - ComplexColumnVector v (count); - - count = 0; - for (j = 0; j < m_nc; j++) - for (i = 0; i < m_nr; i++) - { - Complex c = m.elem (i, j); - if (c != 0.0) - { - i_idx (count) = i; - j_idx (count) = j; - v (count) = c; - count++; - } - } - - tree_constant tmp (v, 1); - return find_to_fortran_idx (i_idx, j_idx, tmp, m_nr, m_nc, nargout); -} - -Octave_object -find_nonzero_elem_idx (const tree_constant& a, int nargout) -{ - Matrix result; - - nargout = (nargout == 0) ? 1 : nargout; - Octave_object retval (nargout, result); - - tree_constant tmp = a.make_numeric (); - - switch (tmp.const_type ()) - { - case tree_constant_rep::matrix_constant: - { - Matrix m = tmp.matrix_value (); - return find_nonzero_elem_idx (m, nargout); - } - break; - case tree_constant_rep::scalar_constant: - { - double d = tmp.double_value (); - if (d != 0.0) - { - retval(0) = 1.0; - if (nargout > 1) - retval(1) = 1.0; - if (nargout > 2) - retval(2) = d; - } - } - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix m = tmp.complex_matrix_value (); - return find_nonzero_elem_idx (m, nargout); - } - break; - case tree_constant_rep::complex_scalar_constant: - { - Complex c = tmp.complex_value (); - if (c != 0.0) - { - retval(0) = 1.0; - if (nargout > 1) - retval(1) = 1.0; - if (nargout > 2) - retval(2) = c; - } - } - break; - default: - break; - } - return retval; -} - -// XXX FIXME XXX -- the next two functions (and expm) should really be just -// one... - -Octave_object -matrix_log (const tree_constant& a) -{ - Octave_object retval (1); - - tree_constant tmp = a.make_numeric ();; - - if (tmp.rows () == 0 || tmp.columns () == 0) - { - int flag = user_pref.propagate_empty_matrices; - if (flag != 0) - { - if (flag < 0) - gripe_empty_arg ("logm", 0); - Matrix m; - retval(0) = tree_constant (m); - return retval; - } - else - gripe_empty_arg ("logm", 1); - } - - switch (tmp.const_type ()) - { - case tree_constant_rep::matrix_constant: - { - Matrix m = tmp.matrix_value (); - - int nr = m.rows (); - int nc = m.columns (); - - if (nr == 0 || nc == 0 || nr != nc) - gripe_square_matrix_required ("logm"); - else - { - EIG m_eig (m); - ComplexColumnVector lambda (m_eig.eigenvalues ()); - ComplexMatrix Q (m_eig.eigenvectors ()); - - for (int i = 0; i < nr; i++) - { - Complex elt = lambda.elem (i); - if (imag (elt) == 0.0 && real (elt) > 0.0) - lambda.elem (i) = log (real (elt)); - else - lambda.elem (i) = log (elt); - } - - ComplexDiagMatrix D (lambda); - ComplexMatrix result = Q * D * Q.inverse (); - - retval(0) = tree_constant (result); - } - } - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix m = tmp.complex_matrix_value (); - - int nr = m.rows (); - int nc = m.columns (); - - if (nr == 0 || nc == 0 || nr != nc) - gripe_square_matrix_required ("logm"); - else - { - EIG m_eig (m); - ComplexColumnVector lambda (m_eig.eigenvalues ()); - ComplexMatrix Q (m_eig.eigenvectors ()); - - for (int i = 0; i < nr; i++) - { - Complex elt = lambda.elem (i); - if (imag (elt) == 0.0 && real (elt) > 0.0) - lambda.elem (i) = log (real (elt)); - else - lambda.elem (i) = log (elt); - } - - ComplexDiagMatrix D (lambda); - ComplexMatrix result = Q * D * Q.inverse (); - - retval(0) = tree_constant (result); - } - } - break; - case tree_constant_rep::scalar_constant: - { - double d = tmp.double_value (); - if (d > 0.0) - retval(0) = tree_constant (log (d)); - else - { - Complex dtmp (d); - retval(0) = tree_constant (log (dtmp)); - } - } - break; - case tree_constant_rep::complex_scalar_constant: - { - Complex c = tmp.complex_value (); - retval(0) = tree_constant (log (c)); - } - break; - default: - break; - } - return retval; -} - -Octave_object -matrix_sqrt (const tree_constant& a) -{ - Octave_object retval (1); - - tree_constant tmp = a.make_numeric ();; - - if (tmp.rows () == 0 || tmp.columns () == 0) - { - int flag = user_pref.propagate_empty_matrices; - if (flag != 0) - { - if (flag < 0) - gripe_empty_arg ("sqrtm", 0); - Matrix m; - retval(0) = tree_constant (m); - return retval; - } - else - gripe_empty_arg ("sqrtm", 1); - } - - switch (tmp.const_type ()) - { - case tree_constant_rep::matrix_constant: - { - Matrix m = tmp.matrix_value (); - - int nr = m.rows (); - int nc = m.columns (); - - if (nr == 0 || nc == 0 || nr != nc) - gripe_square_matrix_required ("sqrtm"); - else - { - EIG m_eig (m); - ComplexColumnVector lambda (m_eig.eigenvalues ()); - ComplexMatrix Q (m_eig.eigenvectors ()); - - for (int i = 0; i < nr; i++) - { - Complex elt = lambda.elem (i); - if (imag (elt) == 0.0 && real (elt) > 0.0) - lambda.elem (i) = sqrt (real (elt)); - else - lambda.elem (i) = sqrt (elt); - } - - ComplexDiagMatrix D (lambda); - ComplexMatrix result = Q * D * Q.inverse (); - - retval(0) = tree_constant (result); - } - } - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix m = tmp.complex_matrix_value (); - - int nr = m.rows (); - int nc = m.columns (); - - if (nr == 0 || nc == 0 || nr != nc) - gripe_square_matrix_required ("sqrtm"); - else - { - EIG m_eig (m); - ComplexColumnVector lambda (m_eig.eigenvalues ()); - ComplexMatrix Q (m_eig.eigenvectors ()); - - for (int i = 0; i < nr; i++) - { - Complex elt = lambda.elem (i); - if (imag (elt) == 0.0 && real (elt) > 0.0) - lambda.elem (i) = sqrt (real (elt)); - else - lambda.elem (i) = sqrt (elt); - } - - ComplexDiagMatrix D (lambda); - ComplexMatrix result = Q * D * Q.inverse (); - - retval(0) = tree_constant (result); - } - } - break; - case tree_constant_rep::scalar_constant: - { - double d = tmp.double_value (); - if (d > 0.0) - retval(0) = tree_constant (sqrt (d)); - else - { - Complex dtmp (d); - retval(0) = tree_constant (sqrt (dtmp)); - } - } - break; - case tree_constant_rep::complex_scalar_constant: - { - Complex c = tmp.complex_value (); - retval(0) = tree_constant (log (c)); - } - break; - default: - break; - } - return retval; -} - -Octave_object -column_max (const Octave_object& args, int nargout) -{ - Octave_object retval; - - tree_constant arg1; - tree_constant arg2; - tree_constant_rep::constant_type arg1_type = - tree_constant_rep::unknown_constant; - tree_constant_rep::constant_type arg2_type = - tree_constant_rep::unknown_constant; - - int nargin = args.length (); - - switch (nargin) - { - case 3: - arg2 = args(2).make_numeric (); - arg2_type = arg2.const_type (); -// Fall through... - case 2: - arg1 = args(1).make_numeric (); - arg1_type = arg1.const_type (); - break; - default: - panic_impossible (); - break; - } - - if (nargin == 2 && (nargout == 1 || nargout == 0)) - { - retval.resize (1); - switch (arg1_type) - { - case tree_constant_rep::scalar_constant: - retval(0) = tree_constant (arg1.double_value ()); - break; - case tree_constant_rep::complex_scalar_constant: - retval(0) = tree_constant (arg1.complex_value ()); - break; - case tree_constant_rep::matrix_constant: - { - Matrix m = arg1.matrix_value (); - if (m.rows () == 1) - retval(0) = tree_constant (m.row_max ()); - else - retval(0) = tree_constant (m.column_max (), 0); - } - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix m = arg1.complex_matrix_value (); - if (m.rows () == 1) - retval(0) = tree_constant (m.row_max ()); - else - retval(0) = tree_constant (m.column_max (), 0); - } - break; - default: - panic_impossible (); - break; - } - } - else if (nargin == 2 && nargout == 2) - { - retval.resize (2); - switch (arg1_type) - { - case tree_constant_rep::scalar_constant: - { - retval(0) = tree_constant (arg1.double_value ()); - retval(1) = tree_constant (1); - } - break; - case tree_constant_rep::complex_scalar_constant: - { - retval(0) = tree_constant (arg1.complex_value ()); - retval(1) = tree_constant (1); - } - break; - case tree_constant_rep::matrix_constant: - { - Matrix m = arg1.matrix_value (); - if (m.rows () == 1) - { - retval(0) = tree_constant (m.row_max ()); - retval(1) = tree_constant (m.row_max_loc ()); - } - else - { - retval(0) = tree_constant (m.column_max (), 0); - retval(1) = tree_constant (m.column_max_loc (), 0); - } - } - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix m = arg1.complex_matrix_value (); - if (m.rows () == 1) - { - retval(0) = tree_constant (m.row_max ()); - retval(1) = tree_constant (m.row_max_loc ()); - } - else - { - retval(0) = tree_constant (m.column_max (), 0); - retval(1) = tree_constant (m.column_max_loc (), 0); - } - } - break; - default: - panic_impossible (); - break; - } - } - else if (nargin == 3) - { - if (arg1.rows () == arg2.rows () - && arg1.columns () == arg2.columns ()) - { - retval.resize (1); - switch (arg1_type) - { - case tree_constant_rep::scalar_constant: - { - double result; - double a_elem = arg1.double_value (); - double b_elem = arg2.double_value (); - result = MAX (a_elem, b_elem); - retval(0) = tree_constant (result); - } - break; - case tree_constant_rep::complex_scalar_constant: - { - Complex result; - Complex a_elem = arg1.complex_value (); - Complex b_elem = arg2.complex_value (); - if (abs (a_elem) > abs (b_elem)) - result = a_elem; - else - result = b_elem; - retval(0) = tree_constant (result); - } - break; - case tree_constant_rep::matrix_constant: - { - Matrix result; - result = max (arg1.matrix_value (), arg2.matrix_value ()); - retval(0) = tree_constant (result); - } - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix result; - result = max (arg1.complex_matrix_value (), - arg2.complex_matrix_value ()); - retval(0) = tree_constant (result); - } - break; - default: - panic_impossible (); - break; - } - } - else - error ("max: nonconformant matrices"); - } - else - panic_impossible (); - - return retval; -} - -Octave_object -column_min (const Octave_object& args, int nargout) -{ - Octave_object retval; - - tree_constant arg1; - tree_constant arg2; - tree_constant_rep::constant_type arg1_type = - tree_constant_rep::unknown_constant; - tree_constant_rep::constant_type arg2_type = - tree_constant_rep::unknown_constant; - - int nargin = args.length (); - - switch (nargin) - { - case 3: - arg2 = args(2).make_numeric (); - arg2_type = arg2.const_type (); -// Fall through... - case 2: - arg1 = args(1).make_numeric (); - arg1_type = arg1.const_type (); - break; - default: - panic_impossible (); - break; - } - - if (nargin == 2 && (nargout == 1 || nargout == 0)) - { - retval.resize (1); - switch (arg1_type) - { - case tree_constant_rep::scalar_constant: - retval(0) = tree_constant (arg1.double_value ()); - break; - case tree_constant_rep::complex_scalar_constant: - retval(0) = tree_constant (arg1.complex_value ()); - break; - case tree_constant_rep::matrix_constant: - { - Matrix m = arg1.matrix_value (); - if (m.rows () == 1) - retval(0) = tree_constant (m.row_min ()); - else - retval(0) = tree_constant (m.column_min (), 0); - } - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix m = arg1.complex_matrix_value (); - if (m.rows () == 1) - retval(0) = tree_constant (m.row_min ()); - else - retval(0) = tree_constant (m.column_min (), 0); - } - break; - default: - panic_impossible (); - break; - } - } - else if (nargin == 2 && nargout == 2) - { - retval.resize (2); - switch (arg1_type) - { - case tree_constant_rep::scalar_constant: - { - retval(0) = tree_constant (arg1.double_value ()); - retval(1) = tree_constant (1); - } - break; - case tree_constant_rep::complex_scalar_constant: - { - retval(0) = tree_constant (arg1.complex_value ()); - retval(1) = tree_constant (1); - } - break; - case tree_constant_rep::matrix_constant: - { - Matrix m = arg1.matrix_value (); - if (m.rows () == 1) - { - retval(0) = tree_constant (m.row_min ()); - retval(1) = tree_constant (m.row_min_loc ()); - } - else - { - retval(0) = tree_constant (m.column_min (), 0); - retval(1) = tree_constant (m.column_min_loc (), 0); - } - } - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix m = arg1.complex_matrix_value (); - if (m.rows () == 1) - { - retval(0) = tree_constant (m.row_min ()); - retval(1) = tree_constant (m.row_min_loc ()); - } - else - { - retval(0) = tree_constant (m.column_min (), 0); - retval(1) = tree_constant (m.column_min_loc (), 0); - } - } - break; - default: - panic_impossible (); - break; - } - } - else if (nargin == 3) - { - if (arg1.rows () == arg2.rows () - && arg1.columns () == arg2.columns ()) - { - retval.resize (1); - switch (arg1_type) - { - case tree_constant_rep::scalar_constant: - { - double result; - double a_elem = arg1.double_value (); - double b_elem = arg2.double_value (); - result = MIN (a_elem, b_elem); - retval(0) = tree_constant (result); - } - break; - case tree_constant_rep::complex_scalar_constant: - { - Complex result; - Complex a_elem = arg1.complex_value (); - Complex b_elem = arg2.complex_value (); - if (abs (a_elem) < abs (b_elem)) - result = a_elem; - else - result = b_elem; - retval(0) = tree_constant (result); - } - break; - case tree_constant_rep::matrix_constant: - { - Matrix result; - result = min (arg1.matrix_value (), arg2.matrix_value ()); - retval(0) = tree_constant (result); - } - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix result; - result = min (arg1.complex_matrix_value (), - arg2.complex_matrix_value ()); - retval(0) = tree_constant (result); - } - break; - default: - panic_impossible (); - break; - } - } - else - error ("min: nonconformant matrices"); - } - else - panic_impossible (); - - return retval; -} - -static void -mx_sort (Matrix& m, Matrix& idx, int return_idx) -{ - int nr = m.rows (); - int nc = m.columns (); - idx.resize (nr, nc); - int i, j; - - if (return_idx) - { - for (j = 0; j < nc; j++) - for (i = 0; i < nr; i++) - idx.elem (i, j) = i+1; - } - - for (j = 0; j < nc; j++) - { - for (int gap = nr/2; gap > 0; gap /= 2) - for (i = gap; i < nr; i++) - for (int k = i - gap; - k >= 0 && m.elem (k, j) > m.elem (k+gap, j); - k -= gap) - { - double tmp = m.elem (k, j); - m.elem (k, j) = m.elem (k+gap, j); - m.elem (k+gap, j) = tmp; - - if (return_idx) - { - double tmp = idx.elem (k, j); - idx.elem (k, j) = idx.elem (k+gap, j); - idx.elem (k+gap, j) = tmp; - } - } - } -} - -static void -mx_sort (RowVector& v, RowVector& idx, int return_idx) -{ - int n = v.capacity (); - idx.resize (n); - int i; - - if (return_idx) - for (i = 0; i < n; i++) - idx.elem (i) = i+1; - - for (int gap = n/2; gap > 0; gap /= 2) - for (i = gap; i < n; i++) - for (int k = i - gap; - k >= 0 && v.elem (k) > v.elem (k+gap); - k -= gap) - { - double tmp = v.elem (k); - v.elem (k) = v.elem (k+gap); - v.elem (k+gap) = tmp; - - if (return_idx) - { - double tmp = idx.elem (k); - idx.elem (k) = idx.elem (k+gap); - idx.elem (k+gap) = tmp; - } - } -} - -static void -mx_sort (ComplexMatrix& cm, Matrix& idx, int return_idx) -{ - int nr = cm.rows (); - int nc = cm.columns (); - idx.resize (nr, nc); - int i, j; - - if (return_idx) - { - for (j = 0; j < nc; j++) - for (i = 0; i < nr; i++) - idx.elem (i, j) = i+1; - } - - for (j = 0; j < nc; j++) - { - for (int gap = nr/2; gap > 0; gap /= 2) - for (i = gap; i < nr; i++) - for (int k = i - gap; - k >= 0 && abs (cm.elem (k, j)) > abs (cm.elem (k+gap, j)); - k -= gap) - { - Complex ctmp = cm.elem (k, j); - cm.elem (k, j) = cm.elem (k+gap, j); - cm.elem (k+gap, j) = ctmp; - - if (return_idx) - { - double tmp = idx.elem (k, j); - idx.elem (k, j) = idx.elem (k+gap, j); - idx.elem (k+gap, j) = tmp; - } - } - } -} - -static void -mx_sort (ComplexRowVector& cv, RowVector& idx, int return_idx) -{ - int n = cv.capacity (); - idx.resize (n); - int i; - - if (return_idx) - for (i = 0; i < n; i++) - idx.elem (i) = i+1; - - for (int gap = n/2; gap > 0; gap /= 2) - for (i = gap; i < n; i++) - for (int k = i - gap; - k >= 0 && abs (cv.elem (k)) > abs (cv.elem (k+gap)); - k -= gap) - { - Complex tmp = cv.elem (k); - cv.elem (k) = cv.elem (k+gap); - cv.elem (k+gap) = tmp; - - if (return_idx) - { - double tmp = idx.elem (k); - idx.elem (k) = idx.elem (k+gap); - idx.elem (k+gap) = tmp; - } - } -} - -Octave_object -sort (const Octave_object& args, int nargout) -{ -// Assumes that we have been given the correct number of arguments. - - Octave_object retval; - - int return_idx = nargout > 1; - if (return_idx) - retval.resize (2); - else - retval.resize (1); - - switch (args(1).const_type ()) - { - case tree_constant_rep::scalar_constant: - { - retval(0) = tree_constant (args(1).double_value ()); - if (return_idx) - retval(1) = tree_constant (1.0); - } - break; - case tree_constant_rep::complex_scalar_constant: - { - retval(0) = tree_constant (args(1).complex_value ()); - if (return_idx) - retval(1) = tree_constant (1.0); - } - break; - case tree_constant_rep::string_constant: - case tree_constant_rep::range_constant: - case tree_constant_rep::matrix_constant: - { - Matrix m = args(1).to_matrix (); - if (m.rows () == 1) - { - int nc = m.columns (); - RowVector v (nc); - for (int i = 0; i < nc; i++) - v.elem (i) = m.elem (0, i); - RowVector idx; - mx_sort (v, idx, return_idx); - - retval(0) = tree_constant (v, 0); - if (return_idx) - retval(1) = tree_constant (idx, 0); - } - else - { -// Sorts m in place, optionally computes index Matrix. - Matrix idx; - mx_sort (m, idx, return_idx); - - retval(0) = tree_constant (m); - if (return_idx) - retval(1) = tree_constant (idx); - } - } - break; - case tree_constant_rep::complex_matrix_constant: - { - ComplexMatrix cm = args(1).complex_matrix_value (); - if (cm.rows () == 1) - { - int nc = cm.columns (); - ComplexRowVector cv (nc); - for (int i = 0; i < nc; i++) - cv.elem (i) = cm.elem (0, i); - RowVector idx; - mx_sort (cv, idx, return_idx); - - retval(0) = tree_constant (cv, 0); - if (return_idx) - retval(1) = tree_constant (idx, 0); - } - else - { -// Sorts cm in place, optionally computes index Matrix. - Matrix idx; - mx_sort (cm, idx, return_idx); - - retval(0) = tree_constant (cm); - if (return_idx) - retval(1) = tree_constant (idx); - } - } - break; - default: - panic_impossible (); - break; - } - - return retval; -} - -Octave_object -feval (const Octave_object& args, int nargout) -{ -// Assumes that we have been given the correct number of arguments. - - Octave_object retval; - - tree_fvc *fcn = is_valid_function (args(1), "feval", 1); - if (fcn != (tree_fvc *) NULL) - { - int nargin = args.length () - 1; - Octave_object tmp_args (nargin); - for (int i = 0; i < nargin; i++) - tmp_args(i) = args(i+1); - retval = fcn->eval (0, nargout, tmp_args); - } - - return retval; -} - -tree_constant -eval_string (const char *string, int print, int ans_assign, - int& parse_status) -{ - begin_unwind_frame ("eval_string"); - - unwind_protect_int (get_input_from_eval_string); - unwind_protect_ptr (global_command); - unwind_protect_ptr (current_eval_string); - - get_input_from_eval_string = 1; - current_eval_string = string; - - YY_BUFFER_STATE old_buf = current_buffer (); - YY_BUFFER_STATE new_buf = create_buffer ((FILE *) NULL); - - 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 (); - - parse_status = yyparse (); - -// Important to reset the idea of where input is coming from before -// trying to eval the command we just parsed -- it might contain the -// name of an function file that still needs to be parsed! - - tree *command = global_command; - - run_unwind_frame ("eval_string"); - - tree_constant retval; - - if (parse_status == 0 && command != NULL_TREE) - { - retval = command->eval (print); - delete command; - } - - return retval; -} - -tree_constant -eval_string (const tree_constant& arg, int& parse_status) -{ - if (! arg.is_string_type ()) - { - error ("eval: expecting string argument"); - return -1; - } - - char *string = arg.string_value (); - -// Yes Virginia, we always print here... - - return eval_string (string, 1, 1, parse_status); -} - -static int -match_sans_spaces (const char *standard, const char *test) -{ - const char *tp = test; - while (*tp == ' ' || *tp == '\t') - tp++; - - const char *ep = test + strlen (test) - 1; - while (*ep == ' ' || *ep == '\t') - ep--; - - int len = ep - tp + 1; - - return (strncmp (standard, tp, len) == 0); -} - -tree_constant -get_user_input (const Octave_object& args, int nargout, int debug = 0) -{ - tree_constant retval; - - int nargin = args.length (); - - int read_as_string = 0; - - if (nargin == 3) - { - if (args(2).is_string_type () - && strcmp ("s", args(2).string_value ()) == 0) - read_as_string++; - else - { - error ("input: unrecognized second argument"); - return retval; - } - } - - char *prompt = "debug> "; - if (nargin > 1) - { - if (args(1).is_string_type ()) - prompt = args(1).string_value (); - else - { - error ("input: unrecognized argument"); - return retval; - } - } - - again: - - flush_output_to_pager (); - - char *input_buf = gnu_readline (prompt); - - if (input_buf != (char *) NULL) - { - if (input_buf) - maybe_save_history (input_buf); - - int len = strlen (input_buf); - - if (len < 1) - { - if (debug) - goto again; - else - return retval; - } - - if (match_sans_spaces ("exit", input_buf) - || match_sans_spaces ("quit", input_buf) - || match_sans_spaces ("return", input_buf)) - return tree_constant (); - else if (read_as_string) - retval = tree_constant (input_buf); - else - { - int parse_status; - retval = eval_string (input_buf, 0, 0, parse_status); - if (debug && retval.is_defined ()) - retval.eval (1); - } - } - else - error ("input: reading user-input failed!"); - - if (debug) - goto again; - - return retval; -} - /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/src/pt-const.h b/src/pt-const.h --- a/src/pt-const.h +++ b/src/pt-const.h @@ -1,4 +1,4 @@ -// The rest of the tree classes. -*- C++ -*- +// tree-const.h -*- C++ -*- /* Copyright (C) 1992, 1993, 1994 John W. Eaton @@ -33,7 +33,6 @@ #include "mx-base.h" #include "Range.h" -#include "builtins.h" #include "tree-base.h" #include "tree-expr.h" #include "tc-rep.h" @@ -41,6 +40,8 @@ class idx_vector; +struct Mapper_fcn; + /* * Constants. */ @@ -98,7 +99,7 @@ void operator delete (void *p, size_t size); #endif - tree_constant operator = (tree_constant& a) + tree_constant operator = (const tree_constant& a) { if (--rep->count <= 0 && rep != a.rep) delete rep; @@ -286,42 +287,10 @@ tree_constant_rep *rep; }; -/* - * Here are some extra functions that are related to the tree_constant - * class but that don't need to be class members or friends. - */ - +// XXX FIXME XXX -- this is not used very much now. Perhaps it can be +// eliminated. extern Octave_object vector_of_empties (int nargout, const char *fcn_name); -extern tree_constant fill_matrix (const tree_constant& a, - double d, const char *warn_for); -extern tree_constant fill_matrix (const tree_constant& a, - const tree_constant& b, - double d, const char *warn_for); - -extern tree_constant identity_matrix (const tree_constant& a); -extern tree_constant identity_matrix (const tree_constant& a, - const tree_constant& b); - -extern Octave_object find_nonzero_elem_idx (const tree_constant& a, - int nargout); - -extern Octave_object matrix_log (const tree_constant& a); -extern Octave_object matrix_sqrt (const tree_constant& a); - -extern Octave_object column_max (const Octave_object& args, int nargout); -extern Octave_object column_min (const Octave_object& args, int nargout); - -extern Octave_object sort (const Octave_object& args, int nargout); - -extern Octave_object feval (const Octave_object& args, int nargout); - -extern tree_constant eval_string (const tree_constant& arg, int& - parse_status); - -extern tree_constant get_user_input (const Octave_object& args, - int nargout, int debug = 0); - #endif /* diff --git a/src/pt-exp-base.cc b/src/pt-exp-base.cc --- a/src/pt-exp-base.cc +++ b/src/pt-exp-base.cc @@ -1,4 +1,4 @@ -// Tree class. -*- C++ -*- +// tree-expr.cc -*- C++ -*- /* Copyright (C) 1992, 1993, 1994 John W. Eaton @@ -55,6 +55,7 @@ #include "unwind-prot.h" #include "parse.h" #include "lex.h" +#include "defun.h" extern "C" { @@ -148,15 +149,15 @@ tree_matrix::tree_matrix (void) { dir = tree::md_none; - element = (tree_expression *) NULL; - next = (tree_matrix *) NULL; + element = 0; + next = 0; } tree_matrix::tree_matrix (tree_expression *e, tree::matrix_dir d) { dir = d; element = e; - next = (tree_matrix *) NULL; + next = 0; } tree_matrix::~tree_matrix (void) @@ -178,9 +179,9 @@ { tree_matrix *list = this; tree_matrix *next; - tree_matrix *prev = (tree_matrix *) NULL; - - while (list != (tree_matrix *) NULL) + tree_matrix *prev = 0; + + while (list) { next = list->next; list->next = prev; @@ -195,7 +196,7 @@ { tree_matrix *list = this; int len = 0; - while (list != (tree_matrix *) NULL) + while (list) { len++; list = list->next; @@ -206,9 +207,9 @@ tree_return_list * tree_matrix::to_return_list (void) { - tree_return_list *retval = (tree_return_list *) NULL; + tree_return_list *retval = 0; tree_matrix *list; - for (list = this; list != (tree_matrix *) NULL; list = list->next) + for (list = this; list; list = list->next) { tree_expression *elem = list->element; if (elem->is_identifier ()) @@ -232,12 +233,12 @@ else { delete retval; - retval = (tree_return_list *) NULL; + retval = 0; break; } } - if (retval != (tree_return_list *) NULL) + if (retval) retval = retval->reverse (); return retval; } @@ -302,8 +303,8 @@ Matrix m; ComplexMatrix cm; - char *string = (char *) NULL; - char *str_ptr = (char *) NULL; + char *string = 0; + char *str_ptr = 0; // Eliminate empties and gather stats. @@ -313,7 +314,7 @@ for (int i = 0; i < total_len; i++) { tree_expression *elem = ptr->element; - if (elem == (tree_expression *) NULL) + if (! elem) { retval = tree_constant (Matrix ()); goto done; @@ -494,7 +495,7 @@ cm (put_row, put_col) = tmp.double_value (); break; case tree_constant_rep::string_constant: - if (all_strings && str_ptr != (char *) NULL) + if (all_strings && str_ptr) { memcpy (str_ptr, tmp.string_value (), nc); str_ptr += nc; @@ -532,7 +533,7 @@ m (put_row, put_col) = tmp.double_value (); break; case tree_constant_rep::string_constant: - if (all_strings && str_ptr != (char *) NULL) + if (all_strings && str_ptr) { memcpy (str_ptr, tmp.string_value (), nc); str_ptr += nc; @@ -563,7 +564,7 @@ prev_nc = nc; } - if (all_strings && string != (char *) NULL) + if (all_strings && string) retval = tree_constant (string); else if (found_complex) retval = tree_constant (cm); @@ -586,47 +587,36 @@ /* * Builtin functions. */ -tree_builtin::tree_builtin (const char *nm = (char *) NULL) +tree_builtin::tree_builtin (const char *nm) { nargin_max = -1; nargout_max = -1; - text_fcn = (Text_fcn) NULL; - general_fcn = (General_fcn) NULL; - if (nm != (char *) NULL) + 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 = (char *) NULL) + const char *nm) { nargin_max = i_max; nargout_max = o_max; mapper_fcn = m_fcn; - text_fcn = (Text_fcn) NULL; - general_fcn = (General_fcn) NULL; - if (nm != (char *) NULL) + is_mapper = 1; + fcn = 0; + if (nm) my_name = strsave (nm); } -tree_builtin::tree_builtin (int i_max, int o_max, Text_fcn t_fcn, - const char *nm = (char *) NULL) +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; - text_fcn = t_fcn; - general_fcn = (General_fcn) NULL; - if (nm != (char *) NULL) - my_name = strsave (nm); -} - -tree_builtin::tree_builtin (int i_max, int o_max, General_fcn g_fcn, - const char *nm = (char *) NULL) -{ - nargin_max = i_max; - nargout_max = o_max; - text_fcn = (Text_fcn) NULL; - general_fcn = g_fcn; - if (nm != (char *) NULL) + is_mapper = 0; + fcn = g_fcn; + if (nm) my_name = strsave (nm); } @@ -642,6 +632,12 @@ } #endif +int +tree_builtin::is_mapper_function (void) const +{ + return is_mapper; +} + tree_constant tree_builtin::eval (int print) { @@ -650,20 +646,11 @@ if (error_state) return retval; - if (text_fcn != (Text_fcn) NULL) - { - char **argv = new char * [1]; - argv[0] = strsave (my_name); - Octave_object tmp = (*text_fcn) (1, argv, 1); - if (tmp.length () > 0) - retval = tmp(0); - delete [] argv; - } - else if (general_fcn != (General_fcn) NULL) + if (fcn) { Octave_object args (1); args(0) = tree_constant (my_name); - Octave_object tmp = (*general_fcn) (args, 1); + Octave_object tmp = (*fcn) (args, 1); if (tmp.length () > 0) retval = tmp(0); } @@ -683,31 +670,14 @@ int nargin = args.length (); - if (text_fcn != (Text_fcn) NULL) - { -// XXX FIXME XXX -- what if some arg is not a string? - - int argc = nargin; - char **argv = new char * [argc + 1]; - argv[0] = strsave (my_name); - for (int i = 1; i < argc; i++) - argv[i] = strsave (args(i).string_value ()); - argv[argc] = (char *) NULL; - - retval = (*text_fcn) (argc, argv, nargout); - - for (i = 0; i < argc; i++) - delete [] argv[i]; - delete [] argv; - } - else if (general_fcn != (General_fcn) NULL) + if (fcn) { if (any_arg_is_magic_colon (args)) ::error ("invalid use of colon in function argument list"); else - retval = (*general_fcn) (args, nargout); + retval = (*fcn) (args, nargout); } - else + else if (is_mapper) { if (nargin > nargin_max) ::error ("%s: too many arguments", my_name); @@ -718,6 +688,8 @@ retval(0) = tmp; } } + else + panic_impossible (); return retval; } @@ -742,15 +714,15 @@ /* * Symbols from the symbol table. */ -tree_identifier::tree_identifier (int l = -1, int c = -1) +tree_identifier::tree_identifier (int l, int c) { - sym = (symbol_record *) NULL; + sym = 0; line_num = l; column_num = c; maybe_do_ans_assign = 0; } -tree_identifier::tree_identifier (symbol_record *s, int l = -1, int c = -1) +tree_identifier::tree_identifier (symbol_record *s, int l, int c) { sym = s; line_num = l; @@ -787,7 +759,7 @@ if (status) return this; else - return (tree_identifier *) NULL; + return 0; } tree_identifier * @@ -797,13 +769,13 @@ if (status) return this; else - return (tree_identifier *) NULL; + return 0; } void tree_identifier::document (char *s) { - if (sym != (symbol_record *) NULL && s != (char *) NULL) + if (sym && s) { char *tmp = strsave (s); sym->document (tmp); @@ -889,22 +861,22 @@ int tree_identifier::is_defined (void) { - return (sym != (symbol_record *) NULL && sym->is_defined ()); + return (sym && sym->is_defined ()); } void tree_identifier::bump_value (tree::expression_type etype) { - if (sym != (symbol_record *) NULL) + if (sym) { tree_fvc *tmp = sym->def (); - if (tmp != NULL_TREE) + if (tmp) tmp->bump_value (etype); } } int -tree_identifier::parse_fcn_file (int exec_script = 1) +tree_identifier::parse_fcn_file (int exec_script) { curr_fcn_file_name = name (); char *ff = fcn_file_in_path (curr_fcn_file_name); @@ -966,13 +938,13 @@ } int -tree_identifier::parse_fcn_file (char *ff, int exec_script = 1) +tree_identifier::parse_fcn_file (char *ff, int exec_script) { begin_unwind_frame ("parse_fcn_file"); int script_file_executed = 0; - if (ff != (char *) NULL) + if (ff) { // Open function file and parse. @@ -993,7 +965,7 @@ FILE *ffile = get_input_from_file (ff, 0); - if (ffile != (FILE *) NULL) + if (ffile) { // Check to see if this file defines a function or is just a list of // commands. @@ -1114,7 +1086,7 @@ } } - tree_fvc *ans = (tree_fvc *) NULL; + tree_fvc *ans = 0; if (! script_file_executed) ans = sym->def (); @@ -1125,7 +1097,7 @@ void tree_identifier::mark_as_formal_parameter (void) { - if (sym != (symbol_record *) NULL) + if (sym) sym->mark_as_formal_parameter (); } @@ -1149,9 +1121,7 @@ if (! script_file_executed) { - if (ans == (tree_fvc *) NULL) - eval_undefined_error (); - else + if (ans) { int nargout = maybe_do_ans_assign ? 0 : 1; @@ -1162,6 +1132,8 @@ if (tmp.length () > 0) retval = tmp(0); } + else + eval_undefined_error (); } if (! error_state && retval.is_defined ()) @@ -1170,8 +1142,8 @@ { symbol_record *sr = global_sym_tab->lookup ("ans", 1, 0); - assert (sr != (symbol_record *) NULL); - + assert (sr); + tree_identifier *ans_id = new tree_identifier (sr); tree_constant *tmp = new tree_constant (retval); @@ -1234,9 +1206,7 @@ if (! script_file_executed) { - if (ans == (tree_fvc *) NULL) - eval_undefined_error (); - else + if (ans) { if (maybe_do_ans_assign && nargout == 1) { @@ -1251,7 +1221,7 @@ { symbol_record *sr = global_sym_tab->lookup ("ans", 1, 0); - assert (sr != (symbol_record *) NULL); + assert (sr); tree_identifier *ans_id = new tree_identifier (sr); @@ -1267,6 +1237,8 @@ else retval = ans->eval (print, nargout, args); } + else + eval_undefined_error (); } return retval; @@ -1278,12 +1250,12 @@ tree_function::tree_function (void) { call_depth = 0; - param_list = (tree_parameter_list *) NULL; - ret_list = (tree_parameter_list *) NULL; - sym_tab = (symbol_table *) NULL; - cmd_list = NULL_TREE; - file_name = (char *) NULL; - fcn_name = (char *) NULL; + param_list = 0; + ret_list = 0; + sym_tab = 0; + cmd_list = 0; + file_name = 0; + fcn_name = 0; t_parsed = 0; system_fcn_file = 0; num_named_args = 0; @@ -1294,12 +1266,12 @@ tree_function::tree_function (tree *cl, symbol_table *st) { call_depth = 0; - param_list = (tree_parameter_list *) NULL; - ret_list = (tree_parameter_list *) NULL; + param_list = 0; + ret_list = 0; sym_tab = st; cmd_list = cl; - file_name = (char *) NULL; - fcn_name = (char *) NULL; + file_name = 0; + fcn_name = 0; t_parsed = 0; system_fcn_file = 0; num_named_args = 0; @@ -1323,7 +1295,7 @@ { param_list = t; - if (param_list != (tree_parameter_list *) NULL) + if (param_list) { int len = param_list->length (); int va_only = param_list->varargs_only (); @@ -1369,7 +1341,7 @@ void tree_function::mark_as_system_fcn_file (void) { - if (file_name != (char *) NULL) + if (file_name) { // We really should stash the whole path to the file we found, when we // looked it up, to avoid possible race conditions... XXX FIXME XXX @@ -1401,8 +1373,7 @@ int tree_function::takes_varargs (void) const { - return (param_list != (tree_parameter_list *) NULL - && param_list->takes_varargs ()); + return (param_list && param_list->takes_varargs ()); } void @@ -1443,7 +1414,7 @@ { tree_constant retval; - if (error_state || cmd_list == NULL_TREE) + if (error_state || ! cmd_list) return retval; Octave_object tmp_args (1); @@ -1479,7 +1450,7 @@ if (error_state) return retval; - if (cmd_list == NULL_TREE) + if (! cmd_list) return retval; int nargin = args.length (); @@ -1516,8 +1487,7 @@ unwind_protect_int (num_named_args); unwind_protect_int (curr_va_arg_number); - if (param_list != (tree_parameter_list *) NULL - && ! param_list->varargs_only ()) + if (param_list && ! param_list->varargs_only ()) { param_list->define_from_arg_vector (args); if (error_state) @@ -1549,7 +1519,7 @@ // Copy return values out. - if (ret_list != (tree_parameter_list *) NULL) + if (ret_list) { retval = ret_list->convert_to_const_vector (); } @@ -1569,7 +1539,7 @@ int tree_function::max_expected_args (void) { - if (param_list != NULL_TREE) + if (param_list) { if (param_list->takes_varargs ()) return -1; @@ -1586,22 +1556,80 @@ if (error_state >= 0) error_state = -1; - if (fcn_name != (char *) NULL) + if (fcn_name) { - if (file_name != (char *) NULL) + if (file_name) ::error ("called from `%s' in file `%s'", fcn_name, file_name); else ::error ("called from `%s'", fcn_name); } else { - if (file_name != (char *) NULL) + if (file_name) ::error ("called from file `%s'", file_name); else ::error ("called from `?unknown?'"); } } +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") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin == 1) + { + if (curr_function) + { + if (curr_function->takes_varargs ()) + retval = curr_function->octave_va_arg (); + else + { + error ("va_arg only valid within function taking variable"); + error ("number of arguments"); + } + } + else + error ("va_arg only valid within function body"); + } + else + print_usage ("va_arg"); + + return retval; +} + +DEFUN ("va_start", Fva_start, Sva_start, 1, 0, + "va_start (): reset the pointer to the list of optional arguments\n\ +to the beginning") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin == 1) + { + if (curr_function) + { + if (curr_function->takes_varargs ()) + curr_function->octave_va_start (); + else + { + error ("va_start only valid within function taking variable"); + error ("number of arguments"); + } + } + else + error ("va_start only valid within function body"); + } + else + print_usage ("va_start"); + + return retval; +} + /* * Expressions. */ @@ -1631,9 +1659,9 @@ /* * Prefix expressions. */ -tree_prefix_expression::tree_prefix_expression (int l = -1, int c = -1) +tree_prefix_expression::tree_prefix_expression (int l, int c) { - id = (tree_identifier *) NULL; + id = 0; etype = unknown; line_num = l; column_num = c; @@ -1641,7 +1669,7 @@ tree_prefix_expression::tree_prefix_expression (tree_identifier *t, tree::expression_type et, - int l = -1, int c = -1) + int l, int c) { id = t; etype = et; @@ -1662,7 +1690,7 @@ if (error_state) return retval; - if (id != (tree_identifier *) NULL) + if (id) { id->bump_value (etype); retval = id->eval (print); @@ -1703,9 +1731,9 @@ /* * Postfix expressions. */ -tree_postfix_expression::tree_postfix_expression (int l = -1, int c = -1) +tree_postfix_expression::tree_postfix_expression (int l, int c) { - id = (tree_identifier *) NULL; + id = 0; etype = unknown; line_num = l; column_num = c; @@ -1713,7 +1741,7 @@ tree_postfix_expression::tree_postfix_expression (tree_identifier *t, tree::expression_type et, - int l = -1, int c = -1) + int l, int c) { id = t; etype = et; @@ -1734,7 +1762,7 @@ if (error_state) return retval; - if (id != (tree_identifier *) NULL) + if (id) { retval = id->eval (print); id->bump_value (etype); @@ -1769,17 +1797,17 @@ /* * Unary expressions. */ -tree_unary_expression::tree_unary_expression (int l = -1, int c = -1) +tree_unary_expression::tree_unary_expression (int l, int c) { etype = tree::unknown; - op = (tree_expression *) NULL; + op = 0; line_num = l; column_num = c; } tree_unary_expression::tree_unary_expression (tree_expression *a, tree::expression_type t, - int l = -1, int c = -1) + int l, int c) { etype = t; op = a; @@ -1806,7 +1834,7 @@ case tree::uminus: case tree::hermitian: case tree::transpose: - if (op != (tree_expression *) NULL) + if (op) { tree_constant u = op->eval (0); if (error_state) @@ -1854,11 +1882,11 @@ /* * Binary expressions. */ -tree_binary_expression::tree_binary_expression (int l = -1, int c = -1) +tree_binary_expression::tree_binary_expression (int l, int c) { etype = tree::unknown; - op1 = (tree_expression *) NULL; - op2 = (tree_expression *) NULL; + op1 = 0; + op2 = 0; line_num = l; column_num = c; } @@ -1866,7 +1894,7 @@ tree_binary_expression::tree_binary_expression (tree_expression *a, tree_expression *b, tree::expression_type t, - int l = -1, int c = -1) + int l, int c) { etype = t; op1 = a; @@ -1908,12 +1936,12 @@ case tree::cmp_ne: case tree::and: case tree::or: - if (op1 != (tree_expression *) NULL) + if (op1) { tree_constant a = op1->eval (0); if (error_state) eval_error (); - else if (a.is_defined () && op2 != (tree_expression *) NULL) + else if (a.is_defined () && op2) { tree_constant b = op2->eval (0); if (error_state) @@ -1935,7 +1963,7 @@ case tree::or_or: { int result = 0; - if (op1 != NULL_TREE) + if (op1) { tree_constant a = op1->eval (0); if (error_state) @@ -1968,7 +1996,7 @@ } } - if (op2 != NULL_TREE) + if (op2) { tree_constant b = op2->eval (0); if (error_state) @@ -2063,29 +2091,29 @@ * Simple assignment expressions. */ tree_simple_assignment_expression::tree_simple_assignment_expression - (int l = -1, int c = -1) + (int l, int c) { etype = tree::assignment; - lhs = (tree_identifier *) NULL; - index = (tree_argument_list *) NULL; - rhs = (tree_expression *) NULL; + lhs = 0; + index = 0; + rhs = 0; line_num = l; column_num = c; } tree_simple_assignment_expression::tree_simple_assignment_expression - (tree_identifier *i, tree_expression *r, int l = -1, int c = -1) + (tree_identifier *i, tree_expression *r, int l, int c) { etype = tree::assignment; lhs = i; - index = (tree_argument_list *) NULL; + index = 0; rhs = r; line_num = l; column_num = c; } tree_simple_assignment_expression::tree_simple_assignment_expression - (tree_index_expression *idx_expr, tree_expression *r, int l = -1, int c = -1) + (tree_index_expression *idx_expr, tree_expression *r, int l, int c) { etype = tree::assignment; lhs = idx_expr->ident (); @@ -2113,7 +2141,7 @@ if (error_state) return retval; - if (rhs != (tree_expression *) NULL) + if (rhs) { tree_constant rhs_val = rhs->eval (0); if (error_state) @@ -2121,7 +2149,7 @@ if (error_state) eval_error (); } - else if (index == NULL_TREE) + else if (! index) { ans = lhs->assign (rhs_val); if (error_state) @@ -2197,17 +2225,17 @@ * Multi-valued assignmnt expressions. */ tree_multi_assignment_expression::tree_multi_assignment_expression - (int l = -1, int c = -1) + (int l, int c) { etype = tree::multi_assignment; - lhs = (tree_return_list *) NULL; - rhs = (tree_expression *) NULL; + lhs = 0; + rhs = 0; line_num = l; column_num = c; } tree_multi_assignment_expression::tree_multi_assignment_expression - (tree_return_list *lst, tree_expression *r, int l = -1, int c = -1) + (tree_return_list *lst, tree_expression *r, int l, int c) { etype = tree::multi_assignment; lhs = lst; @@ -2245,7 +2273,7 @@ { assert (etype == tree::multi_assignment); - if (error_state || rhs == (tree_expression *) NULL) + if (error_state || ! rhs) return Octave_object (); nargout = lhs->length (); @@ -2264,8 +2292,7 @@ int i = 0; int pad_after = 0; int last_was_scalar_type = 0; - for (elem = lhs; elem != (tree_return_list *) NULL; - elem = elem->next_elem ()) + for (elem = lhs; elem; elem = elem->next_elem ()) { tree_index_expression *lhs_expr = elem->idx_expr (); if (i < nargout) @@ -2273,7 +2300,7 @@ // 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 = NULL_TREE_CONST; + tree_constant *tmp = 0; if (results(i).is_undefined ()) { Matrix m; @@ -2326,7 +2353,7 @@ else { tree_simple_assignment_expression tmp_expr - (lhs_expr, NULL_TREE_CONST, ma_line, ma_column); + (lhs_expr, 0, ma_line, ma_column); tmp_expr.eval (0); @@ -2362,23 +2389,23 @@ /* * Colon expressions. */ -tree_colon_expression::tree_colon_expression (int l = -1, int c = -1) +tree_colon_expression::tree_colon_expression (int l, int c) { etype = tree::colon; - op1 = (tree_expression *) NULL; - op2 = (tree_expression *) NULL; - op3 = (tree_expression *) NULL; + op1 = 0; + op2 = 0; + op3 = 0; line_num = l; column_num = c; } tree_colon_expression::tree_colon_expression (tree_expression *a, tree_expression *b, - int l = -1, int c = -1) + int l, int c) { etype = tree::colon; - op1 = a; // base - op2 = b; // limit - op3 = (tree_expression *) NULL; // increment if not empty. + op1 = a; // base + op2 = b; // limit + op3 = 0; // increment if not empty. line_num = l; column_num = c; } @@ -2393,8 +2420,8 @@ tree_colon_expression * tree_colon_expression::chain (tree_expression *t) { - tree_colon_expression *retval = (tree_colon_expression *) NULL; - if (op1 == NULL_TREE || op3 != NULL_TREE) + tree_colon_expression *retval = 0; + if (! op1 || op3) ::error ("invalid colon expression"); else { @@ -2411,7 +2438,7 @@ { tree_constant retval; - if (error_state || op1 == NULL_TREE || op2 == NULL_TREE) + if (error_state || ! op1 || ! op2) return retval; tree_constant tmp; @@ -2451,7 +2478,7 @@ double limit = tmp.double_value (); double inc = 1.0; - if (op3 != NULL_TREE) + if (op3) { tmp = op3->eval (0); @@ -2494,17 +2521,17 @@ /* * Index expressions. */ -tree_index_expression::tree_index_expression (int l = -1, int c = -1) +tree_index_expression::tree_index_expression (int l, int c) { - id = (tree_identifier *) NULL; - list = (tree_argument_list *) NULL; + id = 0; + list = 0; line_num = l; column_num = c; } tree_index_expression::tree_index_expression (tree_identifier *i, tree_argument_list *lst, - int l = -1, int c = -1) + int l, int c) { id = i; list = lst; @@ -2513,10 +2540,10 @@ } tree_index_expression::tree_index_expression (tree_identifier *i, - int l = -1, int c = -1) + int l, int c) { id = i; - list = (tree_argument_list *) NULL; + list = 0; line_num = l; column_num = c; } @@ -2560,13 +2587,7 @@ if (error_state) return retval; - if (list == (tree_argument_list *) NULL) - { - retval = id->eval (print); - if (error_state) - eval_error (); - } - else + if (list) { // Extract the arguments into a simple vector. Octave_object args = list->convert_to_const_vector (); @@ -2585,6 +2606,13 @@ retval = tmp(0); } } + else + { + retval = id->eval (print); + if (error_state) + eval_error (); + } + return retval; } @@ -2596,14 +2624,7 @@ if (error_state) return retval; - if (list == (tree_argument_list *) NULL) - { - Octave_object tmp_args; - retval = id->eval (print, nargout, tmp_args); - if (error_state) - eval_error (); - } - else + if (list) { // Extract the arguments into a simple vector. Octave_object args = list->convert_to_const_vector (); @@ -2617,6 +2638,14 @@ eval_error (); } } + else + { + Octave_object tmp_args; + retval = id->eval (print, nargout, tmp_args); + if (error_state) + eval_error (); + } + return retval; } @@ -2630,7 +2659,7 @@ char *fmt; if (l != -1 && c != -1) { - if (list != (tree_argument_list *) NULL) + if (list) fmt = "evaluating index expression near line %d, column %d"; else fmt = "evaluating expression near line %d, column %d"; @@ -2639,7 +2668,7 @@ } else { - if (list != (tree_argument_list *) NULL) + if (list) ::error ("evaluating index expression"); else ::error ("evaluating expression"); @@ -2652,14 +2681,14 @@ */ tree_argument_list::tree_argument_list (void) { - arg = NULL_TREE; - next = (tree_argument_list *) NULL; + arg = 0; + next = 0; } tree_argument_list::tree_argument_list (tree *t) { arg = t; - next = (tree_argument_list *) NULL; + next = 0; } tree_argument_list::~tree_argument_list (void) @@ -2681,9 +2710,9 @@ { tree_argument_list *list = this; tree_argument_list *next; - tree_argument_list *prev = (tree_argument_list *) NULL; - - while (list != (tree_argument_list *) NULL) + tree_argument_list *prev = 0; + + while (list) { next = list->next; list->next = prev; @@ -2698,7 +2727,7 @@ { tree_argument_list *list = this; int len = 0; - while (list != (tree_argument_list *) NULL) + while (list) { len++; list = list->next; @@ -2728,7 +2757,7 @@ tree_argument_list *tmp_list = this; for (int k = 1; k < len; k++) { - if (tmp_list != (tree_argument_list *) NULL) + if (tmp_list) { args(k) = tmp_list->eval (0); if (error_state) @@ -2750,7 +2779,7 @@ tree_constant tree_argument_list::eval (int print) { - if (error_state || arg == NULL_TREE) + if (error_state || ! arg) return tree_constant (); else return arg->eval (print); @@ -2762,15 +2791,15 @@ tree_parameter_list::tree_parameter_list (void) { marked_for_varargs = 0; - param = (tree_identifier *) NULL; - next = (tree_parameter_list *) NULL; + param = 0; + next = 0; } tree_parameter_list::tree_parameter_list (tree_identifier *t) { marked_for_varargs = 0; param = t; - next = (tree_parameter_list *) NULL; + next = 0; } tree_parameter_list::~tree_parameter_list (void) @@ -2792,9 +2821,9 @@ { tree_parameter_list *list = this; tree_parameter_list *next; - tree_parameter_list *prev = (tree_parameter_list *) NULL; - - while (list != (tree_parameter_list *) NULL) + tree_parameter_list *prev = 0; + + while (list) { next = list->next; list->next = prev; @@ -2809,7 +2838,7 @@ { tree_parameter_list *list = this; int len = 0; - while (list != (tree_parameter_list *) NULL) + while (list) { len++; list = list->next; @@ -2827,7 +2856,7 @@ tree_parameter_list::mark_as_formal_parameters (void) { param->mark_as_formal_parameter (); - if (next != (tree_parameter_list *) NULL) + if (next) next->mark_as_formal_parameters (); } @@ -2875,7 +2904,7 @@ for (int i = 1; i < expected_nargin; i++) { - tree_constant *tmp = NULL_TREE_CONST; + tree_constant *tmp = 0; if (i < nargin) { @@ -2901,10 +2930,8 @@ Octave_object retval (nout); int i = 0; - - tree_parameter_list *elem = this; - - for ( ; elem != (tree_parameter_list *) NULL; elem = elem->next) + + for (tree_parameter_list *elem = this; elem; elem = elem->next) { if (elem->is_defined ()) retval(i) = elem->eval (0); @@ -2917,7 +2944,7 @@ int tree_parameter_list::is_defined (void) { - return (param != (tree_identifier *) NULL && param->is_defined ()); + return (param && param->is_defined ()); } tree_parameter_list * @@ -2929,7 +2956,7 @@ tree_constant tree_parameter_list::eval (int print) { - if (error_state || param == NULL_TREE) + if (error_state || ! param) return tree_constant (); else return param->eval (print); @@ -2940,20 +2967,20 @@ */ tree_return_list::tree_return_list (void) { - retval = (tree_index_expression *) NULL; - next = (tree_return_list *) NULL; + retval = 0; + next = 0; } tree_return_list::tree_return_list (tree_identifier *t) { retval = new tree_index_expression (t); - next = (tree_return_list *) NULL; + next = 0; } tree_return_list::tree_return_list (tree_index_expression *t) { retval = t; - next = (tree_return_list *) NULL; + next = 0; } tree_return_list::~tree_return_list (void) @@ -2983,9 +3010,9 @@ { tree_return_list *list = this; tree_return_list *next; - tree_return_list *prev = (tree_return_list *) NULL; - - while (list != (tree_return_list *) NULL) + tree_return_list *prev = 0; + + while (list) { next = list->next; list->next = prev; @@ -3000,7 +3027,7 @@ { tree_return_list *list = this; int len = 0; - while (list != (tree_return_list *) NULL) + while (list) { len++; list = list->next; diff --git a/src/pt-exp-base.h b/src/pt-exp-base.h --- a/src/pt-exp-base.h +++ b/src/pt-exp-base.h @@ -1,4 +1,4 @@ -// Tree classes. -*- C++ -*- +// tree-expr.h -*- C++ -*- /* Copyright (C) 1992, 1993, 1994 John W. Eaton @@ -28,9 +28,11 @@ #pragma interface #endif +#include #include -#include "builtins.h" +#include "variables.h" +#include "mappers.h" #include "error.h" #include "oct-obj.h" @@ -38,9 +40,6 @@ class symbol_record; class symbol_table; -typedef Octave_object (*Text_fcn)(int, char **, int); -typedef Octave_object (*General_fcn)(const Octave_object&, int); - class tree_matrix; class tree_builtin; class tree_identifier; @@ -351,7 +350,7 @@ virtual tree_constant assign (tree_constant& t, const Octave_object& args); virtual char *name (void) const - { panic_impossible (); return (char *) NULL; } + { panic_impossible (); return 0; } virtual void bump_value (tree::expression_type) { panic_impossible (); } @@ -360,7 +359,7 @@ { panic_impossible (); return 0; } virtual char *fcn_file_name (void) - { return (char *) NULL; } + { return 0; } virtual time_t time_parsed (void) { panic_impossible (); return 0; } @@ -380,21 +379,20 @@ tree_builtin : public tree_fvc { public: - tree_builtin (const char *nm = (char *) NULL); + tree_builtin (const char *nm = 0); tree_builtin (int i_max, int o_max, Mapper_fcn& m_fcn, - const char *nm = (char *) NULL); + const char *nm = 0); - tree_builtin (int i_max, int o_max, Text_fcn t_fcn, - const char *nm = (char *) NULL); - - tree_builtin (int i_max, int o_max, General_fcn t_fcn, - const char *nm = (char *) NULL); + tree_builtin (int i_max, int o_max, Octave_builtin_fcn f, + const char *nm = 0); ~tree_builtin (void); // int is_builtin (void) const; + int is_mapper_function (void) const; + tree_constant eval (int print); Octave_object eval (int print, int nargout, const Octave_object& args); @@ -406,9 +404,9 @@ private: int nargin_max; int nargout_max; + int is_mapper; Mapper_fcn mapper_fcn; - Text_fcn text_fcn; - General_fcn general_fcn; + Octave_builtin_fcn fcn; char *my_name; }; diff --git a/src/sighandlers.cc b/src/sighandlers.cc --- a/src/sighandlers.cc +++ b/src/sighandlers.cc @@ -1,7 +1,7 @@ // sighandlers.cc -*- C++ -*- /* -Copyright (C) 1992, 1993 John W. Eaton +Copyright (C) 1992, 1993, 1994 John W. Eaton This file is part of Octave. @@ -127,7 +127,7 @@ sigpipe_handler (int i) { if (pipe_handler_error_count++ == 0) - message ((char *) NULL, "broken pipe"); + message (0, "broken pipe"); // Don\'t loop forever on account of this. if (pipe_handler_error_count > 100) diff --git a/src/sysdep.cc b/src/sysdep.cc --- a/src/sysdep.cc +++ b/src/sysdep.cc @@ -25,11 +25,47 @@ #include "config.h" #endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif #include +#include #include +#include +#include "tree-const.h" +#include "octave.h" +#include "input.h" +#include "utils.h" +#include "oct-obj.h" #include "error.h" #include "sysdep.h" +#include "defun.h" + +extern "C" +{ +#include + +extern char *term_clrpag; +extern void _rl_output_character_function (); + +#if defined (HAVE_TERMIOS_H) +#include +#elif defined (HAVE_TERMIO_H) +#include +#elif defined (HAVE_SGTTY_H) +#include +#else +LOSE! LOSE! +#endif + +extern int ioctl (); +} + +#ifndef STDIN_FILENO +#define STDIN_FILENO 1 +#endif // Octave's idea of infinity. double octave_Inf; @@ -80,6 +116,10 @@ #ifdef linux octave_Inf = HUGE_VAL; #else +#ifdef __alpha__ + extern unsigned int DINFINITY[2]; + octave_Inf = (*((double *) (DINFINITY))); +#else double tmp = 1e+10; octave_Inf = tmp; for (;;) @@ -91,6 +131,9 @@ } #endif #endif +#endif + + #if defined (HAVE_QUIET_NAN) octave_NaN = (double) quiet_nan (); @@ -98,9 +141,14 @@ #ifdef linux octave_NaN = NAN; #else +#ifdef __alpha__ + extern unsigned int DQNAN[2]; + octave_NaN = (*((double *) (DQNAN))); +#else octave_NaN = octave_Inf / octave_Inf; #endif #endif +#endif #else @@ -158,6 +206,289 @@ } /* + * Set terminal in raw mode. From less-177. + * + * Change terminal to "raw mode", or restore to "normal" mode. + * "Raw mode" means + * 1. An outstanding read will complete on receipt of a single keystroke. + * 2. Input is not echoed. + * 3. On output, \n is mapped to \r\n. + * 4. \t is NOT expanded into spaces. + * 5. Signal-causing characters such as ctrl-C (interrupt), + * etc. are NOT disabled. + * It doesn't matter whether an input \n is mapped to \r, or vice versa. + */ +void +raw_mode (int on) +{ + static int curr_on = 0; + + int tty_fd = STDIN_FILENO; + if (! isatty (tty_fd)) + { + if (interactive) + error ("stdin is not a tty!"); + return; + } + + if (on == curr_on) + return; + +#if defined (HAVE_TERMIOS_H) + { + struct termios s; + static struct termios save_term; + + if (on) + { +// Get terminal modes. + + tcgetattr (tty_fd, &s); + +// Save modes and set certain variables dependent on modes. + + save_term = s; +// ospeed = s.c_cflag & CBAUD; +// erase_char = s.c_cc[VERASE]; +// kill_char = s.c_cc[VKILL]; + +// Set the modes to the way we want them. + + s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL); + s.c_oflag |= (OPOST|ONLCR); +#if defined (OCRNL) + s.c_oflag &= ~(OCRNL); +#endif +#if defined (ONOCR) + s.c_oflag &= ~(ONOCR); +#endif +#if defined (ONLRET) + s.c_oflag &= ~(ONLRET); +#endif + s.c_cc[VMIN] = 1; + s.c_cc[VTIME] = 0; + } + else + { +// Restore saved modes. + s = save_term; + } + tcsetattr (tty_fd, TCSAFLUSH, &s); + } +#elif defined (HAVE_TERMIO_H) + { + struct termio s; + static struct termio save_term; + + if (on) + { +// Get terminal modes. + + ioctl (tty_fd, TCGETA, &s); + +// Save modes and set certain variables dependent on modes. + + save_term = s; +// ospeed = s.c_cflag & CBAUD; +// erase_char = s.c_cc[VERASE]; +// kill_char = s.c_cc[VKILL]; + +// Set the modes to the way we want them. + + s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL); + s.c_oflag |= (OPOST|ONLCR); +#if defined (OCRNL) + s.c_oflag &= ~(OCRNL); +#endif +#if defined (ONOCR) + s.c_oflag &= ~(ONOCR); +#endif +#if defined (ONLRET) + s.c_oflag &= ~(ONLRET); +#endif + s.c_cc[VMIN] = 1; + s.c_cc[VTIME] = 0; + } + else + { +// Restore saved modes. + s = save_term; + } + ioctl (tty_fd, TCSETAW, &s); + } +#elif defined (HAVE_SGTTY_H) + { + struct sgttyb s; + static struct sgttyb save_term; + + if (on) + { +// Get terminal modes. + + ioctl (tty_fd, TIOCGETP, &s); + +// Save modes and set certain variables dependent on modes. + + save_term = s; +// ospeed = s.sg_ospeed; +// erase_char = s.sg_erase; +// kill_char = s.sg_kill; + +// Set the modes to the way we want them. + + s.sg_flags |= CBREAK; + s.sg_flags &= ~(ECHO); + } + else + { +// Restore saved modes. + s = save_term; + } + ioctl (tty_fd, TIOCSETN, &s); + } +#else +LOSE! LOSE! +#endif + + curr_on = on; +} + +/* + * Read one character from the terminal. + */ +int +kbhit (void) +{ + int c; + raw_mode (1); + c = cin.get (); + raw_mode (0); + return c; +} + +DEFUN ("clc", Fclc, Sclc, 1, 0, + "clc (): clear screen") +{ + Octave_object retval; + + rl_beg_of_line (); + rl_kill_line (1); + +#if ! defined (_GO32_) + if (term_clrpag) + tputs (term_clrpag, 1, _rl_output_character_function); + else + crlf (); +#else + crlf (); +#endif + + fflush (rl_outstream); + + return retval; +} + +DEFUN ("getenv", Fgetenv, Sgetenv, 2, 1, + "getenv (STRING): get environment variable values") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin == 2 && args(1).is_string_type ()) + { + char *value = getenv (args(1).string_value ()); + if (value) + retval = value; + else + retval = ""; + } + else + print_usage ("getenv"); + + return retval; +} + +DEFALIAS (home, clc) + +DEFUN ("kbhit", Fkbhit, Skbhit, 1, 1, + "kbhit: get a single character from the terminal") +{ + Octave_object retval; + +// XXX FIXME XXX -- add timeout and default value args? + + if (interactive) + { + int c = kbhit (); + char *s = new char [2]; + s[0] = c; + s[1] = '\0'; + retval = s; + } + + return retval; +} + +DEFUN ("pause", Fpause, Spause, 1, 1, + "pause (seconds): suspend program execution") +{ + Octave_object retval; + + int nargin = args.length (); + + if (! (nargin == 1 || nargin == 2)) + { + print_usage ("pause"); + return retval; + } + + if (interactive) + { + switch (nargin) + { + case 2: + { + int delay = NINT (args(1).double_value ()); + if (delay > 0) + { + sleep (delay); + break; + } + } + default: + if (kbhit () == EOF) + clean_up_and_exit (0); + break; + } + } + + return retval; +} + +#if !defined (HAVE_GETHOSTNAME) && defined (HAVE_SYS_UTSNAME_H) +extern "C" +{ +#include +int +gethostname (char *name, int namelen) +{ + int i; + struct utsname ut; + + --namelen; + + uname (&ut); + i = strlen (ut.nodename) + 1; + strncpy (name, ut.nodename, i < namelen ? i : namelen); + name[namelen] = '\0'; + + return 0; +} +} +#endif + +/* ;;; Local Variables: *** ;;; mode: C++ *** ;;; page-delimiter: "^/\\*" *** diff --git a/src/sysdep.h b/src/sysdep.h --- a/src/sysdep.h +++ b/src/sysdep.h @@ -26,6 +26,15 @@ extern void sysdep_init (void); +extern void raw_mode (int); +extern int kbhit (void); + + +extern "C" +{ +extern int gethostname (); +} + // Octave's idea of infinity. extern double octave_Inf; diff --git a/src/tc-rep.cc b/src/tc-rep.cc --- a/src/tc-rep.cc +++ b/src/tc-rep.cc @@ -1,4 +1,4 @@ -// The constants for the tree class. -*- C++ -*- +// tc-rep.cc -*- C++ -*- /* Copyright (C) 1992, 1993, 1994 John W. Eaton @@ -656,7 +656,7 @@ } void -tree_constant_rep::maybe_resize (int i, force_orient f_orient = no_orient) +tree_constant_rep::maybe_resize (int i, force_orient f_orient) { int nr = rows (); int nc = columns (); @@ -816,7 +816,7 @@ } tree_constant_rep::constant_type -tree_constant_rep::force_numeric (int force_str_conv = 0) +tree_constant_rep::force_numeric (int force_str_conv) { switch (type_tag) { @@ -887,7 +887,7 @@ } tree_constant -tree_constant_rep::make_numeric (int force_str_conv = 0) const +tree_constant_rep::make_numeric (int force_str_conv) const { tree_constant retval; switch (type_tag) @@ -1488,10 +1488,10 @@ char *tag = extract_keyword (is, "type"); - if (tag != (char *) NULL && *tag != '\0') + if (tag && *tag) { char *ptr = strchr (tag, ' '); - if (ptr != (char *) NULL) + if (ptr) { *ptr = '\0'; is_global = (strncmp (tag, "global", 6) == 0); @@ -2567,7 +2567,7 @@ && (scalar < m_fcn.lower_limit || scalar > m_fcn.upper_limit)) { - if (m_fcn.c_c_mapper != NULL) + if (m_fcn.c_c_mapper) { Complex c = m_fcn.c_c_mapper (Complex (scalar)); retval = tree_constant (c); @@ -2577,7 +2577,7 @@ } else { - if (m_fcn.d_d_mapper != NULL) + if (m_fcn.d_d_mapper) { double d = m_fcn.d_d_mapper (scalar); retval = tree_constant (d); @@ -2591,7 +2591,7 @@ && (any_element_less_than (*matrix, m_fcn.lower_limit) || any_element_greater_than (*matrix, m_fcn.upper_limit))) { - if (m_fcn.c_c_mapper != NULL) + if (m_fcn.c_c_mapper) { ComplexMatrix cm = map (m_fcn.c_c_mapper, ComplexMatrix (*matrix)); @@ -2602,7 +2602,7 @@ } else { - if (m_fcn.d_d_mapper != NULL) + if (m_fcn.d_d_mapper) { Matrix m = map (m_fcn.d_d_mapper, *matrix); retval = tree_constant (m); @@ -2612,13 +2612,13 @@ } break; case complex_scalar_constant: - if (m_fcn.d_c_mapper != NULL) + if (m_fcn.d_c_mapper) { double d; d = m_fcn.d_c_mapper (*complex_scalar); retval = tree_constant (d); } - else if (m_fcn.c_c_mapper != NULL) + else if (m_fcn.c_c_mapper) { Complex c; c = m_fcn.c_c_mapper (*complex_scalar); @@ -2628,13 +2628,13 @@ panic_impossible (); break; case complex_matrix_constant: - if (m_fcn.d_c_mapper != NULL) + if (m_fcn.d_c_mapper) { Matrix m; m = map (m_fcn.d_c_mapper, *complex_matrix); retval = tree_constant (m); } - else if (m_fcn.c_c_mapper != NULL) + else if (m_fcn.c_c_mapper) { ComplexMatrix cm; cm = map (m_fcn.c_c_mapper, *complex_matrix); @@ -2659,7 +2659,7 @@ * hand off to other functions to do the real work. */ void -tree_constant_rep::assign (tree_constant& rhs, const Octave_object& args) +tree_constant_rep::assign (const tree_constant& rhs, const Octave_object& args) { tree_constant rhs_tmp = rhs.make_numeric (); @@ -2698,7 +2698,7 @@ * this can convert the left-hand side to a matrix. */ void -tree_constant_rep::do_scalar_assignment (tree_constant& rhs, +tree_constant_rep::do_scalar_assignment (const tree_constant& rhs, const Octave_object& args) { assert (type_tag == unknown_constant @@ -2805,7 +2805,7 @@ * matrix to an expression with empty indices to do nothing. */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, const Octave_object& args) { assert (type_tag == unknown_constant @@ -2878,8 +2878,8 @@ * Matrix assignments indexed by a single value. */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - tree_constant& i_arg) +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + const tree_constant& i_arg) { int nr = rows (); int nc = columns (); @@ -2924,8 +2924,8 @@ * multi-dimensional matrices. */ void -tree_constant_rep::fortran_style_matrix_assignment (tree_constant& rhs, - tree_constant& i_arg) +tree_constant_rep::fortran_style_matrix_assignment (const tree_constant& rhs, + const tree_constant& i_arg) { tree_constant tmp_i = i_arg.make_numeric_or_magic (); @@ -3087,7 +3087,7 @@ * Fortran-style assignment for vector index. */ void -tree_constant_rep::fortran_style_matrix_assignment (tree_constant& rhs, +tree_constant_rep::fortran_style_matrix_assignment (const tree_constant& rhs, idx_vector& i) { assert (rhs.is_matrix_type ()); @@ -3133,7 +3133,7 @@ */ void tree_constant_rep::fortran_style_matrix_assignment - (tree_constant& rhs, tree_constant_rep::constant_type mci) + (const tree_constant& rhs, tree_constant_rep::constant_type mci) { assert (rhs.is_matrix_type () && mci == tree_constant_rep::magic_colon); @@ -3182,7 +3182,8 @@ * assignment to a matrix indexed by two colons. */ void -tree_constant_rep::vector_assignment (tree_constant& rhs, tree_constant& i_arg) +tree_constant_rep::vector_assignment (const tree_constant& rhs, + const tree_constant& i_arg) { int nr = rows (); int nc = columns (); @@ -3301,7 +3302,7 @@ * Assignment to a vector with an integer index. */ void -tree_constant_rep::do_vector_assign (tree_constant& rhs, int i) +tree_constant_rep::do_vector_assign (const tree_constant& rhs, int i) { int rhs_nr = rhs.rows (); int rhs_nc = rhs.columns (); @@ -3359,7 +3360,8 @@ * Assignment to a vector with a vector index. */ void -tree_constant_rep::do_vector_assign (tree_constant& rhs, idx_vector& iv) +tree_constant_rep::do_vector_assign (const tree_constant& rhs, + idx_vector& iv) { if (rhs.is_zero_by_zero ()) { @@ -3464,7 +3466,8 @@ * Assignment to a vector with a range index. */ void -tree_constant_rep::do_vector_assign (tree_constant& rhs, Range& ri) +tree_constant_rep::do_vector_assign (const tree_constant& rhs, + Range& ri) { if (rhs.is_zero_by_zero ()) { @@ -3573,9 +3576,9 @@ * assignment. */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - tree_constant& i_arg, - tree_constant& j_arg) +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + const tree_constant& i_arg, + const tree_constant& j_arg) { tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic (); @@ -3637,8 +3640,8 @@ /* MA1 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, - tree_constant& j_arg) +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, int i, + const tree_constant& j_arg) { tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); @@ -3775,8 +3778,9 @@ /* MA2 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, idx_vector& iv, - tree_constant& j_arg) +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + idx_vector& iv, + const tree_constant& j_arg) { tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); @@ -3907,8 +3911,9 @@ /* MA3 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - Range& ri, tree_constant& j_arg) +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + Range& ri, + const tree_constant& j_arg) { tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); @@ -4044,9 +4049,9 @@ /* MA4 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, tree_constant_rep::constant_type i, - tree_constant& j_arg) + const tree_constant& j_arg) { tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic (); @@ -4227,7 +4232,8 @@ /* 1 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, int j) +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + int i, int j) { REP_ELEM_ASSIGN (i, j, rhs.double_value (), rhs.complex_value (), rhs.is_real_type ()); @@ -4235,7 +4241,7 @@ /* 2 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, int i, idx_vector& jv) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4247,7 +4253,8 @@ /* 3 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, Range& rj) +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + int i, Range& rj) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4265,7 +4272,7 @@ /* 4 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, int i, tree_constant_rep::constant_type mcj) { assert (mcj == magic_colon); @@ -4295,7 +4302,7 @@ /* 5 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, idx_vector& iv, int j) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4310,8 +4317,9 @@ /* 6 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - idx_vector& iv, idx_vector& jv) +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + idx_vector& iv, + idx_vector& jv) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4329,8 +4337,9 @@ /* 7 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, - idx_vector& iv, Range& rj) +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + idx_vector& iv, + Range& rj) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4352,7 +4361,8 @@ /* 8 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, idx_vector& iv, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + idx_vector& iv, tree_constant_rep::constant_type mcj) { assert (mcj == magic_colon); @@ -4381,7 +4391,8 @@ /* 9 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri, int j) +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + Range& ri, int j) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4399,7 +4410,8 @@ /* 10 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + Range& ri, idx_vector& jv) { REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc); @@ -4422,7 +4434,8 @@ /* 11 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + Range& ri, Range& rj) { double ib = ri.base (); @@ -4448,7 +4461,8 @@ /* 12 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, + Range& ri, tree_constant_rep::constant_type mcj) { assert (mcj == magic_colon); @@ -4479,7 +4493,7 @@ /* 13 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, tree_constant_rep::constant_type mci, int j) { @@ -4510,7 +4524,7 @@ /* 14 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, tree_constant_rep::constant_type mci, idx_vector& jv) { @@ -4540,7 +4554,7 @@ /* 15 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, tree_constant_rep::constant_type mci, Range& rj) { @@ -4574,7 +4588,7 @@ /* 16 */ void -tree_constant_rep::do_matrix_assignment (tree_constant& rhs, +tree_constant_rep::do_matrix_assignment (const tree_constant& rhs, tree_constant_rep::constant_type mci, tree_constant_rep::constant_type mcj) { @@ -5247,8 +5261,8 @@ if (index_nr >= 1 && index_nc >= 1) { - const double *cop_out = (const double *) NULL; - const Complex *c_cop_out = (const Complex *) NULL; + const double *cop_out = 0; + const Complex *c_cop_out = 0; int real_type = type_tag == matrix_constant; if (real_type) cop_out = matrix->data (); @@ -6224,9 +6238,10 @@ tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci, tree_constant_rep::constant_type mcj) const { + tree_constant retval; assert (mci == magic_colon && mcj == magic_colon); - - return tree_constant (*this); + retval = tree_constant (*this); + return retval; } tree_constant diff --git a/src/tc-rep.h b/src/tc-rep.h --- a/src/tc-rep.h +++ b/src/tc-rep.h @@ -1,4 +1,4 @@ -// The rest of the tree classes. -*- C++ -*- +// tc-rep.h -*- C++ -*- /* Copyright (C) 1992, 1993, 1994 John W. Eaton @@ -37,6 +37,8 @@ class idx_vector; +struct Mapper_fcn; + /* * Forward class declarations. */ @@ -156,64 +158,78 @@ tree_constant_rep::constant_type force_numeric (int force_str_conv = 0); tree_constant make_numeric (int force_str_conv = 0) const; - void assign (tree_constant& rhs, const Octave_object& args); + void assign (const tree_constant& rhs, const Octave_object& args); - void do_scalar_assignment (tree_constant& rhs, const Octave_object& args); + void do_scalar_assignment (const tree_constant& rhs, + const Octave_object& args); - void do_matrix_assignment (tree_constant& rhs, const Octave_object& args); + void do_matrix_assignment (const tree_constant& rhs, + const Octave_object& args); - void do_matrix_assignment (tree_constant& rhs, tree_constant& i_arg); + void do_matrix_assignment (const tree_constant& rhs, + const tree_constant& i_arg); - void do_matrix_assignment - (tree_constant& rhs, tree_constant& i_arg, tree_constant& j_arg); + void do_matrix_assignment (const tree_constant& rhs, + const tree_constant& i_arg, + const tree_constant& j_arg); - void fortran_style_matrix_assignment (tree_constant& rhs, - tree_constant& i_arg); + void fortran_style_matrix_assignment (const tree_constant& rhs, + const tree_constant& i_arg); - void fortran_style_matrix_assignment (tree_constant& rhs, constant_type ci); + void fortran_style_matrix_assignment (const tree_constant& rhs, + constant_type ci); - void fortran_style_matrix_assignment (tree_constant& rhs, idx_vector& i); + void fortran_style_matrix_assignment (const tree_constant& rhs, + idx_vector& i); - void vector_assignment (tree_constant& rhs, tree_constant& i_arg); + void vector_assignment (const tree_constant& rhs, + const tree_constant& i_arg); void check_vector_assign (int rhs_nr, int rhs_nc, int ilen, const char *rm); - void do_vector_assign (tree_constant& rhs, int i); - void do_vector_assign (tree_constant& rhs, idx_vector& i); - void do_vector_assign (tree_constant& rhs, Range& i); + void do_vector_assign (const tree_constant& rhs, int i); + void do_vector_assign (const tree_constant& rhs, idx_vector& i); + void do_vector_assign (const tree_constant& rhs, Range& i); + + void do_matrix_assignment (const tree_constant& rhs, int i, + const tree_constant& j_arg); + void do_matrix_assignment (const tree_constant& rhs, idx_vector& i, + const tree_constant& j_arg); + void do_matrix_assignment (const tree_constant& rhs, Range& i, + const tree_constant& j_arg); + void do_matrix_assignment (const tree_constant& rhs, constant_type i, + const tree_constant& j_arg); - void do_matrix_assignment - (tree_constant& rhs, int i, tree_constant& j_arg); - void do_matrix_assignment - (tree_constant& rhs, idx_vector& i, tree_constant& j_arg); - void do_matrix_assignment - (tree_constant& rhs, Range& i, tree_constant& j_arg); - void do_matrix_assignment - (tree_constant& rhs, constant_type i, tree_constant& j_arg); + void do_matrix_assignment (const tree_constant& rhs, int i, int j); + void do_matrix_assignment (const tree_constant& rhs, int i, idx_vector& jv); + void do_matrix_assignment (const tree_constant& rhs, int i, Range& j); + void do_matrix_assignment (const tree_constant& rhs, int i, constant_type cj); - void do_matrix_assignment (tree_constant& rhs, int i, int j); - void do_matrix_assignment (tree_constant& rhs, int i, idx_vector& jv); - void do_matrix_assignment (tree_constant& rhs, int i, Range& j); - void do_matrix_assignment (tree_constant& rhs, int i, constant_type cj); - - void do_matrix_assignment (tree_constant& rhs, idx_vector& iv, int j); - void do_matrix_assignment (tree_constant& rhs, idx_vector& iv, + void do_matrix_assignment (const tree_constant& rhs, idx_vector& iv, + int j); + void do_matrix_assignment (const tree_constant& rhs, idx_vector& iv, idx_vector& jv); - void do_matrix_assignment (tree_constant& rhs, idx_vector& iv, Range& j); - void do_matrix_assignment (tree_constant& rhs, idx_vector& iv, + void do_matrix_assignment (const tree_constant& rhs, idx_vector& iv, + Range& j); + void do_matrix_assignment (const tree_constant& rhs, idx_vector& iv, constant_type j); - void do_matrix_assignment (tree_constant& rhs, Range& i, int j); - void do_matrix_assignment (tree_constant& rhs, Range& i, idx_vector& jv); - void do_matrix_assignment (tree_constant& rhs, Range& i, Range& j); - void do_matrix_assignment (tree_constant& rhs, Range& i, constant_type j); + void do_matrix_assignment (const tree_constant& rhs, Range& i, int j); + void do_matrix_assignment (const tree_constant& rhs, Range& i, + idx_vector& jv); + void do_matrix_assignment (const tree_constant& rhs, Range& i, + Range& j); + void do_matrix_assignment (const tree_constant& rhs, Range& i, + constant_type j); - void do_matrix_assignment (tree_constant& rhs, constant_type i, int j); - void do_matrix_assignment (tree_constant& rhs, constant_type i, + void do_matrix_assignment (const tree_constant& rhs, constant_type i, int j); + void do_matrix_assignment (const tree_constant& rhs, constant_type i, idx_vector& jv); - void do_matrix_assignment (tree_constant& rhs, constant_type i, Range& j); - void do_matrix_assignment (tree_constant& rhs, constant_type i, + void do_matrix_assignment (const tree_constant& rhs, constant_type i, + Range& j); + void do_matrix_assignment (const tree_constant& rhs, + const constant_type i, constant_type j); void delete_row (int); diff --git a/src/token.cc b/src/token.cc --- a/src/token.cc +++ b/src/token.cc @@ -35,14 +35,14 @@ #include "utils.h" #include "symtab.h" -token::token (int l = -1, int c = -1) +token::token (int l, int c) { line_num = l; column_num = c; type_tag = generic_token; } -token::token (char *s, int l = -1, int c = -1) +token::token (char *s, int l, int c) { line_num = l; column_num = c; @@ -50,7 +50,7 @@ str = strsave (s); } -token::token (double d, int l = -1, int c = -1) +token::token (double d, int l, int c) { line_num = l; column_num = c; @@ -58,7 +58,7 @@ num = d; } -token::token (end_tok_type t, int l = -1, int c = -1) +token::token (end_tok_type t, int l, int c) { line_num = l; column_num = c; @@ -66,7 +66,7 @@ et = t; } -token::token (plot_tok_type t, int l = -1, int c = -1) +token::token (plot_tok_type t, int l, int c) { line_num = l; column_num = c; @@ -74,7 +74,7 @@ pt = t; } -token::token (symbol_record *s, int l = -1, int c = -1) +token::token (symbol_record *s, int l, int c) { line_num = l; column_num = c; diff --git a/src/unwind-prot.cc b/src/unwind-prot.cc --- a/src/unwind-prot.cc +++ b/src/unwind-prot.cc @@ -41,21 +41,21 @@ unwind_elem::unwind_elem (void) { - unwind_elem_tag = (char *) NULL; - unwind_elem_fptr = (cleanup_func) NULL; - unwind_elem_ptr = (void *) NULL; + unwind_elem_tag = 0; + unwind_elem_fptr = 0; + unwind_elem_ptr = 0; } unwind_elem::unwind_elem (char *t) { unwind_elem_tag = strsave (t); - unwind_elem_fptr = (cleanup_func) NULL; - unwind_elem_ptr = (void *) NULL; + unwind_elem_fptr = 0; + unwind_elem_ptr = 0; } unwind_elem::unwind_elem (cleanup_func f, void *p) { - unwind_elem_tag = (char *) NULL; + unwind_elem_tag = 0; unwind_elem_fptr = f; unwind_elem_ptr = p; } @@ -115,7 +115,7 @@ unwind_elem el = unwind_protect_list.pop (); cleanup_func f = el.fptr (); - if (f != (cleanup_func) NULL) + if (f) f (el.ptr ()); } @@ -140,11 +140,11 @@ unwind_elem el = unwind_protect_list.pop (); cleanup_func f = el.fptr (); - if (f != (cleanup_func) NULL) + if (f) f (el.ptr ()); char *t = el.tag (); - if (t != (char *) NULL && strcmp (t, tag) == 0) + if (t && strcmp (t, tag) == 0) break; } } @@ -156,7 +156,7 @@ { unwind_elem el = unwind_protect_list.pop (); char *t = el.tag (); - if (t != (char *) NULL && strcmp (t, tag) == 0) + if (t && strcmp (t, tag) == 0) break; } } @@ -169,7 +169,7 @@ unwind_elem el = unwind_protect_list.pop (); cleanup_func f = el.fptr (); - if (f != (cleanup_func) NULL) + if (f) f (el.ptr ()); } } @@ -225,8 +225,8 @@ saved_variable::saved_variable (void) { - gen_ptr = (void *) NULL; - gen_ptr_value = (void *) NULL; + gen_ptr = 0; + gen_ptr_value = 0; type_tag = generic; size = 0; } diff --git a/src/unwind-prot.h b/src/unwind-prot.h --- a/src/unwind-prot.h +++ b/src/unwind-prot.h @@ -28,6 +28,8 @@ #pragma interface #endif +#include + typedef void (*cleanup_func)(void *ptr); void add_unwind_protect (cleanup_func fptr, void *ptr); diff --git a/src/user-prefs.cc b/src/user-prefs.cc --- a/src/user-prefs.cc +++ b/src/user-prefs.cc @@ -50,7 +50,7 @@ { char *val = builtin_string_variable (var); int pref = -1; - if (val != (char *) NULL) + if (val) { if (strncmp (val, "yes", 3) == 0 || strncmp (val, "true", 4) == 0) @@ -103,7 +103,7 @@ { int pref = 0; char *val = builtin_string_variable ("commas_in_literal_matrix"); - if (val != (char *) NULL) + if (val) { if (strncmp (val, "required", 8) == 0) pref = 2; @@ -154,7 +154,7 @@ char *val = builtin_string_variable ("ignore_function_time_stamp"); - if (val != (char *) NULL) + if (val) { if (strncmp (val, "all", 3) == 0) pref = 2; @@ -486,7 +486,7 @@ int status = 0; char *s = builtin_string_variable ("EDITOR"); - if (s != (char *) NULL) + if (s) { delete [] user_pref.editor; user_pref.editor = s; @@ -506,7 +506,7 @@ int status = 0; char *s = builtin_string_variable ("gnuplot_binary"); - if (s != (char *) NULL) + if (s) { delete [] user_pref.gnuplot_binary; user_pref.gnuplot_binary = s; @@ -526,7 +526,7 @@ int status = 0; char *s = builtin_string_variable ("INFO_FILE"); - if (s != (char *) NULL) + if (s) { delete [] user_pref.info_file; user_pref.info_file = s; @@ -546,7 +546,7 @@ int status = 0; char *s = builtin_string_variable ("LOADPATH"); - if (s != (char *) NULL) + if (s) { delete [] user_pref.loadpath; user_pref.loadpath = s; @@ -566,7 +566,7 @@ int status = 0; char *s = builtin_string_variable ("PAGER"); - if (s != (char *) NULL) + if (s) { delete [] user_pref.pager_binary; user_pref.pager_binary = s; @@ -586,7 +586,7 @@ int status = 0; char *s = builtin_string_variable ("PS1"); - if (s != (char *) NULL) + if (s) { delete [] user_pref.ps1; user_pref.ps1 = s; @@ -606,7 +606,7 @@ int status = 0; char *s = builtin_string_variable ("PS2"); - if (s != (char *) NULL) + if (s) { delete [] user_pref.ps2; user_pref.ps2 = s; @@ -626,7 +626,7 @@ int status = 0; char *s = builtin_string_variable ("PWD"); - if (s != (char *) NULL) + if (s) { delete [] user_pref.pwd; user_pref.pwd = s; diff --git a/src/variables.cc b/src/variables.cc --- a/src/variables.cc +++ b/src/variables.cc @@ -30,21 +30,37 @@ #include #endif #include +#include +#include +#include #include #include #include "statdefs.h" #include "tree-const.h" #include "variables.h" +#include "mappers.h" #include "user-prefs.h" +#include "version.h" #include "symtab.h" -#include "builtins.h" -#include "g-builtins.h" -#include "t-builtins.h" +#include "defaults.h" +#include "dirfns.h" +#include "pager.h" +#include "sysdep.h" +#include "octave.h" +#include "oct-obj.h" #include "error.h" #include "utils.h" #include "tree.h" #include "help.h" +#include "defun.h" + +extern "C" +{ +#include + +#include "fnmatch.h" +} // Symbol table for symbols at the top level. symbol_table *top_level_sym_tab; @@ -77,14 +93,13 @@ if (ignore == 2) return 0; - if (sr != (symbol_record *) NULL) + if (sr) { tree_fvc *ans = sr->def (); - if (ans != (tree_fvc *) NULL) + if (ans) { char *ff = ans->fcn_file_name (); - if (! (ff == (char *) NULL - || (ignore && ans->is_system_fcn_file ()))) + if (ff && ! (ignore && ans->is_system_fcn_file ())) { time_t tp = ans->time_parsed (); char *fname = fcn_file_in_path (ff); @@ -108,19 +123,15 @@ else { symbol_record *sym_rec = curr_sym_tab->lookup (name, 0); - if (sym_rec == (symbol_record *) NULL) - { - error ("document: no such symbol `%s'", name); - } + if (sym_rec) + sym_rec->document (help); else - { - sym_rec->document (help); - } + error ("document: no such symbol `%s'", name); } } void -install_builtin_mapper_function (builtin_mapper_functions *mf) +install_builtin_mapper (builtin_mapper_function *mf) { symbol_record *sym_rec = global_sym_tab->lookup (mf->name, 1); sym_rec->unprotect (); @@ -143,56 +154,43 @@ } void -install_builtin_text_function (builtin_text_functions *tf) +install_builtin_function (builtin_function *f) { - symbol_record *sym_rec = global_sym_tab->lookup (tf->name, 1); + symbol_record *sym_rec = global_sym_tab->lookup (f->name, 1); sym_rec->unprotect (); - tree_builtin *def = new tree_builtin (tf->nargin_max, 1, - tf->text_fcn, tf->name); - - sym_rec->define (def); - - sym_rec->document (tf->help_string); - sym_rec->make_eternal (); - sym_rec->protect (); - -} + tree_builtin *def = new tree_builtin (f->nargin_max, f->nargout_max, + f->fcn, f->name); -void -install_builtin_general_function (builtin_general_functions *gf) -{ - symbol_record *sym_rec = global_sym_tab->lookup (gf->name, 1); - sym_rec->unprotect (); + sym_rec->define (def, f->is_text_fcn); - tree_builtin *def = new tree_builtin (gf->nargin_max, - gf->nargout_max, - gf->general_fcn, gf->name); - - sym_rec->define (def); - - sym_rec->document (gf->help_string); + sym_rec->document (f->help_string); sym_rec->make_eternal (); sym_rec->protect (); } void -install_builtin_variable (builtin_string_variables *sv) +install_builtin_variable (builtin_variable *v) { - tree_constant *val = new tree_constant (sv->value); - - bind_builtin_variable (sv->name, val, 0, 1, sv->sv_function, - sv->help_string); + if (v->install_as_function) + install_builtin_variable_as_function (v->name, v->value, v->protect, + v->eternal, v->help_string); + else + bind_builtin_variable (v->name, v->value, v->protect, v->eternal, + v->sv_function, v->help_string); } void install_builtin_variable_as_function (const char *name, tree_constant *val, - int protect = 0, int eternal = 0) + int protect, int eternal, + const char *help) { symbol_record *sym_rec = global_sym_tab->lookup (name, 1); sym_rec->unprotect (); - char *tmp_help = sym_rec->help (); + const char *tmp_help = help; + if (! help) + tmp_help = sym_rec->help (); sym_rec->define_as_fcn (val); @@ -230,16 +228,15 @@ */ void bind_builtin_variable (const char *varname, tree_constant *val, - int protect = 0, int eternal = 0, - sv_Function sv_fcn = (sv_Function) 0, - const char *help = (char *) 0) + int protect, int eternal, sv_Function sv_fcn, + const char *help) { symbol_record *sr = global_sym_tab->lookup (varname, 1, 0); // It is a programming error for a builtin symbol to be missing. // Besides, we just inserted it, so it must be there. - assert (sr != (symbol_record *) NULL); + assert (sr); sr->unprotect (); @@ -264,7 +261,7 @@ /* * Look for the given name in the global symbol table. If it refers - * to a string, return a new copy. If not, return NULL. + * to a string, return a new copy. If not, return 0; */ char * builtin_string_variable (const char *name) @@ -273,20 +270,20 @@ // It is a prorgramming error to look for builtins that aren't. - assert (sr != (symbol_record *) NULL); + assert (sr); - char *retval = (char *) NULL; + char *retval = 0; tree_fvc *defn = sr->def (); - if (defn != (tree_fvc *) NULL) + if (defn) { tree_constant val = defn->eval (0); if (! error_state && val.is_string_type ()) { char *s = val.string_value (); - if (s != (char *) NULL) + if (s) retval = strsave (s); } } @@ -307,11 +304,11 @@ // It is a prorgramming error to look for builtins that aren't. - assert (sr != (symbol_record *) NULL); + assert (sr); tree_fvc *defn = sr->def (); - if (defn != (tree_fvc *) NULL) + if (defn) { tree_constant val = defn->eval (0); @@ -351,22 +348,20 @@ { // Would be nice not to have this cast. XXX FIXME XXX tree_constant *tmp = (tree_constant *) sr->def (); - if (tmp == NULL_TREE_CONST) + if (tmp) + tmp = new tree_constant (*tmp); + else tmp = new tree_constant (); - else - tmp = new tree_constant (*tmp); gsr->define (tmp); } else - { - sr->clear (); - } + sr->clear (); // If the global symbol is currently defined as a function, we need to // hide it with a variable. if (gsr->is_function ()) - gsr->define (NULL_TREE_CONST); + gsr->define ((tree_constant *) 0); sr->alias (gsr, 1); sr->mark_as_linked_to_global (); @@ -381,13 +376,8 @@ { symbol_record *tmp_sym = global_sym_tab->lookup (sr->name (), 0, 0); - if (tmp_sym != (symbol_record *) NULL) - { - if (tmp_sym->is_builtin_variable ()) - { - sr->alias (tmp_sym); - } - } + if (tmp_sym && tmp_sym->is_builtin_variable ()) + sr->alias (tmp_sym); } /* @@ -401,14 +391,10 @@ { symbol_record *tmp_sym = global_sym_tab->lookup (sr->name (), 0, 0); - if (tmp_sym != (symbol_record *) NULL) - { - if ((tmp_sym->is_builtin_variable () || tmp_sym->is_function ()) - && ! tmp_sym->is_formal_parameter ()) - { - sr->alias (tmp_sym); - } - } + if (tmp_sym + && (tmp_sym->is_builtin_variable () || tmp_sym->is_function ()) + && ! tmp_sym->is_formal_parameter ()) + sr->alias (tmp_sym); } /* @@ -432,15 +418,27 @@ } } -/* - * Return 1 if the argument names a globally visible variable. - * Otherwise, return 0. - */ -int -is_globally_visible (const char *name) +DEFUN ("is_global", Fis_global, Sis_global, 2, 1, + "is_global (X): return 1 if the string X names a global variable\n\ +otherwise, return 0.") { + Octave_object retval (0.0); + + int nargin = args.length (); + + if (nargin != 2 || ! args(1).is_string_type ()) + { + print_usage ("is_global"); + return retval; + } + + char *name = args(1).string_value (); + symbol_record *sr = curr_sym_tab->lookup (name, 0, 0); - return (sr != (symbol_record *) NULL && sr->is_linked_to_global ()); + + retval = (double) (sr && sr->is_linked_to_global ()); + + return retval; } /* @@ -457,7 +455,7 @@ { ostrstream buf; - char *retval = (char *) NULL; + char *retval = 0; char c; while (is.get (c)) @@ -576,7 +574,7 @@ int valid_identifier (char *s) { - if (s == (char *) NULL || ! (isalnum (*s) || *s == '_')) + if (! s || ! (isalnum (*s) || *s == '_')) return 0; while (*++s != '\0') @@ -586,36 +584,51 @@ return 1; } -/* - * See if the identifier is in scope. - */ -int -identifier_exists (char *name) +DEFUN ("exist", Fexist, Sexist, 2, 1, + "exist (NAME): check if variable or file exists\n\ +\n\ +return 0 if NAME is undefined, 1 if it is a variable, or 2 if it is\n\ +a function.") { + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2 || ! args(1).is_string_type ()) + { + print_usage ("exist"); + return retval; + } + + char *name = args(1).string_value (); + symbol_record *sr = curr_sym_tab->lookup (name, 0, 0); - if (sr == (symbol_record *) NULL) + if (! sr) sr = global_sym_tab->lookup (name, 0, 0); - if (sr != (symbol_record *) NULL && sr->is_variable () && sr->is_defined ()) - return 1; - else if (sr != (symbol_record *) NULL && sr->is_function ()) - return 2; + retval = 0.0; + + if (sr && sr->is_variable () && sr->is_defined ()) + retval = 1.0; + else if (sr && sr->is_function ()) + retval = 2.0; else { char *path = fcn_file_in_path (name); - if (path != (char *) NULL) + if (path) { delete [] path; - return 2; + retval = 2.0; } else { struct stat buf; if (stat (name, &buf) == 0 && S_ISREG (buf.st_mode)) - return 2; + retval = 2.0; } } - return 0; + + return retval; } /* @@ -625,16 +638,16 @@ is_builtin_variable (const char *name) { symbol_record *sr = global_sym_tab->lookup (name, 0, 0); - return (sr != (symbol_record *) NULL && sr->is_builtin_variable ()); + return (sr && sr->is_builtin_variable ()); } /* * Is this tree_constant a valid function? */ tree_fvc * -is_valid_function (tree_constant& arg, char *warn_for, int warn = 0) +is_valid_function (const tree_constant& arg, char *warn_for, int warn) { - tree_fvc *ans = (tree_fvc *) NULL; + tree_fvc *ans = 0; if (! arg.is_string_type ()) { @@ -646,25 +659,25 @@ char *fcn_name = arg.string_value (); symbol_record *sr = global_sym_tab->lookup (fcn_name, 0, 0); - if (sr == (symbol_record *) NULL) + if (sr && symbol_out_of_date (sr)) + { + tree_identifier tmp (sr); + tmp.parse_fcn_file (0); + } + else { sr = global_sym_tab->lookup (fcn_name, 1, 0); tree_identifier tmp (sr); tmp.parse_fcn_file (0); } - else if (symbol_out_of_date (sr)) - { - tree_identifier tmp (sr); - tmp.parse_fcn_file (0); - } ans = sr->def (); - if (ans == (tree_fvc *) NULL || ! sr->is_function ()) + if (! ans || ! sr->is_function ()) { if (warn) error ("%s: the symbol `%s' is not valid as a function", warn_for, fcn_name); - ans = (tree_fvc *) NULL; + ans = 0; } return ans; @@ -675,7 +688,7 @@ */ int takes_correct_nargs (tree_fvc *fcn, int expected_nargin, char *warn_for, - int warn = 0) + int warn) { int nargin = fcn->max_expected_args () - 1; int e_nargin = expected_nargin - 1; @@ -683,7 +696,7 @@ { if (warn) error ("%s: expecting function to take %d argument%c", - warn_for, e_nargin, s_plural (e_nargin)); + warn_for, e_nargin, (e_nargin == 1 ? "" : "s")); return 0; } return 1; @@ -700,11 +713,11 @@ int lcl_len = 0; int ffl_len = 0; - char **key = (char **) NULL; - char **glb = (char **) NULL; - char **top = (char **) NULL; - char **lcl = (char **) NULL; - char **ffl = (char **) NULL; + char **key = 0; + char **glb = 0; + char **top = 0; + char **lcl = 0; + char **ffl = 0; // Each of these functions returns a new vector of pointers to new // strings. @@ -741,7 +754,7 @@ for (i = 0; i < ffl_len; i++) list[j++] = ffl[i]; - list[j] = (char *) NULL; + list[j] = 0; delete [] key; delete [] glb; @@ -752,6 +765,1224 @@ return list; } +int +is_text_function_name (const char *s) +{ + symbol_record *sr = global_sym_tab->lookup (s); + return (sr && sr->is_text_function ()); +} + +/* + * Help stuff. + */ +help_list * +builtin_mapper_functions_help (void) +{ +#if 0 + int count = 0; + builtin_mapper_functions *mfptr; + + mfptr = mapper_functions; + while (mfptr->name) + { + count++; + mfptr++; + } + + if (count == 0) + return 0; + + help_list *hl = new help_list [count+1]; + + int i = 0; + mfptr = mapper_functions; + while (mfptr->name) + { + hl[i].name = mfptr->name; + hl[i].help = mfptr->help_string; + i++; + mfptr++; + } + + hl[count].name = 0; + hl[count].help = 0; + + return hl; +#endif + + return 0; +} + +help_list * +builtin_general_functions_help (void) +{ +#if 0 + int count = 0; + builtin_general_functions *gfptr; + + gfptr = general_functions; + while (gfptr->name) + { + count++; + gfptr++; + } + + if (count == 0) + return 0; + + help_list *hl = new help_list [count+1]; + + int i = 0; + gfptr = general_functions; + while (gfptr->name) + { + hl[i].name = gfptr->name; + hl[i].help = gfptr->help_string; + i++; + gfptr++; + } + + hl[count].name = 0; + hl[count].help = 0; + + return hl; +#endif + + return 0; +} + +help_list * +builtin_text_functions_help (void) +{ +#if 0 + int count = 0; + builtin_text_functions *tfptr; + + tfptr = text_functions; + while (tfptr->name) + { + count++; + tfptr++; + } + + if (count == 0) + return 0; + + help_list *hl = new help_list [count+1]; + + int i = 0; + tfptr = text_functions; + while (tfptr->name) + { + hl[i].name = tfptr->name; + hl[i].help = tfptr->help_string; + i++; + tfptr++; + } + + hl[count].name = 0; + hl[count].help = 0; + + return hl; +#endif + + return 0; +} + +help_list * +builtin_variables_help (void) +{ +#if 0 + int count = 0; + + builtin_string_variables *svptr; + + svptr = string_variables; + while (svptr->name) + { + count++; + svptr++; + } + + if (count == 0) + return 0; + + help_list *hl = new help_list [count+1]; + + int i = 0; + svptr = string_variables; + while (svptr->name) + { + hl[i].name = svptr->name; + hl[i].help = svptr->help_string; + i++; + svptr++; + } + + hl[count].name = 0; + hl[count].help = 0; + + return hl; +#endif + + return 0; +} + +int +help_from_list (ostrstream& output_buf, const help_list *list, + const char *string, int usage) +{ + char *name; + while ((name = list->name) != 0) + { + if (strcmp (name, string) == 0) + { + if (usage) + output_buf << "\nusage: "; + else + { + output_buf << "\n*** " << string << ":\n\n"; + } + + output_buf << list->help << "\n"; + + return 1; + } + list++; + } + return 0; +} + +void +additional_help_message (ostrstream& output_buf) +{ + output_buf + << "\n" + << "Additional help for builtin functions, operators, and variables\n" + << "is available in the on-line version of the manual.\n" + << "\n" + << "Use the command `help -i ' to search the manual index.\n"; +} + +void +print_usage (const char *string, int just_usage) +{ + ostrstream output_buf; + + help_list *gf_help_list = builtin_general_functions_help (); + help_list *tf_help_list = builtin_text_functions_help (); + help_list *mf_help_list = builtin_mapper_functions_help (); + + if (help_from_list (output_buf, gf_help_list, string, 1) + || help_from_list (output_buf, tf_help_list, string, 1) + || help_from_list (output_buf, mf_help_list, string, 1)) + { + if (! just_usage) + additional_help_message (output_buf); + output_buf << ends; + maybe_page_output (output_buf); + } +} + +void +install_builtin_variables (void) +{ +// XXX FIXME XX -- these should probably be moved to where they +// logically belong instead of being all grouped here. + + DEFVAR ("EDITOR", SBV_EDITOR, editor, 0, 0, 1, sv_editor, + "name of the editor to be invoked by the edit_history command"); + + DEFVAR ("I", SBV_I, Complex (0.0, 1.0), 0, 1, 1, 0, + "sqrt (-1)"); + + DEFVAR ("Inf", SBV_Inf, octave_Inf, 0, 1, 1, 0, + "infinity"); + + DEFVAR ("INFO_FILE", SBV_INFO_FILE, info_file, 0, 0, 1, sv_info_file, + "name of the Octave info file"); + + DEFVAR ("J", SBV_J, Complex (0.0, 1.0), 0, 1, 1, 0, + "sqrt (-1)"); + + #if defined (HAVE_ISNAN) + DEFVAR ("NaN", SBV_NaN, octave_NaN, 0, 1, 1, 0, + "not a number"); + #endif + + DEFVAR ("LOADPATH", SBV_LOADPATH, load_path, 0, 0, 1, sv_loadpath, + "colon separated list of directories to search for scripts"); + + DEFVAR ("PAGER", SBV_PAGER, default_pager (), 0, 0, 1, sv_pager_binary, + "path to pager binary"); + + DEFVAR ("PS1", SBV_PS1, "\\s:\\#> ", 0, 0, 1, sv_ps1, + "primary prompt string"); + + DEFVAR ("PS2", SBV_PS2, "> ", 0, 0, 1, sv_ps2, + "secondary prompt string"); + + DEFVAR ("PWD", SBV_PWD, get_working_directory ("initialize_globals"), + 0, 1, 1, sv_pwd, + "current working directory"); + + DEFVAR ("SEEK_SET", SBV_SEEK_SET, 0.0, 0, 1, 1, 0, + "used with fseek to position file relative to the beginning"); + + DEFVAR ("SEEK_CUR", SBV_SEEK_CUR, 1.0, 0, 1, 1, 0, + "used with fseek to position file relative to the current position"); + + DEFVAR ("SEEK_END", SBV_SEEK_END, 2.0, 0, 1, 1, 0, + "used with fseek to position file relative to the end"); + + DEFVAR ("ans", SBV_ans, , 0, 0, 1, 0, + ""); + + DEFVAR ("commas_in_literal_matrix", SBV_commas_in_literal_matrix, "", + 0, 0, 1, commas_in_literal_matrix, + "control auto-insertion of commas in literal matrices"); + + DEFVAR ("do_fortran_indexing", SBV_do_fortran_indexing, "false", 0, 0, + 1, do_fortran_indexing, + "allow single indices for matrices"); + + DEFVAR ("empty_list_elements_ok", SBV_empty_list_elements_ok, "warn", + 0, 0, 1, empty_list_elements_ok, + "ignore the empty element in expressions like `a = [[], 1]'"); + + DEFVAR ("eps", SBV_eps, DBL_EPSILON, 0, 1, 1, 0, + "machine precision"); + + DEFVAR ("gnuplot_binary", SBV_gnuplot_binary, "gnuplot", 0, 0, 1, + sv_gnuplot_binary, + "path to gnuplot binary"); + + DEFVAR ("i", SBV_i, Complex (0.0, 1.0), 1, 1, 1, 0, + "sqrt (-1)"); + + DEFVAR ("ignore_function_time_stamp", SBV_ignore_function_time_stamp, + "system", 0, 0, 1, + ignore_function_time_stamp, + "don't check to see if function files have changed since they were\n\ + last compiled. Possible values are \"system\" and \"all\""); + + DEFVAR ("implicit_str_to_num_ok", SBV_implicit_str_to_num_ok, "false", + 0, 0, 1, implicit_str_to_num_ok, + "allow implicit string to number conversion"); + + DEFVAR ("inf", SBV_inf, octave_Inf, 0, 1, 1, 0, + "infinity"); + + DEFVAR ("j", SBV_j, Complex (0.0, 1.0), 1, 1, 1, 0, + "sqrt (-1)"); + + #if defined (HAVE_ISNAN) + DEFVAR ("nan", SBV_nan, octave_NaN, 0, 1, 1, 0, + "not a number"); + #endif + + DEFVAR ("ok_to_lose_imaginary_part", SBV_ok_to_lose_imaginary_part, + "warn", 0, 0, 1, ok_to_lose_imaginary_part, + "silently convert from complex to real by dropping imaginary part"); + + DEFVAR ("output_max_field_width", SBV_output_max_field_width, 10.0, 0, + 0, 1, set_output_max_field_width, + "maximum width of an output field for numeric output"); + + DEFVAR ("output_precision", SBV_output_precision, 5.0, 0, 0, 1, + set_output_precision, + "number of significant figures to display for numeric output"); + + DEFVAR ("page_screen_output", SBV_page_screen_output, "true", 0, 0, 1, + page_screen_output, + "if possible, send output intended for the screen through the pager"); + + DEFVAR ("pi", SBV_pi, 4.0 * atan (1.0), 0, 1, 1, 0, + "ratio of the circumference of a circle to its diameter"); + + DEFVAR ("prefer_column_vectors", SBV_prefer_column_vectors, "true", 0, + 0, 1, prefer_column_vectors, + "prefer column/row vectors"); + + DEFVAR ("prefer_zero_one_indexing", SBV_prefer_zero_one_indexing, + "false", 0, 0, 1, prefer_zero_one_indexing, + "when there is a conflict, prefer zero-one style indexing"); + + DEFVAR ("print_answer_id_name", SBV_print_answer_id_name, "true", 0, + 0, 1, print_answer_id_name, + "set output style to print `var_name = ...'"); + + DEFVAR ("print_empty_dimensions", SBV_print_empty_dimensions, "true", + 0, 0, 1, print_empty_dimensions, + "also print dimensions of empty matrices"); + + DEFVAR ("propagate_empty_matrices", SBV_propagate_empty_matrices, + "true", 0, 0, 1, propagate_empty_matrices, + "operations on empty matrices return an empty matrix, not an error"); + + DEFVAR ("resize_on_range_error", SBV_resize_on_range_error, "true", 0, + 0, 1, resize_on_range_error, + "enlarge matrices on assignment"); + + DEFVAR ("return_last_computed_value", SBV_return_last_computed_value, + "false", 0, 0, 1, + return_last_computed_value, + "if a function does not return any values explicitly, return the\n\ + last computed value"); + + DEFVAR ("save_precision", SBV_save_precision, 17.0, 0, 0, 1, + set_save_precision, + "number of significant figures kept by the ASCII save command"); + + DEFVAR ("silent_functions", SBV_silent_functions, "false", 0, 0, 1, + silent_functions, + "suppress printing results in called functions"); + + DEFVAR ("split_long_rows", SBV_split_long_rows, "true", 0, 0, 1, + split_long_rows, + "split long matrix rows instead of wrapping"); + + DEFVAR ("stdin", SBV_stdin, 0.0, 0, 1, 1, 0, + "file number of the standard input stream"); + + DEFVAR ("stdout", SBV_stdout, 1.0, 0, 1, 1, 0, + "file number of the standard output stream"); + + DEFVAR ("stderr", SBV_stderr, 2.0, 0, 1, 1, 0, + "file number of the standard error stream"); + + DEFVAR ("treat_neg_dim_as_zero", SBV_treat_neg_dim_as_zero, "false", + 0, 0, 1, treat_neg_dim_as_zero, + "convert negative dimensions to zero"); + + DEFVAR ("warn_assign_as_truth_value", SBV_warn_assign_as_truth_value, + "true", 0, 0, 1, + warn_assign_as_truth_value, + "produce warning for assignments used as truth values"); + + DEFVAR ("warn_comma_in_global_decl", SBV_warn_comma_in_global_decl, + "true", 0, 0, 1, warn_comma_in_global_decl, + "produce warning for commas in global declarations"); + + DEFVAR ("warn_divide_by_zero", SBV_warn_divide_by_zero, "true", 0, 0, + 1, warn_divide_by_zero, + "on IEEE machines, allow divide by zero errors to be suppressed"); +} + +/* + * List variable names. + */ +static void +print_symbol_info_line (ostrstream& output_buf, const symbol_record_info& s) +{ + output_buf << (s.is_read_only () ? " -" : " w"); + output_buf << (s.is_eternal () ? "- " : "d "); +#if 0 + output_buf << (s.hides_fcn () ? "f" : (s.hides_builtin () ? "F" : "-")); +#endif + output_buf.form (" %-16s", s.type_as_string ()); + if (s.is_function ()) + output_buf << " - -"; + else + { + output_buf.form ("%7d", s.rows ()); + output_buf.form ("%7d", s.columns ()); + } + output_buf << " " << s.name () << "\n"; +} + +static void +print_long_listing (ostrstream& output_buf, symbol_record_info *s) +{ + if (! s) + return; + + symbol_record_info *ptr = s; + while (ptr->is_defined ()) + { + print_symbol_info_line (output_buf, *ptr); + ptr++; + } +} + +static int +maybe_list (const char *header, ostrstream& output_buf, + int show_verbose, symbol_table *sym_tab, unsigned type, + unsigned scope) +{ + int count; + int status = 0; + if (show_verbose) + { + symbol_record_info *symbols; + symbols = sym_tab->long_list (count, 1, type, scope); + if (symbols && count > 0) + { + output_buf << "\n" << header << "\n\n" + << "prot type rows cols name\n" + << "==== ==== ==== ==== ====\n"; + + print_long_listing (output_buf, symbols); + status = 1; + } + delete [] symbols; + } + else + { + char **symbols = sym_tab->list (count, 1, type, scope); + if (symbols && count > 0) + { + output_buf << "\n" << header << "\n\n"; + list_in_columns (output_buf, symbols); + status = 1; + } + delete [] symbols; + } + return status; +} + +DEFUN_TEXT ("clear", Fclear, Sclear, -1, 1, + "clear [name ...]\n\ +\n\ +clear symbol(s) matching a list of globbing patterns\n\ +if no arguments are given, clear all user-defined variables and functions") +{ + Octave_object retval; + + DEFINE_ARGV("clear"); + +// Always clear the local table, but don't clear currently compiled +// functions unless we are at the top level. (Allowing that to happen +// inside functions would result in pretty odd behavior...) + + int clear_user_functions = (curr_sym_tab == top_level_sym_tab); + + if (argc == 1) + { + curr_sym_tab->clear (); + global_sym_tab->clear (clear_user_functions); + } + else + { + int lcount; + char **lvars = curr_sym_tab->list (lcount, 0, + symbol_def::USER_VARIABLE, + SYMTAB_LOCAL_SCOPE); + int gcount; + char **gvars = curr_sym_tab->list (gcount, 0, + symbol_def::USER_VARIABLE, + SYMTAB_GLOBAL_SCOPE); + int fcount; + char **fcns = curr_sym_tab->list (fcount, 0, + symbol_def::USER_FUNCTION, + SYMTAB_ALL_SCOPES); + + while (--argc > 0) + { + argv++; + if (*argv) + { + int i; + for (i = 0; i < lcount; i++) + { + if (fnmatch (*argv, lvars[i], __FNM_FLAGS) == 0) + curr_sym_tab->clear (lvars[i]); + } + + int count; + for (i = 0; i < gcount; i++) + { + if (fnmatch (*argv, gvars[i], __FNM_FLAGS) == 0) + { + count = curr_sym_tab->clear (gvars[i]); + if (count > 0) + global_sym_tab->clear (gvars[i], clear_user_functions); + } + } + + for (i = 0; i < fcount; i++) + { + if (fnmatch (*argv, fcns[i], __FNM_FLAGS) == 0) + { + count = curr_sym_tab->clear (fcns[i]); + if (count > 0) + global_sym_tab->clear (fcns[i], clear_user_functions); + } + } + } + } + + delete [] lvars; + delete [] gvars; + delete [] fcns; + + } + + DELETE_ARGV; + + return retval; +} + +DEFUN_TEXT ("document", Fdocument, Sdocument, -1, 1, + "document symbol string ...\n\ +\n\ +Associate a cryptic message with a variable name.") +{ + Octave_object retval; + + DEFINE_ARGV("document"); + + if (argc == 3) + document_symbol (argv[1], argv[2]); + else + print_usage ("document"); + + DELETE_ARGV; + + return retval; +} + +static int +load_variable (char *nm, int force, istream& is) +{ +// Is there already a symbol by this name? If so, what is it? + + symbol_record *lsr = curr_sym_tab->lookup (nm, 0, 0); + + int is_undefined = 1; + int is_variable = 0; + int is_function = 0; + int is_global = 0; + + if (lsr) + { + is_undefined = ! lsr->is_defined (); + is_variable = lsr->is_variable (); + is_function = lsr->is_function (); + is_global = lsr->is_linked_to_global (); + } + +// Try to read data for this name. + + tree_constant tc; + int global = tc.load (is); + + if (tc.const_type () == tree_constant_rep::unknown_constant) + { + error ("load: unable to load variable `%s'", nm); + return 0; + } + + symbol_record *sr = 0; + + if (global) + { + if (is_global || is_undefined) + { + if (force || is_undefined) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + link_to_global_variable (lsr); + sr = lsr; + } + else + { + warning ("load: global variable name `%s' exists.", nm); + warning ("use `load -force' to overwrite"); + } + } + else if (is_function) + { + if (force) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + link_to_global_variable (lsr); + sr = lsr; + } + else + { + warning ("load: `%s' is currently a function in this scope", nm); + warning ("`load -force' will load variable and hide function"); + } + } + else if (is_variable) + { + if (force) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + link_to_global_variable (lsr); + sr = lsr; + } + else + { + warning ("load: local variable name `%s' exists.", nm); + warning ("use `load -force' to overwrite"); + } + } + else + panic_impossible (); + } + else + { + if (is_global) + { + if (force || is_undefined) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + link_to_global_variable (lsr); + sr = lsr; + } + else + { + warning ("load: global variable name `%s' exists.", nm); + warning ("use `load -force' to overwrite"); + } + } + else if (is_function) + { + if (force) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + link_to_global_variable (lsr); + sr = lsr; + } + else + { + warning ("load: `%s' is currently a function in this scope", nm); + warning ("`load -force' will load variable and hide function"); + } + } + else if (is_variable || is_undefined) + { + if (force || is_undefined) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + sr = lsr; + } + else + { + warning ("load: local variable name `%s' exists.", nm); + warning ("use `load -force' to overwrite"); + } + } + else + panic_impossible (); + } + + if (sr) + { + tree_constant *tmp_tc = new tree_constant (tc); + sr->define (tmp_tc); + return 1; + } + else + error ("load: unable to load variable `%s'", nm); + + return 0; +} + +DEFUN_TEXT ("load", Fload, Sload, -1, 1, + "load [-force] file\n +\n\ +load variables from a file") +{ + Octave_object retval; + + DEFINE_ARGV("load"); + + argc--; + argv++; + + int force = 0; + if (argc > 0 && strcmp (*argv, "-force") == 0) + { + force++; + argc--; + argv++; + } + + if (argc < 1) + { + error ("load: you must specify a single file to read"); + DELETE_ARGV; + return retval; + } + + static istream stream; + static ifstream file; + if (strcmp (*argv, "-") == 0) + { + stream = cin; + } + else + { + char *fname = tilde_expand (*argv); + file.open (fname); + if (! file) + { + error ("load: couldn't open input file `%s'", *argv); + DELETE_ARGV; + return retval; + } + stream = file; + } + + int count = 0; + char *nm = 0; + for (;;) + { +// Read name for this entry or break on EOF. + delete [] nm; + nm = extract_keyword (stream, "name"); + if (nm) + count++; + else + { + if (count == 0) + { + error ("load: no name keywords found in file `%s'", *argv); + error ("Are you sure this is an octave data file?"); + } + break; + } + + if (! *nm) + continue; + + if (! valid_identifier (nm)) + { + warning ("load: skipping bogus identifier `%s'"); + continue; + } + + load_variable (nm, force, stream); + + if (error_state) + { + error ("reading file %s", *argv); + break; + } + } + + if (file); + file.close (); + + DELETE_ARGV; + + return retval; +} + +/* + * Return nonzero if PATTERN has any special globbing chars in it. + */ +static int +glob_pattern_p (char *pattern) +{ + char *p = pattern; + char c; + int open = 0; + + while ((c = *p++) != '\0') + { + switch (c) + { + case '?': + case '*': + return 1; + + case '[': // Only accept an open brace if there is a close + open++; // brace to match it. Bracket expressions must be + continue; // complete, according to Posix.2 + + case ']': + if (open) + return 1; + continue; + + case '\\': + if (*p++ == '\0') + return 0; + + default: + continue; + } + } + + return 0; +} + +DEFUN_TEXT ("save", Fsave, Ssave, -1, 1, + "save file [var ...]\n\ +\n\ +save variables in a file") +{ + Octave_object retval; + +#if 0 + DEFINE_ARGV("save"); + + if (argc < 2) + { + print_usage ("save"); + DELETE_ARGV; + return retval; + } + + argc--; + argv++; + + static ostream stream; + static ofstream file; + if (strcmp (*argv, "-") == 0) + { +// XXX FIXME XXX -- should things intended for the screen end up in a +// tree_constant (string)? + stream = cout; + } + else if (argc == 1 && glob_pattern_p (*argv)) // Guard against things + { // like `save a*', + print_usage ("save"); // which are probably + DELETE_ARGV; // mistakes... + return retval; + } + else + { + char *fname = tilde_expand (*argv); + file.open (fname); + if (! file) + { + error ("save: couldn't open output file `%s'", *argv); + DELETE_ARGV; + return retval; + } + stream = file; + + } + + int prec = user_pref.save_precision; + + if (argc == 1) + { + int count; + char **vars = curr_sym_tab->list (count, 0, + symbol_def::USER_VARIABLE, + SYMTAB_ALL_SCOPES); + + for (int i = 0; i < count; i++) + curr_sym_tab->save (stream, vars[i], + is_globally_visible (vars[i]), prec); + + delete [] vars; + } + else + { + while (--argc > 0) + { + argv++; + + int count; + char **lvars = curr_sym_tab->list (count, 0, + symbol_def::USER_VARIABLE); + + int saved_or_error = 0; + int i; + for (i = 0; i < count; i++) + { + if (fnmatch (*argv, lvars[i], __FNM_FLAGS) == 0 + && curr_sym_tab->save (stream, lvars[i], + is_globally_visible (lvars[i]), + prec) != 0) + saved_or_error++; + } + + char **bvars = global_sym_tab->list (count, 0, + symbol_def::BUILTIN_VARIABLE); + + for (i = 0; i < count; i++) + { + if (fnmatch (*argv, bvars[i], __FNM_FLAGS) == 0 + && global_sym_tab->save (stream, bvars[i], 0, prec) != 0) + saved_or_error++; + } + + delete [] lvars; + delete [] bvars; + + if (! saved_or_error) + warning ("save: no such variable `%s'", *argv); + } + } + + if (file); + file.close (); + + DELETE_ARGV; +#endif + + 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"); + + int show_builtins = 0; + int show_functions = (curr_sym_tab == top_level_sym_tab); + int show_variables = 1; + int show_verbose = 0; + + if (argc > 1) + { + show_functions = 0; + show_variables = 0; + } + + for (int i = 1; i < argc; i++) + { + argv++; + if (strcmp (*argv, "-all") == 0 || strcmp (*argv, "-a") == 0) + { + show_builtins++; + show_functions++; + show_variables++; + } + else if (strcmp (*argv, "-builtins") == 0 + || strcmp (*argv, "-b") == 0) + show_builtins++; + else if (strcmp (*argv, "-functions") == 0 + || strcmp (*argv, "-f") == 0) + show_functions++; + else if (strcmp (*argv, "-long") == 0 + || strcmp (*argv, "-l") == 0) + show_verbose++; + else if (strcmp (*argv, "-variables") == 0 + || strcmp (*argv, "-v") == 0) + show_variables++; + else + warning ("who: unrecognized option `%s'", *argv); + } + +// If the user specified -l and nothing else, show variables. If +// evaluating this at the top level, also show functions. + + if (show_verbose && ! (show_builtins || show_functions || show_variables)) + { + show_functions = (curr_sym_tab == top_level_sym_tab); + show_variables = 1; + } + + ostrstream output_buf; + int pad_after = 0; + + if (show_builtins) + { + pad_after += maybe_list ("*** built-in variables:", + output_buf, show_verbose, global_sym_tab, + symbol_def::BUILTIN_VARIABLE, + SYMTAB_ALL_SCOPES); + + pad_after += maybe_list ("*** built-in functions:", + output_buf, show_verbose, global_sym_tab, + symbol_def::BUILTIN_FUNCTION, + SYMTAB_ALL_SCOPES); + } + + if (show_functions) + { + pad_after += maybe_list ("*** currently compiled functions:", + output_buf, show_verbose, global_sym_tab, + symbol_def::USER_FUNCTION, + SYMTAB_ALL_SCOPES); + } + + if (show_variables) + { + pad_after += maybe_list ("*** local user variables:", + output_buf, show_verbose, curr_sym_tab, + symbol_def::USER_VARIABLE, + SYMTAB_LOCAL_SCOPE); + + pad_after += maybe_list ("*** globally visible user variables:", + output_buf, show_verbose, curr_sym_tab, + symbol_def::USER_VARIABLE, + SYMTAB_GLOBAL_SCOPE); + } + + if (pad_after) + output_buf << "\n"; + + output_buf << ends; + maybe_page_output (output_buf); + + DELETE_ARGV; + + return retval; +} + +// XXX FIXME XXX -- should these really be here? + +char * +octave_home (void) +{ +#ifdef RUN_IN_PLACE + static char *home = OCTAVE_HOME; + return home; +#else + static char *home = 0; + delete [] home; + char *oh = getenv ("OCTAVE_HOME"); + if (oh) + home = strsave (oh); + else + home = strsave (OCTAVE_HOME); + return home; +#endif +} + +char * +octave_lib_dir (void) +{ +#ifdef RUN_IN_PLACE + static char *ol = OCTAVE_LIB_DIR; + return ol; +#else + static char *ol = 0; + delete [] ol; + char *oh = octave_home (); + char *tmp = strconcat (oh, "/lib/octave/"); + ol = strconcat (tmp, version_string); + delete [] tmp; + return ol; +#endif +} + +char * +octave_info_dir (void) +{ +#ifdef RUN_IN_PLACE + static char *oi = OCTAVE_INFO_DIR; + return oi; +#else + static char *oi = 0; + delete [] oi; + char *oh = octave_home (); + oi = strconcat (oh, "/info/"); + return oi; +#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. + */ +char * +default_path (void) +{ + static char *pathstring = 0; + delete [] pathstring; + + static char *std_path = 0; + delete [] std_path; + + char *libdir = octave_lib_dir (); + + std_path = strconcat (".:", libdir); + + char *oct_path = getenv ("OCTAVE_PATH"); + + if (oct_path) + { + pathstring = strsave (oct_path); + + if (pathstring[0] == ':') + { + char *tmp = pathstring; + pathstring = strconcat (std_path, pathstring); + delete [] tmp; + } + + int tmp_len = strlen (pathstring); + if (pathstring[tmp_len-1] == ':') + { + char *tmp = pathstring; + pathstring = strconcat (pathstring, std_path); + delete [] tmp; + } + } + else + pathstring = strsave (std_path); + + return pathstring; +} + +char * +default_info_file (void) +{ + static char *info_file_string = 0; + delete [] info_file_string; + char *oct_info_file = getenv ("OCTAVE_INFO_FILE"); + if (oct_info_file) + info_file_string = strsave (oct_info_file); + else + { + char *infodir = octave_info_dir (); + info_file_string = strconcat (infodir, "/octave.info"); + } + return info_file_string; +} + +char * +default_editor (void) +{ + static char *editor_string = 0; + delete [] editor_string; + char *env_editor = getenv ("EDITOR"); + if (env_editor && *env_editor) + editor_string = strsave (env_editor); + else + editor_string = strsave ("vi"); + return editor_string; +} + +char * +get_site_defaults (void) +{ + static char *sd = 0; + delete [] sd; + char *libdir = octave_lib_dir (); + sd = strconcat (libdir, "/octaverc"); + return sd; +} + +char * +default_pager (void) +{ + static char *pager_binary = 0; + delete [] pager_binary; + char *pgr = getenv ("PAGER"); + if (pgr) + pager_binary = strsave (pgr); + else +#ifdef DEFAULT_PAGER + pager_binary = strsave (DEFAULT_PAGER); +#else + pager_binary = strsave (""); +#endif + + return pager_binary; +} + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/src/variables.h b/src/variables.h --- a/src/variables.h +++ b/src/variables.h @@ -25,18 +25,42 @@ #define octave_variables_h 1 class istream; +class ostrstream; class symbol_record; class symbol_table; class tree; class tree_fvc; class tree_constant; +class Octave_object; -struct builtin_mapper_functions; -struct builtin_text_functions; -struct builtin_general_functions; -struct builtin_string_variables; +struct builtin_mapper_function; +struct builtin_function; +struct builtin_variable; + +typedef int (*sv_Function)(void); -#include "builtins.h" +struct builtin_variable +{ + char *name; + tree_constant *value; + int install_as_function; + int protect; + int eternal; + sv_Function sv_function; + char *help_string; +}; + +typedef Octave_object (*Octave_builtin_fcn)(const Octave_object&, int); + +struct builtin_function +{ + char *name; + int nargin_max; + int nargout_max; + int is_text_fcn; + Octave_builtin_fcn fcn; + char *help_string; +}; extern void initialize_symbol_tables (void); @@ -44,18 +68,17 @@ extern void document_symbol (const char *name, const char *help); -extern void install_builtin_mapper_function (builtin_mapper_functions *mf); - -extern void install_builtin_text_function (builtin_text_functions *tf); +extern void install_builtin_mapper (builtin_mapper_function *mf); -extern void install_builtin_general_function (builtin_general_functions *gf); +extern void install_builtin_function (builtin_function *gf); -extern void install_builtin_variable (builtin_string_variables *sv); +extern void install_builtin_variable (builtin_variable *v); extern void install_builtin_variable_as_function (const char *name, tree_constant *val, int protect = 0, - int eternal = 0); + int eternal = 0, + const char *help = 0); extern void bind_nargin_and_nargout (symbol_table *sym_tab, int nargin, int nargout); @@ -63,7 +86,7 @@ extern void bind_builtin_variable (const char *, tree_constant *, int protect = 0, int eternal = 0, sv_Function f = (sv_Function) 0, - const char *help = (char *) 0); + const char *help = 0); extern char *builtin_string_variable (const char *); extern int builtin_real_scalar_variable (const char *, double&); @@ -83,10 +106,39 @@ extern int valid_identifier (char *); extern int identifier_exists (char *); extern int is_builtin_variable (const char *name); -extern tree_fvc *is_valid_function (tree_constant&, char *, int warn = 0); +extern tree_fvc *is_valid_function (const tree_constant&, char *, + int warn = 0); extern int takes_correct_nargs (tree_fvc *, int, char *, int warn = 0); extern char **make_name_list (void); +extern int is_text_function_name (const char *s); + +struct help_list; + +extern help_list *builtin_mapper_functions_help (void); +extern help_list *builtin_general_functions_help (void); +extern help_list *builtin_text_functions_help (void); +extern help_list *builtin_variables_help (void); + +extern int help_from_list (ostrstream& output_buf, + const help_list *list, const char *string, + int usage); + +extern void additional_help_message (ostrstream& output_buf); + +extern void print_usage (const char *s, int just_usage = 0); + +extern void install_builtin_variables (void); + +extern char *octave_home (void); +extern char *octave_lib_dir (void); +extern char *octave_info_dir (void); +extern char *default_path (void); +extern char *default_info_file (void); +extern char *default_editor (void); +extern char *get_site_defaults (void); +extern char *default_pager (void); + // Symbol table for symbols at the top level. extern symbol_table *top_level_sym_tab;