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