changelog shortlog tags changeset files revisions annotate raw

src/utils.cc

changeset 9846: 1d90fc211872
parent:8e345f2fe4d6
author: John W. Eaton <jwe@octave.org>
date: Sat Nov 21 21:44:51 2009 -0500 (21 hours ago)
permissions: -rw-r--r--
description: configure.ac: report freetype, fontconfig, and fltk cflags and libs info
1/*
2
3Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
4 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 John W. Eaton
5
6This file is part of Octave.
7
8Octave is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13Octave is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with Octave; see the file COPYING. If not, see
20<http://www.gnu.org/licenses/>.
21
22*/
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <cerrno>
29#include <climits>
30#include <cstring>
31
32#include <fstream>
33#include <iostream>
34#include <string>
35
36#ifdef HAVE_UNISTD_H
37#ifdef HAVE_SYS_TYPES_H
38#include <sys/types.h>
39#endif
40#include <unistd.h>
41#endif
42
43#include "quit.h"
44
45#include "dir-ops.h"
46#include "file-ops.h"
47#include "file-stat.h"
48#include "lo-mappers.h"
49#include "oct-cmplx.h"
50#include "oct-env.h"
51#include "pathsearch.h"
52#include "str-vec.h"
53
54#include "Cell.h"
55#include <defaults.h>
56#include "defun.h"
57#include "dirfns.h"
58#include "error.h"
59#include "gripes.h"
60#include "input.h"
61#include "load-path.h"
62#include "oct-errno.h"
63#include "oct-hist.h"
64#include "oct-obj.h"
65#include "pager.h"
66#include "sysdep.h"
67#include "toplev.h"
68#include "unwind-prot.h"
69#include "utils.h"
70#include "variables.h"
71
72// Return TRUE if S is a valid identifier.
73
74bool
75valid_identifier (const char *s)
76{
77 if (! s || ! (isalpha (*s) || *s == '_' || *s == '$'))
78 return false;
79
80 while (*++s != '\0')
81 if (! (isalnum (*s) || *s == '_' || *s == '$'))
82 return false;
83
84 return true;
85}
86
87bool
88valid_identifier (const std::string& s)
89{
90 return valid_identifier (s.c_str ());
91}
92
93DEFUN (isvarname, args, ,
94 "-*- texinfo -*-\n\
95@deftypefn {Built-in Function} {} isvarname (@var{name})\n\
96Return true if @var{name} is a valid variable name\n\
97@end deftypefn")
98{
99 octave_value retval;
100
101 int argc = args.length () + 1;
102
103 string_vector argv = args.make_argv ("isvarname");
104
105 if (error_state)
106 return retval;
107
108 if (argc == 2)
109 retval = valid_identifier (argv[1]);
110 else
111 print_usage ();
112
113 return retval;
114}
115
116// Return TRUE if F and G are both names for the same file.
117
118bool
119same_file (const std::string& f, const std::string& g)
120{
121 return same_file_internal (f, g);
122}
123
124int
125almost_match (const std::string& std, const std::string& s, int min_match_len,
126 int case_sens)
127{
128 int stdlen = std.length ();
129 int slen = s.length ();
130
131 return (slen <= stdlen
132 && slen >= min_match_len
133 && (case_sens
134 ? (strncmp (std.c_str (), s.c_str (), slen) == 0)
135 : (octave_strncasecmp (std.c_str (), s.c_str (), slen) == 0)));
136}
137
138// Ugh.
139
140int
141keyword_almost_match (const char * const *std, int *min_len, const std::string& s,
142 int min_toks_to_match, int max_toks)
143{
144 int status = 0;
145 int tok_count = 0;
146 int toks_matched = 0;
147
148 if (s.empty () || max_toks < 1)
149 return status;
150
151 char *kw = strsave (s.c_str ());
152
153 char *t = kw;
154 while (*t != '\0')
155 {
156 if (*t == '\t')
157 *t = ' ';
158 t++;
159 }
160
161 char *beg = kw;
162 while (*beg == ' ')
163 beg++;
164
165 if (*beg == '\0')
166 return status;
167
168
169 const char **to_match = new const char * [max_toks + 1];
170 const char * const *s1 = std;
171 const char **s2 = to_match;
172
173 if (! s1 || ! s2)
174 goto done;
175
176 s2[tok_count] = beg;
177 char *end;
178 while ((end = strchr (beg, ' ')) != 0)
179 {
180 *end = '\0';
181 beg = end + 1;
182
183 while (*beg == ' ')
184 beg++;
185
186 if (*beg == '\0')
187 break;
188
189 tok_count++;
190 if (tok_count >= max_toks)
191 goto done;
192
193 s2[tok_count] = beg;
194 }
195 s2[tok_count+1] = 0;
196
197 s2 = to_match;
198
199 for (;;)
200 {
201 if (! almost_match (*s1, *s2, min_len[toks_matched], 0))
202 goto done;
203
204 toks_matched++;
205
206 s1++;
207 s2++;
208
209 if (! *s2)
210 {
211 status = (toks_matched >= min_toks_to_match);
212 goto done;
213 }
214
215 if (! *s1)
216 goto done;
217 }
218
219 done:
220
221 delete [] kw;
222 delete [] to_match;
223
224 return status;
225}
226
227// Return non-zero if either NR or NC is zero. Return -1 if this
228// should be considered fatal; return 1 if this is ok.
229
230int
231empty_arg (const char * /* name */, octave_idx_type nr, octave_idx_type nc)
232{
233 return (nr == 0 || nc == 0);
234}
235
236// See if the given file is in the path.
237
238std::string
239search_path_for_file (const std::string& path, const string_vector& names)
240{
241 dir_path p (path);
242
243 return octave_env::make_absolute (p.find_first_of (names),
244 octave_env::getcwd ());
245}
246
247// Find all locations of the given file in the path.
248
249string_vector
250search_path_for_all_files (const std::string& path, const string_vector& names)
251{
252 dir_path p (path);
253
254 string_vector sv = p.find_all_first_of (names);
255
256 octave_idx_type len = sv.length ();
257
258 for (octave_idx_type i = 0; i < len; i++)
259 sv[i] = octave_env::make_absolute (sv[i], octave_env::getcwd ());
260
261 return sv;
262}
263
264static string_vector
265make_absolute (const string_vector& sv)
266{
267 octave_idx_type len = sv.length ();
268
269 string_vector retval (len);
270
271 for (octave_idx_type i = 0; i < len; i++)
272 retval[i] = octave_env::make_absolute (sv[i], octave_env::getcwd ());
273
274 return retval;
275}
276
277DEFUN (file_in_loadpath, args, ,
278 "-*- texinfo -*-\n\
279@deftypefn {Built-in Function} {} file_in_loadpath (@var{file})\n\
280@deftypefnx {Built-in Function} {} file_in_loadpath (@var{file}, \"all\")\n\
281\n\
282Return the absolute name of @var{file} if it can be found in\n\
283the list of directories specified by @code{path}.\n\
284If no file is found, return an empty matrix.\n\
285\n\
286If the first argument is a cell array of strings, search each\n\
287directory of the loadpath for element of the cell array and return\n\
288the first that matches.\n\
289\n\
290If the second optional argument @code{\"all\"} is supplied, return\n\
291a cell array containing the list of all files that have the same\n\
292name in the path. If no files are found, return an empty cell array.\n\
293@seealso{file_in_path, path}\n\
294@end deftypefn")
295{
296 octave_value retval;
297
298 int nargin = args.length ();
299
300 if (nargin == 1 || nargin == 2)
301 {
302 string_vector names = args(0).all_strings ();
303
304 if (! error_state && names.length () > 0)
305 {
306 if (nargin == 1)
307 {
308 std::string fname = octave_env::make_absolute
309 (load_path::find_first_of (names), octave_env::getcwd ());
310
311 if (fname.empty ())
312 retval = Matrix ();
313 else
314 retval = fname;
315 }
316 else if (nargin == 2)
317 {
318 std::string opt = args(1).string_value ();
319
320 if (! error_state && opt == "all")
321 retval = Cell (make_absolute (load_path::find_all_first_of (names)));
322 else
323 error ("file_in_loadpath: invalid option");
324 }
325 }
326 else
327 error ("file_in_loadpath: expecting string as first argument");
328 }
329 else
330 print_usage ();
331
332 return retval;
333}
334
335DEFUN (file_in_path, args, ,
336 "-*- texinfo -*-\n\
337@deftypefn {Built-in Function} {} file_in_path (@var{path}, @var{file})\n\
338@deftypefnx {Built-in Function} {} file_in_path (@var{path}, @var{file}, \"all\")\n\
339Return the absolute name of @var{file} if it can be found in\n\
340@var{path}. The value of @var{path} should be a colon-separated list of\n\
341directories in the format described for @code{path}. If no file\n\
342is found, return an empty matrix. For example,\n\
343\n\
344@example\n\
345@group\n\
346file_in_path (EXEC_PATH, \"sh\")\n\
347 @result{} \"/bin/sh\"\n\
348@end group\n\
349@end example\n\
350\n\
351If the second argument is a cell array of strings, search each\n\
352directory of the path for element of the cell array and return\n\
353the first that matches.\n\
354\n\
355If the third optional argument @code{\"all\"} is supplied, return\n\
356a cell array containing the list of all files that have the same\n\
357name in the path. If no files are found, return an empty cell array.\n\
358@seealso{file_in_loadpath}\n\
359@end deftypefn")
360{
361 octave_value retval;
362
363 int nargin = args.length ();
364
365 if (nargin == 2 || nargin == 3)
366 {
367 std::string path = args(0).string_value ();
368
369 if (! error_state)
370 {
371 string_vector names = args(1).all_strings ();
372
373 if (! error_state && names.length () > 0)
374 {
375 if (nargin == 2)
376 {
377 std::string fname = search_path_for_file (path, names);
378
379 if (fname.empty ())
380 retval = Matrix ();
381 else
382 retval = fname;
383 }
384 else if (nargin == 3)
385 {
386 std::string opt = args(2).string_value ();
387
388 if (! error_state && opt == "all")
389 retval = Cell (make_absolute (search_path_for_all_files (path, names)));
390 else
391 error ("file_in_path: invalid option");
392 }
393 }
394 else
395 error ("file_in_path: expecting string as second argument");
396 }
397 else
398 error ("file_in_path: expecting string as first argument");
399 }
400 else
401 print_usage ();
402
403 return retval;
404}
405
406std::string
407file_in_path (const std::string& name, const std::string& suffix)
408{
409 std::string nm = name;
410
411 if (! suffix.empty ())
412 nm.append (suffix);
413
414 return octave_env::make_absolute
415 (load_path::find_file (nm), octave_env::getcwd ());
416}
417
418// See if there is an function file in the path. If so, return the
419// full path to the file.
420
421std::string
422fcn_file_in_path (const std::string& name)
423{
424 std::string retval;
425
426 int len = name.length ();
427
428 if (len > 0)
429 {
430 if (octave_env::absolute_pathname (name))
431 {
432 file_stat fs (name);
433
434 if (fs.exists ())
435 retval = name;
436 }
437 else if (len > 2 && name [len - 2] == '.' && name [len - 1] == 'm')
438 retval = load_path::find_fcn_file (name.substr (0, len-2));
439 else
440 {
441 std::string fname = name;
442 size_t pos = name.find_first_of (Vfilemarker);
443 if (pos != std::string::npos)
444 fname = name.substr (0, pos);
445
446 retval = load_path::find_fcn_file (fname);
447 }
448 }
449
450 return retval;
451}
452
453// See if there is a directory called "name" in the path and if it
454// contains a Contents.m file return the full path to this file.
455
456std::string
457contents_file_in_path (const std::string& dir)
458{
459 std::string retval;
460
461 if (dir.length () > 0)
462 {
463 std::string tcontents = file_ops::concat (load_path::find_dir (dir),
464 std::string ("Contents.m"));
465
466 file_stat fs (tcontents);
467
468 if (fs.exists ())
469 retval = octave_env::make_absolute (tcontents, octave_env::getcwd ());
470 }
471
472 return retval;
473}
474
475// See if there is a .oct file in the path. If so, return the
476// full path to the file.
477
478std::string
479oct_file_in_path (const std::string& name)
480{
481 std::string retval;
482
483 int len = name.length ();
484
485 if (len > 0)
486 {
487 if (octave_env::absolute_pathname (name))
488 {
489 file_stat fs (name);
490
491 if (fs.exists ())
492 retval = name;
493 }
494 else if (len > 4 && name [len - 4] == '.' && name [len - 3] == 'o'
495 && name [len - 2] == 'c' && name [len - 1] == 't')
496 retval = load_path::find_oct_file (name.substr (0, len-4));
497 else
498 retval = load_path::find_oct_file (name);
499 }
500
501 return retval;
502}
503
504// See if there is a .mex file in the path. If so, return the
505// full path to the file.
506
507std::string
508mex_file_in_path (const std::string& name)
509{
510 std::string retval;
511
512 int len = name.length ();
513
514 if (len > 0)
515 {
516 if (octave_env::absolute_pathname (name))
517 {
518 file_stat fs (name);
519
520 if (fs.exists ())
521 retval = name;
522 }
523 else if (len > 4 && name [len - 4] == '.' && name [len - 3] == 'm'
524 && name [len - 2] == 'e' && name [len - 1] == 'x')
525 retval = load_path::find_mex_file (name.substr (0, len-4));
526 else
527 retval = load_path::find_mex_file (name);
528 }
529
530 return retval;
531}
532
533// Replace backslash escapes in a string with the real values.
534
535std::string
536do_string_escapes (const std::string& s)
537{
538 std::string retval;
539
540 size_t i = 0;
541 size_t j = 0;
542 size_t len = s.length ();
543
544 retval.resize (len);
545
546 while (j < len)
547 {
548 if (s[j] == '\\' && j+1 < len)
549 {
550 switch (s[++j])
551 {
552 case '0':
553 retval[i] = '\0';
554 break;
555
556 case 'a':
557 retval[i] = '\a';
558 break;
559
560 case 'b': // backspace
561 retval[i] = '\b';
562 break;
563
564 case 'f': // formfeed
565 retval[i] = '\f';
566 break;
567
568 case 'n': // newline
569 retval[i] = '\n';
570 break;
571
572 case 'r': // carriage return
573 retval[i] = '\r';
574 break;
575
576 case 't': // horizontal tab
577 retval[i] = '\t';
578 break;
579
580 case 'v': // vertical tab
581 retval[i] = '\v';
582 break;
583
584 case '\\': // backslash
585 retval[i] = '\\';
586 break;
587
588 case '\'': // quote
589 retval[i] = '\'';
590 break;
591
592 case '"': // double quote
593 retval[i] = '"';
594 break;
595
596 default:
597 warning ("unrecognized escape sequence `\\%c' --\
598 converting to `%c'", s[j], s[j]);
599 retval[i] = s[j];
600 break;
601 }
602 }
603 else
604 {
605 retval[i] = s[j];
606 }
607
608 i++;
609 j++;
610 }
611
612 retval.resize (i);
613
614 return retval;
615}
616
617DEFUN (do_string_escapes, args, ,
618 "-*- texinfo -*-\n\
619@deftypefn {Built-in Function} {} do_string_escapes (@var{string})\n\
620Convert special characters in @var{string} to their escaped forms.\n\
621@end deftypefn")
622{
623 octave_value retval;
624
625 int nargin = args.length ();
626
627 if (nargin == 1)
628 {
629 if (args(0).is_string ())
630 retval = do_string_escapes (args(0).string_value ());
631 else
632 error ("do_string_escapes: argument must be a string");
633 }
634 else
635 print_usage ();
636
637 return retval;
638}
639
640const char *
641undo_string_escape (char c)
642{
643 if (! c)
644 return "";
645
646 switch (c)
647 {
648 case '\0':
649 return "\\0";
650
651 case '\a':
652 return "\\a";
653
654 case '\b': // backspace
655 return "\\b";
656
657 case '\f': // formfeed
658 return "\\f";
659
660 case '\n': // newline
661 return "\\n";
662
663 case '\r': // carriage return
664 return "\\r";
665
666 case '\t': // horizontal tab
667 return "\\t";
668
669 case '\v': // vertical tab
670 return "\\v";
671
672 case '\\': // backslash
673 return "\\\\";
674
675 case '"': // double quote
676 return "\\\"";
677
678 default:
679 {
680 static char retval[2];
681 retval[0] = c;
682 retval[1] = '\0';
683 return retval;
684 }
685 }
686}
687
688std::string
689undo_string_escapes (const std::string& s)
690{
691 std::string retval;
692
693 for (size_t i = 0; i < s.length (); i++)
694 retval.append (undo_string_escape (s[i]));
695
696 return retval;
697}
698
699DEFUN (undo_string_escapes, args, ,
700 "-*- texinfo -*-\n\
701@deftypefn {Built-in Function} {} undo_string_escapes (@var{s})\n\
702Converts special characters in strings back to their escaped forms. For\n\
703example, the expression\n\
704\n\
705@example\n\
706bell = \"\\a\";\n\
707@end example\n\
708\n\
709@noindent\n\
710assigns the value of the alert character (control-g, ASCII code 7) to\n\
711the string variable @code{bell}. If this string is printed, the\n\
712system will ring the terminal bell (if it is possible). This is\n\
713normally the desired outcome. However, sometimes it is useful to be\n\
714able to print the original representation of the string, with the\n\
715special characters replaced by their escape sequences. For example,\n\
716\n\
717@example\n\
718@group\n\
719octave:13> undo_string_escapes (bell)\n\
720ans = \\a\n\
721@end group\n\
722@end example\n\
723\n\
724@noindent\n\
725replaces the unprintable alert character with its printable\n\
726representation.\n\
727@end deftypefn")
728{
729 octave_value retval;
730
731 int nargin = args.length ();
732
733 if (nargin == 1)
734 {
735 if (args(0).is_string ())
736 retval = undo_string_escapes (args(0).string_value ());
737 else
738 error ("undo_string_escapes: argument must be a string");
739 }
740 else
741 print_usage ();
742
743 return retval;
744}
745
746DEFUN (is_absolute_filename, args, ,
747 "-*- texinfo -*-\n\
748@deftypefn {Built-in Function} {} is_absolute_filename (@var{file})\n\
749Return true if @var{file} is an absolute filename.\n\
750@end deftypefn")
751{
752 octave_value retval = false;
753
754 if (args.length () == 1)
755 retval = (args(0).is_string ()
756 && octave_env::absolute_pathname (args(0).string_value ()));
757 else
758 print_usage ();
759
760 return retval;
761}
762
763DEFUN (is_rooted_relative_filename, args, ,
764 "-*- texinfo -*-\n\
765@deftypefn {Built-in Function} {} is_rooted_relative_filename (@var{file})\n\
766Return true if @var{file} is a rooted-relative filename.\n\
767@end deftypefn")
768{
769 octave_value retval = false;
770
771 if (args.length () == 1)
772 retval = (args(0).is_string ()
773 && octave_env::rooted_relative_pathname (args(0).string_value ()));
774 else
775 print_usage ();
776
777 return retval;
778}
779
780DEFUN (make_absolute_filename, args, ,
781 "-*- texinfo -*-\n\
782@deftypefn {Built-in Function} {} make_absolute_filename (@var{file})\n\
783Return the full name of @var{file}, relative to the current directory.\n\
784@end deftypefn")
785{
786 octave_value retval = std::string ();
787
788 if (args.length () == 1)
789 {
790 std::string nm = args(0).string_value ();
791
792 if (! error_state)
793 retval = octave_env::make_absolute (nm, octave_env::getcwd ());
794 else
795 error ("make_absolute_filename: expecting argument to be a file name");
796 }
797 else
798 print_usage ();
799
800 return retval;
801}
802
803DEFUN (find_dir_in_path, args, ,
804 "-*- texinfo -*-\n\
805@deftypefn {Built-in Function} {} find_dir_in_path (@var{dir}, \"all\")\n\
806Return the full name of the path element matching @var{dir}. The\n\
807match is performed at the end of each path element. For example, if\n\
808@var{dir} is @code{\"foo/bar\"}, it matches the path element\n\
809@code{\"/some/dir/foo/bar\"}, but not @code{\"/some/dir/foo/bar/baz\"}\n\
810or @code{\"/some/dir/allfoo/bar\"}.\n\
811\n\
812The second argument is optional. If it is supplied, return a cell array\n\
813containing all the directory names that match.\n\
814@end deftypefn")
815{
816 octave_value retval = std::string ();
817
818 int nargin = args.length ();
819
820 std::string dir;
821
822 if (nargin == 1 || nargin == 2)
823 {
824 dir = args(0).string_value ();
825
826 if (! error_state)
827 {
828 if (nargin == 1)
829 retval = load_path::find_dir (dir);
830 else if (nargin == 2)
831 retval = Cell (load_path::find_matching_dirs (dir));
832 }
833 else
834 error ("find_dir_in_path: expecting argument to be a directory name");
835 }
836 else
837 print_usage ();
838
839 return retval;
840}
841
842DEFUNX ("errno", Ferrno, args, ,
843 "-*- texinfo -*-\n\
844@deftypefn {Built-in Function} {@var{err} =} errno ()\n\
845@deftypefnx {Built-in Function} {@var{err} =} errno (@var{val})\n\
846@deftypefnx {Built-in Function} {@var{err} =} errno (@var{name})\n\
847Return the current value of the system-dependent variable errno,\n\
848set its value to @var{val} and return the previous value, or return\n\
849the named error code given @var{name} as a character string, or -1\n\
850if @var{name} is not found.\n\
851@end deftypefn")
852{
853 octave_value retval;
854
855 int nargin = args.length ();
856
857 if (nargin == 1)
858 {
859 if (args(0).is_string ())
860 {
861 std::string nm = args(0).string_value ();
862
863 if (! error_state)
864 retval = octave_errno::lookup (nm);
865 else
866 error ("errno: expecting character string argument");
867 }
868 else
869 {
870 int val = args(0).int_value ();
871
872 if (! error_state)
873 retval = octave_errno::set (val);
874 else
875 error ("errno: expecting integer argument");
876 }
877 }
878 else if (nargin == 0)
879 retval = octave_errno::get ();
880 else
881 print_usage ();
882
883 return retval;
884}
885
886DEFUN (errno_list, args, ,
887 "-*- texinfo -*-\n\
888@deftypefn {Built-in Function} {} errno_list ()\n\
889Return a structure containing the system-dependent errno values.\n\
890@end deftypefn")
891{
892 octave_value retval;
893
894 if (args.length () == 0)
895 retval = octave_errno::list ();
896 else
897 print_usage ();
898
899 return retval;
900}
901
902static void
903check_dimensions (octave_idx_type& nr, octave_idx_type& nc, const char *warnfor)
904{
905 if (nr < 0 || nc < 0)
906 {
907 warning_with_id ("Octave:neg-dim-as-zero",
908 "%s: converting negative dimension to zero", warnfor);
909
910 nr = (nr < 0) ? 0 : nr;
911 nc = (nc < 0) ? 0 : nc;
912 }
913}
914
915void
916check_dimensions (dim_vector& dim, const char *warnfor)
917{
918 bool neg = false;
919
920 for (int i = 0; i < dim.length (); i++)
921 {
922 if (dim(i) < 0)
923 {
924 dim(i) = 0;
925 neg = true;
926 }
927 }
928
929 if (neg)
930 warning_with_id ("Octave:neg-dim-as-zero",
931 "%s: converting negative dimension to zero", warnfor);
932}
933
934
935void
936get_dimensions (const octave_value& a, const char *warn_for,
937 dim_vector& dim)
938{
939 if (a.is_scalar_type ())
940 {
941 dim.resize (2);
942 dim(0) = a.int_value ();
943 dim(1) = dim(0);
944 }
945 else
946 {
947 octave_idx_type nr = a.rows ();
948 octave_idx_type nc = a.columns ();
949
950 if (nr == 1 || nc == 1)
951 {
952 Array<double> v = a.vector_value ();
953
954 if (error_state)
955 return;
956
957 octave_idx_type n = v.length ();
958 dim.resize (n);
959 for (octave_idx_type i = 0; i < n; i++)
960 dim(i) = static_cast<int> (fix (v(i)));
961 }
962 else
963 error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
964 }
965
966 if (! error_state)
967 check_dimensions (dim, warn_for); // May set error_state.
968}
969
970
971void
972get_dimensions (const octave_value& a, const char *warn_for,
973 octave_idx_type& nr, octave_idx_type& nc)
974{
975 if (a.is_scalar_type ())
976 {
977 nr = nc = a.int_value ();
978 }
979 else
980 {
981 nr = a.rows ();
982 nc = a.columns ();
983
984 if ((nr == 1 && nc == 2) || (nr == 2 && nc == 1))
985 {
986 Array<double> v = a.vector_value ();
987
988 if (error_state)
989 return;
990
991 nr = static_cast<octave_idx_type> (fix (v (0)));
992 nc = static_cast<octave_idx_type> (fix (v (1)));
993 }
994 else
995 error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
996 }
997
998 if (! error_state)
999 check_dimensions (nr, nc, warn_for); // May set error_state.
1000}
1001
1002void
1003get_dimensions (const octave_value& a, const octave_value& b,
1004 const char *warn_for, octave_idx_type& nr, octave_idx_type& nc)
1005{
1006 nr = a.is_empty () ? 0 : a.int_value ();
1007 nc = b.is_empty () ? 0 : b.int_value ();
1008
1009 if (error_state)
1010 error ("%s: expecting two scalar arguments", warn_for);
1011 else
1012 check_dimensions (nr, nc, warn_for); // May set error_state.
1013}
1014
1015octave_idx_type
1016dims_to_numel (const dim_vector& dims, const octave_value_list& idx)
1017{
1018 octave_idx_type retval;
1019
1020 octave_idx_type len = idx.length ();
1021
1022 if (len == 0)
1023 retval = dims.numel ();
1024 else
1025 {
1026 const dim_vector dv = dims.redim (len);
1027 retval = 1;
1028 for (octave_idx_type i = 0; i < len; i++)
1029 {
1030 octave_value idxi = idx(i);
1031 if (idxi.is_magic_colon ())
1032 retval *= dv(i);
1033 else if (idxi.is_numeric_type ())
1034 retval *= idxi.numel ();
1035 else
1036 {
1037 idx_vector jdx = idxi.index_vector ();
1038 if (error_state)
1039 break;
1040 retval *= jdx.length (dv(i));
1041 }
1042 }
1043 }
1044
1045 return retval;
1046}
1047
1048Matrix
1049identity_matrix (octave_idx_type nr, octave_idx_type nc)
1050{
1051 Matrix m (nr, nc, 0.0);
1052
1053 if (nr > 0 && nc > 0)
1054 {
1055 octave_idx_type n = std::min (nr, nc);
1056
1057 for (octave_idx_type i = 0; i < n; i++)
1058 m (i, i) = 1.0;
1059 }
1060
1061 return m;
1062}
1063
1064FloatMatrix
1065float_identity_matrix (octave_idx_type nr, octave_idx_type nc)
1066{
1067 FloatMatrix m (nr, nc, 0.0);
1068
1069 if (nr > 0 && nc > 0)
1070 {
1071 octave_idx_type n = std::min (nr, nc);
1072
1073 for (octave_idx_type i = 0; i < n; i++)
1074 m (i, i) = 1.0;
1075 }
1076
1077 return m;
1078}
1079
1080int
1081octave_format (std::ostream& os, const char *fmt, ...)
1082{
1083 int retval = -1;
1084
1085 va_list args;
1086 va_start (args, fmt);
1087
1088 retval = octave_vformat (os, fmt, args);
1089
1090 va_end (args);
1091
1092 return retval;
1093}
1094
1095int
1096octave_vformat (std::ostream& os, const char *fmt, va_list args)
1097{
1098 int retval = -1;
1099
1100#if defined (__GNUG__) && !CXX_ISO_COMPLIANT_LIBRARY
1101
1102 std::streambuf *sb = os.rdbuf ();
1103
1104 if (sb)
1105 {
1106 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1107
1108 retval = sb->vform (fmt, args);
1109
1110 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1111 }
1112
1113#else
1114
1115 char *s = octave_vsnprintf (fmt, args);
1116
1117 if (s)
1118 {
1119 os << s;
1120
1121 retval = strlen (s);
1122 }
1123
1124#endif
1125
1126 return retval;
1127}
1128
1129// We manage storage. User should not free it, and its contents are
1130// only valid until next call to vsnprintf.
1131
1132// Interrupts might happen if someone makes a call with something that
1133// will require a very large buffer. If we are interrupted in that
1134// case, we should make the buffer size smaller for the next call.
1135
1136#define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF \
1137 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1; \
1138 delete [] buf; \
1139 buf = 0; \
1140 size = initial_size; \
1141 octave_rethrow_exception (); \
1142 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2
1143
1144#if defined __GNUC__ && defined __va_copy
1145#define SAVE_ARGS(saved_args, args) __va_copy (saved_args, args)
1146#elif defined va_copy
1147#define SAVE_ARGS(saved_args, args) va_copy (saved_args, args)
1148#else
1149#define SAVE_ARGS(saved_args, args) saved_args = args
1150#endif
1151
1152char *
1153octave_vsnprintf (const char *fmt, va_list args)
1154{
1155 static const size_t initial_size = 100;
1156
1157 static size_t size = initial_size;
1158
1159 static char *buf = 0;
1160
1161#if defined (HAVE_C99_VSNPRINTF)
1162 size_t nchars = 0;
1163#else
1164 int nchars = 0;
1165#endif
1166
1167 if (! buf)
1168 buf = new char [size];
1169
1170 if (! buf)
1171 return 0;
1172
1173#if defined (HAVE_C99_VSNPRINTF)
1174
1175 // Note that the caller is responsible for calling va_end on args.
1176 // We will do it for saved_args.
1177
1178 va_list saved_args;
1179
1180 SAVE_ARGS (saved_args, args);
1181
1182 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF;
1183
1184 nchars = octave_raw_vsnprintf (buf, size, fmt, args);
1185
1186 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1187
1188 if (nchars >= size)
1189 {
1190 size = nchars + 1;
1191
1192 delete [] buf;
1193
1194 buf = new char [size];
1195
1196 if (buf)
1197 {
1198 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF;
1199
1200 octave_raw_vsnprintf (buf, size, fmt, saved_args);
1201
1202 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1203 }
1204 }
1205
1206 va_end (saved_args);
1207
1208#else
1209
1210 while (1)
1211 {
1212 va_list saved_args;
1213
1214 SAVE_ARGS (saved_args, args);
1215
1216 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF;
1217
1218 nchars = octave_raw_vsnprintf (buf, size, fmt, saved_args);
1219
1220 va_end (saved_args);
1221
1222 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1223
1224 if (nchars > -1 && nchars < size-1)
1225 return buf;
1226 else
1227 {
1228 delete [] buf;
1229
1230 size *= 2;
1231
1232 buf = new char [size];
1233
1234 if (! buf)
1235 return 0;
1236 }
1237 }
1238
1239#endif
1240
1241 return buf;
1242}
1243
1244char *
1245octave_snprintf (const char *fmt, ...)
1246{
1247 char *retval = 0;
1248
1249 va_list args;
1250 va_start (args, fmt);
1251
1252 retval = octave_vsnprintf (fmt, args);
1253
1254 va_end (args);
1255
1256 return retval;
1257}
1258
1259void
1260octave_sleep (double seconds)
1261{
1262 if (seconds > 0)
1263 {
1264 double t;
1265
1266 unsigned int usec
1267 = static_cast<unsigned int> (modf (seconds, &t) * 1000000);
1268
1269 unsigned int sec
1270 = (t > UINT_MAX) ? UINT_MAX : static_cast<unsigned int> (t);
1271
1272 // Versions of these functions that accept unsigned int args are
1273 // defined in cutils.c.
1274 octave_sleep (sec);
1275 octave_usleep (usec);
1276 }
1277}
1278
1279DEFUN (isindex, args, ,
1280 "-*- texinfo -*-\n\
1281@deftypefn {Built-in Function} {} isindex (@var{ind}, @var{n})\n\
1282Returns true if @var{ind} is a valid index. Valid indices can be\n\
1283either positive integers (though possibly real data), or logical arrays.\n\
1284If present, @var{n} specifies the extent of the dimension to be indexed.\n\
1285Note that, if possible, the internal conversion result is cached so that\n\
1286subsequent indexing will not perform the checking again.\n\
1287@end deftypefn")
1288{
1289 octave_value retval;
1290 int nargin = args.length ();
1291 octave_idx_type n = 0;
1292
1293 if (nargin == 2)
1294 n = args(1).idx_type_value ();
1295 else if (nargin != 1)
1296 print_usage ();
1297
1298 if (! error_state)
1299 {
1300 unwind_protect::frame_id_t uwp = unwind_protect::begin_frame ();
1301 unwind_protect::protect_var (error_state);
1302 unwind_protect::protect_var (discard_error_messages);
1303 discard_error_messages = true;
1304
1305 try
1306 {
1307 idx_vector idx = args(0).index_vector ();
1308 if (! error_state)
1309 {
1310 if (nargin == 2)
1311 retval = idx.extent (n) <= n;
1312 else
1313 retval = true;
1314 }
1315 else
1316 retval = false;
1317 }
1318 catch (octave_execution_exception)
1319 {
1320 retval = false;
1321 }
1322
1323 unwind_protect::run_frame (uwp);
1324 }
1325
1326 return retval;
1327}
1328
1329/*
1330;;; Local Variables: ***
1331;;; mode: C++ ***
1332;;; End: ***
1333*/