changelog shortlog tags changeset files revisions annotate raw

src/file-io.cc

changeset 9846: 1d90fc211872
parent:5f24df61667a
author: John W. Eaton <jwe@octave.org>
date: Sat Nov 21 21:44:51 2009 -0500 (6 hours ago)
permissions: -rw-r--r--
description: configure.ac: report freetype, fontconfig, and fltk cflags and libs info
1/*
2
3Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
4 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 John W. Eaton
5
6This file is part of Octave.
7
8Octave is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13Octave is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with Octave; see the file COPYING. If not, see
20<http://www.gnu.org/licenses/>.
21
22*/
23
24// Originally written by John C. Campbell <jcc@bevo.che.wisc.edu>
25//
26// Thomas Baier <baier@ci.tuwien.ac.at> added the original versions of
27// the following functions:
28//
29// popen
30// pclose
31// execute (now popen2.m)
32// sync_system (now merged with system)
33// async_system (now merged with system)
34
35// Extensively revised by John W. Eaton <jwe@octave.org>,
36// April 1996.
37
38#ifdef HAVE_CONFIG_H
39#include <config.h>
40#endif
41
42#include <cerrno>
43#include <climits>
44#include <cstdio>
45
46#include <iostream>
47#include <stack>
48#include <vector>
49
50#ifdef HAVE_UNISTD_H
51#ifdef HAVE_SYS_TYPES_H
52#include <sys/types.h>
53#endif
54#include <unistd.h>
55#endif
56
57#ifdef HAVE_ZLIB_H
58#include <zlib.h>
59#endif
60
61#include "error.h"
62#include "file-ops.h"
63#include "file-stat.h"
64#include "lo-ieee.h"
65#include "oct-env.h"
66#include "oct-locbuf.h"
67
68#include "defun.h"
69#include "file-io.h"
70#include "load-path.h"
71#include "oct-fstrm.h"
72#include "oct-iostrm.h"
73#include "oct-map.h"
74#include "oct-obj.h"
75#include "oct-prcstrm.h"
76#include "oct-stream.h"
77#include "oct-strstrm.h"
78#include "pager.h"
79#include "sysdep.h"
80#include "utils.h"
81#include "variables.h"
82
83static octave_value stdin_file;
84static octave_value stdout_file;
85static octave_value stderr_file;
86
87static octave_stream stdin_stream;
88static octave_stream stdout_stream;
89static octave_stream stderr_stream;
90
91void
92initialize_file_io (void)
93{
94 stdin_stream = octave_istream::create (&std::cin, "stdin");
95
96 // This uses octave_stdout (see pager.h), not std::cout so that Octave's
97 // standard output stream will pass through the pager.
98
99 stdout_stream = octave_ostream::create (&octave_stdout, "stdout");
100
101 stderr_stream = octave_ostream::create (&std::cerr, "stderr");
102
103 stdin_file = octave_stream_list::insert (stdin_stream);
104 stdout_file = octave_stream_list::insert (stdout_stream);
105 stderr_file = octave_stream_list::insert (stderr_stream);
106}
107
108void
109close_files (void)
110{
111 octave_stream_list::clear ();
112}
113
114// List of files to delete when we exit or crash.
115//
116// FIXME -- this should really be static, but that causes
117// problems on some systems.
118std::stack <std::string> tmp_files;
119
120void
121mark_for_deletion (const std::string& file)
122{
123 tmp_files.push (file);
124}
125
126void
127cleanup_tmp_files (void)
128{
129 while (! tmp_files.empty ())
130 {
131 std::string filename = tmp_files.top ();
132 tmp_files.pop ();
133 unlink (filename.c_str ());
134 }
135}
136
137static std::ios::openmode
138fopen_mode_to_ios_mode (const std::string& mode_arg)
139{
140 std::ios::openmode retval = std::ios::in;
141
142 if (! mode_arg.empty ())
143 {
144 // Could probably be faster, but does it really matter?
145
146 std::string mode = mode_arg;
147
148 // 'W' and 'R' are accepted as 'w' and 'r', but we warn about
149 // them because Matlab says they perform "automatic flushing"
150 // but we don't know precisely what action that implies.
151
152 size_t pos = mode.find ('W');
153
154 if (pos != std::string::npos)
155 {
156 warning ("fopen: treating mode \"W\" as equivalent to \"w\"");
157 mode[pos] = 'w';
158 }
159
160 pos = mode.find ('R');
161
162 if (pos != std::string::npos)
163 {
164 warning ("fopen: treating mode \"R\" as equivalent to \"r\"");
165 mode[pos] = 'r';
166 }
167
168 pos = mode.find ('z');
169
170 if (pos != std::string::npos)
171 {
172#if defined (HAVE_ZLIB)
173 mode.erase (pos, 1);
174#else
175 error ("this version of Octave does not support gzipped files");
176#endif
177 }
178
179 if (! error_state)
180 {
181 if (mode == "rt")
182 retval = std::ios::in;
183 else if (mode == "wt")
184 retval = std::ios::out | std::ios::trunc;
185 else if (mode == "at")
186 retval = std::ios::out | std::ios::app;
187 else if (mode == "r+t")
188 retval = std::ios::in | std::ios::out;
189 else if (mode == "w+t")
190 retval = std::ios::in | std::ios::out | std::ios::trunc;
191 else if (mode == "a+t")
192 retval = std::ios::in | std::ios::out | std::ios::app;
193 else if (mode == "rb" || mode == "r")
194 retval = std::ios::in | std::ios::binary;
195 else if (mode == "wb" || mode == "w")
196 retval = std::ios::out | std::ios::trunc | std::ios::binary;
197 else if (mode == "ab" || mode == "a")
198 retval = std::ios::out | std::ios::app | std::ios::binary;
199 else if (mode == "r+b" || mode == "r+")
200 retval = std::ios::in | std::ios::out | std::ios::binary;
201 else if (mode == "w+b" || mode == "w+")
202 retval = (std::ios::in | std::ios::out | std::ios::trunc
203 | std::ios::binary);
204 else if (mode == "a+b" || mode == "a+")
205 retval = (std::ios::in | std::ios::out | std::ios::app
206 | std::ios::binary);
207 else
208 ::error ("invalid mode specified");
209 }
210 }
211
212 return retval;
213}
214
215DEFUN (fclose, args, ,
216 "-*- texinfo -*-\n\
217@deftypefn {Built-in Function} {} fclose (@var{fid})\n\
218Closes the specified file. If successful, @code{fclose} returns 0,\n\
219otherwise, it returns -1.\n\
220@seealso{fopen, fseek, ftell}\n\
221@end deftypefn")
222{
223 octave_value retval = -1;
224
225 int nargin = args.length ();
226
227 if (nargin == 1)
228 retval = octave_stream_list::remove (args(0), "fclose");
229 else
230 print_usage ();
231
232 return retval;
233}
234
235DEFUN (fclear, args, ,
236 "-*- texinfo -*-\n\
237@deftypefn {Built-in Function} {} fclear (@var{fid})\n\
238Clear the stream state for the specified file.\n\
239@end deftypefn")
240{
241 octave_value retval;
242
243 int nargin = args.length ();
244
245 if (nargin == 1)
246 {
247 int fid = octave_stream_list::get_file_number (args (0));
248
249 octave_stream os = octave_stream_list::lookup (fid, "fclear");
250
251 if (! error_state)
252 os.clearerr ();
253 }
254 else
255 print_usage ();
256
257 return retval;
258}
259
260DEFUN (fflush, args, ,
261 "-*- texinfo -*-\n\
262@deftypefn {Built-in Function} {} fflush (@var{fid})\n\
263Flush output to @var{fid}. This is useful for ensuring that all\n\
264pending output makes it to the screen before some other event occurs.\n\
265For example, it is always a good idea to flush the standard output\n\
266stream before calling @code{input}.\n\
267\n\
268@code{fflush} returns 0 on success and an OS dependent error value\n\
269(@minus{}1 on unix) on error.\n\
270@seealso{fopen, fclose}\n\
271@end deftypefn")
272{
273 octave_value retval = -1;
274
275 int nargin = args.length ();
276
277 if (nargin == 1)
278 {
279 // FIXME -- any way to avoid special case for stdout?
280
281 int fid = octave_stream_list::get_file_number (args (0));
282
283 if (fid == 1)
284 {
285 flush_octave_stdout ();
286
287 retval = 0;
288 }
289 else
290 {
291 octave_stream os = octave_stream_list::lookup (fid, "fflush");
292
293 if (! error_state)
294 retval = os.flush ();
295 }
296 }
297 else
298 print_usage ();
299
300 return retval;
301}
302
303DEFUN (fgetl, args, ,
304 "-*- texinfo -*-\n\
305@deftypefn {Built-in Function} {} fgetl (@var{fid}, @var{len})\n\
306Read characters from a file, stopping after a newline, or EOF,\n\
307or @var{len} characters have been read. The characters read, excluding\n\
308the possible trailing newline, are returned as a string.\n\
309\n\
310If @var{len} is omitted, @code{fgetl} reads until the next newline\n\
311character.\n\
312\n\
313If there are no more characters to read, @code{fgetl} returns @minus{}1.\n\
314@seealso{fread, fscanf}\n\
315@end deftypefn")
316{
317 static std::string who = "fgetl";
318
319 octave_value_list retval;
320
321 retval(1) = 0;
322 retval(0) = -1;
323
324 int nargin = args.length ();
325
326 if (nargin == 1 || nargin == 2)
327 {
328 octave_stream os = octave_stream_list::lookup (args(0), who);
329
330 if (! error_state)
331 {
332 octave_value len_arg = (nargin == 2) ? args(1) : octave_value ();
333
334 bool err = false;
335
336 std::string tmp = os.getl (len_arg, err, who);
337
338 if (! (error_state || err))
339 {
340 retval(1) = tmp.length ();
341 retval(0) = tmp;
342 }
343 }
344 }
345 else
346 print_usage ();
347
348 return retval;
349}
350
351DEFUN (fgets, args, ,
352 "-*- texinfo -*-\n\
353@deftypefn {Built-in Function} {} fgets (@var{fid}, @var{len})\n\
354Read characters from a file, stopping after a newline, or EOF,\n\
355or @var{len} characters have been read. The characters read, including\n\
356the possible trailing newline, are returned as a string.\n\
357\n\
358If @var{len} is omitted, @code{fgets} reads until the next newline\n\
359character.\n\
360\n\
361If there are no more characters to read, @code{fgets} returns @minus{}1.\n\
362@seealso{fputs, fopen, fread, fscanf}\n\
363@end deftypefn")
364{
365 static std::string who = "fgets";
366
367 octave_value_list retval;
368
369 retval(1) = 0.0;
370 retval(0) = -1.0;
371
372 int nargin = args.length ();
373
374 if (nargin == 1 || nargin == 2)
375 {
376 octave_stream os = octave_stream_list::lookup (args(0), who);
377
378 if (! error_state)
379 {
380 octave_value len_arg = (nargin == 2) ? args(1) : octave_value ();
381
382 bool err = false;
383
384 std::string tmp = os.gets (len_arg, err, who);
385
386 if (! (error_state || err))
387 {
388 retval(1) = tmp.length ();
389 retval(0) = tmp;
390 }
391 }
392 }
393 else
394 print_usage ();
395
396 return retval;
397}
398
399DEFUN (fskipl, args, ,
400 "-*- texinfo -*-\n\
401@deftypefn {Built-in Function} {} fskipl (@var{fid}, @var{count})\n\
402Skips a given number of lines, i.e., discards characters until an end-of-line\n\
403is met exactly @var{count}-times, or end-of-file occurs.\n\
404Returns the number of lines skipped (end-of-line sequences encountered).\n\
405If @var{count} is omitted, it defaults to 1. @var{count} may also be\n\
406@code{Inf}, in which case lines are skipped to the end of file.\n\
407This form is suitable for counting lines in a file.\n\
408@seealso{fgetl, fgets}\n\
409@end deftypefn")
410{
411 static std::string who = "fskipl";
412
413 octave_value retval;
414
415 int nargin = args.length ();
416
417 if (nargin == 1 || nargin == 2)
418 {
419 octave_stream os = octave_stream_list::lookup (args(0), who);
420
421 if (! error_state)
422 {
423 octave_value count_arg = (nargin == 2) ? args(1) : octave_value ();
424
425 bool err = false;
426
427 long tmp = os.skipl (count_arg, err, who);
428
429 if (! (error_state || err))
430 retval = tmp;
431 }
432 }
433 else
434 print_usage ();
435
436 return retval;
437}
438
439
440static octave_stream
441do_stream_open (const std::string& name, const std::string& mode,
442 const std::string& arch, int& fid)
443{
444 octave_stream retval;
445
446 fid = -1;
447
448 std::ios::openmode md = fopen_mode_to_ios_mode (mode);
449
450 if (! error_state)
451 {
452 oct_mach_info::float_format flt_fmt =
453 oct_mach_info::string_to_float_format (arch);
454
455 if (! error_state)
456 {
457 std::string fname = file_ops::tilde_expand (name);
458
459 file_stat fs (fname);
460
461 if (! (md & std::ios::out
462 || octave_env::absolute_pathname (fname)
463 || octave_env::rooted_relative_pathname (fname)))
464 {
465 if (! fs.exists ())
466 {
467 std::string tmp = octave_env::make_absolute
468 (load_path::find_file (fname), octave_env::getcwd ());
469
470 if (! tmp.empty ())
471 {
472 warning_with_id ("Octave:fopen-file-in-path",
473 "fopen: file found in load path");
474 fname = tmp;
475 }
476 }
477 }
478
479 if (! fs.is_dir ())
480 {
481 std::string tmode = mode;
482
483 // Use binary mode if 't' is not specified, but don't add
484 // 'b' if it is already present.
485
486 size_t bpos = tmode.find ('b');
487 size_t tpos = tmode.find ('t');
488
489 if (bpos == std::string::npos && tpos == std::string::npos)
490 tmode += 'b';
491
492#if defined (HAVE_ZLIB)
493 size_t pos = tmode.find ('z');
494
495 if (pos != std::string::npos)
496 {
497 tmode.erase (pos, 1);
498
499 gzFile fptr = ::gzopen (fname.c_str (), tmode.c_str ());
500
501 if (fptr)
502 retval = octave_zstdiostream::create (fname, fptr, md, flt_fmt);
503 else
504 {
505 using namespace std;
506 retval.error (::strerror (errno));
507 }
508 }
509 else
510#endif
511 {
512 FILE *fptr = ::fopen (fname.c_str (), tmode.c_str ());
513
514 retval = octave_stdiostream::create (fname, fptr, md, flt_fmt);
515
516 if (! fptr)
517 {
518 using namespace std;
519 retval.error (::strerror (errno));
520 }
521 }
522
523 }
524 }
525 }
526
527 return retval;
528}
529
530static octave_stream
531do_stream_open (const octave_value& tc_name, const octave_value& tc_mode,
532 const octave_value& tc_arch, const char *fcn, int& fid)
533{
534 octave_stream retval;
535
536 fid = -1;
537
538 std::string name = tc_name.string_value ();
539
540 if (! error_state)
541 {
542 std::string mode = tc_mode.string_value ();
543
544 if (! error_state)
545 {
546 std::string arch = tc_arch.string_value ();
547
548 if (! error_state)
549 retval = do_stream_open (name, mode, arch, fid);
550 else
551 ::error ("%s: architecture type must be a string", fcn);
552 }
553 else
554 ::error ("%s: file mode must be a string", fcn);
555 }
556 else
557 ::error ("%s: file name must be a string", fcn);
558
559 return retval;
560}
561
562DEFUN (fopen, args, ,
563 "-*- texinfo -*-\n\
564@deftypefn {Built-in Function} {[@var{fid}, @var{msg}] =} fopen (@var{name}, @var{mode}, @var{arch})\n\
565@deftypefnx {Built-in Function} {@var{fid_list} =} fopen (\"all\")\n\
566@deftypefnx {Built-in Function} {[@var{file}, @var{mode}, @var{arch}] =} fopen (@var{fid})\n\
567The first form of the @code{fopen} function opens the named file with\n\
568the specified mode (read-write, read-only, etc.) and architecture\n\
569interpretation (IEEE big endian, IEEE little endian, etc.), and returns\n\
570an integer value that may be used to refer to the file later. If an\n\
571error occurs, @var{fid} is set to @minus{}1 and @var{msg} contains the\n\
572corresponding system error message. The @var{mode} is a one or two\n\
573character string that specifies whether the file is to be opened for\n\
574reading, writing, or both.\n\
575\n\
576The second form of the @code{fopen} function returns a vector of file ids\n\
577corresponding to all the currently open files, excluding the\n\
578@code{stdin}, @code{stdout}, and @code{stderr} streams.\n\
579\n\
580The third form of the @code{fopen} function returns information about the\n\
581open file given its file id.\n\
582\n\
583For example,\n\
584\n\
585@example\n\
586myfile = fopen (\"splat.dat\", \"r\", \"ieee-le\");\n\
587@end example\n\
588\n\
589@noindent\n\
590opens the file @file{splat.dat} for reading. If necessary, binary\n\
591numeric values will be read assuming they are stored in IEEE format with\n\
592the least significant bit first, and then converted to the native\n\
593representation.\n\
594\n\
595Opening a file that is already open simply opens it again and returns a\n\
596separate file id. It is not an error to open a file several times,\n\
597though writing to the same file through several different file ids may\n\
598produce unexpected results.\n\
599\n\
600The possible values @samp{mode} may have are\n\
601\n\
602@table @asis\n\
603@item @samp{r}\n\
604Open a file for reading.\n\
605\n\
606@item @samp{w}\n\
607Open a file for writing. The previous contents are discarded.\n\
608\n\
609@item @samp{a}\n\
610Open or create a file for writing at the end of the file.\n\
611\n\
612@item @samp{r+}\n\
613Open an existing file for reading and writing.\n\
614\n\
615@item @samp{w+}\n\
616Open a file for reading or writing. The previous contents are\n\
617discarded.\n\
618\n\
619@item @samp{a+}\n\
620Open or create a file for reading or writing at the end of the\n\
621file.\n\
622@end table\n\
623\n\
624Append a \"t\" to the mode string to open the file in text mode or a\n\
625\"b\" to open in binary mode. On Windows and Macintosh systems, text\n\
626mode reading and writing automatically converts linefeeds to the\n\
627appropriate line end character for the system (carriage-return linefeed\n\
628on Windows, carriage-return on Macintosh). The default if no mode is\n\
629specified is binary mode.\n\
630\n\
631Additionally, you may append a \"z\" to the mode string to open a\n\
632gzipped file for reading or writing. For this to be successful, you\n\
633must also open the file in binary mode.\n\
634\n\
635The parameter @var{arch} is a string specifying the default data format\n\
636for the file. Valid values for @var{arch} are:\n\
637\n\
638@table @asis\n\
639@samp{native}\n\
640The format of the current machine (this is the default).\n\
641\n\
642@samp{ieee-be}\n\
643IEEE big endian format.\n\
644\n\
645@samp{ieee-le}\n\
646IEEE little endian format.\n\
647\n\
648@samp{vaxd}\n\
649VAX D floating format.\n\
650\n\
651@samp{vaxg}\n\
652VAX G floating format.\n\
653\n\
654@samp{cray}\n\
655Cray floating format.\n\
656@end table\n\
657\n\
658@noindent\n\
659however, conversions are currently only supported for @samp{native}\n\
660@samp{ieee-be}, and @samp{ieee-le} formats.\n\
661@seealso{fclose, fgets, fputs, fread, fseek, ferror, fprintf, fscanf, ftell, fwrite}\n\
662@end deftypefn")
663{
664 octave_value_list retval;
665
666 retval(0) = -1.0;
667
668 int nargin = args.length ();
669
670 if (nargin == 1)
671 {
672 if (args(0).is_string ())
673 {
674 // If there is only one argument and it is a string but it
675 // is not the string "all", we assume it is a file to open
676 // with MODE = "r". To open a file called "all", you have
677 // to supply more than one argument.
678
679 if (args(0).string_value () == "all")
680 return octave_stream_list::open_file_numbers ();
681 }
682 else
683 {
684 string_vector tmp = octave_stream_list::get_info (args(0));
685
686 if (! error_state)
687 {
688 retval(2) = tmp(2);
689 retval(1) = tmp(1);
690 retval(0) = tmp(0);
691 }
692
693 return retval;
694 }
695 }
696
697 if (nargin > 0 && nargin < 4)
698 {
699 octave_value mode = (nargin == 2 || nargin == 3)
700 ? args(1) : octave_value ("r");
701
702 octave_value arch = (nargin == 3)
703 ? args(2) : octave_value ("native");
704
705 int fid = -1;
706
707 octave_stream os = do_stream_open (args(0), mode, arch, "fopen", fid);
708
709 if (os && ! error_state)
710 {
711 retval(1) = "";
712 retval(0) = octave_stream_list::insert (os);
713 }
714 else
715 {
716 int error_number = 0;
717
718 retval(1) = os.error (false, error_number);
719 retval(0) = -1.0;
720 }
721 }
722 else
723 print_usage ();
724
725 return retval;
726}
727
728DEFUN (freport, args, ,
729 "-*- texinfo -*-\n\
730@deftypefn {Built-in Function} {} freport ()\n\
731Print a list of which files have been opened, and whether they are open\n\
732for reading, writing, or both. For example,\n\
733\n\
734@example\n\
735@group\n\
736freport ()\n\
737\n\
738 @print{} number mode name\n\
739 @print{} \n\
740 @print{} 0 r stdin\n\
741 @print{} 1 w stdout\n\
742 @print{} 2 w stderr\n\
743 @print{} 3 r myfile\n\
744@end group\n\
745@end example\n\
746@end deftypefn")
747{
748 octave_value_list retval;
749
750 int nargin = args.length ();
751
752 if (nargin > 0)
753 warning ("freport: ignoring extra arguments");
754
755 octave_stdout << octave_stream_list::list_open_files ();
756
757 return retval;
758}
759
760DEFUN (frewind, args, nargout,
761 "-*- texinfo -*-\n\
762@deftypefn {Built-in Function} {} frewind (@var{fid})\n\
763Move the file pointer to the beginning of the file @var{fid}, returning\n\
7640 for success, and -1 if an error was encountered. It is equivalent to\n\
765@code{fseek (@var{fid}, 0, SEEK_SET)}.\n\
766@end deftypefn")
767{
768 octave_value retval;
769
770 int result = -1;
771
772 int nargin = args.length ();
773
774 if (nargin == 1)
775 {
776 octave_stream os = octave_stream_list::lookup (args(0), "frewind");
777
778 if (! error_state)
779 result = os.rewind ();
780 }
781 else
782 print_usage ();
783
784 if (nargout > 0)
785 retval = result;
786
787 return retval;
788}
789
790DEFUN (fseek, args, ,
791 "-*- texinfo -*-\n\
792@deftypefn {Built-in Function} {} fseek (@var{fid}, @var{offset}, @var{origin})\n\
793Set the file pointer to any location within the file @var{fid}.\n\
794\n\
795The pointer is positioned @var{offset} characters from the @var{origin},\n\
796which may be one of the predefined variables @w{@code{SEEK_CUR}} (current\n\
797position), @w{@code{SEEK_SET}} (beginning), or @w{@code{SEEK_END}} (end of\n\
798file) or strings \"cof\", \"bof\" or \"eof\". If @var{origin} is omitted,\n\
799@w{@code{SEEK_SET}} is assumed. The offset must be zero, or a value returned\n\
800by @code{ftell} (in which case @var{origin} must be @w{@code{SEEK_SET}}).\n\
801\n\
802Return 0 on success and -1 on error.\n\
803@seealso{ftell, fopen, fclose}\n\
804@end deftypefn")
805{
806 octave_value retval = -1;
807
808 int nargin = args.length ();
809
810 if (nargin == 2 || nargin == 3)
811 {
812 octave_stream os = octave_stream_list::lookup (args(0), "fseek");
813
814 if (! error_state)
815 {
816 octave_value origin_arg = (nargin == 3)
817 ? args(2) : octave_value (-1.0);
818
819 retval = os.seek (args(1), origin_arg);
820 }
821 }
822 else
823 print_usage ();
824
825 return retval;
826}
827
828DEFUN (ftell, args, ,
829 "-*- texinfo -*-\n\
830@deftypefn {Built-in Function} {} ftell (@var{fid})\n\
831Return the position of the file pointer as the number of characters\n\
832from the beginning of the file @var{fid}.\n\
833@seealso{fseek, fopen, fclose}\n\
834@end deftypefn")
835{
836 octave_value retval = -1;
837
838 int nargin = args.length ();
839
840 if (nargin == 1)
841 {
842 octave_stream os = octave_stream_list::lookup (args(0), "ftell");
843
844 if (! error_state)
845 retval = os.tell ();
846 }
847 else
848 print_usage ();
849
850 return retval;
851}
852
853DEFUN (fprintf, args, nargout,
854 "-*- texinfo -*-\n\
855@deftypefn {Built-in Function} {} fprintf (@var{fid}, @var{template}, @dots{})\n\
856This function is just like @code{printf}, except that the output is\n\
857written to the stream @var{fid} instead of @code{stdout}.\n\
858If @var{fid} is omitted, the output is written to @code{stdout}.\n\
859@seealso{printf, sprintf, fread, fscanf, fopen, fclose}\n\
860@end deftypefn")
861{
862 static std::string who = "fprintf";
863
864 octave_value retval;
865
866 int result = -1;
867
868 int nargin = args.length ();
869
870 if (nargin > 1 || (nargin > 0 && args(0).is_string ()))
871 {
872 octave_stream os;
873 int fmt_n = 0;
874
875 if (args(0).is_string ())
876 {
877 os = octave_stream_list::lookup (1, who);
878 }
879 else
880 {
881 fmt_n = 1;
882 os = octave_stream_list::lookup (args(0), who);
883 }
884
885 if (! error_state)
886 {
887 if (args(fmt_n).is_string ())
888 {
889 octave_value_list tmp_args;
890
891 if (nargin > 1 + fmt_n)
892 {
893 tmp_args.resize (nargin-fmt_n-1, octave_value ());
894
895 for (int i = fmt_n + 1; i < nargin; i++)
896 tmp_args(i-fmt_n-1) = args(i);
897 }
898
899 result = os.printf (args(fmt_n), tmp_args, who);
900 }
901 else
902 ::error ("%s: format must be a string", who.c_str ());
903 }
904 }
905 else
906 print_usage ();
907
908 if (nargout > 0)
909 retval = result;
910
911 return retval;
912}
913
914DEFUN (printf, args, nargout,
915 "-*- texinfo -*-\n\
916@deftypefn {Built-in Function} {} printf (@var{template}, @dots{})\n\
917Print optional arguments under the control of the template string\n\
918@var{template} to the stream @code{stdout} and return the number of\n\
919characters printed.\n\
920@ifclear OCTAVE_MANUAL\n\
921\n\
922See the Formatted Output section of the GNU Octave manual for a\n\
923complete description of the syntax of the template string.\n\
924@end ifclear\n\
925@seealso{fprintf, sprintf, scanf}\n\
926@end deftypefn")
927{
928 static std::string who = "printf";
929
930 octave_value retval;
931
932 int result = -1;
933
934 int nargin = args.length ();
935
936 if (nargin > 0)
937 {
938 if (args(0).is_string ())
939 {
940 octave_value_list tmp_args;
941
942 if (nargin > 1)
943 {
944 tmp_args.resize (nargin-1, octave_value ());
945
946 for (int i = 1; i < nargin; i++)
947 tmp_args(i-1) = args(i);
948 }
949
950 result = stdout_stream.printf (args(0), tmp_args, who);
951 }
952 else
953 ::error ("%s: format must be a string", who.c_str ());
954 }
955 else
956 print_usage ();
957
958 if (nargout > 0)
959 retval = result;
960
961 return retval;
962}
963
964DEFUN (fputs, args, ,
965 "-*- texinfo -*-\n\
966@deftypefn {Built-in Function} {} fputs (@var{fid}, @var{string})\n\
967Write a string to a file with no formatting.\n\
968\n\
969Return a non-negative number on success and EOF on error.\n\
970@seealso{scanf, sscanf, fread, fprintf, fgets, fscanf}\n\
971@end deftypefn")
972{
973 static std::string who = "fputs";
974
975 octave_value retval = -1;
976
977 int nargin = args.length ();
978
979 if (nargin == 2)
980 {
981 octave_stream os = octave_stream_list::lookup (args(0), who);
982
983 if (! error_state)
984 retval = os.puts (args(1), who);
985 }
986 else
987 print_usage ();
988
989 return retval;
990}
991
992DEFUN (puts, args, ,
993 "-*- texinfo -*-\n\
994@deftypefn {Built-in Function} {} puts (@var{string})\n\
995Write a string to the standard output with no formatting.\n\
996\n\
997Return a non-negative number on success and EOF on error.\n\
998@end deftypefn")
999{
1000 static std::string who = "puts";
1001
1002 octave_value retval = -1;
1003
1004 if (args.length () == 1)
1005 retval = stdout_stream.puts (args(0), who);
1006 else
1007 print_usage ();
1008
1009 return retval;
1010}
1011
1012DEFUN (sprintf, args, ,
1013 "-*- texinfo -*-\n\
1014@deftypefn {Built-in Function} {} sprintf (@var{template}, @dots{})\n\
1015This is like @code{printf}, except that the output is returned as a\n\
1016string. Unlike the C library function, which requires you to provide a\n\
1017suitably sized string as an argument, Octave's @code{sprintf} function\n\
1018returns the string, automatically sized to hold all of the items\n\
1019converted.\n\
1020@seealso{printf, fprintf, sscanf}\n\
1021@end deftypefn")
1022{
1023 static std::string who = "sprintf";
1024
1025 octave_value_list retval;
1026
1027 int nargin = args.length ();
1028
1029 if (nargin > 0)
1030 {
1031 retval(2) = -1.0;
1032 retval(1) = "unknown error";
1033 retval(0) = "";
1034
1035 octave_ostrstream *ostr = new octave_ostrstream ();
1036
1037 octave_stream os (ostr);
1038
1039 if (os.is_valid ())
1040 {
1041 octave_value fmt_arg = args(0);
1042
1043 if (fmt_arg.is_string ())
1044 {
1045 octave_value_list tmp_args;
1046
1047 if (nargin > 1)
1048 {
1049 tmp_args.resize (nargin-1, octave_value ());
1050
1051 for (int i = 1; i < nargin; i++)
1052 tmp_args(i-1) = args(i);
1053 }
1054
1055 retval(2) = os.printf (fmt_arg, tmp_args, who);
1056 retval(1) = os.error ();
1057 retval(0) = octave_value (ostr->str (),
1058 fmt_arg.is_sq_string () ? '\'' : '"');
1059 }
1060 else
1061 ::error ("%s: format must be a string", who.c_str ());
1062 }
1063 else
1064 ::error ("%s: unable to create output buffer", who.c_str ());
1065 }
1066 else
1067 print_usage ();
1068
1069 return retval;
1070}
1071
1072DEFUN (fscanf, args, ,
1073 "-*- texinfo -*-\n\
1074@deftypefn {Built-in Function} {[@var{val}, @var{count}] =} fscanf (@var{fid}, @var{template}, @var{size})\n\
1075@deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}] =} fscanf (@var{fid}, @var{template}, \"C\")\n\
1076In the first form, read from @var{fid} according to @var{template},\n\
1077returning the result in the matrix @var{val}.\n\
1078\n\
1079The optional argument @var{size} specifies the amount of data to read\n\
1080and may be one of\n\
1081\n\
1082@table @code\n\
1083@item Inf\n\
1084Read as much as possible, returning a column vector.\n\
1085\n\
1086@item @var{nr}\n\
1087Read up to @var{nr} elements, returning a column vector.\n\
1088\n\
1089@item [@var{nr}, Inf]\n\
1090Read as much as possible, returning a matrix with @var{nr} rows. If the\n\
1091number of elements read is not an exact multiple of @var{nr}, the last\n\
1092column is padded with zeros.\n\
1093\n\
1094@item [@var{nr}, @var{nc}]\n\
1095Read up to @code{@var{nr} * @var{nc}} elements, returning a matrix with\n\
1096@var{nr} rows. If the number of elements read is not an exact multiple\n\
1097of @var{nr}, the last column is padded with zeros.\n\
1098@end table\n\
1099\n\
1100@noindent\n\
1101If @var{size} is omitted, a value of @code{Inf} is assumed.\n\
1102\n\
1103A string is returned if @var{template} specifies only character\n\
1104conversions.\n\
1105\n\
1106The number of items successfully read is returned in @var{count}.\n\
1107\n\
1108In the second form, read from @var{fid} according to @var{template},\n\
1109with each conversion specifier in @var{template} corresponding to a\n\
1110single scalar return value. This form is more `C-like', and also\n\
1111compatible with previous versions of Octave. The number of successful\n\
1112conversions is returned in @var{count}\n\
1113@ifclear OCTAVE_MANUAL\n\
1114\n\
1115See the Formatted Input section of the GNU Octave manual for a\n\
1116complete description of the syntax of the template string.\n\
1117@end ifclear\n\
1118@seealso{scanf, sscanf, fread, fprintf, fgets, fputs}\n\
1119@end deftypefn")
1120{
1121 static std::string who = "fscanf";
1122
1123 octave_value_list retval;
1124
1125 int nargin = args.length ();
1126
1127 if (nargin == 3 && args(2).is_string ())
1128 {
1129 octave_stream os = octave_stream_list::lookup (args(0), who);
1130
1131 if (! error_state)
1132 {
1133 if (args(1).is_string ())
1134 retval = os.oscanf (args(1), who);
1135 else
1136 ::error ("%s: format must be a string", who.c_str ());
1137 }
1138 }
1139 else
1140 {
1141 retval (1) = 0.0;
1142 retval (0) = Matrix ();
1143
1144 if (nargin == 2 || nargin == 3)
1145 {
1146 octave_stream os = octave_stream_list::lookup (args(0), who);
1147
1148 if (! error_state)
1149 {
1150 if (args(1).is_string ())
1151 {
1152 octave_idx_type count = 0;
1153
1154 Array<double> size = (nargin == 3)
1155 ? args(2).vector_value ()
1156 : Array<double> (1, lo_ieee_inf_value ());
1157
1158 if (! error_state)
1159 {
1160 octave_value tmp = os.scanf (args(1), size, count, who);
1161
1162 if (! error_state)
1163 {
1164 retval(1) = count;
1165 retval(0) = tmp;
1166 }
1167 }
1168 }
1169 else
1170 ::error ("%s: format must be a string", who.c_str ());
1171 }
1172 }
1173 else
1174 print_usage ();
1175 }
1176
1177 return retval;
1178}
1179
1180DEFUN (sscanf, args, ,
1181 "-*- texinfo -*-\n\
1182@deftypefn {Built-in Function} {[@var{val}, @var{count}] =} sscanf (@var{string}, @var{template}, @var{size})\n\
1183@deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}] =} sscanf (@var{string}, @var{template}, \"C\")\n\
1184This is like @code{fscanf}, except that the characters are taken from the\n\
1185string @var{string} instead of from a stream. Reaching the end of the\n\
1186string is treated as an end-of-file condition.\n\
1187@seealso{fscanf, scanf, sprintf}\n\
1188@end deftypefn")
1189{
1190 static std::string who = "sscanf";
1191
1192 octave_value_list retval;
1193
1194 int nargin = args.length ();
1195
1196 if (nargin == 3 && args(2).is_string ())
1197 {
1198 if (args(0).is_string ())
1199 {
1200 std::string data = args(0).string_value ();
1201
1202 octave_stream os = octave_istrstream::create (data);
1203
1204 if (os.is_valid ())
1205 {
1206 if (args(1).is_string ())
1207 retval = os.oscanf (args(1), who);
1208 else
1209 ::error ("%s: format must be a string", who.c_str ());
1210 }
1211 else
1212 ::error ("%s: unable to create temporary input buffer",
1213 who.c_str ());
1214 }
1215 else
1216 ::error ("%s: first argument must be a string", who.c_str ());
1217 }
1218 else
1219 {
1220 if (nargin == 2 || nargin == 3)
1221 {
1222 retval(3) = -1.0;
1223 retval(2) = "unknown error";
1224 retval(1) = 0.0;
1225 retval(0) = Matrix ();
1226
1227 if (args(0).is_string ())
1228 {
1229 std::string data = args(0).string_value ();
1230
1231 octave_stream os = octave_istrstream::create (data);
1232
1233 if (os.is_valid ())
1234 {
1235 if (args(1).is_string ())
1236 {
1237 octave_idx_type count = 0;
1238
1239 Array<double> size = (nargin == 3)
1240 ? args(2).vector_value ()
1241 : Array<double> (1, lo_ieee_inf_value ());
1242
1243 octave_value tmp = os.scanf (args(1), size, count, who);
1244
1245 if (! error_state)
1246 {
1247 // FIXME -- is this the right thing to do?
1248 // Extract error message first, because getting
1249 // position will clear it.
1250 std::string errmsg = os.error ();
1251
1252 retval(3) = os.tell () + 1;
1253 retval(2) = errmsg;
1254 retval(1) = count;
1255 retval(0) = tmp;
1256 }
1257 }
1258 else
1259 ::error ("%s: format must be a string", who.c_str ());
1260 }
1261 else
1262 ::error ("%s: unable to create temporary input buffer",
1263 who.c_str ());
1264 }
1265 else
1266 ::error ("%s: first argument must be a string", who.c_str ());
1267 }
1268 else
1269 print_usage ();
1270 }
1271
1272 return retval;
1273}
1274
1275DEFUN (scanf, args, nargout,
1276 "-*- texinfo -*-\n\
1277@deftypefn {Built-in Function} {[@var{val}, @var{count}] =} scanf (@var{template}, @var{size})\n\
1278@deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}]] =} scanf (@var{template}, \"C\")\n\
1279This is equivalent to calling @code{fscanf} with @var{fid} = @code{stdin}.\n\
1280\n\
1281It is currently not useful to call @code{scanf} in interactive\n\
1282programs.\n\
1283@seealso{fscanf, sscanf, printf}\n\
1284@end deftypefn")
1285{
1286 int nargin = args.length ();
1287
1288 octave_value_list tmp_args (nargin+1, octave_value ());
1289
1290 tmp_args (0) = 0.0;
1291 for (int i = 0; i < nargin; i++)
1292 tmp_args (i+1) = args (i);
1293
1294 return Ffscanf (tmp_args, nargout);
1295}
1296
1297static octave_value
1298do_fread (octave_stream& os, const octave_value& size_arg,
1299 const octave_value& prec_arg, const octave_value& skip_arg,
1300 const octave_value& arch_arg, octave_idx_type& count)
1301{
1302 octave_value retval;
1303
1304 count = -1;
1305
1306 Array<double> size = size_arg.vector_value ();
1307
1308 if (! error_state)
1309 {
1310 std::string prec = prec_arg.string_value ();
1311
1312 if (! error_state)
1313 {
1314 int block_size = 1;
1315 oct_data_conv::data_type input_type;
1316 oct_data_conv::data_type output_type;
1317
1318 oct_data_conv::string_to_data_type (prec, block_size,
1319 input_type, output_type);
1320
1321 if (! error_state)
1322 {
1323 int skip = skip_arg.int_value (true);
1324
1325 if (! error_state)
1326 {
1327 std::string arch = arch_arg.string_value ();
1328
1329 if (! error_state)
1330 {
1331 oct_mach_info::float_format flt_fmt
1332 = oct_mach_info::string_to_float_format (arch);
1333
1334 if (! error_state)
1335 retval = os.read (size, block_size, input_type,
1336 output_type, skip, flt_fmt, count);
1337 }
1338 else
1339 ::error ("fread: architecture type must be a string");
1340 }
1341 else
1342 ::error ("fread: skip must be an integer");
1343 }
1344 else
1345 ::error ("fread: invalid data type specified");
1346 }
1347 else
1348 ::error ("fread: precision must be a string");
1349 }
1350 else
1351 ::error ("fread: invalid size specified");
1352
1353 return retval;
1354}
1355
1356DEFUN (fread, args, ,
1357 "-*- texinfo -*-\n\
1358@deftypefn {Built-in Function} {[@var{val}, @var{count}] =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip}, @var{arch})\n\
1359Read binary data of type @var{precision} from the specified file ID\n\
1360@var{fid}.\n\
1361\n\
1362The optional argument @var{size} specifies the amount of data to read\n\
1363and may be one of\n\
1364\n\
1365@table @code\n\
1366@item Inf\n\
1367Read as much as possible, returning a column vector.\n\
1368\n\
1369@item @var{nr}\n\
1370Read up to @var{nr} elements, returning a column vector.\n\
1371\n\
1372@item [@var{nr}, Inf]\n\
1373Read as much as possible, returning a matrix with @var{nr} rows. If the\n\
1374number of elements read is not an exact multiple of @var{nr}, the last\n\
1375column is padded with zeros.\n\
1376\n\
1377@item [@var{nr}, @var{nc}]\n\
1378Read up to @code{@var{nr} * @var{nc}} elements, returning a matrix with\n\
1379@var{nr} rows. If the number of elements read is not an exact multiple\n\
1380of @var{nr}, the last column is padded with zeros.\n\
1381@end table\n\
1382\n\
1383@noindent\n\
1384If @var{size} is omitted, a value of @code{Inf} is assumed.\n\
1385\n\
1386The optional argument @var{precision} is a string specifying the type of\n\
1387data to read and may be one of\n\
1388\n\
1389@table @code\n\
1390@item \"schar\"\n\
1391@itemx \"signed char\"\n\
1392Signed character.\n\
1393\n\
1394@item \"uchar\"\n\
1395@itemx \"unsigned char\"\n\
1396Unsigned character.\n\
1397\n\
1398@item \"int8\"\n\
1399@itemx \"integer*1\"\n\
1400\n\
14018-bit signed integer.\n\
1402\n\
1403@item \"int16\"\n\
1404@itemx \"integer*2\"\n\
140516-bit signed integer.\n\
1406\n\
1407@item \"int32\"\n\
1408@itemx \"integer*4\"\n\
140932-bit signed integer.\n\
1410\n\
1411@item \"int64\"\n\
1412@itemx \"integer*8\"\n\
141364-bit signed integer.\n\
1414\n\
1415@item \"uint8\"\n\
14168-bit unsigned integer.\n\
1417\n\
1418@item \"uint16\"\n\
141916-bit unsigned integer.\n\
1420\n\
1421@item \"uint32\"\n\
142232-bit unsigned integer.\n\
1423\n\
1424@item \"uint64\"\n\
142564-bit unsigned integer.\n\
1426\n\
1427@item \"single\"\n\
1428@itemx \"float32\"\n\
1429@itemx \"real*4\"\n\
143032-bit floating point number.\n\
1431\n\
1432@item \"double\"\n\
1433@itemx \"float64\"\n\
1434@itemx \"real*8\"\n\
143564-bit floating point number.\n\
1436\n\
1437@item \"char\"\n\
1438@itemx \"char*1\"\n\
1439Single character.\n\
1440\n\
1441@item \"short\"\n\
1442Short integer (size is platform dependent).\n\
1443\n\
1444@item \"int\"\n\
1445Integer (size is platform dependent).\n\
1446\n\
1447@item \"long\"\n\
1448Long integer (size is platform dependent).\n\
1449\n\
1450@item \"ushort\"\n\
1451@itemx \"unsigned short\"\n\
1452Unsigned short integer (size is platform dependent).\n\
1453\n\
1454@item \"uint\"\n\
1455@itemx \"unsigned int\"\n\
1456Unsigned integer (size is platform dependent).\n\
1457\n\
1458@item \"ulong\"\n\
1459@itemx \"unsigned long\"\n\
1460Unsigned long integer (size is platform dependent).\n\
1461\n\
1462@item \"float\"\n\
1463Single precision floating point number (size is platform dependent).\n\
1464@end table\n\
1465\n\
1466@noindent\n\
1467The default precision is @code{\"uchar\"}.\n\
1468\n\
1469The @var{precision} argument may also specify an optional repeat\n\
1470count. For example, @samp{32*single} causes @code{fread} to read\n\
1471a block of 32 single precision floating point numbers. Reading in\n\
1472blocks is useful in combination with the @var{skip} argument.\n\
1473\n\
1474The @var{precision} argument may also specify a type conversion.\n\
1475For example, @samp{int16=>int32} causes @code{fread} to read 16-bit\n\
1476integer values and return an array of 32-bit integer values. By\n\
1477default, @code{fread} returns a double precision array. The special\n\
1478form @samp{*TYPE} is shorthand for @samp{TYPE=>TYPE}.\n\
1479\n\
1480The conversion and repeat counts may be combined. For example, the\n\
1481specification @samp{32*single=>single} causes @code{fread} to read\n\
1482blocks of single precision floating point values and return an array\n\
1483of single precision values instead of the default array of double\n\
1484precision values.\n\
1485\n\
1486The optional argument @var{skip} specifies the number of bytes to skip\n\
1487after each element (or block of elements) is read. If it is not\n\
1488specified, a value of 0 is assumed. If the final block read is not\n\
1489complete, the final skip is omitted. For example,\n\
1490\n\
1491@example\n\
1492fread (f, 10, \"3*single=>single\", 8)\n\
1493@end example\n\
1494\n\
1495@noindent\n\
1496will omit the final 8-byte skip because the last read will not be\n\
1497a complete block of 3 values.\n\
1498\n\
1499The optional argument @var{arch} is a string specifying the data format\n\
1500for the file. Valid values are\n\
1501\n\
1502@table @code\n\
1503@item \"native\"\n\
1504The format of the current machine.\n\
1505\n\
1506@item \"ieee-be\"\n\
1507IEEE big endian.\n\
1508\n\
1509@item \"ieee-le\"\n\
1510IEEE little endian.\n\
1511\n\
1512@item \"vaxd\"\n\
1513VAX D floating format.\n\
1514\n\
1515@item \"vaxg\"\n\
1516VAX G floating format.\n\
1517\n\
1518@item \"cray\"\n\
1519Cray floating format.\n\
1520@end table\n\
1521\n\
1522@noindent\n\
1523Conversions are currently only supported for @code{\"ieee-be\"} and\n\
1524@code{\"ieee-le\"} formats.\n\
1525\n\
1526The data read from the file is returned in @var{val}, and the number of\n\
1527values read is returned in @code{count}\n\
1528@seealso{fwrite, fopen, fclose}\n\
1529@end deftypefn")
1530{
1531 octave_value_list retval;
1532
1533 int nargin = args.length ();
1534
1535 if (nargin > 0 && nargin < 6)
1536 {
1537 retval(1) = -1.0;
1538 retval(0) = Matrix ();
1539
1540 octave_stream os = octave_stream_list::lookup (args(0), "fread");
1541
1542 if (! error_state)
1543 {
1544 octave_value size = lo_ieee_inf_value ();
1545 octave_value prec = "uchar";
1546 octave_value skip = 0;
1547 octave_value arch = "unknown";
1548
1549 int idx = 1;
1550
1551 if (nargin > idx && ! args(idx).is_string ())
1552 size = args(idx++);
1553
1554 if (nargin > idx)
1555 prec = args(idx++);
1556
1557 if (nargin > idx)
1558 skip = args(idx++);
1559
1560 if (nargin > idx)
1561 arch = args(idx++);
1562 else if (skip.is_string ())
1563 {
1564 arch = skip;
1565 skip = 0;
1566 }
1567
1568 octave_idx_type count = -1;
1569
1570 octave_value tmp = do_fread (os, size, prec, skip, arch, count);
1571
1572 retval(1) = count;
1573 retval(0) = tmp;
1574 }
1575 }
1576 else
1577 print_usage ();
1578
1579 return retval;
1580}
1581
1582static int
1583do_fwrite (octave_stream& os, const octave_value& data,
1584 const octave_value& prec_arg, const octave_value& skip_arg,
1585 const octave_value& arch_arg)
1586{
1587 int retval = -1;
1588
1589 std::string prec = prec_arg.string_value ();
1590
1591 if (! error_state)
1592 {
1593 int block_size = 1;
1594 oct_data_conv::data_type output_type;
1595
1596 oct_data_conv::string_to_data_type (prec, block_size, output_type);
1597
1598 if (! error_state)
1599 {
1600 int skip = skip_arg.int_value (true);
1601
1602 if (! error_state)
1603 {
1604 std::string arch = arch_arg.string_value ();
1605
1606 if (! error_state)
1607 {
1608 oct_mach_info::float_format flt_fmt
1609 = oct_mach_info::string_to_float_format (arch);
1610
1611 if (! error_state)
1612 retval = os.write (data, block_size, output_type,
1613 skip, flt_fmt);
1614 }
1615 else
1616 ::error ("fwrite: architecture type must be a string");
1617 }
1618 else
1619 ::error ("fwrite: skip must be an integer");
1620 }
1621 else
1622 ::error ("fwrite: invalid precision specified");
1623 }
1624 else
1625 ::error ("fwrite: precision must be a string");
1626
1627 return retval;
1628}
1629
1630DEFUN (fwrite, args, ,
1631 "-*- texinfo -*-\n\
1632@deftypefn {Built-in Function} {@var{count} =} fwrite (@var{fid}, @var{data}, @var{precision}, @var{skip}, @var{arch})\n\
1633Write data in binary form of type @var{precision} to the specified file\n\
1634ID @var{fid}, returning the number of values successfully written to the\n\
1635file.\n\
1636\n\
1637The argument @var{data} is a matrix of values that are to be written to\n\
1638the file. The values are extracted in column-major order.\n\
1639\n\
1640The remaining arguments @var{precision}, @var{skip}, and @var{arch} are\n\
1641optional, and are interpreted as described for @code{fread}.\n\
1642\n\
1643The behavior of @code{fwrite} is undefined if the values in @var{data}\n\
1644are too large to fit in the specified precision.\n\
1645@seealso{fread, fopen, fclose}\n\
1646@end deftypefn")
1647{
1648 octave_value retval = -1;
1649
1650 int nargin = args.length ();
1651
1652 if (nargin > 1 && nargin < 6)
1653 {
1654 octave_stream os = octave_stream_list::lookup (args(0), "fwrite");
1655
1656 if (! error_state)
1657 {
1658 octave_value prec = "uchar";
1659 octave_value skip = 0;
1660 octave_value arch = "unknown";
1661
1662 int idx = 1;
1663
1664 octave_value data = args(idx++);
1665
1666 if (nargin > idx)
1667 prec = args(idx++);
1668
1669 if (nargin > idx)
1670 skip = args(idx++);
1671
1672 if (nargin > idx)
1673 arch = args(idx++);
1674 else if (skip.is_string ())
1675 {
1676 arch = skip;
1677 skip = 0;
1678 }
1679
1680 double status = do_fwrite (os, data, prec, skip, arch);
1681
1682 retval = status;
1683 }
1684 }
1685 else
1686 print_usage ();
1687
1688 return retval;
1689}
1690
1691DEFUNX ("feof", Ffeof, args, ,
1692 "-*- texinfo -*-\n\
1693@deftypefn {Built-in Function} {} feof (@var{fid})\n\
1694Return 1 if an end-of-file condition has been encountered for a given\n\
1695file and 0 otherwise. Note that it will only return 1 if the end of the\n\
1696file has already been encountered, not if the next read operation will\n\
1697result in an end-of-file condition.\n\
1698@seealso{fread, fopen, fclose}\n\
1699@end deftypefn")
1700{
1701 octave_value retval = -1;
1702
1703 int nargin = args.length ();
1704
1705 if (nargin == 1)
1706 {
1707 octave_stream os = octave_stream_list::lookup (args(0), "feof");
1708
1709 if (! error_state)
1710 retval = os.eof () ? 1.0 : 0.0;
1711 }
1712 else
1713 print_usage ();
1714
1715 return retval;
1716}
1717
1718DEFUNX ("ferror", Fferror, args, ,
1719 "-*- texinfo -*-\n\
1720@deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} ferror (@var{fid}, \"clear\")\n\
1721Return 1 if an error condition has been encountered for the file ID\n\
1722@var{fid} and 0 otherwise. Note that it will only return 1 if an error\n\
1723has already been encountered, not if the next operation will result in\n\
1724an error condition.\n\
1725\n\
1726The second argument is optional. If it is supplied, also clear the\n\
1727error condition.\n\
1728@end deftypefn")
1729{
1730 octave_value_list retval;
1731
1732 int nargin = args.length ();
1733
1734 if (nargin == 1 || nargin == 2)
1735 {
1736 octave_stream os = octave_stream_list::lookup (args(0), "ferror");
1737
1738 if (! error_state)
1739 {
1740 bool clear = false;
1741
1742 if (nargin == 2)
1743 {
1744 std::string opt = args(1).string_value ();
1745
1746 if (! error_state)
1747 clear = (opt == "clear");
1748 else
1749 return retval;
1750 }
1751
1752 int error_number = 0;
1753
1754 std::string error_message = os.error (clear, error_number);
1755
1756 retval(1) = error_number;
1757 retval(0) = error_message;
1758 }
1759 }
1760 else
1761 print_usage ();
1762
1763 return retval;
1764}
1765
1766DEFUN (popen, args, ,
1767 "-*- texinfo -*-\n\
1768@deftypefn {Built-in Function} {@var{fid} =} popen (@var{command}, @var{mode})\n\
1769Start a process and create a pipe. The name of the command to run is\n\
1770given by @var{command}. The file identifier corresponding to the input\n\
1771or output stream of the process is returned in @var{fid}. The argument\n\
1772@var{mode} may be\n\
1773\n\
1774@table @code\n\
1775@item \"r\"\n\
1776The pipe will be connected to the standard output of the process, and\n\
1777open for reading.\n\
1778\n\
1779@item \"w\"\n\
1780The pipe will be connected to the standard input of the process, and\n\
1781open for writing.\n\
1782@end table\n\
1783\n\
1784For example,\n\
1785\n\
1786@example\n\
1787@group\n\
1788fid = popen (\"ls -ltr / | tail -3\", \"r\");\n\
1789while (ischar (s = fgets (fid)))\n\
1790 fputs (stdout, s);\n\
1791endwhile\n\
1792 @print{} drwxr-xr-x 33 root root 3072 Feb 15 13:28 etc\n\
1793 @print{} drwxr-xr-x 3 root root 1024 Feb 15 13:28 lib\n\
1794 @print{} drwxrwxrwt 15 root root 2048 Feb 17 14:53 tmp\n\
1795@end group\n\
1796@end example\n\
1797@end deftypefn")
1798{
1799 octave_value retval = -1;
1800
1801 int nargin = args.length ();
1802
1803 if (nargin == 2)
1804 {
1805 std::string name = args(0).string_value ();
1806
1807 if (! error_state)
1808 {
1809 std::string mode = args(1).string_value ();
1810
1811 if (! error_state)
1812 {
1813 if (mode == "r")
1814 {
1815 octave_stream ips = octave_iprocstream::create (name);
1816
1817 retval = octave_stream_list::insert (ips);
1818 }
1819 else if (mode == "w")
1820 {
1821 octave_stream ops = octave_oprocstream::create (name);
1822
1823 retval = octave_stream_list::insert (ops);
1824 }
1825 else
1826 ::error ("popen: invalid mode specified");
1827 }
1828 else
1829 ::error ("popen: mode must be a string");
1830 }
1831 else
1832 ::error ("popen: name must be a string");
1833 }
1834 else
1835 print_usage ();
1836
1837 return retval;
1838}
1839
1840DEFUN (pclose, args, ,
1841 "-*- texinfo -*-\n\
1842@deftypefn {Built-in Function} {} pclose (@var{fid})\n\
1843Close a file identifier that was opened by @code{popen}. You may also\n\
1844use @code{fclose} for the same purpose.\n\
1845@end deftypefn")
1846{
1847 octave_value retval = -1;
1848
1849 int nargin = args.length ();
1850
1851 if (nargin == 1)
1852 retval = octave_stream_list::remove (args(0), "pclose");
1853 else
1854 print_usage ();
1855
1856 return retval;
1857}
1858
1859DEFUN (tmpnam, args, ,
1860 "-*- texinfo -*-\n\
1861@deftypefn {Built-in Function} {} tmpnam (@var{dir}, @var{prefix})\n\
1862Return a unique temporary file name as a string.\n\
1863\n\
1864If @var{prefix} is omitted, a value of @code{\"oct-\"} is used.\n\
1865If @var{dir} is also omitted, the default directory for temporary files\n\
1866is used. If @var{dir} is provided, it must exist, otherwise the default\n\
1867directory for temporary files is used. Since the named file is not\n\
1868opened, by @code{tmpnam}, it is possible (though relatively unlikely)\n\
1869that it will not be available by the time your program attempts to open it.\n\
1870@seealso{tmpfile, mkstemp, P_tmpdir}\n\
1871@end deftypefn")
1872{
1873 octave_value retval;
1874
1875 int len = args.length ();
1876
1877 if (len < 3)
1878 {
1879 std::string dir = len > 0 ? args(0).string_value () : std::string ();
1880
1881 if (! error_state)
1882 {
1883 std::string pfx
1884 = len > 1 ? args(1).string_value () : std::string ("oct-");
1885
1886 if (! error_state)
1887 retval = file_ops::tempnam (dir, pfx);
1888 else
1889 ::error ("expecting second argument to be a string");
1890 }
1891 else
1892 ::error ("expecting first argument to be a string");
1893 }
1894 else
1895 print_usage ();
1896
1897 return retval;
1898}
1899
1900DEFALIAS (octave_tmp_file_name, tmpnam);
1901
1902DEFUN (tmpfile, args, ,
1903 "-*- texinfo -*-\n\
1904@deftypefn {Built-in Function} {[@var{fid}, @var{msg}] =} tmpfile ()\n\
1905Return the file ID corresponding to a new temporary file with a unique\n\
1906name. The file is opened in binary read/write (@code{\"w+b\"}) mode.\n\
1907The file will be deleted automatically when it is closed or when Octave\n\
1908exits.\n\
1909\n\
1910If successful, @var{fid} is a valid file ID and @var{msg} is an empty\n\
1911string. Otherwise, @var{fid} is -1 and @var{msg} contains a\n\
1912system-dependent error message.\n\
1913@seealso{tmpnam, mkstemp, P_tmpdir}\n\
1914@end deftypefn")
1915{
1916 octave_value_list retval;
1917
1918 retval(1) = std::string ();
1919 retval(0) = -1;
1920
1921 int nargin = args.length ();
1922
1923 if (nargin == 0)
1924 {
1925 FILE *fid = tmpfile ();
1926
1927 if (fid)
1928 {
1929 std::string nm;
1930
1931 std::ios::openmode md = fopen_mode_to_ios_mode ("w+b");
1932
1933 octave_stream s = octave_stdiostream::create (nm, fid, md);
1934
1935 if (s)
1936 retval(0) = octave_stream_list::insert (s);
1937 else
1938 error ("tmpfile: failed to create octave_stdiostream object");
1939
1940 }
1941 else
1942 {
1943 using namespace std;
1944 retval(1) = ::strerror (errno);
1945 retval(0) = -1;
1946 }
1947 }
1948 else
1949 print_usage ();
1950
1951 return retval;
1952}
1953
1954#if defined (HAVE_MKSTEMPS)
1955// Prototype for mkstemps in libiberty
1956extern "C" int mkstemps (char *pattern, int suffix_len);
1957#endif
1958
1959#if ! defined (HAVE_MKSTEMP) && ! defined (HAVE_MKSTEMPS) && defined (_MSC_VER)
1960# if defined (HAVE_FCNTL_H)
1961# include <fcntl.h>
1962# endif
1963# if defined (HAVE_SYS_STAT_H)
1964# include <sys/stat.h>
1965# endif
1966int mkstemp (char *tmpl)
1967{
1968 int ret=-1;
1969 mktemp (tmpl);
1970 ret = open (tmpl, O_RDWR | O_BINARY | O_CREAT | O_EXCL | _O_SHORT_LIVED,
1971 _S_IREAD | _S_IWRITE);
1972 return ret;
1973}
1974#define HAVE_MKSTEMP 1
1975#endif
1976
1977DEFUN (mkstemp, args, ,
1978 "-*- texinfo -*-\n\
1979@deftypefn {Built-in Function} {[@var{fid}, @var{name}, @var{msg}] =} mkstemp (@var{template}, @var{delete})\n\
1980Return the file ID corresponding to a new temporary file with a unique\n\
1981name created from @var{template}. The last six characters of @var{template}\n\
1982must be @code{XXXXXX} and these are replaced with a string that makes the\n\
1983filename unique. The file is then created with mode read/write and\n\
1984permissions that are system dependent (on GNU/Linux systems, the permissions\n\
1985will be 0600 for versions of glibc 2.0.7 and later). The file is opened\n\
1986with the @w{@code{O_EXCL}} flag.\n\
1987\n\
1988If the optional argument @var{delete} is supplied and is true,\n\
1989the file will be deleted automatically when Octave exits, or when\n\
1990the function @code{purge_tmp_files} is called.\n\
1991\n\
1992If successful, @var{fid} is a valid file ID, @var{name} is the name of\n\
1993the file, and @var{msg} is an empty string. Otherwise, @var{fid}\n\
1994is -1, @var{name} is empty, and @var{msg} contains a system-dependent\n\
1995error message.\n\
1996@seealso{tmpfile, tmpnam, P_tmpdir}\n\
1997@end deftypefn")
1998{
1999 octave_value_list retval;
2000
2001 retval(2) = std::string ();
2002 retval(1) = std::string ();
2003 retval(0) = -1;
2004
2005#if defined (HAVE_MKSTEMP) || defined (HAVE_MKSTEMPS)
2006
2007 int nargin = args.length ();
2008
2009 if (nargin == 1 || nargin == 2)
2010 {
2011 std::string tmpl8 = args(0).string_value ();
2012
2013 if (! error_state)
2014 {
2015 OCTAVE_LOCAL_BUFFER (char, tmp, tmpl8.size () + 1);
2016 strcpy (tmp, tmpl8.c_str ());
2017
2018#if defined (HAVE_MKSTEMP)
2019 int fd = mkstemp (tmp);
2020#else
2021 int fd = mkstemps (tmp, 0);
2022#endif
2023
2024 if (fd < 0)
2025 {
2026 using namespace std;
2027 retval(2) = ::strerror (errno);
2028 retval(0) = fd;
2029 }
2030 else
2031 {
2032 const char *fopen_mode = "w+";
2033
2034 FILE *fid = fdopen (fd, fopen_mode);
2035
2036 if (fid)
2037 {
2038 std::string nm = tmp;
2039
2040 std::ios::openmode md = fopen_mode_to_ios_mode (fopen_mode);
2041
2042 octave_stream s = octave_stdiostream::create (nm, fid, md);
2043
2044 if (s)
2045 {
2046 retval(1) = nm;
2047 retval(0) = octave_stream_list::insert (s);
2048
2049 if (nargin == 2 && args(1).is_true ())
2050 mark_for_deletion (nm);
2051 }
2052 else
2053 error ("mkstemp: failed to create octave_stdiostream object");
2054 }
2055 else
2056 {
2057 using namespace std;
2058 retval(2) = ::strerror (errno);
2059 retval(0) = -1;
2060 }
2061 }
2062 }
2063 else
2064 error ("mkstemp: expecting string as first argument");
2065 }
2066 else
2067 print_usage ();
2068
2069#else
2070 retval(2) = "mkstemp: not supported on this sytem";
2071#endif
2072
2073 return retval;
2074}
2075
2076static int
2077convert (int x, int ibase, int obase)
2078{
2079 int retval = 0;
2080
2081 int tmp = x % obase;
2082
2083 if (tmp > ibase - 1)
2084 ::error ("umask: invalid digit");
2085 else
2086 {
2087 retval = tmp;
2088 int mult = ibase;
2089 while ((x = (x - tmp) / obase))
2090 {
2091 tmp = x % obase;
2092 if (tmp > ibase - 1)
2093 {
2094 ::error ("umask: invalid digit");
2095 break;
2096 }
2097 retval += mult * tmp;
2098 mult *= ibase;
2099 }
2100 }
2101
2102 return retval;
2103}
2104
2105DEFUN (umask, args, ,
2106 "-*- texinfo -*-\n\
2107@deftypefn {Built-in Function} {} umask (@var{mask})\n\
2108Set the permission mask for file creation. The parameter @var{mask}\n\
2109is an integer, interpreted as an octal number. If successful,\n\
2110returns the previous value of the mask (as an integer to be\n\
2111interpreted as an octal number); otherwise an error message is printed.\n\
2112@end deftypefn")
2113{
2114 octave_value_list retval;
2115
2116 int status = 0;
2117
2118 if (args.length () == 1)
2119 {
2120 int mask = args(0).int_value (true);
2121
2122 if (! error_state)
2123 {
2124 if (mask < 0)
2125 {
2126 status = -1;
2127 ::error ("umask: MASK must be a positive integer value");
2128 }
2129 else
2130 {
2131 int oct_mask = convert (mask, 8, 10);
2132
2133 if (! error_state)
2134 status = convert (file_ops::umask (oct_mask), 10, 8);
2135 }
2136 }
2137 else
2138 {
2139 status = -1;
2140 ::error ("umask: expecting integer argument");
2141 }
2142 }
2143 else
2144 print_usage ();
2145
2146 if (status >= 0)
2147 retval(0) = status;
2148
2149 return retval;
2150}
2151
2152static octave_value
2153const_value (const char *, const octave_value_list& args, int val)
2154{
2155 octave_value retval;
2156
2157 int nargin = args.length ();
2158
2159 if (nargin == 0)
2160 retval = val;
2161 else
2162 print_usage ();
2163
2164 return retval;
2165}
2166
2167#if ! defined (P_tmpdir)
2168#define P_tmpdir "/tmp"
2169#endif
2170
2171DEFUNX ("P_tmpdir", FP_tmpdir, args, ,
2172 "-*- texinfo -*-\n\
2173@deftypefn {Built-in Function} {} P_tmpdir ()\n\
2174Return the default name of the directory for temporary files on\n\
2175this system. The name of this directory is system dependent.\n\
2176@end deftypefn")
2177{
2178 octave_value retval;
2179
2180 int nargin = args.length ();
2181
2182 if (nargin == 0)
2183 retval = P_tmpdir;
2184 else
2185 print_usage ();
2186
2187 return retval;
2188}
2189
2190// NOTE: the values of SEEK_SET, SEEK_CUR, and SEEK_END have to be
2191// this way for Matlab compatibility.
2192
2193DEFUNX ("SEEK_SET", FSEEK_SET, args, ,
2194 "-*- texinfo -*-\n\
2195@deftypefn {Built-in Function} {} SEEK_SET ()\n\
2196@deftypefnx {Built-in Function} {} SEEK_CUR ()\n\
2197@deftypefnx {Built-in Function} {} SEEK_END ()\n\
2198Return the value required to request that @code{fseek} perform\n\
2199one of the following actions:\n\
2200@table @code\n\
2201@item SEEK_SET\n\
2202Position file relative to the beginning.\n\
2203\n\
2204@item SEEK_CUR\n\
2205Position file relative to the current position.\n\
2206\n\
2207@item SEEK_END\n\
2208Position file relative to the end.\n\
2209@end table\n\
2210@end deftypefn")
2211{
2212 return const_value ("SEEK_SET", args, -1);
2213}
2214
2215DEFUNX ("SEEK_CUR", FSEEK_CUR, args, ,
2216 "-*- texinfo -*-\n\
2217@deftypefn {Built-in Function} {} SEEK_CUR ()\n\
2218See SEEK_SET.\n\
2219@end deftypefn")
2220{
2221 return const_value ("SEEK_CUR", args, 0);
2222}
2223
2224DEFUNX ("SEEK_END", FSEEK_END, args, ,
2225 "-*- texinfo -*-\n\
2226@deftypefn {Built-in Function} {} SEEK_END ()\n\
2227See SEEK_SET.\n\
2228@end deftypefn")
2229{
2230 return const_value ("SEEK_END", args, 1);
2231}
2232
2233static octave_value
2234const_value (const char *, const octave_value_list& args,
2235 const octave_value& val)
2236{
2237 octave_value retval;
2238
2239 int nargin = args.length ();
2240
2241 if (nargin == 0)
2242 retval = val;
2243 else
2244 print_usage ();
2245
2246 return retval;
2247}
2248
2249DEFUNX ("stdin", Fstdin, args, ,
2250 "-*- texinfo -*-\n\
2251@deftypefn {Built-in Function} {} stdin ()\n\
2252Return the numeric value corresponding to the standard input stream.\n\
2253When Octave is used interactively, this is filtered through the command\n\
2254line editing functions.\n\
2255@seealso{stdout, stderr}\n\
2256@end deftypefn")
2257{
2258 return const_value ("stdin", args, stdin_file);
2259}
2260
2261DEFUNX ("stdout", Fstdout, args, ,
2262 "-*- texinfo -*-\n\
2263@deftypefn {Built-in Function} {} stdout ()\n\
2264Return the numeric value corresponding to the standard output stream.\n\
2265Data written to the standard output is normally filtered through the pager.\n\
2266@seealso{stdin, stderr}\n\
2267@end deftypefn")
2268{
2269 return const_value ("stdout", args, stdout_file);
2270}
2271
2272DEFUNX ("stderr", Fstderr, args, ,
2273 "-*- texinfo -*-\n\
2274@deftypefn {Built-in Function} {} stderr ()\n\
2275Return the numeric value corresponding to the standard error stream.\n\
2276Even if paging is turned on, the standard error is not sent to the\n\
2277pager. It is useful for error messages and prompts.\n\
2278@seealso{stdin, stdout}\n\
2279@end deftypefn")
2280{
2281 return const_value ("stderr", args, stderr_file);
2282}
2283
2284/*
2285;;; Local Variables: ***
2286;;; mode: C++ ***
2287;;; End: ***
2288*/