Mercurial > hg > octave-lyh
changeset 3665:0689afb1d001
[project @ 2000-05-11 19:07:56 by jwe]
author | jwe |
---|---|
date | Thu, 11 May 2000 19:10:09 +0000 |
parents | d178e2bbd873 |
children | 301e0da5b455 |
files | liboctave/Array-d.cc liboctave/Array-idx-vec.cc liboctave/Array.h liboctave/Array2.cc liboctave/Array2.h liboctave/Array3.h liboctave/ArrayN-idx.h liboctave/ArrayN.cc liboctave/ArrayN.h liboctave/ChangeLog liboctave/Makefile.in src/ChangeLog src/Makefile.in src/comment-list.cc src/comment-list.h src/data.cc src/lex.l src/ov-base-nd-array.cc src/ov-base-nd-array.h src/ov-re-nd-array.cc src/ov-re-nd-array.h src/ov-usr-fcn.cc src/ov-usr-fcn.h src/parse.y src/pt-except.cc src/pt-except.h src/pt-loop.cc src/pt-loop.h src/pt-pr-code.cc src/pt-pr-code.h src/pt-select.cc src/pt-select.h src/pt-stmt.cc src/pt-stmt.h |
diffstat | 34 files changed, 2507 insertions(+), 163 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/Array-d.cc +++ b/liboctave/Array-d.cc @@ -46,6 +46,12 @@ template int assign (Array2<double>&, const Array2<short>&); template int assign (Array2<double>&, const Array2<char>&); +#include "ArrayN.h" +#include "ArrayN.cc" + +template class ArrayN<double>; +template std::ostream& operator << (std::ostream&, const ArrayN<double>&); + #include "DiagArray2.h" #include "DiagArray2.cc"
new file mode 100644 --- /dev/null +++ b/liboctave/Array-idx-vec.cc @@ -0,0 +1,40 @@ +/* + +Copyright (C) 1996, 1997 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +// Instantiate Arrays of integer values. + +#include "idx-vector.h" + +#include "Array.h" +#include "Array.cc" + +template class Array<idx_vector>; + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
--- a/liboctave/Array.h +++ b/liboctave/Array.h @@ -164,6 +164,9 @@ int capacity (void) const { return rep->length (); } int length (void) const { return rep->length (); } + T range_error (const char *fcn, int n) const; + T& range_error (const char *fcn, int n); + // No checking, even for multiple references, ever. T& xelem (int n) { return rep->elem (n); } @@ -228,9 +231,6 @@ return *this; } - T range_error (const char *fcn, int n) const; - T& range_error (const char *fcn, int n); - #ifdef HEAVYWEIGHT_INDEXING void set_max_indices (int mi) { max_indices = mi; } @@ -251,7 +251,8 @@ }; template <class LT, class RT> -int assign (Array<LT>& lhs, const Array<RT>& rhs); +int +assign (Array<LT>& lhs, const Array<RT>& rhs); #endif
--- a/liboctave/Array2.cc +++ b/liboctave/Array2.cc @@ -42,6 +42,8 @@ #include "lo-error.h" +// Two dimensional array class. + template <class T> int Array2<T>::get_size (int r, int c) const @@ -106,8 +108,6 @@ return foo; } -// Two dimensional array class. - template <class T> void Array2<T>::resize (int r, int c)
--- a/liboctave/Array2.h +++ b/liboctave/Array2.h @@ -120,6 +120,9 @@ int cols (void) const { return d2; } int columns (void) const { return d2; } + T range_error (const char *fcn, int i, int j) const; + T& range_error (const char *fcn, int i, int j); + // No checking of any kind, ever. T& xelem (int i, int j) { return Array<T>::xelem (d1*j+i); } @@ -132,12 +135,7 @@ T& checkelem (int i, int j) { if (i < 0 || j < 0 || i >= d1 || j >= d2) - { - (*current_liboctave_error_handler) - ("T& Array2<T>::checkelem (%d, %d): range error", i, j); - static T foo; - return foo; - } + return range_error ("T& Array2<T>::checkelem", i, j); else return Array<T>::elem (d1*j+i); } @@ -153,11 +151,7 @@ T checkelem (int i, int j) const { if (i < 0 || j < 0 || i >= d1 || j >= d2) - { - (*current_liboctave_error_handler) - ("T Array2<T>::checkelem (%d, %d): range error", i, j); - return T (); - } + return range_error ("T Array2<T>::checkelem", i, j); else return Array<T>::elem (d1*j+i); } @@ -170,9 +164,6 @@ T operator () (int i, int j) const { return elem (i, j); } #endif - T range_error (const char *fcn, int i, int j) const; - T& range_error (const char *fcn, int i, int j); - void resize (int n, int m); void resize (int n, int m, const T& val); @@ -196,7 +187,8 @@ }; template <class LT, class RT> -int assign (Array2<LT>& lhs, const Array2<RT>& rhs); +int +assign (Array2<LT>& lhs, const Array2<RT>& rhs); #endif
--- a/liboctave/Array3.h +++ b/liboctave/Array3.h @@ -157,7 +157,8 @@ }; template <class LT, class RT> -int assign (Array3<LT>& lhs, const Array3<RT>& rhs); +int +assign (Array3<LT>& lhs, const Array3<RT>& rhs); #endif
new file mode 100644 --- /dev/null +++ b/liboctave/ArrayN-idx.h @@ -0,0 +1,270 @@ +// Template array classes +/* + +Copyright (C) 2000 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "Array-flags.h" +#include "idx-vector.h" +#include "lo-error.h" + +template <class T> +void +ArrayN<T>::maybe_delete_elements (Array<idx_vector>&) +{ + assert (0); +} + +template <class T> +ArrayN<T> +ArrayN<T>::value (void) +{ + ArrayN<T> retval; + + int n_idx = index_count (); + + if (n_idx > 1) + { + Array<idx_vector> idx (n_idx); + + idx_vector *tmp = get_idx (); + + for (int i = 0; i < n_idx; i++) + idx(i) = tmp[i]; + + return index (idx); + } + else if (n_idx == 1) + { + idx_vector *tmp = get_idx (); + + idx_vector idx = tmp[0]; + + return index (idx); + } + else + (*current_liboctave_error_handler) + ("invalid number of indices for array expression"); + + clear_index (); + + return retval; +} + +template <class T> +ArrayN<T> +ArrayN<T>::index (idx_vector& idx) const +{ + ArrayN<T> retval; + assert (0); + return retval; +} + +static Array<int> +freeze (Array<idx_vector>& idx, const Array<int>& dimensions) +{ + Array<int> retval; + + int n = idx.length (); + + assert (n == dimensions.length ()); + + retval.resize (n); + + for (int i = 0; i < n; i++) + retval(i) = idx(i).freeze (dimensions(i), "XXX FIXME XXX"); + + return retval; +} + +static bool +all_ok (const Array<idx_vector>& idx) +{ + bool retval = true; + + int n = idx.length (); + + for (int i = 0; i < n; i++) + { + if (! idx(i)) + { + retval = false; + break; + } + } + + return retval; +} + +static bool +any_orig_empty (const Array<idx_vector>& idx) +{ + bool retval = false; + + int n = idx.length (); + + for (int i = 0; i < n; i++) + { + if (idx(i).orig_empty ()) + { + retval = true; + break; + } + } + + return retval; +} + +static bool +any_zero_len (const Array<int>& frozen_lengths) +{ + bool retval = false; + + int n = frozen_lengths.length (); + + for (int i = 0; i < n; i++) + { + if (frozen_lengths(i) == 0) + { + retval = true; + break; + } + } + + return retval; +} + +static Array<int> +get_zero_len_size (const Array<int>& frozen_lengths, + const Array<int>& dimensions) +{ + Array<int> retval; + assert (0); + return retval; +} + +static bool +all_colon_equiv (const Array<idx_vector>& idx, + const Array<int>& frozen_lengths) +{ + bool retval = true; + + int idx_n = idx.length (); + + int n = frozen_lengths.length (); + + assert (idx_n == n); + + for (int i = 0; i < n; i++) + { + if (! idx(i).is_colon_equiv (frozen_lengths(i))) + { + retval = false; + break; + } + } + + return retval; +} + +static Array<int> +get_elt_idx (const Array<idx_vector>& idx, const Array<int>& result_idx) +{ + int n = idx.length (); + + Array<int> retval (n); + + for (int i = 0; i < n; i++) + retval(i) = idx(result_idx(i)); + + return retval; +} + +template <class T> +ArrayN<T> +ArrayN<T>::index (Array<idx_vector>& idx) const +{ + ArrayN<T> retval; + + int n_dims = dimensions.length (); + + Array<int> frozen_lengths = freeze (idx, dimensions); + + if (frozen_lengths.length () == n_dims) + { + if (all_ok (idx)) + { + if (any_orig_empty (idx)) + { + retval.resize (frozen_lengths); + } + else if (any_zero_len (frozen_lengths)) + { + Array<int> new_size = get_zero_len_size (frozen_lengths, + dimensions); + + retval.resize (new_size); + } + else if (all_colon_equiv (idx, frozen_lengths)) + { + retval = *this; + } + else + { +#if 0 + retval.resize (frozen_lengths); + + int n = Array<T>::get_size (frozen_lengths); + + Array<int> result_idx (n_dims, 0); + + for (int i = 0; i < n; i++) + { + Array<int> elt_idx = get_elt_idx (result_idx); + + retval.elem (result_idx) = elem (elt_idx); + + increment_index (result_idx, frozen_lengths); + } +#endif + } + } + // idx_vector::freeze() printed an error message for us. + } + else + (*current_liboctave_error_handler) + ("invalid number of dimensions for N-dimensional array index"); + + return retval; +} + +template <class LT, class RT> +int +assign (ArrayN<LT>&, const ArrayN<RT>&) +{ + assert (0); + return 0; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
new file mode 100644 --- /dev/null +++ b/liboctave/ArrayN.cc @@ -0,0 +1,379 @@ +// Template array classes +/* + +Copyright (C) 2000 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if defined (__GNUG__) +#pragma implementation +#endif + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <cassert> + +#include <iostream> + +#include "ArrayN.h" + +#if defined (HEAVYWEIGHT_INDEXING) +#include "idx-vector.h" +#include "ArrayN-idx.h" +#endif + +#include "lo-error.h" + +// N-dimensional array class. + +template <class T> +int +ArrayN<T>::compute_index (const Array<int>& idx) const +{ + int retval = -1; + + int n = dimensions.length (); + + if (n > 0 && n == idx.length ()) + { + retval = idx(--n); + + while (--n >= 0) + { + retval *= dimensions(n); + retval += idx(n); + } + } + else + (*current_liboctave_error_handler) + ("ArrayN<T>::compute_index: invalid indexing operation"); + + return retval; +} + +template <class T> +int +ArrayN<T>::get_size (const Array<int>& idx) +{ + // XXX KLUGE XXX + + // If an allocation of an array with r * c elements of type T + // would cause an overflow in the allocator when computing the + // size of the allocation, then return a value which, although + // not equivalent to the actual request, should be too large for + // most current hardware, but not so large to cause the + // allocator to barf on computing retval * sizeof (T). + + // A guess (should be quite conservative). + static const int MALLOC_OVERHEAD = 1024; + + static int nl; + static double dl + = frexp (static_cast<double> + (INT_MAX - MALLOC_OVERHEAD) / sizeof (T), &nl); + + // This value should be an integer. If we return this value and + // things work the way we expect, we should be paying a visit to + // new_handler in no time flat. + static int max_items = static_cast<int> (ldexp (dl, nl)); + + int retval = max_items; + + int n = idx.length (); + + int nt = 0; + double dt = 1; + + for (int i = 0; i < n; i++) + { + int nidx; + double didx = frexp (static_cast<double> (idx(i)), &nidx); + + nt += nidx; + dt *= didx; + } + + if (dt <= 0.5) + { + nt--; + dt *= 2; + + if (dt <= 0.5) + nt--; + } + + if (nt < nl || (nt == nl && dt < dl)) + { + retval = 1; + + for (int i = 0; i < n; i++) + retval *= idx(i); + } + + return retval; +} + +template <class T> +T +ArrayN<T>::range_error (const char *fcn, const Array<int>& idx) const +{ + // XXX FIXME XXX -- report index values too! + + (*current_liboctave_error_handler) ("range error"); + + return T (); +} + +template <class T> +T& +ArrayN<T>::range_error (const char *fcn, const Array<int>& idx) +{ + // XXX FIXME XXX -- report index values too! + + (*current_liboctave_error_handler) ("range error"); + + static T foo; + return foo; +} + +static inline bool +index_in_bounds (const Array<int>& idx, const Array<int>& dimensions) +{ + bool retval = true; + + int n = idx.length (); + + if (n == dimensions.length ()) + { + for (int i = 0; i < n; i++) + { + if (idx(i) < 0 || idx(i) >= dimensions (i)) + { + retval = false; + break; + } + } + } + else + retval = false; + + return retval; +} + +static inline void +increment_index (Array<int>& idx, const Array<int>& dimensions) +{ + idx(0)++; + + int n = idx.length () - 1; + + for (int i = 0; i < n; i++) + { + if (idx(i) < dimensions(i)) + break; + else + { + idx(i) = 0; + idx(i+1)++; + } + } +} + +template <class T> +void +ArrayN<T>::resize (const Array<int>& dims) +{ + int n = dims.length (); + + for (int i = 0; i < n; i++) + { + if (dims(i) < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + } + + bool no_change = true; + + for (int i = 0; i < n; i++) + { + if (dims(i) != dimensions(i)) + { + no_change = false; + break; + } + } + + if (no_change) + return; + + Array<T>::ArrayRep *old_rep = rep; + const T *old_data = data (); + + rep = new Array<T>::ArrayRep (get_size (dims)); + + Array<int> old_dimensions = dimensions; + + int old_len = length (); + + dimensions = dims; + + Array<int> idx (dimensions.length (), 0); + + for (int i = 0; i < old_len; i++) + { + if (index_in_bounds (idx, dimensions)) + xelem (idx) = old_data[i]; + + increment_index (idx, dimensions); + } + + if (--old_rep->count <= 0) + delete old_rep; +} + +template <class T> +void +ArrayN<T>::resize (const Array<int>& dims, const T& val) +{ + int n = dims.length (); + + for (int i = 0; i < n; i++) + { + if (dims(i) < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + } + + bool no_change = true; + + for (int i = 0; i < n; i++) + { + if (dims(i) != dimensions(i)) + { + no_change = false; + break; + } + } + + if (no_change) + return; + + Array<T>::ArrayRep *old_rep = rep; + const T *old_data = data (); + + int len = get_size (dims); + + rep = new Array<T>::ArrayRep (len); + + Array<int> old_dimensions = dimensions; + + int old_len = length (); + + dimensions = dims; + + Array<int> idx (dimensions.length (), 0); + + for (int i = 0; i < len; i++) + rep->elem (i) = val; + + for (int i = 0; i < old_len; i++) + { + if (index_in_bounds (idx, dimensions)) + xelem (idx) = old_data[i]; + + increment_index (idx, dimensions); + } + + if (--old_rep->count <= 0) + delete old_rep; +} + +template <class T> +ArrayN<T>& +ArrayN<T>::insert (const ArrayN<T>& a, const Array<int>& idx) +{ + int n = idx.length (); + + if (n == dimensions.length ()) + { + Array<int> a_dims = a.dims (); + + for (int i = 0; i < n; i++) + { + if (idx(i) < 0 || idx(i) + a_dims(i) > dimensions(i)) + { + (*current_liboctave_error_handler) + ("ArrayN<T>::insert: range error for insert"); + return *this; + } + } + +#if 0 + // XXX FIXME XXX -- need to copy elements + + for (int j = 0; j < a_cols; j++) + for (int i = 0; i < a_rows; i++) + elem (r+i, c+j) = a.elem (i, j); +#endif + + } + else + (*current_liboctave_error_handler) + ("ArrayN<T>::insert: invalid indexing operation"); + + return *this; +} + +template <class T> +std::ostream& +operator << (std::ostream& os, const ArrayN<T>& a) +{ + Array<int> dims = a.dimensions; + + int n_dims = dims.length (); + + os << n_dims << "-dimensional array ("; + + for (int i = 0; i < n_dims - 1; i++) + os << dims(i) << "x"; + os << dims(n_dims-1) << ")\n\n"; + + os << "data:\n"; + + int n = ArrayN<T>::get_size (dims); + + // for (int i = 0; i < n; i++) + // os << a.elem (i) << "\n"; + + return os; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
new file mode 100644 --- /dev/null +++ b/liboctave/ArrayN.h @@ -0,0 +1,202 @@ +// Template array classes +/* + +Copyright (C) 2000 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_ArrayN_h) +#define octave_ArrayN_h 1 + +#if defined (__GNUG__) +#pragma interface +#endif + +#include <iostream> + +#include <cassert> +#include <climits> +#include <cmath> +#include <cstdlib> + +#include "Array.h" +#include "lo-error.h" + +class idx_vector; + +// N-dimensional array class. + +template <class T> +class +ArrayN : public Array<T> +{ +protected: + + ArrayN (T *d, const Array<int>& dims) : Array<T> (d, get_size (dims)) + { + dimensions = dims; + set_max_indices (dimensions.length ()); + } + +public: + + static int get_size (const Array<int>& dims); + + // These really need to be protected (and they will be in the + // future, so don't depend on them being here!), but they can't be + // until template friends work correctly in g++. + + Array<int> dimensions; + + ArrayN (void) : Array<T> () { } + + ArrayN (const Array<int>& dims) : Array<T> (get_size (dims)) + { + dimensions = dims; + set_max_indices (dimensions.length ()); + } + + ArrayN (const Array<int>& dims, const T& val) + : Array<T> (get_size (dims), val) + { + dimensions = dims; + set_max_indices (dimensions.length ()); + } + + ArrayN (const ArrayN<T>& a) : Array<T> (a) + { + dimensions = a.dimensions; + set_max_indices (dimensions.length ()); + } + + ArrayN (const Array<T>& a, const Array<int>& dims) : Array<T> (a) + { + dimensions = dims; + set_max_indices (dimensions.length ()); + } + + ~ArrayN (void) { } + + ArrayN<T>& operator = (const ArrayN<T>& a) + { + if (this != &a && rep != a.rep) + { + Array<T>::operator = (a); + dimensions = a.dimensions; + } + + return *this; + } + + int compute_index (const Array<int>& idx) const; + + Array<int> dims (void) const { return dimensions; } + + T range_error (const char *fcn, const Array<int>& idx) const; + T& range_error (const char *fcn, const Array<int>& idx); + + // No checking of any kind, ever. + + T& xelem (const Array<int>& idx) + { return Array<T>::xelem (compute_index (idx)); } + + T xelem (const Array<int>& idx) const + { return Array<T>::xelem (compute_index (idx)); } + + // Note that the following element selection methods don't use + // xelem() because they need to make use of the code in + // Array<T>::elem() that checks the reference count. + + T& checkelem (const Array<int>& idx) + { + int i = compute_index (idx); + + if (i < 0) + return range_error ("ArrayN<T>::checkelem", idx); + else + return Array<T>::elem (i); + } + + T& elem (const Array<int>& idx) + { + int i = compute_index (idx); + + return Array<T>::elem (i); + } + +#if defined (BOUNDS_CHECKING) + T& operator () (const Array<int>& idx) { return checkelem (idx); } +#else + T& operator () (const Array<int>& idx) { return elem (idx); } +#endif + + T checkelem (const Array<int>& idx) const + { + int i = compute_index (idx); + + if (i < 0) + return range_error ("ArrayN<T>::checkelem", idx); + else + return Array<T>::elem (i); + } + + T elem (const Array<int>& idx) const + { + int i = compute_index (idx); + + return Array<T>::elem (i); + } + +#if defined (BOUNDS_CHECKING) + T operator () (const Array<int>& idx) const { return checkelem (idx); } +#else + T operator () (const Array<int>& idx) const { return elem (idx); } +#endif + + void resize (const Array<int>& dims); + void resize (const Array<int>& dims, const T& val); + + ArrayN<T>& insert (const ArrayN<T>& a, const Array<int>& dims); + +#ifdef HEAVYWEIGHT_INDEXING + void maybe_delete_elements (Array<idx_vector>& idx); + + ArrayN<T> value (void); + + ArrayN<T> index (idx_vector& idx) const; + + ArrayN<T> index (Array<idx_vector>& idx) const; +#endif +}; + +template <class LT, class RT> +int +assign (ArrayN<LT>& lhs, const ArrayN<RT>& rhs); + +template <class T> +std::ostream& +operator << (std::ostream&, const ArrayN<T>&); + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,9 @@ +2000-05-11 John W. Eaton <jwe@bevo.che.wisc.edu> + + * Array-d.cc: Instantiate ArrayN<double> here too. + * Array-idx-vec.cc, ArrayN-idx.h, ArrayN.cc, ArrayN.h: New files. + * Makefile.in: Add them to the appropriate lists. + 2000-04-06 John W. Eaton <jwe@bevo.che.wisc.edu> * Array.cc (Array<T>::operator =): Don't set max_indices to 1 here.
--- a/liboctave/Makefile.in +++ b/liboctave/Makefile.in @@ -23,7 +23,7 @@ LIBOCTAVE_LIBS = -lcruft -lreadline -lkpathsea -lglob -MATRIX_INC := Array.h Array2.h Array3.h DiagArray2.h Array-flags.h \ +MATRIX_INC := Array.h Array2.h Array3.h ArrayN.h DiagArray2.h Array-flags.h \ Array-idx.h Array2-idx.h Array3-idx.h MArray-defs.h \ MArray.h MArray2.h MDiagArray2.h Matrix.h \ base-lu.h mx-base.h mx-op-defs.h mx-defs.h mx-ext.h \ @@ -59,11 +59,11 @@ $(MX_OP_INC) \ $(VX_OP_INC) -TEMPLATE_SRC := Array.cc Array2.cc Array3.cc DiagArray2.cc \ +TEMPLATE_SRC := Array.cc Array2.cc Array3.cc ArrayN.cc DiagArray2.cc \ MArray.cc MArray2.cc MDiagArray2.cc base-lu.cc TI_SRC := Array-C.cc Array-b.cc Array-ch.cc Array-i.cc Array-d.cc \ - Array-s.cc Array-str.cc \ + Array-s.cc Array-str.cc Array-idx-vec.cc \ MArray-C.cc MArray-ch.cc MArray-i.cc MArray-d.cc MArray-s.cc MATRIX_SRC := Array-flags.cc CColVector.cc CDiagMatrix.cc CMatrix.cc \
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,38 @@ +2000-05-11 John W. Eaton <jwe@bevo.che.wisc.edu> + + * ov-base-nd-array.h, ov-base-nd-array.cc, ov-re-nd-array.h, + ov-re-nd-array.h: New files. + * Makefile.in: Add them to the appropriate lists. + + * pt-stmt.h, pt-stmt.cc (class tree_statement): + Store comments associated with this parse tree element. + * pt-select.h, pt-select.cc (class tree_if_clause, + class tree_if_command, class tree_switch_case + class tree_switch_command): Likewise. + * pt-loop.h, pt-loop.cc (class tree_while_command, + class tree_do_until_command, class tree_simple_for_command, + class tree_complex_for_command): Likewise. + * pt-except.h, pt-except.cc (class tree_try_catch_command, + class tree_unwind_protect_command): Likewise. + * ov-usr-fcn.h, ov-usr-fcn.cc (class octave_user_function): Likewise. + * pt-pr-code.h, pt-pr-code.cc (tree_print_code::print_comment_elt, + tree_print_code::print_comment_list, + tree_print_code::print_indented_comment): New functions. + (tree_print_code::visit_simple_for_command, + tree_print_code::visit_complex_for_command, + tree_print_code::visit_octave_user_function_header, + tree_print_code::visit_octave_user_function_trailer, + tree_print_code::visit_if_command, tree_print_code::visit_statement, + tree_print_code::visit_switch_case, + tree_print_code::visit_switch_command, + tree_print_code::visit_try_catch_command, + tree_print_code::visit_unwind_protect_command + tree_print_code::visit_while_command, + tree_print_code::visit_do_until_command): Handle comments. + * lex.l, parse.y: Handle comments in parse trees. + * comment-list.h, comment-list.cc: New files. + * Makefile.in: Add them to the appropriate lists. + 2000-04-23 etienne grossmann <etienne@anonimo.isr.ist.utl.pt> * pt-mat.cc (tm_row_const::tm_row_const_rep::eval_error):
--- a/src/Makefile.in +++ b/src/Makefile.in @@ -69,7 +69,7 @@ ov-colon.h ov-base.h ov-base-mat.h ov-base-scalar.h \ ov-str-mat.h ov-bool-mat.h ov-bool.h ov-file.h ov-cell.h ov.h \ ov-fcn.h ov-builtin.h ov-dld-fcn.h ov-mapper.h ov-usr-fcn.h \ - ov-typeinfo.h + ov-base-nd-array.h ov-re-nd-array.h ov-typeinfo.h PT_INCLUDES := pt.h pt-all.h pt-arg-list.h pt-assign.h pt-binop.h \ pt-cell.h pt-check.h pt-cmd.h pt-colon.h pt-const.h pt-decl.h \ @@ -78,7 +78,7 @@ pt-pr-code.h pt-select.h pt-stmt.h pt-unop.h pt-walk.h INCLUDES := BaseSLList.h Cell.h DLList.h Map.h Pix.h SLList.h \ - SLStack.h Stack.h c-file-ptr-stream.h defun-dld.h \ + SLStack.h Stack.h c-file-ptr-stream.h comment-list.h defun-dld.h \ defun-int.h defun.h dirfns.h dynamic-ld.h error.h file-io.h \ fn-cache.h gripes.h help.h input.h lex.h load-save.h \ oct-fstrm.h oct-hist.h oct-iostrm.h oct-map.h oct-obj.h \ @@ -111,7 +111,8 @@ ov-complex.cc ov-str-mat.cc ov-struct.cc ov-va-args.cc \ ov-colon.cc ov-bool-mat.cc ov-bool.cc ov-file.cc ov-cell.cc \ ov.cc ov-fcn.cc ov-builtin.cc ov-dld-fcn.cc ov-mapper.cc \ - ov-usr-fcn.cc ov-typeinfo.cc + ov-usr-fcn.cc ov-base-nd-array.cc ov-re-nd-array.cc \ + ov-typeinfo.cc PT_SRC := pt.cc pt-arg-list.cc pt-assign.cc pt-binop.cc pt-cell.cc \ pt-check.cc pt-cmd.cc pt-colon.cc pt-const.cc pt-decl.cc \ @@ -120,7 +121,8 @@ pt-select.cc pt-stmt.cc pt-unop.cc DIST_SRC := BaseSLList.cc Cell.cc DLList.cc Map.cc SLList.cc \ - SLStack.cc Stack.cc c-file-ptr-stream.cc cutils.c data.cc \ + SLStack.cc Stack.cc c-file-ptr-stream.cc comment-list.cc \ + cutils.c data.cc \ defaults.cc defun.cc dirfns.cc dynamic-ld.cc error.cc \ file-io.cc fn-cache.cc gripes.cc help.cc input.cc lex.l \ load-save.cc mappers.cc matherr.c oct-fstrm.cc oct-hist.cc \
new file mode 100644 --- /dev/null +++ b/src/comment-list.cc @@ -0,0 +1,101 @@ +/* + +Copyright (C) 2000 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if defined (__GNUG__) +#pragma implementation +#endif + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "lo-utils.h" + +#include "comment-list.h" +#include "error.h" + +#include "SLList.h" +#include "SLList.cc" + +template SLList<octave_comment_elt>; + +octave_comment_buffer *octave_comment_buffer::instance = 0; + +bool +octave_comment_buffer::instance_ok (void) +{ + bool retval = true; + + if (! instance) + instance = new octave_comment_buffer (); + + if (! instance) + { + ::error ("unable to create comment buffer object"); + + retval = false; + } + + return retval; +} + +void +octave_comment_buffer::append (const std::string& s, + octave_comment_elt::comment_type t) +{ + if (instance_ok ()) + instance->do_append (s, t); +} + + +octave_comment_list * +octave_comment_buffer::get_comment (void) +{ + return (instance_ok ()) ? instance->do_get_comment () : 0; +} + +void +octave_comment_buffer::do_append (const std::string& s, + octave_comment_elt::comment_type t) +{ + comment_list->append(s, t); +} + +octave_comment_list * +octave_comment_buffer::do_get_comment (void) +{ + octave_comment_list *retval = 0; + + if (comment_list && comment_list->length () > 0) + { + retval = comment_list; + comment_list = new octave_comment_list (); + } + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
new file mode 100644 --- /dev/null +++ b/src/comment-list.h @@ -0,0 +1,148 @@ +/* + +Copyright (C) 2000 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_comment_list_h) +#define octave_comment_list_h 1 + +#if defined (__GNUG__) +#pragma interface +#endif + +#include <string> + +#include <SLList.h> + +extern std::string get_comment_text (void); + +extern char *get_comment_text_c_str (void); + +extern void save_comment_text (const std::string& text); + +class +octave_comment_elt +{ +public: + + enum comment_type + { + unknown, + block, + end_of_line, + doc_string, + copyright + }; + + octave_comment_elt (const std::string& s = std::string (), + comment_type t = unknown) + : txt (s), typ (t) { } + + octave_comment_elt (const octave_comment_elt& oc) + : txt (oc.txt), typ (oc.typ) { } + + octave_comment_elt& operator = (const octave_comment_elt& oc) + { + if (this != &oc) + { + txt = oc.txt; + typ = oc.typ; + } + + return *this; + } + + std::string text (void) const { return txt; } + + comment_type type (void) const { return typ; } + + ~octave_comment_elt (void) { } + +private: + + // The text of the comment. + std::string txt; + + // The type of comment. + comment_type typ; +}; + +class +octave_comment_list : public SLList<octave_comment_elt> +{ +public: + + octave_comment_list (void) { } + + ~octave_comment_list (void) { } + + void append + (const std::string& s, + octave_comment_elt::comment_type t = octave_comment_elt::unknown) + { + SLList<octave_comment_elt>::append (octave_comment_elt (s, t)); + } + + octave_comment_list (const octave_comment_list& ocb) + : SLList<octave_comment_elt> (ocb) { } + + octave_comment_list& operator = (const octave_comment_list& ocb) + { + if (this != &ocb) + SLList<octave_comment_elt>::operator = (ocb); + + return *this; + } +}; + +class +octave_comment_buffer +{ +public: + + octave_comment_buffer (void) + : comment_list (new octave_comment_list) { } + + static bool instance_ok (void); + + static void append + (const std::string& s, + octave_comment_elt::comment_type t = octave_comment_elt::unknown); + + static octave_comment_list *get_comment (void); + +private: + + void do_append (const std::string& s, octave_comment_elt::comment_type t); + + octave_comment_list *do_get_comment (void); + + octave_comment_list *comment_list; + + static octave_comment_buffer *instance; +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
--- a/src/data.cc +++ b/src/data.cc @@ -37,6 +37,7 @@ #include "gripes.h" #include "oct-map.h" #include "ov.h" +#include "ov-re-nd-array.h" #include "variables.h" #include "oct-obj.h" #include "utils.h"
--- a/src/lex.l +++ b/src/lex.l @@ -44,6 +44,7 @@ // because it may not be protected to allow it to be included multiple // times. +#include "comment-list.h" #include "defun.h" #include "error.h" #include "input.h" @@ -187,6 +188,7 @@ static int handle_identifier (const std::string& tok, int spc_gobbled); static bool have_continuation (bool trailing_comments_ok = true); static bool have_ellipsis_continuation (bool trailing_comments_ok = true); +static void scan_for_comments (const char *); static yum_yum eat_whitespace (void); static yum_yum eat_continuation (void); static void maybe_warn_separator_insert (char sep); @@ -267,6 +269,7 @@ %} <MATRIX>{SNLCMT}*\]{S}* { + scan_for_comments (yytext); fixup_column_count (yytext); int c = yytext[yyleng-1]; int cont_is_spc = eat_continuation (); @@ -346,6 +349,7 @@ %} <MATRIX>{SNLCMT}*;{SNLCMT}* { + scan_for_comments (yytext); fixup_column_count (yytext); eat_whitespace (); lexer_flags.quote_is_transpose = false; @@ -362,6 +366,7 @@ <MATRIX>{S}*{COMMENT}{SNLCMT}* | <MATRIX>{S}*{NL}{SNLCMT}* { + scan_for_comments (yytext); fixup_column_count (yytext); eat_whitespace (); @@ -461,6 +466,7 @@ {CONT}{S}*{NL} | {CONT}{S}*{COMMENT} { + scan_for_comments (yytext); promptflag--; current_input_column = 1; } @@ -564,14 +570,28 @@ && lexer_flags.beginning_of_function && nesting_level.none ()) { + lexer_flags.beginning_of_function = false; + grab_help_text (); - lexer_flags.beginning_of_function = false; + + octave_comment_buffer::append (help_buf); } else { + std::string buf; + + bool begin_comment = true; + int c; while ((c = yyinput ()) != EOF && c != '\n') - ; // Eat comment. + { + if (begin_comment && (c == '#' || c == '%')) + ; /* Skip leading comment characters. */ + else + buf += (char) c; + } + + octave_comment_buffer::append (buf); } current_input_column = 1; @@ -1188,6 +1208,7 @@ bool begin_comment = true; bool in_comment = true; bool discard_space = true; + int c = 0; while ((c = yyinput ()) != EOF) @@ -1459,6 +1480,81 @@ return retval; } +static void +scan_for_comments (const char *text) +{ + std::string comment_buf; + + bool in_comment = false; + bool beginning_of_comment = false; + + int len = strlen (text); + int i = 0; + + while (i < len) + { + char c = text[i++]; + + switch (c) + { + case '%': + case '#': + if (in_comment) + { + if (! beginning_of_comment) + comment_buf += (char) c; + } + else + { + in_comment = true; + beginning_of_comment = true; + } + break; + + case '\n': + if (in_comment) + { + comment_buf += (char) c; + octave_comment_buffer::append (comment_buf); + comment_buf.resize (0); + in_comment = false; + beginning_of_comment = false; + } + break; + + case '\r': + if (in_comment) + comment_buf += (char) c; + if (i < len) + { + c = text[i++]; + + if (c == '\n') + { + if (in_comment) + { + comment_buf += (char) c; + octave_comment_buffer::append (comment_buf); + in_comment = false; + beginning_of_comment = false; + } + } + } + + default: + if (in_comment) + { + comment_buf += (char) c; + beginning_of_comment = false; + } + break; + } + } + + if (! comment_buf.empty ()) + octave_comment_buffer::append (comment_buf); +} + // Discard whitespace, including comments and continuations. // // Return value is logical OR of the following values: @@ -1471,8 +1567,14 @@ eat_whitespace (void) { yum_yum retval = ATE_NOTHING; + + std::string comment_buf; + bool in_comment = false; - int c; + bool beginning_of_comment = false; + + int c = 0; + while ((c = yyinput ()) != EOF) { current_input_column++; @@ -1481,23 +1583,48 @@ { case ' ': case '\t': + if (in_comment) + { + comment_buf += (char) c; + beginning_of_comment = false; + } retval |= ATE_SPACE_OR_TAB; break; case '\n': retval |= ATE_NEWLINE; - in_comment = false; + if (in_comment) + { + comment_buf += (char) c; + octave_comment_buffer::append (comment_buf); + comment_buf.resize (0); + in_comment = false; + beginning_of_comment = false; + } current_input_column = 0; break; case '#': case '%': - in_comment = true; + if (in_comment) + { + if (! beginning_of_comment) + comment_buf += (char) c; + } + else + { + in_comment = true; + beginning_of_comment = true; + } break; case '.': if (in_comment) - break; + { + comment_buf += (char) c; + beginning_of_comment = false; + break; + } else { if (have_ellipsis_continuation ()) @@ -1508,7 +1635,11 @@ case '\\': if (in_comment) - break; + { + comment_buf += (char) c; + beginning_of_comment = false; + break; + } else { if (have_continuation ()) @@ -1519,12 +1650,19 @@ default: if (in_comment) - break; + { + comment_buf += (char) c; + beginning_of_comment = false; + break; + } else goto done; } } + if (! comment_buf.empty ()) + octave_comment_buffer::append (comment_buf); + done: unput (c); current_input_column--; @@ -1600,8 +1738,13 @@ { std::ostrstream buf; + std::string comment_buf; + bool in_comment = false; - int c; + bool beginning_of_comment = false; + + int c = 0; + while ((c = yyinput ()) != EOF) { buf << (char) c; @@ -1610,34 +1753,67 @@ { case ' ': case '\t': + if (in_comment) + { + comment_buf += (char) c; + beginning_of_comment = false; + } break; case '%': case '#': if (trailing_comments_ok) - in_comment = true; + { + if (in_comment) + { + if (! beginning_of_comment) + comment_buf += (char) c; + } + else + { + in_comment = true; + beginning_of_comment = true; + } + } else goto cleanup; break; case '\n': + if (in_comment) + { + comment_buf += (char) c; + octave_comment_buffer::append (comment_buf); + } current_input_column = 0; promptflag--; return true; case '\r': + if (in_comment) + comment_buf += (char) c; c = yyinput (); if (c == EOF) break; else if (c == '\n') { + if (in_comment) + { + comment_buf += (char) c; + octave_comment_buffer::append (comment_buf); + } current_input_column = 0; promptflag--; return true; - } + } default: - if (! in_comment) + if (in_comment) + { + comment_buf += (char) c; + beginning_of_comment = false; + } + else goto cleanup; break; } @@ -1694,7 +1870,9 @@ eat_continuation (void) { int retval = ATE_NOTHING; + int c = yyinput (); + if ((c == '.' && have_ellipsis_continuation ()) || (c == '\\' && have_continuation ())) retval = eat_whitespace (); @@ -2155,9 +2333,15 @@ // force the parser to return after reading the function. Calling // unput with EOF does not work. + std::string comment_buf; + bool in_comment = false; + bool beginning_of_comment = true; + int lineno = input_line_number; - int c; + + int c = 0; + while ((c = yyinput ()) != EOF) { switch (c) @@ -2166,21 +2350,45 @@ case '\t': case ';': case ',': + if (in_comment) + { + comment_buf += (char) c; + beginning_of_comment = false; + } break; case '\n': if (in_comment) - in_comment = false; + { + comment_buf += (char) c; + octave_comment_buffer::append (comment_buf); + comment_buf.resize (0); + in_comment = false; + beginning_of_comment = false; + } break; case '%': case '#': - in_comment = true; + if (in_comment) + { + if (! beginning_of_comment) + comment_buf += (char) c; + } + else + { + in_comment = true; + beginning_of_comment = true; + } break; default: if (in_comment) - break; + { + comment_buf += (char) c; + beginning_of_comment = false; + break; + } else { warning ("ignoring trailing garbage after end of function\n\ @@ -2191,6 +2399,10 @@ } } } + + if (! comment_buf.empty ()) + octave_comment_buffer::append (comment_buf); + unput ('\n'); }
new file mode 100644 --- /dev/null +++ b/src/ov-base-nd-array.cc @@ -0,0 +1,148 @@ +/* + +Copyright (C) 2000 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if defined (__GNUG__) +#pragma implementation +#endif + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <iostream> + +#include "oct-obj.h" +#include "ov-base.h" +#include "ov-base-nd-array.h" +#include "pr-output.h" + +static Array<idx_vector> +idx_list_to_idx_array (const octave_value_list& idx) +{ + int n = idx.length (); + + Array<idx_vector> retval (n); + + for (int i = 0; i < n; i++) + retval(i) = idx(i).index_vector (); + + return retval; +} + +template <class AT> +octave_value +octave_base_nd_array<AT>::do_index_op (const octave_value_list& idx) +{ + octave_value retval; + + int len = idx.length (); + + if (len > 1) + { + Array<idx_vector> i = idx_list_to_idx_array (idx); + + retval + = octave_value (new octave_base_nd_array<AT> (AT (array.index (i)))); + } + else if (len == 1) + { + idx_vector i = idx(0).index_vector (); + + retval + = octave_value (new octave_base_nd_array<AT> (AT (array.index (i)))); + } + else + { + std::string n = type_name (); + + error ("invalid number of indices (%d) for %s value", + len, n.c_str ()); + } + + return retval; +} + +template <class AT> +bool +octave_base_nd_array<AT>::is_true (void) const +{ + // XXX FIXME XXX + return false; +} + +template <class AT> +bool +octave_base_nd_array<AT>::print_as_scalar (void) const +{ + // XXX FIXME XXX + return false; +} + +template <class AT> +void +octave_base_nd_array<AT>::print (std::ostream& os, + bool pr_as_read_syntax) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +template <class AT> +void +octave_base_nd_array<AT>::print_raw (std::ostream& os, + bool pr_as_read_syntax) const +{ + // XXX FIXME XX + os << array; +#if 0 + octave_print_internal (os, array, pr_as_read_syntax, + current_print_indent_level ()); +#endif +} + +template <class AT> +bool +octave_base_nd_array<AT>::print_name_tag (std::ostream& os, + const std::string& name) const +{ + bool retval = false; + + indent (os); + + if (print_as_scalar ()) + os << name << " = "; + else + { + os << name << " ="; + newline (os); + newline (os); + retval = true; + } + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
new file mode 100644 --- /dev/null +++ b/src/ov-base-nd-array.h @@ -0,0 +1,99 @@ +/* + +Copyright (C) 2000 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_base_nd_array_h) +#define octave_base_nd_array_h 1 + +#if defined (__GNUG__) +#pragma interface +#endif + +#include <cstdlib> + +#include <iostream> +#include <string> + +#include "mx-base.h" +#include "str-vec.h" + +#include "error.h" +#include "ov-base.h" +#include "ov-typeinfo.h" + +class Octave_map; +class octave_value_list; + +class tree_walker; + +// ND array values values. + +template <class AT> +class +octave_base_nd_array : public octave_base_value +{ +public: + + octave_base_nd_array (void) + : octave_base_value () { } + + octave_base_nd_array (const AT& a) + : octave_base_value (), array (a) { } + + octave_base_nd_array (const octave_base_nd_array& a) + : octave_base_value (), array (a.array) { } + + ~octave_base_nd_array (void) { } + + octave_value *clone (void) { return new octave_base_nd_array (*this); } + + octave_value do_index_op (const octave_value_list& idx); + + bool is_matrix_type (void) const { return false; } + + bool is_numeric_type (void) const { return true; } + + bool is_defined (void) const { return true; } + + bool is_constant (void) const { return true; } + + bool is_true (void) const; + + virtual bool print_as_scalar (void) const; + + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + + void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; + + bool print_name_tag (std::ostream& os, const std::string& name) const; + +protected: + + AT array; +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
new file mode 100644 --- /dev/null +++ b/src/ov-re-nd-array.cc @@ -0,0 +1,151 @@ +/* + +Copyright (C) 2000 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if defined (__GNUG__) +#pragma implementation +#endif + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <iostream> + +#include "lo-ieee.h" +#include "lo-utils.h" +#include "mx-base.h" + +#include "gripes.h" +#include "oct-obj.h" +#include "oct-lvalue.h" +#include "ops.h" +#include "ov-base.h" +#include "ov-base-nd-array.h" +#include "ov-base-nd-array.cc" +#include "ov-re-nd-array.h" +#include "pr-output.h" +#include "variables.h" + +template class octave_base_nd_array<ArrayN<double> >; + +DEFINE_OCTAVE_ALLOCATOR (octave_double_nd_array); + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_double_nd_array, + "double-nd-array"); + +#if 0 +octave_value * +octave_matrix::try_narrowing_conversion (void) +{ + octave_value *retval = 0; + + int nr = matrix.rows (); + int nc = matrix.cols (); + + if (nr == 1 && nc == 1) + retval = new octave_scalar (matrix (0, 0)); + + return retval; +} + +#if !defined (CXX_NEW_FRIEND_TEMPLATE_DECL) +extern void assign (Array2<double>&, const Array2<double>&); +#endif + +void +octave_matrix::assign (const octave_value_list& idx, const Matrix& rhs) +{ + int len = idx.length (); + + switch (len) + { + case 2: + { + idx_vector i = idx (0).index_vector (); + idx_vector j = idx (1).index_vector (); + + matrix.set_index (i); + matrix.set_index (j); + + ::assign (matrix, rhs); + } + break; + + case 1: + { + idx_vector i = idx (0).index_vector (); + + matrix.set_index (i); + + ::assign (matrix, rhs); + } + break; + + default: + error ("invalid number of indices (%d) for indexed matrix assignment", + len); + break; + } +} + +bool +octave_matrix::valid_as_scalar_index (void) const +{ + // XXX FIXME XXX + return false; +} + +double +octave_matrix::double_value (bool) const +{ + double retval = octave_NaN; + + // XXX FIXME XXX -- maybe this should be a function, valid_as_scalar() + if ((rows () == 1 && columns () == 1) + || (Vdo_fortran_indexing && rows () > 0 && columns () > 0)) + retval = matrix (0, 0); + else + gripe_invalid_conversion ("real matrix", "real scalar"); + + return retval; +} + +Complex +octave_matrix::complex_value (bool) const +{ + Complex retval (octave_NaN, octave_NaN); + + if ((rows () == 1 && columns () == 1) + || (Vdo_fortran_indexing && rows () > 0 && columns () > 0)) + retval = matrix (0, 0); + else + gripe_invalid_conversion ("real matrix", "complex scalar"); + + return retval; +} +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
new file mode 100644 --- /dev/null +++ b/src/ov-re-nd-array.h @@ -0,0 +1,104 @@ +/* + +Copyright (C) 2000 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_re_nd_array_h) +#define octave_re_nd_array_h 1 + +#if defined (__GNUG__) +#pragma interface +#endif + +#include <cstdlib> + +#include <iostream> +#include <string> + +#include "ArrayN.h" +#include "oct-alloc.h" + +#include "error.h" +#include "ov-base.h" +#include "ov-base-nd-array.h" +#include "ov-typeinfo.h" + +class octave_value_list; + +// Real N-dimensional array values. + +class +octave_double_nd_array : public octave_base_nd_array<ArrayN<double> > +{ +public: + + octave_double_nd_array (void) + : octave_base_nd_array<ArrayN<double> > () { } + + octave_double_nd_array (const ArrayN<double>& a) + : octave_base_nd_array<ArrayN<double> > (a) { } + + octave_double_nd_array (const octave_double_nd_array& a) + : octave_base_nd_array<ArrayN<double> > (a) { } + + ~octave_double_nd_array (void) { } + + octave_value *clone (void) { return new octave_double_nd_array (*this); } + +#if 0 + octave_value *try_narrowing_conversion (void); + + void assign (const octave_value_list& idx, const Matrix& rhs); + + idx_vector index_vector (void) const { return idx_vector (matrix); } + + bool is_real_matrix (void) const { return false; } + + bool is_real_type (void) const { return true; } + + bool valid_as_scalar_index (void) const; + + double double_value (bool = false) const; + + double scalar_value (bool frc_str_conv = false) const + { return double_value (frc_str_conv); } + + Matrix matrix_value (bool = false) const; + + Complex complex_value (bool = false) const; + + ComplexMatrix complex_matrix_value (bool = false) const + { return ComplexMatrix (matrix_value ()); } +#endif + +private: + + DECLARE_OCTAVE_ALLOCATOR + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
--- a/src/ov-usr-fcn.cc +++ b/src/ov-usr-fcn.cc @@ -76,7 +76,8 @@ tree_statement_list *cl, symbol_table *st) : octave_function (std::string (), std::string ()), param_list (pl), ret_list (rl), cmd_list (cl), - sym_tab (st), file_name (), fcn_name (), + sym_tab (st), lead_comm (), trail_comm (), + file_name (), fcn_name (), t_parsed (static_cast<time_t> (0)), t_checked (static_cast<time_t> (0)), system_fcn_file (false), call_depth (0), @@ -100,6 +101,8 @@ delete sym_tab; delete cmd_list; delete vr_list; + delete lead_comm; + delete trail_comm; } octave_user_function *
--- a/src/ov-usr-fcn.h +++ b/src/ov-usr-fcn.h @@ -31,6 +31,7 @@ #include <string> +#include "comment-list.h" #include "oct-obj.h" #include "ov-fcn.h" #include "ov-typeinfo.h" @@ -67,6 +68,10 @@ void stash_fcn_file_name (void); + void stash_leading_comment (octave_comment_list *lc) { lead_comm = lc; } + + void stash_trailing_comment (octave_comment_list *tc) { trail_comm = tc; } + void mark_fcn_file_up_to_date (const octave_time& t) { t_checked = t; } void stash_fcn_file_time (const octave_time& t) @@ -124,6 +129,10 @@ tree_statement_list *body (void) { return cmd_list; } + octave_comment_list *leading_comment (void) { return lead_comm; } + + octave_comment_list *trailing_comment (void) { return trail_comm; } + void accept (tree_walker& tw); private: @@ -145,6 +154,12 @@ // The local symbol table for this function. symbol_table *sym_tab; + // The comments preceding the FUNCTION token. + octave_comment_list *lead_comm; + + // The comments preceding the ENDFUNCTION token. + octave_comment_list *trail_comm; + // The name of the file we parsed std::string file_name;
--- a/src/parse.y +++ b/src/parse.y @@ -46,6 +46,7 @@ #include "file-ops.h" #include "file-stat.h" +#include "comment-list.h" #include "defun.h" #include "dynamic-ld.h" #include "error.h" @@ -103,6 +104,9 @@ // Buffer for help text snagged from function files. std::string help_buf; +// Buffer for comments appearing before a function statement. +static std::string fcn_comment_header; + // TRUE means we are using readline. // (--no-line-editing) bool line_editing = true; @@ -179,28 +183,31 @@ // Build an unwind-protect command. static tree_command * make_unwind_command (token *unwind_tok, tree_statement_list *body, - tree_statement_list *cleanup, token *end_tok); + tree_statement_list *cleanup, token *end_tok, + octave_comment_list *lc, octave_comment_list *mc); // Build a try-catch command. static tree_command * make_try_command (token *try_tok, tree_statement_list *body, - tree_statement_list *cleanup, token *end_tok); + tree_statement_list *cleanup, token *end_tok, + octave_comment_list *lc, octave_comment_list *mc); // Build a while command. static tree_command * make_while_command (token *while_tok, tree_expression *expr, - tree_statement_list *body, token *end_tok); + tree_statement_list *body, token *end_tok, + octave_comment_list *lc); // Build a do-until command. static tree_command * make_do_until_command (token *do_tok, tree_statement_list *body, - tree_expression *expr); + tree_expression *expr, octave_comment_list *lc); // Build a for command. static tree_command * make_for_command (token *for_tok, tree_argument_list *lhs, tree_expression *expr, tree_statement_list *body, - token *end_tok); + token *end_tok, octave_comment_list *lc); // Build a break command. static tree_command * @@ -220,20 +227,24 @@ // Finish an if command. static tree_if_command * -finish_if_command (token *if_tok, tree_if_command_list *list, token *end_tok); +finish_if_command (token *if_tok, tree_if_command_list *list, + token *end_tok, octave_comment_list *lc); // Build an elseif clause. static tree_if_clause * -make_elseif_clause (tree_expression *expr, tree_statement_list *list); +make_elseif_clause (tree_expression *expr, tree_statement_list *list, + octave_comment_list *lc); // Finish a switch command. static tree_switch_command * finish_switch_command (token *switch_tok, tree_expression *expr, - tree_switch_case_list *list, token *end_tok); + tree_switch_case_list *list, token *end_tok, + octave_comment_list *lc); // Build a switch case. static tree_switch_case * -make_switch_case (tree_expression *expr, tree_statement_list *list); +make_switch_case (tree_expression *expr, tree_statement_list *list, + octave_comment_list *lc); // Build an assignment to a variable. static tree_expression * @@ -250,11 +261,13 @@ // Finish defining a function. static octave_user_function * -finish_function (tree_identifier *id, octave_user_function *fcn); +finish_function (tree_identifier *id, octave_user_function *fcn, + octave_comment_list *lc); // Finish defining a function a different way. static octave_user_function * -finish_function (tree_parameter_list *ret_list, octave_user_function *fcn); +finish_function (tree_parameter_list *ret_list, + octave_user_function *fcn, octave_comment_list *lc); // Reset state after parsing function. static void @@ -309,6 +322,9 @@ // The type of the basic tokens returned by the lexer. token *tok_val; + // Comment strings that we need to deal with mid-rule. + octave_comment_list *comment_type; + // Types for the nonterminals we generate. char sep_type; tree *tree_type; @@ -375,6 +391,7 @@ %token USING TITLE WITH AXES COLON OPEN_BRACE CLOSE_BRACE CLEAR // Nonterminals we construct. +%type <comment_type> stash_comment function_beg %type <sep_type> sep_no_nl opt_sep_no_nl sep opt_sep %type <tree_type> input %type <tree_constant_type> constant magic_colon @@ -510,14 +527,28 @@ ; statement : expression - { $$ = new tree_statement ($1); } + { + octave_comment_list *comment + = octave_comment_buffer::get_comment (); + + $$ = new tree_statement ($1, comment); + } | command - { $$ = new tree_statement ($1); } + { + octave_comment_list *comment + = octave_comment_buffer::get_comment (); + + $$ = new tree_statement ($1, comment); + } | PLOT CLEAR { symbol_record *sr = lookup_by_name ("clearplot", 0); tree_identifier *id = new tree_identifier (sr); - $$ = new tree_statement (id); + + octave_comment_list *comment + = octave_comment_buffer::get_comment (); + + $$ = new tree_statement (id, comment); } ; @@ -880,9 +911,9 @@ // If statement // ============ -if_command : IF if_cmd_list END +if_command : IF stash_comment if_cmd_list END { - if (! ($$ = finish_if_command ($1, $2, $3))) + if (! ($$ = finish_if_command ($1, $3, $4, $2))) ABORT_PARSE; } ; @@ -905,21 +936,23 @@ } ; -elseif_clause : ELSEIF opt_sep expression opt_sep opt_list - { $$ = make_elseif_clause ($3, $5); } +elseif_clause : ELSEIF stash_comment opt_sep expression opt_sep opt_list + { $$ = make_elseif_clause ($4, $6, $2); } ; -else_clause : ELSE opt_sep opt_list - { $$ = new tree_if_clause ($3); } +else_clause : ELSE stash_comment opt_sep opt_list + { + $$ = new tree_if_clause ($4, $2); + } ; // ================ // Switch statement // ================ -switch_command : SWITCH expression opt_sep case_list END +switch_command : SWITCH stash_comment expression opt_sep case_list END { - if (! ($$ = finish_switch_command ($1, $2, $4, $5))) + if (! ($$ = finish_switch_command ($1, $3, $5, $6, $2))) ABORT_PARSE; } ; @@ -942,31 +975,33 @@ } ; -switch_case : CASE opt_sep expression opt_sep list - { $$ = make_switch_case ($3, $5); } +switch_case : CASE stash_comment opt_sep expression opt_sep list + { $$ = make_switch_case ($4, $6, $2); } ; -default_case : OTHERWISE opt_sep opt_list - { $$ = new tree_switch_case ($3); } +default_case : OTHERWISE stash_comment opt_sep opt_list + { + $$ = new tree_switch_case ($4, $2); + } ; // ======= // Looping // ======= -loop_command : WHILE expression opt_sep opt_list END +loop_command : WHILE stash_comment expression opt_sep opt_list END { - if (! ($$ = make_while_command ($1, $2, $4, $5))) + if (! ($$ = make_while_command ($1, $3, $5, $6, $2))) ABORT_PARSE; } - | DO opt_sep opt_list UNTIL expression + | DO stash_comment opt_sep opt_list UNTIL expression { - if (! ($$ = make_do_until_command ($1, $3, $5))) + if (! ($$ = make_do_until_command ($1, $4, $6, $2))) ABORT_PARSE; } - | FOR assign_lhs '=' expression opt_sep opt_list END + | FOR stash_comment assign_lhs '=' expression opt_sep opt_list END { - if (! ($$ = make_for_command ($1, $2, $4, $6, $7))) + if (! ($$ = make_for_command ($1, $3, $5, $7, $8, $2))) ABORT_PARSE; } ; @@ -996,14 +1031,16 @@ // Exceptions // ========== -except_command : UNWIND opt_sep opt_list CLEANUP opt_sep opt_list END +except_command : UNWIND stash_comment opt_sep opt_list CLEANUP + stash_comment opt_sep opt_list END { - if (! ($$ = make_unwind_command ($1, $3, $6, $7))) + if (! ($$ = make_unwind_command ($1, $4, $8, $9, $2, $6))) ABORT_PARSE; } - | TRY opt_sep opt_list CATCH opt_sep opt_list END + | TRY stash_comment opt_sep opt_list CATCH + stash_comment opt_sep opt_list END { - if (! ($$ = make_try_command ($1, $3, $6, $7))) + if (! ($$ = make_try_command ($1, $4, $8, $9, $2, $6))) ABORT_PARSE; } ; @@ -1136,23 +1173,25 @@ // Function definition // =================== -function_beg : FCN global_symtab +function_beg : FCN stash_comment global_symtab + { $$ = $2; } ; function : function_beg function2 { + $2->stash_leading_comment ($1); recover_from_parsing_function (); $$ = 0; } | function_beg identifier function1 { - finish_function ($2, $3); + finish_function ($2, $3, $1); recover_from_parsing_function (); $$ = 0; } | function_beg return_list function1 { - finish_function ($2, $3); + finish_function ($2, $3, $1); recover_from_parsing_function (); $$ = 0; } @@ -1355,6 +1394,10 @@ // Miscellaneous // ============= +stash_comment : // empty + { $$ = octave_comment_buffer::get_comment (); } + ; + parse_error : LEXICAL_ERROR { yyerror ("parse error"); } | error @@ -2030,16 +2073,20 @@ static tree_command * make_unwind_command (token *unwind_tok, tree_statement_list *body, - tree_statement_list *cleanup, token *end_tok) + tree_statement_list *cleanup, token *end_tok, + octave_comment_list *lc, octave_comment_list *mc) { tree_command *retval = 0; if (end_token_ok (end_tok, token::unwind_protect_end)) { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + int l = unwind_tok->line (); int c = unwind_tok->column (); - retval = new tree_unwind_protect_command (body, cleanup, l, c); + retval = new tree_unwind_protect_command (body, cleanup, + lc, mc, tc, l, c); } return retval; @@ -2049,16 +2096,20 @@ static tree_command * make_try_command (token *try_tok, tree_statement_list *body, - tree_statement_list *cleanup, token *end_tok) + tree_statement_list *cleanup, token *end_tok, + octave_comment_list *lc, octave_comment_list *mc) { tree_command *retval = 0; if (end_token_ok (end_tok, token::try_catch_end)) { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + int l = try_tok->line (); int c = try_tok->column (); - retval = new tree_try_catch_command (body, cleanup, l, c); + retval = new tree_try_catch_command (body, cleanup, + lc, mc, tc, l, c); } return retval; @@ -2068,7 +2119,8 @@ static tree_command * make_while_command (token *while_tok, tree_expression *expr, - tree_statement_list *body, token *end_tok) + tree_statement_list *body, token *end_tok, + octave_comment_list *lc) { tree_command *retval = 0; @@ -2076,12 +2128,14 @@ if (end_token_ok (end_tok, token::while_end)) { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + lexer_flags.looping--; int l = while_tok->line (); int c = while_tok->column (); - retval = new tree_while_command (expr, body, l, c); + retval = new tree_while_command (expr, body, lc, tc, l, c); } return retval; @@ -2091,18 +2145,20 @@ static tree_command * make_do_until_command (token *do_tok, tree_statement_list *body, - tree_expression *expr) + tree_expression *expr, octave_comment_list *lc) { tree_command *retval = 0; maybe_warn_assign_as_truth_value (expr); + octave_comment_list *tc = octave_comment_buffer::get_comment (); + lexer_flags.looping--; int l = do_tok->line (); int c = do_tok->column (); - retval = new tree_do_until_command (expr, body, l, c); + retval = new tree_do_until_command (expr, body, lc, tc, l, c); return retval; } @@ -2112,12 +2168,14 @@ static tree_command * make_for_command (token *for_tok, tree_argument_list *lhs, tree_expression *expr, tree_statement_list *body, - token *end_tok) + token *end_tok, octave_comment_list *lc) { tree_command *retval = 0; if (end_token_ok (end_tok, token::for_end)) { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + lexer_flags.looping--; int l = for_tok->line (); @@ -2127,12 +2185,14 @@ { tree_expression *tmp = lhs->remove_front (); - retval = new tree_simple_for_command (tmp, expr, body, l, c); + retval = new tree_simple_for_command (tmp, expr, body, + lc, tc, l, c); delete lhs; } else - retval = new tree_complex_for_command (lhs, expr, body, l, c); + retval = new tree_complex_for_command (lhs, expr, body, + lc, tc, l, c); } return retval; @@ -2210,16 +2270,18 @@ static tree_if_command * finish_if_command (token *if_tok, tree_if_command_list *list, - token *end_tok) + token *end_tok, octave_comment_list *lc) { tree_if_command *retval = 0; if (end_token_ok (end_tok, token::if_end)) { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + int l = if_tok->line (); int c = if_tok->column (); - retval = new tree_if_command (list, l, c); + retval = new tree_if_command (list, lc, tc, l, c); } return retval; @@ -2228,27 +2290,31 @@ // Build an elseif clause. static tree_if_clause * -make_elseif_clause (tree_expression *expr, tree_statement_list *list) +make_elseif_clause (tree_expression *expr, tree_statement_list *list, + octave_comment_list *lc) { maybe_warn_assign_as_truth_value (expr); - return new tree_if_clause (expr, list); + return new tree_if_clause (expr, list, lc); } // Finish a switch command. static tree_switch_command * finish_switch_command (token *switch_tok, tree_expression *expr, - tree_switch_case_list *list, token *end_tok) + tree_switch_case_list *list, token *end_tok, + octave_comment_list *lc) { tree_switch_command *retval = 0; if (end_token_ok (end_tok, token::switch_end)) { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + int l = switch_tok->line (); int c = switch_tok->column (); - retval = new tree_switch_command (expr, list, l, c); + retval = new tree_switch_command (expr, list, lc, tc, l, c); } return retval; @@ -2257,11 +2323,12 @@ // Build a switch case. static tree_switch_case * -make_switch_case (tree_expression *expr, tree_statement_list *list) +make_switch_case (tree_expression *expr, tree_statement_list *list, + octave_comment_list *lc) { maybe_warn_variable_switch_label (expr); - return new tree_switch_case (expr, list); + return new tree_switch_case (expr, list, lc); } // Build an assignment to a variable. @@ -2362,6 +2429,13 @@ octave_user_function *fcn = new octave_user_function (param_list, 0, body, curr_sym_tab); + if (fcn) + { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + + fcn->stash_trailing_comment (tc); + } + return fcn; } @@ -2439,22 +2513,28 @@ // Finish defining a function. static octave_user_function * -finish_function (tree_identifier *id, octave_user_function *fcn) +finish_function (tree_identifier *id, octave_user_function *fcn, + octave_comment_list *lc) { tree_parameter_list *tpl = new tree_parameter_list (id); tpl->mark_as_formal_parameters (); + fcn->stash_leading_comment (lc); + return fcn->define_ret_list (tpl); } // Finish defining a function a different way. static octave_user_function * -finish_function (tree_parameter_list *ret_list, octave_user_function *fcn) +finish_function (tree_parameter_list *ret_list, + octave_user_function *fcn, octave_comment_list *lc) { ret_list->mark_as_formal_parameters (); + fcn->stash_leading_comment (lc); + return fcn->define_ret_list (ret_list); } @@ -2785,13 +2865,16 @@ // comments read if it doesn't look like a copyright notice. If // IN_PARTS, consider each block of comments separately; otherwise, // grab them all at once. If UPDATE_POS is TRUE, line and column -// number information is updated. +// number information is updated. If SAVE_COPYRIGHT is TRUE, then +// comments that are recognized as a copyright notice are saved in the +// comment buffer. // XXX FIXME XXX -- grab_help_text() in lex.l duplicates some of this // code! static std::string -gobble_leading_white_space (FILE *ffile, bool in_parts, bool update_pos) +gobble_leading_white_space (FILE *ffile, bool in_parts, + bool update_pos, bool save_copyright) { std::string help_txt; @@ -2893,11 +2976,17 @@ if (! help_txt.empty ()) { - if (looks_like_octave_copyright (help_txt)) - help_txt.resize (0); + if (looks_like_octave_copyright (help_txt)) + { + if (save_copyright) + octave_comment_buffer::append (help_txt); + + help_txt.resize (0); + } if (in_parts && help_txt.empty ()) - help_txt = gobble_leading_white_space (ffile, in_parts, update_pos); + help_txt = gobble_leading_white_space (ffile, in_parts, + update_pos, false); } return help_txt; @@ -2916,7 +3005,7 @@ { unwind_protect::add (safe_fclose, (void *) fptr); - retval = gobble_leading_white_space (fptr, true, true); + retval = gobble_leading_white_space (fptr, true, true, false); unwind_protect::run (); } @@ -2932,7 +3021,7 @@ long pos = ftell (ffile); - gobble_leading_white_space (ffile, false, false); + gobble_leading_white_space (ffile, false, false, false); char buf [10]; fgets (buf, 10, ffile); @@ -3031,10 +3120,12 @@ reset_parser (); - help_buf = gobble_leading_white_space (ffile, true, true); + help_buf = gobble_leading_white_space (ffile, true, true, true); + + octave_comment_buffer::append (help_buf); // XXX FIXME XXX -- this should not be necessary. - gobble_leading_white_space (ffile, false, true); + gobble_leading_white_space (ffile, false, true, false); int status = yyparse ();
--- a/src/pt-except.cc +++ b/src/pt-except.cc @@ -46,6 +46,9 @@ { delete try_code; delete catch_code; + delete lead_comm; + delete mid_comm; + delete trail_comm; } static void @@ -120,6 +123,9 @@ { delete unwind_protect_code; delete cleanup_code; + delete lead_comm; + delete mid_comm; + delete trail_comm; } static void
--- a/src/pt-except.h +++ b/src/pt-except.h @@ -31,6 +31,7 @@ class tree_walker; +#include "comment-list.h" #include "pt-cmd.h" // Simple exception handling. @@ -41,11 +42,16 @@ public: tree_try_catch_command (int l = -1, int c = -1) - : tree_command (l, c), try_code (0), catch_code (0) { } + : tree_command (l, c), try_code (0), catch_code (0), lead_comm (0), + mid_comm (0), trail_comm (0) { } tree_try_catch_command (tree_statement_list *tc, tree_statement_list *cc, + octave_comment_list *cl = 0, + octave_comment_list *cm = 0, + octave_comment_list *ct = 0, int l = -1, int c = -1) - : tree_command (l, c), try_code (tc), catch_code (cc) { } + : tree_command (l, c), try_code (tc), catch_code (cc), + lead_comm (cl), mid_comm (cm), trail_comm (ct) { } ~tree_try_catch_command (void); @@ -55,6 +61,12 @@ tree_statement_list *cleanup (void) { return catch_code; } + octave_comment_list *leading_comment (void) { return lead_comm; } + + octave_comment_list *middle_comment (void) { return mid_comm; } + + octave_comment_list *trailing_comment (void) { return trail_comm; } + void accept (tree_walker& tw); private: @@ -65,6 +77,15 @@ // The code to execute if an error occurs in the first block. tree_statement_list *catch_code; + // Comment preceding TRY token. + octave_comment_list *lead_comm; + + // Comment preceding CATCH token. + octave_comment_list *mid_comm; + + // Comment preceding END_TRY_CATCH token. + octave_comment_list *trail_comm; + // No copying! tree_try_catch_command (const tree_try_catch_command&); @@ -80,12 +101,17 @@ public: tree_unwind_protect_command (int l = -1, int c = -1) - : tree_command (l, c), unwind_protect_code (0), cleanup_code (0) { } + : tree_command (l, c), unwind_protect_code (0), cleanup_code (0), + lead_comm (0), mid_comm (0), trail_comm (0) { } tree_unwind_protect_command (tree_statement_list *tc, tree_statement_list *cc, + octave_comment_list *cl = 0, + octave_comment_list *cm = 0, + octave_comment_list *ct = 0, int l = -1, int c = -1) - : tree_command (l, c), unwind_protect_code (tc), cleanup_code (cc) { } + : tree_command (l, c), unwind_protect_code (tc), cleanup_code (cc), + lead_comm (cl), mid_comm (cm), trail_comm (ct) { } ~tree_unwind_protect_command (void); @@ -95,6 +121,12 @@ tree_statement_list *cleanup (void) { return cleanup_code; } + octave_comment_list *leading_comment (void) { return lead_comm; } + + octave_comment_list *middle_comment (void) { return mid_comm; } + + octave_comment_list *trailing_comment (void) { return trail_comm; } + void accept (tree_walker& tw); private: @@ -106,6 +138,15 @@ // body of code. tree_statement_list *cleanup_code; + // Comment preceding TRY token. + octave_comment_list *lead_comm; + + // Comment preceding CATCH token. + octave_comment_list *mid_comm; + + // Comment preceding END_TRY_CATCH token. + octave_comment_list *trail_comm; + // No copying! tree_unwind_protect_command (const tree_unwind_protect_command&);
--- a/src/pt-loop.cc +++ b/src/pt-loop.cc @@ -67,6 +67,8 @@ { delete expr; delete list; + delete lead_comm; + delete trail_comm; } void @@ -164,6 +166,8 @@ { delete expr; delete list; + delete lead_comm; + delete trail_comm; } inline void @@ -364,6 +368,8 @@ { delete expr; delete list; + delete lead_comm; + delete trail_comm; } void
--- a/src/pt-loop.h +++ b/src/pt-loop.h @@ -36,6 +36,7 @@ class tree_walker; +#include "comment-list.h" #include "pt-cmd.h" // While. @@ -46,14 +47,22 @@ public: tree_while_command (int l = -1, int c = -1) - : tree_command (l, c), expr (0), list (0) { } + : tree_command (l, c), expr (0), list (0), lead_comm (0), + trail_comm (0) { } - tree_while_command (tree_expression *e, int l = -1, int c = -1) - : tree_command (l, c), expr (e), list (0) { } + tree_while_command (tree_expression *e, + octave_comment_list *lc = 0, + octave_comment_list *tc = 0, + int l = -1, int c = -1) + : tree_command (l, c), expr (e), list (0), lead_comm (lc), + trail_comm (tc) { } tree_while_command (tree_expression *e, tree_statement_list *lst, + octave_comment_list *lc = 0, + octave_comment_list *tc = 0, int l = -1, int c = -1) - : tree_command (l, c), expr (e), list (lst) { } + : tree_command (l, c), expr (e), list (lst), lead_comm (lc), + trail_comm (tc) { } ~tree_while_command (void); @@ -65,6 +74,10 @@ tree_statement_list *body (void) { return list; } + octave_comment_list *leading_comment (void) { return lead_comm; } + + octave_comment_list *trailing_comment (void) { return trail_comm; } + void accept (tree_walker& tw); protected: @@ -75,6 +88,12 @@ // List of commands to execute. tree_statement_list *list; + // Comment preceding WHILE token. + octave_comment_list *lead_comm; + + // Comment preceding ENDWHILE token. + octave_comment_list *trail_comm; + private: // No copying! @@ -94,12 +113,17 @@ tree_do_until_command (int l = -1, int c = -1) : tree_while_command (l, c) { } - tree_do_until_command (tree_expression *e, int l = -1, int c = -1) - : tree_while_command (e, l, c) { } + tree_do_until_command (tree_expression *e, + octave_comment_list *lc = 0, + octave_comment_list *tc = 0, + int l = -1, int c = -1) + : tree_while_command (e, lc, tc, l, c) { } tree_do_until_command (tree_expression *e, tree_statement_list *lst, - int l = -1, int c = -1) - : tree_while_command (e, lst, l, c) { } + octave_comment_list *lc = 0, + octave_comment_list *tc = 0, + int l = -1, int c = -1) + : tree_while_command (e, lst, lc, tc, l, c) { } ~tree_do_until_command (void) { } @@ -126,11 +150,16 @@ public: tree_simple_for_command (int l = -1, int c = -1) - : tree_command (l, c), lhs (0), expr (0), list (0) { } + : tree_command (l, c), lhs (0), expr (0), list (0), lead_comm (0), + trail_comm (0) { } tree_simple_for_command (tree_expression *le, tree_expression *re, - tree_statement_list *lst, int l = -1, int c = -1) - : tree_command (l, c), lhs (le), expr (re), list (lst) { } + tree_statement_list *lst, + octave_comment_list *lc = 0, + octave_comment_list *tc = 0, + int l = -1, int c = -1) + : tree_command (l, c), lhs (le), expr (re), list (lst), + lead_comm (lc), trail_comm (tc) { } ~tree_simple_for_command (void); @@ -144,6 +173,10 @@ tree_statement_list *body (void) { return list; } + octave_comment_list *leading_comment (void) { return lead_comm; } + + octave_comment_list *trailing_comment (void) { return trail_comm; } + void accept (tree_walker& tw); private: @@ -157,6 +190,12 @@ // List of commands to execute. tree_statement_list *list; + // Comment preceding FOR token. + octave_comment_list *lead_comm; + + // Comment preceding ENDFOR token. + octave_comment_list *trail_comm; + void do_for_loop_once (octave_lvalue &ult, const octave_value& rhs, bool& quit); @@ -173,11 +212,16 @@ public: tree_complex_for_command (int l = -1, int c = -1) - : tree_command (l, c), lhs (0), expr (0), list (0) { } + : tree_command (l, c), lhs (0), expr (0), list (0), lead_comm (0), + trail_comm (0) { } tree_complex_for_command (tree_argument_list *le, tree_expression *re, - tree_statement_list *lst, int l = -1, int c = -1) - : tree_command (l, c), lhs (le), expr (re), list (lst) { } + tree_statement_list *lst, + octave_comment_list *lc = 0, + octave_comment_list *tc = 0, + int l = -1, int c = -1) + : tree_command (l, c), lhs (le), expr (re), list (lst), + lead_comm (lc), trail_comm (tc) { } ~tree_complex_for_command (void); @@ -191,6 +235,10 @@ tree_statement_list *body (void) { return list; } + octave_comment_list *leading_comment (void) { return lead_comm; } + + octave_comment_list *trailing_comment (void) { return trail_comm; } + void accept (tree_walker& tw); private: @@ -204,6 +252,12 @@ // List of commands to execute. tree_statement_list *list; + // Comment preceding FOR token. + octave_comment_list *lead_comm; + + // Comment preceding ENDFOR token. + octave_comment_list *trail_comm; + void do_for_loop_once (octave_lvalue &val_ref, octave_lvalue &key_ref, const octave_value& val, const octave_value& key, bool& quit);
--- a/src/pt-pr-code.cc +++ b/src/pt-pr-code.cc @@ -28,8 +28,11 @@ #include <config.h> #endif +#include <cctype> + #include <iostream> +#include "comment-list.h" #include "error.h" #include "ov-usr-fcn.h" #include "pr-output.h" @@ -182,6 +185,8 @@ void tree_print_code::visit_simple_for_command (tree_simple_for_command& cmd) { + print_comment_list (cmd.leading_comment ()); + indent (); os << "for "; @@ -205,10 +210,14 @@ if (list) { increment_indent_level (); + list->accept (*this); + decrement_indent_level (); } + print_indented_comment (cmd.trailing_comment ()); + indent (); os << "endfor"; @@ -217,6 +226,8 @@ void tree_print_code::visit_complex_for_command (tree_complex_for_command& cmd) { + print_comment_list (cmd.leading_comment ()); + indent (); os << "for ["; @@ -240,10 +251,14 @@ if (list) { increment_indent_level (); + list->accept (*this); + decrement_indent_level (); } + print_indented_comment (cmd.trailing_comment ()); + indent (); os << "endfor"; @@ -261,7 +276,9 @@ if (cmd_list) { increment_indent_level (); + cmd_list->accept (*this); + decrement_indent_level (); } @@ -271,6 +288,14 @@ void tree_print_code::visit_octave_user_function_header (octave_user_function& fcn) { + octave_comment_list *leading_comment = fcn.leading_comment (); + + if (leading_comment) + { + print_comment_list (leading_comment); + newline (); + } + indent (); os << "function "; @@ -341,8 +366,10 @@ } void -tree_print_code::visit_octave_user_function_trailer (octave_user_function&) +tree_print_code::visit_octave_user_function_trailer (octave_user_function& fcn) { + print_indented_comment (fcn.trailing_comment ()); + indent (); os << "endfunction"; @@ -373,12 +400,12 @@ newline (); - increment_indent_level (); - tree_statement_list *list = cmd.commands (); if (list) { + increment_indent_level (); + list->accept (*this); decrement_indent_level (); @@ -388,6 +415,8 @@ void tree_print_code::visit_if_command (tree_if_command& cmd) { + print_comment_list (cmd.leading_comment ()); + indent (); os << "if "; @@ -397,6 +426,8 @@ if (list) list->accept (*this); + print_indented_comment (cmd.trailing_comment ()); + indent (); os << "endif"; @@ -417,6 +448,8 @@ { if (! first_elt) { + print_indented_comment (elt->leading_comment ()); + indent (); if (elt->is_else_clause ()) @@ -440,10 +473,16 @@ print_parens (expr, "("); + bool expr_has_parens = false; + tree_expression *e = expr.expression (); if (e) - e->accept (*this); + { + e->accept (*this); + + expr_has_parens = e->is_postfix_indexed (); + } tree_argument_list *list = expr.arg_list (); @@ -453,6 +492,8 @@ list->accept (*this); os << ")"; } + else if (expr_has_parens) + os << " ()"; print_parens (expr, ")"); } @@ -773,6 +814,8 @@ void tree_print_code::visit_statement (tree_statement& stmt) { + print_comment_list (stmt.comment_text ()); + tree_command *cmd = stmt.command (); if (cmd) @@ -928,6 +971,8 @@ void tree_print_code::visit_switch_case (tree_switch_case& cs) { + print_comment_list (cs.leading_comment ()); + indent (); if (cs.is_default_case ()) @@ -942,14 +987,16 @@ newline (); - increment_indent_level (); - tree_statement_list *list = cs.commands (); if (list) { + increment_indent_level (); + list->accept (*this); + newline (); + decrement_indent_level (); } } @@ -973,6 +1020,8 @@ void tree_print_code::visit_switch_command (tree_switch_command& cmd) { + print_comment_list (cmd.leading_comment ()); + indent (); os << "switch "; @@ -984,12 +1033,18 @@ newline (); - increment_indent_level (); - tree_switch_case_list *list = cmd.case_list (); if (list) - list->accept (*this); + { + increment_indent_level (); + + list->accept (*this); + + decrement_indent_level (); + } + + print_indented_comment (cmd.leading_comment ()); indent (); @@ -999,9 +1054,11 @@ void tree_print_code::visit_try_catch_command (tree_try_catch_command& cmd) { + print_comment_list (cmd.leading_comment ()); + indent (); - os << "try_catch"; + os << "try"; newline (); @@ -1010,10 +1067,14 @@ if (try_code) { increment_indent_level (); + try_code->accept (*this); + decrement_indent_level (); } + print_indented_comment (cmd.middle_comment ()); + indent (); os << "catch"; @@ -1025,10 +1086,14 @@ if (catch_code) { increment_indent_level (); + catch_code->accept (*this); + decrement_indent_level (); } + print_indented_comment (cmd.trailing_comment ()); + indent (); os << "end_try_catch"; @@ -1038,6 +1103,8 @@ tree_print_code::visit_unwind_protect_command (tree_unwind_protect_command& cmd) { + print_comment_list (cmd.leading_comment ()); + indent (); os << "unwind_protect"; @@ -1049,10 +1116,14 @@ if (unwind_protect_code) { increment_indent_level (); + unwind_protect_code->accept (*this); + decrement_indent_level (); } + print_indented_comment (cmd.middle_comment ()); + indent (); os << "unwind_protect_cleanup"; @@ -1064,10 +1135,14 @@ if (cleanup_code) { increment_indent_level (); + cleanup_code->accept (*this); + decrement_indent_level (); } + print_indented_comment (cmd.trailing_comment ()); + indent (); os << "end_unwind_protect"; @@ -1076,6 +1151,8 @@ void tree_print_code::visit_while_command (tree_while_command& cmd) { + print_comment_list (cmd.leading_comment ()); + indent (); os << "while "; @@ -1092,10 +1169,14 @@ if (list) { increment_indent_level (); + list->accept (*this); + decrement_indent_level (); } + print_indented_comment (cmd.trailing_comment ()); + indent (); os << "endwhile"; @@ -1104,6 +1185,8 @@ void tree_print_code::visit_do_until_command (tree_do_until_command& cmd) { + print_comment_list (cmd.leading_comment ()); + indent (); os << "do"; @@ -1115,10 +1198,14 @@ if (list) { increment_indent_level (); + list->accept (*this); + decrement_indent_level (); } + print_indented_comment (cmd.trailing_comment ()); + indent (); os << "until"; @@ -1186,6 +1273,91 @@ os << txt; } +void +tree_print_code::print_comment_elt (const octave_comment_elt& elt) +{ + bool printed_something = false; + + bool prev_char_was_newline = false; + + string comment = elt.text (); + + size_t len = comment.length (); + + size_t i = 0; + + while (i < len && comment[i++] == '\n') + ; /* Skip leading new lines. */ + i--; + + while (i < len) + { + char c = comment[i++]; + + if (c == '\n') + { + if (prev_char_was_newline) + os << "##"; + + newline (); + + prev_char_was_newline = true; + } + else + { + if (beginning_of_line) + { + printed_something = true; + + indent (); + + os << "##"; + + if (! (isspace (c) || c == '!')) + os << " "; + } + + os << (char) c; + + prev_char_was_newline = false; + } + } + + if (printed_something && ! beginning_of_line) + newline (); +} + +void +tree_print_code::print_comment_list (octave_comment_list *comment_list) +{ + if (comment_list) + { + Pix p = comment_list->first (); + + while (p) + { + octave_comment_elt elt = comment_list->operator () (p); + + print_comment_elt (elt); + + comment_list->next (p); + + if (p) + newline (); + } + } +} + +void +tree_print_code::print_indented_comment (octave_comment_list *comment_list) +{ + increment_indent_level (); + + print_comment_list (comment_list); + + decrement_indent_level (); +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/pt-pr-code.h +++ b/src/pt-pr-code.h @@ -29,6 +29,7 @@ #include <string> +#include "comment-list.h" #include "pt-walk.h" class tree_expression; @@ -168,6 +169,12 @@ void print_parens (const tree_expression& expr, const char *txt); + void print_comment_list (octave_comment_list *comment_list); + + void print_comment_elt (const octave_comment_elt& comment_elt); + + void print_indented_comment (octave_comment_list *comment_list); + // Must create with an output stream! tree_print_code (void);
--- a/src/pt-select.cc +++ b/src/pt-select.cc @@ -43,6 +43,7 @@ { delete expr; delete list; + delete lead_comm; } int @@ -90,6 +91,8 @@ tree_if_command::~tree_if_command (void) { delete list; + delete lead_comm; + delete trail_comm; } void @@ -115,6 +118,7 @@ { delete label; delete list; + delete lead_comm; } bool @@ -204,6 +208,8 @@ { delete expr; delete list; + delete lead_comm; + delete trail_comm; } void
--- a/src/pt-select.h +++ b/src/pt-select.h @@ -34,6 +34,7 @@ class tree_walker; +#include "comment-list.h" #include "pt-cmd.h" // If. @@ -44,13 +45,14 @@ public: tree_if_clause (void) - : expr (0), list (0) { } + : expr (0), list (0), lead_comm (0) { } - tree_if_clause (tree_statement_list *l) - : expr (0), list (l) { } + tree_if_clause (tree_statement_list *l, octave_comment_list *lc = 0) + : expr (0), list (l), lead_comm (lc) { } - tree_if_clause (tree_expression *e, tree_statement_list *l) - : expr (e), list (l) { } + tree_if_clause (tree_expression *e, tree_statement_list *l, + octave_comment_list *lc = 0) + : expr (e), list (l), lead_comm (lc) { } ~tree_if_clause (void); @@ -63,6 +65,8 @@ tree_statement_list *commands (void) { return list; } + octave_comment_list *leading_comment (void) { return lead_comm; } + void accept (tree_walker& tw); private: @@ -73,6 +77,9 @@ // The list of statements to evaluate if expr is true. tree_statement_list *list; + // Comment preceding ELSE or ELSEIF token. + octave_comment_list *lead_comm; + // No copying! tree_if_clause (const tree_if_clause&); @@ -119,10 +126,11 @@ public: tree_if_command (int l = -1, int c = -1) - : tree_command (l, c), list (0) { } + : tree_command (l, c), list (0), lead_comm (0), trail_comm (0) { } - tree_if_command (tree_if_command_list *lst, int l = -1, int c = -1) - : tree_command (l, c), list (lst) { } + tree_if_command (tree_if_command_list *lst, octave_comment_list *lc, + octave_comment_list *tc, int l = -1, int c = -1) + : tree_command (l, c), list (lst), lead_comm (lc), trail_comm (tc) { } ~tree_if_command (void); @@ -130,6 +138,10 @@ tree_if_command_list *cmd_list (void) { return list; } + octave_comment_list *leading_comment (void) { return lead_comm; } + + octave_comment_list *trailing_comment (void) { return trail_comm; } + void accept (tree_walker& tw); private: @@ -137,6 +149,12 @@ // List of if commands (if, elseif, elseif, ... else, endif) tree_if_command_list *list; + // Comment preceding IF token. + octave_comment_list *lead_comm; + + // Comment preceding ENDIF token. + octave_comment_list *trail_comm; + // No copying! tree_if_command (const tree_if_command&); @@ -152,13 +170,14 @@ public: tree_switch_case (void) - : label (0), list (0) { } + : label (0), list (0), lead_comm (0) { } - tree_switch_case (tree_statement_list *l) - : label (0), list (l) { } + tree_switch_case (tree_statement_list *l, octave_comment_list *lc = 0) + : label (0), list (l), lead_comm (lc) { } - tree_switch_case (tree_expression *e, tree_statement_list *l) - : label (e), list (l) { } + tree_switch_case (tree_expression *e, tree_statement_list *l, + octave_comment_list *lc = 0) + : label (e), list (l), lead_comm (lc) { } ~tree_switch_case (void); @@ -175,6 +194,8 @@ tree_statement_list *commands (void) { return list; } + octave_comment_list *leading_comment (void) { return lead_comm; } + void accept (tree_walker& tw); private: @@ -185,6 +206,9 @@ // The list of statements to evaluate if the label matches. tree_statement_list *list; + // Comment preceding CASE or OTHERWISE token. + octave_comment_list *lead_comm; + // No copying! tree_switch_case (const tree_switch_case&); @@ -231,11 +255,14 @@ public: tree_switch_command (int l = -1, int c = -1) - : tree_command (l, c), expr (0), list (0) { } + : tree_command (l, c), expr (0), list (0), lead_comm (0), + trail_comm (0) { } tree_switch_command (tree_expression *e, tree_switch_case_list *lst, + octave_comment_list *lc, octave_comment_list *tc, int l = -1, int c = -1) - : tree_command (l, c), expr (e), list (lst) { } + : tree_command (l, c), expr (e), list (lst), lead_comm (lc), + trail_comm (tc) { } ~tree_switch_command (void); @@ -247,6 +274,10 @@ tree_switch_case_list *case_list (void) { return list; } + octave_comment_list *leading_comment (void) { return lead_comm; } + + octave_comment_list *trailing_comment (void) { return trail_comm; } + void accept (tree_walker& tw); private: @@ -257,6 +288,12 @@ // List of cases (case 1, case 2, ..., default) tree_switch_case_list *list; + // Comment preceding SWITCH token. + octave_comment_list *lead_comm; + + // Comment preceding ENDSWITCH token. + octave_comment_list *trail_comm; + // No copying! tree_switch_command (const tree_switch_command&);
--- a/src/pt-stmt.cc +++ b/src/pt-stmt.cc @@ -56,6 +56,7 @@ { delete cmd; delete expr; + delete comm; } int
--- a/src/pt-stmt.h +++ b/src/pt-stmt.h @@ -36,6 +36,8 @@ class tree_walker; +#include "comment-list.h" + // A statement is either a command to execute or an expression to // evaluate. @@ -45,13 +47,13 @@ public: tree_statement (void) - : cmd (0), expr (0), print_flag (true) { } + : cmd (0), expr (0), comm (0), print_flag (true) { } - tree_statement (tree_command *c) - : cmd (c), expr (0), print_flag (true) { } + tree_statement (tree_command *c, octave_comment_list *cl) + : cmd (c), expr (0), comm (cl), print_flag (true) { } - tree_statement (tree_expression *e) - : cmd (0), expr (e), print_flag (true) { } + tree_statement (tree_expression *e, octave_comment_list *cl) + : cmd (0), expr (e), comm (cl), print_flag (true) { } ~tree_statement (void); @@ -77,6 +79,8 @@ tree_expression *expression (void) { return expr; } + octave_comment_list *comment_text (void) { return comm; } + void accept (tree_walker& tw); private: @@ -89,6 +93,9 @@ // Expression to evaluate. tree_expression *expr; + // Comment associated with this statement. + octave_comment_list *comm; + // Print result of eval for this command? bool print_flag;