1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1995-2021 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 <cerrno>
31 #include <cstdlib>
32
33 #include <new>
34 #include <sstream>
35 #include <string>
36
37 #if defined (OCTAVE_USE_WINDOWS_API)
38 # define WIN32_LEAN_AND_MEAN 1
39 # include <windows.h>
40 #endif
41
42 #include "async-system-wrapper.h"
43 #include "child-list.h"
44 #include "lo-error.h"
45 #include "oct-fftw.h"
46 #include "oct-locbuf.h"
47 #include "oct-syscalls.h"
48 #include "signal-wrappers.h"
49 #include "str-vec.h"
50 #include "wait-for-input.h"
51
52 #include "build-env.h"
53 #include "liboctinterp-build-info.h"
54 #include "defaults.h"
55 #include "defun.h"
56 #include "error.h"
57 #include "file-io.h"
58 #include "help.h"
59 #include "interpreter-private.h"
60 #include "octave.h"
61 #include "oct-map.h"
62 #include "ovl.h"
63 #include "ov.h"
64 #include "pager.h"
65 #include "procstream.h"
66 #include "sysdep.h"
67 #include "unwind-prot.h"
68 #include "utils.h"
69 #include "version.h"
70
71 #if ! defined (SHELL_PATH)
72 # define SHELL_PATH "/bin/sh"
73 #endif
74
75 DEFUN (warranty, , ,
76 doc: /* -*- texinfo -*-
77 @deftypefn {} {} warranty ()
78 Describe the conditions for copying and distributing Octave.
79 @end deftypefn */)
80 {
81 octave_stdout << "\n" << octave_name_version_and_copyright () << "\n\
82 \n\
83 GNU Octave is free software: you can redistribute it and/or modify it\n\
84 under the terms of the GNU General Public License as published by\n\
85 the Free Software Foundation, either version 3 of the License, or\n\
86 (at your option) any later version.\n\
87 \n\
88 GNU Octave is distributed in the hope that it will be useful, but\n\
89 WITHOUT ANY WARRANTY; without even the implied warranty of\n\
90 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
91 GNU General Public License for more details.\n\
92 \n\
93 You should have received a copy of the GNU General Public License\n\
94 along with GNU Octave; see the file COPYING. If not, see\n\
95 <https://www.gnu.org/licenses/>.\n\
96 \n";
97
98 return ovl ();
99 }
100
101 // Execute a shell command.
102
103 static octave_value_list
run_command_and_return_output(const std::string & cmd_str)104 run_command_and_return_output (const std::string& cmd_str)
105 {
106 octave_value_list retval;
107 octave::unwind_protect frame;
108
109 iprocstream *cmd = new iprocstream (cmd_str.c_str ());
110 frame.add_delete (cmd);
111
112 octave::child_list& kids
113 = octave::__get_child_list__ ("run_command_and_return_output");
114 frame.add_method (kids, &octave::child_list::remove, cmd->pid ());
115
116 if (! *cmd)
117 error ("system: unable to start subprocess for '%s'", cmd_str.c_str ());
118
119 int fid = cmd->file_number ();
120
121 std::ostringstream output_buf;
122
123 char ch;
124
125 for (;;)
126 {
127 if (cmd->get (ch))
128 output_buf.put (ch);
129 else
130 {
131 if (! cmd->eof () && errno == EAGAIN)
132 {
133 cmd->clear ();
134
135 if (octave_wait_for_input (fid) != 1)
136 break;
137 }
138 else
139 break;
140 }
141 }
142
143 int cmd_status = cmd->close ();
144
145 if (octave::sys::wifexited (cmd_status))
146 cmd_status = octave::sys::wexitstatus (cmd_status);
147 else
148 cmd_status = 127;
149
150 retval = ovl (cmd_status, output_buf.str ());
151
152 return retval;
153 }
154
155 // Combine alloc+get in one action.
156
157 static void *
get_signal_mask(void)158 get_signal_mask (void)
159 {
160 void *mask = octave_alloc_signal_mask ();
161
162 octave_get_signal_mask (mask);
163
164 return mask;
165 }
166
167 // Combine set+free in one action.
168
169 static void
restore_signal_mask(void * mask)170 restore_signal_mask (void *mask)
171 {
172 octave_set_signal_mask (mask);
173
174 octave_free_signal_mask (mask);
175 }
176
177 enum system_exec_type { et_sync, et_async };
178
179 DEFUN (system, args, nargout,
180 doc: /* -*- texinfo -*-
181 @deftypefn {} {} system ("@var{string}")
182 @deftypefnx {} {} system ("@var{string}", @var{return_output})
183 @deftypefnx {} {} system ("@var{string}", @var{return_output}, @var{type})
184 @deftypefnx {} {[@var{status}, @var{output}] =} system (@dots{})
185 Execute a shell command specified by @var{string}.
186
187 If @var{system} is called with one or more output arguments, or if the optional
188 argument @var{return_output} is true and the subprocess is started
189 synchronously, then the output from the command is returned as a variable.
190 Otherwise, if the subprocess is executed synchronously, its output is sent to
191 the standard output. To send the output of a command executed with
192 @code{system} through the pager, use a command like
193
194 @example
195 @group
196 [~, text] = system ("cmd");
197 more on;
198 disp (text);
199 @end group
200 @end example
201
202 @noindent
203 or
204
205 @example
206 @group
207 more on;
208 printf ("%s\n", nthargout (2, "system", "cmd"));
209 @end group
210 @end example
211
212 If the optional argument @var{type} is @qcode{"async"}, the process is started
213 in the background and the process ID of the child process is returned
214 immediately. Otherwise, the child process is started and Octave waits until it
215 exits. If the @var{type} argument is omitted, it defaults to the value
216 @qcode{"sync"}.
217
218 The @code{system} function can return two values. The first is the exit status
219 of the command and the second is any output from the command that was written
220 to the standard output stream. For example,
221
222 @example
223 [status, output] = system ("echo foo & exit 2");
224 @end example
225
226 @noindent
227 will set the variable @var{output} to the string @samp{foo}, and the variable
228 @var{status} to the integer @samp{2}.
229
230 For commands run asynchronously, @var{status} is the process id of the command
231 shell that is started to run the command.
232
233 The shell used for executing commands varies with operating system and is
234 typically @file{/bin/sh} for UNIX systems and @nospell{@file{cmd.exe}} for
235 Windows systems.
236 @seealso{unix, dos}
237 @end deftypefn */)
238 {
239 int nargin = args.length ();
240
241 if (nargin == 0 || nargin > 3)
242 print_usage ();
243
244 system_exec_type type = et_sync;
245 if (nargin == 3)
246 {
247 std::string type_str = args(2).xstring_value ("system: TYPE must be a string");
248
249 if (type_str == "sync")
250 type = et_sync;
251 else if (type_str == "async")
252 type = et_async;
253 else
254 error (R"(system: TYPE must be "sync" or "async")");
255 }
256
257 octave_value_list retval;
258
259 bool return_output = (nargin == 1 && nargout > 1);
260
261 if (nargin > 1)
262 {
263 try
264 {
265 return_output = args(1).is_true ();
266 }
267 catch (octave::execution_exception& e)
268 {
269 error (e, "system: RETURN_OUTPUT must be boolean value true or false");
270 }
271 }
272
273 if (return_output && type == et_async)
274 error ("system: can't return output from commands run asynchronously");
275
276 std::string cmd_str = args(0).xstring_value ("system: first argument must be a string");
277
278 #if defined (OCTAVE_USE_WINDOWS_API)
279 // Work around weird double-quote handling on Windows systems.
280 if (type == et_sync)
281 cmd_str = '"' + cmd_str + '"';
282 #endif
283
284 octave::unwind_protect frame;
285
286 frame.add_fcn (restore_signal_mask, get_signal_mask ());
287
288 octave_unblock_async_signals ();
289 octave_unblock_signal_by_name ("SIGTSTP");
290
291 if (type == et_async)
292 retval(0) = octave_async_system_wrapper (cmd_str.c_str ());
293 else if (return_output)
294 retval = run_command_and_return_output (cmd_str);
295 else
296 {
297 int status = system (cmd_str.c_str ());
298
299 // The value in status is as returned by waitpid. If
300 // the process exited normally, extract the actual exit
301 // status of the command. Otherwise, return 127 as a
302 // failure code.
303
304 if (octave::sys::wifexited (status))
305 status = octave::sys::wexitstatus (status);
306
307 retval(0) = status;
308 }
309
310 return retval;
311 }
312
313 /*
314 %!test
315 %! cmd = ls_command ();
316 %! [status, output] = system (cmd);
317 %! assert (status, 0);
318 %! assert (ischar (output));
319 %! assert (! isempty (output));
320
321 %!error system ()
322 %!error system (1, 2, 3)
323 */
324
325 static octave_value
find_config_info(const octave_scalar_map & m,const std::string & key)326 find_config_info (const octave_scalar_map& m, const std::string& key)
327 {
328 if (m.isfield (key))
329 {
330 Cell c = m.contents (key);
331
332 if (! c.isempty ())
333 return c(0);
334 }
335
336 return octave_value ();
337 }
338
339 DEFUN (__octave_config_info__, args, ,
340 doc: /* -*- texinfo -*-
341 @deftypefn {} {} __octave_config_info__ ()
342 @deftypefnx {} {} __octave_config_info__ (@var{option})
343 Return a structure containing configuration and installation information for
344 Octave.
345
346 If @var{option} is a string, return the configuration information for the
347 specified option.
348
349 @seealso{computer}
350 @end deftypefn */)
351 {
352 static octave_scalar_map config;
353 static octave_scalar_map build_env;
354 static octave_scalar_map build_features;
355
356 static bool initialized = false;
357
358 if (! initialized)
359 {
360 std::map<std::string, octave_value> conf_info_map
361 = {{ "DEFAULT_PAGER", octave::config::default_pager () },
362
363 #if defined (OCTAVE_ENABLE_64)
364 { "ENABLE_64", true },
365 #else
366 { "ENABLE_64", false },
367 #endif
368
369 #if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)
370 { "ENABLE_COMMAND_LINE_PUSH_PARSER", true },
371 #else
372 { "ENABLE_COMMAND_LINE_PUSH_PARSER", false },
373 #endif
374
375 #if defined (ENABLE_DOCS)
376 { "ENABLE_DOCS", true },
377 #else
378 { "ENABLE_DOCS", false },
379 #endif
380
381 #if defined (OCTAVE_ENABLE_FLOAT_TRUNCATE)
382 { "ENABLE_FLOAT_TRUNCATE", true },
383 #else
384 { "ENABLE_FLOAT_TRUNCATE", false },
385 #endif
386
387 #if defined (ENABLE_JIT)
388 { "ENABLE_JIT", true },
389 #else
390 { "ENABLE_JIT", false },
391 #endif
392
393 #if defined (OCTAVE_ENABLE_OPENMP)
394 { "ENABLE_OPENMP", true },
395 #else
396 { "ENABLE_OPENMP", false },
397 #endif
398
399 { "api_version", OCTAVE_API_VERSION },
400 { "archlibdir", octave::config::arch_lib_dir () },
401 { "bindir", octave::config::bin_dir () },
402 { "canonical_host_type", octave::config::canonical_host_type () },
403 { "datadir", octave::config::data_dir () },
404 { "datarootdir", octave::config::dataroot_dir () },
405 { "fcnfiledir", octave::config::fcn_file_dir () },
406 { "fftw_version", octave::fftw_version () },
407 { "fftwf_version", octave::fftwf_version () },
408 { "imagedir", octave::config::image_dir () },
409 { "includedir", octave::config::include_dir () },
410 { "infodir", octave::config::info_dir () },
411 { "libdir", octave::config::lib_dir () },
412 { "libexecdir", octave::config::libexec_dir () },
413 // Each library and executable has its own definition of the hg
414 // id. We check for consistency when Octave starts so we just
415 // store and report one of them here.
416 { "hg_id", liboctinterp_hg_id () },
417 { "localapiarchlibdir", octave::config::local_api_arch_lib_dir () },
418 { "localapifcnfiledir", octave::config::local_api_fcn_file_dir () },
419 { "localapioctfiledir", octave::config::local_api_oct_file_dir () },
420 { "localarchlibdir", octave::config::local_arch_lib_dir () },
421 { "localfcnfiledir", octave::config::local_fcn_file_dir () },
422 { "localoctfiledir", octave::config::local_oct_file_dir () },
423 { "localstartupfiledir", octave::config::local_startupfile_dir () },
424 { "localverarchlibdir", octave::config::local_ver_arch_lib_dir () },
425 { "localverfcnfiledir", octave::config::local_ver_fcn_file_dir () },
426 { "localveroctfiledir", octave::config::local_ver_oct_file_dir () },
427 { "man1dir", octave::config::man1_dir () },
428 { "man1ext", octave::config::man1_ext () },
429 { "mandir", octave::config::man_dir () },
430 { "octdatadir", octave::config::oct_data_dir () },
431 { "octdocdir", octave::config::oct_doc_dir () },
432 { "octetcdir", octave::config::oct_etc_dir () },
433 { "octfiledir", octave::config::oct_file_dir () },
434 { "octfontsdir", octave::config::oct_fonts_dir () },
435 { "octincludedir", octave::config::oct_include_dir () },
436 { "octlibdir", octave::config::oct_lib_dir () },
437 { "octtestsdir", octave::config::oct_tests_dir () },
438 { "release_date", OCTAVE_RELEASE_DATE },
439 { "startupfiledir", octave::config::startupfile_dir () },
440 { "version", OCTAVE_VERSION }};
441
442 std::map<std::string, octave_value> build_env_map
443 = {{ "AMD_CPPFLAGS", octave::build_env::AMD_CPPFLAGS },
444 { "AMD_LDFLAGS", octave::build_env::AMD_LDFLAGS },
445 { "AMD_LIBS", octave::build_env::AMD_LIBS },
446 { "AR", octave::build_env::AR },
447 { "ARFLAGS", octave::build_env::ARFLAGS },
448 { "ARPACK_CPPFLAGS", octave::build_env::ARPACK_CPPFLAGS },
449 { "ARPACK_LDFLAGS", octave::build_env::ARPACK_LDFLAGS },
450 { "ARPACK_LIBS", octave::build_env::ARPACK_LIBS },
451 { "BLAS_LIBS", octave::build_env::BLAS_LIBS },
452 { "CAMD_CPPFLAGS", octave::build_env::CAMD_CPPFLAGS },
453 { "CAMD_LDFLAGS", octave::build_env::CAMD_LDFLAGS },
454 { "CAMD_LIBS", octave::build_env::CAMD_LIBS },
455 { "CARBON_LIBS", octave::build_env::CARBON_LIBS },
456 { "CC", octave::build_env::CC },
457 { "CCOLAMD_CPPFLAGS", octave::build_env::CCOLAMD_CPPFLAGS },
458 { "CCOLAMD_LDFLAGS", octave::build_env::CCOLAMD_LDFLAGS },
459 { "CCOLAMD_LIBS", octave::build_env::CCOLAMD_LIBS },
460 { "CFLAGS", octave::build_env::CFLAGS },
461 { "CHOLMOD_CPPFLAGS", octave::build_env::CHOLMOD_CPPFLAGS },
462 { "CHOLMOD_LDFLAGS", octave::build_env::CHOLMOD_LDFLAGS },
463 { "CHOLMOD_LIBS", octave::build_env::CHOLMOD_LIBS },
464 { "COLAMD_CPPFLAGS", octave::build_env::COLAMD_CPPFLAGS },
465 { "COLAMD_LDFLAGS", octave::build_env::COLAMD_LDFLAGS },
466 { "COLAMD_LIBS", octave::build_env::COLAMD_LIBS },
467 { "CPICFLAG", octave::build_env::CPICFLAG },
468 { "CPPFLAGS", octave::build_env::CPPFLAGS },
469 { "CURL_CPPFLAGS", octave::build_env::CURL_CPPFLAGS },
470 { "CURL_LDFLAGS", octave::build_env::CURL_LDFLAGS },
471 { "CURL_LIBS", octave::build_env::CURL_LIBS },
472 { "CXSPARSE_CPPFLAGS", octave::build_env::CXSPARSE_CPPFLAGS },
473 { "CXSPARSE_LDFLAGS", octave::build_env::CXSPARSE_LDFLAGS },
474 { "CXSPARSE_LIBS", octave::build_env::CXSPARSE_LIBS },
475 { "CXX", octave::build_env::CXX },
476 { "CXXCPP", octave::build_env::CXXCPP },
477 { "CXXFLAGS", octave::build_env::CXXFLAGS },
478 { "CXXPICFLAG", octave::build_env::CXXPICFLAG },
479 { "DEFS", octave::build_env::DEFS },
480 { "DL_LDFLAGS", octave::build_env::DL_LDFLAGS },
481 { "GCC_VERSION", octave::build_env::GCC_VERSION },
482 { "GXX_VERSION", octave::build_env::GXX_VERSION },
483 { "EXEEXT", octave::build_env::EXEEXT },
484 { "F77", octave::build_env::F77 },
485 { "F77_FLOAT_STORE_FLAG", octave::build_env::F77_FLOAT_STORE_FLAG },
486 { "F77_INTEGER_8_FLAG", octave::build_env::F77_INTEGER_8_FLAG },
487 { "FFLAGS", octave::build_env::FFLAGS },
488 { "FFTW3_CPPFLAGS", octave::build_env::FFTW3_CPPFLAGS },
489 { "FFTW3_LDFLAGS", octave::build_env::FFTW3_LDFLAGS },
490 { "FFTW3_LIBS", octave::build_env::FFTW3_LIBS },
491 { "FFTW3F_CPPFLAGS", octave::build_env::FFTW3F_CPPFLAGS },
492 { "FFTW3F_LDFLAGS", octave::build_env::FFTW3F_LDFLAGS },
493 { "FFTW3F_LIBS", octave::build_env::FFTW3F_LIBS },
494 { "FLIBS", octave::build_env::FLIBS },
495 { "FLTK_CPPFLAGS", octave::build_env::FLTK_CPPFLAGS },
496 { "FLTK_LDFLAGS", octave::build_env::FLTK_LDFLAGS },
497 { "FLTK_LIBS", octave::build_env::FLTK_LIBS },
498 { "FONTCONFIG_CPPFLAGS", octave::build_env::FONTCONFIG_CPPFLAGS },
499 { "FONTCONFIG_LIBS", octave::build_env::FONTCONFIG_LIBS },
500 { "FPICFLAG", octave::build_env::FPICFLAG },
501 { "FT2_CPPFLAGS", octave::build_env::FT2_CPPFLAGS },
502 { "FT2_LIBS", octave::build_env::FT2_LIBS },
503 { "GLPK_CPPFLAGS", octave::build_env::GLPK_CPPFLAGS },
504 { "GLPK_LDFLAGS", octave::build_env::GLPK_LDFLAGS },
505 { "GLPK_LIBS", octave::build_env::GLPK_LIBS },
506 { "GNUPLOT", octave::build_env::GNUPLOT },
507 { "HDF5_CPPFLAGS", octave::build_env::HDF5_CPPFLAGS },
508 { "HDF5_LDFLAGS", octave::build_env::HDF5_LDFLAGS },
509 { "HDF5_LIBS", octave::build_env::HDF5_LIBS },
510 { "LAPACK_LIBS", octave::build_env::LAPACK_LIBS },
511 { "LDFLAGS", octave::build_env::LDFLAGS },
512 { "LD_STATIC_FLAG", octave::build_env::LD_STATIC_FLAG },
513 { "LEX", octave::build_env::LEX },
514 { "LEXLIB", octave::build_env::LEXLIB },
515 { "LFLAGS", octave::build_env::LFLAGS },
516 { "LIBOCTAVE", octave::build_env::LIBOCTAVE },
517 { "LIBOCTINTERP", octave::build_env::LIBOCTINTERP },
518 { "LIBS", octave::build_env::LIBS },
519 { "LLVM_CPPFLAGS", octave::build_env::LLVM_CPPFLAGS },
520 { "LLVM_LDFLAGS", octave::build_env::LLVM_LDFLAGS },
521 { "LLVM_LIBS", octave::build_env::LLVM_LIBS },
522 { "LN_S", octave::build_env::LN_S },
523 { "MAGICK_CPPFLAGS", octave::build_env::MAGICK_CPPFLAGS },
524 { "MAGICK_LDFLAGS", octave::build_env::MAGICK_LDFLAGS },
525 { "MAGICK_LIBS", octave::build_env::MAGICK_LIBS },
526 { "MKOCTFILE_DL_LDFLAGS", octave::build_env::MKOCTFILE_DL_LDFLAGS },
527 { "OCTAVE_LINK_DEPS", octave::build_env::OCTAVE_LINK_DEPS },
528 { "OCTAVE_LINK_OPTS", octave::build_env::OCTAVE_LINK_OPTS },
529 { "OCT_LINK_DEPS", octave::build_env::OCT_LINK_DEPS },
530 { "OCT_LINK_OPTS", octave::build_env::OCT_LINK_OPTS },
531 { "OPENGL_LIBS", octave::build_env::OPENGL_LIBS },
532 { "PCRE_CPPFLAGS", octave::build_env::PCRE_CPPFLAGS },
533 { "PCRE_LDFLAGS", octave::build_env::PCRE_LDFLAGS },
534 { "PCRE_LIBS", octave::build_env::PCRE_LIBS },
535 { "PTHREAD_CFLAGS", octave::build_env::PTHREAD_CFLAGS },
536 { "PTHREAD_LIBS", octave::build_env::PTHREAD_LIBS },
537 { "QHULL_CPPFLAGS", octave::build_env::QHULL_CPPFLAGS },
538 { "QHULL_LDFLAGS", octave::build_env::QHULL_LDFLAGS },
539 { "QHULL_LIBS", octave::build_env::QHULL_LIBS },
540 { "QRUPDATE_CPPFLAGS", octave::build_env::QRUPDATE_CPPFLAGS },
541 { "QRUPDATE_LDFLAGS", octave::build_env::QRUPDATE_LDFLAGS },
542 { "QRUPDATE_LIBS", octave::build_env::QRUPDATE_LIBS },
543 { "QT_CPPFLAGS", octave::build_env::QT_CPPFLAGS },
544 { "QT_LDFLAGS", octave::build_env::QT_LDFLAGS },
545 { "QT_LIBS", octave::build_env::QT_LIBS },
546 { "QT_OPENGL_LIBS", octave::build_env::QT_OPENGL_LIBS },
547 { "RANLIB", octave::build_env::RANLIB },
548 { "RDYNAMIC_FLAG", octave::build_env::RDYNAMIC_FLAG },
549 { "READLINE_LIBS", octave::build_env::READLINE_LIBS },
550 { "SHARED_LIBS", octave::build_env::SHARED_LIBS },
551 { "SH_LDFLAGS", octave::build_env::SH_LDFLAGS },
552 { "STATIC_LIBS", octave::build_env::STATIC_LIBS },
553 { "SUITESPARSECONFIG_LIBS", octave::build_env::SUITESPARSECONFIG_LIBS },
554 { "TERM_LIBS", octave::build_env::TERM_LIBS },
555 { "UMFPACK_CPPFLAGS", octave::build_env::UMFPACK_CPPFLAGS },
556 { "UMFPACK_LDFLAGS", octave::build_env::UMFPACK_LDFLAGS },
557 { "UMFPACK_LIBS", octave::build_env::UMFPACK_LIBS },
558 { "WARN_CFLAGS", octave::build_env::WARN_CFLAGS },
559 { "WARN_CXXFLAGS", octave::build_env::WARN_CXXFLAGS },
560 { "X11_INCFLAGS", octave::build_env::X11_INCFLAGS },
561 { "X11_LIBS", octave::build_env::X11_LIBS },
562 { "XTRA_CFLAGS", octave::build_env::XTRA_CFLAGS },
563 { "XTRA_CXXFLAGS", octave::build_env::XTRA_CXXFLAGS },
564 { "YACC", octave::build_env::YACC },
565 { "YFLAGS", octave::build_env::YFLAGS },
566 { "Z_CPPFLAGS", octave::build_env::Z_CPPFLAGS },
567 { "Z_LDFLAGS", octave::build_env::Z_LDFLAGS },
568 { "Z_LIBS", octave::build_env::Z_LIBS },
569 { "config_opts", octave::build_env::config_opts }};
570
571 config = octave_scalar_map (conf_info_map);
572 build_env = octave_scalar_map (build_env_map);
573 build_features = octave::build_env::features ();
574
575 bool unix_system = true;
576 bool mac_system = false;
577 bool windows_system = false;
578
579 #if defined (__WIN32__)
580 windows_system = true;
581 #if ! defined (__CYGWIN__)
582 unix_system = false;
583 #endif
584 #endif
585
586 #if defined (OCTAVE_USE_OS_X_API)
587 mac_system = true;
588 #endif
589
590 config.assign ("unix", octave_value (unix_system));
591 config.assign ("mac", octave_value (mac_system));
592 config.assign ("windows", octave_value (windows_system));
593
594 octave::mach_info::float_format ff = octave::mach_info::native_float_format ();
595 config.assign ("float_format",
596 octave_value (octave::mach_info::float_format_as_string (ff)));
597
598 config.assign ("words_big_endian",
599 octave_value (octave::mach_info::words_big_endian ()));
600
601 config.assign ("words_little_endian",
602 octave_value (octave::mach_info::words_little_endian ()));
603
604 config.assign ("build_environment", octave_value (build_env));
605
606 config.assign ("build_features", octave_value (build_features));
607
608 initialized = true;
609 }
610
611 int nargin = args.length ();
612
613 if (nargin > 1)
614 print_usage ();
615
616 octave_value_list retval;
617
618 if (nargin == 1)
619 {
620 std::string arg = args(0).xstring_value ("__octave_config_info__: OPTION argument must be a string");
621
622 octave_value info = find_config_info (config, arg);
623
624 if (info.is_undefined ())
625 info = find_config_info (build_env, arg);
626
627 if (info.is_undefined ())
628 info = find_config_info (build_features, arg);
629
630 if (info.is_undefined ())
631 error ("__octave_config_info__: no info for '%s'", arg.c_str ());
632
633 return info;
634 }
635 else
636 retval = ovl (config);
637
638 return retval;
639 }
640
641 /*
642 %!assert (ischar (__octave_config_info__ ("version")))
643 %!assert (__octave_config_info__ ("version"), OCTAVE_VERSION ())
644 %!test
645 %! x = __octave_config_info__ ();
646 %! assert (isstruct (x));
647 %! assert (! isempty (x));
648 %! assert (x.version, OCTAVE_VERSION ());
649
650 %!error __octave_config_info__ (1, 2)
651 */
652
653 #if defined (__GNUG__) && defined (DEBUG_NEW_DELETE)
654
655 int debug_new_delete = 0;
656
657 typedef void (*vfp)(void);
658 extern vfp __new_handler;
659
660 void *
__builtin_new(std::size_t sz)661 __builtin_new (std::size_t sz)
662 {
663 void *p;
664
665 // malloc (0) is unpredictable; avoid it.
666 if (sz == 0)
667 sz = 1;
668 p = std::malloc (sz);
669 while (p == 0)
670 {
671 (*__new_handler) ();
672 p = std::malloc (sz);
673 }
674
675 if (debug_new_delete)
676 std::cerr << "__builtin_new: " << p << std::endl;
677
678 return p;
679 }
680
681 void
__builtin_delete(void * ptr)682 __builtin_delete (void *ptr)
683 {
684 if (debug_new_delete)
685 std::cerr << "__builtin_delete: " << ptr << std::endl;
686
687 free (ptr);
688 }
689
690 #endif
691