GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
file-io.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 // Originally written by John C. Campbell <jcc@bevo.che.wisc.edu>
27 //
28 // Thomas Baier <baier@ci.tuwien.ac.at> added the original versions of
29 // the following functions:
30 //
31 // popen
32 // pclose
33 // execute (now popen2.m)
34 // sync_system (now merged with system)
35 // async_system (now merged with system)
36 
37 // Extensively revised by John W. Eaton <jwe@octave.org>,
38 // April 1996.
39 
40 #if defined (HAVE_CONFIG_H)
41 # include "config.h"
42 #endif
43 
44 #include <cerrno>
45 #include <cstdio>
46 
47 #include <iomanip>
48 #include <string>
49 
50 #if defined (HAVE_ZLIB_H)
51 # include <zlib.h>
52 #endif
53 
54 #include "file-ops.h"
55 #include "file-stat.h"
56 #include "iconv-wrappers.h"
57 #include "lo-ieee.h"
58 #include "lo-sysdep.h"
59 #include "localcharset-wrapper.h"
60 #include "mkostemp-wrapper.h"
61 #include "oct-env.h"
62 #include "oct-locbuf.h"
63 #include "unistd-wrappers.h"
64 
65 #include "builtin-defun-decls.h"
66 #include "defun.h"
67 #include "error.h"
68 #include "errwarn.h"
69 #include "interpreter-private.h"
70 #include "interpreter.h"
71 #include "load-path.h"
72 #include "oct-fstrm.h"
73 #include "oct-iostrm.h"
74 #include "oct-map.h"
75 #include "oct-prcstrm.h"
76 #include "oct-stream.h"
77 #include "oct-strstrm.h"
78 #include "ov.h"
79 #include "ovl.h"
80 #include "pager.h"
81 #include "sysdep.h"
82 #include "utils.h"
83 #include "variables.h"
84 
86 
87 static void
88 normalize_fopen_mode (std::string& mode, bool& use_zlib)
89 {
90  use_zlib = false;
91 
92  if (! mode.empty ())
93  {
94  // Matlab uses 'A' and 'W' to indicate that buffered writing should
95  // take place. Octave already does that. Theoretically, we should
96  // warn about using 'a', 'r', or 'w' because Octave does not enable
97  // automatic flushing with these modes. The performance hit is ~4X
98  // when using automatic flushing and seems completely unnecessary.
99  // See bug #52644.
100 
101  std::size_t pos = mode.find ('W');
102 
103  if (pos != std::string::npos)
104  mode[pos] = 'w';
105 
106  pos = mode.find ('R');
107 
108  if (pos != std::string::npos)
109  mode[pos] = 'r';
110 
111  pos = mode.find ('A');
112 
113  if (pos != std::string::npos)
114  mode[pos] = 'a';
115 
116  pos = mode.find ('z');
117 
118  if (pos != std::string::npos)
119  {
120 #if defined (HAVE_ZLIB)
121  use_zlib = true;
122  mode.erase (pos, 1);
123 #else
124  err_disabled_feature ("", "gzipped files (zlib)");
125 #endif
126  }
127 
128  // Use binary mode if 't' is not specified, but don't add
129  // 'b' if it is already present.
130 
131  std::size_t bpos = mode.find ('b');
132  std::size_t tpos = mode.find ('t');
133 
134  if (bpos == std::string::npos && tpos == std::string::npos)
135  mode += 'b';
136  }
137 }
138 
139 static std::ios::openmode
140 fopen_mode_to_ios_mode (const std::string& mode)
141 {
142  std::ios::openmode retval = std::ios::in;
143 
144  if (mode == "rt")
145  retval = std::ios::in;
146  else if (mode == "wt")
147  retval = std::ios::out | std::ios::trunc;
148  else if (mode == "at")
149  retval = std::ios::out | std::ios::app;
150  else if (mode == "r+t" || mode == "rt+")
151  retval = std::ios::in | std::ios::out;
152  else if (mode == "w+t" || mode == "wt+")
153  retval = std::ios::in | std::ios::out | std::ios::trunc;
154  else if (mode == "a+t" || mode == "at+")
155  retval = std::ios::in | std::ios::out | std::ios::app;
156  else if (mode == "rb" || mode == "r")
157  retval = std::ios::in | std::ios::binary;
158  else if (mode == "wb" || mode == "w")
159  retval = std::ios::out | std::ios::trunc | std::ios::binary;
160  else if (mode == "ab" || mode == "a")
161  retval = std::ios::out | std::ios::app | std::ios::binary;
162  else if (mode == "r+b" || mode == "rb+" || mode == "r+")
163  retval = std::ios::in | std::ios::out | std::ios::binary;
164  else if (mode == "w+b" || mode == "wb+" || mode == "w+")
165  retval = (std::ios::in | std::ios::out | std::ios::trunc
166  | std::ios::binary);
167  else if (mode == "a+b" || mode == "ab+" || mode == "a+")
168  retval = (std::ios::in | std::ios::out | std::ios::app
169  | std::ios::binary);
170  else
171  error ("invalid mode specified");
172 
173  return retval;
174 }
175 
176 DEFMETHOD (fclose, interp, args, ,
177  doc: /* -*- texinfo -*-
178 @deftypefn {} {@var{status} =} fclose (@var{fid})
179 @deftypefnx {} {@var{status} =} fclose ("all")
180 Close the file specified by the file descriptor @var{fid}.
181 
182 If successful, @code{fclose} returns 0, otherwise, it returns -1. The
183 second form of the @code{fclose} call closes all open files except
184 @code{stdin}, @code{stdout}, @code{stderr}, and any FIDs associated
185 with gnuplot.
186 @seealso{fopen, fflush, freport}
187 @end deftypefn */)
188 {
189  if (args.length () != 1)
190  print_usage ();
191 
192  stream_list& streams = interp.get_stream_list ();
193 
194  return ovl (streams.remove (args(0), "fclose"));
195 }
196 
197 DEFMETHOD (fclear, interp, args, ,
198  doc: /* -*- texinfo -*-
199 @deftypefn {} {} fclear (@var{fid})
200 Clear the stream state for the file specified by the file descriptor
201 @var{fid}.
202 @seealso{ferror, fopen}
203 @end deftypefn */)
204 {
205  if (args.length () != 1)
206  print_usage ();
207 
208  stream_list& streams = interp.get_stream_list ();
209 
210  int fid = streams.get_file_number (args(0));
211 
212  stream os = streams.lookup (fid, "fclear");
213 
214  os.clearerr ();
215 
216  return ovl ();
217 }
218 
219 DEFMETHOD (fflush, interp, args, ,
220  doc: /* -*- texinfo -*-
221 @deftypefn {} {@var{status} =} fflush (@var{fid})
222 Flush output to file descriptor @var{fid}.
223 
224 @code{fflush} returns 0 on success and an OS dependent error value
225 (@minus{}1 on Unix) on error.
226 
227 Programming Note: Flushing is useful for ensuring that all pending output
228 makes it to the screen before some other event occurs. For example, it is
229 always a good idea to flush the standard output stream before calling
230 @code{input}.
231 @seealso{fopen, fclose}
232 @end deftypefn */)
233 {
234  if (args.length () != 1)
235  print_usage ();
236 
237  octave_value retval = -1;
238 
239  stream_list& streams = interp.get_stream_list ();
240 
241  // FIXME: any way to avoid special case for stdout?
242  int fid = streams.get_file_number (args(0));
243 
244  if (fid == 1)
245  {
246  flush_stdout ();
247 
248  retval = 0;
249  }
250  else
251  {
252  stream os = streams.lookup (fid, "fflush");
253 
254  retval = os.flush ();
255  }
256 
257  return retval;
258 }
259 
260 DEFMETHOD (fgetl, interp, args, ,
261  doc: /* -*- texinfo -*-
262 @deftypefn {} {@var{str} =} fgetl (@var{fid})
263 @deftypefnx {} {@var{str} =} fgetl (@var{fid}, @var{len})
264 Read characters from a file, stopping after a newline, or EOF,
265 or @var{len} characters have been read.
266 
267 The characters read, excluding the possible trailing newline, are returned
268 as a string.
269 
270 If @var{len} is omitted, @code{fgetl} reads until the next newline
271 character.
272 
273 If there are no more characters to read, @code{fgetl} returns @minus{}1.
274 
275 To read a line and return the terminating newline,
276 @pxref{XREFfgets,,@code{fgets}}.
277 @seealso{fgets, fscanf, fread, fopen}
278 @end deftypefn */)
279 {
280  static const std::string who = "fgetl";
281 
282  int nargin = args.length ();
283 
284  if (nargin < 1 || nargin > 2)
285  print_usage ();
286 
287  stream_list& streams = interp.get_stream_list ();
288 
289  stream os = streams.lookup (args(0), who);
290 
291  octave_value len_arg = (nargin == 2) ? args(1) : octave_value ();
292 
293  bool err = false;
294 
295  std::string tmp = os.getl (len_arg, err, who);
296 
297  if (! err)
298  return ovl (tmp, tmp.length ());
299  else
300  return ovl (-1, 0);
301 }
302 
303 DEFMETHOD (fgets, interp, args, ,
304  doc: /* -*- texinfo -*-
305 @deftypefn {} {@var{str} =} fgets (@var{fid})
306 @deftypefnx {} {@var{str} =} fgets (@var{fid}, @var{len})
307 Read characters from a file, stopping after a newline, or EOF,
308 or @var{len} characters have been read.
309 
310 The characters read, including the possible trailing newline, are returned
311 as a string.
312 
313 If @var{len} is omitted, @code{fgets} reads until the next newline
314 character.
315 
316 If there are no more characters to read, @code{fgets} returns @minus{}1.
317 
318 To read a line and discard the terminating newline,
319 @pxref{XREFfgetl,,@code{fgetl}}.
320 @seealso{fputs, fgetl, fscanf, fread, fopen}
321 @end deftypefn */)
322 {
323  static const std::string who = "fgets";
324 
325  int nargin = args.length ();
326 
327  if (nargin < 1 || nargin > 2)
328  print_usage ();
329 
330  stream_list& streams = interp.get_stream_list ();
331 
332  stream os = streams.lookup (args(0), who);
333 
334  octave_value len_arg = (nargin == 2) ? args(1) : octave_value ();
335 
336  bool err = false;
337 
338  std::string tmp = os.gets (len_arg, err, who);
339 
340  if (! err)
341  return ovl (tmp, tmp.length ());
342  else
343  return ovl (-1.0, 0.0);
344 }
345 
346 DEFMETHOD (fskipl, interp, args, ,
347  doc: /* -*- texinfo -*-
348 @deftypefn {} {@var{nlines} =} fskipl (@var{fid})
349 @deftypefnx {} {@var{nlines} =} fskipl (@var{fid}, @var{count})
350 @deftypefnx {} {@var{nlines} =} fskipl (@var{fid}, Inf)
351 Read and skip @var{count} lines from the file specified by the file
352 descriptor @var{fid}.
353 
354 @code{fskipl} discards characters until an end-of-line is encountered
355 exactly @var{count}-times, or until the end-of-file marker is found.
356 
357 If @var{count} is omitted, it defaults to 1. @var{count} may also be
358 @code{Inf}, in which case lines are skipped until the end of the file.
359 This form is suitable for counting the number of lines in a file.
360 
361 Returns the number of lines skipped (end-of-line sequences encountered).
362 @seealso{fgetl, fgets, fscanf, fopen}
363 @end deftypefn */)
364 {
365  static const std::string who = "fskipl";
366 
367  int nargin = args.length ();
368 
369  if (nargin < 1 || nargin > 2)
370  print_usage ();
371 
372  stream_list& streams = interp.get_stream_list ();
373 
374  stream os = streams.lookup (args(0), who);
375 
376  octave_value count_arg = (nargin == 2) ? args(1) : octave_value ();
377 
378  bool err = false;
379 
380  off_t tmp = os.skipl (count_arg, err, who);
381 
382  if (! err)
383  return ovl (tmp);
384  else
385  return ovl ();
386 }
387 
388 static stream
389 do_stream_open (const std::string& name, const std::string& mode_arg,
390  const std::string& arch, std::string encoding, int& fid)
391 {
392  stream retval;
393 
394  fid = -1;
395 
396  if (encoding.compare ("utf-8"))
397  {
398  // check if encoding is valid
399  void *codec = octave_iconv_open_wrapper (encoding.c_str (), "utf-8");
400  if (codec == reinterpret_cast<void *> (-1))
401  {
402  if (errno == EINVAL)
403  error ("fopen: conversion from codepage '%s' not supported",
404  encoding.c_str ());
405  }
406  else
408  }
409 
410  std::string mode = mode_arg;
411  bool use_zlib = false;
412  normalize_fopen_mode (mode, use_zlib);
413 
414  std::ios::openmode md = fopen_mode_to_ios_mode (mode);
415 
418 
419  std::string fname = sys::file_ops::tilde_expand (name);
420 
421  bool is_dir = sys::dir_exists (fname);
422 
423  if (! (md & std::ios::out))
424  fname = find_data_file_in_load_path ("fopen", fname);
425 
426  if (! is_dir)
427  {
428 #if defined (HAVE_ZLIB)
429  if (use_zlib)
430  {
431  FILE *fptr = sys::fopen (fname.c_str (), mode.c_str ());
432 
433  if (fptr)
434  {
435  int fd = fileno (fptr);
436 
437  gzFile gzf = ::gzdopen (fd, mode.c_str ());
438 
439  retval = zstdiostream::create (fname, gzf, fd, md, flt_fmt,
440  encoding);
441  }
442  else
443  retval.error (std::strerror (errno));
444  }
445  else
446 #endif
447  {
448  FILE *fptr = sys::fopen (fname, mode);
449 
450  retval = stdiostream::create (fname, fptr, md, flt_fmt, encoding);
451 
452  if (! fptr)
453  retval.error (std::strerror (errno));
454  }
455 
456  }
457 
458  return retval;
459 }
460 
461 static stream
462 do_stream_open (const octave_value& tc_name, const octave_value& tc_mode,
463  const octave_value& tc_arch, const octave_value& tc_encoding,
464  const char *fcn, int& fid)
465 {
466  stream retval;
467 
468  fid = -1;
469 
470  std::string name = tc_name.xstring_value ("%s: filename must be a string", fcn);
471  std::string mode = tc_mode.xstring_value ("%s: file mode must be a string", fcn);
472  std::string arch = tc_arch.xstring_value ("%s: architecture type must be a string", fcn);
473  std::string encoding = tc_encoding.xstring_value ("%s: ENCODING must be a string", fcn);
474 
475  // Valid names for encodings consist of ASCII characters only.
476  std::transform (encoding.begin (), encoding.end (), encoding.begin (),
477  ::tolower);
478 
479  if (encoding == "system")
480  encoding = octave_locale_charset_wrapper ();
481 
482 #if defined (OCTAVE_HAVE_STRICT_ENCODING_FACET)
483  if (encoding != "utf-8")
484  {
485  warning_with_id ("Octave:fopen:encoding-unsupported",
486  "fopen: encoding must be 'UTF-8' for this version");
487  encoding = "utf-8";
488  }
489 #endif
490 
491  retval = do_stream_open (name, mode, arch, encoding, fid);
492 
493  return retval;
494 }
495 
496 DEFMETHOD (fopen, interp, args, nargout,
497  doc: /* -*- texinfo -*-
498 @deftypefn {} {@var{fid} =} fopen (@var{name})
499 @deftypefnx {} {@var{fid} =} fopen (@var{name}, @var{mode})
500 @deftypefnx {} {@var{fid} =} fopen (@var{name}, @var{mode}, @var{arch})
501 @deftypefnx {} {@var{fid} =} fopen (@var{name}, @var{mode}, @var{arch}, @var{encoding})
502 @deftypefnx {} {[@var{fid}, @var{msg}] =} fopen (@dots{})
503 @deftypefnx {} {@var{fid_list} =} fopen ("all")
504 @deftypefnx {} {[@var{file}, @var{mode}, @var{arch}, @var{encoding}] =} fopen (@var{fid})
505 Open a file for low-level I/O or query open files and file descriptors.
506 
507 The first form of the @code{fopen} function opens the named file with
508 the specified mode (read-write, read-only, etc.@:), architecture
509 interpretation (IEEE big endian, IEEE little endian, etc.@:) and file encoding,
510 and returns an integer value that may be used to refer to the file later. If
511 an error occurs, @var{fid} is set to @minus{}1 and @var{msg} contains the
512 corresponding system error message. The @var{mode} is a one or two
513 character string that specifies whether the file is to be opened for
514 reading, writing, or both. The @var{encoding} is a character string with a
515 valid encoding identifier. This encoding is used when strings are read from
516 or written to the file. By default, that is UTF-8.
517 
518 The second form of the @code{fopen} function returns a vector of file ids
519 corresponding to all the currently open files, excluding the
520 @code{stdin}, @code{stdout}, and @code{stderr} streams.
521 
522 The third form of the @code{fopen} function returns information about the
523 open file given its file id.
524 
525 For example,
526 
527 @example
528 myfile = fopen ("splat.dat", "r", "ieee-le");
529 @end example
530 
531 @noindent
532 opens the file @file{splat.dat} for reading. If necessary, binary
533 numeric values will be read assuming they are stored in IEEE format with
534 the least significant bit first, and then converted to the native
535 representation.
536 
537 Opening a file that is already open simply opens it again and returns a
538 separate file id. It is not an error to open a file several times,
539 though writing to the same file through several different file ids may
540 produce unexpected results.
541 
542 The possible values of @var{mode} are
543 
544 @table @asis
545 @item @samp{r} (default)
546 Open a file for reading.
547 
548 @item @samp{w}
549 Open a file for writing. The previous contents are discarded.
550 
551 @item @samp{a}
552 Open or create a file for writing at the end of the file.
553 
554 @item @samp{r+}
555 Open an existing file for reading and writing.
556 
557 @item @samp{w+}
558 Open a file for reading or writing. The previous contents are
559 discarded.
560 
561 @item @samp{a+}
562 Open or create a file for reading or writing at the end of the
563 file.
564 @end table
565 
566 Append a @qcode{"t"} to the mode string to open the file in text mode or a
567 @qcode{"b"} to open in binary mode. On Windows systems,
568 text mode reading and writing automatically converts linefeeds to the
569 appropriate line end character for the system (carriage-return linefeed on
570 Windows). The default when no mode is specified is binary.
571 
572 Additionally, you may append a @qcode{"z"} to the mode string to open a
573 gzipped file for reading or writing. For this to be successful, you
574 must also open the file in binary mode.
575 
576 The parameter @var{arch} is a string specifying the default data format
577 for the file. Valid values for @var{arch} are:
578 
579 @table @asis
580 @item @qcode{"native"} or @qcode{"n"} (default)
581 The format of the current machine.
582 
583 @item @qcode{"ieee-be"} or @qcode{"b"}
584 IEEE big endian format.
585 
586 @item @qcode{"ieee-le"} or @qcode{"l"}
587 IEEE little endian format.
588 @end table
589 
590 When opening a new file that does not yet exist, permissions will be set to
591 @code{0666 - @var{umask}}.
592 
593 Compatibility Note: Octave opens files using buffered I/O. Small writes are
594 accumulated until an internal buffer is filled, and then everything is written
595 in a single operation. This is very efficient and improves performance.
596 @sc{matlab}, however, opens files using flushed I/O where every write operation
597 is immediately performed. If the write operation must be performed immediately
598 after data has been written then the write should be followed by a call to
599 @code{fflush} to flush the internal buffer.
600 @seealso{fclose, fgets, fgetl, fscanf, fread, fputs, fdisp, fprintf, fwrite,
601 fskipl, fseek, frewind, ftell, feof, ferror, fclear, fflush, freport, umask}
602 @end deftypefn */)
603 {
604  int nargin = args.length ();
605 
606  if (nargin < 1 || nargin > 4)
607  print_usage ();
608 
609  octave_value_list retval = ovl (-1.0);
610 
611  stream_list& streams = interp.get_stream_list ();
612 
613  if (nargin == 1)
614  {
615  if (args(0).is_string ())
616  {
617  // If there is only one argument and it is a string but it
618  // is not the string "all", we assume it is a file to open
619  // with MODE = "r". To open a file called "all", you have
620  // to supply more than one argument.
621  if (nargout < 2 && args(0).string_value () == "all")
622  return streams.open_file_numbers ();
623  }
624  else
625  {
626  string_vector tmp = streams.get_info (args(0));
627 
628  retval = ovl (tmp(0), tmp(1), tmp(2), tmp(3));
629 
630  return retval;
631  }
632  }
633 
634  octave_value mode = (nargin > 1) ? args(1) : octave_value ("r");
635 
636  octave_value arch = (nargin > 2) ? args(2) : octave_value ("native");
637 
638  octave_value encoding = (nargin > 3) ? args(3) : octave_value ("utf-8");
639 
640  int fid = -1;
641 
642  stream os = do_stream_open (args(0), mode, arch, encoding, "fopen",
643  fid);
644 
645  if (os)
646  retval = ovl (streams.insert (os), "");
647  else
648  {
649  int error_number = 0;
650 
651  retval = ovl (-1.0, os.error (false, error_number));
652  }
653 
654  return retval;
655 }
656 
657 /*
658 ## Further tests are in io.tst
659 %!test # Uses hardcoded value of 1 for stdout
660 %! [name, mode, arch, encoding] = fopen (1);
661 %! assert (name, "stdout");
662 %! assert (mode, "w");
663 %! assert (encoding, "utf-8");
664 
665 %!test # Query of non-existent stream returns all ""
666 %! [name, mode, arch] = fopen (-1);
667 %! assert (name, "");
668 %! assert (mode, "");
669 %! assert (arch, "");
670 
671 ## FIXME: should be conditional on OCTAVE_HAVE_STRICT_ENCODING_FACET
672 %!testif HAVE_LLVM_LIBCXX
673 %! fname = tempname ();
674 %! unwind_protect
675 %! fail ("fid = fopen (fname, 'wb', 'n', 'Windows-1252')", ...
676 %! "warning", "encoding must be 'UTF-8'");
677 %! [name, mode, arch, encoding] = fopen (fid);
678 %! assert (name, fname);
679 %! assert (mode, "wb");
680 %! assert (encoding, "utf-8"); # fallback after warning
681 %! unwind_protect_cleanup
682 %! fclose (fid);
683 %! unlink (fname);
684 %! end_unwind_protect
685 */
686 
687 DEFMETHOD (freport, interp, args, ,
688  doc: /* -*- texinfo -*-
689 @deftypefn {} {} freport ()
690 Print a list of which files have been opened, and whether they are open
691 for reading, writing, or both.
692 
693 For example:
694 
695 @example
696 @group
697 freport ()
698 
699  @print{} number mode arch name
700  @print{} ------ ---- ---- ----
701  @print{} 0 r ieee-le stdin
702  @print{} 1 w ieee-le stdout
703  @print{} 2 w ieee-le stderr
704  @print{} 3 r ieee-le myfile
705 @end group
706 @end example
707 @seealso{fopen, fclose, is_valid_file_id}
708 @end deftypefn */)
709 {
710  if (args.length () > 0)
711  warning ("freport: ignoring extra arguments");
712 
713  stream_list& streams = interp.get_stream_list ();
714 
715  octave_stdout << streams.list_open_files ();
716 
717  return ovl ();
718 }
719 
720 DEFMETHOD (frewind, interp, args, nargout,
721  doc: /* -*- texinfo -*-
722 @deftypefn {} {} frewind (@var{fid})
723 @deftypefnx {} {@var{status} =} frewind (@var{fid})
724 Move the file pointer to the beginning of the file specified by file
725 descriptor @var{fid}.
726 
727 If an output @var{status} is requested then @code{frewind} returns 0 for
728 success, and -1 if an error is encountered.
729 
730 Programming Note: @code{frewind} is equivalent to
731 @code{fseek (@var{fid}, 0, SEEK_SET)}.
732 @seealso{fseek, ftell, fopen}
733 @end deftypefn */)
734 {
735  if (args.length () != 1)
736  print_usage ();
737 
738  int result = -1;
739 
740  stream_list& streams = interp.get_stream_list ();
741 
742  stream os = streams.lookup (args(0), "frewind");
743 
744  result = os.rewind ();
745 
746  if (nargout > 0)
747  return ovl (result);
748  else
749  return ovl ();
750 }
751 
752 DEFMETHOD (fseek, interp, args, ,
753  doc: /* -*- texinfo -*-
754 @deftypefn {} {@var{status} =} fseek (@var{fid}, @var{offset})
755 @deftypefnx {} {@var{status} =} fseek (@var{fid}, @var{offset}, @var{origin})
756 Set the file pointer to the location @var{offset} within the file @var{fid}.
757 
758 The pointer is positioned @var{offset} characters from the @var{origin}, which
759 may be one of the predefined variables @w{@qcode{SEEK_SET}}@ (beginning),
760 @w{@qcode{SEEK_CUR}}@ (current position), or @w{@qcode{SEEK_END}}@ (end of file)
761 or strings @nospell{@qcode{"bof"}}, @nospell{@qcode{"cof"}}, or
762 @nospell{@qcode{"eof"}}. If @var{origin} is omitted, @w{@qcode{SEEK_SET}}@ is
763 assumed. @var{offset} may be positive, negative, or zero but not all
764 combinations of @var{origin} and @var{offset} can be realized.
765 
766 @code{fseek} returns 0 on success and -1 on error.
767 @seealso{fskipl, frewind, ftell, fopen, SEEK_SET, SEEK_CUR, SEEK_END}
768 @end deftypefn */)
769 {
770  int nargin = args.length ();
771 
772  if (nargin < 2 || nargin > 3)
773  print_usage ();
774 
775  stream_list& streams = interp.get_stream_list ();
776 
777  stream os = streams.lookup (args(0), "fseek");
778 
779  octave_value origin_arg = (nargin == 3) ? args(2) : octave_value (-1.0);
780 
781  return ovl (os.seek (args(1), origin_arg));
782 }
783 
784 DEFMETHOD (ftell, interp, args, ,
785  doc: /* -*- texinfo -*-
786 @deftypefn {} {@var{pos} =} ftell (@var{fid})
787 Return the position of the file pointer as the number of characters from the
788 beginning of the file specified by file descriptor @var{fid}.
789 @seealso{fseek, frewind, feof, fopen}
790 @end deftypefn */)
791 {
792  if (args.length () != 1)
793  print_usage ();
794 
795  stream_list& streams = interp.get_stream_list ();
796 
797  stream os = streams.lookup (args(0), "ftell");
798 
799  return ovl (os.tell ());
800 }
801 
802 static octave_value_list
803 printf_internal (interpreter& interp, const std::string& who,
804  const octave_value_list& args, int nargout)
805 {
806  int nargin = args.length ();
807 
808  if (! (nargin > 1 || (nargin > 0 && args(0).is_string ())))
809  print_usage ();
810 
811  int result;
812 
813  stream os;
814  int fmt_n = 0;
815 
816  stream_list& streams = interp.get_stream_list ();
817 
818  if (args(0).is_string ())
819  os = streams.lookup (1, who);
820  else
821  {
822  fmt_n = 1;
823  os = streams.lookup (args(0), who);
824  }
825 
826  if (! args(fmt_n).is_string ())
827  error ("%s: format TEMPLATE must be a string", who.c_str ());
828 
829  octave_value_list tmp_args;
830 
831  if (nargin > 1 + fmt_n)
832  {
833  tmp_args.resize (nargin-fmt_n-1, octave_value ());
834 
835  for (int i = fmt_n + 1; i < nargin; i++)
836  tmp_args(i-fmt_n-1) = args(i);
837  }
838 
839  result = os.printf (args(fmt_n), tmp_args, who);
840 
841  if (nargout > 0)
842  return ovl (result);
843  else
844  return ovl ();
845 }
846 
847 DEFMETHOD (fprintf, interp, args, nargout,
848  doc: /* -*- texinfo -*-
849 @deftypefn {} {} fprintf (@var{fid}, @var{template}, @dots{})
850 @deftypefnx {} {} fprintf (@var{template}, @dots{})
851 @deftypefnx {} {@var{numbytes} =} fprintf (@dots{})
852 This function is equivalent to @code{printf}, except that the output is
853 written to the file descriptor @var{fid} instead of @code{stdout}.
854 
855 If @var{fid} is omitted, the output is written to @code{stdout} making the
856 function exactly equivalent to @code{printf}.
857 
858 The optional output @var{numbytes} returns the number of bytes written to the
859 file.
860 
861 Implementation Note: For compatibility with @sc{matlab}, escape sequences in
862 the template string (e.g., @qcode{"@backslashchar{}n"} => newline) are
863 expanded even when the template string is defined with single quotes.
864 @seealso{fputs, fdisp, fwrite, fscanf, printf, sprintf, fopen}
865 @end deftypefn */)
866 {
867  static const std::string who = "fprintf";
868 
869  return printf_internal (interp, who, args, nargout);
870 }
871 
872 DEFMETHOD (printf, interp, args, nargout,
873  doc: /* -*- texinfo -*-
874 @deftypefn {} {} printf (@var{template}, @dots{})
875 @deftypefnx {} {@var{numbytes} =} printf (@dots{})
876 Print optional arguments under the control of the template string
877 @var{template} to the stream @code{stdout} and return the number of characters
878 printed.
879 @ifclear OCTAVE_MANUAL
880 
881 See the Formatted Output section of the GNU Octave manual for a complete
882 description of the syntax of the template string.
883 @end ifclear
884 
885 The optional output @var{numbytes} returns the number of bytes printed.
886 
887 Implementation Note: For compatibility with @sc{matlab}, escape sequences in
888 the template string (e.g., @qcode{"@backslashchar{}n"} => newline) are
889 expanded even when the template string is defined with single quotes.
890 @seealso{fprintf, sprintf, scanf}
891 @end deftypefn */)
892 {
893  static const std::string who = "printf";
894 
895  octave_value_list tmp_args = args;
896 
897  return printf_internal (interp, who, tmp_args.prepend (octave_value (1)),
898  nargout);
899 }
900 
901 static octave_value_list
902 puts_internal (interpreter& interp, const std::string& who,
903  const octave_value_list& args)
904 {
905  if (args.length () != 2)
906  print_usage ();
907 
908  stream_list& streams = interp.get_stream_list ();
909 
910  stream os = streams.lookup (args(0), who);
911 
912  return ovl (- (os.puts (args(1), who) < 0));
913 }
914 
915 DEFMETHOD (fputs, interp, args, ,
916  doc: /* -*- texinfo -*-
917 @deftypefn {} {@var{status} =} fputs (@var{fid}, @var{string})
918 Write the string @var{string} to the file with file descriptor @var{fid}.
919 
920 The string is written to the file with no additional formatting. Use
921 @code{fdisp} instead to automatically append a newline character appropriate
922 for the local machine.
923 
924 The optional output @var{status} is 0 for success, or -1 if an error was
925 encountered.
926 @seealso{fdisp, fprintf, fwrite, fopen}
927 @end deftypefn */)
928 {
929  static const std::string who = "fputs";
930 
931  return puts_internal (interp, who, args);
932 }
933 
934 /*
935 ## Check if text is correctly converted to output encoding
936 # FIXME: should be conditional on OCTAVE_HAVE_STRICT_ENCODING_FACET
937 %!testif ; ! __have_feature__ ("LLVM_LIBCXX") <*61839>
938 %! str = "aäöu"; # string with non-ASCII characters
939 %! fname = tempname ();
940 %! fid = fopen (fname, "wt", "n", "ISO-8859-1");
941 %! unwind_protect
942 %! fprintf (fid, '%s\n', str);
943 %! fdisp (fid, str);
944 %! fputs (fid, str);
945 %! fclose (fid);
946 %! ## re-open file for reading in binary mode
947 %! fid = fopen (fname, "rb");
948 %! fb = fread (fid);
949 %! fclose (fid);
950 %! ## check file content
951 %! encoded = [97 228 246 117]; # original string in ISO-8859-1 encoding
952 %! if (ispc ())
953 %! eol = double ("\r\n");
954 %! else
955 %! eol = double ("\n");
956 %! endif
957 %! assert (fb.', [encoded eol encoded eol encoded])
958 %! unwind_protect_cleanup
959 %! unlink (fname);
960 %! end_unwind_protect
961 */
962 
963 DEFMETHOD (puts, interp, args, ,
964  doc: /* -*- texinfo -*-
965 @deftypefn {} {@var{status} =} puts (@var{string})
966 Write a string to the standard output with no formatting.
967 
968 The string is written verbatim to the standard output. Use @code{disp} to
969 automatically append a newline character appropriate for the local machine.
970 
971 The optional output @var{status} is 0 for success, or -1 if an error was
972 encountered.
973 @seealso{fputs, disp}
974 @end deftypefn */)
975 {
976  static const std::string who = "puts";
977 
978  octave_value_list tmp_args = args;
979 
980  return puts_internal (interp, who, tmp_args.prepend (octave_value (1)));
981 }
982 
983 DEFUN (sprintf, args, ,
984  doc: /* -*- texinfo -*-
985 @deftypefn {} {@var{str} =} sprintf (@var{template}, @dots{})
986 This is like @code{printf}, except that the output is returned as a
987 string.
988 
989 Unlike the C library function, which requires you to provide a suitably
990 sized string as an argument, Octave's @code{sprintf} function returns the
991 string, automatically sized to hold all of the items converted.
992 
993 Implementation Note: For compatibility with @sc{matlab}, escape sequences in
994 the template string (e.g., @qcode{"@backslashchar{}n"} => newline) are
995 expanded even when the template string is defined with single quotes.
996 @seealso{printf, fprintf, sscanf}
997 @end deftypefn */)
998 {
999  static const std::string who = "sprintf";
1000 
1001  int nargin = args.length ();
1002 
1003  if (nargin == 0)
1004  print_usage ();
1005 
1006  // We don't use ostrstream::create here because need direct
1007  // access to the OSTR object so that we can extract a string object
1008  // from it to return.
1009  ostrstream *ostr = new ostrstream ();
1010 
1011  // The stream destructor will delete OSTR for us.
1012  stream os (ostr);
1013 
1014  if (! os.is_valid ())
1015  error ("%s: unable to create output buffer", who.c_str ());
1016 
1017  octave_value fmt_arg = args(0);
1018 
1019  if (! fmt_arg.is_string ())
1020  error ("%s: format TEMPLATE must be a string", who.c_str ());
1021 
1022  octave_value_list retval (3);
1023 
1024  octave_value_list tmp_args;
1025  if (nargin > 1)
1026  {
1027  tmp_args.resize (nargin-1, octave_value ());
1028 
1029  for (int i = 1; i < nargin; i++)
1030  tmp_args(i-1) = args(i);
1031  }
1032 
1033  // NOTE: Call to os.error must precede next call to ostr which might reset it.
1034  retval(2) = os.printf (fmt_arg, tmp_args, who);
1035  retval(1) = os.error ();
1036 
1037  std::string result = ostr->str ();
1038  char type = (fmt_arg.is_sq_string () ? '\'' : '"');
1039 
1040  retval(0) = (result.empty () ? octave_value (charMatrix (1, 0), type)
1041  : octave_value (result, type));
1042 
1043  return retval;
1044 }
1045 
1046 static octave_value_list
1047 scanf_internal (interpreter& interp, const std::string& who,
1048  const octave_value_list& args)
1049 {
1050  int nargin = args.length ();
1051 
1052  if (nargin < 2 || nargin > 3)
1053  print_usage ();
1054 
1055  octave_value_list retval;
1056 
1057  stream_list& streams = interp.get_stream_list ();
1058 
1059  stream os = streams.lookup (args(0), who);
1060 
1061  if (! args(1).is_string ())
1062  error ("%s: format TEMPLATE must be a string", who.c_str ());
1063 
1064  if (nargin == 3 && args(2).is_string ())
1065  {
1066  retval = os.oscanf (args(1), who);
1067  }
1068  else
1069  {
1070  octave_idx_type count = 0;
1071 
1072  Array<double> size
1073  = (nargin == 3
1074  ? args(2).vector_value ()
1075  : Array<double> (dim_vector (1, 1), lo_ieee_inf_value ()));
1076 
1077  octave_value tmp = os.scanf (args(1), size, count, who);
1078 
1079  retval = ovl (tmp, count, os.error ());
1080  }
1081 
1082  return retval;
1083 }
1084 
1085 DEFMETHOD (fscanf, interp, args, ,
1086  doc: /* -*- texinfo -*-
1087 @deftypefn {} {[@var{val}, @var{count}, @var{errmsg}] =} fscanf (@var{fid}, @var{template}, @var{size})
1088 @deftypefnx {} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}] =} fscanf (@var{fid}, @var{template}, "C")
1089 In the first form, read from @var{fid} according to @var{template},
1090 returning the result in the matrix @var{val}.
1091 
1092 The optional argument @var{size} specifies the amount of data to read
1093 and may be one of
1094 
1095 @table @code
1096 @item Inf
1097 Read as much as possible, returning a column vector.
1098 
1099 @item @var{nr}
1100 Read up to @var{nr} elements, returning a column vector.
1101 
1102 @item [@var{nr}, Inf]
1103 Read as much as possible, returning a matrix with @var{nr} rows. If the
1104 number of elements read is not an exact multiple of @var{nr}, the last
1105 column is padded with zeros.
1106 
1107 @item [@var{nr}, @var{nc}]
1108 Read up to @code{@var{nr} * @var{nc}} elements, returning a matrix with
1109 @var{nr} rows. If the number of elements read is not an exact multiple
1110 of @var{nr}, the last column is padded with zeros.
1111 @end table
1112 
1113 @noindent
1114 If @var{size} is omitted, a value of @code{Inf} is assumed.
1115 
1116 A string is returned if @var{template} specifies only character conversions.
1117 
1118 The number of items successfully read is returned in @var{count}.
1119 
1120 If an error occurs, @var{errmsg} contains a system-dependent error message.
1121 
1122 In the second form, read from @var{fid} according to @var{template},
1123 with each conversion specifier in @var{template} corresponding to a
1124 single scalar return value. This form is more ``C-like'', and also
1125 compatible with previous versions of Octave. The number of successful
1126 conversions is returned in @var{count}
1127 @ifclear OCTAVE_MANUAL
1128 
1129 See the Formatted Input section of the GNU Octave manual for a
1130 complete description of the syntax of the template string.
1131 @end ifclear
1132 @seealso{fgets, fgetl, fread, scanf, sscanf, fopen}
1133 @end deftypefn */)
1134 {
1135  static const std::string who = "fscanf";
1136 
1137  return scanf_internal (interp, who, args);
1138 }
1139 
1140 static std::string
1141 get_scan_string_data (const octave_value& val, const std::string& who)
1142 {
1143  std::string retval;
1144 
1145  if (! val.is_string ())
1146  error ("%s: argument STRING must be a string", who.c_str ());
1147 
1148  octave_value tmp = val.reshape (dim_vector (1, val.numel ()));
1149 
1150  retval = tmp.string_value ();
1151 
1152  return retval;
1153 }
1154 
1155 DEFUN (sscanf, args, ,
1156  doc: /* -*- texinfo -*-
1157 @deftypefn {} {[@var{val}, @var{count}, @var{errmsg}, @var{pos}] =} sscanf (@var{string}, @var{template}, @var{size})
1158 @deftypefnx {} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}] =} sscanf (@var{string}, @var{template}, "C")
1159 This is like @code{fscanf}, except that the characters are taken from the
1160 string @var{string} instead of from a stream.
1161 
1162 Reaching the end of the string is treated as an end-of-file condition. In
1163 addition to the values returned by @code{fscanf}, the index of the next
1164 character to be read is returned in @var{pos}.
1165 @seealso{fscanf, scanf, sprintf}
1166 @end deftypefn */)
1167 {
1168  static const std::string who = "sscanf";
1169 
1170  int nargin = args.length ();
1171 
1172  if (nargin < 2 || nargin > 3)
1173  print_usage ();
1174 
1175  octave_value_list retval;
1176 
1177  std::string data = get_scan_string_data (args(0), who);
1178 
1179  stream os = istrstream::create (data);
1180 
1181  if (! os.is_valid ())
1182  error ("%s: unable to create temporary input buffer", who.c_str ());
1183 
1184  if (! args(1).is_string ())
1185  error ("%s: format TEMPLATE must be a string", who.c_str ());
1186 
1187  if (nargin == 3 && args(2).is_string ())
1188  {
1189  retval = os.oscanf (args(1), who);
1190  }
1191  else
1192  {
1193  octave_idx_type count = 0;
1194 
1195  Array<double> size = (nargin == 3) ? args(2).vector_value ()
1196  : Array<double> (dim_vector (1, 1),
1197  lo_ieee_inf_value ());
1198 
1199  octave_value tmp = os.scanf (args(1), size, count, who);
1200 
1201  // FIXME: is this the right thing to do?
1202  // Extract error message first, because getting
1203  // position will clear it.
1204  std::string errmsg = os.error ();
1205 
1206  retval = ovl (tmp, count, errmsg,
1207  (os.eof () ? data.length () : os.tell ()) + 1);
1208  }
1209 
1210  return retval;
1211 }
1212 
1213 /*
1214 %!test <*56396>
1215 %! [val, count, errmsg, nextpos] = sscanf ('1234a6', '%2d', 3);
1216 %! assert (val, [12; 34]);
1217 %! assert (count, 2);
1218 %! assert (errmsg, "sscanf: format failed to match");
1219 %! assert (nextpos, 5);
1220 */
1221 
1222 DEFMETHOD (scanf, interp, args, ,
1223  doc: /* -*- texinfo -*-
1224 @deftypefn {} {[@var{val}, @var{count}, @var{errmsg}] =} scanf (@var{template}, @var{size})
1225 @deftypefnx {} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}] =} scanf (@var{template}, "C")
1226 This is equivalent to calling @code{fscanf} with @var{fid} = @code{stdin}.
1227 
1228 It is currently not useful to call @code{scanf} in interactive programs.
1229 @seealso{fscanf, sscanf, printf}
1230 @end deftypefn */)
1231 {
1232  static const std::string who = "scanf";
1233 
1234  octave_value_list tmp_args = args;
1235 
1236  return scanf_internal (interp, who, tmp_args.prepend (octave_value (0)));
1237 }
1238 
1239 static octave_value_list
1240 textscan_internal (interpreter& interp, const std::string& who,
1241  const octave_value_list& args)
1242 {
1243  if (args.length () < 1)
1244  print_usage (who);
1245 
1246  stream os;
1247 
1248  if (args(0).is_string ())
1249  {
1250  std::string data = get_scan_string_data (args(0), who);
1251 
1252  os = istrstream::create (data);
1253 
1254  if (! os.is_valid ())
1255  error ("%s: unable to create temporary input buffer", who.c_str ());
1256  }
1257  else
1258  {
1259  stream_list& streams = interp.get_stream_list ();
1260 
1261  os = streams.lookup (args(0), who);
1262  }
1263 
1264  int nskip = 1;
1265 
1266  std::string fmt;
1267 
1268  if (args.length () == 1)
1269  {
1270  // omitted format = %f. explicit "" = width from file
1271  fmt = "%f";
1272  }
1273  else if (args(1).is_string ())
1274  {
1275  fmt = args(1).string_value ();
1276 
1277  if (args(1).is_sq_string ())
1278  fmt = do_string_escapes (fmt);
1279 
1280  nskip++;
1281  }
1282  else
1283  error ("%s: FORMAT must be a string", who.c_str ());
1284 
1285  octave_idx_type ntimes = -1;
1286 
1287  if (args.length () > 2)
1288  {
1289  if (args(2).isnumeric ())
1290  {
1291  ntimes = args(2).idx_type_value ();
1292 
1293  if (ntimes < args(2).double_value ())
1294  error ("%s: REPEAT = %g is too large",
1295  who.c_str (), args(2).double_value ());
1296 
1297  nskip++;
1298  }
1299  }
1300 
1301  octave_value_list options = args.splice (0, nskip);
1302 
1303  octave_idx_type count = 0;
1304 
1305  octave_value result = os.textscan (fmt, ntimes, options, who, count);
1306 
1307  std::string errmsg = os.error ();
1308 
1309  return ovl (result, count, errmsg);
1310 }
1311 
1312 DEFMETHOD (textscan, interp, args, ,
1313  doc: /* -*- texinfo -*-
1314 @deftypefn {} {@var{C} =} textscan (@var{fid}, @var{format})
1315 @deftypefnx {} {@var{C} =} textscan (@var{fid}, @var{format}, @var{repeat})
1316 @deftypefnx {} {@var{C} =} textscan (@var{fid}, @var{format}, @var{param}, @var{value}, @dots{})
1317 @deftypefnx {} {@var{C} =} textscan (@var{fid}, @var{format}, @var{repeat}, @var{param}, @var{value}, @dots{})
1318 @deftypefnx {} {@var{C} =} textscan (@var{str}, @dots{})
1319 @deftypefnx {} {[@var{C}, @var{position}, @var{errmsg}] =} textscan (@dots{})
1320 Read data from a text file or string.
1321 
1322 The string @var{str} or file associated with @var{fid} is read from and
1323 parsed according to @var{format}. The function is an extension of
1324 @code{strread} and @code{textread}. Differences include: the ability to
1325 read from either a file or a string, additional options, and additional
1326 format specifiers.
1327 
1328 The input is interpreted as a sequence of words, delimiters (such as
1329 whitespace), and literals. The characters that form delimiters and
1330 whitespace are determined by the options. The format consists of format
1331 specifiers interspersed between literals. In the format, whitespace forms
1332 a delimiter between consecutive literals, but is otherwise ignored.
1333 
1334 The output @var{C} is a cell array where the number of columns is determined
1335 by the number of format specifiers.
1336 
1337 The first word of the input is matched to the first specifier of the format
1338 and placed in the first column of the output; the second is matched to the
1339 second specifier and placed in the second column and so forth. If there
1340 are more words than specifiers then the process is repeated until all words
1341 have been processed or the limit imposed by @var{repeat} has been met (see
1342 below).
1343 
1344 The string @var{format} describes how the words in @var{str} should be
1345 parsed. As in @var{fscanf}, any (non-whitespace) text in the format that is
1346 not one of these specifiers is considered a literal. If there is a literal
1347 between two format specifiers then that same literal must appear in the
1348 input stream between the matching words.
1349 
1350 The following specifiers are valid:
1351 
1352 @table @code
1353 @item %f
1354 @itemx %f64
1355 @itemx %n
1356 The word is parsed as a number and converted to double.
1357 
1358 @item %f32
1359 The word is parsed as a number and converted to single (float).
1360 
1361 @item %d
1362 @itemx %d8
1363 @itemx %d16
1364 @itemx %d32
1365 @itemx %d64
1366 The word is parsed as a number and converted to int8, int16, int32, or
1367 int64. If no size is specified then int32 is used.
1368 
1369 @item %u
1370 @itemx %u8
1371 @itemx %u16
1372 @itemx %u32
1373 @itemx %u64
1374 The word is parsed as a number and converted to uint8, uint16, uint32, or
1375 uint64. If no size is specified then uint32 is used.
1376 
1377 @item %s
1378 The word is parsed as a string ending at the last character before
1379 whitespace, an end-of-line, or a delimiter specified in the options.
1380 
1381 @item %q
1382 The word is parsed as a "quoted string".
1383 If the first character of the string is a double quote (") then the string
1384 includes everything until a matching double quote---including whitespace,
1385 delimiters, and end-of-line characters. If a pair of consecutive double
1386 quotes appears in the input, it is replaced in the output by a single
1387 double quote. For examples, the input "He said ""Hello""" would
1388 return the value 'He said "Hello"'.
1389 
1390 @item %c
1391 The next character of the input is read.
1392 This includes delimiters, whitespace, and end-of-line characters.
1393 
1394 @item %[@dots{}]
1395 @itemx %[^@dots{}]
1396 In the first form, the word consists of the longest run consisting of only
1397 characters between the brackets. Ranges of characters can be specified by
1398 a hyphen; for example, %[0-9a-zA-Z] matches all alphanumeric characters (if
1399 the underlying character set is ASCII). Since @sc{matlab} treats hyphens
1400 literally, this expansion only applies to alphanumeric characters. To
1401 include '-' in the set, it should appear first or last in the brackets; to
1402 include ']', it should be the first character. If the first character is
1403 '^' then the word consists of characters @strong{not} listed.
1404 
1405 @item %N@dots{}
1406 For %s, %c %d, %f, %n, %u, an optional width can be specified as %Ns, etc.
1407 where N is an integer > 1. For %c, this causes exactly N characters to be
1408 read instead of a single character. For the other specifiers, it is an
1409 upper bound on the number of characters read; normal delimiters can cause
1410 fewer characters to be read. For complex numbers, this limit applies to
1411 the real and imaginary components individually. For %f and %n, format
1412 specifiers like %N.Mf are allowed, where M is an upper bound on number of
1413 characters after the decimal point to be considered; subsequent digits are
1414 skipped. For example, the specifier %8.2f would read 12.345e6 as 1.234e7.
1415 
1416 @item %*@dots{}
1417 The word specified by the remainder of the conversion specifier is skipped.
1418 
1419 @item literals
1420 In addition the format may contain literal character strings; these will be
1421 skipped during reading. If the input string does not match this literal,
1422 the processing terminates.
1423 @end table
1424 
1425 Parsed words corresponding to the first specifier are returned in the first
1426 output argument and likewise for the rest of the specifiers.
1427 
1428 By default, if there is only one input argument, @var{format} is @t{"%f"}.
1429 This means that numbers are read from the input into a single column vector.
1430 If @var{format} is explicitly empty (@qcode{""}) then textscan will
1431 return data in a number of columns matching the number of fields on the
1432 first data line of the input. Either of these is suitable only when the
1433 input is exclusively numeric.
1434 
1435 For example, the string
1436 
1437 @smallexample
1438 @group
1439 @var{str} = "\
1440 Bunny Bugs 5.5\n\
1441 Duck Daffy -7.5e-5\n\
1442 Penguin Tux 6"
1443 @end group
1444 @end smallexample
1445 
1446 @noindent
1447 can be read using
1448 
1449 @example
1450 @var{a} = textscan (@var{str}, "%s %s %f");
1451 @end example
1452 
1453 The optional numeric argument @var{repeat} can be used for limiting the
1454 number of items read:
1455 
1456 @table @asis
1457 @item -1
1458 Read all of the string or file until the end (default).
1459 
1460 @item N
1461 Read until the first of two conditions occurs: 1) the format has been
1462 processed N times, or 2) N lines of the input have been processed. Zero
1463 (0) is an acceptable value for @var{repeat}. Currently, end-of-line
1464 characters inside %q, %c, and %[@dots{}]$ conversions do not contribute to
1465 the line count. This is incompatible with @sc{matlab} and may change in
1466 future.
1467 @end table
1468 
1469 The behavior of @code{textscan} can be changed via property/value pairs.
1470 The following properties are recognized:
1471 
1472 @table @asis
1473 @item @qcode{"BufSize"}
1474 This specifies the number of bytes to use for the internal buffer.
1475 A modest speed improvement may be obtained by setting this to a large value
1476 when reading a large file, especially if the input contains long strings.
1477 The default is 4096, or a value dependent on @var{n} if that is specified.
1478 
1479 @item @qcode{"CollectOutput"}
1480 A value of 1 or true instructs @code{textscan} to concatenate consecutive
1481 columns of the same class in the output cell array. A value of 0 or false
1482 (default) leaves output in distinct columns.
1483 
1484 @item @qcode{"CommentStyle"}
1485 Specify parts of the input which are considered comments and will be
1486 skipped. @var{value} is the comment style and can be either (1) A string
1487 or 1x1 cell string, to skip everything to the right of it; (2) A cell array
1488 of two strings, to skip everything between the first and second strings.
1489 Comments are only parsed where whitespace is accepted and do not act as
1490 delimiters.
1491 
1492 @item @qcode{"Delimiter"}
1493 If @var{value} is a string, any character in @var{value} will be used to
1494 split the input into words. If @var{value} is a cell array of strings,
1495 any string in the array will be used to split the input into words.
1496 (default value = any whitespace.)
1497 
1498 @item @qcode{"EmptyValue"}
1499 Value to return for empty numeric values in non-whitespace delimited data.
1500 The default is NaN@. When the data type does not support NaN (int32 for
1501 example), then the default is zero.
1502 
1503 @item @qcode{"EndOfLine"}
1504 @var{value} can be either an empty or one character specifying the
1505 end-of-line character, or the pair
1506 @qcode{"@backslashchar{}r@backslashchar{}n"} (CRLF).
1507 In the latter case, any of
1508 @qcode{"@backslashchar{}r"}, @qcode{"@backslashchar{}n"} or
1509 @qcode{"@backslashchar{}r@backslashchar{}n"} is counted as a (single)
1510 newline. If no value is given,
1511 @qcode{"@backslashchar{}r@backslashchar{}n"} is used.
1512 @c If set to "" (empty string) EOLs are ignored as delimiters and added
1513 @c to whitespace.
1514 
1515 @c When reading from a character string, optional input argument @var{n}
1516 @c specifies the number of times @var{format} should be used (i.e., to limit
1517 @c the amount of data read).
1518 @c When reading from file, @var{n} specifies the number of data lines to read;
1519 @c in this sense it differs slightly from the format repeat count in strread.
1520 
1521 @item @qcode{"HeaderLines"}
1522 The first @var{value} number of lines of @var{fid} are skipped. Note that
1523 this does not refer to the first non-comment lines, but the first lines of
1524 any type.
1525 
1526 @item @qcode{"MultipleDelimsAsOne"}
1527 If @var{value} is nonzero, treat a series of consecutive delimiters,
1528 without whitespace in between, as a single delimiter. Consecutive
1529 delimiter series need not be vertically aligned. Without this option, a
1530 single delimiter before the end of the line does not cause the line to be
1531 considered to end with an empty value, but a single delimiter at the start
1532 of a line causes the line to be considered to start with an empty value.
1533 
1534 @item @qcode{"TreatAsEmpty"}
1535 Treat single occurrences (surrounded by delimiters or whitespace) of the
1536 string(s) in @var{value} as missing values.
1537 
1538 @item @qcode{"ReturnOnError"}
1539 If set to numerical 1 or true, return normally as soon as an error is
1540 encountered, such as trying to read a string using @code{%f}.
1541 If set to 0 or false, return an error and no data.
1542 
1543 @item @qcode{"Whitespace"}
1544 Any character in @var{value} will be interpreted as whitespace and trimmed;
1545 The default value for whitespace is
1546 @c Note: the next line specifically has a newline which generates a space
1547 @c in the output of qcode, but keeps the next line < 80 characters.
1548 @qcode{"
1549 @backslashchar{}b@backslashchar{}r@backslashchar{}n@backslashchar{}t"}
1550 (note the space). Unless whitespace is set to @qcode{""} (empty) AND at
1551 least one @qcode{"%s"} format conversion specifier is supplied, a space is
1552 always part of whitespace.
1553 
1554 @end table
1555 
1556 When the number of words in @var{str} or @var{fid} doesn't match an exact
1557 multiple of the number of format conversion specifiers, @code{textscan}'s
1558 behavior depends on whether the last character of the string or file is an
1559 end-of-line as specified by the @code{EndOfLine} option:
1560 
1561 @table @asis
1562 @item last character = end-of-line
1563 Data columns are padded with empty fields, NaN or 0 (for integer fields) so
1564 that all columns have equal length
1565 
1566 @item last character is not end-of-line
1567 Data columns are not padded; @code{textscan} returns columns of unequal
1568 length
1569 @end table
1570 
1571 The second output @var{position} provides the location, in characters
1572 from the beginning of the file or string, where processing stopped.
1573 
1574 @seealso{dlmread, fscanf, load, strread, textread}
1575 @end deftypefn */)
1576 {
1577  static const std::string who = "textscan";
1578 
1579  return textscan_internal (interp, who, args);
1580 }
1581 
1582 DEFMETHOD (__textscan__, interp, args, ,
1583  doc: /* -*- texinfo -*-
1584 @deftypefn {} {@var{C} =} __textscan__ (@var{who}, @dots{})
1585 Like @code{textscan} but accept additional argument @var{who} to use
1586 as the name of the function when reporting errors.
1587 @end deftypefn */)
1588 {
1589  if (args.length () == 0)
1590  print_usage ();
1591 
1592  return textscan_internal (interp, args(0).string_value (),
1593  args.splice (0, 1));
1594 }
1595 
1596 /*
1597 %!test
1598 %! str = "1, 2, 3, 4\n 5, , , 8\n 9, 10, 11, 12";
1599 %! fmtstr = "%f %d %f %s";
1600 %! c = textscan (str, fmtstr, 2, "delimiter", ",", "emptyvalue", -Inf);
1601 %! assert (c{1}, [1;5]);
1602 %! assert (c{3}, [3; -Inf]);
1603 %! assert (iscellstr (c{4}));
1604 
1605 %!test
1606 %! b = [10:10:100];
1607 %! b = [b; 8*b/5];
1608 %! str = sprintf ("%g miles/hr = %g kilometers/hr\n", b);
1609 %! fmt = "%f miles/hr = %f kilometers/hr";
1610 %! c = textscan (str, fmt);
1611 %! assert (c{1}, b(1,:)', 1e-5);
1612 %! assert (c{2}, b(2,:)', 1e-5);
1613 
1614 %!test
1615 %! str = "13, -, NA, str1, -25\r\n// Middle line\r\n36, na, 05, str3, 6";
1616 %! c = textscan (str, "%d %n %f %s %n", "delimiter", ",",
1617 %! "treatAsEmpty", {"NA", "na", "-"}, "commentStyle", "//");
1618 %! assert (c{1}, int32 ([13; 36]));
1619 %! assert (c{2}, [NaN; NaN]);
1620 %! assert (c{3}, [NaN; 5]);
1621 %! assert (c{4}, {"str1"; "str3"});
1622 %! assert (c{5}, [-25; 6]);
1623 
1624 %!test
1625 %! str = "Km:10 = hhhBjjj miles16hour\r\n";
1626 %! str = [str "Km:15 = hhhJjjj miles241hour\r\n"];
1627 %! str = [str "Km:2 = hhhRjjj miles3hour\r\n"];
1628 %! str = [str "Km:25 = hhhZ\r\n"];
1629 %! fmt = "Km:%d = hhh%1sjjj miles%dhour";
1630 %! c = textscan (str, fmt, "delimiter", " ");
1631 %! assert (c{1}', int32 ([10, 15, 2, 25]));
1632 %! assert (c{2}', {'B' 'J' 'R' 'Z'});
1633 %! assert (c{3}', int32 ([16, 241, 3, 0]));
1634 
1635 ## Test with default EndOfLine parameter
1636 %!test
1637 %! c = textscan ("L1\nL2", "%s");
1638 %! assert (c{:}, {"L1"; "L2"});
1639 
1640 ## Test with EndofLine parameter set to "" (empty) - newline should be in word
1641 %!test
1642 %! c = textscan ("L1\nL2", "%s", "endofline", "");
1643 %! assert (int8 ([c{:}{:}]), int8 ([76, 49, 10, 76, 50]));
1644 
1645 ## Matlab fails this test. A literal after a conversion is not a delimiter
1646 %!#test
1647 %! ## No delimiters at all besides EOL. Skip fields, even empty fields
1648 %! str = "Text1Text2Text\nTextText4Text\nText57Text";
1649 %! c = textscan (str, "Text%*dText%dText");
1650 %! assert (c{1}, int32 ([2; 4; 0]));
1651 
1652 ## CollectOutput test
1653 %!test
1654 %! b = [10:10:100];
1655 %! b = [b; 8*b/5; 8*b*1000/5];
1656 %! str = sprintf ("%g miles/hr = %g (%g) kilometers (meters)/hr\n", b);
1657 %! fmt = "%f miles%s %s %f (%f) kilometers %*s";
1658 %! c = textscan (str, fmt, "collectoutput", 1);
1659 %! assert (size (c{3}), [10, 2]);
1660 %! assert (size (c{2}), [10, 2]);
1661 
1662 ## CollectOutput test with uneven column length files
1663 %!test
1664 %! b = [10:10:100];
1665 %! b = [b; 8*b/5; 8*b*1000/5];
1666 %! str = sprintf ("%g miles/hr = %g (%g) kilometers (meters)/hr\n", b);
1667 %! str = [str "110 miles/hr"];
1668 %! fmt = "%f miles%s %s %f (%f) kilometers %*s";
1669 %! c = textscan (str, fmt, "collectoutput", 1);
1670 %! assert (size (c{1}), [11, 1]);
1671 %! assert (size (c{3}), [11, 2]);
1672 %! assert (size (c{2}), [11, 2]);
1673 %! assert (c{3}(end), NaN);
1674 %! assert (c{2}{11, 1}, "/hr");
1675 %! assert (isempty (c{2}{11, 2}), true);
1676 
1677 ## Double quoted string
1678 %!test
1679 %! str = 'First "the second called ""the middle""" third';
1680 %! fmt = "%q";
1681 %! c = textscan (str, fmt);
1682 %! assert (c{1}, {"First"; 'the second called "the middle"'; "third"});
1683 
1684 ## Arbitrary character
1685 %!test
1686 %! c = textscan ("a first, \n second, third", "%s %c %11c", "delimiter", " ,");
1687 %! assert (c{1}, {"a"; "ond"});
1688 %! assert (c{2}, {"f"; "t"});
1689 %! assert (c{3}, {"irst, \n sec"; "hird"});
1690 
1691 ## Field width and non-standard delimiters
1692 %!test
1693 %! str = "12;34;123456789;7";
1694 %! c = textscan (str, "%4d %4d", "delimiter", ";", "collectOutput", 1);
1695 %! assert (c, {[12, 34; 1234, 5678; 9, 7]});
1696 
1697 ## Field width and non-standard delimiters (2)
1698 %!test
1699 %! str = "12;34;123456789;7";
1700 %! c = textscan (str, "%4f %f", "delimiter", ";", "collectOutput", 1);
1701 %! assert (c, {[12, 34; 1234, 56789; 7, NaN]});
1702 
1703 ## FIXME: Not Matlab compatible. Matlab prioritizes precision over field width
1704 ## so "12.234e+2", when read with "%10.2f %f", yields "12.23" and "4e+2".
1705 ## Ignore trailing delimiter, but use leading one
1706 %!#test
1707 %! str = "12.234e+2,34, \n12345.789-9876j,78\n,10|3";
1708 %! c = textscan (str, "%10.2f %f", "delimiter", ",", "collectOutput", 1,
1709 %! "expChars", "e|");
1710 %! assert (c, {[1223, 34; 12345.79-9876j, 78; NaN, 10000]}, 1e-6);
1711 
1712 ## Multi-character delimiter
1713 %!test
1714 %! str = "99end2 space88gap 4564";
1715 %! c = textscan (str, "%d %s", "delimiter", {"end", "gap", "space"});
1716 %! assert (c{1}, int32 ([99; 88]));
1717 %! assert (c{2}, {"2 "; "4564"});
1718 
1719 ## FIXME: Following two tests still fail (4/13/2016).
1720 ## Delimiters as part of literals, and following literals
1721 %!#test
1722 %! str = "12 R&D & 7";
1723 %! c = textscan (str, "%f R&D %f", "delimiter", "&", "collectOutput", 1,
1724 %! "EmptyValue", -99);
1725 %! assert (c, {[12, -99; 7, -99]});
1726 
1727 ## Delimiters as part of literals, and before literals
1728 %!#test
1729 %! str = "12 & R&D 7";
1730 %! c = textscan (str, "%f R&D %f", "delimiter", "&", "collectOutput", 1);
1731 %! assert (c, {[12 7]});
1732 
1733 ## Check number of lines read, not number of passes through format string
1734 %!test
1735 %! f = tempname ();
1736 %! fid = fopen (f, "w+");
1737 %! fprintf (fid, "1\n2\n3\n4\n5\n6");
1738 %! fseek (fid, 0, "bof");
1739 %! c = textscan (fid, "%f %f", 2);
1740 %! E = feof (fid);
1741 %! fclose (fid);
1742 %! unlink (f);
1743 %! assert (c, {1, 2});
1744 %! assert (! E);
1745 
1746 ## Check number of lines read, not number of passes through format string
1747 %!test
1748 %! f = tempname ();
1749 %! fid = fopen (f, "w+");
1750 %! fprintf (fid, "1\r\n2\r3\n4\r\n5\n6");
1751 %! fseek (fid, 0, "bof");
1752 %! c = textscan (fid, "%f %f", 4);
1753 %! fclose (fid);
1754 %! unlink (f);
1755 %! assert (c, {[1;3], [2;4]});
1756 
1757 ## Check number of lines read, with multiple delimiters
1758 %!test
1759 %! f = tempname ();
1760 %! fid = fopen (f, "w+");
1761 %! fprintf (fid, "1-\r\n-2\r3-\n-4\r\n5\n6");
1762 %! fseek (fid, 0, "bof");
1763 %! c = textscan (fid, "%f %f", 4, "delimiter", "-", "multipleDelimsAsOne", 1);
1764 %! fclose (fid);
1765 %! unlink (f);
1766 %! assert (c, {[1;3], [2;4]});
1767 
1768 ## Check ReturnOnError
1769 %!test
1770 %! f = tempname ();
1771 %! fid = fopen (f, "w+");
1772 %! str = "1 2 3\n4 s 6";
1773 %! fprintf (fid, str);
1774 %! fseek (fid, 0, "bof");
1775 %! c = textscan (fid, "%f %f %f", "ReturnOnError", 1);
1776 %! fseek (fid, 0, "bof");
1777 %! fclose (fid);
1778 %! unlink (f);
1779 %! u = textscan (str, "%f %f %f", "ReturnOnError", 1);
1780 %! assert (c, {[1;4], [2], [3]});
1781 %! assert (u, {[1;4], [2], [3]});
1782 
1783 %! ## Check ReturnOnError (2)
1784 %!test
1785 %! f = tempname ();
1786 %! fid = fopen (f, "w+");
1787 %! str = "1 2 3\n4 s 6\n";
1788 %! fprintf (fid, str);
1789 %! fseek (fid, 0, "bof");
1790 %! c = textscan (fid, "%f %f %f", "ReturnOnError", 1);
1791 %! fseek (fid, 0, "bof");
1792 %! fclose (fid);
1793 %! unlink (f);
1794 %! u = textscan (str, "%f %f %f", "ReturnOnError", 1);
1795 %! assert (c, {[1;4], 2, 3});
1796 %! assert (u, {[1;4], 2, 3});
1797 
1798 %!error <Read error in field 2 of row 2>
1799 %! textscan ("1 2 3\n4 s 6", "%f %f %f", "ReturnOnError", 0);
1800 
1801 ## Check ReturnOnError (3)
1802 %!test
1803 %! f = tempname ();
1804 %! fid = fopen (f, "w+");
1805 %! fprintf (fid, "1 s 3\n4 5 6");
1806 %! fseek (fid, 0, "bof");
1807 %! c = textscan (fid, "", "ReturnOnError", 1);
1808 %! fseek (fid, 0, "bof");
1809 %! fclose (fid);
1810 %! unlink (f);
1811 %! assert (c, {1});
1812 
1813 ## Check ReturnOnError with empty fields
1814 %!test
1815 %! c = textscan ("1,,3\n4,5,6", "", "Delimiter", ",", "ReturnOnError", 1);
1816 %! assert (c, {[1;4], [NaN;5], [3;6]});
1817 
1818 ## Check ReturnOnError with empty fields (2)
1819 %!test
1820 %! c = textscan ("1,,3\n4,5,6", "%f %f %f", "Delimiter", ",",
1821 %! "ReturnOnError", 1);
1822 %! assert (c, {[1;4], [NaN;5], [3;6]});
1823 
1824 ## Check ReturnOnError in first column
1825 %!test
1826 %! c = textscan ("1 2 3\ns 5 6", "", "ReturnOnError", 1);
1827 %! assert (c, {1, 2, 3});
1828 
1829 ## FIXME: This test fails (4/14/16)
1830 ## Test incomplete first data line
1831 %!#test
1832 %! R = textscan (['Empty1' char(10)], 'Empty%d %f');
1833 %! assert (R{1}, int32 (1));
1834 %! assert (isempty (R{2}), true);
1835 
1836 %!test <*37023>
1837 %! data = textscan (" 1. 1 \n 2 3\n", '%f %f');
1838 %! assert (data{1}, [1; 2], 1e-15);
1839 %! assert (data{2}, [1; 3], 1e-15);
1840 
1841 ## Whitespace test using delimiter ";"
1842 %!test <*37333>
1843 %! tc{1, 1} = "C:/code;";
1844 %! tc{1, end+1} = "C:/code/meas;";
1845 %! tc{1, end+1} = " C:/code/sim;";
1846 %! tc{1, end+1} = "C:/code/utils;";
1847 %! string = [tc{:}];
1848 %! c = textscan (string, "%s", "delimiter", ";");
1849 %! for k = 1:max (numel (c{1}), numel (tc))
1850 %! lh = c{1}{k};
1851 %! rh = tc{k};
1852 %! rh(rh == ";") = "";
1853 %! rh = strtrim (rh);
1854 %! assert (strcmp (lh, rh));
1855 %! endfor
1856 
1857 ## Whitespace test, adding multipleDelimsAsOne true arg
1858 %!test <*37333>
1859 %! tc{1, 1} = "C:/code;";
1860 %! tc{1, end+1} = " C:/code/meas;";
1861 %! tc{1, end+1} = "C:/code/sim;;";
1862 %! tc{1, end+1} = "C:/code/utils;";
1863 %! string = [tc{:}];
1864 %! c = textscan (string, "%s", "delimiter", ";", "multipleDelimsAsOne", 1);
1865 %! for k = 1:max (numel (c{1}), numel (tc))
1866 %! lh = c{1}{k};
1867 %! rh = tc{k};
1868 %! rh(rh == ";") = "";
1869 %! rh = strtrim (rh);
1870 %! assert (strcmp (lh, rh));
1871 %! endfor
1872 
1873 ## Whitespace test (bug #37333), adding multipleDelimsAsOne false arg
1874 %!test <*37333>
1875 %! tc{1, 1} = "C:/code;";
1876 %! tc{1, end+1} = " C:/code/meas;";
1877 %! tc{1, end+1} = "C:/code/sim;;";
1878 %! tc{1, end+1} = "";
1879 %! tc{1, end+1} = "C:/code/utils;";
1880 %! string = [tc{:}];
1881 %! c = textscan (string, "%s", "delimiter", ";", "multipleDelimsAsOne", 0);
1882 %! for k = 1:max (numel (c{1}), numel (tc))
1883 %! lh = c{1}{k};
1884 %! rh = tc{k};
1885 %! rh(rh == ";") = "";
1886 %! rh = strtrim (rh);
1887 %! assert (strcmp (lh, rh));
1888 %! endfor
1889 
1890 ## Whitespace test (bug #37333) whitespace "" arg
1891 %!test <*37333>
1892 %! tc{1, 1} = "C:/code;";
1893 %! tc{1, end+1} = " C:/code/meas;";
1894 %! tc{1, end+1} = "C:/code/sim;";
1895 %! tc{1, end+1} = "C:/code/utils;";
1896 %! string = [tc{:}];
1897 %! c = textscan (string, "%s", "delimiter", ";", "whitespace", "");
1898 %! for k = 1:max (numel (c{1}), numel (tc))
1899 %! lh = c{1}{k};
1900 %! rh = tc{k};
1901 %! rh(rh == ";") = "";
1902 %! assert (strcmp (lh, rh));
1903 %! endfor
1904 
1905 ## Whitespace test (bug #37333), whitespace " " arg
1906 %!test <*37333>
1907 %! tc{1, 1} = "C:/code;";
1908 %! tc{1, end+1} = " C:/code/meas;";
1909 %! tc{1, end+1} = "C:/code/sim;";
1910 %! tc{1, end+1} = "C:/code/utils;";
1911 %! string = [tc{:}];
1912 %! c = textscan (string, "%s", "delimiter", ";", "whitespace", " ");
1913 %! for k = 1:max (numel (c{1}), numel (tc))
1914 %! lh = c{1}{k};
1915 %! rh = tc{k};
1916 %! rh(rh == ";") = "";
1917 %! rh = strtrim (rh);
1918 %! assert (strcmp (lh, rh));
1919 %! endfor
1920 
1921 ## Tests reading with empty format, should return proper nr of columns
1922 %!test
1923 %! f = tempname ();
1924 %! fid = fopen (f, "w+");
1925 %! fprintf (fid, " 1 2 3 4\n5 6 7 8");
1926 %! fseek (fid, 0, "bof");
1927 %! C = textscan (fid, "");
1928 %! E = feof (fid);
1929 %! fclose (fid);
1930 %! unlink (f);
1931 %! assert (C{1}, [1 ; 5], 1e-6);
1932 %! assert (C{2}, [2 ; 6], 1e-6);
1933 %! assert (C{3}, [3 ; 7], 1e-6);
1934 %! assert (C{4}, [4 ; 8], 1e-6);
1935 %! assert (E);
1936 
1937 ## Test leaving the file at the correct position on exit
1938 %!test
1939 %! f = tempname ();
1940 %! fid = fopen (f, "w+");
1941 %! fprintf (fid, "1,2\n3,4\n");
1942 %! fseek (fid, 0, "bof");
1943 %! C = textscan (fid, "%s %f", 2, "Delimiter", ",");
1944 %! E = ftell (fid);
1945 %! fclose (fid);
1946 %! unlink (f);
1947 %! assert (E, 8);
1948 
1949 ## Tests reading with empty format; empty fields & incomplete lower row
1950 %!test
1951 %! f = tempname ();
1952 %! fid = fopen (f, "w+");
1953 %! fprintf (fid, " ,2,,4\n5,6");
1954 %! fseek (fid, 0, "bof");
1955 %! C = textscan (fid, "", "delimiter", ",", "EmptyValue", 999,
1956 %! "CollectOutput" , 1);
1957 %! fclose (fid);
1958 %! unlink (f);
1959 %! assert (C{1}, [999, 2, 999, 4; 5, 6, 999, 999], 1e-6);
1960 
1961 ## Error message tests
1962 
1963 %!test
1964 %! f = tempname ();
1965 %! fid = fopen (f, "w+");
1966 %! msg1 = "textscan: 1 parameters given, but only 0 values";
1967 %! try
1968 %! C = textscan (fid, "", "headerlines");
1969 %! end_try_catch
1970 %! assert (! feof (fid));
1971 %! fclose (fid);
1972 %! unlink (f);
1973 %! assert (msg1, lasterr);
1974 
1975 %!test
1976 %! f = tempname ();
1977 %! fid = fopen (f, "w+");
1978 %! msg1 = "textscan: HeaderLines must be numeric";
1979 %! try
1980 %! C = textscan (fid, "", "headerlines", "hh");
1981 %! end_try_catch
1982 %! fclose (fid);
1983 %! unlink (f);
1984 %! assert (msg1, lasterr);
1985 
1986 ## Skip headerlines
1987 %!test
1988 %! C = textscan ("field 1 field2\n 1 2\n3 4", "", "headerlines", 1,
1989 %! "collectOutput", 1);
1990 %! assert (C, {[1 2; 3 4]});
1991 
1992 ## Skip headerlines with non-default EOL
1993 %!test
1994 %! C = textscan ("field 1 field2\r 1 2\r3 4", "", "headerlines", 2,
1995 %! "collectOutput", 1, "EndOfLine", '\r');
1996 %! assert (C, {[3 4]});
1997 
1998 %!test
1999 %! f = tempname ();
2000 %! fid = fopen (f, "w+");
2001 %! fprintf (fid,"some_string");
2002 %! fseek (fid, 0, "bof");
2003 %! msg1 = "textscan: EndOfLine must be at most one character or '\\r\\n'";
2004 %! try
2005 %! C = textscan (fid, "%f", "EndOfLine", "\n\r");
2006 %! end_try_catch
2007 %! fclose (fid);
2008 %! unlink (f);
2009 %! assert (msg1, lasterr);
2010 
2011 %!test
2012 %! f = tempname ();
2013 %! fid = fopen (f, "w+");
2014 %! fprintf (fid,"some_string");
2015 %! fseek (fid, 0, "bof");
2016 %! msg1 = "textscan: EndOfLine must be at most one character or '\\r\\n'";
2017 %! try
2018 %! C = textscan (fid, "%f", "EndOfLine", 33);
2019 %! end_try_catch
2020 %! fclose (fid);
2021 %! unlink (f);
2022 %! assert (msg1, lasterr);
2023 
2024 %!assert <*41824> (textscan ("123", "", "whitespace", " "){:}, 123);
2025 
2026 ## just test supplied emptyvalue
2027 %!assert <*42343> (textscan (",NaN", "", "delimiter", "," ,"emptyValue" ,Inf),
2028 %! {Inf, NaN})
2029 
2030 ## test padding with supplied emptyvalue
2031 %!test <*42343>
2032 %! c = textscan (",1,,4\nInf, ,NaN\n", "", "delimiter", ",",
2033 %! "emptyvalue", -10);
2034 %! assert (cell2mat (c), [-10, 1, -10, 4; Inf, -10, NaN, -10]);
2035 
2036 %!test <*42528>
2037 %! assert (textscan ("1i", ""){1}, 0+1i);
2038 %! C = textscan ("3, 2-4i, NaN\n -i, 1, 23.4+2.2i\n 1+1 1+1j", "",
2039 %! "delimiter", ",");
2040 %! assert (cell2mat (C), [3+0i, 2-4i, NaN+0i; 0-i, 1+0i, 23.4+2.2i; 1 1 1+1i]);
2041 
2042 %!test
2043 %! ## TreatAsEmpty
2044 %! C = textscan ("1,2,3,NN,5,6\n", "%d%d%d%f", "delimiter", ",",
2045 %! "TreatAsEmpty", "NN");
2046 %! assert (C{3}(1), int32 (3));
2047 %! assert (C{4}(1), NaN);
2048 
2049 ## MultipleDelimsAsOne
2050 %!test
2051 %! str = "11, 12, 13,, 15\n21,, 23, 24, 25\n,, 33, 34, 35\n";
2052 %! C = textscan (str, "%f %f %f %f", "delimiter", ",",
2053 %! "multipledelimsasone", 1, "endofline", "\n");
2054 %! assert (C{1}', [11, 21, 33]);
2055 %! assert (C{2}', [12, 23, 34]);
2056 %! assert (C{3}', [13, 24, 35]);
2057 %! assert (C{4}', [15, 25, NaN]);
2058 
2059 ## Single-quoted escape sequences
2060 %!test
2061 %! str = "11\t12\t13\r21\t22\t23";
2062 %! c = textscan (str, "", "delimiter", '\t', "EndOfLine", '\r');
2063 %! assert (c{1}', [11, 21]);
2064 %! assert (c{2}', [12, 22]);
2065 %! assert (c{3}', [13, 23]);
2066 
2067 %!test <*44750>
2068 %! c = textscan ("/home/foo/", "%s", "delimiter", "/",
2069 %! "MultipleDelimsAsOne", 1);
2070 %! assert (c{1}, {"home"; "foo"});
2071 
2072 ## FIXME: Test still fails (4/13/2016).
2073 ## Allow cuddling %sliteral, but warn it is ambiguous
2074 %!#test
2075 %! C = textscan ("abcxyz51\nxyz83\n##xyz101", "%s xyz %d");
2076 %! assert (C{1}([1 3]), {"abc"; "##"});
2077 %! assert (isempty (C{1}{2}), true);
2078 %! assert (C{2}, int32 ([51; 83; 101]));
2079 
2080 ## Literals are not delimiters.
2081 
2082 ## Test for false positives in check for non-supported format specifiers
2083 %!test
2084 %! c = textscan ("Total: 32.5 % (of cm values)",
2085 %! "Total: %f %% (of cm values)");
2086 %! assert (c{1}, 32.5, 1e-5);
2087 
2088 ## Test various forms of string format specifiers
2089 %!test <*45712>
2090 %! str = "14 :1 z:2 z:3 z:5 z:11";
2091 %! C = textscan (str, "%f %s %*s %3s %*3s %f", "delimiter", ":");
2092 %! assert (C, {14, {"1 z"}, {"3 z"}, 11});
2093 
2094 ## Bit width, fixed width conversion specifiers
2095 %!test
2096 %! str2 = "123456789012345 ";
2097 %! str2 = [str2 str2 str2 str2 str2 str2 str2 str2];
2098 %! str2 = [str2 "123456789.01234 1234567890.1234 12345.678901234 12345.678901234"];
2099 %! pttrn = "%3u8%*s %5u16%*s %10u32%*s %15u64 %3d8%*s %5d16%*s %10d32%*s %15d64 %9f32%*s %14f64%*s %10.2f32%*s %12.2f64%*s";
2100 %! C = textscan (str2, pttrn, "delimiter", " ");
2101 %! assert (C{1}, uint8 (123));
2102 %! assert (C{2}, uint16 (12345));
2103 %! assert (C{3}, uint32 (1234567890));
2104 %! assert (C{4}, uint64 (123456789012345));
2105 %! assert (C{5}, int8 (123));
2106 %! assert (C{6}, int16 (12345));
2107 %! assert (C{7}, int32 (1234567890));
2108 %! assert (C{8}, int64 (123456789012345));
2109 %! assert (C{9}, single (123456789), 1e-12);
2110 %! assert (C{10}, double (1234567890.123), 1e-15);
2111 %! assert (C{11}, single (12345.68), 1e-5);
2112 %! assert (C{12}, double (12345.68), 1e-11);
2113 
2114 ## Bit width, fixed width conv. specifiers -- check the right amount is left
2115 %!test
2116 %! str2 = "123456789012345 ";
2117 %! str2 = [str2 str2 "123456789.01234"];
2118 %! pttrn = "%3u8 %5u16 %10u32 %3d8 %5d16 %10d32 %9f32 %9f";
2119 %! C = textscan (str2, pttrn, "delimiter", " ");
2120 %! assert (C{1}, uint8 (123));
2121 %! assert (C{2}, uint16 (45678));
2122 %! assert (C{3}, uint32 (9012345));
2123 %! assert (C{4}, int8 (123));
2124 %! assert (C{5}, int16 (45678));
2125 %! assert (C{6}, int32 (9012345));
2126 %! assert (C{7}, single (123456789), 1e-12);
2127 %! assert (C{8}, double (0.01234), 1e-12);
2128 
2129 %!test
2130 %! C = textscan ("123.123", "%2f %3f %3f");
2131 %! assert (C{1}, 12);
2132 %! assert (C{2}, 3.1, 1e-11);
2133 %! assert (C{3}, 23);
2134 
2135 %!test
2136 %! C = textscan ("123.123", "%3f %3f %3f");
2137 %! assert (C{1}, 123);
2138 %! assert (C{2}, 0.12, 1e-11);
2139 %! assert (C{3}, 3);
2140 
2141 %!test
2142 %! C = textscan ("123.123", "%4f %3f");
2143 %! assert (C{1}, 123);
2144 %! assert (C{2}, 123);
2145 
2146 ## field width interrupts exponent. (Matlab incorrectly gives [12, 2e12])
2147 %!test
2148 %! assert (textscan ("12e12", "%4f"), {[120; 2]});
2149 %! assert (textscan ("12e+12", "%5f"), {[120; 2]});
2150 %! assert (textscan ("125e-12","%6f"), {[12.5; 2]});
2151 
2152 ## %[] tests
2153 ## Plain [..] and *[..]
2154 %!test
2155 %! ar = "abcdefguvwxAny\nacegxyzTrailing\nJunk";
2156 %! C = textscan (ar, "%[abcdefg] %*[uvwxyz] %s");
2157 %! assert (C{1}, {"abcdefg"; "aceg"; ""});
2158 %! assert (C{2}, {"Any"; "Trailing"; "Junk"});
2159 
2160 %!test
2161 %! assert (textscan ("A2 B2 C3", "%*[ABC]%d", 3), {int32([2; 2; 3])});
2162 
2163 ## [^..] and *[^..]
2164 %!test
2165 %! br = "abcdefguvwx1Any\nacegxyz2Trailing\n3Junk";
2166 %! C = textscan (br, "%[abcdefg] %*[^0123456789] %s");
2167 %! assert (C{1}, {"abcdefg"; "aceg"; ""});
2168 %! assert (C{2}, {"1Any"; "2Trailing"; "3Junk"});
2169 
2170 ## [..] and [^..] containing delimiters
2171 %!test
2172 %! cr = "ab cd efguv wx1Any\na ce gx yz2Trailing\n 3Junk";
2173 %! C = textscan (cr, "%[ abcdefg] %*[^0123456789] %s", "delimiter", " \n",
2174 %! "whitespace", "");
2175 %! assert (C{1}, {"ab cd efg"; "a ce g"; " "});
2176 %! assert (C{2}, {"1Any"; "2Trailing"; "3Junk"});
2177 
2178 %!assert <*36464> (textscan ("1 2 3 4 5 6", "%*n%n%*[^\n]"){1}, 2);
2179 
2180 ## test %[]] and %[^]]
2181 %!test
2182 %! assert (textscan ("345]", "%*[123456]%[]]"){1}{1}, "]");
2183 %! assert (textscan ("345]", "%*[^]]%s"){1}{1}, "]");
2184 
2185 ## Test that "-i" checks the next two characters
2186 %!test
2187 %! C = textscan ("-i -in -inf -infinity", "%f %f%s %f %f %s");
2188 %! assert (C, {-i, -i, {"n"}, -Inf, -Inf, {"inity"}});
2189 
2190 ## Again for "+i", this time with custom parser
2191 %!test
2192 %! C = textscan ("+i +in +inf +infinity", "%f %f%s %f %f %s", "ExpChars", "eE");
2193 %! assert (C, {i, i, {"n"}, Inf, Inf, {"inity"}});
2194 
2195 ## Check single quoted format interprets control sequences
2196 %!test
2197 %! C = textscan ("1 2\t3 4", '%f %[^\t] %f %f');
2198 %! assert (C, {1, {"2"}, 3, 4});
2199 
2200 ## Check a non-empty line with no valid conversion registers empytValue
2201 %!test
2202 %! C = textscan ("Empty\n", "Empty%f %f");
2203 %! assert (C, { NaN, NaN });
2204 
2205 ## Check overflow and underflow of integer types
2206 %!test
2207 %! a = "-1e90 ";
2208 %! b = "1e90 ";
2209 %! fmt = "%d8 %d16 %d32 %d64 %u8 %u16 %u32 %u64 ";
2210 %! C = textscan ([a a a a a a a a b b b b b b b b], fmt);
2211 %! assert (C{1}, int8 ([-128; 127]));
2212 %! assert (C{2}, int16 ([-32768; 32767]));
2213 %! assert (C{3}, int32 ([-2147483648; 2147483647]));
2214 %! assert (C{4}, int64 ([-9223372036854775808; 9223372036854775807]));
2215 %! assert (C{5}, uint8 ([0; 255]));
2216 %! assert (C{6}, uint16 ([0; 65535]));
2217 %! assert (C{7}, uint32 ([0; 4294967295]));
2218 %! assert (C{8}, uint64 ([0; 18446744073709551615]));
2219 
2220 ## Tests from Matlab (does The MathWorks have any copyright over the input?)
2221 %!test
2222 %! f = tempname ();
2223 %! fid = fopen (f, "w+");
2224 %! fprintf (fid,"09/12/2005 Level1 12.34 45 1.23e10 inf Nan Yes 5.1+3i\n");
2225 %! fprintf (fid,"10/12/2005 Level2 23.54 60 9e19 -inf 0.001 No 2.2-.5i\n");
2226 %! fprintf (fid,"11/12/2005 Level3 34.90 12 2e5 10 100 No 3.1+.1i\n");
2227 %! fseek (fid, 0, "bof");
2228 %! C = textscan (fid,"%s %s %f32 %d8 %u %f %f %s %f");
2229 %! %assert (C{1}, {"09/12/2005";"10/12/2005";"11/12/2005"});
2230 %! assert (C{2}, {"Level1";"Level2";"Level3"});
2231 %! assert (C{3}, [single(12.34);single(23.54);single(34.90)]);
2232 %! assert (C{4}, [int8(45);int8(60);int8(12)]);
2233 %! assert (C{5}, [uint32(4294967295);uint32(4294967295);uint32(200000)]);
2234 %! assert (C{6}, [inf;-inf;10]);
2235 %! assert (C{7}, [NaN;0.001;100], eps);
2236 %! assert (C{8}, {"Yes";"No";"No"});
2237 %! assert (C{9}, [5.1+3i;2.2-0.5i;3.1+0.1i]);
2238 %! fseek (fid, 0, "bof");
2239 %! C = textscan (fid,"%s Level%d %f32 %d8 %u %f %f %s %f");
2240 %! assert (C{2}, [int32(1);int32(2);int32(3)]);
2241 %! assert (C{3}, [single(12.34);single(23.54);single(34.90)]);
2242 %! fseek (fid, 0, "bof");
2243 %! C = textscan (fid, '%s %*[^\n]');
2244 %! fclose (fid);
2245 %! unlink (f);
2246 %! assert (C, {{"09/12/2005";"10/12/2005";"11/12/2005"}});
2247 
2248 %!test
2249 %! f = tempname ();
2250 %! fid = fopen (f, "w+");
2251 %! fprintf (fid,"1, 2, 3, 4, , 6\n");
2252 %! fprintf (fid,"7, 8, 9, , 11, 12\n");
2253 %! fseek (fid, 0, "bof");
2254 %! C = textscan (fid,"%f %f %f %f %u8 %f", "Delimiter",",","EmptyValue",-Inf);
2255 %! fclose (fid);
2256 %! unlink (f);
2257 %! assert (C{4}, [4; -Inf]);
2258 %! assert (C{5}, uint8 ([0; 11]));
2259 
2260 %!test
2261 %! f = tempname ();
2262 %! fid = fopen (f, "w+");
2263 %! fprintf (fid,"abc, 2, NA, 3, 4\n");
2264 %! fprintf (fid,"// Comment Here\n");
2265 %! fprintf (fid,"def, na, 5, 6, 7\n");
2266 %! fseek (fid, 0, "bof");
2267 %! C = textscan (fid, "%s %n %n %n %n", "Delimiter", ",",
2268 %! "TreatAsEmpty", {"NA","na"}, "CommentStyle", "//");
2269 %! fclose (fid);
2270 %! unlink (f);
2271 %! assert (C{1}, {"abc";"def"});
2272 %! assert (C{2}, [2; NaN]);
2273 %! assert (C{3}, [NaN; 5]);
2274 %! assert (C{4}, [3; 6]);
2275 %! assert (C{5}, [4; 7]);
2276 
2277 ## FIXME: Almost passes. Second return value is {"/"}. Tested 4/14/16.
2278 ## Test start of comment as string
2279 %!#test
2280 %! c = textscan ("1 / 2 // 3", "%n %s %u8", "CommentStyle", {"//"});
2281 %! assert (c(1), {1, "/", 2});
2282 
2283 %!assert (textscan (["1 2 3 4"; "5 6 7 8"], "%f"), {[15; 26; 37; 48]})
2284 
2285 ## Check for delimiter after exponent
2286 %!assert (textscan ("1e-3|42", "%f", "delimiter", "|"), {[1e-3; 42]})
2287 
2288 %!test <*52479>
2289 %! str = "\t\ta\tb\tc\n";
2290 %! ret = textscan (str, "%s", "delimiter", "\t");
2291 %! assert (ret, { {''; ''; 'a'; 'b'; 'c'} });
2292 
2293 %!test <*52479>
2294 %! str = "\t\ta\tb\tc\n";
2295 %! ret = textscan (str, "%s", "delimiter", {"\t"});
2296 %! assert (ret, { {''; ''; 'a'; 'b'; 'c'} });
2297 
2298 %!test <*52550>
2299 %! str = ",,1,2,3\n";
2300 %! obs = textscan (str, "%d", "delimiter", ",");
2301 %! assert (obs, { [0; 0; 1; 2; 3] });
2302 %! obs = textscan (str, "%d", "delimiter", {","});
2303 %! assert (obs, { [0; 0; 1; 2; 3] });
2304 
2305 %!test <*52550>
2306 %! str = " , ,1,2,3\n";
2307 %! obs = textscan (str, "%d", "delimiter", ",");
2308 %! assert (obs, { [0; 0; 1; 2; 3] });
2309 %! textscan (str, "%d", "delimiter", {","});
2310 %! assert (obs, { [0; 0; 1; 2; 3] });
2311 
2312 %!test <*52550>
2313 %! str = " 0 , 5+6j , -INF+INFj ,NaN,3\n";
2314 %! obs = textscan (str, "%f", "delimiter", ",");
2315 %! assert (obs, { [0; 5+6i; complex(-Inf,Inf); NaN; 3] });
2316 %! obs = textscan (str, "%f", "delimiter", {","});
2317 %! assert (obs, { [0; 5+6i; complex(-Inf,Inf); NaN; 3] });
2318 
2319 %!test <*52550>
2320 %! str = " 0;,;,1;,2;,3\n";
2321 %! assert (textscan (str, "%f", "delimiter", {";,"}), { [0; NaN; 1; 2; 3] });
2322 
2323 %!test <*52550>
2324 %! str = " 0 ;1 , $ 2 ;3\n";
2325 %! obs = textscan (str, "%f", "delimiter", ",;$");
2326 %! assert (obs, { [0; 1; NaN; 2; 3] });
2327 %! obs = textscan (str, "%f", "delimiter", {",",";","$"});
2328 %! assert (obs, { [0; 1; NaN; 2; 3] });
2329 
2330 ## file stream with encoding
2331 ## FIXME: should be conditional on OCTAVE_HAVE_STRICT_ENCODING_FACET
2332 %!testif ; ! __have_feature__ ("LLVM_LIBCXX")
2333 %! f = tempname ();
2334 %! fid = fopen (f, "wt+", "n", "iso-8859-1");
2335 %! unwind_protect
2336 %! fprintf (fid, "abc,äöü\n");
2337 %! fflush (fid);
2338 %! fseek (fid, 0, "bof");
2339 %! obs = textscan (fid, "%s", "delimiter", ",");
2340 %! fclose (fid);
2341 %! assert (obs, { {"abc"; "äöü"} });
2342 %! unwind_protect_cleanup
2343 %! unlink (f);
2344 %! end_unwind_protect
2345 
2346 %!test <*56917>
2347 %! str = '"a,b","c"';
2348 %! obs = textscan (str, "%q", "delimiter", ",");
2349 %! assert (obs, { { "a,b"; "c" } });
2350 
2351 %!test <*58008>
2352 %! txt = sprintf ('literal_other_1_1;literal_other_1_2\nliteral_other_2_1;literal_other_2_2\nliteral_other_3_1;literal_other_3_2');
2353 %! nm1 = textscan (txt, 'literal%s literal%s', 'Delimiter', ';');
2354 %! assert (nm1{1}, {"_other_1_1" ; "_other_2_1" ; "_other_3_1"});
2355 %! assert (nm1{2}, {"_other_1_2" ; "_other_2_2" ; "_other_3_2"});
2356 %! nm2 = textscan (txt, 'literal%s;literal%s', 'Delimiter', ';');
2357 %! assert (nm1, nm2);
2358 
2359 %!test <*57612>
2360 %! str = sprintf (['101,' '\n' '201,']);
2361 %! C = textscan (str, '%s%q', 'Delimiter', ',');
2362 %! assert (size (C), [1, 2]);
2363 %! assert (C{1}, { "101"; "201" });
2364 %! assert (C{2}, { ""; "" });
2365 
2366 %!test <*57612>
2367 %! str = sprintf (['101,' '\n' '201,']);
2368 %! C = textscan (str, '%s%f', 'Delimiter', ',');
2369 %! assert (size (C), [1, 2]);
2370 %! assert (C{1}, { "101"; "201" });
2371 %! assert (C{2}, [ NaN; NaN ]);
2372 
2373 %!test <*57612>
2374 %! str = sprintf (['101,' '\n' '201,']);
2375 %! C = textscan (str, '%s%d', 'Delimiter', ',');
2376 %! assert (size (C), [1, 2]);
2377 %! assert (C{1}, { "101"; "201" });
2378 %! assert (C{2}, int32 ([ 0; 0 ]));
2379 
2380 %!test <*51093>
2381 %! str = sprintf ('a\t\tb\tc');
2382 %! C = textscan (str, '%s', 'Delimiter', '\t', 'MultipleDelimsAsOne', false);
2383 %! assert (C{1}, {'a'; ''; 'b'; 'c'});
2384 
2385 %!test <50743>
2386 %! C = textscan ('5973459727478852968', '%u64');
2387 %! assert (C{1}, uint64 (5973459727478852968));
2388 
2389 %!assert <*60711> (textscan('1,.,2', '%f', 'Delimiter', ','), {1});
2390 
2391 */
2392 
2393 // These tests have end-comment sequences, so can't just be in a comment
2394 #if 0
2395 ## Test unfinished comment
2396 %!test
2397 %! c = textscan ("1 2 /* half comment", "%n %u8", "CommentStyle", {"/*", "*/"});
2398 %! assert (c, {1, 2});
2399 
2400 ## Test reading from a real file
2401 %!test
2402 %! f = tempname ();
2403 %! fid = fopen (f, "w+");
2404 %! d = rand (1, 4);
2405 %! fprintf (fid, " %f %f /* comment */ %f %f ", d);
2406 %! fseek (fid, 0, "bof");
2407 %! A = textscan (fid, "%f %f", "CommentStyle", {"/*", "*/"});
2408 %! E = feof (fid);
2409 %! fclose (fid);
2410 %! unlink (f);
2411 %! assert (A{1}, [d(1); d(3)], 1e-6);
2412 %! assert (A{2}, [d(2); d(4)], 1e-6);
2413 %! assert (E);
2414 #endif
2415 
2416 /*
2417 ## Test input validation
2418 %!error textscan ()
2419 %!error <file id must be> textscan (single (4))
2420 %!error <file id must be> textscan ({4})
2421 %!error <must be a string> textscan ("Hello World", 2)
2422 %!error <at most one character or>
2423 %! textscan ("Hello World", "%s", "EndOfLine", 3);
2424 %!error <'%z' is not a valid format specifier> textscan ("1.0", "%z")
2425 %!error <no valid format conversion specifiers> textscan ("1.0", "foo")
2426 */
2427 
2428 static octave_value
2429 do_fread (stream& os, const octave_value& size_arg,
2430  const octave_value& prec_arg, const octave_value& skip_arg,
2431  const octave_value& arch_arg, octave_idx_type& count)
2432 {
2433  count = -1;
2434 
2435  Array<double> size = size_arg.xvector_value ("fread: invalid SIZE specified");
2436 
2437  std::string prec = prec_arg.xstring_value ("fread: PRECISION must be a string");
2438 
2439  int block_size = 1;
2440  oct_data_conv::data_type input_type;
2441  oct_data_conv::data_type output_type;
2442 
2443  try
2444  {
2445  oct_data_conv::string_to_data_type (prec, block_size,
2446  input_type, output_type);
2447  }
2448  catch (execution_exception& ee)
2449  {
2450  error (ee, "fread: invalid PRECISION specified");
2451  }
2452 
2453  int skip = 0;
2454 
2455  try
2456  {
2457  skip = skip_arg.int_value (true);
2458  }
2459  catch (execution_exception& ee)
2460  {
2461  error (ee, "fread: SKIP must be an integer");
2462  }
2463 
2464  std::string arch = arch_arg.xstring_value ("fread: ARCH architecture type must be a string");
2465 
2466  mach_info::float_format flt_fmt
2468 
2469  return os.read (size, block_size, input_type, output_type, skip,
2470  flt_fmt, count);
2471 }
2472 
2473 DEFMETHOD (fread, interp, args, ,
2474  doc: /* -*- texinfo -*-
2475 @deftypefn {} {@var{val} =} fread (@var{fid})
2476 @deftypefnx {} {@var{val} =} fread (@var{fid}, @var{size})
2477 @deftypefnx {} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision})
2478 @deftypefnx {} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip})
2479 @deftypefnx {} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip}, @var{arch})
2480 @deftypefnx {} {[@var{val}, @var{count}] =} fread (@dots{})
2481 Read binary data from the file specified by the file descriptor @var{fid}.
2482 
2483 The optional argument @var{size} specifies the amount of data to read
2484 and may be one of
2485 
2486 @table @code
2487 @item Inf
2488 Read as much as possible, returning a column vector.
2489 
2490 @item @var{nr}
2491 Read up to @var{nr} elements, returning a column vector.
2492 
2493 @item [@var{nr}, Inf]
2494 Read as much as possible, returning a matrix with @var{nr} rows. If the
2495 number of elements read is not an exact multiple of @var{nr}, the last
2496 column is padded with zeros.
2497 
2498 @item [@var{nr}, @var{nc}]
2499 Read up to @code{@var{nr} * @var{nc}} elements, returning a matrix with
2500 @var{nr} rows. If the number of elements read is not an exact multiple
2501 of @var{nr}, the last column is padded with zeros.
2502 @end table
2503 
2504 @noindent
2505 If @var{size} is omitted, a value of @code{Inf} is assumed.
2506 
2507 The optional argument @var{precision} is a string specifying the type of
2508 data to read and may be one of
2509 
2510 @table @asis
2511 @item @qcode{"uint8"} (default)
2512 8-bit unsigned integer.
2513 
2514 @item @qcode{"int8"}
2515 @itemx @qcode{"integer*1"}
2516 8-bit signed integer.
2517 
2518 @item @qcode{"uint16"}
2519 @itemx @qcode{"ushort"}
2520 @itemx @qcode{"unsigned short"}
2521 16-bit unsigned integer.
2522 
2523 @item @qcode{"int16"}
2524 @itemx @qcode{"integer*2"}
2525 @itemx @qcode{"short"}
2526 16-bit signed integer.
2527 
2528 @item @qcode{"uint"}
2529 @itemx @qcode{"uint32"}
2530 @itemx @qcode{"unsigned int"}
2531 @itemx @qcode{"ulong"}
2532 @itemx @qcode{"unsigned long"}
2533 32-bit unsigned integer.
2534 
2535 @item @qcode{"int"}
2536 @itemx @qcode{"int32"}
2537 @itemx @qcode{"integer*4"}
2538 @itemx @qcode{"long"}
2539 32-bit signed integer.
2540 
2541 @item @qcode{"uint64"}
2542 64-bit unsigned integer.
2543 
2544 @item @qcode{"int64"}
2545 @itemx @qcode{"integer*8"}
2546 64-bit signed integer.
2547 
2548 @item @qcode{"single"}
2549 @itemx @qcode{"float"}
2550 @itemx @qcode{"float32"}
2551 @itemx @qcode{"real*4"}
2552 32-bit floating point number.
2553 
2554 @item @qcode{"double"}
2555 @itemx @qcode{"float64"}
2556 @itemx @qcode{"real*8"}
2557 64-bit floating point number.
2558 
2559 @item @qcode{"char"}
2560 @itemx @qcode{"char*1"}
2561 8-bit single character.
2562 
2563 @item @qcode{"uchar"}
2564 @itemx @qcode{"unsigned char"}
2565 8-bit unsigned character.
2566 
2567 @item @qcode{"schar"}
2568 @itemx @qcode{"signed char"}
2569 8-bit signed character.
2570 
2571 @end table
2572 
2573 @noindent
2574 The default precision is @qcode{"uint8"}.
2575 
2576 The @var{precision} argument may also specify an optional repeat
2577 count. For example, @samp{32*single} causes @code{fread} to read
2578 a block of 32 single precision floating point numbers. Reading in
2579 blocks is useful in combination with the @var{skip} argument.
2580 
2581 The @var{precision} argument may also specify a type conversion.
2582 For example, @samp{int16=>int32} causes @code{fread} to read 16-bit
2583 integer values and return an array of 32-bit integer values. By
2584 default, @code{fread} returns a double precision array. The special
2585 form @samp{*TYPE} is shorthand for @samp{TYPE=>TYPE}.
2586 
2587 The conversion and repeat counts may be combined. For example, the
2588 specification @samp{32*single=>single} causes @code{fread} to read
2589 blocks of single precision floating point values and return an array
2590 of single precision values instead of the default array of double
2591 precision values.
2592 
2593 The optional argument @var{skip} specifies the number of bytes to skip
2594 after each element (or block of elements) is read. If it is not
2595 specified, a value of 0 is assumed. If the final block read is not
2596 complete, the final skip is omitted. For example,
2597 
2598 @example
2599 fread (f, 10, "3*single=>single", 8)
2600 @end example
2601 
2602 @noindent
2603 will omit the final 8-byte skip because the last read will not be
2604 a complete block of 3 values.
2605 
2606 The optional argument @var{arch} is a string specifying the data format
2607 for the file. Valid values are
2608 
2609 @table @asis
2610 @item @qcode{"native"} or @qcode{"n"}
2611 The format of the current machine.
2612 
2613 @item @qcode{"ieee-be"} or @qcode{"b"}
2614 IEEE big endian.
2615 
2616 @item @qcode{"ieee-le"} or @qcode{"l"}
2617 IEEE little endian.
2618 @end table
2619 
2620 If no @var{arch} is given the value used in the call to @code{fopen} which
2621 created the file descriptor is used. Otherwise, the value specified with
2622 @code{fread} overrides that of @code{fopen} and determines the data format.
2623 
2624 The output argument @var{val} contains the data read from the file.
2625 
2626 The optional return value @var{count} contains the number of elements read.
2627 @seealso{fwrite, fgets, fgetl, fscanf, fopen}
2628 @end deftypefn */)
2629 {
2630  int nargin = args.length ();
2631 
2632  if (nargin < 1 || nargin > 5)
2633  print_usage ();
2634 
2635  stream_list& streams = interp.get_stream_list ();
2636 
2637  stream os = streams.lookup (args(0), "fread");
2638 
2639  octave_value size = lo_ieee_inf_value ();
2640  octave_value prec = "uint8";
2641  octave_value skip = 0;
2642  octave_value arch = "unknown";
2643 
2644  int idx = 1;
2645 
2646  if (nargin > idx && ! args(idx).is_string ())
2647  size = args(idx++);
2648 
2649  if (nargin > idx)
2650  prec = args(idx++);
2651 
2652  if (nargin > idx)
2653  skip = args(idx++);
2654 
2655  if (nargin > idx)
2656  arch = args(idx++);
2657  else if (skip.is_string ())
2658  {
2659  arch = skip;
2660  skip = 0;
2661  }
2662 
2663  octave_idx_type count = -1;
2664 
2665  octave_value tmp = do_fread (os, size, prec, skip, arch, count);
2666 
2667  return ovl (tmp, count);
2668 }
2669 
2670 static int
2671 do_fwrite (stream& os, const octave_value& data,
2672  const octave_value& prec_arg, const octave_value& skip_arg,
2673  const octave_value& arch_arg)
2674 {
2675  std::string prec = prec_arg.xstring_value ("fwrite: PRECISION must be a string");
2676 
2677  int block_size = 1;
2678  oct_data_conv::data_type output_type;
2679 
2680  try
2681  {
2682  oct_data_conv::string_to_data_type (prec, block_size, output_type);
2683  }
2684  catch (execution_exception& ee)
2685  {
2686  error (ee, "fwrite: invalid PRECISION specified");
2687  }
2688 
2689  int skip = 0;
2690 
2691  try
2692  {
2693  skip = skip_arg.int_value (true);
2694  }
2695  catch (execution_exception& ee)
2696  {
2697  error (ee, "fwrite: SKIP must be an integer");
2698  }
2699 
2700  std::string arch = arch_arg.xstring_value ("fwrite: ARCH architecture type must be a string");
2701 
2702  mach_info::float_format flt_fmt
2704 
2705  return os.write (data, block_size, output_type, skip, flt_fmt);
2706 }
2707 
2708 DEFMETHOD (fwrite, interp, args, ,
2709  doc: /* -*- texinfo -*-
2710 @deftypefn {} {@var{count} =} fwrite (@var{fid}, @var{data})
2711 @deftypefnx {} {@var{count} =} fwrite (@var{fid}, @var{data}, @var{precision})
2712 @deftypefnx {} {@var{count} =} fwrite (@var{fid}, @var{data}, @var{precision}, @var{skip})
2713 @deftypefnx {} {@var{count} =} fwrite (@var{fid}, @var{data}, @var{precision}, @var{skip}, @var{arch})
2714 Write data in binary form to the file specified by the file descriptor
2715 @var{fid}.
2716 
2717 The argument @var{data} is a matrix of values that are to be written to the
2718 file. The values are extracted in column-major order.
2719 
2720 The remaining arguments @var{precision}, @var{skip}, and @var{arch} are
2721 optional, and are interpreted as described for @code{fread}.
2722 
2723 The output @var{count} is the number of data items successfully written.
2724 
2725 Programming Note: The behavior of @code{fwrite} is undefined if the values in
2726 @var{data} are too large to fit in the specified precision.
2727 @seealso{fread, fputs, fprintf, fopen}
2728 @end deftypefn */)
2729 {
2730  int nargin = args.length ();
2731 
2732  if (nargin < 2 || nargin > 5)
2733  print_usage ();
2734 
2735  stream_list& streams = interp.get_stream_list ();
2736 
2737  stream os = streams.lookup (args(0), "fwrite");
2738 
2739  octave_value prec = "uchar";
2740  octave_value skip = 0;
2741  octave_value arch = "unknown";
2742 
2743  int idx = 1;
2744 
2745  octave_value data = args(idx++);
2746 
2747  if (nargin > idx)
2748  prec = args(idx++);
2749 
2750  if (nargin > idx)
2751  skip = args(idx++);
2752 
2753  if (nargin > idx)
2754  arch = args(idx++);
2755  else if (skip.is_string ())
2756  {
2757  arch = skip;
2758  skip = 0;
2759  }
2760 
2761  return ovl (do_fwrite (os, data, prec, skip, arch));
2762 }
2763 
2764 DEFMETHODX ("feof", Ffeof, interp, args, ,
2765  doc: /* -*- texinfo -*-
2766 @deftypefn {} {@var{status} =} feof (@var{fid})
2767 Return 1 if an end-of-file condition has been encountered for the file
2768 specified by file descriptor @var{fid} and 0 otherwise.
2769 
2770 Note that @code{feof} will only return 1 if the end of the file has already
2771 been encountered, not if the next read operation will result in an
2772 end-of-file condition.
2773 @seealso{fread, frewind, fseek, fclear, fopen}
2774 @end deftypefn */)
2775 {
2776  if (args.length () != 1)
2777  print_usage ();
2778 
2779  stream_list& streams = interp.get_stream_list ();
2780 
2781  stream os = streams.lookup (args(0), "feof");
2782 
2783  return ovl (os.eof () ? 1.0 : 0.0);
2784 }
2785 
2786 DEFMETHODX ("ferror", Fferror, interp, args, ,
2787  doc: /* -*- texinfo -*-
2788 @deftypefn {} {@var{msg} =} ferror (@var{fid})
2789 @deftypefnx {} {[@var{msg}, @var{err}] =} ferror (@var{fid})
2790 @deftypefnx {} {[@dots{}] =} ferror (@var{fid}, "clear")
2791 Query the error status of the stream specified by file descriptor @var{fid}.
2792 
2793 If an error condition exists then return a string @var{msg} describing the
2794 error. Otherwise, return an empty string @qcode{""}.
2795 
2796 The second input @qcode{"clear"} is optional. If supplied, the error
2797 state on the stream will be cleared.
2798 
2799 The optional second output is a numeric indication of the error status.
2800 @var{err} is 1 if an error condition has been encountered and 0 otherwise.
2801 
2802 Note that @code{ferror} indicates if an error has already occurred, not
2803 whether the next operation will result in an error condition.
2804 @seealso{fclear, fopen}
2805 @end deftypefn */)
2806 {
2807  int nargin = args.length ();
2808 
2809  if (nargin < 1 || nargin > 2)
2810  print_usage ();
2811 
2812  stream_list& streams = interp.get_stream_list ();
2813 
2814  stream os = streams.lookup (args(0), "ferror");
2815 
2816  bool clear = false;
2817 
2818  if (nargin == 2)
2819  {
2820  std::string opt = args(1).string_value ();
2821 
2822  clear = (opt == "clear");
2823  }
2824 
2825  int error_number = 0;
2826 
2827  std::string error_message = os.error (clear, error_number);
2828 
2829  return ovl (error_message, error_number);
2830 }
2831 
2832 DEFMETHODX ("popen", Fpopen, interp, args, ,
2833  doc: /* -*- texinfo -*-
2834 @deftypefn {} {@var{fid} =} popen (@var{command}, @var{mode})
2835 Start a process and create a pipe.
2836 
2837 The name of the command to run is given by @var{command}. The argument
2838 @var{mode} may be
2839 
2840 @table @asis
2841 @item @qcode{"r"}
2842 The pipe will be connected to the standard output of the process, and
2843 open for reading.
2844 
2845 @item @qcode{"w"}
2846 The pipe will be connected to the standard input of the process, and
2847 open for writing.
2848 @end table
2849 
2850 The file identifier corresponding to the input or output stream of the
2851 process is returned in @var{fid}.
2852 
2853 For example:
2854 
2855 @example
2856 @group
2857 fid = popen ("ls -ltr / | tail -3", "r");
2858 while (ischar (s = fgets (fid)))
2859  fputs (stdout, s);
2860 endwhile
2861 
2862  @print{} drwxr-xr-x 33 root root 3072 Feb 15 13:28 etc
2863  @print{} drwxr-xr-x 3 root root 1024 Feb 15 13:28 lib
2864  @print{} drwxrwxrwt 15 root root 2048 Feb 17 14:53 tmp
2865 @end group
2866 @end example
2867 @seealso{popen2}
2868 @end deftypefn */)
2869 {
2870  if (args.length () != 2)
2871  print_usage ();
2872 
2873  std::string name = args(0).xstring_value ("popen: COMMAND must be a string");
2874  std::string mode = args(1).xstring_value ("popen: MODE must be a string");
2875 
2876  octave_value retval;
2877 
2878  stream_list& streams = interp.get_stream_list ();
2879 
2880  if (mode == "r")
2881  {
2882  stream ips = octave_iprocstream::create (name);
2883 
2884  retval = streams.insert (ips);
2885  }
2886  else if (mode == "w")
2887  {
2888  stream ops = octave_oprocstream::create (name);
2889 
2890  retval = streams.insert (ops);
2891  }
2892  else
2893  error ("popen: invalid MODE specified");
2894 
2895  return retval;
2896 }
2897 
2898 DEFMETHODX ("pclose", Fpclose, interp, args, ,
2899  doc: /* -*- texinfo -*-
2900 @deftypefn {} {@var{status} =} pclose (@var{fid})
2901 Close a file identifier @var{fid} that was opened by @code{popen}.
2902 
2903 If successful, @code{fclose} returns 0, otherwise, it returns -1.
2904 
2905 Programming Note: The function @code{fclose} may also be used for the same
2906 purpose.
2907 @seealso{fclose, popen}
2908 @end deftypefn */)
2909 {
2910  if (args.length () != 1)
2911  print_usage ();
2912 
2913  stream_list& streams = interp.get_stream_list ();
2914 
2915  return ovl (streams.remove (args(0), "pclose"));
2916 }
2917 
2918 DEFUN (tempdir, args, ,
2919  doc: /* -*- texinfo -*-
2920 @deftypefn {} {@var{dir} =} tempdir ()
2921 Return the name of the host system's directory for temporary files.
2922 
2923 The directory name is taken first from the environment variable @env{TMPDIR}.
2924 If that does not exist, the environment variable @env{TMP} (and on Windows
2925 platforms also with higher priority the environment variable @env{TEMP}) is
2926 checked. If none of those are set, the system default returned by
2927 @code{P_tmpdir} is used.
2928 @seealso{P_tmpdir, tempname, mkstemp, tmpfile}
2929 @end deftypefn */)
2930 {
2931  if (args.length () > 0)
2932  print_usage ();
2933 
2934  std::string tmpdir = sys::env::get_temp_directory ();
2935 
2936  if (! sys::file_ops::is_dir_sep (tmpdir.back ()))
2937  tmpdir += sys::file_ops::dir_sep_str ();
2938 
2939  return ovl (tmpdir);
2940 }
2941 
2942 /*
2943 %!assert (ischar (tempdir ()))
2944 
2945 %!test
2946 %! old_wstate = warning ("off");
2947 %! old_tmpdir = getenv ("TMPDIR");
2948 %! unwind_protect
2949 %! setenv ("TMPDIR", "__MY_TMP_DIR__");
2950 %! assert (tempdir (), ["__MY_TMP_DIR__" filesep()]);
2951 %! unwind_protect_cleanup
2952 %! if (! isempty (old_tmpdir))
2953 %! setenv ("TMPDIR", old_tmpdir);
2954 %! else
2955 %! unsetenv ("TMPDIR");
2956 %! endif
2957 %! warning (old_wstate);
2958 %! end_unwind_protect
2959 */
2960 
2961 DEFUN (tempname, args, ,
2962  doc: /* -*- texinfo -*-
2963 @deftypefn {} {@var{fname} =} tempname ()
2964 @deftypefnx {} {@var{fname} =} tempname (@var{dir})
2965 @deftypefnx {} {@var{fname} =} tempname (@var{dir}, @var{prefix})
2966 Return a unique temporary filename as a string.
2967 
2968 If @var{prefix} is omitted, a value of @qcode{"oct-"} is used.
2969 
2970 If @var{dir} is also omitted, the default directory for temporary files
2971 (@code{P_tmpdir}) is used. If @var{dir} is provided, it must exist,
2972 otherwise the default directory for temporary files is used.
2973 
2974 Programming Note: Because the named file is not opened by @code{tempname},
2975 it is possible, though relatively unlikely, that it will not be available
2976 by the time your program attempts to open it. If this is a concern,
2977 @pxref{XREFtmpfile,,@code{tmpfile}}.
2978 @seealso{mkstemp, tempdir, P_tmpdir, tmpfile}
2979 @end deftypefn */)
2980 {
2981  int nargin = args.length ();
2982 
2983  if (nargin > 2)
2984  print_usage ();
2985 
2986  std::string dir;
2987 
2988  if (nargin > 0)
2989  dir = args(0).xstring_value ("tempname: DIR must be a string");
2990 
2991  std::string pfx ("oct-");
2992 
2993  if (nargin > 1)
2994  pfx = args(1).xstring_value ("tempname: PREFIX must be a string");
2995 
2996  return ovl (sys::tempnam (dir, pfx));
2997 }
2998 
2999 /*
3000 %!test
3001 %! envvar = {"TMPDIR", "TMP"};
3002 %! envdir = cellfun (@(x) getenv (x), envvar, "uniformoutput", false);
3003 %! unwind_protect
3004 %! cellfun (@(x) unsetenv (x), envvar);
3005 %! envname = "TMPDIR";
3006 %! def_tmpdir = P_tmpdir;
3007 %! ## Strip trailing file separators from P_tmpdir
3008 %! while (length (def_tmpdir) > 2 && any (def_tmpdir(end) == filesep ("all")))
3009 %! def_tmpdir(end) = [];
3010 %! endwhile
3011 %!
3012 %! ## Test 0-argument form
3013 %! fname = tempname ();
3014 %! [tmpdir, tmpfname] = fileparts (fname);
3015 %! assert (tmpdir, def_tmpdir);
3016 %! assert (tmpfname (1:4), "oct-");
3017 %! ## Test 1-argument form
3018 %! tmp_tmpdir = [def_tmpdir filesep() substr(tmpfname, -5)];
3019 %! mkdir (tmp_tmpdir) || error ("Unable to create tmp dir");
3020 %! setenv (envname, def_tmpdir);
3021 %! fname = tempname (tmp_tmpdir);
3022 %! [tmpdir, tmpfname] = fileparts (fname);
3023 %! assert (tmpdir, tmp_tmpdir);
3024 %! assert (tmpfname (1:4), "oct-");
3025 %! ## Test 1-argument form w/null tmpdir
3026 %! fname = tempname ("");
3027 %! [tmpdir, tmpfname] = fileparts (fname);
3028 %! assert (tmpdir, def_tmpdir);
3029 %! assert (tmpfname (1:4), "oct-");
3030 %! ## Test 2-argument form
3031 %! fname = tempname (tmp_tmpdir, "pfx-");
3032 %! [tmpdir, tmpfname] = fileparts (fname);
3033 %! assert (tmpdir, tmp_tmpdir);
3034 %! assert (tmpfname (1:4), "pfx-");
3035 %! ## Test 2-argument form w/null prefix
3036 %! fname = tempname (tmp_tmpdir, "");
3037 %! [tmpdir, tmpfname] = fileparts (fname);
3038 %! assert (tmpdir, tmp_tmpdir);
3039 %! assert (tmpfname (1:4), "file");
3040 %! unwind_protect_cleanup
3041 %! sts = rmdir (tmp_tmpdir);
3042 %! for i = 1:numel (envvar)
3043 %! if (isempty (envdir{i}))
3044 %! unsetenv (envvar{i});
3045 %! else
3046 %! setenv (envvar{i}, envdir{i});
3047 %! endif
3048 %! endfor
3049 %! end_unwind_protect
3050 */
3051 
3052 DEFMETHOD (tmpfile, interp, args, ,
3053  doc: /* -*- texinfo -*-
3054 @deftypefn {} {[@var{fid}, @var{msg}] =} tmpfile ()
3055 Return the file ID corresponding to a new temporary file with a unique
3056 name.
3057 
3058 The file is opened in binary read/write (@qcode{"w+b"}) mode and will be
3059 deleted automatically when it is closed or when Octave exits.
3060 
3061 If successful, @var{fid} is a valid file ID and @var{msg} is an empty
3062 string. Otherwise, @var{fid} is -1 and @var{msg} contains a
3063 system-dependent error message.
3064 @seealso{tempname, mkstemp, tempdir, P_tmpdir}
3065 @end deftypefn */)
3066 {
3067  if (args.length () != 0)
3068  print_usage ();
3069 
3070  octave_value_list retval;
3071 
3072  std::string tmpfile (sys::tempnam (sys::env::get_temp_directory (), "oct-"));
3073 
3074  FILE *fid = sys::fopen_tmp (tmpfile, "w+b");
3075 
3076  if (fid)
3077  {
3078  std::ios::openmode md = fopen_mode_to_ios_mode ("w+b");
3079 
3080  stream s = stdiostream::create (tmpfile, fid, md);
3081 
3082  if (! s)
3083  {
3084  fclose (fid);
3085 
3086  error ("tmpfile: failed to create stdiostream object");
3087  }
3088 
3089  stream_list& streams = interp.get_stream_list ();
3090 
3091  retval = ovl (streams.insert (s), "");
3092  }
3093  else
3094  retval = ovl (-1, std::strerror (errno));
3095 
3096  return retval;
3097 }
3098 
3099 DEFMETHOD (mkstemp, interp, args, ,
3100  doc: /* -*- texinfo -*-
3101 @deftypefn {} {[@var{fid}, @var{name}, @var{msg}] =} mkstemp ("@var{template}")
3102 @deftypefnx {} {[@var{fid}, @var{name}, @var{msg}] =} mkstemp ("@var{template}", @var{delete})
3103 Return the file descriptor @var{fid} corresponding to a new temporary file
3104 with a unique name created from @var{template}.
3105 
3106 The last six characters of @var{template} must be @qcode{"XXXXXX"} and
3107 these are replaced with a string that makes the filename unique. The file
3108 is then created with mode read/write and permissions that are system
3109 dependent (on GNU/Linux systems, the permissions will be 0600 for versions
3110 of glibc 2.0.7 and later). The file is opened in binary mode and with the
3111 @w{@code{O_EXCL}}@ flag.
3112 
3113 If the optional argument @var{delete} is supplied and is true, the file will
3114 be deleted automatically when Octave exits.
3115 
3116 If successful, @var{fid} is a valid file ID, @var{name} is the name of the
3117 file, and @var{msg} is an empty string. Otherwise, @var{fid} is -1,
3118 @var{name} is empty, and @var{msg} contains a system-dependent error
3119 message.
3120 @seealso{tempname, tempdir, P_tmpdir, tmpfile, fopen}
3121 @end deftypefn */)
3122 {
3123  int nargin = args.length ();
3124 
3125  if (nargin < 1 || nargin > 2)
3126  print_usage ();
3127 
3128  std::string tmpl8 = args(0).xstring_value ("mkstemp: TEMPLATE argument must be a string");
3129 
3130  octave_value_list retval = ovl (-1, "", "");
3131 
3132  OCTAVE_LOCAL_BUFFER (char, tmp, tmpl8.size () + 1);
3133  strcpy (tmp, tmpl8.c_str ());
3134 
3135  int fd = octave_mkostemp_wrapper (tmp);
3136 
3137  if (fd < 0)
3138  {
3139  retval(0) = fd;
3140  retval(2) = std::strerror (errno);
3141  }
3142  else
3143  {
3144  const char *fopen_mode = "w+b";
3145 
3146  FILE *fid = fdopen (fd, fopen_mode);
3147 
3148  if (! fid)
3149  {
3150  retval(0) = -1;
3151  retval(2) = std::strerror (errno);
3152  }
3153  else
3154  {
3155  std::string nm = tmp;
3156 
3157  std::ios::openmode md = fopen_mode_to_ios_mode (fopen_mode);
3158 
3159  stream s = stdiostream::create (nm, fid, md);
3160 
3161  if (! s)
3162  error ("mkstemp: failed to create stdiostream object");
3163 
3164  stream_list& streams = interp.get_stream_list ();
3165 
3166  retval(0) = streams.insert (s);
3167  retval(1) = nm;
3168 
3169  if (nargin == 2 && args(1).is_true ())
3170  interp.mark_for_deletion (nm);
3171  }
3172  }
3173 
3174  return retval;
3175 }
3176 
3177 // FIXME: This routine also exists verbatim in syscalls.cc.
3178 // Maybe change to be a general utility routine.
3179 static int
3180 convert (int x, int ibase, int obase)
3181 {
3182  int retval = 0;
3183 
3184  int tmp = x % obase;
3185 
3186  if (tmp > ibase - 1)
3187  error ("umask: invalid digit");
3188 
3189  retval = tmp;
3190  int mult = ibase;
3191  while ((x = (x - tmp) / obase))
3192  {
3193  tmp = x % obase;
3194 
3195  if (tmp > ibase - 1)
3196  error ("umask: invalid digit");
3197 
3198  retval += mult * tmp;
3199  mult *= ibase;
3200  }
3201 
3202  return retval;
3203 }
3204 
3205 DEFUNX ("umask", Fumask, args, ,
3206  doc: /* -*- texinfo -*-
3207 @deftypefn {} {@var{oldmask} =} umask (@var{mask})
3208 Set the permission mask for file creation.
3209 
3210 The parameter @var{mask} is an integer, interpreted as an octal number.
3211 
3212 If successful, returns the previous value of the mask (as an integer to be
3213 interpreted as an octal number); otherwise an error message is printed.
3214 
3215 The permission mask is a UNIX concept used when creating new objects on a
3216 file system such as files, directories, or named FIFOs. The object to be
3217 created has base permissions in an octal number @var{mode} which are
3218 modified according to the octal value of @var{mask}. The final permissions
3219 for the new object are @code{@var{mode} - @var{mask}}.
3220 @seealso{fopen, mkdir, mkfifo}
3221 @end deftypefn */)
3222 {
3223  if (args.length () != 1)
3224  print_usage ();
3225 
3226  int mask = args(0).xint_value ("umask: MASK must be an integer");
3227 
3228  if (mask < 0)
3229  error ("umask: MASK must be a positive integer value");
3230 
3231  int oct_mask = convert (mask, 8, 10);
3232 
3233  int status = convert (sys::umask (oct_mask), 10, 8);
3234 
3235  if (status >= 0)
3236  return ovl (status);
3237  else
3238  return ovl ();
3239 }
3240 
3241 static octave_value
3242 const_value (const char *, const octave_value_list& args, int val)
3243 {
3244  if (args.length () != 0)
3245  print_usage ();
3246 
3247  return octave_value (val);
3248 }
3249 
3250 DEFUNX ("P_tmpdir", FP_tmpdir, args, ,
3251  doc: /* -*- texinfo -*-
3252 @deftypefn {} {@var{sys_tmpdir} =} P_tmpdir ()
3253 Return the name of the host system's @strong{default} directory for
3254 temporary files.
3255 
3256 Programming Note: The value returned by @code{P_tmpdir} is always the
3257 default location. This value may not agree with that returned from
3258 @code{tempdir} if the user has overridden the default with the @env{TMPDIR}
3259 environment variable.
3260 @seealso{tempdir, tempname, mkstemp, tmpfile}
3261 @end deftypefn */)
3262 {
3263  if (args.length () != 0)
3264  print_usage ();
3265 
3266  return ovl (get_P_tmpdir ());
3267 }
3268 
3269 // NOTE: the values of SEEK_SET, SEEK_CUR, and SEEK_END have to be
3270 // this way for Matlab compatibility.
3271 
3272 DEFUNX ("SEEK_SET", FSEEK_SET, args, ,
3273  doc: /* -*- texinfo -*-
3274 @deftypefn {} {@var{fseek_origin} =} SEEK_SET ()
3275 Return the numerical value to pass to @code{fseek} to position the file pointer
3276 relative to the beginning of the file.
3277 @seealso{SEEK_CUR, SEEK_END, fseek}
3278 @end deftypefn */)
3279 {
3280  return const_value ("SEEK_SET", args, -1);
3281 }
3282 
3283 DEFUNX ("SEEK_CUR", FSEEK_CUR, args, ,
3284  doc: /* -*- texinfo -*-
3285 @deftypefn {} {@var{fseek_origin} =} SEEK_CUR ()
3286 Return the numerical value to pass to @code{fseek} to position the file pointer
3287 relative to the current position.
3288 @seealso{SEEK_SET, SEEK_END, fseek}
3289 @end deftypefn */)
3290 {
3291  return const_value ("SEEK_CUR", args, 0);
3292 }
3293 
3294 DEFUNX ("SEEK_END", FSEEK_END, args, ,
3295  doc: /* -*- texinfo -*-
3296 @deftypefn {} {@var{fseek_origin} =} SEEK_END ()
3297 Return the numerical value to pass to @code{fseek} to position the file pointer
3298 relative to the end of the file.
3299 @seealso{SEEK_SET, SEEK_CUR, fseek}
3300 @end deftypefn */)
3301 {
3302  return const_value ("SEEK_END", args, 1);
3303 }
3304 
3305 static octave_value
3306 const_value (const char *, const octave_value_list& args,
3307  const octave_value& val)
3308 {
3309  if (args.length () != 0)
3310  print_usage ();
3311 
3312  return octave_value (val);
3313 }
3314 
3315 DEFMETHODX ("stdin", Fstdin, interp, args, ,
3316  doc: /* -*- texinfo -*-
3317 @deftypefn {} {@var{fid} =} stdin ()
3318 Return the numeric value corresponding to the standard input stream.
3319 
3320 When Octave is used interactively, stdin is filtered through the command
3321 line editing functions.
3322 @seealso{stdout, stderr}
3323 @end deftypefn */)
3324 {
3325  stream_list& streams = interp.get_stream_list ();
3326 
3327  return const_value ("stdin", args, streams.stdin_file ());
3328 }
3329 
3330 DEFMETHODX ("stdout", Fstdout, interp, args, ,
3331  doc: /* -*- texinfo -*-
3332 @deftypefn {} {@var{fid} =} stdout ()
3333 Return the numeric value corresponding to the standard output stream.
3334 
3335 Data written to the standard output may be filtered through the pager.
3336 @seealso{stdin, stderr, page_screen_output}
3337 @end deftypefn */)
3338 {
3339  stream_list& streams = interp.get_stream_list ();
3340 
3341  return const_value ("stdout", args, streams.stdout_file ());
3342 }
3343 
3344 DEFMETHODX ("stderr", Fstderr, interp, args, ,
3345  doc: /* -*- texinfo -*-
3346 @deftypefn {} {@var{fid} =} stderr ()
3347 Return the numeric value corresponding to the standard error stream.
3348 
3349 Even if paging is turned on, the standard error is not sent to the pager.
3350 It is useful for error messages and prompts.
3351 @seealso{stdin, stdout}
3352 @end deftypefn */)
3353 {
3354  stream_list& streams = interp.get_stream_list ();
3355 
3356  return const_value ("stderr", args, streams.stderr_file ());
3357 }
3358 
3359 OCTAVE_END_NAMESPACE(octave)
octave_value_list Fstdin(octave::interpreter &, const octave_value_list &=octave_value_list(), int=0)
octave_value_list FP_tmpdir(const octave_value_list &=octave_value_list(), int=0)
octave_value_list Fpclose(octave::interpreter &, const octave_value_list &=octave_value_list(), int=0)
octave_value_list Fumask(const octave_value_list &=octave_value_list(), int=0)
octave_value_list FSEEK_END(const octave_value_list &=octave_value_list(), int=0)
octave_value_list Fstderr(octave::interpreter &, const octave_value_list &=octave_value_list(), int=0)
octave_value_list Ffeof(octave::interpreter &, const octave_value_list &=octave_value_list(), int=0)
octave_value_list Fpopen(octave::interpreter &, const octave_value_list &=octave_value_list(), int=0)
octave_value_list Fferror(octave::interpreter &, const octave_value_list &=octave_value_list(), int=0)
octave_value_list FSEEK_SET(const octave_value_list &=octave_value_list(), int=0)
octave_value_list Fstdout(octave::interpreter &, const octave_value_list &=octave_value_list(), int=0)
octave_value_list FSEEK_CUR(const octave_value_list &=octave_value_list(), int=0)
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
void mark_for_deletion(const std::string &file)
stream_list & get_stream_list()
static stream create(const char *data, std::ios::openmode arg_md=std::ios::out, mach_info::float_format ff=mach_info::native_float_format(), const std::string &encoding="utf-8")
Definition: oct-strstrm.cc:57
static data_type string_to_data_type(const std::string &s)
Definition: data-conv.cc:293
static octave::stream create(const std::string &n, std::ios::openmode arg_md=std::ios::in, octave::mach_info::float_format flt_fmt=octave::mach_info::native_float_format(), const std::string &encoding="utf-8")
Definition: oct-prcstrm.cc:38
static octave::stream create(const std::string &n, std::ios::openmode arg_md=std::ios::out, octave::mach_info::float_format flt_fmt=octave::mach_info::native_float_format(), const std::string &encoding="utf-8")
Definition: oct-prcstrm.cc:59
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: ovl.h:117
octave_value_list splice(octave_idx_type offset, octave_idx_type len, const octave_value_list &lst=octave_value_list()) const
Definition: ovl.cc:139
octave_idx_type length() const
Definition: ovl.h:113
octave_value_list & prepend(const octave_value &val)
Definition: ovl.cc:80
int int_value(bool req_int=false, bool frc_str_conv=false) const
Definition: ov.h:812
bool is_sq_string() const
Definition: ov.h:640
bool is_string() const
Definition: ov.h:637
Matrix size()
Definition: ov.h:462
octave_value reshape(const dim_vector &dv) const
Definition: ov.h:571
octave_idx_type numel() const
Definition: ov.h:559
std::string string_value(bool force=false) const
Definition: ov.h:974
std::string xstring_value(const char *fmt,...) const
Array< double > xvector_value(const char *fmt,...) const
std::string str()
Definition: oct-strstrm.h:167
Definition: oct-rand.h:45
static stream create(const std::string &n, FILE *f=nullptr, std::ios::openmode m=std::ios::in|std::ios::out, mach_info::float_format ff=mach_info::native_float_format(), const std::string &encoding="utf-8", c_file_ptr_buf::close_fcn cf=c_file_ptr_buf::file_close)
Definition: oct-stdstrm.h:137
octave_value stdin_file() const
Definition: oct-stream.cc:7717
int insert(stream &os)
Definition: oct-stream.cc:7413
int get_file_number(const octave_value &fid) const
Definition: oct-stream.cc:7676
std::string list_open_files() const
Definition: oct-stream.cc:7624
octave_value stdout_file() const
Definition: oct-stream.cc:7723
stream lookup(int fid, const std::string &who="") const
Definition: oct-stream.cc:7454
octave_value open_file_numbers() const
Definition: oct-stream.cc:7657
string_vector get_info(int fid) const
Definition: oct-stream.cc:7575
int remove(int fid, const std::string &who="")
Definition: oct-stream.cc:7487
octave_value stderr_file() const
Definition: oct-stream.cc:7729
off_t tell()
Definition: oct-stream.cc:6367
int flush()
Definition: oct-stream.cc:6127
bool is_valid() const
Definition: oct-stream.h:429
octave_value scanf(const std::string &fmt, const Array< double > &size, octave_idx_type &count, const std::string &who)
Definition: oct-stream.cc:7144
std::string gets(octave_idx_type max_len, bool &err, const std::string &who)
Definition: oct-stream.cc:6173
int rewind()
Definition: oct-stream.cc:6378
void clearerr()
Definition: oct-stream.h:464
off_t skipl(off_t count, bool &err, const std::string &who)
Definition: oct-stream.cc:6208
octave_value textscan(const std::string &fmt, octave_idx_type ntimes, const octave_value_list &options, const std::string &who, octave_idx_type &count)
Definition: oct-stream.cc:7214
bool eof() const
Definition: oct-stream.cc:7292
int puts(const std::string &s, const std::string &who)
Definition: oct-stream.cc:7260
int printf(const std::string &fmt, const octave_value_list &args, const std::string &who)
Definition: oct-stream.cc:7224
int seek(off_t offset, int origin)
Definition: oct-stream.cc:6250
octave_value_list oscanf(const std::string &fmt, const std::string &who)
Definition: oct-stream.cc:7180
std::string getl(octave_idx_type max_len, bool &err, const std::string &who)
Definition: oct-stream.cc:6138
std::string error(bool clear, int &err_num)
octave_value read(const Array< double > &size, octave_idx_type block_size, oct_data_conv::data_type input_type, oct_data_conv::data_type output_type, octave_idx_type skip, mach_info::float_format flt_fmt, octave_idx_type &count)
Definition: oct-stream.cc:6609
octave_idx_type write(const octave_value &data, octave_idx_type block_size, oct_data_conv::data_type output_type, octave_idx_type skip, mach_info::float_format flt_fmt)
Definition: oct-stream.cc:6802
static stream create(const std::string &n, gzFile f=nullptr, int fid=0, std::ios::openmode m=std::ios::in|std::ios::out, mach_info::float_format ff=mach_info::native_float_format(), const std::string &encoding="utf-8", c_zfile_ptr_buf::close_fcn cf=c_zfile_ptr_buf::file_close)
Definition: oct-stdstrm.h:170
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage(void)
Definition: defun-int.h:72
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:111
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
#define DEFUNX(name, fname, args_name, nargout_name, doc)
Macro to define a builtin function with certain internal name.
Definition: defun.h:85
void warning(const char *fmt,...)
Definition: error.cc:1063
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1078
void() error(const char *fmt,...)
Definition: error.cc:988
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:53
bool is_dir_sep(char c)
int umask(mode_t)
std::string dir_sep_str()
ColumnVector transform(const Matrix &m, double x, double y, double z)
Definition: graphics.cc:5468
int octave_iconv_close_wrapper(void *cd)
void * octave_iconv_open_wrapper(const char *tocode, const char *fromcode)
double lo_ieee_inf_value()
Definition: lo-ieee.cc:68
F77_RET_T const F77_INT F77_CMPLX * A
std::complex< T > trunc(const std::complex< T > &x)
Definition: lo-mappers.h:111
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T const F77_DBLE * x
F77_RET_T const F77_DBLE const F77_DBLE * f
FloatComplex(* fptr)(const FloatComplex &, float, int, octave_idx_type &)
Definition: lo-specfun.cc:1102
bool dir_exists(const std::string &dirname)
Definition: lo-sysdep.cc:389
std::FILE * fopen(const std::string &filename, const std::string &mode)
Definition: lo-sysdep.cc:511
std::FILE * fopen_tmp(const std::string &name, const std::string &mode)
Definition: lo-sysdep.cc:583
std::string fgetl(FILE *f)
Definition: lo-utils.cc:172
std::string fgets(FILE *f)
Definition: lo-utils.cc:90
const char * octave_locale_charset_wrapper(void)
float_format string_to_float_format(const std::string &s)
Definition: mach-info.cc:91
float_format
Definition: mach-info.h:38
bool is_true(const std::string &s)
Definition: mkoctfile.cc:604
int octave_mkostemp_wrapper(char *tmpl)
std::string tilde_expand(const std::string &name)
Definition: file-ops.cc:289
std::string tempnam(const std::string &dir, const std::string &pfx)
Definition: file-ops.cc:749
int unlink(const std::string &name)
Definition: file-ops.cc:727
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219
#define octave_stdout
Definition: pager.h:309
void flush_stdout()
DEFMETHODX("quad", Fquad, interp, args,, doc:)
Definition: quad.cc:136
std::string get_P_tmpdir()
std::string find_data_file_in_load_path(const std::string &fcn, const std::string &file, bool require_regular_file=false)
std::string do_string_escapes(const std::string &s)