1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2002-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 (octave_interpreter_h)
27 #define octave_interpreter_h 1
28 
29 #include "octave-config.h"
30 
31 #include <map>
32 #include <stack>
33 #include <string>
34 
35 #include "child-list.h"
36 #include "oct-time.h"
37 #include "quit.h"
38 #include "str-vec.h"
39 
40 #include "cdef-manager.h"
41 #include "display.h"
42 #include "dynamic-ld.h"
43 #include "environment.h"
44 #include "error.h"
45 #include "event-manager.h"
46 #include "graphics.h"
47 #include "gtk-manager.h"
48 #include "help.h"
49 #include "input.h"
50 #include "load-path.h"
51 #include "load-save.h"
52 #include "oct-hist.h"
53 #include "oct-stream.h"
54 #include "ov-typeinfo.h"
55 #include "pager.h"
56 #include "pt-eval.h"
57 #include "settings.h"
58 #include "symtab.h"
59 #include "url-handle-manager.h"
60 
61 extern OCTINTERP_API bool quit_allowed;
62 
63 // TRUE means we are ready to interpret commands, but not everything
64 // is ready for interactive use.
65 extern OCTINTERP_API bool octave_interpreter_ready;
66 
67 // TRUE means we've processed all the init code and we are good to go.
68 extern OCTINTERP_API bool octave_initialized;
69 
70 #include "oct-time.h"
71 
72 namespace octave
73 {
74   class profiler;
75   class child_list;
76 
77   // The time we last time we changed directories.
78   extern sys::time Vlast_chdir_time;
79 
80   // The application object contains a pointer to the current
81   // interpreter and the interpreter contains a pointer back to the
82   // application context so we need a forward declaration for one (or
83   // both) of them...
84 
85   class application;
86 
87   class temporary_file_list
88   {
89   public:
90 
temporary_file_list(void)91     temporary_file_list (void) : m_files () { }
92 
93     // No copying!
94 
95     temporary_file_list (const temporary_file_list&) = delete;
96 
97     temporary_file_list& operator = (const temporary_file_list&) = delete;
98 
99     ~temporary_file_list (void);
100 
101     void insert (const std::string& file);
102 
103     void cleanup (void);
104 
105   private:
106 
107     // List of temporary files to delete when we exit.
108     std::set<std::string> m_files;
109 
110   };
111 
112   class OCTINTERP_API interpreter
113   {
114   public:
115 
116     // Create an interpreter object and perform basic initialization.
117 
118     interpreter (application *app_context = nullptr);
119 
120     // No copying, at least not yet...
121 
122     interpreter (const interpreter&) = delete;
123 
124     interpreter& operator = (const interpreter&) = delete;
125 
126     // Clean up the interpreter object.
127 
128     ~interpreter (void);
129 
130     void intern_nargin (octave_idx_type nargs);
131 
132     // If creating an embedded interpreter, you may inhibit reading
133     // the command history file by calling initialize_history with
134     // read_history_file = false prior to calling initialize.
135 
136     void initialize_history (bool read_history_file = false);
137 
138     // If creating an embedded interpreter, you may inhibit setting
139     // the default compiled-in path by calling initialize_load_path
140     // with set_initial_path = false prior calling initialize.  After
141     // that, you can add directories to the load path to set up a
142     // custom path.
143 
144     void initialize_load_path (bool set_initial_path = true);
145 
146     // Load command line history, set the load path.
147 
148     void initialize (void);
149 
150     // Initialize the interpreter (if not already done by an explicit
151     // call to initialize), execute startup files, --eval option code,
152     // script files, and/or interactive commands.
153 
154     int execute (void);
155 
156     void shutdown (void);
157 
interactive(void)158     bool interactive (void) const
159     {
160       return m_interactive;
161     }
162 
interactive(bool arg)163     void interactive (bool arg)
164     {
165       m_interactive = arg;
166     }
167 
read_site_files(bool flag)168     void read_site_files (bool flag)
169     {
170       m_read_site_files = flag;
171     }
172 
read_init_files(bool flag)173     void read_init_files (bool flag)
174     {
175       m_read_init_files = flag;
176     }
177 
verbose(bool flag)178     void verbose (bool flag)
179     {
180       m_verbose = flag;
181     }
182 
inhibit_startup_message(bool flag)183     void inhibit_startup_message (bool flag)
184     {
185       m_inhibit_startup_message = flag;
186     }
187 
in_top_level_repl(void)188     bool in_top_level_repl (void) const
189     {
190       return m_evaluator.in_top_level_repl ();
191     }
192 
initialized(void)193     bool initialized (void) const
194     {
195       return m_initialized;
196     }
197 
get_display_info(void)198     display_info& get_display_info (void)
199     {
200       return m_display_info;
201     }
202 
get_environment(void)203     environment& get_environment (void)
204     {
205       return m_environment;
206     }
207 
get_settings(void)208     settings& get_settings (void)
209     {
210       return m_settings;
211     }
212 
get_error_system(void)213     error_system& get_error_system (void)
214     {
215       return m_error_system;
216     }
217 
get_help_system(void)218     help_system& get_help_system (void)
219     {
220       return m_help_system;
221     }
222 
get_input_system(void)223     input_system& get_input_system (void)
224     {
225       return m_input_system;
226     }
227 
get_output_system(void)228     output_system& get_output_system (void)
229     {
230       return m_output_system;
231     }
232 
get_history_system(void)233     history_system& get_history_system (void)
234     {
235       return m_history_system;
236     }
237 
get_dynamic_loader(void)238     dynamic_loader& get_dynamic_loader (void)
239     {
240       return m_dynamic_loader;
241     }
242 
get_load_path(void)243     load_path& get_load_path (void)
244     {
245       return m_load_path;
246     }
247 
get_load_save_system(void)248     load_save_system& get_load_save_system (void)
249     {
250       return m_load_save_system;
251     }
252 
get_type_info(void)253     type_info& get_type_info (void)
254     {
255       return m_type_info;
256     }
257 
get_symbol_table(void)258     symbol_table& get_symbol_table (void)
259     {
260       return m_symbol_table;
261     }
262 
263     tree_evaluator& get_evaluator (void);
264 
265     symbol_scope get_top_scope (void) const;
266     symbol_scope get_current_scope (void) const;
267     symbol_scope require_current_scope (const std::string& who) const;
268 
269     profiler& get_profiler (void);
270 
271     stream_list& get_stream_list (void);
272 
get_child_list(void)273     child_list& get_child_list (void)
274     {
275       return m_child_list;
276     }
277 
278     url_handle_manager& get_url_handle_manager (void);
279 
get_cdef_manager(void)280     cdef_manager& get_cdef_manager (void)
281     {
282       return m_cdef_manager;
283     }
284 
get_gtk_manager(void)285     gtk_manager& get_gtk_manager (void)
286     {
287       return m_gtk_manager;
288     }
289 
get_event_manager(void)290     event_manager& get_event_manager (void)
291     {
292       return m_event_manager;
293     }
294 
get_gh_manager(void)295     gh_manager& get_gh_manager (void)
296     {
297       return *m_gh_manager;
298     }
299 
300     // Any Octave code that needs to change the current directory should
301     // call this function instead of calling the system chdir function
302     // directly so that the  load-path and GUI may be notified of the
303     // change.
304 
305     int chdir (const std::string& dir);
306 
307     void mlock (bool skip_first = false) const;
308     void munlock (bool skip_first = false) const;
309     bool mislocked (bool skip_first = false) const;
310 
311     // NOTE: since we have a version that accepts a bool argument, we
312     // can't rely on automatic conversion from char* to std::string.
313     void munlock (const char *nm);
314     void munlock (const std::string& nm);
315 
316     bool mislocked (const char *nm);
317     bool mislocked (const std::string& nm);
318 
319     std::string mfilename (const std::string& opt = "") const;
320 
321     octave_value_list eval_string (const std::string& eval_str, bool silent,
322                                    int& parse_status, int nargout);
323 
324     octave_value eval_string (const std::string& eval_str, bool silent,
325                               int& parse_status);
326 
327     octave_value_list eval_string (const octave_value& arg, bool silent,
328                                    int& parse_status, int nargout);
329 
330     octave_value_list eval (const std::string& try_code, int nargout);
331 
332     octave_value_list eval (const std::string& try_code,
333                             const std::string& catch_code, int nargout);
334 
335     octave_value_list evalin (const std::string& context,
336                               const std::string& try_code, int nargout);
337 
338     octave_value_list evalin (const std::string& context,
339                               const std::string& try_code,
340                               const std::string& catch_code, int nargout);
341 
342     octave_value_list
343     feval (const char *name,
344            const octave_value_list& args = octave_value_list (),
345            int nargout = 0);
346 
347     octave_value_list
348     feval (const std::string& name,
349            const octave_value_list& args = octave_value_list (),
350            int nargout = 0);
351 
352     octave_value_list
353     feval (octave_function *fcn,
354            const octave_value_list& args = octave_value_list (),
355            int nargout = 0);
356 
357     octave_value_list
358     feval (const octave_value& f_arg,
359            const octave_value_list& args = octave_value_list (),
360            int nargout = 0);
361 
362     octave_value_list feval (const octave_value_list& args, int nargout = 0);
363 
364     octave_value make_function_handle (const std::string& name);
365 
366     void install_variable (const std::string& name, const octave_value& value,
367                            bool global);
368 
369     void set_global_value (const std::string& name, const octave_value& value);
370 
371     octave_value global_varval (const std::string& name) const;
372 
373     void global_assign (const std::string& name,
374                         const octave_value& val = octave_value ());
375 
376     octave_value top_level_varval (const std::string& name) const;
377 
378     void top_level_assign (const std::string& name,
379                            const octave_value& val = octave_value ());
380 
381     bool is_variable (const std::string& name) const;
382 
383     bool is_local_variable (const std::string& name) const;
384 
385     octave_value varval (const std::string& name) const;
386 
387     void assign (const std::string& name,
388                  const octave_value& val = octave_value ());
389 
390     void assignin (const std::string& context, const std::string& varname,
391                    const octave_value& val = octave_value ());
392 
393     void source_file (const std::string& file_name,
394                       const std::string& context = "",
395                       bool verbose = false, bool require_file = true);
396 
397     bool at_top_level (void) const;
398 
399     bool isglobal (const std::string& name) const;
400 
401     octave_value find (const std::string& name);
402 
403     void clear_all (bool force = false);
404 
405     void clear_objects (void);
406 
407     void clear_variable (const std::string& name);
408 
409     void clear_variable_pattern (const std::string& pattern);
410 
411     void clear_variable_regexp (const std::string& pattern);
412 
413     void clear_variables (void);
414 
415     void clear_global_variable (const std::string& name);
416 
417     void clear_global_variable_pattern (const std::string& pattern);
418 
419     void clear_global_variable_regexp (const std::string& pattern);
420 
421     void clear_global_variables (void);
422 
423     void clear_functions (bool force = false);
424 
425     void clear_function (const std::string& name);
426 
427     void clear_symbol (const std::string& name);
428 
429     void clear_function_pattern (const std::string& pat);
430 
431     void clear_function_regexp (const std::string& pat);
432 
433     void clear_symbol_pattern (const std::string& pat);
434 
435     void clear_symbol_regexp (const std::string& pat);
436 
437     std::list<std::string> variable_names (void);
438 
439     std::list<std::string> top_level_variable_names (void);
440 
441     std::list<std::string> global_variable_names (void);
442 
443     std::list<std::string> user_function_names (void);
444 
445     std::list<std::string> autoloaded_functions (void) const;
446 
447     void handle_exception (const execution_exception& e);
448 
449     void recover_from_exception (void);
450 
451     void mark_for_deletion (const std::string& file);
452 
453     void cleanup_tmp_files (void);
454 
455     void quit (int exit_status, bool force = false, bool confirm = true);
456 
cancel_quit(bool flag)457     void cancel_quit (bool flag) { m_cancel_quit = flag; }
458 
executing_finish_script(void)459     bool executing_finish_script (void) const
460     {
461       return m_executing_finish_script;
462     }
463 
464     void add_atexit_fcn (const std::string& fname);
465 
466     bool remove_atexit_fcn (const std::string& fname);
467 
468     OCTAVE_DEPRECATED (6, "use interpreter::add_atexit_fcn member function instead")
469     static void add_atexit_function (const std::string& fname);
470 
471     OCTAVE_DEPRECATED (6, "use interpreter::remove_atexit_fcn member function instead")
472     static bool remove_atexit_function (const std::string& fname);
473 
the_interpreter(void)474     static interpreter * the_interpreter (void) { return instance; }
475 
476   private:
477 
478     // The interpreter instance;  Currently it is only possible to
479     // have one, so OCTAVE_THREAD_LOCAL will normally be defined to be
480     // empty.  Eventually we would like to allow multiple interpreters
481     // to be active at once, but they will still be limited to one per
482     // thread.  When that is possible, OCTAVE_THREAD_LOCAL can be
483     // replaced by the C++ thread_local keyword.  For now, use a macro
484     // to allow experimenting with thread_local storage.
485 
486     OCTAVE_THREAD_LOCAL static interpreter *instance;
487 
488     void display_startup_message (void) const;
489 
490     int execute_startup_files (void);
491 
492     int execute_eval_option_code (void);
493 
494     int execute_command_line_file (void);
495 
496     int main_loop (void);
497 
498     void execute_atexit_fcns (void);
499 
500     application *m_app_context;
501 
502     temporary_file_list m_tmp_files;
503 
504     std::list<std::string> m_atexit_fcns;
505 
506     display_info m_display_info;
507 
508     environment m_environment;
509 
510     settings m_settings;
511 
512     error_system m_error_system;
513 
514     help_system m_help_system;
515 
516     input_system m_input_system;
517 
518     output_system m_output_system;
519 
520     history_system m_history_system;
521 
522     dynamic_loader m_dynamic_loader;
523 
524     load_path m_load_path;
525 
526     load_save_system m_load_save_system;
527 
528     type_info m_type_info;
529 
530     symbol_table m_symbol_table;
531 
532     tree_evaluator m_evaluator;
533 
534     stream_list m_stream_list;
535 
536     child_list m_child_list;
537 
538     url_handle_manager m_url_handle_manager;
539 
540     cdef_manager m_cdef_manager;
541 
542     gtk_manager m_gtk_manager;
543 
544     event_manager m_event_manager;
545 
546     gh_manager *m_gh_manager;
547 
548     // TRUE means this is an interactive interpreter (forced or not).
549     bool m_interactive;
550 
551     bool m_read_site_files;
552 
553     bool m_read_init_files;
554 
555     bool m_verbose;
556 
557     bool m_inhibit_startup_message;
558 
559     bool m_load_path_initialized;
560 
561     bool m_history_initialized;
562 
563     bool m_cancel_quit;
564 
565     bool m_executing_finish_script;
566 
567     bool m_executing_atexit;
568 
569     bool m_initialized;
570 
571     void maximum_braindamage (void);
572 
573     void execute_pkg_add (const std::string& dir);
574   };
575 }
576 
577 #endif
578