NEURON
fileio.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 /* /local/src/master/nrn/src/oc/fileio.cpp,v 1.34 1999/09/14 13:11:46 hines Exp */
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <cstdarg>
7 #include <filesystem>
8 #include <fstream>
9 #include <iostream>
10 #include <locale>
11 #include <optional>
12 #include <regex>
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16 #include "ocmisc.h"
17 #include "hocstr.h"
18 #include "parse.hpp"
19 #include "hocparse.h"
20 #include <errno.h>
21 #include "nrnfilewrap.h"
22 #include <fmt/format.h>
23 
24 extern char* neuron_home;
25 
27 FILE* hoc_fout;
28 
29 void hoc_stdout(void) {
30  static int prev = -1;
31  if (ifarg(1)) {
32  FILE* f1;
33  if (prev != -1) {
34  hoc_execerror("stdout already switched", (char*) 0);
35  }
36  prev = dup(1);
37  if (prev < 0) {
38  hoc_execerror("Unable to backup stdout", (char*) 0);
39  }
40  f1 = fopen(gargstr(1), "wb");
41 
42  if (!f1) {
43  hoc_execerror("Unable to open ", gargstr(1));
44  }
45  if (dup2(fileno(f1), 1) < 0) {
46  hoc_execerror("Unable to attach stdout to ", gargstr(1));
47  }
48  fclose(f1);
49  } else if (prev > -1) {
50  if (dup2(prev, 1) < 0) {
51  hoc_execerror("Unable to restore stdout", (char*) 0);
52  }
53  close(prev);
54  prev = -1;
55  }
56  hoc_ret();
57  hoc_pushx((double) fileno(stdout));
58 }
59 
60 void hoc_ropen(void) /* open file for reading */
61 {
62  double d;
63  const char* fname;
64 
65  if (ifarg(1))
66  fname = gargstr(1);
67  else
68  fname = "";
69  d = 1.;
70  if (!nrn_fw_eq(hoc_frin, stdin))
73  if (fname[0] != 0) {
74  if ((hoc_frin = nrn_fw_fopen(fname, "r")) == (NrnFILEWrap*) 0) {
75  const char* retry;
76  retry = expand_env_var(fname);
77  if ((hoc_frin = nrn_fw_fopen(retry, "r")) == (NrnFILEWrap*) 0) {
78  d = 0.;
80  }
81  }
82  }
83  errno = 0;
84  hoc_ret();
85  hoc_pushx(d);
86 }
87 
88 void hoc_wopen(void) /* open file for writing */
89 {
90  const char* fname;
91  double d;
92 
93  if (ifarg(1))
94  fname = gargstr(1);
95  else
96  fname = "";
97  d = 1.;
98  if (hoc_fout != stdout) {
99  IGNORE(fclose(hoc_fout));
100  }
101  hoc_fout = stdout;
102  if (fname[0] != 0) {
103  if ((hoc_fout = fopen(expand_env_var(fname), "w")) == nullptr) {
104  d = 0.;
105  hoc_fout = stdout;
106  }
107  }
108  errno = 0;
109  hoc_ret();
110  hoc_pushx(d);
111 }
112 
113 const char* expand_env_var(const char* s) {
114  static HocStr* hs;
115  const char* cp1;
116  char* cp2;
117  int n;
118  int begin = 1; /* only needed for mac when necessary to prepend a : */
119  if (!hs) {
120  hs = hocstr_create(256);
121  }
122  hocstr_resize(hs, strlen(s) + 2);
123  for (cp1 = s, cp2 = hs->buf + begin; *cp1; ++cp1) {
124  if (*cp1 == '$' && cp1[1] == '(') {
125  char* cp3;
126  char buf[200];
127  cp1 += 2;
128  for (cp3 = buf; *cp1 && *cp1 != ')'; ++cp1) {
129  *cp3++ = *cp1;
130  assert(cp3 - buf < 200);
131  }
132  if (*cp1) {
133  *cp3 = '\0';
134  if (strcmp(buf, "NEURONHOME") == 0) {
135  cp3 = neuron_home;
136  } else {
137  cp3 = getenv(buf);
138  }
139  if (cp3) {
140  n = cp2 - hs->buf;
141  hocstr_resize(hs, n + strlen(cp3) + strlen(s) + 2);
142  cp2 = hs->buf + n;
143  while (*cp3) {
144  *cp2++ = *cp3++;
145  }
146  }
147  } else {
148  --cp1;
149  }
150  } else {
151  *cp2++ = *cp1;
152  }
153  }
154  *cp2 = '\0';
155  return hs->buf + begin;
156 }
157 
160 
161 char* hoc_current_xopen(void) {
162  return hoc_xopen_file_;
163 }
164 
165 // read and execute a hoc program
166 int hoc_xopen1(const char* name, const char* rcs) {
167  std::string fname{name};
168  if (rcs) {
169  if (rcs[0] != '\0') {
170  // cmd ---> co -p{rcs} {fname} > {fname}-{rcs}
171  // fname -> {fname}-{rcs}
172  std::string cmd{"co -p"};
173  cmd.append(rcs);
174  cmd.append(1, ' ');
175  cmd.append(fname);
176  cmd.append(" > ");
177  fname.append(1, '-');
178  fname.append(rcs);
179  cmd.append(fname);
180  if (system(cmd.c_str()) != 0) {
181  hoc_execerror(name, "\nreturned error in hoc_co system call");
182  }
183  }
184  } else if (hoc_retrieving_audit()) {
185  hoc_xopen_from_audit(fname.c_str());
186  return 0;
187  }
188  auto const savpipflag = hoc_pipeflag;
189  auto const savfin = hoc_fin;
190  hoc_pipeflag = 0;
191 
192  errno = EINTR;
193  while (errno == EINTR) {
194  errno = 0;
195  constexpr auto mode_str = "r";
196  if (!(hoc_fin = nrn_fw_fopen(fname.c_str(), mode_str))) {
197  fname = expand_env_var(fname.c_str());
198  if (!(hoc_fin = nrn_fw_fopen(fname.c_str(), mode_str))) {
199  hoc_fin = savfin;
200  hoc_pipeflag = savpipflag;
201  hoc_execerror("Can't open ", fname.c_str());
202  }
203  }
204  }
205 
206  auto const save_lineno = hoc_lineno;
207  hoc_lineno = 0;
208  std::string savname{hoc_xopen_file_};
209  if (fname.size() >= hoc_xopen_file_size_) {
210  hoc_xopen_file_size_ = fname.size() + 100;
212  }
213  strcpy(hoc_xopen_file_, fname.c_str());
214  if (hoc_fin) {
215  hoc_audit_from_xopen1(fname.c_str(), rcs);
216  IGNORE(hoc_xopen_run((Symbol*) 0, (char*) 0));
217  }
218  if (hoc_fin && !nrn_fw_eq(hoc_fin, stdin)) {
220  }
221  hoc_fin = savfin;
222  hoc_pipeflag = savpipflag;
223  if (rcs && rcs[0]) {
224  unlink(fname.c_str());
225  }
226  hoc_xopen_file_[0] = '\0';
227  hoc_lineno = save_lineno;
228  strcpy(hoc_xopen_file_, savname.c_str());
229  return 0;
230 }
231 
232 void hoc_xopen(void) /* read and execute a hoc program */
233 {
234  if (ifarg(2)) {
235  hoc_xopen1(gargstr(1), gargstr(2));
236  } else {
237  hoc_xopen1(gargstr(1), 0);
238  }
239  hoc_ret();
240  hoc_pushx(1.);
241 }
242 
243 void hoc_Fprint(void) /* fprintf function */
244 {
245  char* buf;
246  double d;
247 
248  hoc_sprint1(&buf, 1);
249  d = (double) fprintf(hoc_fout, "%s", buf);
250  hoc_ret();
251  hoc_pushx(d);
252 }
253 
254 void hoc_PRintf(void) /* printf function */
255 {
256  char* buf;
257  double d;
258 
259  hoc_sprint1(&buf, 1);
260  d = (int) strlen(buf);
261  hoc_plprint(buf);
262  fflush(stdout);
263  hoc_ret();
264  hoc_pushx(d);
265 }
266 
267 
268 void hoc_Sprint(void) /* sprintf_function */
269 {
270  char** cpp;
271  char* buf;
272  /* This is not guaranteed safe since we may be pointing to double */
273  cpp = hoc_pgargstr(1);
274  hoc_sprint1(&buf, 2);
275  hoc_assign_str(cpp, buf);
276  hoc_ret();
277  hoc_pushx(1.);
278 }
279 
280 double hoc_scan(FILE* fi) {
281  double d;
282  char fs[256];
283 
284  for (;;) {
285  if (fscanf(fi, "%255s", fs) == EOF) {
286  hoc_execerror("EOF in fscan", (char*) 0);
287  }
288  if (fs[0] == 'i' || fs[0] == 'n' || fs[0] == 'I' || fs[0] == 'N') {
289  continue;
290  }
291  if (sscanf(fs, "%lf", &d) == 1) {
292  /* but if at end of line, leave at beginning of next*/
293  if (fscanf(fi, "\n")) {
294  ;
295  } /* ignore return value */
296  break;
297  }
298  }
299  return d;
300 }
301 
303  double d;
304  char fs[256];
305 
306  for (;;) {
307  if (nrn_fw_fscanf(fi, "%255s", fs) == EOF) {
308  hoc_execerror("EOF in fscan", (char*) 0);
309  }
310  if (fs[0] == 'i' || fs[0] == 'n' || fs[0] == 'I' || fs[0] == 'N') {
311  continue;
312  }
313  if (sscanf(fs, "%lf", &d) == 1) {
314  /* but if at end of line, leave at beginning of next*/
315  nrnignore = nrn_fw_fscanf(fi, "\n");
316  break;
317  }
318  }
319  return d;
320 }
321 
322 void hoc_Fscan(void) /* read a number from input file */
323 {
324  double d;
325  NrnFILEWrap* fi;
326 
327  if (nrn_fw_eq(hoc_frin, stdin)) {
328  fi = hoc_fin;
329  } else {
330  fi = hoc_frin;
331  }
332  d = hoc_fw_scan(fi);
333  hoc_ret();
334  hoc_pushx(d);
335 }
336 
337 void hoc_Getstr(void) /* read a line (or word) from input file */
338 {
339  char* buf;
340  char** cpp;
341  NrnFILEWrap* fi;
342  int word = 0;
343  if (nrn_fw_eq(hoc_frin, stdin)) {
344  fi = hoc_fin;
345  } else {
346  fi = hoc_frin;
347  }
348  cpp = hoc_pgargstr(1);
349  if (ifarg(2)) {
350  word = (int) chkarg(2, 0., 1.);
351  }
352  if (word) {
353  buf = hoc_tmpbuf->buf;
354  if (nrn_fw_fscanf(fi, "%s", buf) != 1) {
355  hoc_execerror("EOF in getstr", (char*) 0);
356  }
357  } else {
358  if ((buf = fgets_unlimited(hoc_tmpbuf, fi)) == (char*) 0) {
359  hoc_execerror("EOF in getstr", (char*) 0);
360  }
361  }
362  hoc_assign_str(cpp, buf);
363  hoc_ret();
364  hoc_pushx((double) strlen(buf));
365 }
366 
367 void hoc_sprint1(char** ppbuf, int argn) { /* convert args to right type for conversion */
368  /* argn is argument number where format is */
369  static HocStr* hs;
370  char *pfmt, *pfrag, frag[120];
371  int convflag, lflag, didit; //, hoc_argtype();
372  char *fmt, *cp;
373 
374  if (!hs) {
375  hs = hocstr_create(512);
376  }
377  fmt = gargstr(argn++);
378  convflag = lflag = didit = 0;
379  auto* pbuf = hs->buf;
380  auto pbuf_size = hs->size + 1;
381  pfrag = frag;
382  *pfrag = 0;
383  *pbuf = 0;
384 
385  auto const resize = [&pbuf, &pbuf_size](HocStr* hs, std::size_t extra_size) {
386  auto const n = pbuf - hs->buf;
387  auto const new_size = n + extra_size;
388  hocstr_resize(hs, new_size);
389  pbuf = hs->buf + n;
390  pbuf_size = new_size + 1 - n;
391  };
392  for (pfmt = fmt; *pfmt; pfmt++) {
393  *pfrag++ = *pfmt;
394  *pfrag = 0;
395  if (convflag) {
396  switch (*pfmt) {
397  case 'l':
398  lflag += 1;
399  break;
400 
401  case 'd':
402  case 'o':
403  case 'x':
404  if (lflag) {
405  if (lflag == 1) {
406  pfrag[1] = pfrag[0];
407  pfrag[0] = pfrag[-1];
408  pfrag[-1] = 'l';
409  }
410  std::snprintf(pbuf, pbuf_size, frag, (long long) *getarg(argn));
411  } else {
412  std::snprintf(pbuf, pbuf_size, frag, (int) *getarg(argn));
413  }
414  didit = 1;
415  break;
416 
417  case 'c':
418  std::snprintf(pbuf, pbuf_size, frag, (char) *getarg(argn));
419  didit = 1;
420  break;
421 
422  case 'f':
423  case 'e':
424  case 'g':
425  std::snprintf(pbuf, pbuf_size, frag, *getarg(argn));
426  didit = 1;
427  break;
428 
429  case 's':
430  if (hoc_is_object_arg(argn)) {
431  cp = hoc_object_name(*hoc_objgetarg(argn));
432  } else {
433  cp = gargstr(argn);
434  }
435  resize(hs, std::strlen(cp) + 100);
436  std::snprintf(pbuf, pbuf_size, frag, cp);
437  didit = 1;
438  break;
439 
440  case '%':
441  pfrag[-1] = 0;
442  std::strncpy(pbuf, frag, pbuf_size);
443  assert(pbuf[pbuf_size - 1] == '\0');
444  didit = 1;
445  argn--; /* an arg was not consumed */
446  break;
447 
448  default:
449  break;
450  }
451  } else if (*pfmt == '%') {
452  convflag = 1;
453  } else if (pfrag - frag > 100) {
454  resize(hs, std::strlen(frag) + 100);
455  std::snprintf(pbuf, pbuf_size, "%s", frag);
456  pfrag = frag;
457  *pfrag = 0;
458  while (*pbuf) {
459  ++pbuf;
460  --pbuf_size;
461  }
462  }
463 
464  if (didit) {
465  argn++;
466  lflag = 0;
467  convflag = 0;
468  didit = 0;
469  pfrag = frag;
470  *pfrag = 0;
471  while (*pbuf) {
472  ++pbuf;
473  --pbuf_size;
474  }
475  resize(hs, 100);
476  }
477  }
478  if (pfrag != frag)
479  std::snprintf(pbuf, pbuf_size, "%s", frag);
480  *ppbuf = hs->buf;
481 }
482 
483 
484 // Split a string containing an env variable into multiple paths (OS-specific)
485 // and return a container with the results
486 static auto split_paths(const std::string& input) {
487  // separator for items in env variables
488 #if defined(WIN32)
489  static constexpr auto os_pathsep = ";";
490 #else
491  static constexpr auto os_pathsep = ":";
492 #endif
493 
494  std::vector<std::string> result;
495  std::size_t start = 0;
496  std::size_t end = 0;
497 
498  while ((end = input.find(os_pathsep, start)) != std::string::npos) {
499  if (end > start) {
500  result.push_back(input.substr(start, end - start));
501  }
502  start = end + 1;
503  }
504 
505  // Add the last segment if it's non-empty
506  if (start < input.size()) {
507  result.push_back(input.substr(start));
508  }
509 
510  return result;
511 }
512 
513 // return the default search paths for loading files
514 static auto default_search_paths() {
515  auto result = std::vector<std::string>({"."});
516 
517  // insert hoc paths (if any)
518  auto hoc_library_path = getenv("HOC_LIBRARY_PATH");
519  if (hoc_library_path) {
520  auto paths = split_paths(std::string(hoc_library_path));
521  std::copy(begin(paths), end(paths), back_inserter(result));
522  }
523 
524  // insert home path
525  auto home_path = fmt::format("{}/lib/hoc", std::string(neuron_home));
526  result.push_back(home_path);
527 
528  return result;
529 }
530 
531 // look for regex ``pattern`` in ``paths`` (non-recursively);
532 // if there is no match, return empty value
533 // if there is a match, return the path of the first file containing the match
534 static std::optional<std::string> search_hoc_files_regex(const std::regex& pattern,
535  const std::vector<std::string>& paths) {
536  namespace fs = std::filesystem;
537  for (const auto& path: paths) {
538  // construct a list containing names of, in this order:
539  // - `.oc` files (sorted according to locale)
540  // - `.hoc` files (sorted according to locale)
541  std::vector<std::string> paths_oc;
542  std::vector<std::string> paths_hoc;
543  for (const auto& entry: fs::directory_iterator(path)) {
544  if (entry.is_regular_file() && entry.path().extension() == ".oc") {
545  paths_oc.push_back(entry.path().string());
546  } else if (entry.is_regular_file() && entry.path().extension() == ".hoc") {
547  paths_hoc.push_back(entry.path().string());
548  }
549  }
550  std::sort(paths_oc.begin(), paths_oc.end(), std::locale());
551  std::sort(paths_hoc.begin(), paths_hoc.end(), std::locale());
552 
553  std::vector<std::string> result;
554  std::merge(paths_oc.begin(),
555  paths_oc.end(),
556  paths_hoc.begin(),
557  paths_hoc.end(),
558  back_inserter(result));
559 
560  for (const auto& entry: result) {
561  auto file = std::ifstream(entry);
562  if (!file.is_open())
563  continue;
564 
565  std::string line;
566  while (std::getline(file, line)) {
567  if (std::regex_search(line, pattern)) {
568  return entry;
569  }
570  }
571  }
572  }
573  return {};
574 }
575 
576 static int hoc_Load_file(int, const char*);
577 
578 static void hoc_load(const char* stype) {
579  int i = 1;
580 
581  while (ifarg(i)) {
582  const char* s = gargstr(i);
583  ++i;
584  const Symbol* sym = hoc_lookup(s);
585  if (!sym || sym->type == UNDEF) {
586  auto pattern = std::regex(fmt::format("^{} {}", stype, s));
587  auto file = search_hoc_files_regex(pattern, default_search_paths());
588  if (file) {
589  fprintf(stderr, "Getting %s from %s\n", s, file->c_str());
590  hoc_Load_file(0, file->c_str());
591  } else {
592  fprintf(stderr, "Couldn't find a file that declares %s\n", s);
593  }
594  }
595  }
596 }
597 
598 void hoc_load_proc(void) {
599  hoc_load("proc");
600  hoc_ret();
601  hoc_pushx(1.);
602 }
603 void hoc_load_func(void) {
604  hoc_load("func");
605  hoc_ret();
606  hoc_pushx(1.);
607 }
608 void hoc_load_template(void) {
609  hoc_load("begintemplate");
610  hoc_ret();
611  hoc_pushx(1.);
612 }
613 
614 void hoc_load_file(void) {
615  int iarg = 1;
616  int i = 0;
617  if (hoc_is_double_arg(iarg)) {
618  i = (int) chkarg(iarg, 0., 1.);
619  iarg = 2;
620  }
621  if (!ifarg(iarg + 1) || !hoc_lookup(gargstr(iarg + 1))) {
622  i = hoc_Load_file(i, gargstr(iarg));
623  }
624  hoc_ret();
625  hoc_pushx((double) i);
626 }
627 
628 static constexpr auto hoc_load_file_size_ = 1024;
629 static int hoc_Load_file(int always, const char* name) {
630  /*
631  if always is 0 then
632  xopen only if file of that name not already loaded with one of
633  the load_xxx functions
634  and search in the current, $HOC_LIBRARY_PATH,
635  $NEURONHOME/lib/hoc directories (in that order) for
636  the file if there is no directory prefix.
637  Temporarily change to the directory containing the file so
638  that it can xopen files relative to its location.
639  */
640  static std::vector<std::string> loaded;
641  int b, is_loaded;
642  int goback;
643  char expname[hoc_load_file_size_];
644  const char* base;
645  char path[hoc_load_file_size_], old[hoc_load_file_size_];
646  char fname[hoc_load_file_size_], cmd[hoc_load_file_size_ + 50];
647  FILE* f;
648 
649  old[0] = '\0';
650  goback = 0;
651  /* has the file already been loaded */
652  is_loaded = 0;
653 
654  for (const std::string& q: loaded) {
655  if (q == name) {
656  if (!always) {
657  return 1;
658  } else {
659  is_loaded = 1;
660  }
661  }
662  }
663 
664  /* maybe the name already has an explicit path */
665  expname[hoc_load_file_size_ - 1] = '\0';
666  strncpy(expname, expand_env_var(name), hoc_load_file_size_);
667  assert(expname[hoc_load_file_size_ - 1] == '\0');
668  name = expname;
669  if ((base = strrchr(name, '/')) != NULL) {
670  strncpy(path, name, base - name);
671  path[base - name] = '\0';
672  ++base;
673  f = fopen(name, "r");
674  } else {
675  base = name;
676  path[0] = '\0';
677  /* otherwise find the file in the default directories */
678  f = fopen(base, "r"); /* cwd */
679  if (!f) { /* try HOC_LIBRARY_PATH */
680  char* hlp;
681  hlp = getenv("HOC_LIBRARY_PATH");
682  while (hlp && *hlp) {
683  char* cp = strchr(hlp, ':');
684  if (!cp) {
685  cp = strchr(hlp, ' ');
686  }
687  if (!cp) {
688  cp = hlp + strlen(hlp);
689  }
690  assert(cp - hlp < hoc_load_file_size_);
691  strncpy(path, hlp, cp - hlp);
692  path[cp - hlp] = '\0';
693  if (*cp) {
694  hlp = cp + 1;
695  } else {
696  hlp = 0;
697  }
698  if (path[0]) {
699  nrn_assert(snprintf(fname, hoc_load_file_size_, "%s/%s", path, base) <
701  f = fopen(expand_env_var(fname), "r");
702  if (f) {
703  break;
704  }
705  } else {
706  break;
707  }
708  }
709  }
710  if (!f) { /* try NEURONHOME/lib/hoc */
711  Sprintf(path, "$(NEURONHOME)/lib/hoc");
712  assert(strlen(path) + strlen(base) + 1 < hoc_load_file_size_);
713  nrn_assert(snprintf(fname, hoc_load_file_size_, "%s/%s", path, base) <
715  f = fopen(expand_env_var(fname), "r");
716  }
717  }
718  /* add the name to the list of loaded packages */
719  if (f) {
720  if (!is_loaded) {
721  loaded.push_back(name);
722  }
723  b = 1;
724  } else {
725  b = 0;
726  hoc_warning("Couldn't find:", name);
727  path[0] = '\0';
728  }
729  /* change to the right directory*/
730  if (b && path[0]) {
731  goback = (getcwd(old, 1000) != 0);
732  errno = 0;
733  if (chdir(expand_env_var(path)) == -1) {
734  hoc_warning("Couldn't change directory to:", path);
735  path[0] = '\0';
736  b = 0;
737  }
738  /*printf("load_file cd to %s\n", path);*/
739  }
740  /* xopen the file */
741  if (b) {
742  /*printf("load_file xopen %s\n", base);*/
743  nrn_assert(strlen(base) < hoc_load_file_size_);
744  snprintf(cmd,
745  hoc_load_file_size_ + 50,
746  "hoc_ac_ = execute1(\"{xopen(\\\"%s\\\")}\")\n",
747  base);
748  b = hoc_oc(cmd);
749  b = (int) hoc_ac_;
750  if (!b) {
751  hoc_execerror("hoc_Load_file", base);
752  }
753  }
754  /* change back */
755  if (path[0] && goback) {
756  if (hoc_chdir(old) == -1) {
757  hoc_warning("Couldn't change directory back to:", old);
758  b = 0;
759  }
760  /*printf("load_file cd back to %s\n", old);*/
761  }
762 
763  return b;
764 }
765 char* hoc_back2forward(char*);
766 void hoc_getcwd(void) {
767  int len;
768  static char* buf;
769  if (!buf) {
770  buf = static_cast<char*>(emalloc(hoc_load_file_size_));
771  }
772  if (!getcwd(buf, hoc_load_file_size_)) {
773  hoc_execerror("getcwd failed. Perhaps the path length is > hoc_load_file_size_", (char*) 0);
774  }
775 #if defined(WIN32)
776  { strcpy(buf, hoc_back2forward(buf)); }
777 #endif
778  len = strlen(buf);
779  if (buf[len - 1] != '/') {
780  buf[len] = '/';
781  buf[len + 1] = '\0';
782  }
783  hoc_ret();
784  hoc_pushstr(&buf);
785 }
786 
787 void hoc_machine_name(void) {
788 #if !defined(WIN32)
789  /*----- functions called -----*/
790  /*----- local variables -----*/
791  char buf[20];
792 
793  gethostname(buf, 20);
795 #endif
796  hoc_ret();
797  hoc_pushx(0.);
798 }
799 
800 int hoc_chdir(const char* path) {
801  return chdir(expand_env_var(path));
802 }
803 
804 void hoc_Chdir(void) {
805  int i = hoc_chdir(gargstr(1));
806  hoc_ret();
807  hoc_pushx((double) i);
808 }
809 
811 int (*nrnpy_pr_stdoe_callback)(int, char*);
812 static int (*nrnpy_pass_callback)();
813 
814 extern "C" void nrnpy_set_pr_etal(int (*cbpr_stdoe)(int, char*), int (*cbpass)()) {
815  nrnpy_pr_stdoe_callback = cbpr_stdoe;
816  nrnpy_pass_callback = cbpass;
817 }
818 
819 void nrnpy_pass() {
820  if (nrnpy_pass_callback) {
821  if ((*nrnpy_pass_callback)() != 1) {
822  hoc_execerror("nrnpy_pass", nullptr);
823  }
824  }
825 }
826 
827 /** printf style specification of hoc_execerror message. (512 char limit) **/
828 [[noreturn]] void hoc_execerr_ext(const char* fmt, ...) {
829  int size; // vsnprintf returns -1 on error.
830  va_list ap;
831 
832  // determine the message size
833  va_start(ap, fmt);
834  size = vsnprintf(NULL, 0, fmt, ap);
835  va_end(ap);
836 
837  if (size >= 0) {
838  constexpr size_t maxsize = 512;
839  char s[maxsize + 1];
840  va_start(ap, fmt);
841  size = vsnprintf(s, maxsize, fmt, ap);
842  va_end(ap);
843  if (size >= 0) {
844  s[maxsize] = '\0'; // truncate if too long
845  hoc_execerror(s, NULL);
846  }
847  }
848  hoc_execerror("hoc_execerr_ext failure with format:", fmt);
849 }
char * gargstr(int narg)
Definition: code2.cpp:227
#define i
Definition: md1redef.h:19
double chkarg(int, double low, double high)
Definition: code2.cpp:626
static auto default_search_paths()
Definition: fileio.cpp:514
void hoc_load_template(void)
Definition: fileio.cpp:608
void hoc_Sprint(void)
Definition: fileio.cpp:268
static std::optional< std::string > search_hoc_files_regex(const std::regex &pattern, const std::vector< std::string > &paths)
Definition: fileio.cpp:534
NrnFILEWrap * hoc_frin
Definition: fileio.cpp:26
static void hoc_load(const char *stype)
Definition: fileio.cpp:578
static int(* nrnpy_pass_callback)()
Definition: fileio.cpp:812
char * hoc_xopen_file_
Definition: fileio.cpp:159
void hoc_load_file(void)
Definition: fileio.cpp:614
double hoc_fw_scan(NrnFILEWrap *fi)
Definition: fileio.cpp:302
int(* nrnpy_pr_stdoe_callback)(int, char *)
Definition: fileio.cpp:811
void hoc_PRintf(void)
Definition: fileio.cpp:254
int nrn_is_python_extension
Definition: fileio.cpp:810
void hoc_getcwd(void)
Definition: fileio.cpp:766
static int hoc_Load_file(int, const char *)
Definition: fileio.cpp:629
size_t hoc_xopen_file_size_
Definition: fileio.cpp:158
void hoc_load_func(void)
Definition: fileio.cpp:603
void hoc_Fscan(void)
Definition: fileio.cpp:322
double hoc_scan(FILE *fi)
Definition: fileio.cpp:280
void hoc_xopen(void)
Definition: fileio.cpp:232
void hoc_machine_name(void)
Definition: fileio.cpp:787
void hoc_wopen(void)
Definition: fileio.cpp:88
void hoc_load_proc(void)
Definition: fileio.cpp:598
FILE * hoc_fout
Definition: fileio.cpp:27
char * hoc_back2forward(char *)
static auto split_paths(const std::string &input)
Definition: fileio.cpp:486
void nrnpy_set_pr_etal(int(*cbpr_stdoe)(int, char *), int(*cbpass)())
Definition: fileio.cpp:814
void hoc_ropen(void)
Definition: fileio.cpp:60
char * hoc_current_xopen(void)
Definition: fileio.cpp:161
char * neuron_home
Definition: hoc_init.cpp:227
void hoc_Getstr(void)
Definition: fileio.cpp:337
void hoc_Fprint(void)
Definition: fileio.cpp:243
void hoc_stdout(void)
Definition: fileio.cpp:29
static constexpr auto hoc_load_file_size_
Definition: fileio.cpp:628
void hoc_Chdir(void)
Definition: fileio.cpp:804
char buf[512]
Definition: init.cpp:13
int hoc_xopen1(const char *name, const char *rcs)
Definition: fileio.cpp:166
int hoc_is_object_arg(int narg)
Definition: code.cpp:876
void hoc_plprint(const char *)
Definition: plot.cpp:97
void hoc_xopen_from_audit(const char *fname)
Definition: audit.cpp:248
int hoc_retrieving_audit(void)
Definition: audit.cpp:185
void hoc_pushstr(char **d)
Definition: code.cpp:800
void hoc_execerr_ext(const char *fmt,...)
printf style specification of hoc_execerror message.
Definition: fileio.cpp:828
void hoc_ret()
void hoc_audit_from_xopen1(const char *fname, const char *rcs)
Definition: audit.cpp:130
void hoc_assign_str(char **cpp, const char *buf)
Definition: code.cpp:2263
const char * expand_env_var(const char *s)
Definition: fileio.cpp:113
int hoc_oc(const char *buf)
Definition: hoc.cpp:1314
int hoc_is_double_arg(int narg)
Definition: code.cpp:864
int hoc_xopen_run(Symbol *sp, const char *str)
Definition: code.cpp:667
int hoc_chdir(const char *path)
Definition: fileio.cpp:800
double hoc_ac_
Definition: hoc_init.cpp:222
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:73
void nrnpy_pass()
Definition: fileio.cpp:819
int nrnignore
Definition: hoc.cpp:42
void hoc_sprint1(char **ppbuf, int argn)
Definition: fileio.cpp:367
Symbol * hoc_lookup(const char *)
Definition: symbol.cpp:59
char ** hoc_pgargstr(int narg)
Definition: code.cpp:1623
char * fgets_unlimited(HocStr *s, NrnFILEWrap *f)
Definition: hoc.cpp:838
HocStr * hoc_tmpbuf
Definition: hoc.cpp:137
HocStr * hocstr_create(size_t size)
Definition: hoc.cpp:828
int hoc_lineno
Definition: hoc.cpp:156
void hocstr_resize(HocStr *hs, size_t n)
Definition: hoc.cpp:847
int hoc_pipeflag
Definition: hoc.cpp:120
#define assert(ex)
Definition: hocassrt.h:24
#define getarg
Definition: hocdec.h:17
Object ** hoc_objgetarg(int)
Definition: code.cpp:1614
void hoc_pushx(double)
Definition: code.cpp:779
#define IGNORE(arg)
Definition: model.h:224
const char * name
Definition: init.cpp:16
Item * prev(Item *item)
Definition: list.cpp:94
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
void * erealloc(void *ptr, size_t size)
Definition: nrnoc_aux.cpp:94
static void * emalloc(size_t size)
Definition: mpispike.cpp:30
void hoc_warning(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:44
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.
Definition: wrap_sprintf.h:14
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
#define nrn_fw_eq(fw, ff)
Definition: nrnfilewrap.h:11
#define nrn_fw_fclose
Definition: nrnfilewrap.h:12
#define nrn_fw_set_stdin()
Definition: nrnfilewrap.h:13
#define nrn_fw_fscanf
Definition: nrnfilewrap.h:18
FILE NrnFILEWrap
Definition: nrnfilewrap.h:8
#define nrn_fw_fopen
Definition: nrnfilewrap.h:14
int const size_t const size_t n
Definition: nrngsl.h:10
size_t q
s
Definition: multisend.cpp:521
int ifarg(int)
Definition: code.cpp:1607
FILE * hoc_fin
Definition: hoc.cpp:152
static double resize(void *v)
Definition: ocptrvector.cpp:86
#define NULL
Definition: spdefs.h:105
Definition: hocstr.h:6
size_t size
Definition: hocstr.h:8
char * buf
Definition: hocstr.h:7
Definition: model.h:47
short type
Definition: model.h:48