00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <cerrno>
00029 #include <climits>
00030 #include <cstring>
00031
00032 #include <fstream>
00033 #include <iostream>
00034 #include <string>
00035
00036 #include <sys/types.h>
00037 #include <unistd.h>
00038
00039 #include "vasnprintf.h"
00040
00041 #include "quit.h"
00042
00043 #include "dir-ops.h"
00044 #include "file-ops.h"
00045 #include "file-stat.h"
00046 #include "lo-mappers.h"
00047 #include "lo-utils.h"
00048 #include "oct-cmplx.h"
00049 #include "oct-env.h"
00050 #include "pathsearch.h"
00051 #include "str-vec.h"
00052
00053 #include "Cell.h"
00054 #include <defaults.h>
00055 #include "defun.h"
00056 #include "dirfns.h"
00057 #include "error.h"
00058 #include "gripes.h"
00059 #include "input.h"
00060 #include "lex.h"
00061 #include "load-path.h"
00062 #include "oct-errno.h"
00063 #include "oct-hist.h"
00064 #include "oct-obj.h"
00065 #include "ov-range.h"
00066 #include "pager.h"
00067 #include "parse.h"
00068 #include "sysdep.h"
00069 #include "toplev.h"
00070 #include "unwind-prot.h"
00071 #include "utils.h"
00072 #include "variables.h"
00073
00074
00075
00076 bool
00077 valid_identifier (const char *s)
00078 {
00079 if (! s || ! (isalpha (*s) || *s == '_' || *s == '$'))
00080 return false;
00081
00082 while (*++s != '\0')
00083 if (! (isalnum (*s) || *s == '_' || *s == '$'))
00084 return false;
00085
00086 return true;
00087 }
00088
00089 bool
00090 valid_identifier (const std::string& s)
00091 {
00092 return valid_identifier (s.c_str ());
00093 }
00094
00095 DEFUN (isvarname, args, ,
00096 "-*- texinfo -*-\n\
00097 @deftypefn {Built-in Function} {} isvarname (@var{name})\n\
00098 Return true if @var{name} is a valid variable name.\n\
00099 @seealso{iskeyword, exist, who}\n\
00100 @end deftypefn")
00101 {
00102 octave_value retval;
00103
00104 int argc = args.length () + 1;
00105
00106 string_vector argv = args.make_argv ("isvarname");
00107
00108 if (error_state)
00109 return retval;
00110
00111 if (argc == 2)
00112 retval = valid_identifier (argv[1]) && ! is_keyword (argv[1]);
00113 else
00114 print_usage ();
00115
00116 return retval;
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 bool
00133 same_file (const std::string& f, const std::string& g)
00134 {
00135 return same_file_internal (f, g);
00136 }
00137
00138 int
00139 almost_match (const std::string& std, const std::string& s, int min_match_len,
00140 int case_sens)
00141 {
00142 int stdlen = std.length ();
00143 int slen = s.length ();
00144
00145 return (slen <= stdlen
00146 && slen >= min_match_len
00147 && (case_sens
00148 ? (strncmp (std.c_str (), s.c_str (), slen) == 0)
00149 : (octave_strncasecmp (std.c_str (), s.c_str (), slen) == 0)));
00150 }
00151
00152
00153
00154 int
00155 keyword_almost_match (const char * const *std, int *min_len, const std::string& s,
00156 int min_toks_to_match, int max_toks)
00157 {
00158 int status = 0;
00159 int tok_count = 0;
00160 int toks_matched = 0;
00161
00162 if (s.empty () || max_toks < 1)
00163 return status;
00164
00165 char *kw = strsave (s.c_str ());
00166
00167 char *t = kw;
00168 while (*t != '\0')
00169 {
00170 if (*t == '\t')
00171 *t = ' ';
00172 t++;
00173 }
00174
00175 char *beg = kw;
00176 while (*beg == ' ')
00177 beg++;
00178
00179 if (*beg == '\0')
00180 return status;
00181
00182
00183 const char **to_match = new const char * [max_toks + 1];
00184 const char * const *s1 = std;
00185 const char **s2 = to_match;
00186
00187 if (! s1 || ! s2)
00188 goto done;
00189
00190 s2[tok_count] = beg;
00191 char *end;
00192 while ((end = strchr (beg, ' ')) != 0)
00193 {
00194 *end = '\0';
00195 beg = end + 1;
00196
00197 while (*beg == ' ')
00198 beg++;
00199
00200 if (*beg == '\0')
00201 break;
00202
00203 tok_count++;
00204 if (tok_count >= max_toks)
00205 goto done;
00206
00207 s2[tok_count] = beg;
00208 }
00209 s2[tok_count+1] = 0;
00210
00211 s2 = to_match;
00212
00213 for (;;)
00214 {
00215 if (! almost_match (*s1, *s2, min_len[toks_matched], 0))
00216 goto done;
00217
00218 toks_matched++;
00219
00220 s1++;
00221 s2++;
00222
00223 if (! *s2)
00224 {
00225 status = (toks_matched >= min_toks_to_match);
00226 goto done;
00227 }
00228
00229 if (! *s1)
00230 goto done;
00231 }
00232
00233 done:
00234
00235 delete [] kw;
00236 delete [] to_match;
00237
00238 return status;
00239 }
00240
00241
00242
00243
00244 int
00245 empty_arg (const char * , octave_idx_type nr, octave_idx_type nc)
00246 {
00247 return (nr == 0 || nc == 0);
00248 }
00249
00250
00251
00252 std::string
00253 search_path_for_file (const std::string& path, const string_vector& names)
00254 {
00255 dir_path p (path);
00256
00257 return octave_env::make_absolute (p.find_first_of (names));
00258 }
00259
00260
00261
00262 string_vector
00263 search_path_for_all_files (const std::string& path, const string_vector& names)
00264 {
00265 dir_path p (path);
00266
00267 string_vector sv = p.find_all_first_of (names);
00268
00269 octave_idx_type len = sv.length ();
00270
00271 for (octave_idx_type i = 0; i < len; i++)
00272 sv[i] = octave_env::make_absolute (sv[i]);
00273
00274 return sv;
00275 }
00276
00277 static string_vector
00278 make_absolute (const string_vector& sv)
00279 {
00280 octave_idx_type len = sv.length ();
00281
00282 string_vector retval (len);
00283
00284 for (octave_idx_type i = 0; i < len; i++)
00285 retval[i] = octave_env::make_absolute (sv[i]);
00286
00287 return retval;
00288 }
00289
00290 DEFUN (file_in_loadpath, args, ,
00291 "-*- texinfo -*-\n\
00292 @deftypefn {Built-in Function} {} file_in_loadpath (@var{file})\n\
00293 @deftypefnx {Built-in Function} {} file_in_loadpath (@var{file}, \"all\")\n\
00294 \n\
00295 Return the absolute name of @var{file} if it can be found in\n\
00296 the list of directories specified by @code{path}.\n\
00297 If no file is found, return an empty character string.\n\
00298 \n\
00299 If the first argument is a cell array of strings, search each\n\
00300 directory of the loadpath for element of the cell array and return\n\
00301 the first that matches.\n\
00302 \n\
00303 If the second optional argument @code{\"all\"} is supplied, return\n\
00304 a cell array containing the list of all files that have the same\n\
00305 name in the path. If no files are found, return an empty cell array.\n\
00306 @seealso{file_in_path, path}\n\
00307 @end deftypefn")
00308 {
00309 octave_value retval;
00310
00311 int nargin = args.length ();
00312
00313 if (nargin == 1 || nargin == 2)
00314 {
00315 string_vector names = args(0).all_strings ();
00316
00317 if (! error_state && names.length () > 0)
00318 {
00319 if (nargin == 1)
00320 retval = octave_env::make_absolute (load_path::find_first_of (names));
00321 else if (nargin == 2)
00322 {
00323 std::string opt = args(1).string_value ();
00324
00325 if (! error_state && opt == "all")
00326 retval = Cell (make_absolute
00327 (load_path::find_all_first_of (names)));
00328 else
00329 error ("file_in_loadpath: invalid option");
00330 }
00331 }
00332 else
00333 error ("file_in_loadpath: FILE argument must be a string");
00334 }
00335 else
00336 print_usage ();
00337
00338 return retval;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 DEFUN (file_in_path, args, ,
00360 "-*- texinfo -*-\n\
00361 @deftypefn {Built-in Function} {} file_in_path (@var{path}, @var{file})\n\
00362 @deftypefnx {Built-in Function} {} file_in_path (@var{path}, @var{file}, \"all\")\n\
00363 Return the absolute name of @var{file} if it can be found in\n\
00364 @var{path}. The value of @var{path} should be a colon-separated list of\n\
00365 directories in the format described for @code{path}. If no file\n\
00366 is found, return an empty character string. For example:\n\
00367 \n\
00368 @example\n\
00369 @group\n\
00370 file_in_path (EXEC_PATH, \"sh\")\n\
00371 @result{} \"/bin/sh\"\n\
00372 @end group\n\
00373 @end example\n\
00374 \n\
00375 If the second argument is a cell array of strings, search each\n\
00376 directory of the path for element of the cell array and return\n\
00377 the first that matches.\n\
00378 \n\
00379 If the third optional argument @code{\"all\"} is supplied, return\n\
00380 a cell array containing the list of all files that have the same\n\
00381 name in the path. If no files are found, return an empty cell array.\n\
00382 @seealso{file_in_loadpath}\n\
00383 @end deftypefn")
00384 {
00385 octave_value retval;
00386
00387 int nargin = args.length ();
00388
00389 if (nargin == 2 || nargin == 3)
00390 {
00391 std::string path = args(0).string_value ();
00392
00393 if (! error_state)
00394 {
00395 string_vector names = args(1).all_strings ();
00396
00397 if (! error_state && names.length () > 0)
00398 {
00399 if (nargin == 2)
00400 retval = search_path_for_file (path, names);
00401 else if (nargin == 3)
00402 {
00403 std::string opt = args(2).string_value ();
00404
00405 if (! error_state && opt == "all")
00406 retval = Cell (make_absolute
00407 (search_path_for_all_files (path, names)));
00408 else
00409 error ("file_in_path: invalid option");
00410 }
00411 }
00412 else
00413 error ("file_in_path: all arguments must be strings");
00414 }
00415 else
00416 error ("file_in_path: PATH must be a string");
00417 }
00418 else
00419 print_usage ();
00420
00421 return retval;
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 std::string
00444 file_in_path (const std::string& name, const std::string& suffix)
00445 {
00446 std::string nm = name;
00447
00448 if (! suffix.empty ())
00449 nm.append (suffix);
00450
00451 return octave_env::make_absolute (load_path::find_file (nm));
00452 }
00453
00454
00455
00456
00457 std::string
00458 fcn_file_in_path (const std::string& name)
00459 {
00460 std::string retval;
00461
00462 int len = name.length ();
00463
00464 if (len > 0)
00465 {
00466 if (octave_env::absolute_pathname (name))
00467 {
00468 file_stat fs (name);
00469
00470 if (fs.exists ())
00471 retval = name;
00472 }
00473 else if (len > 2 && name [len - 2] == '.' && name [len - 1] == 'm')
00474 retval = load_path::find_fcn_file (name.substr (0, len-2));
00475 else
00476 {
00477 std::string fname = name;
00478 size_t pos = name.find_first_of (Vfilemarker);
00479 if (pos != std::string::npos)
00480 fname = name.substr (0, pos);
00481
00482 retval = load_path::find_fcn_file (fname);
00483 }
00484 }
00485
00486 return retval;
00487 }
00488
00489
00490
00491
00492 std::string
00493 contents_file_in_path (const std::string& dir)
00494 {
00495 std::string retval;
00496
00497 if (dir.length () > 0)
00498 {
00499 std::string tcontents = file_ops::concat (load_path::find_dir (dir),
00500 std::string ("Contents.m"));
00501
00502 file_stat fs (tcontents);
00503
00504 if (fs.exists ())
00505 retval = octave_env::make_absolute (tcontents);
00506 }
00507
00508 return retval;
00509 }
00510
00511
00512
00513
00514 std::string
00515 oct_file_in_path (const std::string& name)
00516 {
00517 std::string retval;
00518
00519 int len = name.length ();
00520
00521 if (len > 0)
00522 {
00523 if (octave_env::absolute_pathname (name))
00524 {
00525 file_stat fs (name);
00526
00527 if (fs.exists ())
00528 retval = name;
00529 }
00530 else if (len > 4 && name [len - 4] == '.' && name [len - 3] == 'o'
00531 && name [len - 2] == 'c' && name [len - 1] == 't')
00532 retval = load_path::find_oct_file (name.substr (0, len-4));
00533 else
00534 retval = load_path::find_oct_file (name);
00535 }
00536
00537 return retval;
00538 }
00539
00540
00541
00542
00543 std::string
00544 mex_file_in_path (const std::string& name)
00545 {
00546 std::string retval;
00547
00548 int len = name.length ();
00549
00550 if (len > 0)
00551 {
00552 if (octave_env::absolute_pathname (name))
00553 {
00554 file_stat fs (name);
00555
00556 if (fs.exists ())
00557 retval = name;
00558 }
00559 else if (len > 4 && name [len - 4] == '.' && name [len - 3] == 'm'
00560 && name [len - 2] == 'e' && name [len - 1] == 'x')
00561 retval = load_path::find_mex_file (name.substr (0, len-4));
00562 else
00563 retval = load_path::find_mex_file (name);
00564 }
00565
00566 return retval;
00567 }
00568
00569
00570
00571 std::string
00572 do_string_escapes (const std::string& s)
00573 {
00574 std::string retval;
00575
00576 size_t i = 0;
00577 size_t j = 0;
00578 size_t len = s.length ();
00579
00580 retval.resize (len);
00581
00582 while (j < len)
00583 {
00584 if (s[j] == '\\' && j+1 < len)
00585 {
00586 switch (s[++j])
00587 {
00588 case '0':
00589 retval[i] = '\0';
00590 break;
00591
00592 case 'a':
00593 retval[i] = '\a';
00594 break;
00595
00596 case 'b':
00597 retval[i] = '\b';
00598 break;
00599
00600 case 'f':
00601 retval[i] = '\f';
00602 break;
00603
00604 case 'n':
00605 retval[i] = '\n';
00606 break;
00607
00608 case 'r':
00609 retval[i] = '\r';
00610 break;
00611
00612 case 't':
00613 retval[i] = '\t';
00614 break;
00615
00616 case 'v':
00617 retval[i] = '\v';
00618 break;
00619
00620 case '\\':
00621 retval[i] = '\\';
00622 break;
00623
00624 case '\'':
00625 retval[i] = '\'';
00626 break;
00627
00628 case '"':
00629 retval[i] = '"';
00630 break;
00631
00632 default:
00633 warning ("unrecognized escape sequence '\\%c' --\
00634 converting to '%c'", s[j], s[j]);
00635 retval[i] = s[j];
00636 break;
00637 }
00638 }
00639 else
00640 {
00641 retval[i] = s[j];
00642 }
00643
00644 i++;
00645 j++;
00646 }
00647
00648 retval.resize (i);
00649
00650 return retval;
00651 }
00652
00653 DEFUN (do_string_escapes, args, ,
00654 "-*- texinfo -*-\n\
00655 @deftypefn {Built-in Function} {} do_string_escapes (@var{string})\n\
00656 Convert special characters in @var{string} to their escaped forms.\n\
00657 @end deftypefn")
00658 {
00659 octave_value retval;
00660
00661 int nargin = args.length ();
00662
00663 if (nargin == 1)
00664 {
00665 if (args(0).is_string ())
00666 retval = do_string_escapes (args(0).string_value ());
00667 else
00668 error ("do_string_escapes: STRING argument must be of type string");
00669 }
00670 else
00671 print_usage ();
00672
00673 return retval;
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 const char *
00693 undo_string_escape (char c)
00694 {
00695 if (! c)
00696 return "";
00697
00698 switch (c)
00699 {
00700 case '\0':
00701 return "\\0";
00702
00703 case '\a':
00704 return "\\a";
00705
00706 case '\b':
00707 return "\\b";
00708
00709 case '\f':
00710 return "\\f";
00711
00712 case '\n':
00713 return "\\n";
00714
00715 case '\r':
00716 return "\\r";
00717
00718 case '\t':
00719 return "\\t";
00720
00721 case '\v':
00722 return "\\v";
00723
00724 case '\\':
00725 return "\\\\";
00726
00727 case '"':
00728 return "\\\"";
00729
00730 default:
00731 {
00732 static char retval[2];
00733 retval[0] = c;
00734 retval[1] = '\0';
00735 return retval;
00736 }
00737 }
00738 }
00739
00740 std::string
00741 undo_string_escapes (const std::string& s)
00742 {
00743 std::string retval;
00744
00745 for (size_t i = 0; i < s.length (); i++)
00746 retval.append (undo_string_escape (s[i]));
00747
00748 return retval;
00749 }
00750
00751 DEFUN (undo_string_escapes, args, ,
00752 "-*- texinfo -*-\n\
00753 @deftypefn {Built-in Function} {} undo_string_escapes (@var{s})\n\
00754 Convert special characters in strings back to their escaped forms. For\n\
00755 example, the expression\n\
00756 \n\
00757 @example\n\
00758 bell = \"\\a\";\n\
00759 @end example\n\
00760 \n\
00761 @noindent\n\
00762 assigns the value of the alert character (control-g, ASCII code 7) to\n\
00763 the string variable @code{bell}. If this string is printed, the\n\
00764 system will ring the terminal bell (if it is possible). This is\n\
00765 normally the desired outcome. However, sometimes it is useful to be\n\
00766 able to print the original representation of the string, with the\n\
00767 special characters replaced by their escape sequences. For example,\n\
00768 \n\
00769 @example\n\
00770 @group\n\
00771 octave:13> undo_string_escapes (bell)\n\
00772 ans = \\a\n\
00773 @end group\n\
00774 @end example\n\
00775 \n\
00776 @noindent\n\
00777 replaces the unprintable alert character with its printable\n\
00778 representation.\n\
00779 @end deftypefn")
00780 {
00781 octave_value retval;
00782
00783 int nargin = args.length ();
00784
00785 if (nargin == 1)
00786 {
00787 if (args(0).is_string ())
00788 retval = undo_string_escapes (args(0).string_value ());
00789 else
00790 error ("undo_string_escapes: S argument must be a string");
00791 }
00792 else
00793 print_usage ();
00794
00795 return retval;
00796 }
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812 DEFUN (is_absolute_filename, args, ,
00813 "-*- texinfo -*-\n\
00814 @deftypefn {Built-in Function} {} is_absolute_filename (@var{file})\n\
00815 Return true if @var{file} is an absolute filename.\n\
00816 @seealso{is_rooted_relative_filename, make_absolute_filename, isdir}\n\
00817 @end deftypefn")
00818 {
00819 octave_value retval = false;
00820
00821 if (args.length () == 1)
00822 retval = (args(0).is_string ()
00823 && octave_env::absolute_pathname (args(0).string_value ()));
00824 else
00825 print_usage ();
00826
00827 return retval;
00828 }
00829
00830
00831
00832
00833
00834
00835
00836
00837 DEFUN (is_rooted_relative_filename, args, ,
00838 "-*- texinfo -*-\n\
00839 @deftypefn {Built-in Function} {} is_rooted_relative_filename (@var{file})\n\
00840 Return true if @var{file} is a rooted-relative filename.\n\
00841 @seealso{is_absolute_filename, make_absolute_filename, isdir}\n\
00842 @end deftypefn")
00843 {
00844 octave_value retval = false;
00845
00846 if (args.length () == 1)
00847 retval = (args(0).is_string ()
00848 && octave_env::rooted_relative_pathname (args(0).string_value ()));
00849 else
00850 print_usage ();
00851
00852 return retval;
00853 }
00854
00855
00856
00857
00858
00859
00860
00861
00862 DEFUN (make_absolute_filename, args, ,
00863 "-*- texinfo -*-\n\
00864 @deftypefn {Built-in Function} {} make_absolute_filename (@var{file})\n\
00865 Return the full name of @var{file}, relative to the current directory.\n\
00866 @seealso{is_absolute_filename, is_rooted_relative_filename, isdir}\n\
00867 @end deftypefn")
00868 {
00869 octave_value retval = std::string ();
00870
00871 if (args.length () == 1)
00872 {
00873 std::string nm = args(0).string_value ();
00874
00875 if (! error_state)
00876 retval = octave_env::make_absolute (nm);
00877 else
00878 error ("make_absolute_filename: FILE argument must be a file name");
00879 }
00880 else
00881 print_usage ();
00882
00883 return retval;
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893 DEFUN (find_dir_in_path, args, ,
00894 "-*- texinfo -*-\n\
00895 @deftypefn {Built-in Function} {} find_dir_in_path (@var{dir})\n\
00896 @deftypefnx {Built-in Function} {} find_dir_in_path (@var{dir}, \"all\")\n\
00897 Return the full name of the path element matching @var{dir}. The\n\
00898 match is performed at the end of each path element. For example, if\n\
00899 @var{dir} is @code{\"foo/bar\"}, it matches the path element\n\
00900 @code{\"/some/dir/foo/bar\"}, but not @code{\"/some/dir/foo/bar/baz\"}\n\
00901 or @code{\"/some/dir/allfoo/bar\"}.\n\
00902 \n\
00903 The second argument is optional. If it is supplied, return a cell array\n\
00904 containing all name matches rather than just the first.\n\
00905 @end deftypefn")
00906 {
00907 octave_value retval = std::string ();
00908
00909 int nargin = args.length ();
00910
00911 std::string dir;
00912
00913 if (nargin == 1 || nargin == 2)
00914 {
00915 dir = args(0).string_value ();
00916
00917 if (! error_state)
00918 {
00919 if (nargin == 1)
00920 retval = load_path::find_dir (dir);
00921 else if (nargin == 2)
00922 retval = Cell (load_path::find_matching_dirs (dir));
00923 }
00924 else
00925 error ("find_dir_in_path: DIR must be a directory name");
00926 }
00927 else
00928 print_usage ();
00929
00930 return retval;
00931 }
00932
00933
00934
00935
00936
00937
00938
00939
00940 DEFUNX ("errno", Ferrno, args, ,
00941 "-*- texinfo -*-\n\
00942 @deftypefn {Built-in Function} {@var{err} =} errno ()\n\
00943 @deftypefnx {Built-in Function} {@var{err} =} errno (@var{val})\n\
00944 @deftypefnx {Built-in Function} {@var{err} =} errno (@var{name})\n\
00945 Return the current value of the system-dependent variable errno,\n\
00946 set its value to @var{val} and return the previous value, or return\n\
00947 the named error code given @var{name} as a character string, or -1\n\
00948 if @var{name} is not found.\n\
00949 @end deftypefn")
00950 {
00951 octave_value retval;
00952
00953 int nargin = args.length ();
00954
00955 if (nargin == 1)
00956 {
00957 if (args(0).is_string ())
00958 {
00959 std::string nm = args(0).string_value ();
00960
00961 if (! error_state)
00962 retval = octave_errno::lookup (nm);
00963 else
00964 error ("errno: expecting character string argument");
00965 }
00966 else
00967 {
00968 int val = args(0).int_value ();
00969
00970 if (! error_state)
00971 retval = octave_errno::set (val);
00972 else
00973 error ("errno: expecting integer argument");
00974 }
00975 }
00976 else if (nargin == 0)
00977 retval = octave_errno::get ();
00978 else
00979 print_usage ();
00980
00981 return retval;
00982 }
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999 DEFUN (errno_list, args, ,
01000 "-*- texinfo -*-\n\
01001 @deftypefn {Built-in Function} {} errno_list ()\n\
01002 Return a structure containing the system-dependent errno values.\n\
01003 @end deftypefn")
01004 {
01005 octave_value retval;
01006
01007 if (args.length () == 0)
01008 retval = octave_errno::list ();
01009 else
01010 print_usage ();
01011
01012 return retval;
01013 }
01014
01015
01016
01017
01018
01019
01020
01021 static void
01022 check_dimensions (octave_idx_type& nr, octave_idx_type& nc, const char *warnfor)
01023 {
01024 if (nr < 0 || nc < 0)
01025 {
01026 warning_with_id ("Octave:neg-dim-as-zero",
01027 "%s: converting negative dimension to zero", warnfor);
01028
01029 nr = (nr < 0) ? 0 : nr;
01030 nc = (nc < 0) ? 0 : nc;
01031 }
01032 }
01033
01034 void
01035 check_dimensions (dim_vector& dim, const char *warnfor)
01036 {
01037 bool neg = false;
01038
01039 for (int i = 0; i < dim.length (); i++)
01040 {
01041 if (dim(i) < 0)
01042 {
01043 dim(i) = 0;
01044 neg = true;
01045 }
01046 }
01047
01048 if (neg)
01049 warning_with_id ("Octave:neg-dim-as-zero",
01050 "%s: converting negative dimension to zero", warnfor);
01051 }
01052
01053
01054 void
01055 get_dimensions (const octave_value& a, const char *warn_for,
01056 dim_vector& dim)
01057 {
01058 if (a.is_scalar_type ())
01059 {
01060 dim.resize (2);
01061 dim(0) = a.int_value ();
01062 dim(1) = dim(0);
01063 }
01064 else
01065 {
01066 octave_idx_type nr = a.rows ();
01067 octave_idx_type nc = a.columns ();
01068
01069 if (nr == 1 || nc == 1)
01070 {
01071 Array<double> v = a.vector_value ();
01072
01073 if (error_state)
01074 return;
01075
01076 octave_idx_type n = v.length ();
01077 dim.resize (n);
01078 for (octave_idx_type i = 0; i < n; i++)
01079 dim(i) = static_cast<int> (fix (v(i)));
01080 }
01081 else
01082 error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
01083 }
01084
01085 if (! error_state)
01086 check_dimensions (dim, warn_for);
01087 }
01088
01089
01090 void
01091 get_dimensions (const octave_value& a, const char *warn_for,
01092 octave_idx_type& nr, octave_idx_type& nc)
01093 {
01094 if (a.is_scalar_type ())
01095 {
01096 nr = nc = a.int_value ();
01097 }
01098 else
01099 {
01100 nr = a.rows ();
01101 nc = a.columns ();
01102
01103 if ((nr == 1 && nc == 2) || (nr == 2 && nc == 1))
01104 {
01105 Array<double> v = a.vector_value ();
01106
01107 if (error_state)
01108 return;
01109
01110 nr = static_cast<octave_idx_type> (fix (v (0)));
01111 nc = static_cast<octave_idx_type> (fix (v (1)));
01112 }
01113 else
01114 error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
01115 }
01116
01117 if (! error_state)
01118 check_dimensions (nr, nc, warn_for);
01119 }
01120
01121 void
01122 get_dimensions (const octave_value& a, const octave_value& b,
01123 const char *warn_for, octave_idx_type& nr, octave_idx_type& nc)
01124 {
01125 nr = a.is_empty () ? 0 : a.int_value ();
01126 nc = b.is_empty () ? 0 : b.int_value ();
01127
01128 if (error_state)
01129 error ("%s: expecting two scalar arguments", warn_for);
01130 else
01131 check_dimensions (nr, nc, warn_for);
01132 }
01133
01134 octave_idx_type
01135 dims_to_numel (const dim_vector& dims, const octave_value_list& idx)
01136 {
01137 octave_idx_type retval;
01138
01139 octave_idx_type len = idx.length ();
01140
01141 if (len == 0)
01142 retval = dims.numel ();
01143 else
01144 {
01145 const dim_vector dv = dims.redim (len);
01146 retval = 1;
01147 for (octave_idx_type i = 0; i < len; i++)
01148 {
01149 octave_value idxi = idx(i);
01150 if (idxi.is_magic_colon ())
01151 retval *= dv(i);
01152 else if (idxi.is_numeric_type ())
01153 retval *= idxi.numel ();
01154 else
01155 {
01156 idx_vector jdx = idxi.index_vector ();
01157 if (error_state)
01158 break;
01159 retval *= jdx.length (dv(i));
01160 }
01161 }
01162 }
01163
01164 return retval;
01165 }
01166
01167 Matrix
01168 identity_matrix (octave_idx_type nr, octave_idx_type nc)
01169 {
01170 Matrix m (nr, nc, 0.0);
01171
01172 if (nr > 0 && nc > 0)
01173 {
01174 octave_idx_type n = std::min (nr, nc);
01175
01176 for (octave_idx_type i = 0; i < n; i++)
01177 m (i, i) = 1.0;
01178 }
01179
01180 return m;
01181 }
01182
01183 FloatMatrix
01184 float_identity_matrix (octave_idx_type nr, octave_idx_type nc)
01185 {
01186 FloatMatrix m (nr, nc, 0.0);
01187
01188 if (nr > 0 && nc > 0)
01189 {
01190 octave_idx_type n = std::min (nr, nc);
01191
01192 for (octave_idx_type i = 0; i < n; i++)
01193 m (i, i) = 1.0;
01194 }
01195
01196 return m;
01197 }
01198
01199 size_t
01200 octave_format (std::ostream& os, const char *fmt, ...)
01201 {
01202 size_t retval;
01203
01204 va_list args;
01205 va_start (args, fmt);
01206
01207 retval = octave_vformat (os, fmt, args);
01208
01209 va_end (args);
01210
01211 return retval;
01212 }
01213
01214 size_t
01215 octave_vformat (std::ostream& os, const char *fmt, va_list args)
01216 {
01217 std::string s = octave_vasprintf (fmt, args);
01218
01219 os << s;
01220
01221 return s.length ();
01222 }
01223
01224 std::string
01225 octave_vasprintf (const char *fmt, va_list args)
01226 {
01227 std::string retval;
01228
01229 char *result;
01230
01231 int status = gnulib::vasprintf (&result, fmt, args);
01232
01233 if (status >= 0)
01234 {
01235 retval = result;
01236 ::free (result);
01237 }
01238
01239 return retval;
01240 }
01241
01242 std::string
01243 octave_asprintf (const char *fmt, ...)
01244 {
01245 std::string retval;
01246
01247 va_list args;
01248 va_start (args, fmt);
01249
01250 retval = octave_vasprintf (fmt, args);
01251
01252 va_end (args);
01253
01254 return retval;
01255 }
01256
01257 void
01258 octave_sleep (double seconds)
01259 {
01260 if (seconds > 0)
01261 {
01262 double t;
01263
01264 unsigned int usec
01265 = static_cast<unsigned int> (modf (seconds, &t) * 1000000);
01266
01267 unsigned int sec
01268 = (t > UINT_MAX) ? UINT_MAX : static_cast<unsigned int> (t);
01269
01270
01271
01272 octave_sleep (sec);
01273 octave_usleep (usec);
01274
01275 octave_quit ();
01276 }
01277 }
01278
01279 DEFUN (isindex, args, ,
01280 "-*- texinfo -*-\n\
01281 @deftypefn {Built-in Function} {} isindex (@var{ind})\n\
01282 @deftypefnx {Built-in Function} {} isindex (@var{ind}, @var{n})\n\
01283 Return true if @var{ind} is a valid index. Valid indices are\n\
01284 either positive integers (although possibly of real data type), or logical\n\
01285 arrays. If present, @var{n} specifies the maximum extent of the dimension\n\
01286 to be indexed. When possible the internal result is cached so that\n\
01287 subsequent indexing using @var{ind} will not perform the check again.\n\
01288 @end deftypefn")
01289 {
01290 octave_value retval;
01291 int nargin = args.length ();
01292 octave_idx_type n = 0;
01293
01294 if (nargin == 2)
01295 n = args(1).idx_type_value ();
01296 else if (nargin != 1)
01297 print_usage ();
01298
01299 if (! error_state)
01300 {
01301 unwind_protect frame;
01302
01303 frame.protect_var (Vallow_noninteger_range_as_index);
01304 Vallow_noninteger_range_as_index = false;
01305
01306 frame.protect_var (error_state);
01307
01308 frame.protect_var (discard_error_messages);
01309 discard_error_messages = true;
01310
01311 try
01312 {
01313 idx_vector idx = args(0).index_vector ();
01314 if (! error_state)
01315 {
01316 if (nargin == 2)
01317 retval = idx.extent (n) <= n;
01318 else
01319 retval = true;
01320 }
01321 else
01322 retval = false;
01323 }
01324 catch (octave_execution_exception)
01325 {
01326 retval = false;
01327 }
01328 }
01329
01330 return retval;
01331 }
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341 octave_value_list
01342 do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
01343 const char *fun_name, const octave_value_list& args,
01344 int nargout)
01345 {
01346 octave_value_list new_args = args, retval;
01347 int nargin = args.length ();
01348 OCTAVE_LOCAL_BUFFER (bool, iscell, nargin);
01349 OCTAVE_LOCAL_BUFFER (Cell, cells, nargin);
01350 OCTAVE_LOCAL_BUFFER (Cell, rcells, nargout);
01351
01352 const Cell *ccells = cells;
01353
01354 octave_idx_type numel = 1;
01355 dim_vector dims (1, 1);
01356
01357 for (int i = 0; i < nargin; i++)
01358 {
01359 octave_value arg = new_args(i);
01360 iscell[i] = arg.is_cell ();
01361 if (iscell[i])
01362 {
01363 cells[i] = arg.cell_value ();
01364 octave_idx_type n = ccells[i].numel ();
01365 if (n == 1)
01366 {
01367 iscell[i] = false;
01368 new_args(i) = ccells[i](0);
01369 }
01370 else if (numel == 1)
01371 {
01372 numel = n;
01373 dims = ccells[i].dims ();
01374 }
01375 else if (dims != ccells[i].dims ())
01376 {
01377 error ("%s: cell arguments must have matching sizes", fun_name);
01378 break;
01379 }
01380 }
01381 }
01382
01383 if (! error_state)
01384 {
01385 for (int i = 0; i < nargout; i++)
01386 rcells[i].clear (dims);
01387
01388 for (octave_idx_type j = 0; j < numel; j++)
01389 {
01390 for (int i = 0; i < nargin; i++)
01391 if (iscell[i])
01392 new_args(i) = ccells[i](j);
01393
01394 octave_quit ();
01395
01396 const octave_value_list tmp = fun (new_args, nargout);
01397
01398 if (tmp.length () < nargout)
01399 {
01400 error ("%s: do_simple_cellfun: internal error", fun_name);
01401 break;
01402 }
01403 else
01404 {
01405 for (int i = 0; i < nargout; i++)
01406 rcells[i](j) = tmp(i);
01407 }
01408 }
01409 }
01410
01411 if (! error_state)
01412 {
01413 retval.resize (nargout);
01414 for (int i = 0; i < nargout; i++)
01415 retval(i) = rcells[i];
01416 }
01417
01418 return retval;
01419 }
01420
01421 octave_value
01422 do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
01423 const char *fun_name, const octave_value_list& args)
01424 {
01425 octave_value retval;
01426 const octave_value_list tmp = do_simple_cellfun (fun, fun_name, args, 1);
01427 if (tmp.length () > 0)
01428 retval = tmp(0);
01429
01430 return retval;
01431 }