view liboctave/util/lo-array-gripes.cc @ 20651:e54ecb33727e

lo-array-gripes.cc: Remove FIXME's related to buffer size. * lo-array-gripes.cc: Remove FIXME's related to buffer size. Shorten sprintf buffers from 100 to 64 characters (still well more than 19 required). Use 'const' decorator on constant value for clarity. Remove extra space between variable and array bracket.
author Rik <rik@octave.org>
date Mon, 12 Oct 2015 21:13:47 -0700
parents dd6345fd8a97
children
line wrap: on
line source

/*

Copyright (C) 2003-2015 John W. Eaton
Copyright (C) 2009 VZLU Prague

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 3 of the License, 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, see
<http://www.gnu.org/licenses/>.

*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string.h>
#include "lo-array-gripes.h"
#include "lo-error.h"

const char *error_id_nonconformant_args = "Octave:nonconformant-args";

const char *error_id_index_out_of_bounds = "Octave:index-out-of-bounds";

const char *error_id_invalid_index = "Octave:invalid-index";

const char *warning_id_nearly_singular_matrix = "Octave:nearly-singular-matrix";

const char *warning_id_singular_matrix = "Octave:singular-matrix";

void
gripe_nan_to_logical_conversion (void)
{
  (*current_liboctave_error_handler)
    ("invalid conversion from NaN to logical");
}

void
gripe_nan_to_character_conversion (void)
{
  (*current_liboctave_error_handler)
    ("invalid conversion from NaN to character");
}

void
gripe_nonconformant (const char *op, octave_idx_type op1_len,
                     octave_idx_type op2_len)
{
  const char *err_id = error_id_nonconformant_args;

  (*current_liboctave_error_with_id_handler)
    (err_id, "%s: nonconformant arguments (op1 len: %d, op2 len: %d)",
     op, op1_len, op2_len);
}

void
gripe_nonconformant (const char *op,
                     octave_idx_type op1_nr, octave_idx_type op1_nc,
                     octave_idx_type op2_nr, octave_idx_type op2_nc)
{
  const char *err_id = error_id_nonconformant_args;

  (*current_liboctave_error_with_id_handler)
    (err_id, "%s: nonconformant arguments (op1 is %dx%d, op2 is %dx%d)",
     op, op1_nr, op1_nc, op2_nr, op2_nc);
}

void
gripe_nonconformant (const char *op, const dim_vector& op1_dims,
                     const dim_vector& op2_dims)
{
  const char *err_id = error_id_nonconformant_args;

  std::string op1_dims_str = op1_dims.str ();
  std::string op2_dims_str = op2_dims.str ();

  (*current_liboctave_error_with_id_handler)
    (err_id, "%s: nonconformant arguments (op1 is %s, op2 is %s)",
     op, op1_dims_str.c_str (), op2_dims_str.c_str ());
}

void
gripe_del_index_out_of_range (bool is1d, octave_idx_type idx,
                              octave_idx_type ext)
{
  const char *err_id = error_id_index_out_of_bounds;

  (*current_liboctave_error_with_id_handler)
    (err_id, "A(%s) = []: index out of bounds; value %d out of bound %d",
     is1d ? "I" : "..,I,..", idx, ext);
}



// Common procedures of base class index_exception, thrown whenever an
// object is indexed incorrectly, such as by an index that is out of
// range, negative, fractional, complex, or of a non-numeric type.

const char *
index_exception::err (void) throw ()
{
  msg = access () + "; " + explain ();
  return msg.c_str ();
}

// Show what was illegally accessed, e.g.,  "A(-1,_)", "A(0+1i)", "A(_,3)"
// Show how many indices come before/after the offending one,
// e.g., (<error>), (<error>,_), or (_,<error>,...[x5]...)

std::string
index_exception:: access (void) const
{
  // FIXME: don't use a fixed size buffer!
  const int buf_len = 300;

  char output [buf_len];
  char pre [buf_len];
  char post [buf_len];

  // dim == 0 if position not yet given, or
  // <static_cast unsigned int>(-1) if explicitly shown to be unknown
  // both are caught by this condition

  if (static_cast <unsigned int> (dim-1) > 100000)
    {
      // No parentheses are given if the dimension is not known.
      pre[0] = post[0] = '\0';
    }
  else
    {
      if (dim < 5)
        {
          pre[0] = '(';
          octave_idx_type i;

          for (i = 1; i < dim; i++)
            {
              pre[2*i-1] = '_';
              pre[2*i]   = ',';
            }

          pre[2*i-1] = '\0';    // i == min (1, dim)
        }
      else
        {
          sprintf (pre, "(...[x%d]...", dim-1);
        }

      if (static_cast <unsigned int> (nd-dim) < 5)
        {
          for (octave_idx_type i = 0; i < nd-dim; i++)
            {
              post[2*i]   = ',';
              post[2*i+1] = '_';
            }

          if (nd >= dim)
            {
              post[2*(nd-dim)] = ')';
              post[2*(nd-dim)+1] = '\0';
            }
        }
      else
        sprintf (post, "...[x%d]...)", nd-dim);
    }

  const char *v;

  if (var[0] == '\0' || var == "<unknown>")
    v = "index ";
  else
    v = var.c_str ();

  snprintf (output, buf_len, "%s%s%s%s", v, pre, idx(), post);

  return output;
}

class invalid_index : public index_exception
{
public:

  invalid_index (const char *value, octave_idx_type ndim,
                 octave_idx_type dimen)
    : index_exception (value, ndim, dimen)
  { }

  const char* explain (void) const
  {
#ifdef USE_64_BIT_IDX_T
    return "subscripts must be either integers 1 to (2^63)-1 or logicals";
#else
    return "subscripts must be either integers 1 to (2^31)-1 or logicals";
#endif
  }

  // ID of error to throw
  const char* id (void) const
  {
    return error_id_invalid_index;
  }
};

// Complain of an index that is: negative, fractional, or too big.

void
gripe_invalid_index (const char *idx, octave_idx_type nd,
                     octave_idx_type dim, const char * /* var */)
{
    invalid_index e (idx, nd, dim);

    throw e;
}

