00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifdef HAVE_CONFIG_H
00038 #include <config.h>
00039 #endif
00040
00041 #include <cerrno>
00042 #include <climits>
00043 #include <cstdio>
00044
00045 #include <iostream>
00046 #include <stack>
00047 #include <vector>
00048
00049 #include <fcntl.h>
00050 #include <sys/types.h>
00051 #include <unistd.h>
00052
00053 #ifdef HAVE_ZLIB_H
00054 #include <zlib.h>
00055 #endif
00056
00057 #include "error.h"
00058 #include "file-ops.h"
00059 #include "file-stat.h"
00060 #include "lo-ieee.h"
00061 #include "oct-env.h"
00062 #include "oct-locbuf.h"
00063
00064 #include "defun.h"
00065 #include "file-io.h"
00066 #include "load-path.h"
00067 #include "oct-fstrm.h"
00068 #include "oct-iostrm.h"
00069 #include "oct-map.h"
00070 #include "oct-obj.h"
00071 #include "oct-prcstrm.h"
00072 #include "oct-stream.h"
00073 #include "oct-strstrm.h"
00074 #include "pager.h"
00075 #include "sysdep.h"
00076 #include "utils.h"
00077 #include "variables.h"
00078
00079 static octave_value stdin_file;
00080 static octave_value stdout_file;
00081 static octave_value stderr_file;
00082
00083 static octave_stream stdin_stream;
00084 static octave_stream stdout_stream;
00085 static octave_stream stderr_stream;
00086
00087 void
00088 initialize_file_io (void)
00089 {
00090 stdin_stream = octave_istream::create (&std::cin, "stdin");
00091
00092
00093
00094
00095 stdout_stream = octave_ostream::create (&octave_stdout, "stdout");
00096
00097 stderr_stream = octave_ostream::create (&std::cerr, "stderr");
00098
00099 stdin_file = octave_stream_list::insert (stdin_stream);
00100 stdout_file = octave_stream_list::insert (stdout_stream);
00101 stderr_file = octave_stream_list::insert (stderr_stream);
00102 }
00103
00104 void
00105 close_files (void)
00106 {
00107 octave_stream_list::clear ();
00108 }
00109
00110
00111
00112
00113
00114 std::stack <std::string> tmp_files;
00115
00116 void
00117 mark_for_deletion (const std::string& file)
00118 {
00119 tmp_files.push (file);
00120 }
00121
00122 void
00123 cleanup_tmp_files (void)
00124 {
00125 while (! tmp_files.empty ())
00126 {
00127 std::string filename = tmp_files.top ();
00128 tmp_files.pop ();
00129 gnulib::unlink (filename.c_str ());
00130 }
00131 }
00132
00133 static std::ios::openmode
00134 fopen_mode_to_ios_mode (const std::string& mode_arg)
00135 {
00136 std::ios::openmode retval = std::ios::in;
00137
00138 if (! mode_arg.empty ())
00139 {
00140
00141
00142 std::string mode = mode_arg;
00143
00144
00145
00146
00147
00148 size_t pos = mode.find ('W');
00149
00150 if (pos != std::string::npos)
00151 {
00152 warning ("fopen: treating mode \"W\" as equivalent to \"w\"");
00153 mode[pos] = 'w';
00154 }
00155
00156 pos = mode.find ('R');
00157
00158 if (pos != std::string::npos)
00159 {
00160 warning ("fopen: treating mode \"R\" as equivalent to \"r\"");
00161 mode[pos] = 'r';
00162 }
00163
00164 pos = mode.find ('z');
00165
00166 if (pos != std::string::npos)
00167 {
00168 #if defined (HAVE_ZLIB)
00169 mode.erase (pos, 1);
00170 #else
00171 error ("this version of Octave does not support gzipped files");
00172 #endif
00173 }
00174
00175 if (! error_state)
00176 {
00177 if (mode == "rt")
00178 retval = std::ios::in;
00179 else if (mode == "wt")
00180 retval = std::ios::out | std::ios::trunc;
00181 else if (mode == "at")
00182 retval = std::ios::out | std::ios::app;
00183 else if (mode == "r+t" || mode == "rt+")
00184 retval = std::ios::in | std::ios::out;
00185 else if (mode == "w+t" || mode == "wt+")
00186 retval = std::ios::in | std::ios::out | std::ios::trunc;
00187 else if (mode == "a+t" || mode == "at+")
00188 retval = std::ios::in | std::ios::out | std::ios::app;
00189 else if (mode == "rb" || mode == "r")
00190 retval = std::ios::in | std::ios::binary;
00191 else if (mode == "wb" || mode == "w")
00192 retval = std::ios::out | std::ios::trunc | std::ios::binary;
00193 else if (mode == "ab" || mode == "a")
00194 retval = std::ios::out | std::ios::app | std::ios::binary;
00195 else if (mode == "r+b" || mode == "rb+" || mode == "r+")
00196 retval = std::ios::in | std::ios::out | std::ios::binary;
00197 else if (mode == "w+b" || mode == "wb+" || mode == "w+")
00198 retval = (std::ios::in | std::ios::out | std::ios::trunc
00199 | std::ios::binary);
00200 else if (mode == "a+b" || mode == "ab+" || mode == "a+")
00201 retval = (std::ios::in | std::ios::out | std::ios::app
00202 | std::ios::binary);
00203 else
00204 ::error ("invalid mode specified");
00205 }
00206 }
00207
00208 return retval;
00209 }
00210
00211 DEFUN (fclose, args, ,
00212 "-*- texinfo -*-\n\
00213 @deftypefn {Built-in Function} {} fclose (@var{fid})\n\
00214 @deftypefnx {Built-in Function} {} fclose (\"all\")\n\
00215 Close the specified file. If successful, @code{fclose} returns 0,\n\
00216 otherwise, it returns -1. The second form of the @code{fclose} call closes\n\
00217 all open files except @code{stdout}, @code{stderr}, and @code{stdin}.\n\
00218 @seealso{fopen, fseek, ftell}\n\
00219 @end deftypefn")
00220 {
00221 octave_value retval = -1;
00222
00223 int nargin = args.length ();
00224
00225 if (nargin == 1)
00226 retval = octave_stream_list::remove (args(0), "fclose");
00227 else
00228 print_usage ();
00229
00230 return retval;
00231 }
00232
00233 DEFUN (fclear, args, ,
00234 "-*- texinfo -*-\n\
00235 @deftypefn {Built-in Function} {} fclear (@var{fid})\n\
00236 Clear the stream state for the specified file.\n\
00237 @end deftypefn")
00238 {
00239 octave_value retval;
00240
00241 int nargin = args.length ();
00242
00243 if (nargin == 1)
00244 {
00245 int fid = octave_stream_list::get_file_number (args (0));
00246
00247 octave_stream os = octave_stream_list::lookup (fid, "fclear");
00248
00249 if (! error_state)
00250 os.clearerr ();
00251 }
00252 else
00253 print_usage ();
00254
00255 return retval;
00256 }
00257
00258 DEFUN (fflush, args, ,
00259 "-*- texinfo -*-\n\
00260 @deftypefn {Built-in Function} {} fflush (@var{fid})\n\
00261 Flush output to @var{fid}. This is useful for ensuring that all\n\
00262 pending output makes it to the screen before some other event occurs.\n\
00263 For example, it is always a good idea to flush the standard output\n\
00264 stream before calling @code{input}.\n\
00265 \n\
00266 @code{fflush} returns 0 on success and an OS dependent error value\n\
00267 (@minus{}1 on Unix) on error.\n\
00268 @seealso{fopen, fclose}\n\
00269 @end deftypefn")
00270 {
00271 octave_value retval = -1;
00272
00273 int nargin = args.length ();
00274
00275 if (nargin == 1)
00276 {
00277
00278
00279 int fid = octave_stream_list::get_file_number (args (0));
00280
00281 if (fid == 1)
00282 {
00283 flush_octave_stdout ();
00284
00285 retval = 0;
00286 }
00287 else
00288 {
00289 octave_stream os = octave_stream_list::lookup (fid, "fflush");
00290
00291 if (! error_state)
00292 retval = os.flush ();
00293 }
00294 }
00295 else
00296 print_usage ();
00297
00298 return retval;
00299 }
00300
00301 DEFUN (fgetl, args, ,
00302 "-*- texinfo -*-\n\
00303 @deftypefn {Built-in Function} {} fgetl (@var{fid}, @var{len})\n\
00304 Read characters from a file, stopping after a newline, or EOF,\n\
00305 or @var{len} characters have been read. The characters read, excluding\n\
00306 the possible trailing newline, are returned as a string.\n\
00307 \n\
00308 If @var{len} is omitted, @code{fgetl} reads until the next newline\n\
00309 character.\n\
00310 \n\
00311 If there are no more characters to read, @code{fgetl} returns @minus{}1.\n\
00312 @seealso{fread, fscanf}\n\
00313 @end deftypefn")
00314 {
00315 static std::string who = "fgetl";
00316
00317 octave_value_list retval;
00318
00319 retval(1) = 0;
00320 retval(0) = -1;
00321
00322 int nargin = args.length ();
00323
00324 if (nargin == 1 || nargin == 2)
00325 {
00326 octave_stream os = octave_stream_list::lookup (args(0), who);
00327
00328 if (! error_state)
00329 {
00330 octave_value len_arg = (nargin == 2) ? args(1) : octave_value ();
00331
00332 bool err = false;
00333
00334 std::string tmp = os.getl (len_arg, err, who);
00335
00336 if (! (error_state || err))
00337 {
00338 retval(1) = tmp.length ();
00339 retval(0) = tmp;
00340 }
00341 }
00342 }
00343 else
00344 print_usage ();
00345
00346 return retval;
00347 }
00348
00349 DEFUN (fgets, args, ,
00350 "-*- texinfo -*-\n\
00351 @deftypefn {Built-in Function} {} fgets (@var{fid})\n\
00352 @deftypefnx {Built-in Function} {} fgets (@var{fid}, @var{len})\n\
00353 Read characters from a file, stopping after a newline, or EOF,\n\
00354 or @var{len} characters have been read. The characters read, including\n\
00355 the possible trailing newline, are returned as a string.\n\
00356 \n\
00357 If @var{len} is omitted, @code{fgets} reads until the next newline\n\
00358 character.\n\
00359 \n\
00360 If there are no more characters to read, @code{fgets} returns @minus{}1.\n\
00361 @seealso{fputs, fopen, fread, fscanf}\n\
00362 @end deftypefn")
00363 {
00364 static std::string who = "fgets";
00365
00366 octave_value_list retval;
00367
00368 retval(1) = 0.0;
00369 retval(0) = -1.0;
00370
00371 int nargin = args.length ();
00372
00373 if (nargin == 1 || nargin == 2)
00374 {
00375 octave_stream os = octave_stream_list::lookup (args(0), who);
00376
00377 if (! error_state)
00378 {
00379 octave_value len_arg = (nargin == 2) ? args(1) : octave_value ();
00380
00381 bool err = false;
00382
00383 std::string tmp = os.gets (len_arg, err, who);
00384
00385 if (! (error_state || err))
00386 {
00387 retval(1) = tmp.length ();
00388 retval(0) = tmp;
00389 }
00390 }
00391 }
00392 else
00393 print_usage ();
00394
00395 return retval;
00396 }
00397
00398 DEFUN (fskipl, args, ,
00399 "-*- texinfo -*-\n\
00400 @deftypefn {Built-in Function} {} fskipl (@var{fid}, @var{count})\n\
00401 Skip a given number of lines, i.e., discards characters until an end-of-line\n\
00402 is met exactly @var{count}-times, or end-of-file occurs.\n\
00403 Returns the number of lines skipped (end-of-line sequences encountered).\n\
00404 If @var{count} is omitted, it defaults to 1. @var{count} may also be\n\
00405 @code{Inf}, in which case lines are skipped to the end of file.\n\
00406 This form is suitable for counting lines in a file.\n\
00407 @seealso{fgetl, fgets}\n\
00408 @end deftypefn")
00409 {
00410 static std::string who = "fskipl";
00411
00412 octave_value retval;
00413
00414 int nargin = args.length ();
00415
00416 if (nargin == 1 || nargin == 2)
00417 {
00418 octave_stream os = octave_stream_list::lookup (args(0), who);
00419
00420 if (! error_state)
00421 {
00422 octave_value count_arg = (nargin == 2) ? args(1) : octave_value ();
00423
00424 bool err = false;
00425
00426 long tmp = os.skipl (count_arg, err, who);
00427
00428 if (! (error_state || err))
00429 retval = tmp;
00430 }
00431 }
00432 else
00433 print_usage ();
00434
00435 return retval;
00436 }
00437
00438
00439 static octave_stream
00440 do_stream_open (const std::string& name, const std::string& mode,
00441 const std::string& arch, int& fid)
00442 {
00443 octave_stream retval;
00444
00445 fid = -1;
00446
00447 std::ios::openmode md = fopen_mode_to_ios_mode (mode);
00448
00449 if (! error_state)
00450 {
00451 oct_mach_info::float_format flt_fmt =
00452 oct_mach_info::string_to_float_format (arch);
00453
00454 if (! error_state)
00455 {
00456 std::string fname = file_ops::tilde_expand (name);
00457
00458 file_stat fs (fname);
00459
00460 if (! (md & std::ios::out
00461 || octave_env::absolute_pathname (fname)
00462 || octave_env::rooted_relative_pathname (fname)))
00463 {
00464 if (! fs.exists ())
00465 {
00466 std::string tmp
00467 = octave_env::make_absolute (load_path::find_file (fname));
00468
00469 if (! tmp.empty ())
00470 {
00471 warning_with_id ("Octave:fopen-file-in-path",
00472 "fopen: file found in load path");
00473 fname = tmp;
00474 }
00475 }
00476 }
00477
00478 if (! fs.is_dir ())
00479 {
00480 std::string tmode = mode;
00481
00482
00483
00484
00485 size_t bpos = tmode.find ('b');
00486 size_t tpos = tmode.find ('t');
00487
00488 if (bpos == std::string::npos && tpos == std::string::npos)
00489 tmode += 'b';
00490
00491 #if defined (HAVE_ZLIB)
00492 size_t pos = tmode.find ('z');
00493
00494 if (pos != std::string::npos)
00495 {
00496 tmode.erase (pos, 1);
00497
00498 FILE *fptr = gnulib::fopen (fname.c_str (), tmode.c_str ());
00499
00500 int fd = fileno (fptr);
00501
00502 gzFile gzf = ::gzdopen (fd, tmode.c_str ());
00503
00504 if (fptr)
00505 retval = octave_zstdiostream::create (fname, gzf, fd,
00506 md, flt_fmt);
00507 else
00508 retval.error (gnulib::strerror (errno));
00509 }
00510 else
00511 #endif
00512 {
00513 FILE *fptr = gnulib::fopen (fname.c_str (), tmode.c_str ());
00514
00515 retval = octave_stdiostream::create (fname, fptr, md, flt_fmt);
00516
00517 if (! fptr)
00518 retval.error (gnulib::strerror (errno));
00519 }
00520
00521 }
00522 }
00523 }
00524
00525 return retval;
00526 }
00527
00528 static octave_stream
00529 do_stream_open (const octave_value& tc_name, const octave_value& tc_mode,
00530 const octave_value& tc_arch, const char *fcn, int& fid)
00531 {
00532 octave_stream retval;
00533
00534 fid = -1;
00535
00536 std::string name = tc_name.string_value ();
00537
00538 if (! error_state)
00539 {
00540 std::string mode = tc_mode.string_value ();
00541
00542 if (! error_state)
00543 {
00544 std::string arch = tc_arch.string_value ();
00545
00546 if (! error_state)
00547 retval = do_stream_open (name, mode, arch, fid);
00548 else
00549 ::error ("%s: architecture type must be a string", fcn);
00550 }
00551 else
00552 ::error ("%s: file mode must be a string", fcn);
00553 }
00554 else
00555 ::error ("%s: file name must be a string", fcn);
00556
00557 return retval;
00558 }
00559
00560 DEFUN (fopen, args, nargout,
00561 "-*- texinfo -*-\n\
00562 @deftypefn {Built-in Function} {[@var{fid}, @var{msg}] =} fopen (@var{name}, @var{mode}, @var{arch})\n\
00563 @deftypefnx {Built-in Function} {@var{fid_list} =} fopen (\"all\")\n\
00564 @deftypefnx {Built-in Function} {[@var{file}, @var{mode}, @var{arch}] =} fopen (@var{fid})\n\
00565 The first form of the @code{fopen} function opens the named file with\n\
00566 the specified mode (read-write, read-only, etc.) and architecture\n\
00567 interpretation (IEEE big endian, IEEE little endian, etc.), and returns\n\
00568 an integer value that may be used to refer to the file later. If an\n\
00569 error occurs, @var{fid} is set to @minus{}1 and @var{msg} contains the\n\
00570 corresponding system error message. The @var{mode} is a one or two\n\
00571 character string that specifies whether the file is to be opened for\n\
00572 reading, writing, or both.\n\
00573 \n\
00574 The second form of the @code{fopen} function returns a vector of file ids\n\
00575 corresponding to all the currently open files, excluding the\n\
00576 @code{stdin}, @code{stdout}, and @code{stderr} streams.\n\
00577 \n\
00578 The third form of the @code{fopen} function returns information about the\n\
00579 open file given its file id.\n\
00580 \n\
00581 For example,\n\
00582 \n\
00583 @example\n\
00584 myfile = fopen (\"splat.dat\", \"r\", \"ieee-le\");\n\
00585 @end example\n\
00586 \n\
00587 @noindent\n\
00588 opens the file @file{splat.dat} for reading. If necessary, binary\n\
00589 numeric values will be read assuming they are stored in IEEE format with\n\
00590 the least significant bit first, and then converted to the native\n\
00591 representation.\n\
00592 \n\
00593 Opening a file that is already open simply opens it again and returns a\n\
00594 separate file id. It is not an error to open a file several times,\n\
00595 though writing to the same file through several different file ids may\n\
00596 produce unexpected results.\n\
00597 \n\
00598 The possible values @samp{mode} may have are\n\
00599 \n\
00600 @table @asis\n\
00601 @item @samp{r}\n\
00602 Open a file for reading.\n\
00603 \n\
00604 @item @samp{w}\n\
00605 Open a file for writing. The previous contents are discarded.\n\
00606 \n\
00607 @item @samp{a}\n\
00608 Open or create a file for writing at the end of the file.\n\
00609 \n\
00610 @item @samp{r+}\n\
00611 Open an existing file for reading and writing.\n\
00612 \n\
00613 @item @samp{w+}\n\
00614 Open a file for reading or writing. The previous contents are\n\
00615 discarded.\n\
00616 \n\
00617 @item @samp{a+}\n\
00618 Open or create a file for reading or writing at the end of the\n\
00619 file.\n\
00620 @end table\n\
00621 \n\
00622 Append a \"t\" to the mode string to open the file in text mode or a\n\
00623 \"b\" to open in binary mode. On Windows and Macintosh systems, text\n\
00624 mode reading and writing automatically converts linefeeds to the\n\
00625 appropriate line end character for the system (carriage-return linefeed\n\
00626 on Windows, carriage-return on Macintosh). The default if no mode is\n\
00627 specified is binary mode.\n\
00628 \n\
00629 Additionally, you may append a \"z\" to the mode string to open a\n\
00630 gzipped file for reading or writing. For this to be successful, you\n\
00631 must also open the file in binary mode.\n\
00632 \n\
00633 The parameter @var{arch} is a string specifying the default data format\n\
00634 for the file. Valid values for @var{arch} are:\n\
00635 \n\
00636 @table @asis\n\
00637 @samp{native}\n\
00638 The format of the current machine (this is the default).\n\
00639 \n\
00640 @samp{ieee-be}\n\
00641 IEEE big endian format.\n\
00642 \n\
00643 @samp{ieee-le}\n\
00644 IEEE little endian format.\n\
00645 \n\
00646 @samp{vaxd}\n\
00647 VAX D floating format.\n\
00648 \n\
00649 @samp{vaxg}\n\
00650 VAX G floating format.\n\
00651 \n\
00652 @samp{cray}\n\
00653 Cray floating format.\n\
00654 @end table\n\
00655 \n\
00656 @noindent\n\
00657 however, conversions are currently only supported for @samp{native}\n\
00658 @samp{ieee-be}, and @samp{ieee-le} formats.\n\
00659 @seealso{fclose, fgets, fputs, fread, fseek, ferror, fprintf, fscanf, ftell, fwrite}\n\
00660 @end deftypefn")
00661 {
00662 octave_value_list retval;
00663
00664 retval(0) = -1.0;
00665
00666 int nargin = args.length ();
00667
00668 if (nargin == 1)
00669 {
00670 if (args(0).is_string ())
00671 {
00672
00673
00674
00675
00676
00677 if (nargout < 2 && args(0).string_value () == "all")
00678 return octave_stream_list::open_file_numbers ();
00679 }
00680 else
00681 {
00682 string_vector tmp = octave_stream_list::get_info (args(0));
00683
00684 if (! error_state)
00685 {
00686 retval(2) = tmp(2);
00687 retval(1) = tmp(1);
00688 retval(0) = tmp(0);
00689 }
00690
00691 return retval;
00692 }
00693 }
00694
00695 if (nargin > 0 && nargin < 4)
00696 {
00697 octave_value mode = (nargin == 2 || nargin == 3)
00698 ? args(1) : octave_value ("r");
00699
00700 octave_value arch = (nargin == 3)
00701 ? args(2) : octave_value ("native");
00702
00703 int fid = -1;
00704
00705 octave_stream os = do_stream_open (args(0), mode, arch, "fopen", fid);
00706
00707 if (os && ! error_state)
00708 {
00709 retval(1) = "";
00710 retval(0) = octave_stream_list::insert (os);
00711 }
00712 else
00713 {
00714 int error_number = 0;
00715
00716 retval(1) = os.error (false, error_number);
00717 retval(0) = -1.0;
00718 }
00719 }
00720 else
00721 print_usage ();
00722
00723 return retval;
00724 }
00725
00726 DEFUN (freport, args, ,
00727 "-*- texinfo -*-\n\
00728 @deftypefn {Built-in Function} {} freport ()\n\
00729 Print a list of which files have been opened, and whether they are open\n\
00730 for reading, writing, or both. For example:\n\
00731 \n\
00732 @example\n\
00733 @group\n\
00734 freport ()\n\
00735 \n\
00736 @print{} number mode name\n\
00737 @print{}\n\
00738 @print{} 0 r stdin\n\
00739 @print{} 1 w stdout\n\
00740 @print{} 2 w stderr\n\
00741 @print{} 3 r myfile\n\
00742 @end group\n\
00743 @end example\n\
00744 @end deftypefn")
00745 {
00746 octave_value_list retval;
00747
00748 int nargin = args.length ();
00749
00750 if (nargin > 0)
00751 warning ("freport: ignoring extra arguments");
00752
00753 octave_stdout << octave_stream_list::list_open_files ();
00754
00755 return retval;
00756 }
00757
00758 DEFUN (frewind, args, nargout,
00759 "-*- texinfo -*-\n\
00760 @deftypefn {Built-in Function} {} frewind (@var{fid})\n\
00761 Move the file pointer to the beginning of the file @var{fid}, returning\n\
00762 0 for success, and -1 if an error was encountered. It is equivalent to\n\
00763 @code{fseek (@var{fid}, 0, SEEK_SET)}.\n\
00764 @end deftypefn")
00765 {
00766 octave_value retval;
00767
00768 int result = -1;
00769
00770 int nargin = args.length ();
00771
00772 if (nargin == 1)
00773 {
00774 octave_stream os = octave_stream_list::lookup (args(0), "frewind");
00775
00776 if (! error_state)
00777 result = os.rewind ();
00778 }
00779 else
00780 print_usage ();
00781
00782 if (nargout > 0)
00783 retval = result;
00784
00785 return retval;
00786 }
00787
00788 DEFUN (fseek, args, ,
00789 "-*- texinfo -*-\n\
00790 @deftypefn {Built-in Function} {} fseek (@var{fid}, @var{offset}, @var{origin})\n\
00791 Set the file pointer to any location within the file @var{fid}.\n\
00792 \n\
00793 The pointer is positioned @var{offset} characters from the @var{origin},\n\
00794 which may be one of the predefined variables @w{@code{SEEK_CUR}} (current\n\
00795 position), @w{@code{SEEK_SET}} (beginning), or @w{@code{SEEK_END}} (end of\n\
00796 file) or strings \"cof\", \"bof\" or \"eof\". If @var{origin} is omitted,\n\
00797 @w{@code{SEEK_SET}} is assumed. The offset must be zero, or a value returned\n\
00798 by @code{ftell} (in which case @var{origin} must be @w{@code{SEEK_SET}}).\n\
00799 \n\
00800 Return 0 on success and -1 on error.\n\
00801 @seealso{ftell, fopen, fclose}\n\
00802 @end deftypefn")
00803 {
00804 octave_value retval = -1;
00805
00806 int nargin = args.length ();
00807
00808 if (nargin == 2 || nargin == 3)
00809 {
00810 octave_stream os = octave_stream_list::lookup (args(0), "fseek");
00811
00812 if (! error_state)
00813 {
00814 octave_value origin_arg = (nargin == 3)
00815 ? args(2) : octave_value (-1.0);
00816
00817 retval = os.seek (args(1), origin_arg);
00818 }
00819 }
00820 else
00821 print_usage ();
00822
00823 return retval;
00824 }
00825
00826 DEFUN (ftell, args, ,
00827 "-*- texinfo -*-\n\
00828 @deftypefn {Built-in Function} {} ftell (@var{fid})\n\
00829 Return the position of the file pointer as the number of characters\n\
00830 from the beginning of the file @var{fid}.\n\
00831 @seealso{fseek, fopen, fclose}\n\
00832 @end deftypefn")
00833 {
00834 octave_value retval = -1;
00835
00836 int nargin = args.length ();
00837
00838 if (nargin == 1)
00839 {
00840 octave_stream os = octave_stream_list::lookup (args(0), "ftell");
00841
00842 if (! error_state)
00843 retval = os.tell ();
00844 }
00845 else
00846 print_usage ();
00847
00848 return retval;
00849 }
00850
00851 DEFUN (fprintf, args, nargout,
00852 "-*- texinfo -*-\n\
00853 @deftypefn {Built-in Function} {} fprintf (@var{fid}, @var{template}, @dots{})\n\
00854 This function is just like @code{printf}, except that the output is\n\
00855 written to the stream @var{fid} instead of @code{stdout}.\n\
00856 If @var{fid} is omitted, the output is written to @code{stdout}.\n\
00857 @seealso{printf, sprintf, fread, fscanf, fopen, fclose}\n\
00858 @end deftypefn")
00859 {
00860 static std::string who = "fprintf";
00861
00862 octave_value retval;
00863
00864 int result = -1;
00865
00866 int nargin = args.length ();
00867
00868 if (nargin > 1 || (nargin > 0 && args(0).is_string ()))
00869 {
00870 octave_stream os;
00871 int fmt_n = 0;
00872
00873 if (args(0).is_string ())
00874 {
00875 os = octave_stream_list::lookup (1, who);
00876 }
00877 else
00878 {
00879 fmt_n = 1;
00880 os = octave_stream_list::lookup (args(0), who);
00881 }
00882
00883 if (! error_state)
00884 {
00885 if (args(fmt_n).is_string ())
00886 {
00887 octave_value_list tmp_args;
00888
00889 if (nargin > 1 + fmt_n)
00890 {
00891 tmp_args.resize (nargin-fmt_n-1, octave_value ());
00892
00893 for (int i = fmt_n + 1; i < nargin; i++)
00894 tmp_args(i-fmt_n-1) = args(i);
00895 }
00896
00897 result = os.printf (args(fmt_n), tmp_args, who);
00898 }
00899 else
00900 ::error ("%s: format TEMPLATE must be a string", who.c_str ());
00901 }
00902 }
00903 else
00904 print_usage ();
00905
00906 if (nargout > 0)
00907 retval = result;
00908
00909 return retval;
00910 }
00911
00912 DEFUN (printf, args, nargout,
00913 "-*- texinfo -*-\n\
00914 @deftypefn {Built-in Function} {} printf (@var{template}, @dots{})\n\
00915 Print optional arguments under the control of the template string\n\
00916 @var{template} to the stream @code{stdout} and return the number of\n\
00917 characters printed.\n\
00918 @ifclear OCTAVE_MANUAL\n\
00919 \n\
00920 See the Formatted Output section of the GNU Octave manual for a\n\
00921 complete description of the syntax of the template string.\n\
00922 @end ifclear\n\
00923 @seealso{fprintf, sprintf, scanf}\n\
00924 @end deftypefn")
00925 {
00926 static std::string who = "printf";
00927
00928 octave_value retval;
00929
00930 int result = -1;
00931
00932 int nargin = args.length ();
00933
00934 if (nargin > 0)
00935 {
00936 if (args(0).is_string ())
00937 {
00938 octave_value_list tmp_args;
00939
00940 if (nargin > 1)
00941 {
00942 tmp_args.resize (nargin-1, octave_value ());
00943
00944 for (int i = 1; i < nargin; i++)
00945 tmp_args(i-1) = args(i);
00946 }
00947
00948 result = stdout_stream.printf (args(0), tmp_args, who);
00949 }
00950 else
00951 ::error ("%s: format TEMPLATE must be a string", who.c_str ());
00952 }
00953 else
00954 print_usage ();
00955
00956 if (nargout > 0)
00957 retval = result;
00958
00959 return retval;
00960 }
00961
00962 DEFUN (fputs, args, ,
00963 "-*- texinfo -*-\n\
00964 @deftypefn {Built-in Function} {} fputs (@var{fid}, @var{string})\n\
00965 Write a string to a file with no formatting.\n\
00966 \n\
00967 Return a non-negative number on success and EOF on error.\n\
00968 @seealso{scanf, sscanf, fread, fprintf, fgets, fscanf}\n\
00969 @end deftypefn")
00970 {
00971 static std::string who = "fputs";
00972
00973 octave_value retval = -1;
00974
00975 int nargin = args.length ();
00976
00977 if (nargin == 2)
00978 {
00979 octave_stream os = octave_stream_list::lookup (args(0), who);
00980
00981 if (! error_state)
00982 retval = os.puts (args(1), who);
00983 }
00984 else
00985 print_usage ();
00986
00987 return retval;
00988 }
00989
00990 DEFUN (puts, args, ,
00991 "-*- texinfo -*-\n\
00992 @deftypefn {Built-in Function} {} puts (@var{string})\n\
00993 Write a string to the standard output with no formatting.\n\
00994 \n\
00995 Return a non-negative number on success and EOF on error.\n\
00996 @end deftypefn")
00997 {
00998 static std::string who = "puts";
00999
01000 octave_value retval = -1;
01001
01002 if (args.length () == 1)
01003 retval = stdout_stream.puts (args(0), who);
01004 else
01005 print_usage ();
01006
01007 return retval;
01008 }
01009
01010 DEFUN (sprintf, args, ,
01011 "-*- texinfo -*-\n\
01012 @deftypefn {Built-in Function} {} sprintf (@var{template}, @dots{})\n\
01013 This is like @code{printf}, except that the output is returned as a\n\
01014 string. Unlike the C library function, which requires you to provide a\n\
01015 suitably sized string as an argument, Octave's @code{sprintf} function\n\
01016 returns the string, automatically sized to hold all of the items\n\
01017 converted.\n\
01018 @seealso{printf, fprintf, sscanf}\n\
01019 @end deftypefn")
01020 {
01021 static std::string who = "sprintf";
01022
01023 octave_value_list retval;
01024
01025 int nargin = args.length ();
01026
01027 if (nargin > 0)
01028 {
01029 retval(2) = -1.0;
01030 retval(1) = "unknown error";
01031 retval(0) = "";
01032
01033 octave_ostrstream *ostr = new octave_ostrstream ();
01034
01035 octave_stream os (ostr);
01036
01037 if (os.is_valid ())
01038 {
01039 octave_value fmt_arg = args(0);
01040
01041 if (fmt_arg.is_string ())
01042 {
01043 octave_value_list tmp_args;
01044
01045 if (nargin > 1)
01046 {
01047 tmp_args.resize (nargin-1, octave_value ());
01048
01049 for (int i = 1; i < nargin; i++)
01050 tmp_args(i-1) = args(i);
01051 }
01052
01053 retval(2) = os.printf (fmt_arg, tmp_args, who);
01054 retval(1) = os.error ();
01055 retval(0) = octave_value (ostr->str (),
01056 fmt_arg.is_sq_string () ? '\'' : '"');
01057 }
01058 else
01059 ::error ("%s: format TEMPLATE must be a string", who.c_str ());
01060 }
01061 else
01062 ::error ("%s: unable to create output buffer", who.c_str ());
01063 }
01064 else
01065 print_usage ();
01066
01067 return retval;
01068 }
01069
01070 DEFUN (fscanf, args, ,
01071 "-*- texinfo -*-\n\
01072 @deftypefn {Built-in Function} {[@var{val}, @var{count}, @var{errmsg}] =} fscanf (@var{fid}, @var{template}, @var{size})\n\
01073 @deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}] =} fscanf (@var{fid}, @var{template}, \"C\")\n\
01074 In the first form, read from @var{fid} according to @var{template},\n\
01075 returning the result in the matrix @var{val}.\n\
01076 \n\
01077 The optional argument @var{size} specifies the amount of data to read\n\
01078 and may be one of\n\
01079 \n\
01080 @table @code\n\
01081 @item Inf\n\
01082 Read as much as possible, returning a column vector.\n\
01083 \n\
01084 @item @var{nr}\n\
01085 Read up to @var{nr} elements, returning a column vector.\n\
01086 \n\
01087 @item [@var{nr}, Inf]\n\
01088 Read as much as possible, returning a matrix with @var{nr} rows. If the\n\
01089 number of elements read is not an exact multiple of @var{nr}, the last\n\
01090 column is padded with zeros.\n\
01091 \n\
01092 @item [@var{nr}, @var{nc}]\n\
01093 Read up to @code{@var{nr} * @var{nc}} elements, returning a matrix with\n\
01094 @var{nr} rows. If the number of elements read is not an exact multiple\n\
01095 of @var{nr}, the last column is padded with zeros.\n\
01096 @end table\n\
01097 \n\
01098 @noindent\n\
01099 If @var{size} is omitted, a value of @code{Inf} is assumed.\n\
01100 \n\
01101 A string is returned if @var{template} specifies only character\n\
01102 conversions.\n\
01103 \n\
01104 The number of items successfully read is returned in @var{count}.\n\
01105 \n\
01106 If an error occurs, @var{errmsg} contains a system-dependent error message.\n\
01107 \n\
01108 In the second form, read from @var{fid} according to @var{template},\n\
01109 with each conversion specifier in @var{template} corresponding to a\n\
01110 single scalar return value. This form is more `C-like', and also\n\
01111 compatible with previous versions of Octave. The number of successful\n\
01112 conversions is returned in @var{count}\n\
01113 @ifclear OCTAVE_MANUAL\n\
01114 \n\
01115 See the Formatted Input section of the GNU Octave manual for a\n\
01116 complete description of the syntax of the template string.\n\
01117 @end ifclear\n\
01118 @seealso{scanf, sscanf, fread, fprintf, fgets, fputs}\n\
01119 @end deftypefn")
01120 {
01121 static std::string who = "fscanf";
01122
01123 octave_value_list retval;
01124
01125 int nargin = args.length ();
01126
01127 if (nargin == 3 && args(2).is_string ())
01128 {
01129 octave_stream os = octave_stream_list::lookup (args(0), who);
01130
01131 if (! error_state)
01132 {
01133 if (args(1).is_string ())
01134 retval = os.oscanf (args(1), who);
01135 else
01136 ::error ("%s: format TEMPLATE must be a string", who.c_str ());
01137 }
01138 }
01139 else
01140 {
01141 retval(2) = "unknown error";
01142 retval(1) = 0.0;
01143 retval(0) = Matrix ();
01144
01145 if (nargin == 2 || nargin == 3)
01146 {
01147 octave_stream os = octave_stream_list::lookup (args(0), who);
01148
01149 if (! error_state)
01150 {
01151 if (args(1).is_string ())
01152 {
01153 octave_idx_type count = 0;
01154
01155 Array<double> size = (nargin == 3)
01156 ? args(2).vector_value ()
01157 : Array<double> (dim_vector (1, 1), lo_ieee_inf_value ());
01158
01159 if (! error_state)
01160 {
01161 octave_value tmp = os.scanf (args(1), size, count, who);
01162
01163 if (! error_state)
01164 {
01165 retval(2) = os.error ();
01166 retval(1) = count;
01167 retval(0) = tmp;
01168 }
01169 }
01170 }
01171 else
01172 ::error ("%s: format must be a string", who.c_str ());
01173 }
01174 }
01175 else
01176 print_usage ();
01177 }
01178
01179 return retval;
01180 }
01181
01182 static std::string
01183 get_sscanf_data (const octave_value& val)
01184 {
01185 std::string retval;
01186
01187 if (val.is_string ())
01188 {
01189 octave_value tmp = val.reshape (dim_vector (1, val.numel ()));
01190
01191 retval = tmp.string_value ();
01192 }
01193 else
01194 ::error ("sscanf: argument STRING must be a string");
01195
01196 return retval;
01197 }
01198
01199 DEFUN (sscanf, args, ,
01200 "-*- texinfo -*-\n\
01201 @deftypefn {Built-in Function} {[@var{val}, @var{count}, @var{errmsg}, @var{pos}] =} sscanf (@var{string}, @var{template}, @var{size})\n\
01202 @deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}] =} sscanf (@var{string}, @var{template}, \"C\")\n\
01203 This is like @code{fscanf}, except that the characters are taken from the\n\
01204 string @var{string} instead of from a stream. Reaching the end of the\n\
01205 string is treated as an end-of-file condition. In addition to the values\n\
01206 returned by @code{fscanf}, the index of the next character to be read\n\
01207 is returned in @var{pos}.\n\
01208 @seealso{fscanf, scanf, sprintf}\n\
01209 @end deftypefn")
01210 {
01211 static std::string who = "sscanf";
01212
01213 octave_value_list retval;
01214
01215 int nargin = args.length ();
01216
01217 if (nargin == 3 && args(2).is_string ())
01218 {
01219 std::string data = get_sscanf_data (args(0));
01220
01221 if (! error_state)
01222 {
01223 octave_stream os = octave_istrstream::create (data);
01224
01225 if (os.is_valid ())
01226 {
01227 if (args(1).is_string ())
01228 retval = os.oscanf (args(1), who);
01229 else
01230 ::error ("%s: format TEMPLATE must be a string", who.c_str ());
01231 }
01232 else
01233 ::error ("%s: unable to create temporary input buffer",
01234 who.c_str ());
01235 }
01236 else
01237 ::error ("%s: argument STRING must be a string", who.c_str ());
01238 }
01239 else
01240 {
01241 if (nargin == 2 || nargin == 3)
01242 {
01243 retval(3) = -1.0;
01244 retval(2) = "unknown error";
01245 retval(1) = 0.0;
01246 retval(0) = Matrix ();
01247
01248 std::string data = get_sscanf_data (args(0));
01249
01250 if (! error_state)
01251 {
01252 octave_stream os = octave_istrstream::create (data);
01253
01254 if (os.is_valid ())
01255 {
01256 if (args(1).is_string ())
01257 {
01258 octave_idx_type count = 0;
01259
01260 Array<double> size = (nargin == 3)
01261 ? args(2).vector_value ()
01262 : Array<double> (dim_vector (1, 1),
01263 lo_ieee_inf_value ());
01264
01265 octave_value tmp = os.scanf (args(1), size, count, who);
01266
01267 if (! error_state)
01268 {
01269
01270
01271
01272 std::string errmsg = os.error ();
01273
01274 retval(3)
01275 = (os.eof () ? data.length () : os.tell ()) + 1;
01276 retval(2) = errmsg;
01277 retval(1) = count;
01278 retval(0) = tmp;
01279 }
01280 }
01281 else
01282 ::error ("%s: format TEMPLATE must be a string", who.c_str ());
01283 }
01284 else
01285 ::error ("%s: unable to create temporary input buffer",
01286 who.c_str ());
01287 }
01288 }
01289 else
01290 print_usage ();
01291 }
01292
01293 return retval;
01294 }
01295
01296 DEFUN (scanf, args, nargout,
01297 "-*- texinfo -*-\n\
01298 @deftypefn {Built-in Function} {[@var{val}, @var{count}, @var{errmsg}] =} scanf (@var{template}, @var{size})\n\
01299 @deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}]] =} scanf (@var{template}, \"C\")\n\
01300 This is equivalent to calling @code{fscanf} with @var{fid} = @code{stdin}.\n\
01301 \n\
01302 It is currently not useful to call @code{scanf} in interactive\n\
01303 programs.\n\
01304 @seealso{fscanf, sscanf, printf}\n\
01305 @end deftypefn")
01306 {
01307 int nargin = args.length ();
01308
01309 octave_value_list tmp_args (nargin+1, octave_value ());
01310
01311 tmp_args (0) = 0.0;
01312 for (int i = 0; i < nargin; i++)
01313 tmp_args (i+1) = args (i);
01314
01315 return Ffscanf (tmp_args, nargout);
01316 }
01317
01318 static octave_value
01319 do_fread (octave_stream& os, const octave_value& size_arg,
01320 const octave_value& prec_arg, const octave_value& skip_arg,
01321 const octave_value& arch_arg, octave_idx_type& count)
01322 {
01323 octave_value retval;
01324
01325 count = -1;
01326
01327 Array<double> size = size_arg.vector_value ();
01328
01329 if (! error_state)
01330 {
01331 std::string prec = prec_arg.string_value ();
01332
01333 if (! error_state)
01334 {
01335 int block_size = 1;
01336 oct_data_conv::data_type input_type;
01337 oct_data_conv::data_type output_type;
01338
01339 oct_data_conv::string_to_data_type (prec, block_size,
01340 input_type, output_type);
01341
01342 if (! error_state)
01343 {
01344 int skip = skip_arg.int_value (true);
01345
01346 if (! error_state)
01347 {
01348 std::string arch = arch_arg.string_value ();
01349
01350 if (! error_state)
01351 {
01352 oct_mach_info::float_format flt_fmt
01353 = oct_mach_info::string_to_float_format (arch);
01354
01355 if (! error_state)
01356 retval = os.read (size, block_size, input_type,
01357 output_type, skip, flt_fmt, count);
01358 }
01359 else
01360 ::error ("fread: ARCH architecture type must be a string");
01361 }
01362 else
01363 ::error ("fread: SKIP must be an integer");
01364 }
01365 else
01366 ::error ("fread: invalid PRECISION specified");
01367 }
01368 else
01369 ::error ("fread: PRECISION must be a string");
01370 }
01371 else
01372 ::error ("fread: invalid SIZE specified");
01373
01374 return retval;
01375 }
01376
01377 DEFUN (fread, args, ,
01378 "-*- texinfo -*-\n\
01379 @deftypefn {Built-in Function} {[@var{val}, @var{count}] =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip}, @var{arch})\n\
01380 Read binary data of type @var{precision} from the specified file ID\n\
01381 @var{fid}.\n\
01382 \n\
01383 The optional argument @var{size} specifies the amount of data to read\n\
01384 and may be one of\n\
01385 \n\
01386 @table @code\n\
01387 @item Inf\n\
01388 Read as much as possible, returning a column vector.\n\
01389 \n\
01390 @item @var{nr}\n\
01391 Read up to @var{nr} elements, returning a column vector.\n\
01392 \n\
01393 @item [@var{nr}, Inf]\n\
01394 Read as much as possible, returning a matrix with @var{nr} rows. If the\n\
01395 number of elements read is not an exact multiple of @var{nr}, the last\n\
01396 column is padded with zeros.\n\
01397 \n\
01398 @item [@var{nr}, @var{nc}]\n\
01399 Read up to @code{@var{nr} * @var{nc}} elements, returning a matrix with\n\
01400 @var{nr} rows. If the number of elements read is not an exact multiple\n\
01401 of @var{nr}, the last column is padded with zeros.\n\
01402 @end table\n\
01403 \n\
01404 @noindent\n\
01405 If @var{size} is omitted, a value of @code{Inf} is assumed.\n\
01406 \n\
01407 The optional argument @var{precision} is a string specifying the type of\n\
01408 data to read and may be one of\n\
01409 \n\
01410 @table @asis\n\
01411 @item \"schar\"\n\
01412 @itemx \"signed char\"\n\
01413 Signed character.\n\
01414 \n\
01415 @item \"uchar\"\n\
01416 @itemx \"unsigned char\"\n\
01417 Unsigned character.\n\
01418 \n\
01419 @item \"int8\"\n\
01420 @itemx \"integer*1\"\n\
01421 \n\
01422 8-bit signed integer.\n\
01423 \n\
01424 @item \"int16\"\n\
01425 @itemx \"integer*2\"\n\
01426 16-bit signed integer.\n\
01427 \n\
01428 @item \"int32\"\n\
01429 @itemx \"integer*4\"\n\
01430 32-bit signed integer.\n\
01431 \n\
01432 @item \"int64\"\n\
01433 @itemx \"integer*8\"\n\
01434 64-bit signed integer.\n\
01435 \n\
01436 @item \"uint8\"\n\
01437 8-bit unsigned integer.\n\
01438 \n\
01439 @item \"uint16\"\n\
01440 16-bit unsigned integer.\n\
01441 \n\
01442 @item \"uint32\"\n\
01443 32-bit unsigned integer.\n\
01444 \n\
01445 @item \"uint64\"\n\
01446 64-bit unsigned integer.\n\
01447 \n\
01448 @item \"single\"\n\
01449 @itemx \"float32\"\n\
01450 @itemx \"real*4\"\n\
01451 32-bit floating point number.\n\
01452 \n\
01453 @item \"double\"\n\
01454 @itemx \"float64\"\n\
01455 @itemx \"real*8\"\n\
01456 64-bit floating point number.\n\
01457 \n\
01458 @item \"char\"\n\
01459 @itemx \"char*1\"\n\
01460 Single character.\n\
01461 \n\
01462 @item \"short\"\n\
01463 Short integer (size is platform dependent).\n\
01464 \n\
01465 @item \"int\"\n\
01466 Integer (size is platform dependent).\n\
01467 \n\
01468 @item \"long\"\n\
01469 Long integer (size is platform dependent).\n\
01470 \n\
01471 @item \"ushort\"\n\
01472 @itemx \"unsigned short\"\n\
01473 Unsigned short integer (size is platform dependent).\n\
01474 \n\
01475 @item \"uint\"\n\
01476 @itemx \"unsigned int\"\n\
01477 Unsigned integer (size is platform dependent).\n\
01478 \n\
01479 @item \"ulong\"\n\
01480 @itemx \"unsigned long\"\n\
01481 Unsigned long integer (size is platform dependent).\n\
01482 \n\
01483 @item \"float\"\n\
01484 Single precision floating point number (size is platform dependent).\n\
01485 @end table\n\
01486 \n\
01487 @noindent\n\
01488 The default precision is @code{\"uchar\"}.\n\
01489 \n\
01490 The @var{precision} argument may also specify an optional repeat\n\
01491 count. For example, @samp{32*single} causes @code{fread} to read\n\
01492 a block of 32 single precision floating point numbers. Reading in\n\
01493 blocks is useful in combination with the @var{skip} argument.\n\
01494 \n\
01495 The @var{precision} argument may also specify a type conversion.\n\
01496 For example, @samp{int16=>int32} causes @code{fread} to read 16-bit\n\
01497 integer values and return an array of 32-bit integer values. By\n\
01498 default, @code{fread} returns a double precision array. The special\n\
01499 form @samp{*TYPE} is shorthand for @samp{TYPE=>TYPE}.\n\
01500 \n\
01501 The conversion and repeat counts may be combined. For example, the\n\
01502 specification @samp{32*single=>single} causes @code{fread} to read\n\
01503 blocks of single precision floating point values and return an array\n\
01504 of single precision values instead of the default array of double\n\
01505 precision values.\n\
01506 \n\
01507 The optional argument @var{skip} specifies the number of bytes to skip\n\
01508 after each element (or block of elements) is read. If it is not\n\
01509 specified, a value of 0 is assumed. If the final block read is not\n\
01510 complete, the final skip is omitted. For example,\n\
01511 \n\
01512 @example\n\
01513 fread (f, 10, \"3*single=>single\", 8)\n\
01514 @end example\n\
01515 \n\
01516 @noindent\n\
01517 will omit the final 8-byte skip because the last read will not be\n\
01518 a complete block of 3 values.\n\
01519 \n\
01520 The optional argument @var{arch} is a string specifying the data format\n\
01521 for the file. Valid values are\n\
01522 \n\
01523 @table @code\n\
01524 @item \"native\"\n\
01525 The format of the current machine.\n\
01526 \n\
01527 @item \"ieee-be\"\n\
01528 IEEE big endian.\n\
01529 \n\
01530 @item \"ieee-le\"\n\
01531 IEEE little endian.\n\
01532 \n\
01533 @item \"vaxd\"\n\
01534 VAX D floating format.\n\
01535 \n\
01536 @item \"vaxg\"\n\
01537 VAX G floating format.\n\
01538 \n\
01539 @item \"cray\"\n\
01540 Cray floating format.\n\
01541 @end table\n\
01542 \n\
01543 @noindent\n\
01544 Conversions are currently only supported for @code{\"ieee-be\"} and\n\
01545 @code{\"ieee-le\"} formats.\n\
01546 \n\
01547 The data read from the file is returned in @var{val}, and the number of\n\
01548 values read is returned in @code{count}\n\
01549 @seealso{fwrite, fopen, fclose}\n\
01550 @end deftypefn")
01551 {
01552 octave_value_list retval;
01553
01554 int nargin = args.length ();
01555
01556 if (nargin > 0 && nargin < 6)
01557 {
01558 retval(1) = -1.0;
01559 retval(0) = Matrix ();
01560
01561 octave_stream os = octave_stream_list::lookup (args(0), "fread");
01562
01563 if (! error_state)
01564 {
01565 octave_value size = lo_ieee_inf_value ();
01566 octave_value prec = "uchar";
01567 octave_value skip = 0;
01568 octave_value arch = "unknown";
01569
01570 int idx = 1;
01571
01572 if (nargin > idx && ! args(idx).is_string ())
01573 size = args(idx++);
01574
01575 if (nargin > idx)
01576 prec = args(idx++);
01577
01578 if (nargin > idx)
01579 skip = args(idx++);
01580
01581 if (nargin > idx)
01582 arch = args(idx++);
01583 else if (skip.is_string ())
01584 {
01585 arch = skip;
01586 skip = 0;
01587 }
01588
01589 octave_idx_type count = -1;
01590
01591 octave_value tmp = do_fread (os, size, prec, skip, arch, count);
01592
01593 retval(1) = count;
01594 retval(0) = tmp;
01595 }
01596 }
01597 else
01598 print_usage ();
01599
01600 return retval;
01601 }
01602
01603 static int
01604 do_fwrite (octave_stream& os, const octave_value& data,
01605 const octave_value& prec_arg, const octave_value& skip_arg,
01606 const octave_value& arch_arg)
01607 {
01608 int retval = -1;
01609
01610 std::string prec = prec_arg.string_value ();
01611
01612 if (! error_state)
01613 {
01614 int block_size = 1;
01615 oct_data_conv::data_type output_type;
01616
01617 oct_data_conv::string_to_data_type (prec, block_size, output_type);
01618
01619 if (! error_state)
01620 {
01621 int skip = skip_arg.int_value (true);
01622
01623 if (! error_state)
01624 {
01625 std::string arch = arch_arg.string_value ();
01626
01627 if (! error_state)
01628 {
01629 oct_mach_info::float_format flt_fmt
01630 = oct_mach_info::string_to_float_format (arch);
01631
01632 if (! error_state)
01633 retval = os.write (data, block_size, output_type,
01634 skip, flt_fmt);
01635 }
01636 else
01637 ::error ("fwrite: ARCH architecture type must be a string");
01638 }
01639 else
01640 ::error ("fwrite: SKIP must be an integer");
01641 }
01642 else
01643 ::error ("fwrite: invalid PRECISION specified");
01644 }
01645 else
01646 ::error ("fwrite: PRECISION must be a string");
01647
01648 return retval;
01649 }
01650
01651 DEFUN (fwrite, args, ,
01652 "-*- texinfo -*-\n\
01653 @deftypefn {Built-in Function} {@var{count} =} fwrite (@var{fid}, @var{data}, @var{precision}, @var{skip}, @var{arch})\n\
01654 Write data in binary form of type @var{precision} to the specified file\n\
01655 ID @var{fid}, returning the number of values successfully written to the\n\
01656 file.\n\
01657 \n\
01658 The argument @var{data} is a matrix of values that are to be written to\n\
01659 the file. The values are extracted in column-major order.\n\
01660 \n\
01661 The remaining arguments @var{precision}, @var{skip}, and @var{arch} are\n\
01662 optional, and are interpreted as described for @code{fread}.\n\
01663 \n\
01664 The behavior of @code{fwrite} is undefined if the values in @var{data}\n\
01665 are too large to fit in the specified precision.\n\
01666 @seealso{fread, fopen, fclose}\n\
01667 @end deftypefn")
01668 {
01669 octave_value retval = -1;
01670
01671 int nargin = args.length ();
01672
01673 if (nargin > 1 && nargin < 6)
01674 {
01675 octave_stream os = octave_stream_list::lookup (args(0), "fwrite");
01676
01677 if (! error_state)
01678 {
01679 octave_value prec = "uchar";
01680 octave_value skip = 0;
01681 octave_value arch = "unknown";
01682
01683 int idx = 1;
01684
01685 octave_value data = args(idx++);
01686
01687 if (nargin > idx)
01688 prec = args(idx++);
01689
01690 if (nargin > idx)
01691 skip = args(idx++);
01692
01693 if (nargin > idx)
01694 arch = args(idx++);
01695 else if (skip.is_string ())
01696 {
01697 arch = skip;
01698 skip = 0;
01699 }
01700
01701 double status = do_fwrite (os, data, prec, skip, arch);
01702
01703 retval = status;
01704 }
01705 }
01706 else
01707 print_usage ();
01708
01709 return retval;
01710 }
01711
01712 DEFUNX ("feof", Ffeof, args, ,
01713 "-*- texinfo -*-\n\
01714 @deftypefn {Built-in Function} {} feof (@var{fid})\n\
01715 Return 1 if an end-of-file condition has been encountered for a given\n\
01716 file and 0 otherwise. Note that it will only return 1 if the end of the\n\
01717 file has already been encountered, not if the next read operation will\n\
01718 result in an end-of-file condition.\n\
01719 @seealso{fread, fopen, fclose}\n\
01720 @end deftypefn")
01721 {
01722 octave_value retval = -1;
01723
01724 int nargin = args.length ();
01725
01726 if (nargin == 1)
01727 {
01728 octave_stream os = octave_stream_list::lookup (args(0), "feof");
01729
01730 if (! error_state)
01731 retval = os.eof () ? 1.0 : 0.0;
01732 }
01733 else
01734 print_usage ();
01735
01736 return retval;
01737 }
01738
01739 DEFUNX ("ferror", Fferror, args, ,
01740 "-*- texinfo -*-\n\
01741 @deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} ferror (@var{fid}, \"clear\")\n\
01742 Return 1 if an error condition has been encountered for the file ID\n\
01743 @var{fid} and 0 otherwise. Note that it will only return 1 if an error\n\
01744 has already been encountered, not if the next operation will result in\n\
01745 an error condition.\n\
01746 \n\
01747 The second argument is optional. If it is supplied, also clear the\n\
01748 error condition.\n\
01749 @end deftypefn")
01750 {
01751 octave_value_list retval;
01752
01753 int nargin = args.length ();
01754
01755 if (nargin == 1 || nargin == 2)
01756 {
01757 octave_stream os = octave_stream_list::lookup (args(0), "ferror");
01758
01759 if (! error_state)
01760 {
01761 bool clear = false;
01762
01763 if (nargin == 2)
01764 {
01765 std::string opt = args(1).string_value ();
01766
01767 if (! error_state)
01768 clear = (opt == "clear");
01769 else
01770 return retval;
01771 }
01772
01773 int error_number = 0;
01774
01775 std::string error_message = os.error (clear, error_number);
01776
01777 retval(1) = error_number;
01778 retval(0) = error_message;
01779 }
01780 }
01781 else
01782 print_usage ();
01783
01784 return retval;
01785 }
01786
01787 DEFUN (popen, args, ,
01788 "-*- texinfo -*-\n\
01789 @deftypefn {Built-in Function} {@var{fid} =} popen (@var{command}, @var{mode})\n\
01790 Start a process and create a pipe. The name of the command to run is\n\
01791 given by @var{command}. The file identifier corresponding to the input\n\
01792 or output stream of the process is returned in @var{fid}. The argument\n\
01793 @var{mode} may be\n\
01794 \n\
01795 @table @code\n\
01796 @item \"r\"\n\
01797 The pipe will be connected to the standard output of the process, and\n\
01798 open for reading.\n\
01799 \n\
01800 @item \"w\"\n\
01801 The pipe will be connected to the standard input of the process, and\n\
01802 open for writing.\n\
01803 @end table\n\
01804 \n\
01805 For example:\n\
01806 \n\
01807 @example\n\
01808 @group\n\
01809 fid = popen (\"ls -ltr / | tail -3\", \"r\");\n\
01810 while (ischar (s = fgets (fid)))\n\
01811 fputs (stdout, s);\n\
01812 endwhile\n\
01813 @print{} drwxr-xr-x 33 root root 3072 Feb 15 13:28 etc\n\
01814 @print{} drwxr-xr-x 3 root root 1024 Feb 15 13:28 lib\n\
01815 @print{} drwxrwxrwt 15 root root 2048 Feb 17 14:53 tmp\n\
01816 @end group\n\
01817 @end example\n\
01818 @end deftypefn")
01819 {
01820 octave_value retval = -1;
01821
01822 int nargin = args.length ();
01823
01824 if (nargin == 2)
01825 {
01826 std::string name = args(0).string_value ();
01827
01828 if (! error_state)
01829 {
01830 std::string mode = args(1).string_value ();
01831
01832 if (! error_state)
01833 {
01834 if (mode == "r")
01835 {
01836 octave_stream ips = octave_iprocstream::create (name);
01837
01838 retval = octave_stream_list::insert (ips);
01839 }
01840 else if (mode == "w")
01841 {
01842 octave_stream ops = octave_oprocstream::create (name);
01843
01844 retval = octave_stream_list::insert (ops);
01845 }
01846 else
01847 ::error ("popen: invalid MODE specified");
01848 }
01849 else
01850 ::error ("popen: MODE must be a string");
01851 }
01852 else
01853 ::error ("popen: COMMAND must be a string");
01854 }
01855 else
01856 print_usage ();
01857
01858 return retval;
01859 }
01860
01861 DEFUN (pclose, args, ,
01862 "-*- texinfo -*-\n\
01863 @deftypefn {Built-in Function} {} pclose (@var{fid})\n\
01864 Close a file identifier that was opened by @code{popen}. You may also\n\
01865 use @code{fclose} for the same purpose.\n\
01866 @end deftypefn")
01867 {
01868 octave_value retval = -1;
01869
01870 int nargin = args.length ();
01871
01872 if (nargin == 1)
01873 retval = octave_stream_list::remove (args(0), "pclose");
01874 else
01875 print_usage ();
01876
01877 return retval;
01878 }
01879
01880 DEFUNX ("tmpnam", Ftmpnam, args, ,
01881 "-*- texinfo -*-\n\
01882 @c List other forms of function in documentation index\n\
01883 @findex octave_tmp_file_name\n\
01884 \n\
01885 @deftypefn {Built-in Function} {} tmpnam ()\n\
01886 @deftypefnx {Built-in Function} {} tmpnam (@var{dir})\n\
01887 @deftypefnx {Built-in Function} {} tmpnam (@var{dir}, @var{prefix})\n\
01888 Return a unique temporary file name as a string.\n\
01889 \n\
01890 If @var{prefix} is omitted, a value of @code{\"oct-\"} is used.\n\
01891 If @var{dir} is also omitted, the default directory for temporary files\n\
01892 is used. If @var{dir} is provided, it must exist, otherwise the default\n\
01893 directory for temporary files is used. Since the named file is not\n\
01894 opened, by @code{tmpnam}, it is possible (though relatively unlikely)\n\
01895 that it will not be available by the time your program attempts to open it.\n\
01896 @seealso{tmpfile, mkstemp, P_tmpdir}\n\
01897 @end deftypefn")
01898 {
01899 octave_value retval;
01900
01901 int len = args.length ();
01902
01903 if (len < 3)
01904 {
01905 std::string dir = len > 0 ? args(0).string_value () : std::string ();
01906
01907 if (! error_state)
01908 {
01909 std::string pfx
01910 = len > 1 ? args(1).string_value () : std::string ("oct-");
01911
01912 if (! error_state)
01913 retval = octave_tempnam (dir, pfx);
01914 else
01915 ::error ("PREFIX must be a string");
01916 }
01917 else
01918 ::error ("DIR argument must be a string");
01919 }
01920 else
01921 print_usage ();
01922
01923 return retval;
01924 }
01925
01926 DEFALIAS (octave_tmp_file_name, tmpnam);
01927
01928 DEFUN (tmpfile, args, ,
01929 "-*- texinfo -*-\n\
01930 @deftypefn {Built-in Function} {[@var{fid}, @var{msg}] =} tmpfile ()\n\
01931 Return the file ID corresponding to a new temporary file with a unique\n\
01932 name. The file is opened in binary read/write (@code{\"w+b\"}) mode.\n\
01933 The file will be deleted automatically when it is closed or when Octave\n\
01934 exits.\n\
01935 \n\
01936 If successful, @var{fid} is a valid file ID and @var{msg} is an empty\n\
01937 string. Otherwise, @var{fid} is -1 and @var{msg} contains a\n\
01938 system-dependent error message.\n\
01939 @seealso{tmpnam, mkstemp, P_tmpdir}\n\
01940 @end deftypefn")
01941 {
01942 octave_value_list retval;
01943
01944 retval(1) = std::string ();
01945 retval(0) = -1;
01946
01947 int nargin = args.length ();
01948
01949 if (nargin == 0)
01950 {
01951 FILE *fid = gnulib::tmpfile ();
01952
01953 if (fid)
01954 {
01955 std::string nm;
01956
01957 std::ios::openmode md = fopen_mode_to_ios_mode ("w+b");
01958
01959 octave_stream s = octave_stdiostream::create (nm, fid, md);
01960
01961 if (s)
01962 retval(0) = octave_stream_list::insert (s);
01963 else
01964 error ("tmpfile: failed to create octave_stdiostream object");
01965
01966 }
01967 else
01968 {
01969 retval(1) = gnulib::strerror (errno);
01970 retval(0) = -1;
01971 }
01972 }
01973 else
01974 print_usage ();
01975
01976 return retval;
01977 }
01978
01979 DEFUN (mkstemp, args, ,
01980 "-*- texinfo -*-\n\
01981 @deftypefn {Built-in Function} {[@var{fid}, @var{name}, @var{msg}] =} mkstemp (@var{template}, @var{delete})\n\
01982 Return the file ID corresponding to a new temporary file with a unique\n\
01983 name created from @var{template}. The last six characters of @var{template}\n\
01984 must be @code{XXXXXX} and these are replaced with a string that makes the\n\
01985 filename unique. The file is then created with mode read/write and\n\
01986 permissions that are system dependent (on GNU/Linux systems, the permissions\n\
01987 will be 0600 for versions of glibc 2.0.7 and later). The file is opened\n\
01988 in binary mode and with the @w{@code{O_EXCL}} flag.\n\
01989 \n\
01990 If the optional argument @var{delete} is supplied and is true,\n\
01991 the file will be deleted automatically when Octave exits, or when\n\
01992 the function @code{purge_tmp_files} is called.\n\
01993 \n\
01994 If successful, @var{fid} is a valid file ID, @var{name} is the name of\n\
01995 the file, and @var{msg} is an empty string. Otherwise, @var{fid}\n\
01996 is -1, @var{name} is empty, and @var{msg} contains a system-dependent\n\
01997 error message.\n\
01998 @seealso{tmpfile, tmpnam, P_tmpdir}\n\
01999 @end deftypefn")
02000 {
02001 octave_value_list retval;
02002
02003 retval(2) = std::string ();
02004 retval(1) = std::string ();
02005 retval(0) = -1;
02006
02007 int nargin = args.length ();
02008
02009 if (nargin == 1 || nargin == 2)
02010 {
02011 std::string tmpl8 = args(0).string_value ();
02012
02013 if (! error_state)
02014 {
02015 OCTAVE_LOCAL_BUFFER (char, tmp, tmpl8.size () + 1);
02016 strcpy (tmp, tmpl8.c_str ());
02017
02018 int fd = gnulib::mkostemp (tmp, O_BINARY);
02019
02020 if (fd < 0)
02021 {
02022 retval(2) = gnulib::strerror (errno);
02023 retval(0) = fd;
02024 }
02025 else
02026 {
02027 const char *fopen_mode = "w+b";
02028
02029 FILE *fid = fdopen (fd, fopen_mode);
02030
02031 if (fid)
02032 {
02033 std::string nm = tmp;
02034
02035 std::ios::openmode md = fopen_mode_to_ios_mode (fopen_mode);
02036
02037 octave_stream s = octave_stdiostream::create (nm, fid, md);
02038
02039 if (s)
02040 {
02041 retval(1) = nm;
02042 retval(0) = octave_stream_list::insert (s);
02043
02044 if (nargin == 2 && args(1).is_true ())
02045 mark_for_deletion (nm);
02046 }
02047 else
02048 error ("mkstemp: failed to create octave_stdiostream object");
02049 }
02050 else
02051 {
02052 retval(2) = gnulib::strerror (errno);
02053 retval(0) = -1;
02054 }
02055 }
02056 }
02057 else
02058 error ("mkstemp: TEMPLATE argument must be a string");
02059 }
02060 else
02061 print_usage ();
02062
02063 return retval;
02064 }
02065
02066 static int
02067 convert (int x, int ibase, int obase)
02068 {
02069 int retval = 0;
02070
02071 int tmp = x % obase;
02072
02073 if (tmp > ibase - 1)
02074 ::error ("umask: invalid digit");
02075 else
02076 {
02077 retval = tmp;
02078 int mult = ibase;
02079 while ((x = (x - tmp) / obase))
02080 {
02081 tmp = x % obase;
02082 if (tmp > ibase - 1)
02083 {
02084 ::error ("umask: invalid digit");
02085 break;
02086 }
02087 retval += mult * tmp;
02088 mult *= ibase;
02089 }
02090 }
02091
02092 return retval;
02093 }
02094
02095 DEFUNX ("umask", Fumask, args, ,
02096 "-*- texinfo -*-\n\
02097 @deftypefn {Built-in Function} {} umask (@var{mask})\n\
02098 Set the permission mask for file creation. The parameter @var{mask}\n\
02099 is an integer, interpreted as an octal number. If successful,\n\
02100 returns the previous value of the mask (as an integer to be\n\
02101 interpreted as an octal number); otherwise an error message is printed.\n\
02102 @end deftypefn")
02103 {
02104 octave_value_list retval;
02105
02106 int status = 0;
02107
02108 if (args.length () == 1)
02109 {
02110 int mask = args(0).int_value (true);
02111
02112 if (! error_state)
02113 {
02114 if (mask < 0)
02115 {
02116 status = -1;
02117 ::error ("umask: MASK must be a positive integer value");
02118 }
02119 else
02120 {
02121 int oct_mask = convert (mask, 8, 10);
02122
02123 if (! error_state)
02124 status = convert (octave_umask (oct_mask), 10, 8);
02125 }
02126 }
02127 else
02128 {
02129 status = -1;
02130 ::error ("umask: MASK must be an integer");
02131 }
02132 }
02133 else
02134 print_usage ();
02135
02136 if (status >= 0)
02137 retval(0) = status;
02138
02139 return retval;
02140 }
02141
02142 static octave_value
02143 const_value (const char *, const octave_value_list& args, int val)
02144 {
02145 octave_value retval;
02146
02147 int nargin = args.length ();
02148
02149 if (nargin == 0)
02150 retval = val;
02151 else
02152 print_usage ();
02153
02154 return retval;
02155 }
02156
02157 DEFUNX ("P_tmpdir", FP_tmpdir, args, ,
02158 "-*- texinfo -*-\n\
02159 @deftypefn {Built-in Function} {} P_tmpdir ()\n\
02160 Return the default name of the directory for temporary files on\n\
02161 this system. The name of this directory is system dependent.\n\
02162 @end deftypefn")
02163 {
02164 octave_value retval;
02165
02166 int nargin = args.length ();
02167
02168 if (nargin == 0)
02169 retval = get_P_tmpdir ();
02170 else
02171 print_usage ();
02172
02173 return retval;
02174 }
02175
02176
02177
02178
02179 DEFUNX ("SEEK_SET", FSEEK_SET, args, ,
02180 "-*- texinfo -*-\n\
02181 @deftypefn {Built-in Function} {} SEEK_SET ()\n\
02182 @deftypefnx {Built-in Function} {} SEEK_CUR ()\n\
02183 @deftypefnx {Built-in Function} {} SEEK_END ()\n\
02184 Return the numerical value to pass to @code{fseek} to perform\n\
02185 one of the following actions:\n\
02186 @table @code\n\
02187 @item SEEK_SET\n\
02188 Position file relative to the beginning.\n\
02189 \n\
02190 @item SEEK_CUR\n\
02191 Position file relative to the current position.\n\
02192 \n\
02193 @item SEEK_END\n\
02194 Position file relative to the end.\n\
02195 @end table\n\
02196 @seealso{fseek}\n\
02197 @end deftypefn")
02198 {
02199 return const_value ("SEEK_SET", args, -1);
02200 }
02201
02202 DEFUNX ("SEEK_CUR", FSEEK_CUR, args, ,
02203 "-*- texinfo -*-\n\
02204 @deftypefn {Built-in Function} {} SEEK_CUR ()\n\
02205 Return the numerical value to pass to @code{fseek} to\n\
02206 position the file pointer relative to the current position.\n\
02207 @seealso{SEEK_SET, SEEK_END}.\n\
02208 @end deftypefn")
02209 {
02210 return const_value ("SEEK_CUR", args, 0);
02211 }
02212
02213 DEFUNX ("SEEK_END", FSEEK_END, args, ,
02214 "-*- texinfo -*-\n\
02215 @deftypefn {Built-in Function} {} SEEK_END ()\n\
02216 Return the numerical value to pass to @code{fseek} to\n\
02217 position the file pointer relative to the end of the file.\n\
02218 @seealso{SEEK_SET, SEEK_CUR}.\n\
02219 @end deftypefn")
02220 {
02221 return const_value ("SEEK_END", args, 1);
02222 }
02223
02224 static octave_value
02225 const_value (const char *, const octave_value_list& args,
02226 const octave_value& val)
02227 {
02228 octave_value retval;
02229
02230 int nargin = args.length ();
02231
02232 if (nargin == 0)
02233 retval = val;
02234 else
02235 print_usage ();
02236
02237 return retval;
02238 }
02239
02240 DEFUNX ("stdin", Fstdin, args, ,
02241 "-*- texinfo -*-\n\
02242 @deftypefn {Built-in Function} {} stdin ()\n\
02243 Return the numeric value corresponding to the standard input stream.\n\
02244 When Octave is used interactively, this is filtered through the command\n\
02245 line editing functions.\n\
02246 @seealso{stdout, stderr}\n\
02247 @end deftypefn")
02248 {
02249 return const_value ("stdin", args, stdin_file);
02250 }
02251
02252 DEFUNX ("stdout", Fstdout, args, ,
02253 "-*- texinfo -*-\n\
02254 @deftypefn {Built-in Function} {} stdout ()\n\
02255 Return the numeric value corresponding to the standard output stream.\n\
02256 Data written to the standard output is normally filtered through the pager.\n\
02257 @seealso{stdin, stderr}\n\
02258 @end deftypefn")
02259 {
02260 return const_value ("stdout", args, stdout_file);
02261 }
02262
02263 DEFUNX ("stderr", Fstderr, args, ,
02264 "-*- texinfo -*-\n\
02265 @deftypefn {Built-in Function} {} stderr ()\n\
02266 Return the numeric value corresponding to the standard error stream.\n\
02267 Even if paging is turned on, the standard error is not sent to the\n\
02268 pager. It is useful for error messages and prompts.\n\
02269 @seealso{stdin, stdout}\n\
02270 @end deftypefn")
02271 {
02272 return const_value ("stderr", args, stderr_file);
02273 }