NEURON
code.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 /* /local/src/master/nrn/src/oc/code.cpp,v 1.37 1999/07/03 14:20:21 hines Exp */
3 
4 #if defined(__GO32__)
5 #include <go32.h>
6 #endif
7 
8 #include <errno.h>
9 #include "hoc.h"
10 #include "code.h"
11 #include "hocstr.h"
12 #include "parse.hpp"
13 #include "ocfunc.h"
14 #include "ocmisc.h"
15 #include "hocparse.h"
16 #include "equation.h"
17 #include <math.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <nrnmpi.h>
21 #include "nrnfilewrap.h"
22 
23 
24 #if CABLE
25 #include "options.h"
26 #include "section.h"
27 
28 
29 int bbs_poll_;
30 extern void bbs_handle(void);
31 #define BBSPOLL \
32  if (--bbs_poll_ == 0) { \
33  bbs_handle(); \
34  }
35 
36 int nrn_isecstack();
37 #else
38 #define BBSPOLL /**/
39 #endif
40 
41 extern void debugzz(Inst*);
42 int hoc_return_type_code = 0; /* flag for allowing integers (1) and booleans (2) to be recognized as
43  such */
44 
45 #define STACKCHK \
46  if (stackp >= stacklast) \
47  execerror("Stack too deep.", "Increase with -NSTACK stacksize option");
48 
49 int tstkchk_actual(int i, int j) {
50  int k, l;
51  char* s[2];
52  if (i != j) {
53  for (k = 0, l = i; k < 2; k++, l = j) {
54  switch (l) {
55  case NUMBER:
56  s[k] = "(double)";
57  break;
58  case STRING:
59  s[k] = "(char *)";
60  break;
61  case OBJECTVAR:
62  s[k] = "(Object **)";
63  break;
64  case USERINT:
65  s[k] = "(int)";
66  break;
67  case SYMBOL:
68  s[k] = "(Symbol)";
69  break;
70  case VAR:
71  s[k] = "(double *)";
72  break;
73  case OBJECTTMP: /* would use OBJECT if it existed */
74  s[k] = "(Object *)";
75  break;
76  case STKOBJ_UNREF: /* hoc_stkobj_unref allready called */
77  s[k] = "(Object * already unreffed on stack)";
78  break;
79  default:
80  s[k] = "(Unknown)";
81  break;
82  }
83  }
84  fprintf(stderr, "bad stack access: expecting %s; really %s\n", s[1], s[0]);
85  execerror("interpreter stack type error", (char*) 0);
86  }
87  return 0;
88 }
89 
90 #define USEMACROS 1
91 
92 /* warning! tstkchk(i,j) when i!=j will call execerror and error recovery
93  now uses stackp to recover OBJECTTMP resources. So it must be the case that
94  stackp - stack is an even number (since stack item, itemtype values
95  use a pair of stack locations). This invalidates the previous pop idiom
96  tstkchk((--stackp)->i, type), (--stackp)->val)) since if tstkchk calls
97  execerror without returning, stackp is no longer consistent since the
98  second decrement no longer takes place.
99 
100  Furthermore, tstkchk(i,j) should be called prior to actually popping the
101  stack so that the execerror will properly unref the otherwise unexpected
102  possible OBJECTTMP.
103 */
104 
105 #if USEMACROS
106 /* warning! tstkchk is a macro that uses each arg twice. So error if
107  the arg in the call has side effects. Eg avoid args like --stackp
108 */
109 #define tstkchk(i, j) (((i) != (j)) ? tstkchk_actual(i, j) : 0)
110 #define pushxm(d) \
111  ((stackp++)->val = (d)); \
112  ((stackp++)->i = NUMBER)
113 #define pushsm(d) \
114  ((stackp++)->sym = (d)); \
115  ((stackp++)->i = SYMBOL)
116 #define nopopm() (stackp -= 2) /*provision at use made to deal with OBJECTTMP*/
117 #define xpopm() (tstkchk(stackp[-1].i, NUMBER), nopopm(), stackp->val)
118 #define spopm() (tstkchk(stackp[-1].i, SYMBOL), nopopm(), stackp->sym)
119 #else
120 #define pushxm(d) pushx(d)
121 #define pushsm(d) pushs(d)
122 #define xpopm() xpop()
123 #define spopm() spop()
124 #define nopopm() nopop()
125 #define tstkchk(i, j) tstkchk_actual(i, j)
126 #endif
127 
128 #define EPS hoc_epsilon
129 
130 #define NSTACK 1000 /* default size */
131 #define nstack hoc_nstack
132 
133 // TODO - ugly but workable for now
134 namespace std {
135 #define stack stlstack
136 } // namespace std
137 
138 static Datum* stack; /* the stack */
139 static Datum* stackp; /* next free spot on stack */
140 static Datum* stacklast; /* last stack element */
141 
142 #define NPROG 50000
143 Inst* prog; /* the machine */
144 Inst* progp; /* next free spot for code generation */
145 Inst* pc; /* program counter during execution */
146 Inst* progbase; /* start of current subprogram */
147 Inst* prog_parse_recover; /* start after parse error */
148 int hoc_returning; /* 1 if return stmt seen, 2 if break, 3 if continue */
149 /* 4 if stop */
150 typedef struct Frame { /* proc/func call stack frame */
151  Symbol* sp; /* symbol table entry */
152  Inst* retpc; /* where to resume after return */
153  Datum* argn; /* n-th argument on stack */
154  int nargs; /* number of arguments */
155  Inst* iter_stmt_begin; /* Iterator statement starts here */
156  Object* iter_stmt_ob; /* context of Iterator statement */
157  Object* ob; /* for stack frame debug message */
159 #define NFRAME 512 /* default size */
160 #define nframe hoc_nframe
161 static Frame *frame, *fp, *framelast; /* first, frame pointer, last */
162 
163 /* temporary object references come from this pool. This allows the
164 stack to be aware if it is storing a temporary. We are trying to
165 solve problems of objrefs on the stack changing the object they point
166 to and also a failure of garbage collection since temporary objrefs have
167 not, in the past, been reffed or unreffed.
168 The first problem is easily solved without much efficiency loss
169 by having the stack store the object pointer instead of the objref pointer.
170 
171 Garbage collection is implemented by reffing any object that is placed
172 on the stack via hoc_push_object (and thus borrows the use of the
173 type OBJECTTMP) It is then the responsibility of everything that
174 pops an object to determine whether the object should be unreffed.
175 This is also done on error recovery and when the stack frame is popped.
176 I hate the efficiency loss but it is not as bad as it could be
177 since most popping occurs when the stack frame is popped and in this
178 case it is faster to check for OBJECTTMP than if the returned Object**
179 is from the pool.
180 */
181 #define DEBUG_GARBAGE 1
182 #define TOBJ_POOL_SIZE 50
184 static int obj_pool_index_;
185 static int tobj_count; /* how many stack pushes of OBJECTTMP have been reffed*/
186 
187 /*
188 Here is the old comment on the function when it was in hoc_oop.cpp.
189 
190 At this time we are dealing uniformly with object variables and cannot
191 deal cleanly with objects. Eventually it may be possible to put an
192 object pointer on the stack but not now. Try to avoid using "functions
193 which return new objects" as arguments to other functions. If this is
194 done then it may happen that when the stack pointer is finally used it
195 may point to a different object than when it was put on the stack.
196 Things are safe when a temp_objvar is finally removed from the stack.
197 Memory leakage will occur if a temp_objvar is passed as an arg but never
198 assigned to a full fledged object variable. ie its reference count is 0
199 but unref will never be called on it.
200 The danger is illustrated with
201  proc p(obj.func_returning_object()) { // $o1 is on the stack
202  print $o1 // correct object
203  for i=0,100 {
204  o = obj.func_returning_different_object()
205  print i, $o1 //when i=50 $o1 will be different
206  }
207  }
208 In this case one should first assign $o1 to another object variable
209 and then use that object variable exclusively instead of $o1.
210 This also prevent leakage of the object pointed to by $o1.
211 
212 If this ever becomes a problem then it is not too difficult to
213 implement objects on the stack with garbage collection.
214 */
215 
217  Object** tobj;
220  *tobj = obj;
221  return tobj;
222 }
223 
224 /* should be called after finished with pointer from a popobj */
225 
228  --tobj_count;
229  hoc_obj_unref(*p);
230  }
231 }
232 
233 /*
234 vec.cpp.x[0] used freed memory because the temporary vector was unreffed
235 after the x pointer was put on the stack but before it was evaluated.
236 The hoc_pop_defer replaces the nopop in in hoc_object_component handling
237 of a cplus steer method (which pushes a double pointer). The corresponding
238 hoc_unref_defer takes place in hoc_object_eval after evaluating
239 the pointer. This should take care of the most common (itself very rare)
240 problem. However it still would not in general
241 take care of the purposeless passing
242 of &vec.cpp.x[0] as an argument to a function since intervening pop_defer/unref_defer
243 pairs could take place.
244 */
246 
247 void hoc_unref_defer(void) {
248  if (unref_defer_) {
249 #if 0
250  printf("hoc_unref_defer %s %d\n", hoc_object_name(unref_defer_), unref_defer_->refcount);
251 #endif
253  unref_defer_ = (Object*) 0;
254  }
255 }
256 
257 void hoc_pop_defer(void) {
258  Object* obj;
259  if (unref_defer_) {
260 #if 0
261  printf("hoc_pop_defer unrefs %s %d\n", hoc_object_name(unref_defer_), unref_defer_->refcount);
262 #endif
263  hoc_unref_defer();
264  }
265  if (stackp <= stack)
266  execerror("stack underflow", (char*) 0);
267  if (stackp[-1].i == OBJECTTMP) {
268  unref_defer_ = stackp[-2].obj;
269  if (unref_defer_) {
271  }
272 #if 0
273  printf("hoc_pop_defer %s %d\n", hoc_object_name(unref_defer_), unref_defer_->refcount);
274 #endif
275  }
276  hoc_nopop();
277 }
278 
279 /* should be called on each OBJECTTMP on the stack after adjusting the
280 stack pointer downward */
281 
282 void hoc_stkobj_unref(Object* o, int stkindex) {
283  if (stack[stkindex + 1].i == OBJECTTMP) {
284  --tobj_count;
285  hoc_obj_unref(o);
286  stack[stkindex + 1].i = STKOBJ_UNREF;
287  }
288 }
289 
290 /* check the args of the frame and unref any of type OBJECTTMP */
291 
292 static void frameobj_clean(Frame* f) {
293  Datum* s;
294  int i, narg;
295  if (f->nargs == 0) {
296  return;
297  }
298  s = f->argn + 2;
299  for (i = f->nargs - 1; i >= 0; --i) {
300  s -= 2;
301  if (s[1].i == OBJECTTMP) {
302  hoc_stkobj_unref(s->obj, (int) (s - stack));
303  }
304  }
305 }
306 
307 /* unref items on the stack frame associated with localobj in case of error */
308 static void frame_objauto_recover_on_err(Frame* ff) { /* only on error */
309  Frame* f;
310  for (f = fp; f > ff; --f) {
311  int i;
312  Symbol* sp = f->sp;
313  if (sp->u.u_proc == NULL) { /* skip if the procedure is not defined */
314  continue;
315  }
316  /* argn is the nargs argument on the stack. Stack items come in pairs
317  so stack increments are always multiples of 2.
318  Here, stkp is the last+1 localobj slot pair on the stack.
319  */
320  Datum* stkp = f->argn + 2 + sp->u.u_proc->nauto * 2;
321  for (i = sp->u.u_proc->nobjauto; i > 0; --i) {
322  Object* ob = stkp[-2 * i].obj;
323  hoc_obj_unref(ob);
324  /* Note that these AUTOOBJECT stack locations have an itemtype that
325  are left over from the previous stack usage of that location.
326  Regardless of that itemtype (e.g. OBJECTTMP), these did NOT
327  increment tobj_count so we need to guarantee that the subsequent
328  stack_obtmp_recover_on_err does not inadvertently free it again
329  by setting the itemtype to a non OBJECTTMP value. I hope this is
330  the only place where stack space was used in which no item type
331  was specified.
332  We are doing this here which happens rarely to avoid having to
333  set them when the stack obj pointers are zeroed.
334  */
335  stkp[-2 * i + 1].i = 0;
336  }
337  }
338 }
339 
340 static void stack_obtmp_recover_on_err(int tcnt) {
341  if (tobj_count > tcnt) {
342  Datum* stkp;
343  /* stackp - 2 because stackp is next available stack slot and
344  stack item,itemtype takes up two slots.
345  */
346  for (stkp = stackp - 2; stkp >= stack; stkp -= 2) {
347  if (stkp[1].i == OBJECTTMP) {
348  hoc_stkobj_unref(stkp->obj, (int) (stkp - stack));
349  if (tobj_count == tcnt) {
350  return;
351  }
352  } else if (stkp[1].i == STKOBJ_UNREF) {
353  printf("OBJECTTMP at stack index %ld already unreffed\n", stkp - stack);
354  }
355  }
356  }
357 }
358 
359 void hoc_init_space(void) /* create space for stack and code */
360 {
361  if (nframe == 0) {
362  nframe = NFRAME;
363  }
364  if (nstack == 0) {
365  nstack = NSTACK;
366  }
367  stackp = stack = (Datum*) emalloc(sizeof(Datum) * nstack);
368  stacklast = stack + nstack;
369  progp = progbase = prog = (Inst*) emalloc(sizeof(Inst) * NPROG);
370  fp = frame = (Frame*) emalloc(sizeof(Frame) * nframe);
371  framelast = frame + nframe;
373 }
374 
375 #define MAXINITFCNS 10
376 static int maxinitfcns;
378 
379 void hoc_prstack(void) {
380  int i;
381  Datum* s;
382  Printf("interpreter stack: %ld \n", (stackp - stack) / 2);
383  for (i = 0, s = stackp - 1; s > stack; --s, ++i) {
384  if (i > 10) {
385  Printf("...\n");
386  break;
387  }
388  Printf("%d stacktype=%d\n", i, s->i);
389  --s;
390  }
391 }
392 
394  /* modules that may have to be cleaned up after an execerror */
395  if (maxinitfcns < MAXINITFCNS) {
396  initfcns[maxinitfcns++] = pf;
397  } else {
398  fprintf(stderr, "increase definition for MAXINITFCNS\n");
399  nrn_exit(1);
400  }
401 }
402 
403 void initcode(void) /* initialize for code generation */
404 {
405  int i;
406  errno = 0;
407  if (hoc_errno_count > 5) {
408  fprintf(stderr, "errno set %d times on last execution\n", hoc_errno_count);
409  }
410  hoc_errno_count = 0;
412  progp = progbase;
413  hoc_unref_defer();
414 
416  if (tobj_count) {
418 #if DEBUG_GARBAGE
419  if (tobj_count) {
420  printf("initcode failed with %d left\n", tobj_count);
421  }
422 #endif
423  tobj_count = 0;
424  }
425  stackp = stack;
426  fp = frame;
428  hoc_returning = 0;
429  do_equation = 0;
430  for (i = 0; i < maxinitfcns; ++i) {
431  (*initfcns[i])();
432  }
433 #if CABLE
434  nrn_initcode(); /* special requirements for NEURON */
435 #endif
436 }
437 
438 
439 static Frame* rframe;
440 static Datum* rstack;
441 static const char* parsestr;
442 
443 extern "C" void oc_save_code(Inst** a1,
444  Inst** a2,
445  Datum** a3,
446  Frame** a4,
447  int* a5,
448  int* a6,
449  Inst** a7,
450  Frame** a8,
451  Datum** a9,
452  Symlist** a10,
453  Inst** a11,
454  int* a12) {
455  *a1 = progbase;
456  *a2 = progp;
457  *a3 = stackp;
458  *a4 = fp;
459  *a5 = hoc_returning;
460  *a6 = do_equation;
461  *a7 = pc;
462  *a8 = rframe;
463  *a9 = rstack;
464  *a10 = p_symlist;
465  *a11 = prog_parse_recover;
466  *a12 = tobj_count;
467 }
468 
469 extern "C" void oc_restore_code(Inst** a1,
470  Inst** a2,
471  Datum** a3,
472  Frame** a4,
473  int* a5,
474  int* a6,
475  Inst** a7,
476  Frame** a8,
477  Datum** a9,
478  Symlist** a10,
479  Inst** a11,
480  int* a12) {
481  progbase = *a1;
482  progp = *a2;
484  if (tobj_count > *a12) {
486 #if DEBUG_GARBAGE
487  if (tobj_count != *a12) {
488  printf("oc_restore_code tobj_count=%d should be %d\n", tobj_count, *a12);
489  }
490 #endif
491  }
492  stackp = *a3;
493  fp = *a4;
494  hoc_returning = *a5;
495  do_equation = *a6;
496  pc = *a7;
497  rframe = *a8;
498  rstack = *a9;
499  p_symlist = *a10;
500  prog_parse_recover = *a11;
501 }
502 
503 int hoc_strgets_need(void) {
504  return strlen(parsestr);
505 }
506 
507 char* hoc_strgets(char* cbuf, int nc) { /* getc for a string, used by parser */
508  strncpy(cbuf, parsestr, nc);
509  if (*parsestr == '\0') {
510  return (char*) 0;
511  } else {
512  return cbuf;
513  }
514 }
515 
516 static void rinitcode(void) /* initialize for recursive code generation */
517 {
518  errno = 0;
519  hoc_errno_count = 0;
521  progp = progbase;
522  stackp = rstack;
523  fp = rframe;
525  if (hoc_returning != 4) { /* if stop not seen */
526  hoc_returning = 0;
527  }
528  do_equation = 0;
529 }
530 
532  /* can recursively parse and execute what is in cbuf.
533  may parse single tokens. called from hoc_oc(str).
534  All these parse and execute routines should be combined into
535  a single method robust method. The pipeflag method has become
536  encrusted with too many irrelevant mechanisms. There is no longer
537  anything sacred about the cbuf. The only requiremnent is to tell
538  the get line function where to get its string.
539  */
540  int yret;
541 
542  Frame *sframe, *sfp;
543  Inst *sprogbase, *sprogp, *spc, *sprog_parse_recover;
544  Datum *sstackp, *sstack;
545  Symlist* sp_symlist;
546 
547  if (yystart) {
548  sframe = rframe;
549  sfp = fp;
550  sprogbase = progbase;
551  sprogp = progp;
552  spc = pc, sprog_parse_recover = prog_parse_recover;
553  sstackp = stackp;
554  sstack = rstack;
555  sp_symlist = p_symlist;
556  rframe = fp;
557  rstack = stackp;
558  progbase = progp;
559  p_symlist = (Symlist*) 0;
560  }
561 
562  if (yystart) {
563  rinitcode();
564  }
565  if (hoc_in_yyparse) {
566  hoc_execerror("Cannot reenter parser.",
567  "Maybe you were in the middle of a direct command.");
568  }
569  yret = yyparse();
570  switch (yret) {
571  case 1:
572  execute(progbase);
573  rinitcode();
574  break;
575  case -3:
576  hoc_execerror("incomplete statement parse not allowed\n", nullptr);
577  default:
578  break;
579  }
580  if (yystart) {
581  rframe = sframe;
582  fp = sfp;
583  progbase = sprogbase;
584  progp = sprogp;
585  pc = spc;
586  prog_parse_recover = sprog_parse_recover;
587  stackp = sstackp;
588  rstack = sstack;
589  p_symlist = sp_symlist;
590  }
591 
592  return yret;
593 }
594 
595 int hoc_xopen_run(Symbol* sp, const char* str) { /*recursively parse and execute for xopen*/
596  /* if sp != 0 then parse string and save code */
597  /* without executing. Note str must be a 'list'*/
598  int n = 0;
599  Frame *sframe = rframe, *sfp = fp;
600  Inst *sprogbase = progbase, *sprogp = progp, *spc = pc,
601  *sprog_parse_recover = prog_parse_recover;
602  Datum *sstackp = stackp, *sstack = rstack;
603  Symlist* sp_symlist = p_symlist;
604  rframe = fp;
605  rstack = stackp;
606  progbase = progp;
607  p_symlist = (Symlist*) 0;
608 
609  if (sp == (Symbol*) 0) {
610  for (rinitcode(); hoc_yyparse(); rinitcode())
611  execute(progbase);
612  } else {
613  int savpipeflag;
614  rinitcode();
615  savpipeflag = hoc_pipeflag;
616  hoc_pipeflag = 2;
617  parsestr = str;
618  if (!hoc_yyparse()) {
619  execerror("Nothing to parse", (char*) 0);
620  }
621  n = (int) (progp - progbase);
622  hoc_pipeflag = savpipeflag;
623  hoc_define(sp);
624  rinitcode();
625  }
626  rframe = sframe;
627  fp = sfp;
628  progbase = sprogbase;
629  progp = sprogp;
630  pc = spc;
631  prog_parse_recover = sprog_parse_recover;
632  stackp = sstackp;
633  rstack = sstack;
634  p_symlist = sp_symlist;
635  return n;
636 }
637 
638 #define HOC_TEMP_CHARPTR_SIZE 128
640 static int istmp = 0;
641 
642 char** hoc_temp_charptr(void) {
644  return stmp + istmp;
645 }
646 
647 int hoc_is_temp_charptr(char** cpp) {
648  if (cpp >= stmp && cpp < stmp + HOC_TEMP_CHARPTR_SIZE) {
649  return 1;
650  }
651  return 0;
652 }
653 
654 int hoc_stack_type(void) {
655  return stackp[-1].i;
656 }
657 
658 void pushx(double d) { /* push double onto stack */
659  STACKCHK(stackp++)->val = d;
660  (stackp++)->i = NUMBER;
661 }
662 
663 void hoc_pushobj(Object** d) { /* push pointer to object pointer onto stack */
664  STACKCHK
666  hoc_push_object(*d);
667  return;
668  }
669  (stackp++)->pobj = d;
670  (stackp++)->i = OBJECTVAR;
671 }
672 
673 void hoc_push_object(Object* d) { /* push pointer to object onto stack */
674  STACKCHK(stackp++)->obj = d;
675  (stackp++)->i = OBJECTTMP; /* would use OBJECT if it existed */
676  hoc_obj_ref(d);
677  ++tobj_count;
678 }
679 
680 void hoc_pushstr(char** d) { /* push pointer to string pointer onto stack */
681  STACKCHK(stackp++)->pstr = d;
682  (stackp++)->i = STRING;
683 }
684 
685 void hoc_push_string(void) { /* code for pushing a symbols string */
686  Objectdata* odsav;
687  Object* obsav = 0;
688  Symlist* slsav;
689  Symbol* s;
690  s = (pc++)->sym;
691  if (!s) {
692  hoc_pushstr((char**) 0);
693  return;
694  }
695  if (s->type == CSTRING) {
696  hoc_pushstr(&(s->u.cstr));
697  } else {
698  if (s->cpublic == 2) {
699  s = s->u.sym;
700  odsav = hoc_objectdata_save();
701  obsav = hoc_thisobject;
702  slsav = hoc_symlist;
704  hoc_thisobject = 0;
706  }
707  hoc_pushstr(OPSTR(s));
708  if (obsav) {
710  hoc_thisobject = obsav;
711  hoc_symlist = slsav;
712  }
713  }
714 }
715 
716 void hoc_pushpx(double* d) { /* push double pointer onto stack */
717  STACKCHK(stackp++)->pval = d;
718  (stackp++)->i = VAR;
719 }
720 
721 void pushs(Symbol* d) { /* push symbol pointer onto stack */
722  STACKCHK(stackp++)->sym = d;
723  (stackp++)->i = SYMBOL;
724 }
725 
726 void pushi(int d) { /* push integer onto stack */
727  STACKCHK(stackp++)->i = d;
728  (stackp++)->i = USERINT;
729 }
730 
731 int hoc_stacktype(void) {
732  if (stackp <= stack) {
733  execerror("stack empty", (char*) 0);
734  }
735  return (stackp - 1)->i;
736 }
737 
738 int hoc_argtype(int narg) { /* type of nth arg */
739  if (narg > fp->nargs)
740  execerror(fp->sp->name, "not enough arguments");
741  return (fp->argn[(narg - fp->nargs) * 2 + 1].i);
742 }
743 
745  return (hoc_argtype(narg) == NUMBER);
746 }
747 
749  return (hoc_argtype(narg) == VAR);
750 }
751 
753  return (hoc_argtype(narg) == STRING);
754 }
755 
757  int type = hoc_argtype(narg);
758  return (type == OBJECTVAR || type == OBJECTTMP);
759 }
760 
761 extern "C" int hoc_is_tempobj_arg(int narg) {
762  return (hoc_argtype(narg) == OBJECTTMP);
763 }
764 
765 Datum* hoc_look_inside_stack(int i, int type) { /* stack pointer at depth i; i=0 is top */
766  tstkchk((stackp - 2 * i - 1)->i, type);
767  return stackp - 2 * (i + 1);
768 }
769 
770 Object* hoc_obj_look_inside_stack(int i) { /* stack pointer at depth i; i=0 is top */
771  Datum* d = stackp - 2 * i - 2;
772  int type = d[1].i;
773  if (type == OBJECTTMP) {
774  return d[0].obj;
775  }
776  tstkchk(type, OBJECTVAR);
777  return *(d[0].pobj);
778 }
779 
781  return (int) ((stackp - 2 * i - 2) - stack);
782 }
783 
784 int hoc_inside_stacktype(int i) { /* 0 is top */
785  return (stackp - 2 * i - 1)->i;
786 }
787 
788 double xpop(void) { /* pop double and return top elem from stack */
789  if (stackp <= stack)
790  execerror("stack underflow", (char*) 0);
791  tstkchk(stackp[-1].i, NUMBER);
792  stackp -= 2;
793  return stackp->val;
794 }
795 
796 #if 0
797 void pstack(void) {
798  char* hoc_object_name();
799  Datum* d;
800  int i;
801  for (d=stackp; d > stack;) {
802  i = (--d)->i;
803  --d;
804  switch(i) {
805  case NUMBER:
806  printf("(double)\n");
807  break;
808  case STRING:
809  printf("(char *)\n");
810  break;
811  case OBJECTVAR:
812  printf("(Object **) %s\n", hoc_object_name(*(d->pobj)));
813  break;
814  case USERINT:
815  printf("(int)\n");
816  break;
817  case SYMBOL:
818  printf("(Symbol) %s\n", d->sym);
819  break;
820  case VAR:
821  printf("(double *)\n");
822  break;
823  case OBJECTTMP: /* would use OBJECT if it existed */
824  printf("(Object *) %s\n", hoc_object_name(d->obj));
825  break;
826  case STKOBJ_UNREF: /* hoc_stkobj_ref already called */
827  printf("(Object * already unreffed by hoc_stkobj_ref at stkindex %ld. Following name print may cause a crash if already freed.\n", d - stack);
828  printf(" %s\n", hoc_object_name(d->obj));
829  break;
830  default:
831  printf("(Unknown)\n");
832  break;
833  }
834  }
835 }
836 #endif
837 
838 double* hoc_pxpop(void) { /* pop double pointer and return top elem from stack */
839  if (stackp <= stack)
840  execerror("stack underflow", (char*) 0);
841  tstkchk(stackp[-1].i, VAR);
842  stackp -= 2;
843  return stackp->pval;
844 }
845 
846 Symbol* spop(void) { /* pop symbol pointer and return top elem from stack */
847  if (stackp <= stack)
848  execerror("stack underflow", (char*) 0);
849  tstkchk(stackp[-1].i, SYMBOL);
850  stackp -= 2;
851  return stackp->sym;
852 }
853 
854 /*
855 When using objpop, after dealing with the pointer, one should call
856  hoc_tobj_unref(pobj) in order to prevent memory leakage since
857  the object may have been reffed when it was pushed on the stack
858 */
859 
860 Object** hoc_objpop(void) { /* pop pointer to object pointer and return top elem from stack */
861  if (stackp <= stack)
862  execerror("stack underflow", (char*) 0);
863  stackp -= 2;
864  if (stackp[1].i == OBJECTTMP) {
865  return hoc_temp_objptr(stackp->obj);
866  }
867  tstkchk(stackp[1].i, OBJECTVAR); /* safe because cannot be OBJECTTMP */
868  return stackp->pobj;
869 }
870 
871 Object* hoc_pop_object(void) { /* pop object and return top elem from stack */
872  if (stackp <= stack)
873  execerror("stack underflow", (char*) 0);
874  tstkchk(stackp[-1].i, OBJECTTMP);
875  stackp -= 2;
876  return stackp->obj;
877 }
878 
879 char** hoc_strpop(void) { /* pop pointer to string pointer and return top elem from stack */
880  if (stackp <= stack)
881  execerror("stack underflow", (char*) 0);
882  tstkchk(stackp[-1].i, STRING);
883  stackp -= 2;
884  return stackp->pstr;
885 }
886 
887 int ipop(void) { /* pop symbol pointer and return top elem from stack */
888  if (stackp <= stack)
889  execerror("stack underflow", (char*) 0);
890  tstkchk(stackp[-1].i, USERINT);
891  stackp -= 2;
892  return stackp->i;
893 }
894 
895 void nopop(void) { /* just pop the stack without returning anything */
896  if (stackp <= stack)
897  execerror("stack underflow", (char*) 0);
898  stackp -= 2;
899  if (stackp[1].i == OBJECTTMP) {
900  hoc_stkobj_unref(stackp->obj, (int) (stackp - stack));
901  }
902 }
903 
904 void constpush(void) /* push constant onto stack */
905 {
906  pushxm(*((pc++)->sym)->u.pnum);
907 }
908 
909 void pushzero(void) /* push zero onto stack */
910 {
911  pushxm(0.);
912 }
913 
914 void varpush(void) /* push variable onto stack */
915 {
916  pushsm((pc++)->sym);
917 }
918 
919 #define relative(pc) (pc + (pc)->i)
920 
921 void forcode(void) {
922  double d;
923  Inst* savepc = pc; /* loop body */
924  int isec;
925 
926 #if CABLE
927  isec = nrn_isecstack();
928 #endif
929  execute(savepc + 3); /* condition */
930  d = xpopm();
931  while (d) {
932  execute(relative(savepc)); /* body */
933 #if CABLE
934  if (hoc_returning) {
935  nrn_secstack(isec);
936  }
937 #endif
938  if (hoc_returning == 1 || hoc_returning == 4) /* return or stop */
939  break;
940  else if (hoc_returning == 2) /* break */
941  {
942  hoc_returning = 0;
943  break;
944  } else /* continue */
945  hoc_returning = 0;
946  if ((savepc + 2)->i) /* diff between while and for */
947  execute(relative(savepc + 2)); /* increment */
948  execute(savepc + 3);
949  d = xpopm();
950  }
951  if (!hoc_returning)
952  pc = relative(savepc + 1); /* next statement */
953 }
954 
955 static void warn_assign_dynam_unit(const char* name) {
956  static int first = 1;
957  if (first) {
958  char mes[100];
959  first = 0;
960  sprintf(mes,
961  "Assignment to %s physical constant %s",
962  _nrnunit_use_legacy_ ? "legacy" : "modern",
963  name);
964  hoc_warning(mes, NULL);
965  }
966 }
967 
968 void shortfor(void) {
969  Inst* savepc = pc;
970  double begin, end, *pval = 0;
971  Symbol* sym;
972  int isec;
973 
974  end = xpopm() + EPS;
975  begin = xpopm();
976  sym = spopm();
977 
978  switch (sym->type) {
979  case UNDEF:
980  hoc_execerror(sym->name, "undefined variable");
981  case VAR:
982  if (!ISARRAY(sym)) {
983  if (sym->subtype == USERINT) {
984  execerror("integer iteration variable", sym->name);
985  } else if (sym->subtype == USERDOUBLE) {
986  pval = sym->u.pval;
987  } else if (sym->subtype == DYNAMICUNITS) {
988  pval = sym->u.pval + _nrnunit_use_legacy_;
990  } else {
991  pval = OPVAL(sym);
992  }
993  break;
994  } else {
995  if (sym->subtype == USERINT)
996  execerror("integer iteration variable", sym->name);
997  else if (sym->subtype == USERDOUBLE)
998  pval = sym->u.pval + araypt(sym, SYMBOL);
999  else
1000  pval = OPVAL(sym) + araypt(sym, OBJECTVAR);
1001  }
1002  break;
1003  case AUTO:
1004  pval = &(fp->argn[sym->u.u_auto * 2].val);
1005  break;
1006  default:
1007  execerror("for loop non-variable", sym->name);
1008  }
1009 #if CABLE
1010  isec = nrn_isecstack();
1011 #endif
1012  for (*pval = begin; *pval <= end; *pval += 1.) {
1013  execute(relative(savepc));
1014 #if CABLE
1015  if (hoc_returning) {
1016  nrn_secstack(isec);
1017  }
1018 #endif
1019  if (hoc_returning == 1 || hoc_returning == 4) {
1020  break;
1021  } else if (hoc_returning == 2) {
1022  hoc_returning = 0;
1023  break;
1024  } else {
1025  hoc_returning = 0;
1026  }
1027  }
1028  if (!hoc_returning)
1029  pc = relative(savepc + 1);
1030 }
1031 
1032 void hoc_iterator(void) {
1033  /* pc is ITERATOR symbol, argcount, stmtbegin, stmtend */
1034  /* for testing execute stmt once */
1035  Symbol* sym;
1036  int argcount;
1037  Inst *stmtbegin, *stmtend;
1038 
1039  sym = (pc++)->sym;
1040  argcount = (pc++)->i;
1041  stmtbegin = relative(pc);
1042  stmtend = relative(pc + 1);
1043  ;
1044  hoc_iterator_object(sym, argcount, stmtbegin, stmtend, hoc_thisobject);
1045 }
1046 
1047 void hoc_iterator_object(Symbol* sym, int argcount, Inst* beginpc, Inst* endpc, Object* ob) {
1048  int i;
1049  fp++;
1050  if (fp >= framelast) {
1051  fp--;
1052  execerror(sym->name, "call nested too deeply, increase with -NFRAME framesize option");
1053  }
1054  fp->sp = sym;
1055  fp->nargs = argcount;
1056  fp->retpc = endpc;
1057  fp->argn = stackp - 2;
1058  stackp += sym->u.u_proc->nauto * 2;
1059  /* clear the autoobject pointers */
1060  for (i = sym->u.u_proc->nobjauto; i > 0; --i) {
1061  stackp[-2 * i].obj = (Object*) 0;
1062  }
1063  fp->iter_stmt_begin = beginpc;
1064  fp->iter_stmt_ob = ob;
1065  fp->ob = ob;
1066  STACKCHK
1067  execute(sym->u.u_proc->defn.in);
1068  nopop(); /* 0.0 from the procret() */
1069  if (hoc_returning != 4) {
1070  hoc_returning = 0;
1071  }
1072 }
1073 
1074 void hoc_iterator_stmt(void) {
1075  Inst* pcsav;
1076  Object* ob;
1077  Object* obsav;
1078  Objectdata* obdsav;
1079  Symlist* slsav;
1080  int isec;
1081  Frame* iter_f = fp; /* iterator frame */
1082  Frame* ef = fp - 1; /* iterator statement frame */
1083  fp++; /* execution frame */
1084 
1085  fp->sp = iter_f->sp;
1086  fp->ob = iter_f->ob;
1087  if (ef != frame) {
1088  /*SUPPRESS 26*/
1089  fp->argn = ef->argn;
1090  fp->nargs = ef->nargs;
1091  } else { /* top. only for stack trace */
1092  fp->argn = 0;
1093  fp->nargs = 0;
1094  }
1095 
1096  ob = iter_f->iter_stmt_ob;
1097  obsav = hoc_thisobject;
1098  obdsav = hoc_objectdata_save();
1099  slsav = hoc_symlist;
1100  hoc_thisobject = ob;
1101  if (ob) {
1102  hoc_objectdata = ob->u.dataspace;
1103  hoc_symlist = ob->ctemplate->symtable;
1104  } else {
1107  }
1108 
1109  pcsav = pc;
1110 #if CABLE
1111  isec = nrn_isecstack();
1112 #endif
1113  execute(iter_f->iter_stmt_begin);
1114  pc = pcsav;
1116  hoc_thisobject = obsav;
1117  hoc_symlist = slsav;
1118  --fp;
1119 #if CABLE
1120  if (hoc_returning) {
1121  nrn_secstack(isec);
1122  }
1123 #endif
1124  switch (hoc_returning) {
1125  case 1: /* return means not only return from iter but return from
1126  the procedure containing the iter statement */
1127  hoc_execerror("return from within an iterator statement not allowed.",
1128  "Set a flag and use break.");
1129  case 2: /* break means return from iter */
1130  procret();
1131  break;
1132  case 3: /* continue means go on from iter as though nothing happened*/
1133  hoc_returning = 0;
1134  break;
1135  }
1136 }
1137 
1138 static void for_segment2(Symbol* sym, int mode) {
1139  /* symbol on stack; statement pointed to by pc
1140  continuation pointed to by pc+1. template used is shortfor in code.cpp
1141  of hoc system.
1142  */
1143 
1144 #if CABLE
1145  int i, imax;
1146  Inst* savepc = pc;
1147  double *pval = 0, dx;
1148  int isec;
1149 #if METHOD3
1150  extern int _method3;
1151 #endif
1152 
1153  switch (sym->type) {
1154  case UNDEF:
1155  hoc_execerror(sym->name, "undefined variable");
1156  case VAR:
1157  if (!ISARRAY(sym)) {
1158  if (sym->subtype == USERINT) {
1159  execerror("integer iteration variable", sym->name);
1160  } else if (sym->subtype == USERDOUBLE) {
1161  pval = sym->u.pval;
1162  } else if (sym->subtype == DYNAMICUNITS) {
1163  pval = sym->u.pval + _nrnunit_use_legacy_;
1165  } else {
1166  pval = OPVAL(sym);
1167  }
1168  break;
1169  } else {
1170  if (sym->subtype == USERINT)
1171  execerror("integer iteration variable", sym->name);
1172  else if (sym->subtype == USERDOUBLE)
1173  pval = sym->u.pval + araypt(sym, SYMBOL);
1174  else
1175  pval = OPVAL(sym) + araypt(sym, OBJECTVAR);
1176  }
1177  break;
1178  case AUTO:
1179  pval = &(fp->argn[sym->u.u_auto * 2].val);
1180  break;
1181  default:
1182  execerror("for loop non-variable", sym->name);
1183  }
1184  imax = segment_limits(&dx);
1185 #if METHOD3
1186  if (_method3) {
1187  for (i = 0, *pval = 0; i <= imax; i++) {
1188  if (mode == 0 && (i == imax || i == 0)) {
1189  continue;
1190  }
1191  if (i == imax) {
1192  *pval = 1.;
1193  } else {
1194  *pval = i * dx;
1195  }
1196  execute(relative(savepc));
1197  if (hoc_returning == 1 || hoc_returning == 4) {
1198  break;
1199  } else if (hoc_returning == 2) {
1200  hoc_returning = 0;
1201  break;
1202  } else {
1203  hoc_returning = 0;
1204  }
1205  }
1206  } else
1207 #endif
1208  {
1209  if (mode == 0) {
1210  i = 1;
1211  *pval = dx / 2.;
1212  } else {
1213  i = 0;
1214  *pval = 0.;
1215  }
1216 #if CABLE
1217  isec = nrn_isecstack();
1218 #endif
1219  for (; i <= imax; i++) {
1220  if (i == imax) {
1221  if (mode == 0) {
1222  continue;
1223  }
1224  *pval = 1.;
1225  }
1226  execute(relative(savepc));
1227 #if CABLE
1228  if (hoc_returning) {
1229  nrn_secstack(isec);
1230  }
1231 #endif
1232  if (hoc_returning == 1 || hoc_returning == 4) {
1233  break;
1234  } else if (hoc_returning == 2) {
1235  hoc_returning = 0;
1236  break;
1237  } else {
1238  hoc_returning = 0;
1239  }
1240  if (i == 0) {
1241  *pval += dx / 2.;
1242  } else if (i < imax) {
1243  *pval += dx;
1244  }
1245  }
1246  }
1247  if (!hoc_returning)
1248  pc = relative(savepc + 1);
1249 #else
1250  execerror("for (var) {stmt} syntax only allowed in CABLE", (char*) 0);
1251 #endif
1252 }
1253 
1254 void for_segment(void) {
1255  for_segment2(spopm(), 1);
1256 }
1257 
1258 void for_segment1(void) {
1259  Symbol* sym;
1260  double d;
1261  int mode;
1262  d = xpopm();
1263  sym = spopm();
1264  mode = (fabs(d) < EPS) ? 0 : 1;
1265  for_segment2(sym, mode);
1266 }
1267 
1268 void ifcode(void) {
1269  double d;
1270  Inst* savepc = pc; /* then part */
1271 
1272  execute(savepc + 3); /* condition */
1273  d = xpopm();
1274  if (d)
1275  execute(relative(savepc));
1276  else if ((savepc + 1)->i) /* else part? */
1277  execute(relative(savepc + 1));
1278  if (!hoc_returning)
1279  pc = relative(savepc + 2); /* next stmt */
1280 }
1281 
1282 void Break(void) /* break statement */
1283 {
1284  hoc_returning = 2;
1285 }
1286 
1287 void Continue(void) /* continue statement */
1288 {
1289  hoc_returning = 3;
1290 }
1291 
1292 void Stop(void) /* stop statement */
1293 {
1294  hoc_returning = 4;
1295 }
1296 
1297 void hoc_define(Symbol* sp) { /* put func/proc in symbol table */
1298  Inst *inst, *newinst;
1299 
1300  if (sp->u.u_proc->defn.in != STOP)
1301  free((char*) sp->u.u_proc->defn.in);
1302  free_list(&(sp->u.u_proc->list));
1303  sp->u.u_proc->list = p_symlist;
1304  p_symlist = (Symlist*) 0;
1305  sp->u.u_proc->size = (unsigned) (progp - progbase);
1306  sp->u.u_proc->defn.in = (Inst*) emalloc((unsigned) (progp - progbase) * sizeof(Inst));
1307  newinst = sp->u.u_proc->defn.in;
1308  for (inst = progbase; inst != progp;)
1309  *newinst++ = *inst++;
1310  progp = progbase; /* next code starts here */
1311 }
1312 
1313 void frame_debug(void) /* print the call sequence on an execerror */
1314 {
1315  Frame* f;
1316  int i, j;
1317  char id[10];
1318 
1319  if (nrnmpi_numprocs_world > 1) {
1320  sprintf(id, "%d ", nrnmpi_myid_world);
1321  } else {
1322  id[0] = '\0';
1323  }
1324  for (i = 5, f = fp; f != frame && --i; f = f - 1) { /* print only to depth of 5 */
1325  for (j = i; j; j--) {
1326  Fprintf(stderr, " ");
1327  }
1328  if (f->ob) {
1329  Fprintf(stderr, "%s%s.%s(", id, hoc_object_name(f->ob), f->sp->name);
1330  } else {
1331  Fprintf(stderr, "%s%s(", id, f->sp->name);
1332  }
1333  for (j = 1; j <= f->nargs;) {
1334  switch (f->argn[(j - f->nargs) * 2 + 1].i) {
1335  case NUMBER:
1336  Fprintf(stderr, "%g", f->argn[(j - f->nargs) * 2].val);
1337  break;
1338  case STRING: {
1339  char* s = *f->argn[(j - f->nargs) * 2].pstr;
1340  if (strlen(s) > 15) {
1341  Fprintf(stderr, "\"%.10s...\"", s);
1342  } else {
1343  Fprintf(stderr, "\"%s\"", s);
1344  }
1345  } break;
1346  case OBJECTVAR:
1347  Fprintf(stderr, "%s", hoc_object_name(*f->argn[(j - f->nargs) * 2].pobj));
1348  break;
1349  default:
1350  Fprintf(stderr, "...");
1351  break;
1352  }
1353  if (++j <= f->nargs) {
1354  Fprintf(stderr, ", ");
1355  }
1356  }
1357  Fprintf(stderr, ")\n");
1358  }
1359  if (i <= 0) {
1360  Fprintf(stderr, "and others\n");
1361  }
1362 }
1363 
1364 void push_frame(Symbol* sp, int narg) { /* helpful for explicit function calls */
1365  if (++fp >= framelast) {
1366  --fp;
1367  execerror(sp->name, "call nested too deeply, increase with -NFRAME framesize option");
1368  }
1369  fp->sp = sp;
1370  fp->nargs = narg;
1371  fp->argn = stackp - 2; /* last argument */
1372  fp->ob = hoc_thisobject;
1373 }
1374 
1375 void pop_frame(void) {
1376  int i;
1377  frameobj_clean(fp);
1378  for (i = 0; i < fp->nargs; i++)
1379  nopopm(); /* pop arguments */
1380  --fp;
1381 }
1382 
1383 void call(void) /* call a function */
1384 {
1385  int i, isec;
1386  Symbol* sp = pc[0].sym; /* symbol table entry */
1387  /* for function */
1388  if (++fp >= framelast) {
1389  --fp;
1390  execerror(sp->name, "call nested too deeply, increase with -NFRAME framesize option");
1391  }
1392  fp->sp = sp;
1393  fp->nargs = pc[1].i;
1394  fp->retpc = pc + 2;
1395  fp->ob = hoc_thisobject;
1396  /*SUPPRESS 26*/
1397  fp->argn = stackp - 2; /* last argument */
1398  BBSPOLL
1399 #if CABLE
1400  isec = nrn_isecstack();
1401 #endif
1402  if (sp->type == FUN_BLTIN || sp->type == OBJECTFUNC || sp->type == STRINGFUNC) {
1403  stackp += sp->u.u_proc->nauto * 2; /* Offset stack for auto space */
1404  STACKCHK (*(sp->u.u_proc->defn.pf))();
1405  if (hoc_errno_check()) {
1406  hoc_warning("errno set during call of", sp->name);
1407  }
1408  } else if ((sp->type == FUNCTION || sp->type == PROCEDURE || sp->type == HOCOBJFUNCTION) &&
1409  sp->u.u_proc->defn.in != STOP) {
1410  stackp += sp->u.u_proc->nauto * 2; /* Offset stack for auto space */
1411  STACKCHK
1412  /* clear the autoobject pointers. */
1413  for (i = sp->u.u_proc->nobjauto; i > 0; --i) {
1414  stackp[-2 * i].obj = (Object*) 0;
1415  }
1416  if (sp->cpublic == 2) {
1417  Objectdata* odsav = hoc_objectdata_save();
1418  Object* obsav = hoc_thisobject;
1419  Symlist* slsav = hoc_symlist;
1420 
1422  hoc_thisobject = 0;
1424 
1425  execute(sp->u.u_proc->defn.in);
1426 
1428  hoc_thisobject = obsav;
1429  hoc_symlist = slsav;
1430  } else {
1431  execute(sp->u.u_proc->defn.in);
1432  }
1433  /* the autoobject pointers were unreffed at the ret() */
1434 
1435  } else {
1436  execerror(sp->name, "undefined function");
1437  }
1438 #if CABLE
1439  if (hoc_returning) {
1440  nrn_secstack(isec);
1441  }
1442 #endif
1443  if (hoc_returning != 4) { /*if not stopping */
1444  hoc_returning = 0;
1445  }
1446 }
1447 
1449  /*fake it so c code can call functions that ret() */
1450  /* but these functions better not ask for any arguments */
1451  /* don't forget a double is left on the stack and returning = 1 */
1452  /* use the symbol for the function as the argument, only requirement
1453  which is always true is that it has no local variables pushed on
1454  the stack so nauto=0 and nobjauto=0 */
1455  ++fp;
1456  fp->sp = s;
1457  fp->nargs = 0;
1458  fp->retpc = pc;
1459  fp->ob = 0;
1460 }
1461 
1462 double hoc_call_func(Symbol* s, int narg) {
1463  /* call the symbol as a function, The args better be pushed on the stack
1464  first arg first. */
1465  if (s->type == BLTIN) {
1466  return (*(s->u.ptr))(xpop());
1467  } else {
1468  Inst* pcsav;
1469  Inst fc[4];
1470  fc[0].pf = hoc_call;
1471  fc[1].sym = s;
1472  fc[2].i = narg;
1473  fc[3].in = STOP;
1474 
1475  pcsav = hoc_pc;
1476  hoc_execute(fc);
1477  hoc_pc = pcsav;
1478  return hoc_xpop();
1479  }
1480 }
1481 
1482 void hoc_ret(void) { /* common return from func, proc, or iterator */
1483  int i;
1484  /* unref all the auto object pointers */
1485  for (i = fp->sp->u.u_proc->nobjauto; i > 0; --i) {
1486  hoc_obj_unref(stackp[-2 * i].obj);
1487  }
1488  stackp -= fp->sp->u.u_proc->nauto * 2; /* Pop off the autos */
1489  frameobj_clean(fp);
1490  for (i = 0; i < fp->nargs; i++)
1491  nopopm(); /* pop arguments */
1492  pc = (Inst*) fp->retpc;
1493  --fp;
1494  hoc_returning = 1;
1495 }
1496 
1497 void funcret(void) /* return from a function */
1498 {
1499  double d;
1500  if (fp->sp->type != FUNCTION)
1501  execerror(fp->sp->name, "(proc or iterator) returns value");
1502  d = xpopm(); /* preserve function return value */
1503  ret();
1504  pushxm(d);
1505 }
1506 
1507 void procret(void) /* return from a procedure */
1508 {
1509  if (fp->sp->type == FUNCTION)
1510  execerror(fp->sp->name, "(func) returns no value");
1511  if (fp->sp->type == HOCOBJFUNCTION)
1512  execerror(fp->sp->name, "(obfunc) returns no value");
1513  ret();
1514  pushxm(0.); /*will be popped immediately; necessary because caller
1515  may have compiled it as a function*/
1516 }
1517 
1518 void hocobjret(void) /* return from a hoc level obfunc */
1519 {
1520  Object** d;
1521  if (fp->sp->type != HOCOBJFUNCTION)
1522  execerror(fp->sp->name, "objfunc returns objref");
1523  d = hoc_objpop(); /* preserve function return value */
1524  if (*d) {
1525  (*d)->refcount++;
1526  }
1527  ret();
1528  /*make a temp and ref it in case autoobj returned since ret would
1529  have unreffed it*/
1530  hoc_push_object(*d);
1531 
1532  if (*d) {
1533  (*d)->refcount--;
1534  }
1535  hoc_tobj_unref(d);
1536 }
1537 
1538 void hoc_Numarg(void) {
1539  int narg;
1540  Frame* f = fp - 1;
1541  if (f == frame) {
1542  narg = 0;
1543  } else {
1544  narg = f->nargs;
1545  }
1546  ret();
1547  pushxm((double) narg);
1548 }
1549 
1550 void hoc_Argtype(void) {
1551  int narg, iarg, type, itype = 0;
1552  Frame* f = fp - 1;
1553  if (f == frame) {
1554  execerror("argtype can only be called in a func or proc", 0);
1555  }
1556  iarg = (int) chkarg(1, -1000., 100000.);
1557  if (iarg > f->nargs || iarg < 1) {
1558  itype = -1;
1559  } else {
1560  type = (f->argn[(iarg - f->nargs) * 2 + 1].i);
1561  switch (type) {
1562  case NUMBER:
1563  itype = 0;
1564  break;
1565  case OBJECTVAR:
1566  case OBJECTTMP:
1567  itype = 1;
1568  break;
1569  case STRING:
1570  itype = 2;
1571  break;
1572  case VAR:
1573  itype = 3;
1574  break;
1575  }
1576  }
1577  ret();
1578  pushxm((double) itype);
1579 }
1580 
1581 extern "C" int ifarg(int narg) { /* true if there is an nth argument */
1582  if (narg > fp->nargs)
1583  return 0;
1584  return 1;
1585 }
1586 
1587 Object** hoc_objgetarg(int narg) { /* return pointer to nth argument */
1588  Datum* d;
1589  if (narg > fp->nargs)
1590  execerror(fp->sp->name, "not enough arguments");
1591  d = fp->argn + (narg - fp->nargs) * 2;
1592  if (d[1].i == OBJECTTMP) {
1593  return hoc_temp_objptr(d[0].obj);
1594  }
1595  tstkchk(d[1].i, OBJECTVAR);
1596  return d[0].pobj;
1597 }
1598 
1599 char** hoc_pgargstr(int narg) { /* return pointer to nth argument */
1600  char** cpp = NULL;
1601  Symbol* sym;
1602  int type;
1603  if (narg > fp->nargs)
1604  execerror(fp->sp->name, "not enough arguments");
1605  type = fp->argn[(narg - fp->nargs) * 2 + 1].i;
1606  if (type == STRING) {
1607  cpp = fp->argn[(narg - fp->nargs) * 2].pstr;
1608  } else if (type != SYMBOL) {
1609  execerror("Expecting string argument", (char*) 0);
1610  } else {
1611  sym = fp->argn[(narg - fp->nargs) * 2].sym;
1612  if (sym->type == CSTRING) {
1613  cpp = &sym->u.cstr;
1614  } else if (sym->type == STRING) {
1615  cpp = OPSTR(sym);
1616  } else {
1617  execerror("Expecting string argument", (char*) 0);
1618  }
1619  }
1620  return cpp;
1621 }
1622 
1623 double* hoc_pgetarg(int narg) { /* return pointer to nth argument */
1624  if (narg > fp->nargs)
1625  execerror(fp->sp->name, "not enough arguments");
1626  tstkchk(fp->argn[(narg - fp->nargs) * 2 + 1].i, VAR);
1627  return fp->argn[(narg - fp->nargs) * 2].pval;
1628 }
1629 
1630 extern "C" double* getarg(int narg) { /* return pointer to nth argument */
1631  if (narg > fp->nargs)
1632  execerror(fp->sp->name, "not enough arguments");
1633 #if 1
1634  tstkchk(fp->argn[(narg - fp->nargs) * 2 + 1].i, NUMBER);
1635 #endif
1636  return &fp->argn[(narg - fp->nargs) * 2].val;
1637 }
1638 
1639 int hoc_argindex(void) {
1640  int j;
1641  j = (int) xpopm();
1642  if (j < 1) {
1643  hoc_execerror("arg index i < 1", 0);
1644  }
1645  return j;
1646 }
1647 
1648 void arg(void) /* push argument onto stack */
1649 {
1650  int i;
1651  i = (pc++)->i;
1652  if (i == 0) {
1653  i = hoc_argindex();
1654  }
1655  pushxm(*getarg(i));
1656 }
1657 
1658 void hoc_stringarg(void) /* push string arg onto stack */
1659 {
1660  int i;
1661  i = (pc++)->i;
1662  if (i == 0) {
1663  i = hoc_argindex();
1664  }
1666 }
1667 
1668 double hoc_opasgn(int op, double dest, double src) {
1669  switch (op) {
1670  case '+':
1671  return dest + src;
1672  case '*':
1673  return dest * src;
1674  case '-':
1675  return dest - src;
1676  case '/':
1677  if (src == 0.) {
1678  hoc_execerror("Divide by 0", (char*) 0);
1679  }
1680  return dest / src;
1681  default:
1682  return src;
1683  }
1684 }
1685 
1686 void argassign(void) /* store top of stack in argument */
1687 {
1688  double d;
1689  int i, op;
1690  i = (pc++)->i;
1691  if (i == 0) {
1692  i = hoc_argindex();
1693  }
1694  op = (pc++)->i;
1695  d = xpopm();
1696  if (op) {
1697  d = hoc_opasgn(op, *getarg(i), d);
1698  }
1699  pushxm(d); /* leave value on stack */
1700  *getarg(i) = d;
1701 }
1702 
1703 void hoc_argrefasgn(void) {
1704  double d, *pd;
1705  int i, j, op;
1706  i = (pc++)->i;
1707  j = (pc++)->i;
1708  if (i == 0) {
1709  i = hoc_argindex();
1710  }
1711  op = (pc++)->i;
1712  d = xpopm();
1713  if (j) {
1714  j = (int) (xpopm() + EPS);
1715  }
1716  pd = hoc_pgetarg(i);
1717  if (op) {
1718  d = hoc_opasgn(op, pd[j], d);
1719  }
1720  pushxm(d); /* leave value on stack */
1721  pd[j] = d;
1722 }
1723 
1724 void hoc_argref(void) {
1725  int i, j;
1726  double* pd;
1727  i = (pc++)->i;
1728  j = (pc++)->i;
1729  if (i == 0) {
1730  i = hoc_argindex();
1731  }
1732  pd = hoc_pgetarg(i);
1733  if (j) {
1734  j = (int) (xpopm() + EPS);
1735  }
1736  pushxm(pd[j]);
1737 }
1738 
1739 
1740 void hoc_argrefarg(void) {
1741  double* pd;
1742  int i;
1743  i = (pc++)->i;
1744  if (i == 0) {
1745  i = hoc_argindex();
1746  }
1747  pd = hoc_pgetarg(i);
1748  hoc_pushpx(pd);
1749 }
1750 
1751 void bltin(void) /* evaluate built-in on top of stack */
1752 {
1753  double d;
1754  d = xpopm();
1755  d = (*((pc++)->sym->u.ptr))(d);
1756  pushxm(d);
1757 }
1758 
1759 extern "C" Symbol* hoc_get_symbol(const char* var) {
1760  Symlist* sl = (Symlist*) 0;
1761  Symbol *prc, *sym;
1762  Inst* last;
1763  prc = hoc_parse_stmt(var, &sl);
1764  hoc_run_stmt(prc);
1765 
1766  last = (Inst*) prc->u.u_proc->defn.in + prc->u.u_proc->size - 1;
1767  if (last[-2].pf == eval) {
1768  sym = last[-3].sym;
1769  } else if (last[-3].pf == rangepoint || last[-3].pf == rangevareval) {
1770  sym = last[-2].sym;
1771  } else if (last[-4].pf == hoc_object_eval) {
1772  sym = last[-10].sym;
1773  } else {
1774  sym = (Symbol*) 0;
1775  }
1776  free_list(&sl);
1777  return sym;
1778 }
1779 
1780 Symbol* hoc_get_last_pointer_symbol(void) { /* hard to imagine a kludgier function*/
1781  Symbol* sym = (Symbol*) 0;
1782  Inst* pcv;
1783  int istop = 0;
1784  for (pcv = pc; pcv; --pcv) {
1785  if (pcv->pf == hoc_ob_pointer) {
1786  if (pcv[-2].sym) {
1787  sym = pcv[-2].sym; /* e.g. &ExpSyn[0].A */
1788  } else {
1789  sym = pcv[-6].sym; /* e.g. & Cell[0].soma.v(.5) */
1790  }
1791  break;
1792  } else if (pcv->pf == hoc_evalpointer) {
1793  sym = pcv[-1].sym;
1794  break;
1795  } else if (pcv->pf == rangevarevalpointer) {
1796  sym = pcv[1].sym;
1797  break;
1798  } else if (pcv->in == STOP) {
1799  /* hopefully only got here from python. Give up on second STOP*/
1800  if (istop++ == 1) {
1801  break;
1802  }
1803  }
1804  }
1805  return sym;
1806 }
1807 
1808 void hoc_autoobject(void) { /* AUTOOBJ symbol at pc+1. */
1809  /* pointer to object pointer left on stack */
1810  int i;
1811  Symbol* obs;
1812  Object** obp;
1813 #if PDEBUG
1814  printf("code for hoc_autoobject()\n");
1815 #endif
1816  obs = (pc++)->sym;
1817  hoc_pushobj(&(fp->argn[obs->u.u_auto * 2].obj));
1818 }
1819 
1820 void eval(void) /* evaluate variable on stack */
1821 {
1822  Objectdata* odsav;
1823  Object* obsav = 0;
1824  Symlist* slsav;
1825  double d = 0.0;
1826  extern double cable_prop_eval(Symbol*);
1827  Symbol* sym;
1828  sym = spopm();
1829  if (sym->cpublic == 2) {
1830  sym = sym->u.sym;
1831  odsav = hoc_objectdata_save();
1832  obsav = hoc_thisobject;
1833  slsav = hoc_symlist;
1835  hoc_thisobject = 0;
1837  }
1838  switch (sym->type) {
1839  case UNDEF:
1840  execerror("undefined variable", sym->name);
1841  case VAR:
1842  if (!ISARRAY(sym)) {
1843  if (do_equation && sym->s_varn > 0 && hoc_access[sym->s_varn] == 0) {
1844  hoc_access[sym->s_varn] = var_access;
1845  var_access = sym->s_varn;
1846  }
1847  switch (sym->subtype) {
1848  case USERDOUBLE:
1849  d = *(sym->u.pval);
1850  break;
1851  case USERINT:
1852  d = (double) (*(sym->u.pvalint));
1853  break;
1854  case DYNAMICUNITS:
1855  d = sym->u.pval[_nrnunit_use_legacy_];
1856  break;
1857 #if CABLE
1858  case USERPROPERTY:
1859  d = cable_prop_eval(sym);
1860  break;
1861 #endif
1862  case USERFLOAT:
1863  d = (double) (*(sym->u.pvalfloat));
1864  break;
1865  default:
1866  d = *(OPVAL(sym));
1867  break;
1868  }
1869  } else {
1870  switch (sym->subtype) {
1871  case USERDOUBLE:
1872  d = (sym->u.pval)[araypt(sym, SYMBOL)];
1873  break;
1874  case USERINT:
1875  d = (sym->u.pvalint)[araypt(sym, SYMBOL)];
1876  break;
1877  case USERFLOAT:
1878  d = (sym->u.pvalfloat)[araypt(sym, SYMBOL)];
1879  break;
1880 #if NEMO
1881  case NEMONODE:
1882  hoc_eval_nemonode(sym, xpopm(), &d);
1883  break;
1884  case NEMOAREA:
1885  hoc_eval_nemoarea(sym, xpopm(), &d);
1886  break;
1887 #endif /*NEMO*/
1888  default:
1889  d = (OPVAL(sym))[araypt(sym, OBJECTVAR)];
1890  break;
1891  }
1892  }
1893  break;
1894  case AUTO:
1895  d = fp->argn[sym->u.u_auto * 2].val;
1896  break;
1897  default:
1898  execerror("attempt to evaluate a non-variable", sym->name);
1899  }
1900 
1901  if (obsav) {
1903  hoc_thisobject = obsav;
1904  hoc_symlist = slsav;
1905  }
1906  pushxm(d);
1907 }
1908 
1909 void hoc_evalpointer(void) /* leave pointer to variable on stack */
1910 {
1911  Objectdata* odsav;
1912  Object* obsav = 0;
1913  Symlist* slsav;
1914  double* d = 0;
1915  //*cable_prop_eval_pointer();
1916  Symbol* sym;
1917  sym = spopm();
1918  if (sym->cpublic == 2) {
1919  sym = sym->u.sym;
1920  odsav = hoc_objectdata_save();
1921  obsav = hoc_thisobject;
1922  slsav = hoc_symlist;
1924  hoc_thisobject = 0;
1926  }
1927  switch (sym->type) {
1928  case UNDEF:
1929  execerror("undefined variable", sym->name);
1930  case VAR:
1931  if (!ISARRAY(sym)) {
1932  switch (sym->subtype) {
1933  case USERDOUBLE:
1934  d = sym->u.pval;
1935  break;
1936  case USERINT:
1937  case USERFLOAT:
1938  execerror("can use pointer only to doubles", sym->name);
1939  break;
1940  case DYNAMICUNITS:
1941  d = sym->u.pval + _nrnunit_use_legacy_;
1942  break;
1943 #if CABLE
1944  case USERPROPERTY:
1945  d = cable_prop_eval_pointer(sym);
1946  break;
1947 #endif
1948  default:
1949  d = OPVAL(sym);
1950  break;
1951  }
1952  } else {
1953  switch (sym->subtype) {
1954  case USERDOUBLE:
1955  d = sym->u.pval + araypt(sym, SYMBOL);
1956  break;
1957  case USERINT:
1958  case USERFLOAT:
1959 #if NEMO
1960  case NEMONODE:
1961  case NEMOAREA:
1962 #endif /*NEMO*/
1963  execerror("can use pointer only to doubles", sym->name);
1964  break;
1965  default:
1966  d = OPVAL(sym) + araypt(sym, OBJECTVAR);
1967  break;
1968  }
1969  }
1970  break;
1971  case AUTO:
1972 #if 0
1973  execerror("can't use pointer to local variable", sym->name);
1974 #else
1975  d = &(fp->argn[sym->u.u_auto * 2].val);
1976 #endif
1977  break;
1978  default:
1979  execerror("attempt to evaluate pointer to a non-variable", sym->name);
1980  }
1981  if (obsav) {
1983  hoc_thisobject = obsav;
1984  hoc_symlist = slsav;
1985  }
1986  hoc_pushpx(d);
1987 }
1988 
1989 void add(void) /* add top two elems on stack */
1990 {
1991  double d1, d2;
1992  d2 = xpopm();
1993  d1 = xpopm();
1994  d1 += d2;
1995  pushxm(d1);
1996 }
1997 
1998 void hoc_sub(void) /* subtract top two elems on stack */
1999 {
2000  double d1, d2;
2001  d2 = xpopm();
2002  d1 = xpopm();
2003  d1 -= d2;
2004  pushxm(d1);
2005 }
2006 
2007 void mul(void) /* multiply top two elems on stack */
2008 {
2009  double d1, d2;
2010  d2 = xpopm();
2011  d1 = xpopm();
2012  d1 *= d2;
2013  pushxm(d1);
2014 }
2015 
2016 #if _CRAY
2017 /*
2018  try to do integer division, so that if x is an exact multiple of y
2019  then we really get an integer as the result.
2020  Algorithm: find n such that tx = x * 10^n and ty = y * 10^n are both
2021  integral. If tx/ty leaves no remainder, then tx/ty is the correct
2022  answer and is stored in iptr, intdiv returns true. Otherwise a
2023  floating point division can be done, intdiv returns false.
2024 */
2025 
2026 static int intdiv(double x, double y, int* iptr) {
2027  long ix, iy, iz;
2028  int done = 0;
2029  while (!done) {
2030  if (fabs(x) > (1 << 62) || fabs(y) > (1 << 62))
2031  return 0; /* out of range of integers */
2032  if (x == (long) x && y == (long) y)
2033  done = 1;
2034  else {
2035  x *= (long double) 10;
2036  y *= (long double) 10;
2037  }
2038  }
2039  ix = (long) x;
2040  iy = (long) y;
2041  iz = ix / iy;
2042  if (ix == iz * iy) { /* no remainder */
2043  *iptr = (int) iz;
2044  return 1;
2045  }
2046  return 0;
2047 }
2048 #endif
2049 
2050 void hoc_div(void) /* divide top two elems on stack */
2051 {
2052  double d1, d2;
2053  d2 = xpopm();
2054  if (d2 == 0.0)
2055  execerror("division by zero", (char*) 0);
2056  d1 = xpopm();
2057 #if _CRAY
2058  {
2059  int i;
2060  if (intdiv(d1, d2, &i))
2061  d1 = (int) i; /* result is an integer */
2062  else
2063  d1 = d1 / d2; /* result is not an integer */
2064  }
2065 #else
2066  d1 /= d2;
2067 #endif
2068  pushxm(d1);
2069 }
2070 
2071 void hoc_cyclic(void) /* the modulus function */
2072 {
2073  double d1, d2;
2074  double r, q;
2075  d2 = xpopm();
2076  if (d2 <= 0.)
2077  execerror("a%b, b<=0", (char*) 0);
2078  d1 = xpopm();
2079  r = d1;
2080  if (r >= d2) {
2081  q = floor(d1 / d2);
2082  r = d1 - q * d2;
2083  } else if (r <= -d2) {
2084  q = floor(-d1 / d2);
2085  r = d1 + q * d2;
2086  }
2087  if (r > d2) {
2088  r = r - d2;
2089  }
2090  if (r < 0.) {
2091  r = r + d2;
2092  }
2093 
2094  pushxm(r);
2095 }
2096 
2097 void negate(void) /* negate top element on stack */
2098 {
2099  double d;
2100  d = xpopm();
2101  pushxm(-d);
2102 }
2103 
2104 void gt(void) {
2105  double d1, d2;
2106  d2 = xpopm();
2107  d1 = xpopm();
2108  d1 = (double) (d1 > d2 + EPS);
2109  pushxm(d1);
2110 }
2111 
2112 void lt(void) {
2113  double d1, d2;
2114  d2 = xpopm();
2115  d1 = xpopm();
2116  d1 = (double) (d1 < d2 - EPS);
2117  pushxm(d1);
2118 }
2119 
2120 void ge(void) {
2121  double d1, d2;
2122  d2 = xpopm();
2123  d1 = xpopm();
2124  d1 = (double) (d1 >= d2 - EPS);
2125  pushxm(d1);
2126 }
2127 
2128 void le(void) {
2129  double d1, d2;
2130  d2 = xpopm();
2131  d1 = xpopm();
2132  d1 = (double) (d1 <= d2 + EPS);
2133  pushxm(d1);
2134 }
2135 
2136 void eq(void) {
2137  int t1, t2;
2138  double d1 = 0.0, d2;
2139  t1 = (stackp - 1)->i;
2140  t2 = (stackp - 3)->i;
2141  switch (t2) {
2142  case NUMBER:
2143  tstkchk(t1, t2);
2144  d2 = xpopm();
2145  d1 = xpopm();
2146  d1 = (double) (d1 <= d2 + EPS && d1 >= d2 - EPS);
2147  break;
2148  case STRING:
2149  d1 = (double) (strcmp(*hoc_strpop(), *hoc_strpop()) == 0);
2150  break;
2151  case OBJECTTMP:
2152  case OBJECTVAR: {
2153  Object **o1, **o2;
2154  o1 = hoc_objpop();
2155  o2 = hoc_objpop();
2156  d1 = (double) (*o1 == *o2);
2157  hoc_tobj_unref(o1);
2158  hoc_tobj_unref(o2);
2159  } break;
2160  default:
2161  hoc_execerror("don't know how to compare these types", (char*) 0);
2162  }
2163  pushxm(d1);
2164 }
2165 
2166 void ne(void) {
2167  int t1, t2;
2168  double d1 = 0.0, d2;
2169  t1 = (stackp - 1)->i;
2170  t2 = (stackp - 3)->i;
2171  switch (t1) {
2172  case NUMBER:
2173  tstkchk(t1, t2);
2174  d2 = xpopm();
2175  d1 = xpopm();
2176  d1 = (double) (d1 < d2 - EPS || d1 > d2 + EPS);
2177  break;
2178  case STRING:
2179  d1 = (double) (strcmp(*hoc_strpop(), *hoc_strpop()) != 0);
2180  break;
2181  case OBJECTTMP:
2182  case OBJECTVAR: {
2183  Object **o1, **o2;
2184  o1 = hoc_objpop();
2185  o2 = hoc_objpop();
2186  d1 = (double) (*o1 != *o2);
2187  hoc_tobj_unref(o1);
2188  hoc_tobj_unref(o2);
2189  } break;
2190  default:
2191  hoc_execerror("don't know how to compare these types", (char*) 0);
2192  }
2193  pushxm(d1);
2194 }
2195 
2196 void hoc_and(void) {
2197  double d1, d2;
2198  d2 = xpopm();
2199  d1 = xpopm();
2200  d1 = (double) (d1 != 0.0 && d2 != 0.0);
2201  pushxm(d1);
2202 }
2203 
2204 void hoc_or(void) {
2205  double d1, d2;
2206  d2 = xpopm();
2207  d1 = xpopm();
2208  d1 = (double) (d1 != 0.0 || d2 != 0.0);
2209  pushxm(d1);
2210 }
2211 
2212 void hoc_not(void) {
2213  double d;
2214  d = xpopm();
2215  d = (double) (d == 0.0);
2216  pushxm(d);
2217 }
2218 
2219 void power(void) /* arg1 raised to arg2 */
2220 {
2221  double d1, d2;
2222  d2 = xpopm();
2223  d1 = xpopm();
2224  d1 = Pow(d1, d2);
2225  pushxm(d1);
2226 }
2227 
2228 void assign(void) /* assign result of execute to top symbol */
2229 {
2230  Objectdata* odsav;
2231  Object* obsav = 0;
2232  Symlist* slsav;
2233  int op;
2234  Symbol* sym;
2235  double d2;
2236  op = (pc++)->i;
2237  sym = spopm();
2238  if (sym->cpublic == 2) {
2239  sym = sym->u.sym;
2240  odsav = hoc_objectdata_save();
2241  obsav = hoc_thisobject;
2242  slsav = hoc_symlist;
2244  hoc_thisobject = 0;
2246  }
2247  d2 = xpopm();
2248  switch (sym->type) {
2249  case UNDEF:
2250  hoc_execerror(sym->name, "undefined variable");
2251  case VAR:
2252  if (!ISARRAY(sym)) {
2253  switch (sym->subtype) {
2254  case USERDOUBLE:
2255  if (op) {
2256  d2 = hoc_opasgn(op, *(sym->u.pval), d2);
2257  }
2258  *(sym->u.pval) = d2;
2259  break;
2260  case USERINT:
2261  if (op) {
2262  d2 = hoc_opasgn(op, (double) (*(sym->u.pvalint)), d2);
2263  }
2264  *(sym->u.pvalint) = (int) (d2 + EPS);
2265  break;
2266 #if CABLE
2267  case USERPROPERTY:
2268  cable_prop_assign(sym, &d2, op);
2269  break;
2270 #endif
2271  case USERFLOAT:
2272  if (op) {
2273  d2 = hoc_opasgn(op, (double) (*(sym->u.pvalfloat)), d2);
2274  }
2275  *(sym->u.pvalfloat) = (float) (d2);
2276  break;
2277  case DYNAMICUNITS:
2278  if (op) {
2279  d2 = hoc_opasgn(op, sym->u.pval[_nrnunit_use_legacy_], d2);
2280  }
2281  sym->u.pval[_nrnunit_use_legacy_] = (float) (d2);
2283  break;
2284  default:
2285  if (op) {
2286  d2 = hoc_opasgn(op, *(OPVAL(sym)), d2);
2287  }
2288  *(OPVAL(sym)) = d2;
2289  break;
2290  }
2291  } else {
2292  int ind;
2293  switch (sym->subtype) {
2294  case USERDOUBLE:
2295  ind = araypt(sym, SYMBOL);
2296  if (op) {
2297  d2 = hoc_opasgn(op, (sym->u.pval)[ind], d2);
2298  }
2299  (sym->u.pval)[ind] = d2;
2300  break;
2301  case USERINT:
2302  ind = araypt(sym, SYMBOL);
2303  if (op) {
2304  d2 = hoc_opasgn(op, (double) ((sym->u.pvalint)[ind]), d2);
2305  }
2306  (sym->u.pvalint)[ind] = (int) (d2 + EPS);
2307  break;
2308  case USERFLOAT:
2309  ind = araypt(sym, SYMBOL);
2310  if (op) {
2311  d2 = hoc_opasgn(op, (double) ((sym->u.pvalfloat)[ind]), d2);
2312  }
2313  (sym->u.pvalfloat)[ind] = (float) d2;
2314  break;
2315 #if NEMO
2316  case NEMONODE:
2317  hoc_asgn_nemonode(sym, xpopm(), &d2, op);
2318  break;
2319  case NEMOAREA:
2320  hoc_asgn_nemoarea(sym, xpopm(), &d2, op);
2321  break;
2322 #endif /*NEMO*/
2323  default:
2324  ind = araypt(sym, OBJECTVAR);
2325  if (op) {
2326  d2 = hoc_opasgn(op, (OPVAL(sym))[ind], d2);
2327  }
2328  (OPVAL(sym))[ind] = d2;
2329  break;
2330  }
2331  }
2332  break;
2333  case AUTO:
2334  if (op) {
2335  d2 = hoc_opasgn(op, fp->argn[sym->u.u_auto * 2].val, d2);
2336  }
2337  fp->argn[sym->u.u_auto * 2].val = d2;
2338  break;
2339  default:
2340  execerror("assignment to non-variable", sym->name);
2341  }
2342  if (obsav) {
2344  hoc_thisobject = obsav;
2345  hoc_symlist = slsav;
2346  }
2347  pushxm(d2);
2348 }
2349 
2350 void hoc_assign_str(char** cpp, const char* buf) {
2351  char* s = *cpp;
2352  *cpp = (char*) emalloc((unsigned) (strlen(buf) + 1));
2353  Strcpy(*cpp, buf);
2354  if (s) {
2355  hoc_free_string(s);
2356  }
2357 }
2358 
2359 void assstr(void) { /* assign string on top to stack - 1 */
2360  char **ps1, **ps2;
2361 
2362  ps1 = hoc_strpop();
2363  ps2 = hoc_strpop();
2364  hoc_assign_str(ps2, *ps1);
2365 }
2366 
2367 char* hoc_araystr(Symbol* sym, int index, Objectdata* obd) { /* returns array string for multiple
2368  dimensions */
2369  static char name[100];
2370  char* cp = name + 100;
2371  char buf[20];
2372  int i, n, j, n1;
2373 
2374  *--cp = '\0';
2375  if (ISARRAY(sym)) {
2376  Arrayinfo* a;
2377  if (sym->subtype == 0) {
2378  a = obd[sym->u.oboff + 1].arayinfo;
2379  } else {
2380  a = sym->arayinfo;
2381  }
2382  for (i = a->nsub - 1; i >= 0; --i) {
2383  n = a->sub[i];
2384  j = index % n;
2385  index /= n;
2386  Sprintf(buf, "%d", j);
2387  n1 = strlen(buf);
2388  assert(n1 + 2 < cp - name);
2389  *--cp = ']';
2390  for (j = n1 - 1; j >= 0; --j) {
2391  *--cp = buf[j];
2392  }
2393  *--cp = '[';
2394  }
2395  }
2396  return cp;
2397 }
2398 
2399 int hoc_array_index(Symbol* sp, Objectdata* od) { /* subs must be in reverse order on stack */
2400  int i;
2401  if (ISARRAY(sp)) {
2402  if (sp->subtype == 0) {
2403  Objectdata* sav = hoc_objectdata;
2404  hoc_objectdata = od;
2405  i = araypt(sp, OBJECTVAR);
2406  hoc_objectdata = sav;
2407  } else {
2408  i = araypt(sp, 0);
2409  }
2410  } else {
2411  i = 0;
2412  }
2413  return i;
2414 }
2415 
2416 int araypt(Symbol* sp, int type) { /* return subscript - subs in reverse order on stack */
2417  int i, total, varn;
2418  int d;
2419  Arrayinfo* aray;
2420  if (type == OBJECTVAR) {
2421  aray = OPARINFO(sp);
2422  } else {
2423  aray = sp->arayinfo;
2424  }
2425 
2426  total = 0;
2427  for (i = 0; i < aray->nsub; i++) {
2428  tstkchk((stackp - 2 * (aray->nsub - i) + 1)->i, NUMBER);
2429  d = (int) ((stackp - 2 * (aray->nsub - i))->val + EPS);
2430  if (d < 0 || d >= aray->sub[i])
2431  execerror("subscript out of range", sp->name);
2432  total = total * (aray->sub[i]) + d;
2433  }
2434  for (i = 0; i < aray->nsub; i++)
2435  nopopm();
2436  if (do_equation && sp->s_varn != 0 && (varn = (aray->a_varn)[total]) != 0 &&
2437  hoc_access[varn] == 0) {
2438  hoc_access[varn] = var_access;
2439  var_access = varn;
2440  }
2441  return total;
2442 }
2443 
2444 /* obsolete */
2445 #if CABLE && 0
2446 int nrnpnt_araypt(Symbol* sp, int pi) {
2447  int i, total;
2448  int d;
2449  Arrayinfo* aray = sp->arayinfo;
2450  /* the difference is that the first index is for a neuron point
2451  process vector, and the remaining incices are normal vector indices.
2452  the return value is the parameter index and the first
2453  index is returned in pi. return is 0 if not a vector or if element 0.
2454  */
2455  total = 0;
2456  for (i = 0; i < aray->nsub; i++) {
2457  tstkchk((stackp - 2 * (aray->nsub - i) + 1)->i, NUMBER);
2458  d = (int) ((stackp - 2 * (aray->nsub - i))->val + EPS);
2459  if (d < 0 || d >= aray->sub[i])
2460  execerror("subscript out of range", sp->name);
2461  total = total * (aray->sub[i]) + d;
2462  if (i == 0) {
2463  *pi = total;
2464  total = 0;
2465  }
2466  }
2467  for (i = 0; i < aray->nsub; i++)
2468  nopopm();
2469  return total;
2470 }
2471 #endif
2472 
2473 void print(void) /* pop top value from stack, print it */
2474 {
2475 #if defined(__GO32__)
2476  extern int egagrph;
2477  if (egagrph) {
2478  char buf[50];
2479  sprintf(buf, "\t");
2480  grx_output_some_chars(buf, strlen(buf));
2481  prexpr();
2482  grx_output_some_chars("\n", 1);
2483  } else
2484 #endif
2485  {
2486  nrnpy_pr("\t");
2487  prexpr();
2488  nrnpy_pr("\n");
2489  }
2490 }
2491 
2492 void prexpr(void) /* print numeric value */
2493 {
2494  static HocStr* s;
2495  char* ss;
2496 #if CABLE
2497  extern char* secaccessname();
2498 #endif
2499  Object** pob;
2500 
2501  if (!s)
2502  s = hocstr_create(256);
2503  switch (hoc_stacktype()) {
2504  case NUMBER:
2505  Sprintf(s->buf, "%.8g ", xpopm());
2506  break;
2507  case STRING:
2508  ss = *(hoc_strpop());
2509  hocstr_resize(s, strlen(ss) + 1);
2510  Sprintf(s->buf, "%s ", ss);
2511  break;
2512  case OBJECTTMP:
2513  case OBJECTVAR:
2514  pob = hoc_objpop();
2515  Sprintf(s->buf, "%s ", hoc_object_name(*pob));
2516  hoc_tobj_unref(pob);
2517  break;
2518 #if 0 && CABLE
2519  case SECTION:
2520  Sprintf(s->buf, "%s ", secaccessname());
2521  break;
2522 #endif
2523  default:
2524  hoc_execerror("Don't know how to print this type\n", 0);
2525  }
2526  plprint(s->buf);
2527 }
2528 
2529 void prstr(void) /* print string value */
2530 {
2531  static HocStr* s;
2532  char** cpp;
2533  if (!s)
2534  s = hocstr_create(256);
2535  cpp = hoc_strpop();
2536  hocstr_resize(s, strlen(*cpp) + 10);
2537  Sprintf(s->buf, "%s", *cpp);
2538  plprint(s->buf);
2539 }
2540 
2541 /*-----------------------------------------------------------------*/
2543 /* Added 15-JUN-90 by JCW. This routine deletes a
2544 "defined-on-the-fly" variable from the symbol
2545 list. */
2546 /* modified greatly by Hines. Very unsafe in general. */
2547 {
2548 #if 1
2549  /*---- local variables -----*/
2550  Symbol *doomed, *sp;
2551  /*---- start function ------*/
2552 
2553  /* copy address of the symbol that will be deleted */
2554  doomed = (pc++)->sym;
2555 
2556 #endif
2557 /* hoc_execerror("delete_symbol doesn't work right now.", (char *)0);*/
2558 #if 1
2559  if (doomed->type == UNDEF)
2560  fprintf(stderr, "%s: no such variable\n", doomed->name);
2561  else if (doomed->defined_on_the_fly == 0)
2562  fprintf(stderr, "%s: can't be deleted\n", doomed->name);
2563  else {
2564  extern void hoc_free_symspace(Symbol*);
2565  hoc_free_symspace(doomed);
2566  }
2567 #endif
2568 }
2569 
2570 /*----------------------------------------------------------*/
2571 
2572 void hoc_newline(void) /* print newline */
2573 {
2574  plprint("\n");
2575 }
2576 
2577 void varread(void) /* read into variable */
2578 {
2579  double d = 0.0;
2580  extern NrnFILEWrap* fin;
2581  Symbol* var = (pc++)->sym;
2582 
2583  assert(var->cpublic != 2);
2584  if (!((var->type == VAR || var->type == UNDEF) && !ISARRAY(var) && var->subtype == NOTUSER)) {
2585  execerror(var->name, "is not a scalar variable");
2586  }
2587 Again:
2588  switch (nrn_fw_fscanf(fin, "%lf", OPVAL(var))) {
2589  case EOF:
2590  if (moreinput())
2591  goto Again;
2592  d = *(OPVAL(var)) = 0.0;
2593  break;
2594  case 0:
2595  execerror("non-number read into", var->name);
2596  break;
2597  default:
2598  d = 1.0;
2599  break;
2600  }
2601  var->type = VAR;
2602  pushxm(d);
2603 }
2604 
2605 
2606 static Inst* codechk(void) {
2607  if (progp >= prog + NPROG - 1)
2608  execerror("procedure too big", (char*) 0);
2609  if (zzdebug)
2610  debugzz(progp);
2611  return progp++;
2612 }
2613 
2614 Inst* Code(Pfrv f) { /* install one instruction or operand */
2615  progp->pf = f;
2616  return codechk();
2617 }
2618 
2619 Inst* codei(int f) {
2620  progp->pf = NULL; /* zero high order bits to avoid debugzz problem */
2621  progp->i = f;
2622  return codechk();
2623 }
2624 
2625 Inst* hoc_codeptr(void* vp) {
2626  progp->ptr = vp;
2627  return codechk();
2628 }
2629 
2630 void codesym(Symbol* f) {
2631  progp->sym = f;
2632  IGNORE(codechk());
2633 }
2634 
2635 void codein(Inst* f) {
2636  progp->in = f;
2637  IGNORE(codechk());
2638 }
2639 
2640 void insertcode(Inst* begin, Inst* end, Pfrv f) {
2641  Inst* i;
2642  for (i = end - 1; i != begin; i--) {
2643  *i = *(i - 1);
2644  }
2645  begin->pf = f;
2646 
2647  if (zzdebug) {
2648  Inst* p;
2649  printf("insert code: what follows is the entire code so far\n");
2650  for (p = prog; p < progp; ++p) {
2651  debugzz(p);
2652  }
2653  printf("end of insert code debugging\n");
2654  }
2655 }
2656 
2657 #if defined(DOS) || defined(__GO32__) || defined(WIN32) || (MAC && !defined(DARWIN))
2658 static int ntimes;
2659 #endif
2660 
2661 void execute(Inst* p) /* run the machine */
2662 {
2663  Inst* pcsav;
2664 
2665  BBSPOLL
2666  for (pc = p; pc->in != STOP && !hoc_returning;) {
2667 #if defined(DOS)
2668  if (++ntimes > 10) {
2669  ntimes = 0;
2670 #if 0
2671  kbhit(); /* DOS can't capture interrupt when number crunching*/
2672 #endif
2673  }
2674 #endif
2675 
2676 #if MAC && !defined(DARWIN)
2677  /* there is significant overhead here */
2678  if (++ntimes > 100) {
2679  ntimes = 0;
2680  hoc_check_intupt(1);
2681  }
2682 #endif
2683  if (intset)
2684  execerror("interrupted", (char*) 0);
2685  /* (*((pc++)->pf))(); DEC 5000 increments pc after the return!*/
2686  pcsav = pc++;
2687  (*((pcsav)->pf))();
2688  }
2689 }
void rangevareval(void)
Definition: cabcode.cpp:1456
int segment_limits(double *pdx)
Definition: cabcode.cpp:1919
void nrn_secstack(int i)
Definition: cabcode.cpp:58
const char * secaccessname(void)
Definition: cabcode.cpp:2257
double cable_prop_eval(Symbol *sym)
Definition: cabcode.cpp:1518
void cable_prop_assign(Symbol *sym, double *pd, int op)
Definition: cabcode.cpp:1598
int nrn_isecstack(void)
Definition: cabcode.cpp:54
void rangevarevalpointer(void)
Definition: cabcode.cpp:1410
void nrn_initcode(void)
Definition: cabcode.cpp:76
double * cable_prop_eval_pointer(Symbol *sym)
Definition: cabcode.cpp:1536
void rangepoint(void)
Definition: cabcode.cpp:1465
short index
Definition: cabvars.h:10
short type
Definition: cabvars.h:9
void ifcode(void)
Definition: code.cpp:1268
void argassign(void)
Definition: code.cpp:1686
static Frame * frame
Definition: code.cpp:161
static void warn_assign_dynam_unit(const char *name)
Definition: code.cpp:955
static Inst * codechk(void)
Definition: code.cpp:2606
#define BBSPOLL
Definition: code.cpp:38
void hoc_argref(void)
Definition: code.cpp:1724
void varpush(void)
Definition: code.cpp:914
static void frameobj_clean(Frame *f)
Definition: code.cpp:292
#define nopopm()
Definition: code.cpp:116
#define tstkchk(i, j)
Definition: code.cpp:109
void hoc_prstack(void)
Definition: code.cpp:379
void shortfor(void)
Definition: code.cpp:968
void negate(void)
Definition: code.cpp:2097
Inst * Code(Pfrv f)
Definition: code.cpp:2614
void for_segment1(void)
Definition: code.cpp:1258
void bltin(void)
Definition: code.cpp:1751
void hoc_cyclic(void)
Definition: code.cpp:2071
void hoc_delete_symbol(void)
Definition: code.cpp:2542
static char * stmp[HOC_TEMP_CHARPTR_SIZE]
Definition: code.cpp:639
static Frame * rframe
Definition: code.cpp:439
#define HOC_TEMP_CHARPTR_SIZE
Definition: code.cpp:638
void codein(Inst *f)
Definition: code.cpp:2635
static Object ** hoc_temp_obj_pool_
Definition: code.cpp:183
void prexpr(void)
Definition: code.cpp:2492
static void for_segment2(Symbol *sym, int mode)
Definition: code.cpp:1138
double xpop(void)
Definition: code.cpp:788
static Datum * stackp
Definition: code.cpp:139
void assstr(void)
Definition: code.cpp:2359
static int tobj_count
Definition: code.cpp:185
void hoc_push_string(void)
Definition: code.cpp:685
void ne(void)
Definition: code.cpp:2166
Symbol * hoc_get_last_pointer_symbol(void)
Definition: code.cpp:1780
void push_frame(Symbol *sp, int narg)
Definition: code.cpp:1364
int hoc_array_index(Symbol *sp, Objectdata *od)
Definition: code.cpp:2399
#define TOBJ_POOL_SIZE
Definition: code.cpp:182
static int maxinitfcns
Definition: code.cpp:376
#define MAXINITFCNS
Definition: code.cpp:375
void procret(void)
Definition: code.cpp:1507
#define pushsm(d)
Definition: code.cpp:113
static Pfrv initfcns[MAXINITFCNS]
Definition: code.cpp:377
#define pushxm(d)
Definition: code.cpp:110
void hoc_evalpointer(void)
Definition: code.cpp:1909
char * hoc_strgets(char *cbuf, int nc)
Definition: code.cpp:507
static Frame * fp
Definition: code.cpp:161
void pushx(double d)
Definition: code.cpp:658
void pushi(int d)
Definition: code.cpp:726
void hoc_div(void)
Definition: code.cpp:2050
void codesym(Symbol *f)
Definition: code.cpp:2630
void Break(void)
Definition: code.cpp:1282
void constpush(void)
Definition: code.cpp:904
void hoc_iterator_stmt(void)
Definition: code.cpp:1074
static Datum * stacklast
Definition: code.cpp:140
Inst * codei(int f)
Definition: code.cpp:2619
int tstkchk_actual(int i, int j)
Definition: code.cpp:49
void pushs(Symbol *d)
Definition: code.cpp:721
int hoc_stack_type(void)
Definition: code.cpp:654
Inst * progp
Definition: code.cpp:144
void hocobjret(void)
Definition: code.cpp:1518
void assign(void)
Definition: code.cpp:2228
void ge(void)
Definition: code.cpp:2120
void oc_save_code(Inst **a1, Inst **a2, Datum **a3, Frame **a4, int *a5, int *a6, Inst **a7, Frame **a8, Datum **a9, Symlist **a10, Inst **a11, int *a12)
Definition: code.cpp:443
#define EPS
Definition: code.cpp:128
void gt(void)
Definition: code.cpp:2104
void Stop(void)
Definition: code.cpp:1292
Inst * prog
Definition: code.cpp:143
void print(void)
Definition: code.cpp:2473
void hoc_init_space(void)
Definition: code.cpp:359
void power(void)
Definition: code.cpp:2219
struct Frame Frame
Symbol * spop(void)
Definition: code.cpp:846
void add(void)
Definition: code.cpp:1989
void call(void)
Definition: code.cpp:1383
void hoc_argrefasgn(void)
Definition: code.cpp:1703
#define nframe
Definition: code.cpp:160
int araypt(Symbol *sp, int type)
Definition: code.cpp:2416
void initcode(void)
Definition: code.cpp:403
void hoc_iterator_object(Symbol *sym, int argcount, Inst *beginpc, Inst *endpc, Object *ob)
Definition: code.cpp:1047
void le(void)
Definition: code.cpp:2128
void hoc_Numarg(void)
Definition: code.cpp:1538
void hoc_stringarg(void)
Definition: code.cpp:1658
static void frame_objauto_recover_on_err(Frame *ff)
Definition: code.cpp:308
int hoc_strgets_need(void)
Definition: code.cpp:503
Inst * pc
Definition: code.cpp:145
Inst * progbase
Definition: code.cpp:146
#define spopm()
Definition: code.cpp:118
#define xpopm()
Definition: code.cpp:117
void insertcode(Inst *begin, Inst *end, Pfrv f)
Definition: code.cpp:2640
void hoc_sub(void)
Definition: code.cpp:1998
int hoc_return_type_code
Definition: code.cpp:42
static int obj_pool_index_
Definition: code.cpp:184
static void rinitcode(void)
Definition: code.cpp:516
int ipop(void)
Definition: code.cpp:887
void eval(void)
Definition: code.cpp:1820
#define relative(pc)
Definition: code.cpp:919
void hoc_iterator(void)
Definition: code.cpp:1032
#define stack
Definition: code.cpp:135
void oc_restore_code(Inst **a1, Inst **a2, Datum **a3, Frame **a4, int *a5, int *a6, Inst **a7, Frame **a8, Datum **a9, Symlist **a10, Inst **a11, int *a12)
Definition: code.cpp:469
void funcret(void)
Definition: code.cpp:1497
static int istmp
Definition: code.cpp:640
#define NFRAME
Definition: code.cpp:159
#define NPROG
Definition: code.cpp:142
void pushzero(void)
Definition: code.cpp:909
Inst * hoc_codeptr(void *vp)
Definition: code.cpp:2625
void debugzz(Inst *)
Definition: debug.cpp:23
static Frame * framelast
Definition: code.cpp:161
static const char * parsestr
Definition: code.cpp:441
void lt(void)
Definition: code.cpp:2112
void hoc_autoobject(void)
Definition: code.cpp:1808
void nopop(void)
Definition: code.cpp:895
void for_segment(void)
Definition: code.cpp:1254
#define NSTACK
Definition: code.cpp:130
Inst * prog_parse_recover
Definition: code.cpp:147
static Object * unref_defer_
Definition: code.cpp:245
void eq(void)
Definition: code.cpp:2136
void hoc_newline(void)
Definition: code.cpp:2572
void varread(void)
Definition: code.cpp:2577
void hoc_argrefarg(void)
Definition: code.cpp:1740
static void stack_obtmp_recover_on_err(int tcnt)
Definition: code.cpp:340
void mul(void)
Definition: code.cpp:2007
void hoc_not(void)
Definition: code.cpp:2212
void hoc_and(void)
Definition: code.cpp:2196
void hoc_or(void)
Definition: code.cpp:2204
void prstr(void)
Definition: code.cpp:2529
void forcode(void)
Definition: code.cpp:921
void hoc_unref_defer(void)
Definition: code.cpp:247
static Datum * rstack
Definition: code.cpp:440
void Continue(void)
Definition: code.cpp:1287
#define nstack
Definition: code.cpp:131
void arg(void)
Definition: code.cpp:1648
void hoc_define(Symbol *sp)
Definition: code.cpp:1297
void execute(Inst *p)
Definition: code.cpp:2661
#define STACKCHK
Definition: code.cpp:45
void pop_frame(void)
Definition: code.cpp:1375
void hoc_Argtype(void)
Definition: code.cpp:1550
void hoc_object_eval(void)
Definition: hoc_oop.cpp:1296
void hoc_ob_pointer(void)
int zzdebug
Definition: debug.cpp:7
sprintf(buf, " if (secondorder) {\n" " int _i;\n" " for (_i = 0; _i < %d; ++_i) {\n" " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n" " }}\n", numeqn, listnum, listnum)
#define yyparse
Definition: difeqdef.h:4
double chkarg(int, double low, double high)
Definition: code2.cpp:638
int * hoc_access
Definition: nonlin.cpp:13
static int first
Definition: fmenu.cpp:190
static int egagrph
Definition: fmenu.cpp:122
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:754
void nrn_exit(int)
Definition: hoc.cpp:219
char buf[512]
Definition: init.cpp:13
int hoc_is_object_arg(int narg)
Definition: code.cpp:756
Object ** hoc_objgetarg(int narg)
Definition: code.cpp:1587
void hoc_pushstr(char **d)
Definition: code.cpp:680
double hoc_call_func(Symbol *s, int narg)
Definition: code.cpp:1462
Symbol * hoc_get_symbol(const char *var)
Definition: code.cpp:1759
void frame_debug(void)
Definition: code.cpp:1313
Object * hoc_obj_look_inside_stack(int i)
Definition: code.cpp:770
int hoc_returning
Definition: code.cpp:148
int hoc_argindex(void)
Definition: code.cpp:1639
double * getarg(int narg)
Definition: code.cpp:1630
void hoc_pushpx(double *d)
Definition: code.cpp:716
int hoc_inside_stacktype(int i)
Definition: code.cpp:784
Object * hoc_pop_object(void)
Definition: code.cpp:871
void hoc_pushobj(Object **d)
Definition: code.cpp:663
void hoc_free_string(char *)
Definition: symbol.cpp:395
int hoc_ParseExec(int yystart)
Definition: code.cpp:531
int hoc_obj_look_inside_stack_index(int i)
Definition: code.cpp:780
int hoc_is_str_arg(int narg)
Definition: code.cpp:752
int hoc_errno_check(void)
Definition: math.cpp:109
int hoc_is_temp_charptr(char **cpp)
Definition: code.cpp:647
Objectdata * hoc_objectdata
Definition: hoc_oop.cpp:123
void hoc_assign_str(char **cpp, const char *buf)
Definition: code.cpp:2350
Object ** hoc_temp_objptr(Object *obj)
Definition: code.cpp:216
int hoc_argtype(int narg)
Definition: code.cpp:738
double hoc_opasgn(int op, double dest, double src)
Definition: code.cpp:1668
void hoc_tobj_unref(Object **p)
Definition: code.cpp:226
void hoc_ret(void)
Definition: code.cpp:1482
void hoc_warning(const char *, const char *)
int hoc_is_double_arg(int narg)
Definition: code.cpp:744
int ifarg(int narg)
Definition: code.cpp:1581
int nrnpy_pr(const char *fmt,...)
Definition: fileio.cpp:912
char ** hoc_temp_charptr(void)
Definition: code.cpp:642
int hoc_xopen_run(Symbol *sp, const char *str)
Definition: code.cpp:595
void hoc_obj_ref(Object *obj)
Definition: hoc_oop.cpp:1810
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:72
int hoc_stacktype(void)
Definition: code.cpp:731
void hoc_on_init_register(Pfrv pf)
Definition: code.cpp:393
double * hoc_pxpop(void)
Definition: code.cpp:838
void hoc_fake_call(Symbol *s)
Definition: code.cpp:1448
void hoc_stkobj_unref(Object *o, int stkindex)
Definition: code.cpp:282
Datum * hoc_look_inside_stack(int i, int type)
Definition: code.cpp:765
double hoc_xpop(void)
int hoc_is_pdouble_arg(int narg)
Definition: code.cpp:748
double * hoc_pgetarg(int narg)
Definition: code.cpp:1623
void hoc_pop_defer(void)
Definition: code.cpp:257
void hoc_obj_unref(Object *obj)
Definition: hoc_oop.cpp:1828
char ** hoc_strpop(void)
Definition: code.cpp:879
char * hoc_araystr(Symbol *sym, int index, Objectdata *obd)
Definition: code.cpp:2367
void hoc_push_object(Object *d)
Definition: code.cpp:673
int hoc_is_tempobj_arg(int narg)
Definition: code.cpp:761
char ** hoc_pgargstr(int narg)
Definition: code.cpp:1599
Object ** hoc_objpop(void)
Definition: code.cpp:860
HocStr * hocstr_create(size_t size)
Definition: hoc.cpp:945
int hoc_yyparse(void)
Definition: hoc.cpp:1596
int hoc_in_yyparse
Definition: hoc.cpp:1594
int yystart
Definition: hoc.cpp:689
int moreinput(void)
Definition: hoc.cpp:1215
void hocstr_resize(HocStr *hs, size_t n)
Definition: hoc.cpp:964
int intset
Definition: hoc.cpp:196
Objectdata * hoc_objectdata_restore(Objectdata *obdsav)
Definition: hoc_oop.cpp:143
Objectdata * hoc_objectdata_save(void)
Definition: hoc_oop.cpp:133
#define assert(ex)
Definition: hocassrt.h:32
#define USERPROPERTY
Definition: hocdec.h:94
#define ISARRAY(arg)
Definition: hocdec.h:164
#define USERFLOAT
Definition: hocdec.h:95
#define USERDOUBLE
Definition: hocdec.h:93
#define NOTUSER
Definition: hocdec.h:91
#define OBJECTTMP
Definition: hocdec.h:101
void(* Pfrv)(void)
Definition: hocdec.h:40
#define OPARINFO(sym)
Definition: hocdec.h:311
#define STKOBJ_UNREF
Definition: hocdec.h:102
#define DYNAMICUNITS
Definition: hocdec.h:103
#define USERINT
Definition: hocdec.h:92
#define OPSTR(sym)
Definition: hocdec.h:307
#define OPVAL(sym)
Definition: hocdec.h:306
#define STOP
Definition: hocdec.h:66
#define ind(mm, x)
Definition: isaac64.cpp:18
int bbs_poll_
Definition: datapath.cpp:31
Symlist * hoc_top_level_symlist
Definition: code2.cpp:690
void bbs_handle()
Definition: datapath.cpp:33
Objectdata * hoc_top_level_data
Definition: hoc_oop.cpp:124
void hoc_execute(Inst *)
Symlist * hoc_symlist
static int narg()
Definition: ivocvect.cpp:150
Object * hoc_thisobject
Definition: hoc_oop.cpp:122
double var(InputIterator begin, InputIterator end)
Definition: ivocvect.h:101
void hoc_check_intupt(int intupt)
Definition: macprt.cpp:85
#define pval
Definition: md1redef.h:32
#define i
Definition: md1redef.h:12
#define SYMBOL
Definition: model.h:102
#define IGNORE(arg)
Definition: model.h:247
#define Sprintf
Definition: model.h:233
#define Strcpy
Definition: model.h:238
#define Printf
Definition: model.h:237
#define Fprintf
Definition: model.h:234
floor
Definition: extdef.h:4
fabs
Definition: extdef.h:3
char * name
Definition: init.cpp:16
char * emalloc(unsigned n)
Definition: list.cpp:166
#define printf
Definition: mwprefix.h:26
#define fprintf
Definition: mwprefix.h:30
#define nrn_fw_fscanf
Definition: nrnfilewrap.h:50
#define NrnFILEWrap
Definition: nrnfilewrap.h:39
int const size_t const size_t n
Definition: nrngsl.h:11
#define FUNCTION(a, b)
Definition: nrngsl.h:6
size_t q
if(status)
size_t p
size_t j
int nrnmpi_numprocs_world
int nrnmpi_myid_world
void hoc_call()
Inst * hoc_pc
void hoc_nopop()
static philox4x32_key_t k
Definition: nrnran123.cpp:11
int hoc_errno_count
Definition: math.cpp:16
double Pow(double x, double y)
Definition: math.cpp:75
Symlist * p_symlist
Definition: symbol.cpp:48
void free_list(Symlist **list)
Definition: symbol.cpp:359
int hoc_pipeflag
void hoc_run_stmt(Symbol *)
Definition: code2.cpp:685
Symbol * hoc_parse_stmt(const char *, Symlist **)
Definition: code2.cpp:692
#define STRING
Definition: bbslsrv.cpp:9
static double done(void *v)
Definition: ocbbs.cpp:282
#define var_access
Definition: redef.h:130
#define do_equation
Definition: redef.h:48
#define cbuf
Definition: redef.h:36
#define begin
Definition: redef.h:32
#define plprint
Definition: redef.h:110
#define ret
Definition: redef.h:123
#define fin
Definition: redef.h:60
int _nrnunit_use_legacy_
Definition: hoc_init.cpp:409
sl
Definition: seclist.cpp:181
o
Definition: seclist.cpp:175
#define execerror
Definition: section.h:36
#define NULL
Definition: sptree.h:16
void hoc_free_symspace(Symbol *)
Definition: symbol.cpp:271
unsigned * a_varn
Definition: hocdec.h:69
int nsub
Definition: hocdec.h:70
int sub[1]
Definition: hocdec.h:72
Definition: code.cpp:150
Object * ob
Definition: code.cpp:157
Object * iter_stmt_ob
Definition: code.cpp:156
Inst * iter_stmt_begin
Definition: code.cpp:155
Symbol * sp
Definition: code.cpp:151
int nargs
Definition: code.cpp:154
Datum * argn
Definition: code.cpp:153
Inst * retpc
Definition: code.cpp:152
Definition: hocstr.h:7
char * buf
Definition: hocstr.h:8
Definition: hocdec.h:227
Objectdata * dataspace
Definition: hocdec.h:231
int refcount
Definition: hocdec.h:228
union Object::@39 u
int nauto
Definition: hocdec.h:80
Inst defn
Definition: hocdec.h:76
unsigned long size
Definition: hocdec.h:77
HocStruct Symlist * list
Definition: hocdec.h:78
int nobjauto
Definition: hocdec.h:81
Definition: model.h:57
Proc * u_proc
Definition: hocdec.h:145
HocStruct Symbol * sym
Definition: hocdec.h:156
short cpublic
Note: public is a reserved keyword.
Definition: hocdec.h:125
int u_auto
Definition: hocdec.h:143
short type
Definition: model.h:58
double(* ptr)(double)
Definition: hocdec.h:144
int * pvalint
Definition: hocdec.h:141
long subtype
Definition: model.h:59
float * pvalfloat
Definition: hocdec.h:142
char * cstr
Definition: hocdec.h:139
union Symbol::@18 u
unsigned s_varn
Definition: hocdec.h:158
char * name
Definition: model.h:72
double * pval
Definition: hocdec.h:137
int oboff
Definition: hocdec.h:132
Arrayinfo * arayinfo
Definition: hocdec.h:159
short defined_on_the_fly
Definition: hocdec.h:129
Definition: hocdec.h:84
Definition: hocdec.h:177
HocStruct Object * obj
Definition: hocdec.h:183
double * pval
Definition: hocdec.h:181
int i
Definition: hocdec.h:180
char ** pstr
Definition: hocdec.h:184
Symbol * sym
Definition: hocdec.h:179
HocStruct Object ** pobj
Definition: hocdec.h:182
double val
Definition: hocdec.h:178
Definition: hocdec.h:51
Pfrv pf
Definition: hocdec.h:52
HocUnion Inst * in
Definition: hocdec.h:60
int i
Definition: hocdec.h:63
HocStruct Symbol * sym
Definition: hocdec.h:61
void * ptr
Definition: hocdec.h:62
Arrayinfo * arayinfo
Definition: hocdec.h:223