GNU Octave 11.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
sysdep.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1993-2026 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <cmath>
31#include <cstddef>
32
33#include <iostream>
34#include <string>
35
36#if defined (HAVE_TERMIOS_H)
37# include <termios.h>
38#elif defined (HAVE_TERMIO_H)
39# include <termio.h>
40#elif defined (HAVE_SGTTY_H)
41# include <sgtty.h>
42#endif
43
44#if defined (HAVE_CONIO_H)
45# include <conio.h>
46#endif
47
48#if defined (HAVE_SYS_IOCTL_H)
49# include <sys/ioctl.h>
50#endif
51
52#if defined (HAVE_FLOATINGPOINT_H)
53# include <floatingpoint.h>
54#endif
55
56#if defined (HAVE_IEEEFP_H)
57# include <ieeefp.h>
58#endif
59
60#if defined (HAVE_OMP_H)
61# include <omp.h>
62#endif
63
64#include "cmd-edit.h"
65#include "file-ops.h"
66#include "mach-info.h"
67#include "mappers.h"
68#include "oct-env.h"
69#include "oct-sysinfo.h"
70#include "uniconv-wrappers.h"
71#include "unistd-wrappers.h"
72
73#include "builtin-defun-decls.h"
74#include "Cell.h"
75#include "defun.h"
76#include "error.h"
77#include "errwarn.h"
78#include "input.h"
79#include "interpreter-private.h"
80#include "octave.h"
81#include "ov.h"
82#include "ovl.h"
83#include "pager.h"
84#include "parse.h"
85#include "sighandlers.h"
86#include "sysdep.h"
87#include "interpreter.h"
88#include "utils.h"
89#include "file-stat.h"
90
91#if ! defined (STDIN_FILENO)
92# define STDIN_FILENO 1
93#endif
94
95#if defined (__MINGW32__) || defined (_MSC_VER)
96
97#define WIN32_LEAN_AND_MEAN
98#include <windows.h>
99#include <fcntl.h>
100#include <io.h>
101#include <tlhelp32.h>
102#include <psapi.h>
103#include <shellapi.h>
104#include <shobjidl.h>
105
106#endif
107
109
110#if defined (__386BSD__) || defined (__FreeBSD__) || defined (__NetBSD__)
111
112static void
113BSD_init ()
114{
115# if defined (HAVE_FLOATINGPOINT_H)
116 // Disable trapping on common exceptions.
117# if ! defined (FP_X_DNML)
118# define FP_X_DNML 0
119# endif
120 fpsetmask (~(FP_X_OFL|FP_X_INV|FP_X_DZ|FP_X_DNML|FP_X_UFL|FP_X_IMP));
121# endif
122}
123
124#endif
125
126#if defined (__MINGW32__) || defined (_MSC_VER)
127
128static void
129w32_set_octave_home ()
130{
131 std::string bin_dir;
132
133 HANDLE h = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE
134#if defined (TH32CS_SNAPMODULE32)
135 | TH32CS_SNAPMODULE32
136#endif
137 , 0);
138
139 if (h != INVALID_HANDLE_VALUE)
140 {
141 MODULEENTRY32W mod_info;
142
143 ZeroMemory (&mod_info, sizeof (mod_info));
144 mod_info.dwSize = sizeof (mod_info);
145
146 if (Module32FirstW (h, &mod_info))
147 {
148 do
149 {
150 std::string mod_name (sys::u8_from_wstring (mod_info.szModule));
151
152 if (mod_name.find ("octinterp") != std::string::npos)
153 {
154 bin_dir = sys::u8_from_wstring (mod_info.szExePath);
155 if (! bin_dir.empty () && bin_dir.back () != '\\')
156 bin_dir.push_back ('\\');
157 break;
158 }
159 }
160 while (Module32NextW (h, &mod_info));
161 }
162
163 CloseHandle (h);
164 }
165
166 if (! bin_dir.empty ())
167 {
168 std::size_t pos = bin_dir.rfind (R"(\bin\)");
169
170 if (pos != std::string::npos)
171 sys::env::putenv ("OCTAVE_HOME", bin_dir.substr (0, pos));
172 }
173}
174
175static void
176w32_init ()
177{
178 w32_set_octave_home ();
179
181}
182
183#endif
184
185void
187{
188#if defined (__MINGW32__) || defined (_MSC_VER)
189
190 SetCurrentProcessExplicitAppUserModelID (L"gnu.octave." VERSION);
191
192#endif
193}
194
195DEFUN (__open_with_system_app__, args, ,
196 doc: /* -*- texinfo -*-
197@deftypefn {} {@var{status} =} __open_with_system_app__ (@var{file})
198Return 1 on successful system call and 0 otherwise.
199@end deftypefn */)
200{
201 if (args.length () != 1)
202 print_usage ();
203
204 std::string file = args(0).xstring_value ("__open_with_system_app__: argument must be a filename");
205
206#if defined (OCTAVE_USE_WINDOWS_API)
207 std::wstring wfile = sys::u8_to_wstring (file);
208 HINSTANCE status = ShellExecuteW (0, 0, wfile.c_str (), 0, 0, SW_SHOWNORMAL);
209
210 // ShellExecute returns a value greater than 32 if successful.
211 return octave_value (reinterpret_cast<std::ptrdiff_t> (status) > 32);
212#else
213 // Quote file path
214 file = '"' + file + '"';
215
216# if defined (__APPLE__)
217# define FSYSTEM_OPEN_STR "open "
218# else
219# define FSYSTEM_OPEN_STR "xdg-open "
220# endif
222 = Fsystem (ovl (FSYSTEM_OPEN_STR + file + " 2> /dev/null",
223 false, "async"),
224 1);
225# undef FSYSTEM_OPEN_STR
226
227 // Asynchronous Fsystem calls return the new child process identifier,
228 // which must be greater than 1 if successful.
229 return octave_value (tmp(0).double_value () > 1);
230#endif
231}
232
233DEFUN (__is_elevated_process__, args, ,
234 doc: /* -*- texinfo -*-
235@deftypefn {} {@var{retval} =} __is_elevated_process__ ()
236Check if current process has elevated rights.
237
238On Windows, return true if the current process has elevated right. Otherwise,
239return false.
240On non-Windows platforms, this function fails with an error.
241@end deftypefn */)
242{
243#if defined (OCTAVE_USE_WINDOWS_API)
244 if (args.length () != 0)
245 print_usage ();
246
247 bool retval = false;
248 HANDLE h_token = nullptr;
249
250 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &h_token))
251 {
252 TOKEN_ELEVATION elevation;
253 DWORD return_length = sizeof (TOKEN_ELEVATION);
254 if (GetTokenInformation (h_token, TokenElevation, &elevation,
255 sizeof (elevation), &return_length))
256 retval = elevation.TokenIsElevated;
257 }
258
259 if (h_token)
260 CloseHandle (h_token);
261
262 return ovl (retval);
263
264#else
265 octave_unused_parameter (args);
266 error ("__is_elevated_process__: "
267 "Function is only supported on Windows platforms.");
268#endif
269}
270
271DEFUN (__wmemory__, args, ,
272 doc: /* -*- texinfo -*-
273@deftypefn {} {[@var{proc}, @var{sys}] =} __wmemory__ ()
274Return memory information on Windows.
275
276On non-Windows platforms, this function fails with an error.
277@end deftypefn */)
278{
279#if defined (OCTAVE_USE_WINDOWS_API)
280 if (args.length () != 0)
281 print_usage ();
282
283 // Get memory usage of the current process
284 octave_scalar_map proc_struct;
285
286 HANDLE h_proc = GetCurrentProcess ();
287 if (h_proc == nullptr)
288 error ("__wmemory__: Couldn't open handle to own process");
289
290 PROCESS_MEMORY_COUNTERS proc_mem_count;
291 if (GetProcessMemoryInfo (h_proc, &proc_mem_count, sizeof (proc_mem_count)))
292 {
293 proc_struct.setfield ("PageFaultCount",
294 proc_mem_count.PageFaultCount);
295 proc_struct.setfield ("PeakWorkingSetSize",
296 proc_mem_count.PeakWorkingSetSize);
297 proc_struct.setfield ("WorkingSetSize",
298 proc_mem_count.WorkingSetSize);
299 proc_struct.setfield ("QuotaPeakPagedPoolUsage",
300 proc_mem_count.QuotaPeakPagedPoolUsage);
301 proc_struct.setfield ("QuotaPagedPoolUsage",
302 proc_mem_count.QuotaPagedPoolUsage);
303 proc_struct.setfield ("QuotaPeakNonPagedPoolUsage",
304 proc_mem_count.QuotaPeakNonPagedPoolUsage);
305 proc_struct.setfield ("QuotaNonPagedPoolUsage",
306 proc_mem_count.QuotaNonPagedPoolUsage);
307 proc_struct.setfield ("PagefileUsage",
308 proc_mem_count.PagefileUsage);
309 proc_struct.setfield ("PeakPagefileUsage",
310 proc_mem_count.PeakPagefileUsage);
311 }
312 else
313 {
314 proc_struct.setfield ("PageFaultCount", 0);
315 proc_struct.setfield ("PeakWorkingSetSize", 0);
316 proc_struct.setfield ("WorkingSetSize", 0);
317 proc_struct.setfield ("QuotaPeakPagedPoolUsage", 0);
318 proc_struct.setfield ("QuotaPagedPoolUsage", 0);
319 proc_struct.setfield ("QuotaPeakNonPagedPoolUsage", 0);
320 proc_struct.setfield ("QuotaNonPagedPoolUsage", 0);
321 proc_struct.setfield ("PagefileUsage", 0);
322 proc_struct.setfield ("PeakPagefileUsage", 0);
323 }
324
325 CloseHandle (h_proc);
326
327 // Get system memory usage
328 octave_scalar_map sys_struct;
329
330 MEMORYSTATUSEX mem_stat;
331
332 mem_stat.dwLength = sizeof (mem_stat);
333
334 if (GlobalMemoryStatusEx (&mem_stat))
335 {
336 sys_struct.setfield ("MemoryLoad", mem_stat.dwMemoryLoad);
337 sys_struct.setfield ("TotalPhys", mem_stat.ullTotalPhys);
338 sys_struct.setfield ("AvailPhys", mem_stat.ullAvailPhys);
339 sys_struct.setfield ("TotalPageFile", mem_stat.ullTotalPageFile);
340 sys_struct.setfield ("AvailPageFile", mem_stat.ullAvailPageFile);
341 sys_struct.setfield ("TotalVirtual", mem_stat.ullTotalVirtual);
342 sys_struct.setfield ("AvailVirtual", mem_stat.ullAvailVirtual);
343 sys_struct.setfield ("AvailExtendedVirtual",
344 mem_stat.ullAvailExtendedVirtual);
345 }
346 else
347 {
348 sys_struct.setfield ("MemoryLoad", 0);
349 sys_struct.setfield ("TotalPhys", 0);
350 sys_struct.setfield ("AvailPhys", 0);
351 sys_struct.setfield ("TotalPageFile", 0);
352 sys_struct.setfield ("AvailPageFile", 0);
353 sys_struct.setfield ("TotalVirtual", 0);
354 sys_struct.setfield ("AvailVirtual", 0);
355 sys_struct.setfield ("AvailExtendedVirtual", 0);
356 }
357
358 return ovl (proc_struct, sys_struct);
359
360#else
361 octave_unused_parameter (args);
362 error ("__wmemory__: Function is only supported on Windows platforms");
363#endif
364}
365
366#if defined (__MINGW32__)
367
368static void
369MINGW_init ()
370{
371 w32_init ();
372}
373
374#endif
375
376#if defined (_MSC_VER)
377
378static void
379MSVC_init ()
380{
381 w32_init ();
382}
383
384#endif
385
386// Return TRUE if NAME refers to an existing drive letter or UNC share
387
388bool
389drive_or_unc_share (const std::string& name)
390{
391#if defined (OCTAVE_USE_WINDOWS_API)
392 std::size_t len = name.length ();
393 bool candidate = false;
394 if (len > 1 && isalpha(name[0]) && name[1]==':'
395 && (len == 2 || (len == 3 && name[2] == '\\')))
396 candidate = true;
397 if (len > 4 && name[0] == '\\' && name[1] == '\\')
398 {
399 // It starts with two slashes. Find the next slash.
400 std::size_t next_slash = name.find ('\\', 3);
401 if (next_slash != std::string::npos && len > next_slash+1)
402 {
403 // Check if it ends with the share
404 std::size_t last_slash = name.find ('\\', next_slash+1);
405 if (last_slash == std::string::npos
406 || (len > next_slash+2 && last_slash == len-1))
407 candidate = true;
408 }
409 }
410
411 if (candidate)
412 {
413 // Open a handle to the file.
414 std::wstring wname = sys::u8_to_wstring (name);
415 HANDLE h
416 = CreateFileW (wname.c_str (), FILE_READ_ATTRIBUTES,
417 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
418 nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
419 nullptr);
420 if (h != INVALID_HANDLE_VALUE)
421 {
422 CloseHandle (h);
423 return true;
424 }
425 }
426
427 return false;
428
429#else
430
431 octave_unused_parameter (name);
432
433 return false;
434
435#endif
436}
437
438void
440{
441 static bool initialized = false;
442
443 if (initialized)
444 return;
445
446 // Use a function from libgomp to force loading of OpenMP library.
447 // Otherwise, a dynamically loaded library making use of OpenMP such
448 // as GraphicsMagick will segfault on exit (bug #41699).
449#if defined (HAVE_OMP_GET_NUM_THREADS)
450 omp_get_num_threads ();
451#endif
452
453#if defined (__386BSD__) || defined (__FreeBSD__) || defined (__NetBSD__)
454 BSD_init ();
455#elif defined (__MINGW32__)
456 MINGW_init ();
457#elif defined (_MSC_VER)
458 MSVC_init ();
459#endif
460
461 initialized = true;
462}
463
464void
466{
467#if defined (OCTAVE_USE_WINDOWS_API)
468 // Let us fail immediately without displaying any dialog.
469 SetProcessShutdownParameters (0x280, SHUTDOWN_NORETRY);
470#endif
471}
472
473// Set terminal in raw mode. From less-177.
474//
475// Change terminal to "raw mode", or restore to "normal" mode.
476// "Raw mode" means
477// 1. An outstanding read will complete on receipt of a single keystroke.
478// 2. Input is not echoed.
479// 3. On output, \n is mapped to \r\n.
480// 4. \t is NOT expanded into spaces.
481// 5. Signal-causing characters such as ctrl-C (interrupt),
482// etc. are NOT disabled.
483// It doesn't matter whether an input \n is mapped to \r, or vice versa.
484
485void
486raw_mode (bool on, bool wait)
487{
488 static bool curr_on = false;
489
490 int tty_fd = STDIN_FILENO;
491 if (! octave_isatty_wrapper (tty_fd))
492 {
493 interpreter& interp = __get_interpreter__ ();
494
495 if (interp.interactive () && ! application::forced_interactive ())
496 error ("stdin is not a tty!");
497 }
498
499 if (on == curr_on)
500 return;
501
502#if defined (HAVE_TERMIOS_H)
503 {
504 struct termios s;
505 static struct termios save_term;
506
507 if (on)
508 {
509 // Get terminal modes.
510
511 tcgetattr (tty_fd, &s);
512
513 // Save modes and set certain variables dependent on modes.
514
515 save_term = s;
516 // ospeed = s.c_cflag & CBAUD;
517 // erase_char = s.c_cc[VERASE];
518 // kill_char = s.c_cc[VKILL];
519
520 // Set the modes to the way we want them.
521
522 s.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
523 s.c_oflag |= (OPOST | ONLCR);
524#if defined (OCRNL)
525 s.c_oflag &= ~(OCRNL);
526#endif
527#if defined (ONOCR)
528 s.c_oflag &= ~(ONOCR);
529#endif
530#if defined (ONLRET)
531 s.c_oflag &= ~(ONLRET);
532#endif
533 s.c_cc[VMIN] = (wait ? 1 : 0);
534 s.c_cc[VTIME] = 0;
535 }
536 else
537 {
538 // Restore saved modes.
539
540 s = save_term;
541 }
542
543 tcsetattr (tty_fd, wait ? TCSAFLUSH : TCSADRAIN, &s);
544 }
545#elif defined (HAVE_TERMIO_H)
546 {
547 struct termio s;
548 static struct termio save_term;
549
550 if (on)
551 {
552 // Get terminal modes.
553
554 ioctl (tty_fd, TCGETA, &s);
555
556 // Save modes and set certain variables dependent on modes.
557
558 save_term = s;
559 // ospeed = s.c_cflag & CBAUD;
560 // erase_char = s.c_cc[VERASE];
561 // kill_char = s.c_cc[VKILL];
562
563 // Set the modes to the way we want them.
564
565 s.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
566 s.c_oflag |= (OPOST | ONLCR);
567#if defined (OCRNL)
568 s.c_oflag &= ~(OCRNL);
569#endif
570#if defined (ONOCR)
571 s.c_oflag &= ~(ONOCR);
572#endif
573#if defined (ONLRET)
574 s.c_oflag &= ~(ONLRET);
575#endif
576 s.c_cc[VMIN] = (wait ? 1 : 0);
577 }
578 else
579 {
580 // Restore saved modes.
581
582 s = save_term;
583 }
584
585 ioctl (tty_fd, TCSETAW, &s);
586 }
587#elif defined (HAVE_SGTTY_H)
588 {
589 octave_unused_parameter (wait);
590
591 struct sgttyb s;
592 static struct sgttyb save_term;
593
594 if (on)
595 {
596 // Get terminal modes.
597
598 ioctl (tty_fd, TIOCGETP, &s);
599
600 // Save modes and set certain variables dependent on modes.
601
602 save_term = s;
603 // ospeed = s.sg_ospeed;
604 // erase_char = s.sg_erase;
605 // kill_char = s.sg_kill;
606
607 // Set the modes to the way we want them.
608
609 s.sg_flags |= CBREAK;
610 s.sg_flags &= ~(ECHO);
611 }
612 else
613 {
614 // Restore saved modes.
615
616 s = save_term;
617 }
618
619 ioctl (tty_fd, TIOCSETN, &s);
620 }
621#else
622
623 octave_unused_parameter (wait);
624
625 warn_disabled_feature ("", "raw mode console I/O");
626
627 // Make sure the current mode doesn't toggle.
628 on = curr_on;
629#endif
630
631 curr_on = on;
632}
633
634#if defined (OCTAVE_USE_WINDOWS_API)
635// map that stores process handle for each pipe file pointer
636std::map<FILE *, HANDLE> pipe_handle_map;
637#endif
638
639FILE *
640popen (const char *command, const char *mode)
641{
642#if defined (OCTAVE_USE_WINDOWS_API)
643 // On Windows (non-Cygwin), child processes need to be created with a new
644 // console to avoid desynchronization of the console that is used by the
645 // command window widget of the GUI.
646
647 bool is_write = (mode[0] == 'w');
648 // use binary mode on Windows if unspecified
649 bool is_binary = ((strlen (mode) == 1) || mode[1] == 'b');
650
651 HANDLE h_read;
652 HANDLE h_write;
653 SECURITY_ATTRIBUTES sa {};
654 sa.nLength = sizeof (sa);
655 sa.bInheritHandle = TRUE; // child can inherit
656
657 if (! CreatePipe (&h_read, &h_write, &sa, 0))
658 return nullptr;
659
660 HANDLE parent_end = is_write ? h_write : h_read;
661 HANDLE child_end = is_write ? h_read : h_write;
662
663 // prevent child from inheriting the wrong end
664 SetHandleInformation (parent_end, HANDLE_FLAG_INHERIT, 0);
665
666 // spawn child with one end of pipe as stdin or stdout/stderr
667 STARTUPINFOW si {};
668 si.cb = sizeof (si);
669 si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
670 si.wShowWindow = SW_HIDE; // avoid flashing black window
671 if (is_write)
672 si.hStdInput = child_end;
673 else
674 {
675 si.hStdOutput = child_end;
676 si.hStdError = child_end;
677 }
678 PROCESS_INFORMATION pi {};
679
680 std::wstring wcommand {L"cmd.exe /C \""};
681 wcommand.append (sys::u8_to_wstring (command));
682 wcommand.append (L"\"");
683 BOOL ok = CreateProcessW (nullptr, &wcommand[0], nullptr, nullptr, TRUE,
684 CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi);
685 if (! ok)
686 {
687 CloseHandle (h_read);
688 CloseHandle (h_write);
689 return nullptr;
690 }
691
692 CloseHandle (pi.hThread);
693
694 // close child's end of pipe
695 CloseHandle (child_end);
696
697 // convert pipe read or write handle to FILE *
698 int flags = (is_write ? _O_WRONLY : _O_RDONLY);
699 if (is_binary)
700 flags |= _O_BINARY;
701
702 int fd = _open_osfhandle (reinterpret_cast<intptr_t> (parent_end), flags);
703
704 if (fd == -1)
705 {
706 CloseHandle (parent_end);
707 CloseHandle (pi.hProcess);
708 return nullptr;
709 }
710
711 FILE *f = _fdopen (fd, mode);
712 if (! f)
713 {
714 _close (fd); // handle to parent end of pipe is owned by OS file handle
715 CloseHandle (pi.hProcess);
716 return nullptr;
717 }
718
719 pipe_handle_map[f] = pi.hProcess;
720
721 return f;
722
723#else
724 return ::popen (command, mode);
725#endif
726}
727
728int
729pclose (FILE *f)
730{
731#if defined (OCTAVE_USE_WINDOWS_API)
732 auto it = pipe_handle_map.find (f);
733 if (it != pipe_handle_map.end ())
734 {
735 HANDLE h_process = it->second;
736 pipe_handle_map.erase (it);
737
738 // close FILE pointer before waiting for child process
739 ::fclose (f);
740
741 // wait for child to finish
742 WaitForSingleObject (h_process, INFINITE);
743 DWORD exitcode;
744 if (! GetExitCodeProcess (h_process, &exitcode))
745 exitcode = -1;
746
747 // close handle to child process
748 CloseHandle (h_process);
749
750 return static_cast<int> (exitcode);
751 }
752
753 // This should not be happening.
754 return ::fclose (f);
755
756#else
757 return ::pclose (f);
758#endif
759}
760
761// Read one character from the terminal.
762
763int
764kbhit (bool wait)
765{
766#if defined (HAVE__KBHIT) && defined (HAVE__GETCH)
767 // This essentially means we are on a Windows system.
768
769 // The value to return when wait is false and no input is ready.
770 static constexpr int eof = std::istream::traits_type::eof ();
771
772 int c;
773
774 if (wait)
775 c = _getch ();
776 else
777 c = (! _kbhit ()) ? eof : _getch ();
778
779#else
780 raw_mode (true, wait);
781
782 // Get current handler.
783 interrupt_handler saved_interrupt_handler
785
786 // Restore it, disabling system call restarts (if possible) so the
787 // read can be interrupted.
788
789 set_interrupt_handler (saved_interrupt_handler, false);
790
791 int c = std::cin.get ();
792
793 if (std::cin.fail () || std::cin.eof ())
794 {
795 std::cin.clear ();
796 clearerr (stdin);
797 }
798
799 // Restore it, enabling system call restarts (if possible).
800 set_interrupt_handler (saved_interrupt_handler, true);
801
802 raw_mode (false, true);
803#endif
804
805 return c;
806}
807
808std::string
810{
811#if defined (OCTAVE_USE_WINDOWS_API)
812
813 std::string retval;
814
815#if defined (P_tmpdir)
816 retval = P_tmpdir;
817#endif
818
819 // Apparently some versions of MinGW and MSVC either don't define
820 // P_tmpdir, or they define it to a single backslash, neither of which
821 // is particularly helpful.
822
823 if (retval.empty () || retval == R"(\)")
824 {
825 retval = sys::env::getenv ("TEMP");
826
827 if (retval.empty ())
828 retval = sys::env::getenv ("TMP");
829
830 if (retval.empty ())
831 retval = R"(c:\temp)";
832 }
833
834 return retval;
835
836#elif defined (P_tmpdir)
837
838 return P_tmpdir;
839
840#else
841
842 return "/tmp";
843
844#endif
845}
846
847DEFUN (clc, , ,
848 doc: /* -*- texinfo -*-
849@deftypefn {} {} clc ()
850@deftypefnx {} {} home ()
851Clear the terminal screen and move the cursor to the upper left corner.
852
853Programming Note: @code{home} is an alias for @code{clc} and can be used
854interchangeably.
855@end deftypefn */)
856{
857 bool skip_redisplay = true;
858
859 command_editor::clear_screen (skip_redisplay);
860
861 return ovl ();
862}
863
864DEFALIAS (home, clc);
865
866DEFUN (getenv, args, ,
867 doc: /* -*- texinfo -*-
868@deftypefn {} {@var{val} =} getenv ("@var{var}")
869Return the value of the environment variable @var{var}.
870
871For example,
872
873@example
874getenv ("PATH")
875@end example
876
877@noindent
878returns a string containing the value of your path.
879@seealso{setenv, unsetenv, isenv}
880@end deftypefn */)
881{
882 if (args.length () != 1)
883 print_usage ();
884
885 std::string name = args(0).string_value ();
886
887 return ovl (sys::env::getenv (name));
888}
889
890/*
891%!assert (ischar (getenv ("OCTAVE_HOME")))
892*/
893
894DEFUN (isenv, args, ,
895 doc: /* -*- texinfo -*-
896@deftypefn {} {@var{tf} =} isenv (@var{var})
897Return true if the variable @var{var} is an environment variable, and false
898otherwise.
899
900For example,
901
902@example
903tf = isenv ("PATH")
904@end example
905
906@noindent
907will typically return true on UNIX systems because @qcode{"PATH"} is an
908environment variable for UNIX.
909@seealso{getenv, setenv, unsetenv}
910@end deftypefn */)
911{
912 if (args.length () != 1)
913 print_usage ();
914
915 std::string name = args(0).xstring_value ("isenv: VAR must be a string");
916
917 return ovl (sys::env::isenv (name));
918}
919
920/*
921%!test
922%! setenv ("dummy_variable_that_cannot_matter", "foobar");
923%! assert (isenv ("dummy_variable_that_cannot_matter"), true);
924%! unsetenv ("dummy_variable_that_cannot_matter");
925%! assert (isenv ("dummy_variable_that_cannot_matter"), false);
926
927%!error <VAR must be a string> isenv (struct ())
928*/
929
930DEFUN (setenv, args, ,
931 doc: /* -*- texinfo -*-
932@deftypefn {} {} setenv ("@var{var}", @var{value})
933@deftypefnx {} {} setenv (@var{var})
934@deftypefnx {} {} putenv (@dots{})
935Set the value of the environment variable @var{var} to @var{value}.
936
937If no @var{value} is specified then the variable will be assigned the null
938string.
939
940Programming Note: @code{putenv} is an alias for @code{setenv} and can be used
941interchangeably.
942@seealso{unsetenv, getenv, isenv}
943@end deftypefn */)
944{
945 int nargin = args.length ();
946
947 if (nargin < 1 || nargin > 2)
948 print_usage ();
949
950 std::string var = args(0).xstring_value ("setenv: VAR must be a string");
951
952 std::string val = (nargin == 2
953 ? args(1).xstring_value ("setenv: VALUE must be a string")
954 : "");
955
956 sys::env::putenv (var, val);
957
958 return ovl ();
959}
960
961DEFALIAS (putenv, setenv);
962
963/*
964%!test
965%! setenv ("dummy_variable_that_cannot_matter", "foobar");
966%! assert (getenv ("dummy_variable_that_cannot_matter"), "foobar");
967%! unsetenv ("dummy_variable_that_cannot_matter");
968%! assert (getenv ("dummy_variable_that_cannot_matter"), "");
969*/
970
971DEFUN (unsetenv, args, ,
972 doc: /* -*- texinfo -*-
973@deftypefn {} {} unsetenv ("@var{var}")
974@deftypefnx {} {@var{status} =} unsetenv ("@var{var}")
975Delete the environment variable @var{var}.
976
977Return 0 if the variable was deleted, or did not exist, and -1 if an error
978occurred.
979@seealso{setenv, getenv, isenv}
980@end deftypefn */)
981{
982 if (args.length () != 1)
983 print_usage ();
984
985 std::string tmp = args(0).string_value ();
986
987 return ovl (sys::unsetenv_wrapper (tmp));
988}
989
990/*
991## Test for unsetenv is in setenv test
992*/
993
994#if defined (OCTAVE_USE_WINDOWS_API)
995
996static void
997reg_close_key_wrapper (HKEY key)
998{
999 RegCloseKey (key);
1000}
1001
1002// This function is also used in ov-java.cc, so don't declare static.
1003// Maybe the functions that use it should be here instead?
1004
1005LONG
1006get_regkey_value (HKEY h_rootkey, const std::string subkey,
1007 const std::string name, octave_value& value)
1008{
1009 LONG result;
1010 HKEY h_subkey;
1011
1012 std::wstring wsubkey = sys::u8_to_wstring (subkey);
1013 result = RegOpenKeyExW (h_rootkey, wsubkey.c_str (), 0, KEY_READ,
1014 &h_subkey);
1015
1016 if (result != ERROR_SUCCESS)
1017 return result;
1018
1019 unwind_action restore_keys ([h_subkey] () { reg_close_key_wrapper (h_subkey); });
1020
1021 std::wstring wname = sys::u8_to_wstring (name);
1022 DWORD length = 0;
1023 result = RegQueryValueExW (h_subkey, wname.c_str (), nullptr, nullptr,
1024 nullptr, &length);
1025 if (result != ERROR_SUCCESS)
1026 return result;
1027
1028 DWORD type = 0;
1029 OCTAVE_LOCAL_BUFFER (BYTE, data, length);
1030 result = RegQueryValueExW (h_subkey, wname.c_str (), nullptr, &type,
1031 data, &length);
1032 if (result != ERROR_SUCCESS)
1033 return result;
1034
1035 if (type == REG_DWORD)
1036 value = octave_int32 (*(reinterpret_cast<DWORD *> (data)));
1037 else if (type == REG_SZ || type == REG_EXPAND_SZ)
1038 {
1039 // strings in registry might not be zero terminated
1040 wchar_t *dataw = reinterpret_cast<wchar_t *> (data);
1041 DWORD lengthw = length / sizeof (wchar_t);
1042 std::wstring reg_string
1043 = std::wstring (dataw, lengthw - (dataw[lengthw-1]==0));
1044 value = string_vector (sys::u8_from_wstring (reg_string));
1045 }
1046
1047 return result;
1048}
1049
1050static LONG
1051get_regkey_names (HKEY h_rootkey, const std::string subkey,
1052 std::list<std::string>& fields)
1053{
1054 LONG retval;
1055 HKEY h_subkey;
1056
1057 fields.clear ();
1058
1059 std::wstring wsubkey = sys::u8_to_wstring (subkey);
1060 retval = RegOpenKeyExW (h_rootkey, wsubkey.c_str (), 0, KEY_READ,
1061 &h_subkey);
1062 if (retval != ERROR_SUCCESS)
1063 return retval;
1064
1065 DWORD idx = 0;
1066 const int MAX_VALUE_NAME_SIZE = 32766;
1067 wchar_t value_name[MAX_VALUE_NAME_SIZE+1];
1068 DWORD value_name_size = MAX_VALUE_NAME_SIZE;
1069
1070 while (true)
1071 {
1072 retval = RegEnumValueW (h_subkey, idx, value_name, &value_name_size,
1073 nullptr, nullptr, nullptr, nullptr);
1074 if (retval != ERROR_SUCCESS)
1075 break;
1076 fields.push_back (sys::u8_from_wstring (value_name));
1077 value_name_size = MAX_VALUE_NAME_SIZE;
1078 idx++;
1079 }
1080
1081 if (retval == ERROR_NO_MORE_ITEMS)
1082 retval = ERROR_SUCCESS;
1083
1084 RegCloseKey (h_subkey);
1085
1086 return retval;
1087}
1088
1089#endif
1090
1091DEFUN (winqueryreg, args, ,
1092 doc: /* -*- texinfo -*-
1093@deftypefn {} {@var{value} =} winqueryreg (@var{rootkey}, @var{subkey}, @var{valuename})
1094@deftypefnx {} {@var{value} =} winqueryreg (@var{rootkey}, @var{subkey})
1095@deftypefnx {} {@var{names} =} winqueryreg (@code{"name"}, @var{rootkey}, @var{subkey})
1096
1097Query names or value from the Windows registry.
1098
1099On Windows, return the value of the registry key @var{subkey} from the root key
1100@var{rootkey}. You can specify the name of the queried registry value with the
1101optional argument @var{valuename}. Otherwise, if called with only two
1102arguments or @var{valuename} is empty, then the default value of @var{subkey}
1103is returned. If the registry value is of type @nospell{@qcode{"REG_DWORD"}}
1104then @var{value} is of class int32. If the value is of the type
1105@nospell{@qcode{"REG_SZ"}} or @nospell{@qcode{"REG_EXPAND_SZ"}} a string is
1106returned.
1107
1108If the first argument is @qcode{"name"}, a cell array of strings with the names
1109of the values at that key is returned.
1110
1111The variable @var{rootkey} must be a string with a valid root key identifier:
1112
1113@table @asis
1114@item @nospell{HKCR}
1115@itemx @nospell{HKEY_CLASSES_ROOT}
1116
1117@item @nospell{HKEY_CURRENT_CONFIG}
1118
1119@item @nospell{HKCU}
1120@itemx @nospell{HKEY_CURRENT_USER}
1121
1122@item @nospell{HKLM}
1123@itemx @nospell{HKEY_LOCAL_MACHINE}
1124
1125
1126@item @nospell{HKU}
1127@itemx @nospell{HKEY_USERS}
1128
1129
1130@item @nospell{HKEY_PERFORMANCE_DATA}
1131
1132@end table
1133
1134Examples:
1135
1136Get a list of value names at the key
1137@nospell{@qcode{'HKCU@backslashchar{}Environment'}}:
1138
1139@example
1140@group
1141@var{valuenames} = winqueryreg ("name", "HKEY_CURRENT_USER", ...
1142 "Environment");
1143@end group
1144@end example
1145
1146For each @var{valuenames}, display the value:
1147
1148@example
1149@group
1150for @var{k} = 1:numel (@var{valuenames})
1151 @var{val} = winqueryreg ("HKEY_CURRENT_USER", "Environment", ...
1152 @var{valuenames}@{@var{k}@});
1153 @var{str} = sprintf ("%s = %s", @var{valuenames}@{@var{k}@}, num2str (@var{val}));
1154 disp (@var{str});
1155endfor
1156@end group
1157@end example
1158
1159On non-Windows platforms this function fails with an error.
1160@end deftypefn */)
1161{
1162#if defined (OCTAVE_USE_WINDOWS_API)
1163 if ((args.length () < 2) || (args.length () > 3))
1164 print_usage ();
1165
1166 // Input check
1167 std::string rootkey_name
1168 = args(0).xstring_value ("winqueryreg: the first argument must be 'name' "
1169 "or a valid ROOTKEY identifier");
1170 std::string subkey_name = "";
1171 std::string value_name = "";
1172 bool get_names = false;
1173 if (rootkey_name.compare ("name") == 0)
1174 {
1175 if (args.length () < 3)
1176 error ("winqueryreg: if the first argument is 'name', "
1177 "ROOTKEY and SUBKEY must be given");
1178 get_names = true;
1179 rootkey_name
1180 = args(1).xstring_value ("winqueryreg: ROOTKEY must be a string");
1181 subkey_name
1182 = args(2).xstring_value ("winqueryreg: SUBKEY must be a string");
1183 }
1184 else
1185 {
1186 subkey_name
1187 = args(1).xstring_value ("winqueryreg: SUBKEY must be a string");
1188
1189 if (args.length () == 3)
1190 value_name
1191 = args(2).xstring_value ("winqueryreg: VALUENAME must be a string");
1192 }
1193
1194 // Get rootkey handle
1195 HKEY h_rootkey;
1196 if (rootkey_name == "HKEY_CLASSES_ROOT" || rootkey_name == "HKCR")
1197 h_rootkey = HKEY_CLASSES_ROOT;
1198 else if (rootkey_name == "HKEY_CURRENT_CONFIG")
1199 h_rootkey = HKEY_CURRENT_CONFIG;
1200 else if (rootkey_name == "HKEY_CURRENT_USER" || rootkey_name == "HKCU")
1201 h_rootkey = HKEY_CURRENT_USER;
1202 else if (rootkey_name == "HKEY_LOCAL_MACHINE" || rootkey_name == "HKLM")
1203 h_rootkey = HKEY_LOCAL_MACHINE;
1204 else if (rootkey_name == "HKEY_PERFORMANCE_DATA")
1205 h_rootkey = HKEY_PERFORMANCE_DATA;
1206 else if (rootkey_name == "HKEY_USERS" || rootkey_name == "HKU")
1207 h_rootkey = HKEY_USERS;
1208 else
1209 error ("winqueryreg: ROOTKEY is not a valid root key identifier");
1210
1211 if (get_names)
1212 {
1213 std::list<std::string> fields;
1214
1215 LONG retval = get_regkey_names (h_rootkey, subkey_name, fields);
1216 if (retval != ERROR_SUCCESS)
1217 error ("winqueryreg: error %ld reading names from registry", retval);
1218
1219 Cell fieldnames (dim_vector (1, fields.size ()));
1220 std::size_t i = 0;
1221 for (const auto& it : fields)
1222 fieldnames(i++) = it;
1223
1224 return ovl (fieldnames);
1225 }
1226 else
1227 {
1228 octave_value key_val;
1229 LONG retval = get_regkey_value (h_rootkey, subkey_name,
1230 value_name, key_val);
1231 if (retval == ERROR_FILE_NOT_FOUND)
1232 error ("winqueryreg: no value found for '%s' at %s\\%s",
1233 value_name.c_str (), rootkey_name.c_str (),
1234 subkey_name.c_str ());
1235 if (retval != ERROR_SUCCESS)
1236 error ("winqueryreg: error %ld reading the specified key", retval);
1237
1238 return ovl (key_val);
1239 }
1240#else
1241
1242 octave_unused_parameter (args);
1243
1244 error ("winqueryreg: function is only supported on Windows platforms");
1245
1246#endif
1247}
1248
1249/*
1250%!testif ; ispc ()
1251%! assert (ischar (winqueryreg ("HKEY_LOCAL_MACHINE",
1252%! 'SOFTWARE\Microsoft\Windows\CurrentVersion',
1253%! "ProgramFilesDir")));
1254%!testif ; ispc ()
1255%! assert (isa (winqueryreg ("HKEY_LOCAL_MACHINE",
1256%! 'SYSTEM\CurrentControlSet\Control\FileSystem',
1257%! "Win31FileSystem"), "int32"));
1258%!testif ; ispc ()
1259%! assert (iscellstr (winqueryreg ("name", "HKEY_LOCAL_MACHINE",
1260%! 'SOFTWARE\Microsoft\Windows\CurrentVersion')));
1261%!testif ; ispc ()
1262%! fail ('winqueryreg (1, ''SOFTWARE\Microsoft\Windows\CurrentVersion'')',
1263%! "first argument must be 'name' or a valid ROOTKEY identifier");
1264%!testif ; ispc ()
1265%! fail ('winqueryreg ("HKEY_LOCAL_MACHINE", 1)', "SUBKEY must be a string");
1266%!testif ; ispc ()
1267%! fail (['winqueryreg ("HKEY_LOCAL_MACHINE", ', ...
1268%! '''SOFTWARE\Microsoft\Windows\CurrentVersion'', 1)'],
1269%! "VALUENAME must be a string");
1270%!testif ; ispc ()
1271%! fail (['winqueryreg ("FOO", ', ...
1272%! '''SOFTWARE\Microsoft\Windows\CurrentVersion'')'],
1273%! "ROOTKEY is not a valid root key identifier");
1274%!testif ; ispc ()
1275%! fail ('winqueryreg ("HKEY_LOCAL_MACHINE", ''FOO\bar'')',
1276%! "no value found for");
1277%!testif ; ispc ()
1278%! fail (['winqueryreg ("HKEY_LOCAL_MACHINE", ', ...
1279%! '''SOFTWARE\Microsoft\Windows\CurrentVersion'', "foo")'],
1280%! "no value found for");
1281%!testif ; ispc ()
1282%! fail ('winqueryreg ("name", "HKEY_LOCAL_MACHINE")',
1283%! "if the first argument is 'name', ROOTKEY and SUBKEY must be given");
1284%!testif ; ispc ()
1285%! fail (['winqueryreg ("name", 1, ', ...
1286%! '''SOFTWARE\Microsoft\Windows\CurrentVersion'')'],
1287%! "ROOTKEY must be a string");
1288%!testif ; ispc ()
1289%! fail ('winqueryreg ("name", "HKEY_LOCAL_MACHINE", 1)',
1290%! "SUBKEY must be a string");
1291*/
1292
1293// FIXME: perhaps kbhit should also be able to print a prompt?
1294
1295DEFMETHOD (kbhit, interp, args, ,
1296 doc: /* -*- texinfo -*-
1297@deftypefn {} {@var{c} =} kbhit ()
1298@deftypefnx {} {@var{c} =} kbhit (1)
1299Read a single keystroke from the keyboard.
1300
1301If called with an argument (typically 1), don't wait for a keypress and
1302immediately return the next keystroke in the keyboard input buffer or an empty
1303string ("") if no keystroke is available.
1304
1305For example,
1306
1307@example
1308c = kbhit ();
1309@end example
1310
1311@noindent
1312will set @var{c} to the next character typed at the keyboard as soon as it is
1313typed.
1314
1315@example
1316c = kbhit (1);
1317@end example
1318
1319@noindent
1320is identical to the above example, but doesn't wait for a keypress, returning
1321the empty string if no key is available.
1322@seealso{input, pause}
1323@end deftypefn */)
1324{
1325 // FIXME: add timeout and default value args?
1326
1327 Fdrawnow (interp);
1328
1329 int c = kbhit (args.length () == 0);
1330
1331 if (c == -1)
1332 c = 0;
1333
1334 char s[2] = { static_cast<char> (c), '\0' };
1335
1336 return octave_value (s);
1337}
1338
1339// State of the pause system
1340static bool Vpause_enabled = true;
1341
1342DEFMETHOD (pause, interp, args, nargout,
1343 doc: /* -*- texinfo -*-
1344@deftypefn {} {} pause ()
1345@deftypefnx {} {} pause (@var{n})
1346@deftypefnx {} {@var{old_state} =} pause ("on")
1347@deftypefnx {} {@var{old_state} =} pause ("off")
1348@deftypefnx {} {@var{old_state} =} pause ("query")
1349Suspend the execution of the program or change the state of the pause function.
1350
1351If invoked without an input arguments then the program is suspended until a
1352character is typed. If argument @var{n} is a positive real value, it indicates
1353the number of seconds the program shall be suspended, for example:
1354
1355@example
1356@group
1357tic; pause (0.05); toc
1358 @print{} Elapsed time is 0.05039 seconds.
1359@end group
1360@end example
1361
1362The following example prints a message and then waits 5 seconds before clearing
1363the screen.
1364
1365@example
1366@group
1367disp ("wait please...");
1368pause (5);
1369clc;
1370@end group
1371@end example
1372
1373If invoked with a string argument @qcode{"on"}, @qcode{"off"}, or
1374@qcode{"query"}, the state of the pause function is changed or queried. When
1375the state is @qcode{"off"}, the pause function returns immediately. The
1376optional return value contains the previous state of the pause function. In
1377the following example pause is disabled locally:
1378
1379@example
1380@group
1381old_state = pause ("off");
1382tic; pause (0.05); toc
1383 @print{} Elapsed time is 3.00407e-05 seconds.
1384pause (old_state);
1385@end group
1386@end example
1387
1388While the program is suspended Octave still handles figures painting and
1389graphics callbacks execution.
1390
1391@seealso{kbhit}
1392@end deftypefn */)
1393{
1394 octave_value_list retval;
1395
1396 int nargin = args.length ();
1397
1398 if (nargin > 1)
1399 print_usage ();
1400
1401 if (nargin == 1 && args(0).is_string ())
1402 {
1403 bool saved_state = Vpause_enabled;
1404 std::string state = args(0).string_value ();
1405
1406 if (state == "on")
1407 Vpause_enabled = true;
1408 else if (state == "off")
1409 Vpause_enabled = false;
1410 else if (state == "query")
1411 ;// Do nothing
1412 else
1413 error (R"(pause: first argument must be "on", "off", or "query")");
1414
1415 if (nargout > 0 || state == "query")
1416 retval.append (saved_state ? "on" : "off");
1417 }
1418 else if (Vpause_enabled)
1419 {
1420 double dval;
1421
1422 if (nargin == 0)
1423 dval = octave_Inf;
1424 else
1425 dval = args(0).xdouble_value ("pause: N must be a scalar real value");
1426
1427 if (math::isnan (dval))
1428 warning ("pause: NaN is an invalid delay");
1429 else
1430 {
1431 Fdrawnow (interp);
1432
1433 sleep (dval, true);
1434 }
1435 }
1436
1437 return retval;
1438}
1439
1440/*
1441%!test
1442%! pause (1);
1443
1444%!error pause (1, 2)
1445*/
1446
1447// FIXME: maybe this should only return 1 if IEEE floating
1448// point functions really work.
1449
1450DEFUN (isieee, , ,
1451 doc: /* -*- texinfo -*-
1452@deftypefn {} {@var{tf} =} isieee ()
1453Return true if your computer @emph{claims} to conform to the IEEE@tie{}754
1454standard for floating point calculations.
1455
1456No actual tests are performed.
1457@end deftypefn */)
1458{
1459 mach_info::float_format flt_fmt = mach_info::native_float_format ();
1460
1461 return ovl (flt_fmt == mach_info::flt_fmt_ieee_little_endian
1462 || flt_fmt == mach_info::flt_fmt_ieee_big_endian);
1463}
1464
1465/*
1466%!assert (islogical (isieee ()))
1467*/
1468
1470 doc: /* -*- texinfo -*-
1471@deftypefn {} {@var{fmtstr} =} native_float_format ()
1472Return the native floating point format as a string.
1473@end deftypefn */)
1474{
1475 mach_info::float_format flt_fmt = mach_info::native_float_format ();
1476
1477 return ovl (mach_info::float_format_as_string (flt_fmt));
1478}
1479
1480/*
1481%!assert (ischar (native_float_format ()))
1482*/
1483
1484DEFUN (tilde_expand, args, ,
1485 doc: /* -*- texinfo -*-
1486@deftypefn {} {@var{newstr} =} tilde_expand (@var{string})
1487@deftypefnx {} {@var{newcstr} =} tilde_expand (@var{cellstr})
1488Perform tilde expansion on @var{string}.
1489
1490If @var{string} begins with a tilde character, (@samp{~}), all of the
1491characters preceding the first slash (or all characters, if there is no
1492slash) are treated as a possible user name, and the tilde and the following
1493characters up to the slash are replaced by the home directory of the named
1494user. If the tilde is followed immediately by a slash, the tilde is
1495replaced by the home directory of the user running Octave.
1496
1497If the input is a cell array of strings @var{cellstr} then tilde expansion
1498is performed on each string element.
1499
1500Examples:
1501
1502@example
1503@group
1504tilde_expand ("~joeuser/bin")
1505 @xresult{} "/home/joeuser/bin"
1506tilde_expand ("~/bin")
1507 @xresult{} "/home/jwe/bin"
1508@end group
1509@end example
1510@end deftypefn */)
1511{
1512 if (args.length () != 1)
1513 print_usage ();
1514
1515 octave_value arg = args(0);
1516
1517 string_vector sv =
1518 arg.xstring_vector_value ("tilde_expand: argument must be char or cellstr object");
1519
1520 sv = sys::file_ops::tilde_expand (sv);
1521
1522 if (arg.iscellstr ())
1523 return ovl (Cell (arg.dims (), sv));
1524 else
1525 return ovl (sv);
1526}
1527
1528/*
1529%!testif ; isfolder ("~")
1530%! home = get_home_directory ();
1531%! assert (tilde_expand ("~/foobar"), [home "/foobar"]);
1532%! assert (tilde_expand ("/foo/bar"), "/foo/bar");
1533%! assert (tilde_expand ("foo/bar"), "foo/bar");
1534*/
1535
1536DEFUN (get_home_directory, , ,
1537 doc: /* -*- texinfo -*-
1538@deftypefn {} {@var{homedir} =} get_home_directory ()
1539Return the current home directory.
1540
1541On most systems, this is equivalent to @code{getenv ("HOME")}. On Windows
1542systems, if the environment variable @env{HOME} is not set then it is
1543equivalent to
1544@code{fullfile (getenv ("HOMEDRIVE"), getenv ("HOMEPATH"))}
1545@seealso{getenv}
1546@end deftypefn */)
1547{
1548 return ovl (sys::env::get_home_directory ());
1549}
1550
1551/*
1552%!test
1553%! HOME = getenv ("HOME");
1554%! unwind_protect
1555%! setenv ("HOME", P_tmpdir ());
1556%! assert (get_home_directory (), getenv ("HOME"));
1557%! unwind_protect_cleanup
1558%! if (isempty (HOME))
1559%! unsetenv ("HOME");
1560%! else
1561%! setenv ("HOME", HOME);
1562%! endif
1563%! end_unwind_protect
1564*/
1565
1566DEFUN (__blas_version__, , ,
1567 doc: /* -*- texinfo -*-
1568@deftypefn {} {@var{verstr} =} __blas_version__ ()
1569Undocumented internal function.
1570@end deftypefn */)
1571{
1572 return ovl (sys::blas_version ());
1573}
1574
1575DEFUN (__lapack_version__, , ,
1576 doc: /* -*- texinfo -*-
1577@deftypefn {} {@var{verstr} =} __lapack_version__ ()
1578Undocumented internal function.
1579@end deftypefn */)
1580{
1581 return ovl (sys::lapack_version ());
1582}
1583
1584OCTAVE_END_NAMESPACE(octave)
Definition Cell.h:41
static bool forced_interactive()
Definition octave.cc:342
static bool prefer_env_winsize(bool)
Definition cmd-edit.cc:1614
static void clear_screen(bool skip_redisplay=false)
Definition cmd-edit.cc:1252
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:92
bool interactive() const
void setfield(const std::string &key, const octave_value &val)
Definition oct-map.cc:190
octave_value_list & append(const octave_value &val)
Definition ovl.cc:98
octave_idx_type length() const
Definition ovl.h:111
string_vector xstring_vector_value(const char *fmt,...) const
bool iscellstr() const
Definition ov.h:605
dim_vector dims() const
Definition ov.h:539
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
std::string bin_dir()
Definition defaults.cc:182
void print_usage()
Definition defun-int.h:72
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition defun.h:111
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition defun.h:56
#define DEFALIAS(alias, name)
Macro to define an alias for another existing function name.
Definition defun.h:160
void warning(const char *fmt,...)
Definition error.cc:1083
void error(const char *fmt,...)
Definition error.cc:1008
void warn_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition errwarn.cc:319
std::string tilde_expand(const std::string &name)
Definition file-ops.cc:289
octave_value_list Fdrawnow(octave::interpreter &interp, const octave_value_list &args, int)
interpreter & __get_interpreter__()
#define octave_Inf
Definition lo-ieee.h:40
float_format native_float_format()
Definition mach-info.cc:66
octave_int< int32_t > octave_int32
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition oct-locbuf.h:44
T::size_type strlen(const typename T::value_type *str)
Definition oct-string.cc:95
#define ECHO
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition ovl.h:217
interrupt_handler ignore_interrupts()
interrupt_handler set_interrupt_handler(const interrupt_handler &h, bool restart_syscalls)
F77_RET_T const F77_DBLE const F77_DBLE * f
int kbhit(bool wait)
Definition sysdep.cc:764
int pclose(FILE *f)
Definition sysdep.cc:729
void sysdep_cleanup()
Definition sysdep.cc:465
FILE * popen(const char *command, const char *mode)
Definition sysdep.cc:640
std::string get_P_tmpdir()
Definition sysdep.cc:809
void raw_mode(bool on, bool wait)
Definition sysdep.cc:486
void sysdep_init()
Definition sysdep.cc:439
#define FSYSTEM_OPEN_STR
void set_application_id()
Definition sysdep.cc:186
bool drive_or_unc_share(const std::string &name)
Definition sysdep.cc:389
#define STDIN_FILENO
Definition sysdep.cc:92
octave_value_list Fsystem(const octave_value_list &args, int nargout)
Definition toplev.cc:240
int octave_isatty_wrapper(int fd)
void sleep(double seconds, bool do_graphics_events)
Definition utils.cc:1577
F77_RET_T len
Definition xerbla.cc:61