NEURON
ivocmain.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include "nrn_ansi.h"
3 
4 #include "../utils/profile/profiler_interface.h"
5 
7 
8 #if !HAVE_IV
9 #define Session void
10 int hoc_main1(int, const char**, const char**);
11 void hoc_main1_init(const char*, const char**);
12 #endif
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <filesystem>
17 #if HAVE_UNISTD_H
18 #include <unistd.h>
19 #if !defined(__APPLE__)
20 extern char** environ;
21 #else
22 #include <crt_externs.h>
23 #endif
24 #endif
25 
26 namespace fs = std::filesystem;
27 
28 #if HAVE_IV
29 #ifdef WIN32
30 #include <IV-Win/MWlib.h>
31 void iv_display_scale(float);
32 #endif
33 
34 #include <assert.h>
35 #include "ivoc.h"
36 #include "idraw.h"
37 #include <InterViews/style.h>
38 #endif
39 #include "string.h"
40 #include "oc2iv.h"
41 #include "nrnmpi.h"
42 #include "nrnpy.h"
43 
44 #if defined(HAVE_IV) && defined(IVX11_DYNAM)
45 #include <IV-X11/ivx11_dynam.h>
46 #endif
47 
48 #include "utils/logger.hpp"
49 
50 #if 1
51 void pr_profile();
52 #define PR_PROFILE pr_profile();
53 #else
54 #define PR_PROFILE /**/
55 #endif
56 /*****************************************************************************/
57 
58 #if HAVE_IV
59 static PropertyData properties[] = {{"*gui", "sgimotif"},
60  {"*PopupWindow*overlay", "true"},
61  {"*PopupWindow*saveUnder", "on"},
62  {"*TransientWindow*saveUnder", "on"},
63  {"*background", "#ffffff"},
64  {"*brush_width", "0"},
65  {"*double_buffered", "on"},
66  {"*flat", "#aaaaaa"},
67 #ifdef MINGW
68  {"*font", "*Arial*bold*--12*"},
69  {"*MenuBar*font", "*Arial*bold*--12*"},
70  {"*MenuItem*font", "*Arial*bold*--12*"},
71 #endif
72  {"*foreground", "#000000"},
73  {"*synchronous", "off"},
74  {"*malloc_debug", "on"},
75 
76  {"*Scene_background", "#ffffff"},
77  {"*Scene_foreground", "#000000"},
78  {"*FieldEditor*background", "#ffffff"},
79  //{"*background", "#cfffff"},
80  {"*default_brush", "0"},
81  {"*view_margin", ".25"},
82  {"*pwm_dismiss_button", "Iconify"},
83  {"*dismiss_button", "Close"},
84  {"*use_transient_windows", "yes"},
85  {"*nrn_library", " $(NEURONHOME)/lib"},
86  {"*view_pick_epsilon", "2"},
87  {"*pwm_canvas_height", "120"},
88  {"*pwm_paper_height", "11"},
89  {"*pwm_paper_width", "8.5"},
90  {"*pwm_paper_resolution", ".5"},
91  {"*pwm_pixel_resolution", "0"},
92  {"*window_manager_offset_x", "5."},
93  {"*window_manager_offset_y", "26."},
94  {"*pwm_print_file_filter", "*.ps"},
95  {"*pwm_idraw_file_filter", "*.id"},
96  {"*pwm_ascii_file_filter", "*"},
97  {"*pwm_save_file_filter", "*.ses"},
98  {"*pwm_idraw_prologue", "$(NEURONHOME)/lib/prologue.id"},
99  {"*pwm_postscript_filter", "sed 's;/Adobe-;/;'"},
100  {"*SlowSlider*autorepeatStart", "0."},
101  {"*scene_print_border", "1"},
102  {"*radioScale", ".9"},
103  {"*stepper_size", "20."},
104  {"*xvalue_field_size_increase", "10."},
105  {"*xvalue_format", "%.5g"},
106  {"*graph_axis_default", "0"},
107  {"*shape_scale_file", "$(NEURONHOME)/lib/shape.cm2"},
108  {"*shape_quadedge", "0"},
109  {"*CBWidget_ncolor", "10"},
110  {"*CBWidget_nbrush", "10"},
111  {"*units_on_flag", "on"},
112  {"*NFRAME", "0"}, // see src/oc/code.cpp for the default value
113  {"*NSTACK", "0"}, // see src/oc/code.cpp for the default value
114  {"*Py_NoSiteFlag", "0"},
115  {"*python", "off"},
116  {"*nopython", "off"},
117  {"*err_dialog", "off"},
118  {"*banner", "on"},
119  {"*pyexe", ""},
120  {NULL}};
121 
122 static OptionDesc options[] = {{"-dismissbutton", "*dismiss_button", OptionValueImplicit, "Close"},
123  {"-extrapipeinput", "*extrapipeinput", OptionValueNext},
124  {"-dll", "*nrnmechdll", OptionValueNext},
125  {"-showwinio", "*showwinio", OptionValueImplicit, "on"},
126  {"-hidewinio", "*showwinio", OptionValueImplicit, "off"},
127  {"-isatty", "*isatty", OptionValueImplicit, "1"},
128  {"-notatty", "*isatty", OptionValueImplicit, "-1"},
129  {"-bbs_nhost", "*bbs_nhost", OptionValueNext},
130  {"-NSTACK", "*NSTACK", OptionValueNext},
131  {"-NFRAME", "*NFRAME", OptionValueNext},
132  {"--version", "*print_nrn_version", OptionValueImplicit, "on"},
133  {"-python", "*python", OptionValueImplicit, "on"},
134  {"-nopython", "*nopython", OptionValueImplicit, "on"},
135  {"-pyexe", "*pyexe", OptionValueNext},
136  {"-Py_NoSiteFlag", "*Py_NoSiteFlag", OptionValueImplicit, "1"},
137  {"-nobanner", "*banner", OptionValueImplicit, "off"},
138 #if defined(WIN32)
139  {"-mswin_scale", "*mswin_scale", OptionValueNext},
140 #endif
141  {NULL}};
142 #endif // HAVE_IV
143 
144 extern int hoc_obj_run(const char*, Object*);
145 extern int nrn_istty_;
146 extern int nrn_nobanner_;
147 extern void hoc_final_exit();
148 void ivoc_final_exit();
149 #if (defined(NRNMECH_DLL_STYLE) || defined(WIN32))
150 extern const char* nrn_mech_dll;
151 #endif
152 #if defined(USE_PYTHON)
153 int nrn_nopython;
154 extern int use_python_interpreter;
155 std::string nrnpy_pyexe;
156 #endif
157 
158 /*****************************************************************************/
159 // exported initialized data so shared libraries can have assert pure-text
160 #if HAVE_IV
161 int Oc::refcnt_ = 0;
162 Session* Oc::session_ = 0;
164 std::ostream* OcIdraw::idraw_stream = 0;
165 #endif
166 /*****************************************************************************/
167 extern void ivoc_cleanup();
168 #if OCSMALL
169 static char* ocsmall_argv[] = {0, "difus.hoc"};
170 #endif
171 #if defined(WIN32) && HAVE_IV
172 extern HWND hCurrWnd;
173 #endif
174 
175 
176 extern void setneuronhome(const char*);
177 extern const char* neuron_home;
178 int hoc_xopen1(const char* filename, const char* rcs);
179 extern int units_on_flag_;
180 extern double hoc_default_dll_loaded_;
181 extern int hoc_print_first_instance;
183 
184 #if !defined(MINGW)
185 extern void setneuronhome(const char*) {
186  neuron_home = getenv("NEURONHOME");
187 }
188 #endif
189 
190 #if DARWIN || defined(__linux__)
191 #include "nrnwrap_dlfcn.h"
192 #include <string>
193 
194 /* It is definitely now the case on mac and I think sometimes the case on
195 linux that dlopen needs a full path to the file. A path to the binary
196 is not necessarily sufficent as one may launch python or nrniv on the
197 target machine and the lib folder cannot be derived from the location of
198 the python executable.This seems to be robust if nrn_version is inside a
199 shared library.
200 The return value ends with a '/' and if the prefix cannot be determined
201 the return value is "".
202 */
203 const char* path_prefix_to_libnrniv() {
204  static char* path_prefix_to_libnrniv_ = NULL;
205  if (!path_prefix_to_libnrniv_) {
206  Dl_info info;
207  int rval = dladdr((void*) nrn_version, &info);
208  std::string name;
209  if (rval) {
210  if (info.dli_fname) {
211  name = info.dli_fname;
212  if (info.dli_fname[0] == '/') { // likely full path
213  size_t last_slash = name.rfind("/");
214  path_prefix_to_libnrniv_ = strndup(name.c_str(), last_slash + 1);
215  path_prefix_to_libnrniv_[last_slash + 1] = '\0';
216  }
217  }
218  }
219  if (!path_prefix_to_libnrniv_) {
220  path_prefix_to_libnrniv_ = strdup("");
221  }
222  }
223  return path_prefix_to_libnrniv_;
224 }
225 #endif // DARWIN || defined(__linux__)
226 
227 int ivocmain(int, const char**, const char**);
228 int ivocmain_session(int, const char**, const char**, int start_session);
229 extern int nrn_global_argc;
230 extern const char** nrn_global_argv;
232 extern int nrn_is_python_extension;
233 extern void hoc_nrnmpi_init();
234 #if NRNMPI_DYNAMICLOAD
235 extern void nrnmpi_stubs();
236 extern std::string nrnmpi_load();
237 void nrnmpi_load_or_exit();
238 #endif
239 
240 #ifdef MINGW
241 // see iv/src/OS/directory.cpp
242 #include <sys/stat.h>
243 static bool isdir(const char* p) {
244  struct stat st;
245  bool b = stat(p, &st) == 0 && S_ISDIR(st.st_mode);
246  // printf("isdir %s returns %d\n", p, b);
247  return b;
248 }
249 #endif
250 
251 
252 static bool nrn_optarg_on(const char* opt, int* pargc, const char** argv) {
253  for (int i = 0; i < *pargc; ++i) {
254  if (strcmp(opt, argv[i]) == 0) {
255  *pargc -= 1;
256  for (; i < *pargc; ++i) {
257  argv[i] = argv[i + 1];
258  }
259  // printf("nrn_optarg_on %s return true\n", opt);
260  return true;
261  }
262  }
263  return false;
264 }
265 
266 static const char* nrn_optarg(const char* opt, int* pargc, const char** argv) {
267  for (int i = 0; i < *pargc - 1; ++i) {
268  if (strcmp(opt, argv[i]) == 0) {
269  const char* a = argv[i + 1];
270  *pargc -= 2;
271  for (; i < *pargc; ++i) {
272  argv[i] = argv[i + 2];
273  }
274  // printf("nrn_optarg %s return %s\n", opt, a);
275  return a;
276  }
277  }
278  return 0;
279 }
280 
281 static int nrn_optargint(const char* opt, int* pargc, const char** argv, int dflt) {
282  int i = dflt;
283  const char* a = nrn_optarg(opt, pargc, argv);
284  if (a) {
285  sscanf(a, "%d", &i);
286  }
287  // printf("nrn_optargint %s return %d\n", opt, i);
288  return i;
289 }
290 
291 #if USENRNJAVA
292 void nrn_InitializeJavaVM();
293 #endif
294 
296 #if NRNMPI
297  if (!nrnmpi_use) {
298 #if NRNMPI_DYNAMICLOAD
299  nrnmpi_stubs();
300  auto const pmes = nrnmpi_load();
301  if (!pmes.empty()) {
302  Printf(fmt::format("{}\n", pmes).c_str());
303  }
304 #endif
305 
306  char** foo = (char**) nrn_global_argv;
307  nrnmpi_init(2, &nrn_global_argc, &foo);
308  // if (nrnmpi_myid == 0) {printf("hoc_nrnmpi_init called nrnmpi_init\n");}
309  // turn off gui for all ranks > 0
310  if (nrnmpi_myid_world > 0) {
311  hoc_usegui = 0;
313  }
314  }
315 #endif
316  hoc_ret();
317  hoc_pushx(0.0);
318 }
319 
320 /**
321  * Main entrypoint function into the HOC interpeter
322  *
323  * This function simply calls ivocmain_session with the \c start_session = 1.
324  *
325  * \note This is part of NEURON's public interface
326  *
327  * \note \c env argument should not be used as it might become invalid
328  *
329  * \param argc argument count as found in C/C++ \c main functions
330  * \param argv argument vector as found in C/C++ \c main functions
331  * \param env environment variable array as optionally found in main functions.
332  * \return 0 on success, otherwise error code.
333  */
334 int ivocmain(int argc, const char** argv, const char** env) {
335  return ivocmain_session(argc, argv, env, 1);
336 }
337 /**
338  * This used to be ivocmain, the main entrypoint to the HOC interpreter
339  *
340  * ivocmain_session parses command line argument, calls of initialization
341  * functions and drops into an interactive HOC session.
342  * This function is called for example by the "real main" in \c nrnmain.cpp ,
343  * but can be also called from other external user applications that use
344  * NEURON.
345  * Additionally to the original implemenation a new parameter \c start_session
346  * was introduced to control whether an interactive HOC session shoudl be started
347  * or simply NEURON and all data structures be initialized and control returned
348  * to the caller.
349  *
350  * \note \c env argument should not be used as it might become invalid
351  *
352  * \param argc argument count as found in C/C++ \c main functions
353  * \param argv argument vector as found in C/C++ \c main functions
354  * \param env environment variable array as optionally found in main functions.
355  * \param start_session set to 1 for default behavior (drop into interactive HOC session
356  * otherwise set to 0. If set to 1, but compiled with python support this function will
357  * still directly return (since in that mode we don't need an interactive HOC session
358  * either.
359  * \return 0 on success, otherwise error code.
360  */
361 int ivocmain_session(int argc, const char** argv, const char** env, int start_session) {
362  constexpr auto nrniv_help = R"(
363 nrniv [options] [fileargs]
364  options:
365  -dll filename dynamically load the linked mod files.
366  -h print this help message
367  -help print this help message
368  -isatty unbuffered stdout, print prompt when waiting for stdin
369  -mpi launched by mpirun or mpiexec, in parallel environment
370  -mswin_scale float scales gui on screen
371  -music launched as a process of the MUlti SImulator Coordinator
372  -NSTACK integer size of stack (default 1000)
373  -NFRAME integer depth of function call nesting (default 200)
374  -nobanner do not print startup banner
375  -nogui do not send any gui info to screen
376  -notatty buffered stdout and no prompt
377  -python Python is the interpreter
378  -pyexe path Python to use if python (or python3 fallback) not right.
379  -nopython Do not initialize Python
380  -Py_NoSiteFlag Set Py_NoSiteFlag=1 before initializing Python
381  -realtime For hard real-time simulation for dynamic clamp
382  --version print version info and all InterViews and X11 options
383  fileargs: any number of following
384  - input from stdin til ^D (end of file)
385  -c "statement" execute next statement
386  filename execute contents of filename
387 )";
388 
390 
391  // third arg should not be used as it might become invalid
392  // after putenv or setenv. Instead, if necessary use
393  // #include <unistd.h>
394  // extern char** environ;
395  // prargs("at beginning", argc, argv);
397  // https://en.cppreference.com/w/cpp/language/main_function, note that argv is
398  // of length argc + 1 and argv[argc] is null.
399  nrn_global_argv = new const char*[argc + 1];
400  for (int i = 0; i < argc + 1; ++i) {
401  nrn_global_argv[i] = argv[i];
402  }
404  if (nrn_optarg_on("-help", &argc, argv) || nrn_optarg_on("-h", &argc, argv)) {
405  printf(nrniv_help);
406  exit(0);
407  }
408  if (nrn_optarg_on("--version", &argc, argv)) {
409  printf("%s\n", nrn_version(1));
410  exit(0);
411  }
412  if (nrn_optarg_on("-nobanner", &argc, argv)) {
413  nrn_nobanner_ = 1;
414  }
415  if (nrn_optarg_on("-Py_NoSiteFlag", &argc, argv)) {
416  nrnpy_nositeflag = 1;
417  }
418 
420  hoc_usegui = 1;
421  if (nrn_optarg_on("-nogui", &argc, argv)) {
422  hoc_usegui = 0;
424  }
425  if (nrnmpi_numprocs > 1) {
426  hoc_usegui = 0;
428  }
429 #if NRNMPI
430  if (nrnmpi_use) {
431  hoc_usegui = 0;
433  }
434 #else
435 
436  // check if user is trying to use -mpi or -p4 when it was not
437  // enabled at build time. If so, issue a warning.
438 
439  for (int i = 0; i < argc; ++i) {
440  if ((strncmp("-p4", (argv)[i], 3) == 0) || (strcmp("-mpi", (argv)[i]) == 0)) {
441  printf(
442  "Warning: detected user attempt to enable MPI, but MPI support was disabled at "
443  "build "
444  "time.\n");
445  break;
446  }
447  }
448 
449 #endif
450 
451 #if defined(HAVE_IV) && defined(IVX11_DYNAM)
452  if (hoc_usegui && ivx11_dyload()) {
453  hoc_usegui = 0;
455  }
456 #endif
457 
458  const bool music_enabled = nrn_optarg_on("-music", &argc, argv);
459 #if !NRN_MUSIC
460  if (music_enabled) {
461  printf("Warning: attempt to enable MUSIC but MUSIC support was disabled at build time.\n");
462  }
463 #endif
464 
465 #if !HAVE_IV
466  hoc_usegui = 0;
468 #endif
469  int our_argc = argc;
470  const char** our_argv = argv;
471  int exit_status = 0;
472  Session* session = NULL;
473 #if !defined(MINGW)
474  // Gary Holt's first pass at this was:
475  //
476  // Set the NEURONHOME environment variable. This should override any setting
477  // in the environment, so someone doesn't accidently use data files from an
478  // old version of neuron.
479  //
480  // But I have decided to use the environment variable if it exists
481  neuron_home = getenv("NEURONHOME");
482  if (!neuron_home) {
483 #if defined(HAVE_SETENV)
484  setenv("NEURONHOME", NEURON_DATA_DIR, 1);
485  neuron_home = NEURON_DATA_DIR;
486 #else
487 #error "I don't know how to set environment variables."
488 // Maybe in this case the user will have to set it by hand.
489 #endif
490  // putenv and setenv may invalidate env but we no longer
491  // use it so following should not be needed
492  }
493 
494 #else // Not unix:
495  neuron_home = getenv("NEURONHOME");
496  if (!neuron_home) {
497  setneuronhome((argc > 0) ? argv[0] : 0);
498  }
499  if (!neuron_home) {
500 #if defined(WIN32) && HAVE_IV
501  MessageBox(0,
502  "No NEURONHOME environment variable.",
503  "NEURON Incomplete Installation",
504  MB_OK);
505 #else
506  neuron_home = ".";
507  fprintf(stderr,
508  "Warning: no NEURONHOME environment variable-- setting\
509  to %s\n",
510  neuron_home);
511 #endif
512  }
513 #endif // !unix.
514 
515 #if HAVE_IV
516 #if OCSMALL
517  our_argc = 2;
518  our_argv = new char*[2];
519  our_argv[0] = "Neuron";
520  our_argv[1] = ":lib:hoc:macload.hoc";
521  session = new Session("NEURON", our_argc, our_argv, options, properties);
522 #else
523 #if defined(WIN32)
524  if (hoc_usegui) {
525  session = new Session("NEURON", our_argc, (char**) our_argv, options, properties);
526  }
527 #else
528  if (hoc_usegui) {
529  if (getenv("DISPLAY")) {
530  session = new Session("NEURON", our_argc, (char**) our_argv, options, properties);
531  } else {
532  fprintf(stderr,
533  "Warning: no DISPLAY environment variable.\
534 \n--No graphics will be displayed.\n");
535  hoc_usegui = 0;
536  }
537  }
538 #endif
539  if (session) {
540  const auto nrn_def_path1 = fs::path(neuron_home) / "lib" / "nrn.defaults";
541  const auto nrn_def_path2 = fs::path(neuron_home) / "lib" / "nrn.def";
542  auto file_exists = [](const auto& path) noexcept -> bool {
543  // make sure it doesn't throw
544  std::error_code err;
545  return fs::is_regular_file(path, err);
546  };
547 #ifdef WIN32
548  if (file_exists(nrn_def_path1)) {
549  session->style()->load_file(String(nrn_def_path1.string().c_str()), -5);
550  } else if (file_exists(nrn_def_path2)) {
551  session->style()->load_file(String(nrn_def_path2.string().c_str()), -5);
552  } else {
553  fmt::print("Can't load NEURON resources from {}[aults]\n", nrn_def_path1.string());
554  }
555 #else
556  session->style()->load_file(String(nrn_def_path1.string().c_str()), -5);
557 #endif
558  char* h = getenv("HOME");
559  if (h) {
560  const auto nrn_def_path_dot = fs::path(h) / ".nrn.defaults";
561  if (file_exists(nrn_def_path_dot)) {
562  session->style()->load_file(String(nrn_def_path_dot.string().c_str()), -5);
563  }
564  }
565  }
566 
567 #endif /*OCSMALL*/
568 
569  if (session) {
570  session->style()->find_attribute("NSTACK", hoc_nstack);
571  session->style()->find_attribute("NFRAME", hoc_nframe);
572  if (hoc_usegui) {
573  if (session->style()->value_is_on("err_dialog")) {
575  }
576  }
577  } else
578 #endif // HAVE_IV
579  {
580  hoc_nstack = nrn_optargint("-NSTACK", &our_argc, our_argv, 0);
581  hoc_nframe = nrn_optargint("-NFRAME", &our_argc, our_argv, 0);
582  }
583 
584 #if defined(USE_PYTHON)
585  nrn_nopython = 0;
587 #if HAVE_IV
588  if (session) {
589  if (session->style()->value_is_on("nopython")) {
590  nrn_nopython = 1;
591  }
592  String str;
593  if (session->style()->find_attribute("pyexe", str)) {
594  nrnpy_pyexe = str.string();
595  }
596  } else
597 #endif
598  {
599  if (nrn_optarg_on("-nopython", &our_argc, our_argv)) {
600  nrn_nopython = 1;
601  }
602  if (const char* buf = nrn_optarg("-pyexe", &our_argc, our_argv)) {
603  nrnpy_pyexe = buf;
604  }
605  }
606  }
607 #endif // USE_PYTHON
608 
609 #if defined(WIN32) && HAVE_IV
610  if (hoc_usegui) {
611  double scale = 1.;
612  int pw = GetSystemMetrics(SM_CXVIRTUALSCREEN);
613  if (pw < 1100) {
614  scale = 1200. / double(pw);
615  }
616  session->style()->find_attribute("mswin_scale", scale);
617  iv_display_scale(float(scale));
618  }
619 #endif
620 
621  // just eliminate from arg list
622  nrn_optarg_on("-mpi", &our_argc, our_argv);
623 
624 #if (defined(NRNMECH_DLL_STYLE) || defined(WIN32))
625 #if HAVE_IV
626  String str;
627  if (session) {
628  if (session->style()->find_attribute("nrnmechdll", str)) {
629  nrn_mech_dll = str.string();
630  }
631  } else
632 #endif
633  { // if running without IV.
634  nrn_mech_dll = nrn_optarg("-dll", &our_argc, our_argv);
635  // may be duplicated since nrnbbs adds all args to special
636  // which is often a script that adds a -dll arg
637  nrn_optarg("-dll", &our_argc, our_argv);
638  }
639 #if NRNMPI
640  if (nrnmpi_use && !nrn_mech_dll) {
641  // for heterogeneous clusters, mpirun allows different programs
642  // but not different arguments. So the -dll is insufficient.
643  // Therefore we check to see if it makes sense to load
644  // a dll from the usual location.
645  // Actually this is done by default in src/nrnoc/init.cpp
646  }
647 #endif
648 
649 #endif // NRNMECH_DLL_STYLE
650 
651 
652 #if HAVE_IV
653  if (session) {
654  long i;
655  if (session->style()->find_attribute("isatty", i)) {
656  nrn_istty_ = i;
657  }
658  } else
659 #endif
660  {
661  nrn_istty_ = nrn_optarg_on("-isatty", &our_argc, our_argv);
662  if (nrn_istty_ == 0) {
663  nrn_istty_ = nrn_optarg_on("-notatty", &our_argc, our_argv);
664  if (nrn_istty_ == 1) {
665  nrn_istty_ = -1;
666  }
667  }
668  }
669 
670 #if HAVE_IV
671  if (session && session->style()->value_is_on("units_on_flag")) {
672  units_on_flag_ = 1;
673  }
674  Oc oc(session, our_argv[0], env);
675 #else
676  hoc_main1_init(our_argv[0], env);
677 #endif // HAVE_IV
678 
679 #if USENRNJAVA
680  nrn_InitializeJavaVM();
681 #endif
682 #if OCSMALL
683  if (argc == 1) {
684  ocsmall_argv[0] = our_argv[0];
685  exit_status = oc.run(2, ocsmall_argv);
686  } else
687 #endif
688 #if defined(USE_PYTHON)
689 #if HAVE_IV
690  if (session && session->style()->value_is_on("python")) {
691  use_python_interpreter = 1;
692  }
693 #endif
694  if (nrn_optarg_on("-python", &our_argc, our_argv)) {
695  use_python_interpreter = 1;
696  }
697 
699  return 0;
700  }
701  if (neuron::python::methods.interpreter_start) {
703  }
704  if (use_python_interpreter && !neuron::python::methods.interpreter_start) {
705  fprintf(stderr, "Python not available\n");
706  exit(1);
707  }
708 #endif
709  if (start_session) {
710 #if HAVE_IV
711  exit_status = oc.run(our_argc, our_argv);
712 #else
713  exit_status = hoc_main1(our_argc, our_argv, env);
714 #endif
715  } else {
716  return 0;
717  }
718  PR_PROFILE
719 #if defined(USE_PYTHON)
720  if (use_python_interpreter) {
721  // process the .py files and an interactive interpreter
722  if (neuron::python::methods.interpreter_start &&
723  neuron::python::methods.interpreter_start(2) != 0) {
724  // We encountered an error when processing the -c argument or Python
725  // script given on the commandline.
726  exit_status = 1;
727  }
728  }
729  if (neuron::python::methods.interpreter_start) {
731  }
732 #endif
733  hoc_final_exit();
734  ivoc_final_exit();
736 
737  return exit_status;
738 }
739 
741 #if NRNMPI
743 #endif
744 }
745 
746 extern void hoc_ret(), hoc_pushx(double);
747 
749 #if HAVE_IV
750  if (hoc_usegui) {
751  void single_event_run();
752 
754  }
755 #endif
756  hoc_ret();
757  hoc_pushx(1.);
758 }
759 
760 #if !HAVE_IV
762  return 1;
763 }
765 #endif
766 
767 
768 /// A top-level initialization of MPI given argc and argv.
769 /// Sets stubs, load dyn lib, and initializes
770 std::tuple<int, const char**> nrn_mpi_setup(int argc, const char** argv) {
771 #if defined(AUTO_DLOPEN_NRNMECH) && AUTO_DLOPEN_NRNMECH == 0
772  extern int nrn_noauto_dlopen_nrnmech;
774 #endif
775 
776 #if NRNMPI
777 #if NRNMPI_DYNAMICLOAD
778  nrnmpi_stubs();
779  for (int i = 1; i < argc; ++i) {
780  if (strcmp("-mpi", argv[i]) == 0) {
781  nrnmpi_load_or_exit();
782  break;
783  }
784  }
785 #endif // NRNMPI_DYNAMICLOAD
786  auto argv_ptr = const_cast<char***>(&argv); // safe if individual strings not modified
787  nrnmpi_init(1, &argc, argv_ptr); // may change argc and argv
788 #endif // NRNMPI
789  return {argc, argv};
790 }
#define OptionDesc
Definition: _defines.h:191
#define PropertyData
Definition: _defines.h:211
Definition: ivoc.h:36
int run(int argc, const char **argv)
static Session * session_
Definition: ivoc.h:82
static int refcnt_
Definition: ivoc.h:81
static HandleStdin * handleStdin_
Definition: ivoc.h:83
static std::ostream * idraw_stream
Definition: idraw.h:83
#define i
Definition: md1redef.h:19
DLFCN_EXPORT int dladdr(const void *addr, Dl_info *info)
Definition: dlfcn.c:731
char buf[512]
Definition: init.cpp:13
void hoc_ret()
void ivoc_final_exit()
Definition: ivocmain.cpp:740
int hoc_usegui
Definition: hoc.cpp:121
const char * nrn_mech_dll
Definition: hoc_init.cpp:228
static char * env[]
Definition: inithoc.cpp:259
static int argc
Definition: inithoc.cpp:45
static char ** argv
Definition: inithoc.cpp:46
int nrn_err_dialog_active_
Definition: ivoc.cpp:43
void setneuronhome(const char *)
Definition: ivocmain.cpp:185
int nrnpy_nositeflag
Definition: ivocmain.cpp:182
int ivocmain_session(int, const char **, const char **, int start_session)
This used to be ivocmain, the main entrypoint to the HOC interpreter.
Definition: ivocmain.cpp:361
static int nrn_optargint(const char *opt, int *pargc, const char **argv, int dflt)
Definition: ivocmain.cpp:281
int ivocmain(int, const char **, const char **)
Main entrypoint function into the HOC interpeter.
Definition: ivocmain.cpp:334
int hoc_obj_run(const char *, Object *)
Definition: hoc_oop.cpp:315
const char * neuron_home
Definition: hoc_init.cpp:227
void hoc_final_exit()
Definition: hoc.cpp:949
const char ** nrn_global_argv
Definition: hoc.cpp:46
int units_on_flag_
Definition: code2.cpp:20
int nrn_global_argc
Definition: hoc.cpp:45
long hoc_nstack
Definition: ivocmain.cpp:6
void hoc_nrnmpi_init()
Definition: ivocmain.cpp:295
int nrn_istty_
Definition: hoc.cpp:778
void ivoc_cleanup()
Definition: ocnoiv1.cpp:15
int nrn_nobanner_
Definition: init.cpp:117
#define Session
Definition: ivocmain.cpp:9
int hoc_print_first_instance
Definition: hoc_oop.cpp:39
int nrn_is_python_extension
Definition: fileio.cpp:810
static const char * nrn_optarg(const char *opt, int *pargc, const char **argv)
Definition: ivocmain.cpp:266
void pr_profile()
Definition: hoc.cpp:101
void hoc_notify_value()
Definition: ivocmain.cpp:764
void hoc_main1_init(const char *, const char **)
Definition: hoc.cpp:783
void hoc_single_event_run()
Definition: ivocmain.cpp:748
#define PR_PROFILE
Definition: ivocmain.cpp:52
int hoc_main1(int, const char **, const char **)
Definition: hoc.cpp:867
void hoc_pushx(double)
Definition: code.cpp:779
double hoc_default_dll_loaded_
Definition: hoc_init.cpp:225
std::tuple< int, const char ** > nrn_mpi_setup(int argc, const char **argv)
A top-level initialization of MPI given argc and argv.
Definition: ivocmain.cpp:770
int always_false
Definition: ivocmain.cpp:231
int hoc_xopen1(const char *filename, const char *rcs)
Definition: fileio.cpp:166
int run_til_stdin()
Definition: ivocmain.cpp:761
static bool nrn_optarg_on(const char *opt, int *pargc, const char **argv)
Definition: ivocmain.cpp:252
long hoc_nframe
Definition: ivocmain.cpp:6
printf
Definition: extdef.h:5
const char * name
Definition: init.cpp:16
static int nrnmpi_use
Definition: multisplit.cpp:41
impl_ptrs methods
Collection of pointers to functions with python-version-specific implementations.
Definition: nrnpy.cpp:21
static List * info
char * nrn_version(int)
Definition: nrnversion.cpp:27
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
void single_event_run()
size_t p
int nrn_noauto_dlopen_nrnmech
Definition: hoc_init.cpp:229
void nrnmpi_init(int nrnmpi_under_nrncontrol, int *pargc, char ***pargv)
Definition: nrnmpi.cpp:55
void nrnmpi_terminate()
Definition: nrnmpi.cpp:184
int nrn_nopython
std::string nrnpy_pyexe
int nrnmpi_myid_world
#define NULL
Definition: spdefs.h:105
Definition: hocdec.h:173
Definition: dlfcn.h:72
int(* interpreter_start)(int)
Definition: nrnpy.h:43
int Printf(const char *fmt, Args... args)
Definition: logger.hpp:18