# HG changeset patch # User Rik # Date 1450378528 28800 # Node ID 69dcb58b9adafd8f817372cf6bf77644564facf0 # Parent b6ea72a439f8932bebf520c48a055424e7b074e1 Clean up use of error() versus ::error() in stream-based code. * oct-fstrm.cc, oct-iostrm.cc, oct-strstrm.cc: Add comments before code that is specifically using error from stream class rather than ::error from error.h * oct-stream.cc: Overhaul file. Add programming note about difference between error() and ::error() at top of file. Put input validation first. Cuddle parentheses to variable when doing indexing. Declare variables as late as possible. Wrap lines < 80 characters, but try to break comments into intelligible blocks. Avoid declaring retval when returning a value would do just as well. diff -r b6ea72a439f8 -r 69dcb58b9ada libinterp/corefcn/oct-fstrm.cc --- a/libinterp/corefcn/oct-fstrm.cc Thu Dec 17 13:39:00 2015 -0500 +++ b/libinterp/corefcn/oct-fstrm.cc Thu Dec 17 10:55:28 2015 -0800 @@ -56,6 +56,7 @@ #endif if (! fs) + // Note: error() is inherited from octave_base_stream, not ::error(). error (gnulib::strerror (errno)); } @@ -64,6 +65,8 @@ int octave_fstream::seek (off_t, int) { + // Note: error() is inherited from octave_base_stream, not ::error(). + // This error function does not halt execution so "return ..." must exist. error ("fseek: invalid_operation"); return -1; } @@ -73,6 +76,8 @@ off_t octave_fstream::tell (void) { + // Note: error() is inherited from octave_base_stream, not ::error(). + // This error function does not halt execution so "return ..." must exist. error ("ftell: invalid_operation"); return -1; } diff -r b6ea72a439f8 -r 69dcb58b9ada libinterp/corefcn/oct-iostrm.cc --- a/libinterp/corefcn/oct-iostrm.cc Thu Dec 17 13:39:00 2015 -0500 +++ b/libinterp/corefcn/oct-iostrm.cc Thu Dec 17 10:55:28 2015 -0800 @@ -57,6 +57,7 @@ void octave_base_iostream::invalid_operation (void) const { + // Note: use '::error()' to get error from error.h which halts operation. ::error ("%s: invalid operation", stream_type ()); } diff -r b6ea72a439f8 -r 69dcb58b9ada libinterp/corefcn/oct-stream.cc --- a/libinterp/corefcn/oct-stream.cc Thu Dec 17 13:39:00 2015 -0500 +++ b/libinterp/corefcn/oct-stream.cc Thu Dec 17 10:55:28 2015 -0800 @@ -53,6 +53,17 @@ #include "toplev.h" #include "utils.h" +//////////////////////////////////////////////////////////////////////////////// +// Programming Note: There are two very different error() functions used +// in the stream code. When invoked with "error (...)" the member function +// from octave_stream or octave_base_stream is called. This function sets the +// error state on the stream AND returns control to the caller. The caller +// must then return a value at the end of the function. When invoked with +// "::error (...)" the exception-based error function from error.h is used. +// This function will throw an exception and not return control to the caller. +// BE CAREFUL and invoke the correct error function! +//////////////////////////////////////////////////////////////////////////////// + // Possible values for conv_err: // // 1 : not a real scalar @@ -102,21 +113,19 @@ { int retval = -1; - if (! lo_ieee_isnan (d)) + if (lo_ieee_isnan (d)) + ::error ("%s: NaN is invalid as size specification", who.c_str ()); + + if (xisinf (d)) + retval = -1; + else { - if (! xisinf (d)) - { - if (d >= 0.0) - retval = NINT (d); - else - ::error ("%s: negative value invalid as size specification", - who.c_str ()); - } + if (d >= 0.0) + retval = NINT (d); else - retval = -1; + ::error ("%s: negative value invalid as size specification", + who.c_str ()); } - else - ::error ("%s: NaN is invalid as size specification", who.c_str ()); return retval; } @@ -139,16 +148,16 @@ { one_elt_size_spec = true; - dnr = size (0); + dnr = size(0); dnc = (dnr == 0.0) ? 0.0 : 1.0; } else if (sz_len == 2) { - dnr = size (0); + dnr = size(0); if (! xisinf (dnr)) - dnc = size (1); + dnc = size(1); else ::error ("%s: invalid size specification", who.c_str ()); } @@ -936,17 +945,22 @@ octave_base_stream::do_gets (octave_idx_type max_len, bool& err, bool strip_newline, const std::string& who) { - std::string retval; - if (interactive && file_number () == 0) ::error ("%s: unable to read from stdin while running interactively", who.c_str ()); + std::string retval; + err = false; std::istream *isp = input_stream (); - if (isp) + if (! isp) + { + err = true; + invalid_operation (who, "reading"); + } + else { std::istream& is = *isp; @@ -962,7 +976,6 @@ char_count++; // Handle CRLF, CR, or LF as line ending. - if (c == '\r') { if (! strip_newline) @@ -1002,9 +1015,9 @@ if (! is.eof () && char_count > 0) { - // GAGME. Matlab seems to check for EOF even if the last - // character in a file is a newline character. This is NOT - // what the corresponding C-library functions do. + // GAGME. Matlab seems to check for EOF even if the last character + // in a file is a newline character. This is NOT what the + // corresponding C-library functions do. int disgusting_compatibility_hack = is.get (); if (! is.eof ()) is.putback (disgusting_compatibility_hack); @@ -1022,11 +1035,6 @@ error (who, "read error"); } } - else - { - err = true; - invalid_operation (who, "reading"); - } return retval; } @@ -1048,21 +1056,22 @@ off_t octave_base_stream::skipl (off_t num, bool& err, const std::string& who) { + if (interactive && file_number () == 0) + ::error ("%s: unable to read from stdin while running interactively", + who.c_str ()); + off_t cnt = -1; - if (interactive && file_number () == 0) - { - ::error ("%s: unable to read from stdin while running interactively", - who.c_str ()); - - return count; - } - err = false; std::istream *isp = input_stream (); - if (isp) + if (! isp) + { + err = true; + invalid_operation (who, "reading"); + } + else { std::istream& is = *isp; @@ -1073,7 +1082,6 @@ while (is && (c = is.get ()) != EOF) { // Handle CRLF, CR, or LF as line ending. - if (c == '\r' || (c == '\n' && lastc != '\r')) { if (++cnt == num) @@ -1096,11 +1104,6 @@ if (err) cnt = -1; } - else - { - err = true; - invalid_operation (who, "reading"); - } return cnt; } @@ -1128,7 +1131,7 @@ int c1 = EOF; while (is && (c1 = is.get ()) != EOF && isspace (c1)) - /* skip whitespace */; + { /* skip whitespace */ } if (c1 != EOF) { @@ -1180,7 +1183,6 @@ { // Limit input to fmt.width characters by reading into a // temporary stringstream buffer. - std::string tmp; is.width (fmt.width); @@ -1222,7 +1224,7 @@ int c1 = EOF; while (is && (c1 = is.get ()) != EOF && isspace (c1)) - /* skip whitespace */; + { /* skip whitespace */ } if (c1 != EOF) { @@ -1250,25 +1252,25 @@ { OCTAVE_SCAN (is, fmt, valptr); - if (is) + if (! is) + return; + + if (idx == max_size && ! discard) { - if (idx == max_size && ! discard) - { - max_size *= 2; - - if (nr > 0) - mval.resize (nr, max_size / nr, 0.0); - else - mval.resize (max_size, 1, 0.0); - - data = mval.fortran_vec (); - } - - if (! discard) - { - conversion_count++; - data[idx++] = *(valptr); - } + max_size *= 2; + + if (nr > 0) + mval.resize (nr, max_size / nr, 0.0); + else + mval.resize (max_size, 1, 0.0); + + data = mval.fortran_vec (); + } + + if (! discard) + { + conversion_count++; + data[idx++] = *(valptr); } } @@ -1283,7 +1285,7 @@ int c = EOF; \ \ while (is && (c = is.get ()) != EOF && isspace (c)) \ - /* skip whitespace */; \ + { /* skip whitespace */ } \ \ if (c != EOF) \ is.putback (c); \ @@ -1497,16 +1499,12 @@ octave_idx_type& conversion_count, const std::string& who) { + if (interactive && file_number () == 0) + ::error ("%s: unable to read from stdin while running interactively", + who.c_str ()); + octave_value retval = Matrix (); - if (interactive && file_number () == 0) - { - ::error ("%s: unable to read from stdin while running interactively", - who.c_str ()); - - return retval; - } - conversion_count = 0; octave_idx_type nconv = fmt_list.num_conversions (); @@ -1535,10 +1533,8 @@ if (all_char_conv) { - // Any of these could be resized later (if we have %s - // conversions, we may read more than one element for each - // conversion). - + // Any of these could be resized later (if we have %s conversions, + // we may read more than one element for each conversion). if (one_elt_size_spec) { max_size = 512; @@ -1612,13 +1608,11 @@ || elt->type == '%') && max_conv > 0 && conversion_count == max_conv)) { - // We are done, either because we have reached the end - // of the format string and are not cycling through - // the format again or because we've converted all the - // values that have been requested and the next format - // element is a conversion. Determine final array - // size and exit. - + // We are done, either because we have reached the end of the + // format string and are not cycling through the format again + // or because we've converted all the values that have been + // requested and the next format element is a conversion. + // Determine final array size and exit. if (all_char_conv && one_elt_size_spec) { final_nr = 1; @@ -1829,18 +1823,15 @@ // If it looks like we have a matching failure, then // reset the failbit in the stream state. - if (is.rdstate () & std::ios::failbit) is.clear (is.rdstate () & (~std::ios::failbit)); // FIXME: is this the right thing to do? - if (interactive && ! forced_interactive && name () == "stdin") { is.clear (); // Skip to end of line. - bool err; do_gets (-1, err, false, who); } @@ -1871,11 +1862,10 @@ } else { - // Cycle through the format list more than once if we have - // some conversions to make and we haven't reached the - // limit on the number of values to convert (possibly - // because there is no specified limit). - + // Cycle through the format list more than once if we have some + // conversions to make and we haven't reached the limit on the + // number of values to convert (possibly because there is no + // specified limit). elt = fmt_list.next (nconv > 0 && (max_conv == 0 || conversion_count < max_conv)); @@ -1907,27 +1897,25 @@ std::istream *isp = input_stream (); - if (isp) + if (! isp) + invalid_operation (who, "reading"); + else { scanf_format_list fmt_list (fmt); if (fmt_list.num_conversions () == -1) ::error ("%s: invalid format specified", who.c_str ()); - else - { - octave_idx_type nr = -1; - octave_idx_type nc = -1; - - bool one_elt_size_spec; - - get_size (size, nr, nc, one_elt_size_spec, who); - - retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec, - conversion_count, who); - } + + octave_idx_type nr = -1; + octave_idx_type nc = -1; + + bool one_elt_size_spec; + + get_size (size, nr, nc, one_elt_size_spec, who); + + retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec, + conversion_count, who); } - else - invalid_operation (who, "reading"); return retval; } @@ -1936,145 +1924,144 @@ octave_base_stream::do_oscanf (const scanf_format_elt *elt, octave_value& retval, const std::string& who) { + std::istream *isp = input_stream (); + + if (! isp) + return false; + bool quit = false; - std::istream *isp = input_stream (); - - if (isp) + std::istream& is = *isp; + + std::ios::fmtflags flags = is.flags (); + + if (elt) { - std::istream& is = *isp; - - std::ios::fmtflags flags = is.flags (); - - if (elt) + const char *fmt = elt->text; + + bool discard = elt->discard; + + switch (elt->type) { - const char *fmt = elt->text; - - bool discard = elt->discard; - - switch (elt->type) - { - case scanf_format_elt::whitespace_conversion: - DO_WHITESPACE_CONVERSION (); - break; - - case scanf_format_elt::literal_conversion: - DO_LITERAL_CONVERSION (); - break; - - case '%': - { - DO_PCT_CONVERSION (); - - if (! is) - quit = true; - - } - break; - - case 'd': case 'i': + case scanf_format_elt::whitespace_conversion: + DO_WHITESPACE_CONVERSION (); + break; + + case scanf_format_elt::literal_conversion: + DO_LITERAL_CONVERSION (); + break; + + case '%': + { + DO_PCT_CONVERSION (); + + if (! is) + quit = true; + } + break; + + case 'd': case 'i': + { + int tmp; + + if (OCTAVE_SCAN (is, *elt, &tmp)) { - int tmp; - - if (OCTAVE_SCAN (is, *elt, &tmp)) - { - if (! discard) - retval = tmp; - } - else - quit = true; + if (! discard) + retval = tmp; } - break; - - case 'o': case 'u': case 'x': + else + quit = true; + } + break; + + case 'o': case 'u': case 'x': + { + long int tmp; + + if (OCTAVE_SCAN (is, *elt, &tmp)) { - long int tmp; - - if (OCTAVE_SCAN (is, *elt, &tmp)) - { - if (! discard) - retval = tmp; - } - else - quit = true; - } - break; - - case 'e': case 'f': case 'g': - { - double tmp; - - if (OCTAVE_SCAN (is, *elt, &tmp)) - { - if (! discard) - retval = tmp; - } - else - quit = true; - } - break; - - case 'c': - { - BEGIN_C_CONVERSION (); - if (! discard) retval = tmp; - - if (! is) - quit = true; - - is.setf (flags); } - break; - - case 's': + else + quit = true; + } + break; + + case 'e': case 'f': case 'g': + { + double tmp; + + if (OCTAVE_SCAN (is, *elt, &tmp)) { - BEGIN_S_CONVERSION (); - - if (! discard) - retval = tmp; - - if (! is) - quit = true; - } - break; - - case '[': case '^': - { - BEGIN_CHAR_CLASS_CONVERSION (); - if (! discard) retval = tmp; - - if (! is) - quit = true; } - break; - - case 'p': - error ("%s: unsupported format specifier", who.c_str ()); - break; - - default: - error ("%s: internal format error", who.c_str ()); - break; - } + else + quit = true; + } + break; + + case 'c': + { + BEGIN_C_CONVERSION (); + + if (! discard) + retval = tmp; + + if (! is) + quit = true; + + is.setf (flags); + } + break; + + case 's': + { + BEGIN_S_CONVERSION (); + + if (! discard) + retval = tmp; + + if (! is) + quit = true; + } + break; + + case '[': + case '^': + { + BEGIN_CHAR_CLASS_CONVERSION (); + + if (! discard) + retval = tmp; + + if (! is) + quit = true; + } + break; + + case 'p': + error ("%s: unsupported format specifier", who.c_str ()); + break; + + default: + error ("%s: internal format error", who.c_str ()); + break; } - - if (ok () && is.fail ()) + } + + if (ok () && is.fail ()) + { + error ("%s: read error", who.c_str ()); + + // FIXME: is this the right thing to do? + + if (interactive && ! forced_interactive && name () == "stdin") { - error ("%s: read error", who.c_str ()); - - // FIXME: is this the right thing to do? - - if (interactive && ! forced_interactive && name () == "stdin") - { - // Skip to end of line. - - bool err; - do_gets (-1, err, false, who); - } + // Skip to end of line. + bool err; + do_gets (-1, err, false, who); } } @@ -2088,7 +2075,9 @@ std::istream *isp = input_stream (); - if (isp) + if (! isp) + invalid_operation (who, "reading"); + else { std::istream& is = *isp; @@ -2098,67 +2087,63 @@ if (nconv == -1) ::error ("%s: invalid format specified", who.c_str ()); - else + + is.clear (); + + octave_idx_type len = fmt_list.length (); + + retval.resize (nconv+2, Matrix ()); + + const scanf_format_elt *elt = fmt_list.first (); + + int num_values = 0; + + bool quit = false; + + for (octave_idx_type i = 0; i < len; i++) { - is.clear (); - - octave_idx_type len = fmt_list.length (); - - retval.resize (nconv+2, Matrix ()); - - const scanf_format_elt *elt = fmt_list.first (); - - int num_values = 0; - - bool quit = false; - - for (octave_idx_type i = 0; i < len; i++) + octave_value tmp; + + quit = do_oscanf (elt, tmp, who); + + if (quit) + break; + else + { + if (tmp.is_defined ()) + retval(num_values++) = tmp; + + if (! ok ()) + break; + + elt = fmt_list.next (nconv > 0); + } + } + + retval(nconv) = num_values; + + int err_num; + retval(nconv+1) = error (false, err_num); + + if (! quit) + { + // Pick up any trailing stuff. + if (ok () && len > nconv) { octave_value tmp; - quit = do_oscanf (elt, tmp, who); - - if (quit) - break; - else - { - if (tmp.is_defined ()) - retval(num_values++) = tmp; - - if (! ok ()) - break; - - elt = fmt_list.next (nconv > 0); - } - } - - retval(nconv) = num_values; - - int err_num; - retval(nconv+1) = error (false, err_num); - - if (! quit) - { - // Pick up any trailing stuff. - if (ok () && len > nconv) - { - octave_value tmp; - - elt = fmt_list.next (); - - do_oscanf (elt, tmp, who); - } + elt = fmt_list.next (); + + do_oscanf (elt, tmp, who); } } } - else - invalid_operation (who, "reading"); return retval; } -// Functions that are defined for all output streams (output streams -// are those that define os). +// Functions that are defined for all output streams +// (output streams are those that define os). int octave_base_stream::flush (void) @@ -2167,15 +2152,15 @@ std::ostream *os = output_stream (); - if (os) + if (! os) + invalid_operation ("fflush", "writing"); + else { os->flush (); if (os->good ()) retval = 0; } - else - invalid_operation ("fflush", "writing"); return retval; } @@ -2274,7 +2259,6 @@ { // Convert to character string while values are // integers in the range [0 : char max] - const NDArray val = curr_val.array_value (); octave_idx_type idx = elt_idx; @@ -2512,11 +2496,9 @@ std::string tfmt = fmt; std::string::size_type i1, i2; - tfmt.replace ((i1 = tfmt.rfind (elt->type)), - 1, 1, 's'); - - if ((i2 = tfmt.rfind ('.')) != std::string::npos - && i2 < i1) + tfmt.replace ((i1 = tfmt.rfind (elt->type)), 1, 1, 's'); + + if ((i2 = tfmt.rfind ('.')) != std::string::npos && i2 < i1) { tfmt.erase (i2, i1-i2); if (elt->prec == -2) @@ -2606,6 +2588,8 @@ break; default: + // Note: error() is member fcn from octave_base_stream, not ::error(). + // This error() does not halt execution so "return ..." must exist. error ("%s: invalid format specifier", who.c_str ()); return -1; break; @@ -2626,7 +2610,9 @@ std::ostream *osp = output_stream (); - if (osp) + if (! osp) + invalid_operation (who, "writing"); + else { std::ostream& os = *osp; @@ -2641,7 +2627,6 @@ if (elt) { // NSA is the number of 'star' args to convert. - int nsa = (elt->fw == -2) + (elt->prec == -2); int sa_1 = 0; @@ -2714,6 +2699,8 @@ } else { + // FIXME: should this be member fcn "error"? + // Otherwise, retval and break are unnecessary. ::error ("%s: internal error handling format", who.c_str ()); retval = -1; break; @@ -2725,8 +2712,6 @@ break; } } - else - invalid_operation (who, "writing"); return retval; } @@ -2736,16 +2721,12 @@ const octave_value_list& args, const std::string& who) { - int retval = 0; - printf_format_list fmt_list (fmt); if (fmt_list.num_conversions () == -1) ::error ("%s: invalid format specified", who.c_str ()); - else - retval = do_printf (fmt_list, args, who); - - return retval; + + return do_printf (fmt_list, args, who); } int @@ -2755,13 +2736,17 @@ std::ostream *osp = output_stream (); - if (osp) + if (! osp) + invalid_operation (who, "writing"); + else { std::ostream& os = *osp; os << s; - if (os) + if (! os) + error ("%s: write error", who.c_str ()); + else { // FIXME: why does this seem to be necessary? // Without it, output from a loop like @@ -2769,7 +2754,6 @@ // for i = 1:100, fputs (stdout, "foo\n"); endfor // // doesn't seem to go to the pager immediately. - os.flush (); if (os) @@ -2777,11 +2761,7 @@ else error ("%s: write error", who.c_str ()); } - else - error ("%s: write error", who.c_str ()); } - else - invalid_operation (who, "writing"); return retval; } @@ -2804,8 +2784,7 @@ void octave_base_stream::invalid_operation (const std::string& who, const char *rw) { - // Note that this is not ::error () ! - + // Note: This calls the member fcn error(), not ::error() from error.h. error (who, std::string ("stream not open for ") + rw); } @@ -2872,8 +2851,6 @@ octave_stream::getl (const octave_value& tc_max_len, bool& err, const std::string& who) { - std::string retval; - err = false; int conv_err = 0; @@ -2891,9 +2868,7 @@ } } - retval = getl (max_len, err, who); - - return retval; + return getl (max_len, err, who); } std::string @@ -2911,8 +2886,6 @@ octave_stream::gets (const octave_value& tc_max_len, bool& err, const std::string& who) { - std::string retval; - err = false; int conv_err = 0; @@ -2930,9 +2903,7 @@ } } - retval = gets (max_len, err, who); - - return retval; + return gets (max_len, err, who); } off_t @@ -2950,8 +2921,6 @@ octave_stream::skipl (const octave_value& tc_count, bool& err, const std::string& who) { - off_t retval = -1; - err = false; int conv_err = 0; @@ -2974,9 +2943,7 @@ } } - retval = skipl (count, err, who); - - return retval; + return skipl (count, err, who); } int @@ -2989,11 +2956,9 @@ clearerr (); // Find current position so we can return to it if needed. - off_t orig_pos = rep->tell (); // Move to end of file. If successful, find the offset of the end. - status = rep->seek (0, SEEK_END); if (status == 0) @@ -3002,32 +2967,27 @@ if (origin == SEEK_CUR) { - // Move back to original position, otherwise we will be - // seeking from the end of file which is probably not the - // original location. - + // Move back to original position, otherwise we will be seeking + // from the end of file which is probably not the original + // location. rep->seek (orig_pos, SEEK_SET); } - // Attempt to move to desired position; may be outside bounds - // of existing file. - + // Attempt to move to desired position; may be outside bounds of + // existing file. status = rep->seek (offset, origin); if (status == 0) { // Where are we after moving to desired position? - off_t desired_pos = rep->tell (); - // I don't think save_pos can be less than zero, but we'll - // check anyway... - + // I don't think save_pos can be less than zero, + // but we'll check anyway... if (desired_pos > eof_pos || desired_pos < 0) { - // Seek outside bounds of file. Failure should leave - // position unchanged. - + // Seek outside bounds of file. + // Failure should leave position unchanged. rep->seek (orig_pos, SEEK_SET); status = -1; @@ -3035,9 +2995,8 @@ } else { - // Seeking to the desired position failed. Move back to - // original position and return failure status. - + // Seeking to the desired position failed. + // Move back to original position and return failure status. rep->seek (orig_pos, SEEK_SET); status = -1; @@ -3097,9 +3056,11 @@ retval = seek (xoffset, origin); if (retval != 0) + // FIXME: Should this be ::error()? error ("fseek: failed to seek to requested position"); } else + // FIXME: Should this be ::error()? error ("fseek: invalid value for origin"); return retval; @@ -3324,11 +3285,11 @@ default: retval = false; + // FIXME: Should this be ::error()? error ("read: invalid type specification"); break; } - return retval; } @@ -3346,180 +3307,178 @@ bool one_elt_size_spec = false; - if (stream_ok ()) + if (! stream_ok ()) + return retval; + + // FIXME: we may eventually want to make this extensible. + + // FIXME: we need a better way to ensure that this + // numbering stays consistent with the order of the elements in the + // data_type enum in the oct_data_conv class. + + // Expose this in a future version? + octave_idx_type char_count = 0; + + count = 0; + + try { - // FIXME: we may eventually want to make this extensible. - - // FIXME: we need a better way to ensure that this - // numbering stays consistent with the order of the elements in the - // data_type enum in the oct_data_conv class. - - // Expose this in a future version? - octave_idx_type char_count = 0; - - count = 0; - - try - { - get_size (size, nr, nc, one_elt_size_spec, "fread"); - } - catch (const octave_execution_exception&) - { - invalid_operation ("fread", "reading"); - } - - octave_idx_type elts_to_read; - - if (one_elt_size_spec) - { - // If NR == 0, Matlab returns [](0x0). - - // If NR > 0, the result will be a column vector with the given - // number of rows. - - // If NR < 0, then we have Inf and the result will be a column - // vector but we have to wait to see how big NR will be. - - if (nr == 0) - nr = nc = 0; - else - nc = 1; - } + get_size (size, nr, nc, one_elt_size_spec, "fread"); + } + catch (const octave_execution_exception&) + { + invalid_operation ("fread", "reading"); + } + + octave_idx_type elts_to_read; + + if (one_elt_size_spec) + { + // If NR == 0, Matlab returns [](0x0). + + // If NR > 0, the result will be a column vector with the given + // number of rows. + + // If NR < 0, then we have Inf and the result will be a column + // vector but we have to wait to see how big NR will be. + + if (nr == 0) + nr = nc = 0; else - { - // Matlab returns [] even if there are two elements in the size - // specification and one is nonzero. - - // If NC < 0 we have [NR, Inf] and we'll wait to decide how big NC - // should be. - - if (nr == 0 || nc == 0) - nr = nc = 0; - } - - // FIXME: Ensure that this does not overflow. - // Maybe try comparing nr * nc computed in double with - // std::numeric_limits::max (); - - elts_to_read = nr * nc; - - bool read_to_eof = elts_to_read < 0; - - octave_idx_type input_buf_elts = -1; - - if (skip == 0) - { - if (read_to_eof) - input_buf_elts = 1024 * 1024; - else - input_buf_elts = elts_to_read; - } + nc = 1; + } + else + { + // Matlab returns [] even if there are two elements in the size + // specification and one is nonzero. + + // If NC < 0 we have [NR, Inf] and we'll wait to decide how big NC + // should be. + + if (nr == 0 || nc == 0) + nr = nc = 0; + } + + // FIXME: Ensure that this does not overflow. + // Maybe try comparing nr * nc computed in double with + // std::numeric_limits::max (); + elts_to_read = nr * nc; + + bool read_to_eof = elts_to_read < 0; + + octave_idx_type input_buf_elts = -1; + + if (skip == 0) + { + if (read_to_eof) + input_buf_elts = 1024 * 1024; else - input_buf_elts = block_size; - - octave_idx_type input_elt_size - = oct_data_conv::data_type_size (input_type); - - octave_idx_type input_buf_size = input_buf_elts * input_elt_size; - - assert (input_buf_size >= 0); - - // Must also work and return correct type object - // for 0 elements to read. - - std::istream *isp = input_stream (); - - if (isp) + input_buf_elts = elts_to_read; + } + else + input_buf_elts = block_size; + + octave_idx_type input_elt_size + = oct_data_conv::data_type_size (input_type); + + octave_idx_type input_buf_size = input_buf_elts * input_elt_size; + + assert (input_buf_size >= 0); + + // Must also work and return correct type object + // for 0 elements to read. + std::istream *isp = input_stream (); + + if (! isp) + error ("fread: invalid input stream"); + else + { + std::istream& is = *isp; + + std::list input_buf_list; + + while (is && ! is.eof () + && (read_to_eof || count < elts_to_read)) { - std::istream& is = *isp; - - std::list input_buf_list; - - while (is && ! is.eof () - && (read_to_eof || count < elts_to_read)) + if (! read_to_eof) + { + octave_idx_type remaining_elts = elts_to_read - count; + + if (remaining_elts < input_buf_elts) + input_buf_size = remaining_elts * input_elt_size; + } + + char *input_buf = new char [input_buf_size]; + + is.read (input_buf, input_buf_size); + + size_t gcount = is.gcount (); + + char_count += gcount; + + octave_idx_type nel = gcount / input_elt_size; + + count += nel; + + input_buf_list.push_back (input_buf); + + if (is && skip != 0 && nel == block_size) { - if (! read_to_eof) - { - octave_idx_type remaining_elts = elts_to_read - count; - - if (remaining_elts < input_buf_elts) - input_buf_size = remaining_elts * input_elt_size; - } - - char *input_buf = new char [input_buf_size]; - - is.read (input_buf, input_buf_size); - - size_t gcount = is.gcount (); - - char_count += gcount; - - octave_idx_type nel = gcount / input_elt_size; - - count += nel; - - input_buf_list.push_back (input_buf); - - if (is && skip != 0 && nel == block_size) - { - // Seek to skip. If skip would move past EOF, - // position at EOF. - - off_t orig_pos = tell (); - - seek (0, SEEK_END); - - off_t eof_pos = tell (); - - // Is it possible for this to fail to return us to - // the original position? - seek (orig_pos, SEEK_SET); - - off_t remaining = eof_pos - orig_pos; - - if (remaining < skip) - seek (0, SEEK_END); - else - seek (skip, SEEK_CUR); - - if (! is) - break; - } + // Seek to skip. + // If skip would move past EOF, position at EOF. + + off_t orig_pos = tell (); + + seek (0, SEEK_END); + + off_t eof_pos = tell (); + + // Is it possible for this to fail to return us to + // the original position? + seek (orig_pos, SEEK_SET); + + off_t remaining = eof_pos - orig_pos; + + if (remaining < skip) + seek (0, SEEK_END); + else + seek (skip, SEEK_CUR); + + if (! is) + break; } - - if (read_to_eof) - { - if (nc < 0) - { - nc = count / nr; - - if (count % nr != 0) - nc++; - } - else - nr = count; - } - else if (count == 0) + } + + if (read_to_eof) + { + if (nc < 0) { - nr = 0; - nc = 0; - } - else if (count != nr * nc) - { + nc = count / nr; + if (count % nr != 0) - nc = count / nr + 1; - else - nc = count / nr; - - if (count < nr) - nr = count; + nc++; } - - retval = finalize_read (input_buf_list, input_buf_elts, count, - nr, nc, input_type, output_type, ffmt); + else + nr = count; + } + else if (count == 0) + { + nr = 0; + nc = 0; } - else - error ("fread: invalid input stream"); + else if (count != nr * nc) + { + if (count % nr != 0) + nc = count / nr + 1; + else + nc = count / nr; + + if (count < nr) + nr = count; + } + + retval = finalize_read (input_buf_list, input_buf_elts, count, + nr, nc, input_type, output_type, ffmt); } return retval; @@ -3532,7 +3491,9 @@ { octave_idx_type retval = -1; - if (stream_ok ()) + if (! stream_ok ()) + invalid_operation ("fwrite", "writing"); + else { if (flt_fmt == oct_mach_info::flt_fmt_unknown) flt_fmt = float_format (); @@ -3545,8 +3506,6 @@ else retval = status; } - else - invalid_operation ("fwrite", "writing"); return retval; } @@ -3574,9 +3533,7 @@ for (octave_idx_type i = 0; i < n_elts; i++) { - // Yes, we want saturation semantics when converting to an integer - // type. - + // Yes, we want saturation semantics when converting to an integer type. V val (data[i]); vt_data[i] = val.value (); @@ -3693,6 +3650,7 @@ default: retval = false; + // FIXME: Should this be ::error()? error ("write: invalid type specification"); break; } @@ -3730,41 +3688,38 @@ std::ostream *osp = output_stream (); - if (osp) + if (! osp) + return false; + + std::ostream& os = *osp; + + // Seek to skip when inside bounds of existing file. + // Otherwise, write NUL to skip. + off_t orig_pos = tell (); + + seek (0, SEEK_END); + + off_t eof_pos = tell (); + + // Is it possible for this to fail to return us to the original position? + seek (orig_pos, SEEK_SET); + + size_t remaining = eof_pos - orig_pos; + + if (remaining < skip) { - std::ostream& os = *osp; - - // Seek to skip when inside bounds of existing file. - // Otherwise, write NUL to skip. - - off_t orig_pos = tell (); - seek (0, SEEK_END); - off_t eof_pos = tell (); - - // Is it possible for this to fail to return us to the - // original position? - seek (orig_pos, SEEK_SET); - - size_t remaining = eof_pos - orig_pos; - - if (remaining < skip) - { - seek (0, SEEK_END); - - // FIXME: probably should try to write larger blocks... - - unsigned char zero = 0; - for (size_t j = 0; j < skip - remaining; j++) - os.write (reinterpret_cast (&zero), 1); - } - else - seek (skip, SEEK_CUR); - - if (os) - status = true; + // FIXME: probably should try to write larger blocks... + unsigned char zero = 0; + for (size_t j = 0; j < skip - remaining; j++) + os.write (reinterpret_cast (&zero), 1); } + else + seek (skip, SEEK_CUR); + + if (os) + status = true; return status; } @@ -3896,8 +3851,7 @@ } else { - // Note that this is not ::error () ! - + // Note: error() is member fcn from octave_stream, not ::error(). error (who + ": format must be a string"); } @@ -3931,8 +3885,7 @@ } else { - // Note that this is not ::error () ! - + // Note: error() is member fcn from octave_stream, not ::error(). error (who + ": format must be a string"); } @@ -3968,8 +3921,7 @@ } else { - // Note that this is not ::error () ! - + // Note: error() is member fcn from octave_stream, not ::error(). error (who + ": format must be a string"); } @@ -4001,8 +3953,7 @@ } else { - // Note that this is not ::error () ! - + // Note: error() is member fcn from octave_stream, not ::error(). error (who + ": argument must be a string"); } @@ -4196,9 +4147,9 @@ { // Insert item with key corresponding to file-descriptor. - int stream_number; - - if ((stream_number = os.file_number ()) == -1) + int stream_number = os.file_number (); + + if (stream_number == -1) return stream_number; // Should we test for @@ -4219,6 +4170,7 @@ else { stream_number = -1; + // FIXME: Should this be ::error()? error ("could not create file id"); } @@ -4267,13 +4219,9 @@ octave_stream_list::do_lookup (const octave_value& fid, const std::string& who) const { - octave_stream retval; - int i = get_file_number (fid); - retval = do_lookup (i, who); - - return retval; + return do_lookup (i, who); } int @@ -4282,11 +4230,15 @@ int retval = -1; // Can't remove stdin (std::cin), stdout (std::cout), or stderr (std::cerr). - if (fid > 2) + if (fid < 3) + gripe_invalid_file_id (fid, who); + else { ostrl_map::iterator iter = list.find (fid); - if (iter != list.end ()) + if (iter == list.end ()) + gripe_invalid_file_id (fid, who); + else { octave_stream os = iter->second; list.erase (iter); @@ -4301,11 +4253,7 @@ else gripe_invalid_file_id (fid, who); } - else - gripe_invalid_file_id (fid, who); } - else - gripe_invalid_file_id (fid, who); return retval; } @@ -4393,25 +4341,19 @@ string_vector octave_stream_list::do_get_info (const octave_value& fid) const { - string_vector retval; - int conv_err = 0; int int_fid = convert_to_valid_int (fid, conv_err); - if (! conv_err) - retval = do_get_info (int_fid); - else + if (conv_err) ::error ("file id must be a file object or integer value"); - return retval; + return do_get_info (int_fid); } std::string octave_stream_list::do_list_open_files (void) const { - std::string retval; - std::ostringstream buf; buf << "\n" @@ -4439,9 +4381,7 @@ buf << "\n"; - retval = buf.str (); - - return retval; + return buf.str (); } octave_value @@ -4454,7 +4394,6 @@ for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++) { // Skip stdin, stdout, and stderr. - if (p->first > 2 && p->second) retval(0,num_open++) = p->first; } @@ -4475,9 +4414,7 @@ for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++) { - // stdin (std::cin), stdout (std::cout), and stderr (std::cerr) - // are unnamed. - + // stdin, stdout, and stderr are unnamed. if (p->first > 2) { octave_stream os = p->second; @@ -4498,8 +4435,8 @@ if (conv_err) ::error ("file id must be a file object, std::string, or integer value"); - else - retval = int_fid; + + retval = int_fid; } return retval; diff -r b6ea72a439f8 -r 69dcb58b9ada libinterp/corefcn/oct-strstrm.cc --- a/libinterp/corefcn/oct-strstrm.cc Thu Dec 17 13:39:00 2015 -0500 +++ b/libinterp/corefcn/oct-strstrm.cc Thu Dec 17 10:55:28 2015 -0800 @@ -31,6 +31,8 @@ int octave_base_strstream::seek (off_t, int) { + // Note: error() is inherited from octave_base_stream, not ::error(). + // This error function does not halt execution so "return ..." must exist. error ("fseek: invalid operation"); return -1; } @@ -40,6 +42,8 @@ off_t octave_base_strstream::tell (void) { + // Note: error() is inherited from octave_base_stream, not ::error(). + // This error function does not halt execution so "return ..." must exist. error ("ftell: invalid operation"); return -1; }