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