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