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  char format[32];
355  snprintf(format, sizeof(format), "%%%zus", hoc_tmpbuf->size - 1);
356  if (nrn_fw_fscanf(fi, format, buf) != 1) {
357  hoc_execerror("EOF in getstr", (char*) 0);
358  }
359  } else {
360  if ((buf = fgets_unlimited(hoc_tmpbuf, fi)) == (char*) 0) {
361  hoc_execerror("EOF in getstr", (char*) 0);
362  }
363  }
364  hoc_assign_str(cpp, buf);
365  hoc_ret();
366  hoc_pushx((double) strlen(buf));
367 }
368 
369 void hoc_sprint1(char** ppbuf, int argn) { /* convert args to right type for conversion */
370  /* argn is argument number where format is */
371  static HocStr* hs;
372  char *pfmt, *pfrag, frag[120];
373  int convflag, lflag, didit; //, hoc_argtype();
374  char *fmt, *cp;
375 
376  if (!hs) {
377  hs = hocstr_create(512);
378  }
379  fmt = gargstr(argn++);
380  convflag = lflag = didit = 0;
381  auto* pbuf = hs->buf;
382  auto pbuf_size = hs->size + 1;
383  pfrag = frag;
384  *pfrag = 0;
385  *pbuf = 0;
386 
387  auto const resize = [&pbuf, &pbuf_size](HocStr* hs, std::size_t extra_size) {
388  auto const n = pbuf - hs->buf;
389  auto const new_size = n + extra_size;
390  hocstr_resize(hs, new_size);
391  pbuf = hs->buf + n;
392  pbuf_size = new_size + 1 - n;
393  };
394  for (pfmt = fmt; *pfmt; pfmt++) {
395  *pfrag++ = *pfmt;
396  *pfrag = 0;
397  if (convflag) {
398  switch (*pfmt) {
399  case 'l':
400  lflag += 1;
401  break;
402 
403  case 'd':
404  case 'o':
405  case 'x':
406  if (lflag) {
407  if (lflag == 1) {
408  pfrag[1] = pfrag[0];
409  pfrag[0] = pfrag[-1];
410  pfrag[-1] = 'l';
411  }
412  std::snprintf(pbuf, pbuf_size, frag, (long long) *getarg(argn));
413  } else {
414  std::snprintf(pbuf, pbuf_size, frag, (int) *getarg(argn));
415  }
416  didit = 1;
417  break;
418 
419  case 'c':
420  std::snprintf(pbuf, pbuf_size, frag, (char) *getarg(argn));
421  didit = 1;
422  break;
423 
424  case 'f':
425  case 'e':
426  case 'g':
427  std::snprintf(pbuf, pbuf_size, frag, *getarg(argn));
428  didit = 1;
429  break;
430 
431  case 's':
432  if (hoc_is_object_arg(argn)) {
433  cp = hoc_object_name(*hoc_objgetarg(argn));
434  } else {
435  cp = gargstr(argn);
436  }
437  resize(hs, std::strlen(cp) + 100);
438  std::snprintf(pbuf, pbuf_size, frag, cp);
439  didit = 1;
440  break;
441 
442  case '%':
443  pfrag[-1] = 0;
444  std::strncpy(pbuf, frag, pbuf_size);
445  assert(pbuf[pbuf_size - 1] == '\0');
446  didit = 1;
447  argn--; /* an arg was not consumed */
448  break;
449 
450  default:
451  break;
452  }
453  } else if (*pfmt == '%') {
454  convflag = 1;
455  } else if (pfrag - frag > 100) {
456  resize(hs, std::strlen(frag) + 100);
457  std::snprintf(pbuf, pbuf_size, "%s", frag);
458  pfrag = frag;
459  *pfrag = 0;
460  while (*pbuf) {
461  ++pbuf;
462  --pbuf_size;
463  }
464  }
465 
466  if (didit) {
467  argn++;
468  lflag = 0;
469  convflag = 0;
470  didit = 0;
471  pfrag = frag;
472  *pfrag = 0;
473  while (*pbuf) {
474  ++pbuf;
475  --pbuf_size;
476  }
477  resize(hs, 100);
478  }
479  }
480  if (pfrag != frag)
481  std::snprintf(pbuf, pbuf_size, "%s", frag);
482  *ppbuf = hs->buf;
483 }
484 
485 
486 // Split a string containing an env variable into multiple paths (OS-specific)
487 // and return a container with the results
488 static auto split_paths(const std::string& input) {
489  // separator for items in env variables
490 #if defined(WIN32)
491  static constexpr auto os_pathsep = ";";
492 #else
493  static constexpr auto os_pathsep = ":";
494 #endif
495 
496  std::vector<std::string> result;
497  std::size_t start = 0;
498  std::size_t end = 0;
499 
500  while ((end = input.find(os_pathsep, start)) != std::string::npos) {
501  if (end > start) {
502  result.push_back(input.substr(start, end - start));
503  }
504  start = end + 1;
505  }
506 
507  // Add the last segment if it's non-empty
508  if (start < input.size()) {
509  result.push_back(input.substr(start));
510  }
511 
512  return result;
513 }
514 
515 // return the default search paths for loading files
516 static auto default_search_paths() {
517  auto result = std::vector<std::string>({"."});
518 
519  // insert hoc paths (if any)
520  auto hoc_library_path = getenv("HOC_LIBRARY_PATH");
521  if (hoc_library_path) {
522  auto paths = split_paths(std::string(hoc_library_path));
523  std::copy(begin(paths), end(paths), back_inserter(result));
524  }
525 
526  // insert home path
527  auto home_path = fmt::format("{}/lib/hoc", std::string(neuron_home));
528  result.push_back(home_path);
529 
530  return result;
531 }
532 
533 // look for regex ``pattern`` in ``paths`` (non-recursively);
534 // if there is no match, return empty value
535 // if there is a match, return the path of the first file containing the match
536 static std::optional<std::string> search_hoc_files_regex(const std::regex& pattern,
537  const std::vector<std::string>& paths) {
538  namespace fs = std::filesystem;
539  for (const auto& path: paths) {
540  // construct a list containing names of, in this order:
541  // - `.oc` files (sorted according to locale)
542  // - `.hoc` files (sorted according to locale)
543  std::vector<std::string> paths_oc;
544  std::vector<std::string> paths_hoc;
545  for (const auto& entry: fs::directory_iterator(path)) {
546  if (entry.is_regular_file() && entry.path().extension() == ".oc") {
547  paths_oc.push_back(entry.path().string());
548  } else if (entry.is_regular_file() && entry.path().extension() == ".hoc") {
549  paths_hoc.push_back(entry.path().string());
550  }
551  }
552  std::sort(paths_oc.begin(), paths_oc.end(), std::locale());
553  std::sort(paths_hoc.begin(), paths_hoc.end(), std::locale());
554 
555  std::vector<std::string> result;
556  std::merge(paths_oc.begin(),
557  paths_oc.end(),
558  paths_hoc.begin(),
559  paths_hoc.end(),
560  back_inserter(result));
561 
562  for (const auto& entry: result) {
563  auto file = std::ifstream(entry);
564  if (!file.is_open())
565  continue;
566 
567  std::string line;
568  while (std::getline(file, line)) {
569  if (std::regex_search(line, pattern)) {
570  return entry;
571  }
572  }
573  }
574  }
575  return {};
576 }
577 
578 static int hoc_Load_file(int, const char*);
579 
580 static void hoc_load(const char* stype) {
581  int i = 1;
582 
583  while (ifarg(i)) {
584  const char* s = gargstr(i);
585  ++i;
586  const Symbol* sym = hoc_lookup(s);
587  if (!sym || sym->type == UNDEF) {
588  auto pattern = std::regex(fmt::format("^{} {}", stype, s));
589  auto file = search_hoc_files_regex(pattern, default_search_paths());
590  if (file) {
591  fprintf(stderr, "Getting %s from %s\n", s, file->c_str());
592  hoc_Load_file(0, file->c_str());
593  } else {
594  fprintf(stderr, "Couldn't find a file that declares %s\n", s);
595  }
596  }
597  }
598 }
599 
600 void hoc_load_proc(void) {
601  hoc_load("proc");
602  hoc_ret();
603  hoc_pushx(1.);
604 }
605 void hoc_load_func(void) {
606  hoc_load("func");
607  hoc_ret();
608  hoc_pushx(1.);
609 }
610 void hoc_load_template(void) {
611  hoc_load("begintemplate");
612  hoc_ret();
613  hoc_pushx(1.);
614 }
615 
616 void hoc_load_file(void) {
617  int iarg = 1;
618  int i = 0;
619  if (hoc_is_double_arg(iarg)) {
620  i = (int) chkarg(iarg, 0., 1.);
621  iarg = 2;
622  }
623  if (!ifarg(iarg + 1) || !hoc_lookup(gargstr(iarg + 1))) {
624  i = hoc_Load_file(i, gargstr(iarg));
625  }
626  hoc_ret();
627  hoc_pushx((double) i);
628 }
629 
630 static constexpr auto hoc_load_file_size_ = 1024;
631 static int hoc_Load_file(int always, const char* name) {
632  /*
633  if always is 0 then
634  xopen only if file of that name not already loaded with one of
635  the load_xxx functions
636  and search in the current, $HOC_LIBRARY_PATH,
637  $NEURONHOME/lib/hoc directories (in that order) for
638  the file if there is no directory prefix.
639  Temporarily change to the directory containing the file so
640  that it can xopen files relative to its location.
641  */
642  static std::vector<std::string> loaded;
643  int b, is_loaded;
644  int goback;
645  char expname[hoc_load_file_size_];
646  const char* base;
647  char path[hoc_load_file_size_], old[hoc_load_file_size_];
648  char fname[hoc_load_file_size_], cmd[hoc_load_file_size_ + 50];
649  FILE* f;
650 
651  old[0] = '\0';
652  goback = 0;
653  /* has the file already been loaded */
654  is_loaded = 0;
655 
656  for (const std::string& q: loaded) {
657  if (q == name) {
658  if (!always) {
659  return 1;
660  } else {
661  is_loaded = 1;
662  }
663  }
664  }
665 
666  /* maybe the name already has an explicit path */
667  expname[hoc_load_file_size_ - 1] = '\0';
668  strncpy(expname, expand_env_var(name), hoc_load_file_size_);
669  assert(expname[hoc_load_file_size_ - 1] == '\0');
670  name = expname;
671  if ((base = strrchr(name, '/')) != NULL) {
672  strncpy(path, name, base - name);
673  path[base - name] = '\0';
674  ++base;
675  f = fopen(name, "r");
676  } else {
677  base = name;
678  path[0] = '\0';
679  /* otherwise find the file in the default directories */
680  f = fopen(base, "r"); /* cwd */
681  if (!f) { /* try HOC_LIBRARY_PATH */
682  char* hlp;
683  hlp = getenv("HOC_LIBRARY_PATH");
684  while (hlp && *hlp) {
685  char* cp = strchr(hlp, ':');
686  if (!cp) {
687  cp = strchr(hlp, ' ');
688  }
689  if (!cp) {
690  cp = hlp + strlen(hlp);
691  }
692  assert(cp - hlp < hoc_load_file_size_);
693  strncpy(path, hlp, cp - hlp);
694  path[cp - hlp] = '\0';
695  if (*cp) {
696  hlp = cp + 1;
697  } else {
698  hlp = 0;
699  }
700  if (path[0]) {
701  nrn_assert(snprintf(fname, hoc_load_file_size_, "%s/%s", path, base) <
703  f = fopen(expand_env_var(fname), "r");
704  if (f) {
705  break;
706  }
707  } else {
708  break;
709  }
710  }
711  }
712  if (!f) { /* try NEURONHOME/lib/hoc */
713  Sprintf(path, "$(NEURONHOME)/lib/hoc");
714  assert(strlen(path) + strlen(base) + 1 < hoc_load_file_size_);
715  nrn_assert(snprintf(fname, hoc_load_file_size_, "%s/%s", path, base) <
717  f = fopen(expand_env_var(fname), "r");
718  }
719  }
720  /* add the name to the list of loaded packages */
721  if (f) {
722  if (!is_loaded) {
723  loaded.push_back(name);
724  }
725  b = 1;
726  } else {
727  b = 0;
728  hoc_warning("Couldn't find:", name);
729  path[0] = '\0';
730  }
731  /* change to the right directory*/
732  if (b && path[0]) {
733  goback = (getcwd(old, 1000) != 0);
734  errno = 0;
735  if (chdir(expand_env_var(path)) == -1) {
736  hoc_warning("Couldn't change directory to:", path);
737  path[0] = '\0';
738  b = 0;
739  }
740  /*printf("load_file cd to %s\n", path);*/
741  }
742  /* xopen the file */
743  if (b) {
744  /*printf("load_file xopen %s\n", base);*/
745  nrn_assert(strlen(base) < hoc_load_file_size_);
746  snprintf(cmd,
747  hoc_load_file_size_ + 50,
748  "hoc_ac_ = execute1(\"{xopen(\\\"%s\\\")}\")\n",
749  base);
750  b = hoc_oc(cmd);
751  b = (int) hoc_ac_;
752  if (!b) {
753  hoc_execerror("hoc_Load_file", base);
754  }
755  }
756  /* change back */
757  if (path[0] && goback) {
758  if (hoc_chdir(old) == -1) {
759  hoc_warning("Couldn't change directory back to:", old);
760  b = 0;
761  }
762  /*printf("load_file cd back to %s\n", old);*/
763  }
764 
765  return b;
766 }
767 char* hoc_back2forward(char*);
768 void hoc_getcwd(void) {
769  int len;
770  static char* buf;
771  if (!buf) {
772  buf = static_cast<char*>(emalloc(hoc_load_file_size_));
773  }
774  if (!getcwd(buf, hoc_load_file_size_)) {
775  hoc_execerror("getcwd failed. Perhaps the path length is > hoc_load_file_size_", (char*) 0);
776  }
777 #if defined(WIN32)
778  { strcpy(buf, hoc_back2forward(buf)); }
779 #endif
780  len = strlen(buf);
781  if (buf[len - 1] != '/') {
782  buf[len] = '/';
783  buf[len + 1] = '\0';
784  }
785  hoc_ret();
786  hoc_pushstr(&buf);
787 }
788 
789 void hoc_machine_name(void) {
790 #if !defined(WIN32)
791  /*----- functions called -----*/
792  /*----- local variables -----*/
793  char buf[20];
794 
795  gethostname(buf, 20);
797 #endif
798  hoc_ret();
799  hoc_pushx(0.);
800 }
801 
802 int hoc_chdir(const char* path) {
803  return chdir(expand_env_var(path));
804 }
805 
806 void hoc_Chdir(void) {
807  int i = hoc_chdir(gargstr(1));
808  hoc_ret();
809  hoc_pushx((double) i);
810 }
811 
813 int (*nrnpy_pr_stdoe_callback)(int, char*);
814 static int (*nrnpy_pass_callback)();
815 
816 extern "C" void nrnpy_set_pr_etal(int (*cbpr_stdoe)(int, char*), int (*cbpass)()) {
817  nrnpy_pr_stdoe_callback = cbpr_stdoe;
818  nrnpy_pass_callback = cbpass;
819 }
820 
821 void nrnpy_pass() {
822  if (nrnpy_pass_callback) {
823  if ((*nrnpy_pass_callback)() != 1) {
824  hoc_execerror("nrnpy_pass", nullptr);
825  }
826  }
827 }
828 
829 /** printf style specification of hoc_execerror message. (512 char limit) **/
830 [[noreturn]] void hoc_execerr_ext(const char* fmt, ...) {
831  int size; // vsnprintf returns -1 on error.
832  va_list ap;
833 
834  // determine the message size
835  va_start(ap, fmt);
836  size = vsnprintf(NULL, 0, fmt, ap);
837  va_end(ap);
838 
839  if (size >= 0) {
840  constexpr size_t maxsize = 512;
841  char s[maxsize + 1];
842  va_start(ap, fmt);
843  size = vsnprintf(s, maxsize, fmt, ap);
844  va_end(ap);
845  if (size >= 0) {
846  s[maxsize] = '\0'; // truncate if too long
847  hoc_execerror(s, NULL);
848  }
849  }
850  hoc_execerror("hoc_execerr_ext failure with format:", fmt);
851 }
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:516
void hoc_load_template(void)
Definition: fileio.cpp:610
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:536
NrnFILEWrap * hoc_frin
Definition: fileio.cpp:26
static void hoc_load(const char *stype)
Definition: fileio.cpp:580
static int(* nrnpy_pass_callback)()
Definition: fileio.cpp:814
char * hoc_xopen_file_
Definition: fileio.cpp:159
void hoc_load_file(void)
Definition: fileio.cpp:616
double hoc_fw_scan(NrnFILEWrap *fi)
Definition: fileio.cpp:302
int(* nrnpy_pr_stdoe_callback)(int, char *)
Definition: fileio.cpp:813
void hoc_PRintf(void)
Definition: fileio.cpp:254
int nrn_is_python_extension
Definition: fileio.cpp:812
void hoc_getcwd(void)
Definition: fileio.cpp:768
static int hoc_Load_file(int, const char *)
Definition: fileio.cpp:631
size_t hoc_xopen_file_size_
Definition: fileio.cpp:158
void hoc_load_func(void)
Definition: fileio.cpp:605
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:789
void hoc_wopen(void)
Definition: fileio.cpp:88
void hoc_load_proc(void)
Definition: fileio.cpp:600
FILE * hoc_fout
Definition: fileio.cpp:27
char * hoc_back2forward(char *)
static auto split_paths(const std::string &input)
Definition: fileio.cpp:488
void nrnpy_set_pr_etal(int(*cbpr_stdoe)(int, char *), int(*cbpass)())
Definition: fileio.cpp:816
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:630
void hoc_Chdir(void)
Definition: fileio.cpp:806
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:830
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:802
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:821
int nrnignore
Definition: hoc.cpp:42
void hoc_sprint1(char **ppbuf, int argn)
Definition: fileio.cpp:369
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