changelog shortlog tags changeset files revisions annotate raw

src/sysdep.cc

changeset 10289: 4b124317dc38
parent:0522a65bcd56
author: John W. Eaton <jwe@octave.org>
date: Tue Feb 09 20:58:55 2010 -0500 (49 minutes ago)
permissions: -rw-r--r--
description: base_properties::set_children: account for hidden children
1/*
2
3Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2002, 2003,
4 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 <cfloat>
29#include <cstddef>
30#include <cstdio>
31#include <cstdlib>
32#include <cstring>
33
34#include <iostream>
35#include <string>
36
37#include <sys/types.h>
38#include <unistd.h>
39
40#if defined (HAVE_TERMIOS_H)
41#include <termios.h>
42#elif defined (HAVE_TERMIO_H)
43#include <termio.h>
44#elif defined (HAVE_SGTTY_H)
45#include <sgtty.h>
46#endif
47
48#if defined (HAVE_CONIO_H)
49#include <conio.h>
50#endif
51
52#if defined (HAVE_SYS_IOCTL_H)
53#include <sys/ioctl.h>
54#endif
55
56#if defined (HAVE_FLOATINGPOINT_H)
57#include <floatingpoint.h>
58#endif
59
60#if defined (HAVE_IEEEFP_H)
61#include <ieeefp.h>
62#endif
63
64#include "cmd-edit.h"
65#include "file-ops.h"
66#include "lo-mappers.h"
67#include "lo-math.h"
68#include "mach-info.h"
69#include "oct-env.h"
70#include "quit.h"
71
72#include "Cell.h"
73#include "defun.h"
74#include "error.h"
75#include "input.h"
76#include "oct-obj.h"
77#include "ov.h"
78#include "pager.h"
79#include "parse.h"
80#include "sighandlers.h"
81#include "sysdep.h"
82#include "toplev.h"
83#include "utils.h"
84#include "file-stat.h"
85
86#ifndef STDIN_FILENO
87#define STDIN_FILENO 1
88#endif
89
90#if defined (__386BSD__) || defined (__FreeBSD__) || defined (__NetBSD__)
91static void
92BSD_init (void)
93{
94#if defined (HAVE_FLOATINGPOINT_H)
95 // Disable trapping on common exceptions.
96#ifndef FP_X_DNML
97#define FP_X_DNML 0
98#endif
99 fpsetmask (~(FP_X_OFL|FP_X_INV|FP_X_DZ|FP_X_DNML|FP_X_UFL|FP_X_IMP));
100#endif
101}
102#endif
103
104#if defined (__WIN32__) && ! defined (_POSIX_VERSION)
105static void
106w32_set_octave_home (void)
107{
108 int n = 1024;
109
110 std::string bin_dir (n, '\0');
111
112 while (true)
113 {
114 HMODULE hMod = GetModuleHandle ("octinterp");
115 int status = GetModuleFileName (hMod, &bin_dir[0], n);
116
117 if (status < n)
118 {
119 bin_dir.resize (status);
120 break;
121 }
122 else
123 {
124 n *= 2;
125 bin_dir.resize (n);
126 }
127 }
128
129 if (! bin_dir.empty ())
130 {
131 size_t pos = bin_dir.rfind ("\\bin\\");
132
133 if (pos != std::string::npos)
134 octave_env::putenv ("OCTAVE_HOME", bin_dir.substr (0, pos));
135 }
136}
137
138void
139w32_set_quiet_shutdown (void)
140{
141 // Let the user close the console window or shutdown without the
142 // pesky dialog.
143 //
144 // FIXME -- should this be user configurable?
145 SetProcessShutdownParameters (0x280, SHUTDOWN_NORETRY);
146}
147
148void
149MINGW_signal_cleanup (void)
150{
151 w32_set_quiet_shutdown ();
152
153 w32_raise_final ();
154}
155#endif
156
157#if defined (__MINGW32__)
158static void
159MINGW_init (void)
160{
161 w32_set_octave_home ();
162
163 // Init mutex to protect setjmp/longjmp and get main thread context
164 w32_sigint_init ();
165
166 w32_set_quiet_shutdown ();
167}
168#endif
169
170#if defined (_MSC_VER)
171static void
172MSVC_init (void)
173{
174 w32_set_octave_home ();
175
176 // Init mutex to protect setjmp/longjmp and get main thread context
177 w32_sigint_init ();
178
179 w32_set_quiet_shutdown ();
180}
181#endif
182
183
184// Return TRUE if FILE1 and FILE2 refer to the same (physical) file.
185
186bool
187same_file_internal (const std::string& file1, const std::string& file2)
188{
189#ifdef OCTAVE_USE_WINDOWS_API
190
191 bool retval = false;
192
193 // Windows native code
194 // Reference: http://msdn2.microsoft.com/en-us/library/aa363788.aspx
195
196 HANDLE hfile1 = CreateFile (file1.c_str (), 0, FILE_SHARE_READ, 0,
197 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
198
199 if (hfile1 != INVALID_HANDLE_VALUE)
200 {
201 HANDLE hfile2 = CreateFile (file2.c_str (), 0, FILE_SHARE_READ, 0,
202 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
203
204 if (hfile2 != INVALID_HANDLE_VALUE)
205 {
206 BY_HANDLE_FILE_INFORMATION hfi1;
207 BY_HANDLE_FILE_INFORMATION hfi2;
208
209 if (GetFileInformationByHandle (hfile1, &hfi1)
210 && GetFileInformationByHandle (hfile2, &hfi2))
211
212 retval = (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber
213 && hfi1.nFileIndexHigh == hfi2.nFileIndexHigh
214 && hfi1.nFileIndexLow == hfi2.nFileIndexLow);
215
216 CloseHandle (hfile2);
217 }
218
219 CloseHandle (hfile1);
220 }
221
222 return retval;
223
224#else
225
226 // POSIX Code
227
228 file_stat fs_file1 (file1);
229 file_stat fs_file2 (file2);
230
231 return (fs_file1 && fs_file2
232 && fs_file1.ino () == fs_file2.ino ()
233 && fs_file1.dev () == fs_file2.dev ());
234
235#endif
236}
237
238#if defined (__DECCXX)
239
240// These don't seem to be instantiated automatically...
241
242template std::istream&
243std::operator >> (std::istream&, std::complex<double>&);
244
245template std::string&
246std::string::append (const std::string&, size_t, size_t);
247
248#endif
249
250#if defined (NeXT)
251extern "C"
252{
253 typedef void (*_cplus_fcn_int) (int);
254 extern void (*malloc_error (_cplus_fcn_int)) (int);
255}
256
257static void
258malloc_handler (int code)
259{
260 if (code == 5)
261 warning ("hopefully recoverable malloc error: freeing wild pointer");
262 else
263 panic ("probably irrecoverable malloc error: code %d", code);
264}
265
266static void
267NeXT_init (void)
268{
269 malloc_error (malloc_handler);
270}
271#endif
272
273#if defined (__EMX__)
274OS2_init (void)
275{
276 _control87 ((EM_INVALID | EM_DENORMAL | EM_ZERODIVIDE | EM_OVERFLOW
277 | EM_UNDERFLOW | EM_INEXACT), MCW_EM);
278}
279#endif
280
281#if defined (SCO)
282static void
283SCO_init (void)
284{
285#if defined (HAVE_IEEEFP_H)
286 // Disable trapping on common exceptions.
287 fpsetmask (~(FP_X_OFL|FP_X_INV|FP_X_DZ|FP_X_DNML|FP_X_UFL|FP_X_IMP));
288#endif
289}
290#endif
291
292void
293sysdep_init (void)
294{
295#if defined (__386BSD__) || defined (__FreeBSD__) || defined(__NetBSD__)
296 BSD_init ();
297#elif defined (__MINGW32__)
298 MINGW_init ();
299#elif defined (_MSC_VER)
300 MSVC_init ();
301#elif defined (NeXT)
302 NeXT_init ();
303#elif defined (__EMX__)
304 OS2_init ();
305#elif defined (SCO)
306 SCO_init ();
307#endif
308
309 octave_ieee_init ();
310}
311
312void
313sysdep_cleanup (void)
314{
315 MINGW_SIGNAL_CLEANUP ();
316}
317
318// Set terminal in raw mode. From less-177.
319//
320// Change terminal to "raw mode", or restore to "normal" mode.
321// "Raw mode" means
322// 1. An outstanding read will complete on receipt of a single keystroke.
323// 2. Input is not echoed.
324// 3. On output, \n is mapped to \r\n.
325// 4. \t is NOT expanded into spaces.
326// 5. Signal-causing characters such as ctrl-C (interrupt),
327// etc. are NOT disabled.
328// It doesn't matter whether an input \n is mapped to \r, or vice versa.
329
330void
331raw_mode (bool on, bool wait)
332{
333 static bool curr_on = false;
334
335 int tty_fd = STDIN_FILENO;
336 if (! isatty (tty_fd))
337 {
338 if (interactive)
339 error ("stdin is not a tty!");
340 return;
341 }
342
343 if (on == curr_on)
344 return;
345
346#if defined (HAVE_TERMIOS_H)
347 {
348 struct termios s;
349 static struct termios save_term;
350
351 if (on)
352 {
353 // Get terminal modes.
354
355 tcgetattr (tty_fd, &s);
356
357 // Save modes and set certain variables dependent on modes.
358
359 save_term = s;
360// ospeed = s.c_cflag & CBAUD;
361// erase_char = s.c_cc[VERASE];
362// kill_char = s.c_cc[VKILL];
363
364 // Set the modes to the way we want them.
365
366 s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
367 s.c_oflag |= (OPOST|ONLCR);
368#if defined (OCRNL)
369 s.c_oflag &= ~(OCRNL);
370#endif
371#if defined (ONOCR)
372 s.c_oflag &= ~(ONOCR);
373#endif
374#if defined (ONLRET)
375 s.c_oflag &= ~(ONLRET);
376#endif
377 s.c_cc[VMIN] = wait ? 1 : 0;
378 s.c_cc[VTIME] = 0;
379 }
380 else
381 {
382 // Restore saved modes.
383
384 s = save_term;
385 }
386
387 tcsetattr (tty_fd, wait ? TCSAFLUSH : TCSADRAIN, &s);
388 }
389#elif defined (HAVE_TERMIO_H)
390 {
391 struct termio s;
392 static struct termio save_term;
393
394 if (on)
395 {
396 // Get terminal modes.
397
398 ioctl (tty_fd, TCGETA, &s);
399
400 // Save modes and set certain variables dependent on modes.
401
402 save_term = s;
403// ospeed = s.c_cflag & CBAUD;
404// erase_char = s.c_cc[VERASE];
405// kill_char = s.c_cc[VKILL];
406
407 // Set the modes to the way we want them.
408
409 s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
410 s.c_oflag |= (OPOST|ONLCR);
411#if defined (OCRNL)
412 s.c_oflag &= ~(OCRNL);
413#endif
414#if defined (ONOCR)
415 s.c_oflag &= ~(ONOCR);
416#endif
417#if defined (ONLRET)
418 s.c_oflag &= ~(ONLRET);
419#endif
420 s.c_cc[VMIN] = wait ? 1 : 0;
421 }
422 else
423 {
424 // Restore saved modes.
425
426 s = save_term;
427 }
428
429 ioctl (tty_fd, TCSETAW, &s);
430 }
431#elif defined (HAVE_SGTTY_H)
432 {
433 struct sgttyb s;
434 static struct sgttyb save_term;
435
436 if (on)
437 {
438 // Get terminal modes.
439
440 ioctl (tty_fd, TIOCGETP, &s);
441
442 // Save modes and set certain variables dependent on modes.
443
444 save_term = s;
445// ospeed = s.sg_ospeed;
446// erase_char = s.sg_erase;
447// kill_char = s.sg_kill;
448
449 // Set the modes to the way we want them.
450
451 s.sg_flags |= CBREAK;
452 s.sg_flags &= ~(ECHO);
453 }
454 else
455 {
456 // Restore saved modes.
457
458 s = save_term;
459 }
460
461 ioctl (tty_fd, TIOCSETN, &s);
462 }
463#else
464 warning ("no support for raw mode console I/O on this system");
465
466 // Make sure the current mode doesn't toggle.
467 on = curr_on;
468#endif
469
470 curr_on = on;
471}
472
473FILE *
474octave_popen (const char *command, const char *mode)
475{
476#if defined (__MINGW32__) || defined (_MSC_VER)
477 if (mode && mode[0] && ! mode[1])
478 {
479 char tmode[3];
480 tmode[0] = mode[0];
481 tmode[1] = 'b';
482 tmode[2] = 0;
483
484 return _popen (command, tmode);
485 }
486 else
487 return _popen (command, mode);
488#else
489 return popen (command, mode);
490#endif
491}
492
493int
494octave_pclose (FILE *f)
495{
496#if defined (__MINGW32__) || defined (_MSC_VER)
497 return _pclose (f);
498#else
499 return pclose (f);
500#endif
501}
502
503// Read one character from the terminal.
504
505int
506octave_kbhit (bool wait)
507{
508#ifdef HAVE__KBHIT
509 int c = (! wait && ! _kbhit ()) ? 0 : std::cin.get ();
510#else
511 raw_mode (true, wait);
512
513 // Get current handler.
514 octave_interrupt_handler saved_interrupt_handler
515 = octave_ignore_interrupts ();
516
517 // Restore it, disabling system call restarts (if possible) so the
518 // read can be interrupted.
519
520 octave_set_interrupt_handler (saved_interrupt_handler, false);
521
522 int c = std::cin.get ();
523
524 if (std::cin.fail () || std::cin.eof ())
525 std::cin.clear ();
526
527 // Restore it, enabling system call restarts (if possible).
528 octave_set_interrupt_handler (saved_interrupt_handler, true);
529
530 raw_mode (false, true);
531#endif
532
533 return c;
534}
535
536DEFUN (clc, , ,
537 "-*- texinfo -*-\n\
538@deftypefn {Built-in Function} {} clc ()\n\
539@deftypefnx {Built-in Function} {} home ()\n\
540Clear the terminal screen and move the cursor to the upper left corner.\n\
541@end deftypefn")
542{
543 command_editor::clear_screen ();
544
545 return octave_value_list ();
546}
547
548DEFALIAS (home, clc);
549
550DEFUN (getenv, args, ,
551 "-*- texinfo -*-\n\
552@deftypefn {Built-in Function} {} getenv (@var{var})\n\
553Return the value of the environment variable @var{var}. For example,\n\
554\n\
555@example\n\
556getenv (\"PATH\")\n\
557@end example\n\
558\n\
559@noindent\n\
560returns a string containing the value of your path.\n\
561@end deftypefn")
562{
563 octave_value retval;
564
565 int nargin = args.length ();
566
567 if (nargin == 1)
568 {
569 std::string name = args(0).string_value ();
570
571 if (! error_state)
572 retval = octave_env::getenv (name);
573 }
574 else
575 print_usage ();
576
577 return retval;
578}
579
580DEFUN (putenv, args, ,
581 "-*- texinfo -*-\n\
582@deftypefn {Built-in Function} {} putenv (@var{var}, @var{value})\n\
583@deftypefnx {Built-in Function} {} setenv (@var{var}, @var{value})\n\
584Set the value of the environment variable @var{var} to @var{value}.\n\
585@end deftypefn")
586{
587 octave_value_list retval;
588
589 int nargin = args.length ();
590
591 if (nargin == 2 || nargin == 1)
592 {
593 std::string var = args(0).string_value ();
594
595 if (! error_state)
596 {
597 std::string val = (nargin == 2
598 ? args(1).string_value () : std::string ());
599
600 if (! error_state)
601 octave_env::putenv (var, val);
602 else
603 error ("putenv: second argument should be a string");
604 }
605 else
606 error ("putenv: first argument should be a string");
607 }
608 else
609 print_usage ();
610
611 return retval;
612}
613DEFALIAS (setenv, putenv);
614
615// FIXME -- perhaps kbhit should also be able to print a prompt?
616
617DEFUN (kbhit, args, ,
618 "-*- texinfo -*-\n\
619@deftypefn {Built-in Function} {} kbhit ()\n\
620Read a single keystroke from the keyboard. If called with one\n\
621argument, don't wait for a keypress. For example,\n\
622\n\
623@example\n\
624x = kbhit ();\n\
625@end example\n\
626\n\
627@noindent\n\
628will set @var{x} to the next character typed at the keyboard as soon as\n\
629it is typed.\n\
630\n\
631@example\n\
632x = kbhit (1);\n\
633@end example\n\
634\n\
635@noindent\n\
636identical to the above example, but don't wait for a keypress,\n\
637returning the empty string if no key is available.\n\
638@end deftypefn")
639{
640 octave_value retval;
641
642 // FIXME -- add timeout and default value args?
643
644 if (interactive || forced_interactive)
645 {
646 feval ("drawnow");
647
648 int c = octave_kbhit (args.length () == 0);
649
650 if (c == -1)
651 c = 0;
652
653 char *s = new char [2];
654 s[0] = c;
655 s[1] = '\0';
656 retval = s;
657 }
658
659 return retval;
660}
661
662DEFUN (pause, args, ,
663 "-*- texinfo -*-\n\
664@deftypefn {Built-in Function} {} pause (@var{seconds})\n\
665Suspend the execution of the program. If invoked without any arguments,\n\
666Octave waits until you type a character. With a numeric argument, it\n\
667pauses for the given number of seconds. For example, the following\n\
668statement prints a message and then waits 5 seconds before clearing the\n\
669screen.\n\
670\n\
671@example\n\
672@group\n\
673fprintf (stderr, \"wait please...\\n\");\n\
674pause (5);\n\
675clc;\n\
676@end group\n\
677@end example\n\
678@end deftypefn")
679{
680 octave_value_list retval;
681
682 int nargin = args.length ();
683
684 if (! (nargin == 0 || nargin == 1))
685 {
686 print_usage ();
687 return retval;
688 }
689
690 if (nargin == 1)
691 {
692 double dval = args(0).double_value ();
693
694 if (! error_state)
695 {
696 if (! xisnan (dval))
697 {
698 feval ("drawnow");
699
700 if (xisinf (dval))
701 {
702 flush_octave_stdout ();
703 octave_kbhit ();
704 }
705 else
706 octave_sleep (dval);
707 }
708 else
709 warning ("pause: NaN is an invalid delay");
710 }
711 }
712 else
713 {
714 feval ("drawnow");
715 flush_octave_stdout ();
716 octave_kbhit ();
717 }
718
719 return retval;
720}
721
722DEFUN (sleep, args, ,
723 "-*- texinfo -*-\n\
724@deftypefn {Built-in Function} {} sleep (@var{seconds})\n\
725Suspend the execution of the program for the given number of seconds.\n\
726@end deftypefn")
727{
728 octave_value_list retval;
729
730 if (args.length () == 1)
731 {
732 double dval = args(0).double_value ();
733
734 if (! error_state)
735 {
736 if (xisnan (dval))
737 warning ("sleep: NaN is an invalid delay");
738 else
739 {
740 feval ("drawnow");
741 octave_sleep (dval);
742 }
743 }
744 }
745 else
746 print_usage ();
747
748 return retval;
749}
750
751DEFUN (usleep, args, ,
752 "-*- texinfo -*-\n\
753@deftypefn {Built-in Function} {} usleep (@var{microseconds})\n\
754Suspend the execution of the program for the given number of\n\
755microseconds. On systems where it is not possible to sleep for periods\n\
756of time less than one second, @code{usleep} will pause the execution for\n\
757@code{round (@var{microseconds} / 1e6)} seconds.\n\
758@end deftypefn")
759{
760 octave_value_list retval;
761
762 if (args.length () == 1)
763 {
764 double dval = args(0).double_value ();
765
766 if (! error_state)
767 {
768 if (xisnan (dval))
769 warning ("usleep: NaN is an invalid delay");
770 else
771 {
772 feval ("drawnow");
773
774 int delay = NINT (dval);
775
776 if (delay > 0)
777 octave_usleep (delay);
778 }
779 }
780 }
781 else
782 print_usage ();
783
784 return retval;
785}
786
787// FIXME -- maybe this should only return 1 if IEEE floating
788// point functions really work.
789
790DEFUN (isieee, , ,
791 "-*- texinfo -*-\n\
792@deftypefn {Built-in Function} {} isieee ()\n\
793Return 1 if your computer claims to conform to the IEEE standard for\n\
794floating point calculations.\n\
795@end deftypefn")
796{
797 oct_mach_info::float_format flt_fmt = oct_mach_info::native_float_format ();
798
799 return octave_value (flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
800 || flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
801}
802
803DEFUN (native_float_format, , ,
804 "-*- texinfo -*-\n\
805@deftypefn {Built-in Function} {} native_float_format ()\n\
806Return the native floating point format as a string\n\
807@end deftypefn")
808{
809 oct_mach_info::float_format flt_fmt = oct_mach_info::native_float_format ();
810
811 return octave_value (oct_mach_info::float_format_as_string (flt_fmt));
812}
813
814DEFUN (tilde_expand, args, ,
815 "-*- texinfo -*-\n\
816@deftypefn {Built-in Function} {} tilde_expand (@var{string})\n\
817Performs tilde expansion on @var{string}. If @var{string} begins with a\n\
818tilde character, (@samp{~}), all of the characters preceding the first\n\
819slash (or all characters, if there is no slash) are treated as a\n\
820possible user name, and the tilde and the following characters up to the\n\
821slash are replaced by the home directory of the named user. If the\n\
822tilde is followed immediately by a slash, the tilde is replaced by the\n\
823home directory of the user running Octave. For example,\n\
824\n\
825@example\n\
826@group\n\
827tilde_expand (\"~joeuser/bin\")\n\
828 @result{} \"/home/joeuser/bin\"\n\
829tilde_expand (\"~/bin\")\n\
830 @result{} \"/home/jwe/bin\"\n\
831@end group\n\
832@end example\n\
833@end deftypefn")
834{
835 octave_value retval;
836
837 int nargin = args.length ();
838
839 if (nargin == 1)
840 {
841 octave_value arg = args(0);
842
843 string_vector sv = arg.all_strings ();
844
845 if (! error_state)
846 {
847 sv = file_ops::tilde_expand (sv);
848
849 if (arg.is_cellstr ())
850 retval = Cell (arg.dims (), sv);
851 else
852 retval = sv;
853 }
854 else
855 error ("tilde_expand: expecting argument to be char or cellstr object");
856 }
857 else
858 print_usage ();
859
860 return retval;
861}
862
863#if defined (__EMX__) && defined (OS2)
864
865DEFUN (extproc, , ,
866 "extproc: ignored by Octave")
867{
868 return octave_value_list ();
869}
870
871DEFALIAS (EXTPROC, extproc);
872
873#endif