void
gripe_invalid_index (octave_idx_type n, octave_idx_type nd,
                     octave_idx_type dim, const char *var)
{
  // Note: log10 (2^63) = 19 digits.  Use 64 for ease of memory alignment. 
  char buf[64];

  sprintf (buf, "%d", n+1);

  gripe_invalid_index (buf, nd, dim, var);
}

void
gripe_invalid_index (double n, octave_idx_type nd, octave_idx_type dim,
                     const char *var)
{
  char buf[64];

  sprintf (buf, "%g", n+1);

  gripe_invalid_index (buf, nd, dim, var);
}


// Gripe and exception for read access beyond the bounds of an array.

class out_of_range : public index_exception
{
public:

  out_of_range (const char *value, octave_idx_type nd_in,octave_idx_type dim_in)
        : index_exception (value, nd_in, dim_in), extent(0)
    { }

  const char* explain (void) const
  {
    static std::string expl;    // should probably be member variable, but
                                // then explain() can't be const.

    if (nd >= size.length ())   // if not an index slice
      {
        if (var != "")
          expl = "but " + var + " has size ";
        else
          expl = "but object has size ";

        expl = expl + size.str ('x');
      }
    else
      {
        char buf[64];
        sprintf (buf, "%d", extent);
        expl = "out of bound " + std::string (buf);
      }

    return expl.c_str ();
  }

  // ID of error to throw.
  const char* id (void) const
  {
    return (error_id_index_out_of_bounds);
  }

  void set_size (const dim_vector& size_in) { size = size_in; }

  void set_extent (octave_idx_type ext) { extent = ext; }

private:

  dim_vector size;          // dimension of object being accessed

  octave_idx_type extent;   // length of dimension being accessed
};

// Complain of an index that is out of range, but we don't know matrix size
void
gripe_index_out_of_range (int nd, int dim, octave_idx_type idx,
                          octave_idx_type ext)
{
    char buf[64];
    sprintf (buf, "%d", idx);
    out_of_range e (buf, nd, dim);

    e.set_extent (ext);
    dim_vector d (1,1,1,1,1,1,1);   // make explain() give extent not size
    e.set_size (d);
    throw e;
}

// Complain of an index that is out of range
void
gripe_index_out_of_range (int nd, int dim, octave_idx_type idx,
                          octave_idx_type ext, const dim_vector& d)
{
    char buf[64];
    sprintf (buf, "%d", idx);
    out_of_range e (buf, nd, dim);

    e.set_extent (ext);
    e.set_size (d);
    throw e;
}

void
gripe_invalid_resize (void)
{
  (*current_liboctave_error_with_id_handler)
    ("Octave:invalid-resize",
     "Invalid resizing operation or ambiguous assignment to an out-of-bounds array element");
}

void
gripe_singular_matrix (double rcond)
{
  if (rcond == 0.0)
    {
      (*current_liboctave_warning_with_id_handler)
        (warning_id_singular_matrix,
         "matrix singular to machine precision");
    }
  else
    {
      (*current_liboctave_warning_with_id_handler)
        (warning_id_nearly_singular_matrix,
         "matrix singular to machine precision, rcond = %g", rcond);
    }
}

/* Tests in test/index.tst */