NEURON
hoc_oop.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <stdlib.h>
3 #include <classreg.h>
4 #include "hocstr.h"
5 #include "parse.hpp"
6 #include "hocparse.h"
7 #include "code.h"
8 #include "hocassrt.h"
9 #include "hoclist.h"
10 #include "nrnmpi.h"
11 #include "nrnfilewrap.h"
12 #include <nrnpython_config.h>
13 
14 
15 #define PDEBUG 0
16 
17 #if USE_PYTHON
19 void (*nrnpy_py2n_component)(Object* o, Symbol* s, int nindex, int isfunc);
20 void (*nrnpy_hpoasgn)(Object* o, int type);
21 void* (*nrnpy_opaque_obj2pyobj_p_)(Object*);
22 #endif
23 
24 #if CABLE
25 #include "section.h"
26 #include "nrniv_mf.h"
28 struct Section* nrn_sec_pop();
29 double* nrn_rangepointer(Section*, Symbol*, double x);
30 static int connect_obsec_;
31 #endif
32 
33 #define PUBLIC_TYPE 1
34 #define EXTERNAL_TYPE 2
35 static void call_constructor(Object*, Symbol*, int);
36 static void free_objectdata(Objectdata*, cTemplate*);
37 
39 
41 
42 static Symbol* hoc_obj_;
43 
44 void hoc_install_hoc_obj(void) {
45  /* see void hoc_objvardecl(void) */
46  Object** pobj;
47  Symbol* s = hoc_install("_pysec", OBJECTVAR, 0.0, &hoc_top_level_symlist);
49  hoc_objectdata[s->u.oboff].pobj = pobj = (Object**) emalloc(sizeof(Object*));
50  pobj[0] = nullptr;
51 
52  hoc_oc("objref hoc_obj_[2]\n");
53  hoc_obj_ = hoc_lookup("hoc_obj_");
54 }
55 
58  if (p) {
59  return p[i];
60  } else {
61  return nullptr;
62  }
63 }
64 
65 void hoc_obj_set(int i, Object* obj) {
67  hoc_obj_ref(obj);
68  hoc_dec_refcount(p + i);
69  p[i] = obj;
70 }
71 
72 extern "C" char* hoc_object_name(Object* ob) {
73  static char s[100];
74  if (ob) {
75  Sprintf(s, "%s[%d]", ob->ctemplate->sym->name, ob->index);
76  } else {
77  Sprintf(s, "NULLobject");
78  }
79  return s;
80 }
81 
82 size_t hoc_total_array(Symbol* s) /* total number of elements in array pointer */
83 {
84  int total = 1, i;
85  Arrayinfo* a = OPARINFO(s);
86  if (a) {
87  for (i = a->nsub - 1; i >= 0; --i) {
88  total *= a->sub[i];
89  }
90  }
91  return total;
92 }
93 
95  Objectdata* obd) /* total number of elements in array pointer */
96 {
97  Arrayinfo* a;
98  int total = 1, i;
99 
100  if (!obd) {
101  a = s->arayinfo;
102  } else
103  switch (s->type) {
104 #if CABLE
105  case RANGEVAR:
106  a = s->arayinfo;
107  break;
108 #endif
109  default:
110  a = obd[s->u.oboff + 1].arayinfo;
111  break;
112  }
113  if (a) {
114  for (i = a->nsub - 1; i >= 0; --i) {
115  total *= a->sub[i];
116  }
117  }
118  return total;
119 }
120 
121 static int icntobjectdata = 0;
125 static int icnttoplevel;
127 
128 
131 }
132 
134  /* hoc_top_level_data changes when new vars are introduced */
136  /* a template starts out its Objectdata as 0. */
137  return (Objectdata*) 1;
138  } else {
139  return hoc_objectdata;
140  }
141 }
142 
144  if (obdsav == (Objectdata*) 1) {
145  return hoc_top_level_data;
146  ;
147  } else {
148  return obdsav;
149  }
150 }
151 
152 void hoc_obvar_declare(Symbol* sym, int type, int pmes) {
153  if (sym->type != UNDEF) {
154  return;
155  }
156  assert(sym->cpublic != 2);
157  if (pmes && hoc_symlist == hoc_top_level_symlist) {
158  int b = 0;
159 #if USE_NRNFILEWRAP
160  b = (hoc_fin && hoc_fin->f == stdin);
161 #else
162  b = (hoc_fin == stdin);
163 #endif
164  if (nrnmpi_myid_world == 0 && (hoc_print_first_instance && b)) {
165  NOT_PARALLEL_SUB(Printf("first instance of %s\n", sym->name);)
166  }
167  sym->defined_on_the_fly = 1;
168  }
170  sym->type = type;
171  switch (type) {
172  case VAR:
173  /*printf("hoc_obvar_declare %s\n", sym->name);*/
174  OPVAL(sym) = (double*) ecalloc(1, sizeof(double));
175  break;
176  case STRING:
177  OPSTR(sym) = (char**) 0;
178  break;
179  case OBJECTVAR:
180  break;
181 #if CABLE
182  case SECTION:
183  OPSECITM(sym) = nullptr; // TODO: whaa? (struct Item**)0;
184  break;
185 #endif
186  default:
187  hoc_execerror(sym->name, "can't declare this in obvar_declare");
188  break;
189  }
190 }
191 
192 /*-----------------------------------------------*/
193 
194 /* template stack so nested templates are ok */
195 typedef union {
200  int i;
201 } Templatedatum;
202 #define NTEMPLATESTACK 20
205 
206 static Templatedatum* poptemplate(void) {
207  if (templatestackp == templatestack) {
208  hoc_execerror("templatestack underflow", (char*) 0);
209  }
210  return (--templatestackp);
211 }
212 
213 #define pushtemplatesym(arg) \
214  chktemplate(); \
215  (templatestackp++)->sym = arg
216 #define pushtemplatesymlist(arg) \
217  chktemplate(); \
218  (templatestackp++)->symlist = arg
219 #define pushtemplatei(arg) \
220  chktemplate(); \
221  (templatestackp++)->i = arg
222 #define pushtemplateodata(arg) \
223  chktemplate(); \
224  (templatestackp++)->odata = arg
225 #define pushtemplateo(arg) \
226  chktemplate(); \
227  (templatestackp++)->o = arg
228 
229 static void chktemplate(void) {
232  hoc_execerror("templatestack overflow", (char*) 0);
233  }
234 }
235 /*------------------------------------------------*/
236 
237 /* mostly to allow saving of objects */
238 
239 #define OBJ_STACK_SIZE 10
240 static Object* obj_stack_[OBJ_STACK_SIZE + 1]; /* +1 so we can see the most recent pushed */
241 static int obj_stack_loc;
242 
243 void hoc_object_push(void) {
244  Object* ob = *hoc_objgetarg(1);
245  if (ob->ctemplate->constructor) {
246  hoc_execerror("Can't do object_push for built-in class", 0);
247  }
248  if (obj_stack_loc >= OBJ_STACK_SIZE) {
249  hoc_execerror("too many object context stack depth", 0);
250  }
253  hoc_thisobject = ob;
254  if (ob) {
255  hoc_symlist = ob->ctemplate->symtable;
256  hoc_objectdata = ob->u.dataspace;
257  } else {
260  }
261  hoc_ret();
262  pushx(0.);
263 }
264 
265 void hoc_object_pushed(void) {
266  Object* ob;
267  int i = chkarg(1, 0., (double) obj_stack_loc);
268  ob = obj_stack_[obj_stack_loc - i];
269  hoc_ret();
270  hoc_push_object(ob);
271 }
272 
273 void hoc_object_pop(void) {
274  Object* ob;
275  if (obj_stack_loc < 1) {
276  hoc_execerror("object context stack underflow", 0);
277  }
278  obj_stack_[obj_stack_loc] = nullptr;
279  ob = obj_stack_[--obj_stack_loc];
280  hoc_thisobject = ob;
281  if (ob) {
282  hoc_symlist = ob->ctemplate->symtable;
283  hoc_objectdata = ob->u.dataspace;
284  } else {
287  }
288  hoc_ret();
289  pushx(0.);
290 }
291 /*-----------------------------------------------*/
292 int hoc_resize_toplevel(int more) {
293  if (more > 0) {
294  icnttoplevel += more;
296  icnttoplevel * sizeof(Objectdata));
297  if (templatestackp == templatestack) {
299  }
300  }
301  return icnttoplevel;
302 }
303 
305  if (!hoc_objectdata) {
306  icntobjectdata = 0;
307  }
308  sp->u.oboff = icntobjectdata;
309  icntobjectdata += 2; /* data pointer and Arrayinfo */
311  icntobjectdata * sizeof(Objectdata));
313  if (sp->arayinfo) {
314  ++sp->arayinfo->refcount;
315  }
316  if (templatestackp == templatestack) {
319  }
320 }
321 
322 int hoc_obj_run(const char* cmd, Object* ob) {
323  int err;
324  Object* objsave;
325  Objectdata* obdsave;
326  Symlist* slsave;
327  int osloc;
328  objsave = hoc_thisobject;
329  obdsave = hoc_objectdata_save();
330  slsave = hoc_symlist;
331  osloc = obj_stack_loc;
332 
333  if (ob) {
334  if (ob->ctemplate->constructor) {
335  hoc_execerror("Can't execute in a built-in class context", 0);
336  }
337  hoc_thisobject = ob;
338  hoc_objectdata = ob->u.dataspace;
339  hoc_symlist = ob->ctemplate->symtable;
340  } else {
341  hoc_thisobject = 0;
344  }
345 
346  err = hoc_oc(cmd);
347 
348  hoc_thisobject = objsave;
350  hoc_symlist = slsave;
351  obj_stack_loc = osloc;
352 
353  return err;
354 }
355 
356 void hoc_exec_cmd(void) { /* execute string from top level or within an object context */
357  int err;
358  char* cmd;
359  char buf[256];
360  char* pbuf;
361  Object* ob = 0;
362  HocStr* hs = 0;
363  cmd = gargstr(1);
364  pbuf = buf;
365  if (strlen(cmd) > 256 - 10) {
366  hs = hocstr_create(strlen(cmd) + 10);
367  pbuf = hs->buf;
368  }
369  if (cmd[0] == '~') {
370  sprintf(pbuf, "%s\n", cmd + 1);
371  } else {
372  sprintf(pbuf, "{%s}\n", cmd);
373  }
374  if (ifarg(2)) {
375  ob = *hoc_objgetarg(2);
376  }
377  err = hoc_obj_run(pbuf, ob);
378  if (err) {
379  hoc_execerror("execute error:", cmd);
380  }
381  if (pbuf != buf) {
382  hocstr_delete(hs);
383  }
384  hoc_ret();
385  pushx((double) (err));
386 }
387 
388 /* call a function within the context of an object. Args must be on stack */
389 double hoc_call_objfunc(Symbol* s, int narg, Object* ob) {
390  double d; //, hoc_call_func();
391  Object* objsave;
392  Objectdata* obdsave;
393  Symlist* slsave;
394  objsave = hoc_thisobject;
395  obdsave = hoc_objectdata_save();
396  slsave = hoc_symlist;
397 
398  if (ob) {
399  hoc_thisobject = ob;
400  hoc_objectdata = ob->u.dataspace;
401  hoc_symlist = ob->ctemplate->symtable;
402  } else {
403  hoc_thisobject = 0;
406  }
407 
408  d = hoc_call_func(s, narg);
409 
410  hoc_thisobject = objsave;
412  hoc_symlist = slsave;
413 
414  return d;
415 }
416 
422  hoc_thisobject = nullptr;
423  obj_stack_loc = 0;
424  hoc_in_template = 0;
425 #if CABLE
426  connect_obsec_ = 0;
427 #endif
428 }
429 
430 extern "C" void oc_save_hoc_oop(Object** a1,
431  Objectdata** a2,
432  // a3 is missing, do not add it
433  int* a4,
434  Symlist** a5) {
435  *a1 = hoc_thisobject;
436  /* same style as hoc_objectdata_sav */
438  *a2 = (Objectdata*) 1;
439  } else {
440  *a2 = hoc_objectdata;
441  }
442  *a4 = obj_stack_loc;
443  *a5 = hoc_symlist;
444 }
445 
446 extern "C" void oc_restore_hoc_oop(Object** a1, Objectdata** a2, int* a4, Symlist** a5) {
447  hoc_thisobject = *a1;
448  if (*a2 == (Objectdata*) 1) {
450  } else {
451  hoc_objectdata = *a2;
452  }
453  obj_stack_loc = *a4;
454  hoc_symlist = *a5;
455 }
456 
457 Object* hoc_new_object(Symbol* symtemp, void* v) {
458  Object* ob;
459 #if PDEBUG
460  printf("new object from template %s created.\n", symtemp->name);
461 #endif
462  ob = (Object*) emalloc(sizeof(Object));
463  ob->recurse = 0;
464  ob->unref_recurse_cnt = 0;
465  ob->refcount = 1; /* so template notify will not delete */
466  ob->observers = nullptr;
467  ob->ctemplate = symtemp->u.ctemplate;
468  ob->aliases = nullptr;
469  ob->itm_me = hoc_l_lappendobj(ob->ctemplate->olist, ob);
470  ob->secelm_ = (hoc_Item*) 0;
471  ob->ctemplate->count++;
472  ob->index = ob->ctemplate->index++;
473  if (symtemp->subtype & (CPLUSOBJECT | JAVAOBJECT)) {
474  ob->u.this_pointer = v;
475  if (v) {
476  hoc_template_notify(ob, 1);
477  }
478  } else {
479  ob->u.dataspace = 0;
480  }
481  ob->refcount = 0;
482  return ob;
483 }
484 
485 void hoc_new_object_asgn(Object** obp, Symbol* st, void* v) {
486  hoc_dec_refcount(obp);
487  *obp = hoc_new_object(st, v);
488  hoc_obj_ref(*obp);
489 }
490 
491 Object** hoc_temp_objvar(Symbol* symtemp, void* v) {
492  return hoc_temp_objptr(hoc_new_object(symtemp, v));
493 }
494 
495 /** If hoc_newob1 fails after creating a new object, that object needs to be
496  unreffed. To handle the case of constructors themselves creating new objects
497  before the error or intervening recovery of error by a callee recovering from
498  execerror, the incomplete new object is put on a stack along with the
499  current longjump target, and removed from the stack when the object
500  is complete. There could be a problem if the destructor doesn't work
501  with a partially constructed object. In case of a execerror before newobj1
502  completion, all partially constructed objects with a longjump handle equal
503  to the current longjump handle are unreffed.
504 **/
505 
506 #define NEWOBJ1_ERR_SIZE 32 /* starts with this size, and doubles on overflow */
507 typedef struct {
509  void* oji;
510 } newobj1_err_t;
511 
512 extern void* nrn_get_oji();
513 extern void* nrn_get_hoc_jmp();
514 extern void (*oc_jump_target_)();
515 static int newobj1_err_index_; /* stack index */
516 static int newobj1_err_size_;
517 static newobj1_err_t* newobj1_err_; /* stack of newobj1_err_t */
518 
519 /** save partially constructed object and controlling longjump handle **/
520 static void push_newobj1_err(Object* ob) {
522  if (newobj1_err_size_ == 0) {
526  } else {
527  newobj1_err_size_ *= 2;
529  newobj1_err_size_ * sizeof(newobj1_err_t));
531  }
532  }
533 
535  ne->ob = ob;
537 }
538 
539 /** pop the now fully constructed object **/
543 }
544 
545 /** unref partially constructed objects controlled by current longjump handle **/
546 void hoc_newobj1_err() { /* called from hoc_execerror */
547  if (newobj1_err_index_ > 0) {
548  int i;
549  /* Note: for the case of pure hoc, there may not be an oc_jump_target_
550  in which case jmp will get set to the hoc.c controlling jmp_buf
551  */
552  void* oji = oc_jump_target_ ? nrn_get_oji() : nrn_get_hoc_jmp();
553  while (newobj1_err_index_ > 0) {
555  if (ne->oji == oji) {
556  hoc_obj_unref(ne->ob);
557  pop_newobj1_err();
558  } else {
559  break;
560  }
561  }
562  }
563 }
564 
566  Object* ob;
567  Objectdata* obd;
568  Symbol* s;
569  int i, total;
570 
571  ob = hoc_new_object(sym, nullptr);
572  ob->refcount = 1;
573  push_newobj1_err(ob); /* allow unref if execerror before return */
574  if (sym->subtype & (CPLUSOBJECT | JAVAOBJECT)) {
575  call_constructor(ob, sym, narg);
576  } else {
577  ob->u.dataspace = obd = (Objectdata*) ecalloc(ob->ctemplate->dataspace_size,
578  sizeof(Objectdata));
579  for (s = ob->ctemplate->symtable->first; s; s = s->next) {
580  if (s->cpublic != 2) {
581  switch (s->type) {
582  case VAR:
583  if ((obd[s->u.oboff + 1].arayinfo = s->arayinfo) != (Arrayinfo*) 0) {
584  ++s->arayinfo->refcount;
585  }
586  total = hoc_total_array_data(s, obd);
587  obd[s->u.oboff].pval = (double*) emalloc(total * sizeof(double));
588  for (i = 0; i < total; i++) {
589  (obd[s->u.oboff].pval)[i] = 0.;
590  }
591  break;
592  case STRING:
593  obd[s->u.oboff + 1].arayinfo = (Arrayinfo*) 0;
594  obd[s->u.oboff].ppstr = (char**) emalloc(sizeof(char*));
595  *obd[s->u.oboff].ppstr = (char*) emalloc(sizeof(char));
596  **(obd[s->u.oboff].ppstr) = '\0';
597  break;
598  case OBJECTVAR:
599  if ((obd[s->u.oboff + 1].arayinfo = s->arayinfo) != (Arrayinfo*) 0) {
600  ++s->arayinfo->refcount;
601  }
602  total = hoc_total_array_data(s, obd);
603  obd[s->u.oboff].pobj = (Object**) emalloc(total * sizeof(Object*));
604  for (i = 0; i < total; i++) {
605  (obd[s->u.oboff].pobj)[i] = (Object*) 0;
606  }
607  if (strcmp(s->name, "this") == 0) {
608  obd[s->u.oboff].pobj[0] = ob;
609  }
610  break;
611 #if CABLE
612  case SECTION:
613  if ((obd[s->u.oboff + 1].arayinfo = s->arayinfo) != (Arrayinfo*) 0) {
614  ++s->arayinfo->refcount;
615  }
616  total = hoc_total_array_data(s, obd);
617  obd[s->u.oboff].psecitm = (hoc_Item**) emalloc(total * sizeof(hoc_Item*));
618  new_sections(ob, s, obd[s->u.oboff].psecitm, total);
619  break;
620 #endif
621  }
622  }
623  }
624  if (ob->ctemplate->is_point_) {
626  }
627  if (ob->ctemplate->init) {
628  call_ob_proc(ob, ob->ctemplate->init, narg);
629  } else {
630  for (i = 0; i < narg; ++i) {
631  hoc_nopop();
632  }
633  }
634  }
635  hoc_template_notify(ob, 1);
636  pop_newobj1_err();
637  return ob;
638 }
639 
640 void hoc_newobj_arg(void) {
641  Object* ob;
642  Symbol* sym;
643  int narg;
644  sym = (pc++)->sym;
645  narg = (pc++)->i;
646  ob = hoc_newobj1(sym, narg);
647  --ob->refcount; /*not necessarily 0 since init may reference 'this' */
649 }
650 
651 void hoc_newobj_ret(void) {
652  hoc_newobj_arg();
653 }
654 
655 void hoc_newobj(void) { /* template at pc+1 */
656  Object *ob, **obp;
657  Objectdata* obd;
658  Symbol *sym, *s;
659  int i, total;
660  int narg;
661 
662  sym = (pc++)->sym;
663  narg = (pc++)->i;
664 #if USE_PYTHON
665  /* look inside stack because of limited number of temporary objects? */
666  /* whatever. we will keep the strategy */
667  if (hoc_inside_stacktype(narg) == OBJECTVAR) {
668 #endif
669  obp = hoc_look_inside_stack(narg, OBJECTVAR)->pobj;
670  ob = hoc_newobj1(sym, narg);
671  hoc_nopop(); /* the object pointer */
672  hoc_dec_refcount(obp);
673  *(obp) = ob;
674  hoc_pushobj(obp);
675 #if USE_PYTHON
676  } else { /* Assignment to OBJECTTMP not allowed */
678  hoc_execerror("Assignment to $o only allowed if caller arg was declared as objref", NULL);
679  }
680 #endif
681 }
682 
683 static void call_constructor(Object* ob, Symbol* sym, int narg) {
684  Inst* pcsav;
685  Symlist* slsav;
686  Objectdata* obdsav;
687  Object* obsav;
688 
689  slsav = hoc_symlist;
690  obdsav = hoc_objectdata_save();
691  obsav = hoc_thisobject;
692  pcsav = pc;
693 
694  push_frame(sym, narg);
695  ob->u.this_pointer = (ob->ctemplate->constructor)(ob);
696  pop_frame();
697 
698  pc = pcsav;
699  hoc_symlist = slsav;
701  hoc_thisobject = obsav;
702 }
703 
704 /* When certain methods of some Objects are called, the gui-redirect macros
705  need Object* instead of Object*->u.this_pointer. Not worth changing the
706  prototype of the call as it is used in so many places. So store the Object*
707  to be obtained if needed.
708 */
709 
712  return gui_redirect_obj_;
713 }
714 
715 void call_ob_proc(Object* ob, Symbol* sym, int narg) {
716  Inst *pcsav, callcode[4];
717  Symlist* slsav;
718  Objectdata* obdsav;
719  Object* obsav;
720 
721  slsav = hoc_symlist;
722  obdsav = hoc_objectdata_save();
723  obsav = hoc_thisobject;
724  pcsav = pc;
725 
726  if (ob->ctemplate->sym->subtype & CPLUSOBJECT) {
727  hoc_thisobject = ob;
728  gui_redirect_obj_ = ob;
729  push_frame(sym, narg);
730  hoc_thisobject = obsav;
731  if (sym->type == OBFUNCTION) {
732  Object** o;
733  o = (*(sym->u.u_proc->defn.pfo_vp))(ob->u.this_pointer);
734  if (*o) {
735  ++(*o)->refcount;
736  } /* in case unreffed below */
737  pop_frame();
738  if (*o) {
739  --(*o)->refcount;
740  }
741  hoc_pushobj(o);
742  } else if (sym->type == STRFUNCTION) {
743  char** s;
744  s = (char**) (*(sym->u.u_proc->defn.pfs_vp))(ob->u.this_pointer);
745  pop_frame();
746  hoc_pushstr(s);
747  } else {
748  double x;
749  x = (*(sym->u.u_proc->defn.pfd_vp))(ob->u.this_pointer);
750  pop_frame();
751  hoc_pushx(x);
752  }
753 #if CABLE
754  } else if (ob->ctemplate->is_point_ && special_pnt_call(ob, sym, narg)) {
755  ; /*empty since special_pnt_call did the work for get_loc, has_loc, and loc*/
756 #endif
757  } else {
758  callcode[0].pf = call;
759  callcode[1].sym = sym;
760  callcode[2].i = narg;
761  callcode[3].in = STOP;
762 
763  hoc_objectdata = ob->u.dataspace;
764  hoc_thisobject = ob;
765  hoc_symlist = ob->ctemplate->symtable;
766  execute(callcode);
767  if (sym->type == PROCEDURE) {
768  hoc_nopop();
769  }
770  }
771  if (hoc_errno_check()) {
772  char str[200];
773  sprintf(str, "%s.%s", hoc_object_name(ob), sym->name);
774  hoc_warning("errno set during call of", str);
775  }
776  pc = pcsav;
777  hoc_symlist = slsav;
779  hoc_thisobject = obsav;
780 }
781 
782 static void call_ob_iter(Object* ob, Symbol* sym, int narg) {
783  Symlist* slsav;
784  Objectdata* obdsav;
785  Object* obsav;
786  Object* stmtobj;
787  Inst *stmtbegin, *stmtend;
788 
789  slsav = hoc_symlist;
790  obdsav = hoc_objectdata_save();
791  obsav = hoc_thisobject;
792 
793  hoc_objectdata = ob->u.dataspace;
794  hoc_thisobject = ob;
795  hoc_symlist = ob->ctemplate->symtable;
796 
797  stmtobj = hoc_look_inside_stack(narg + 1, OBJECTTMP)->obj;
798  stmtbegin = pc + pc->i;
799  pc++;
800  stmtend = pc + pc->i;
801  hoc_iterator_object(sym, narg, stmtbegin, stmtend, stmtobj);
802 
803  /* the stack was popped by hoc_iterator_object
804  hoc_nopop();
805  */
806 
807  hoc_symlist = slsav;
809  hoc_thisobject = obsav;
810 }
811 
812 void hoc_objvardecl(void) { /* symbol at pc+1, number of indices at pc+2 */
813  Symbol* sym;
814  int nsub, size, i;
815  Object** pobj;
816 
817  sym = (pc++)->sym;
818 #if PDEBUG
819  printf("declareing %s as objectvar\n", sym->name);
820 #endif
821  if (sym->type == OBJECTVAR) {
822  int total, i;
823  total = hoc_total_array(sym);
824  for (i = 0; i < total; i++) {
825  hoc_dec_refcount((OPOBJ(sym)) + i);
826  }
827  free(hoc_objectdata[sym->u.oboff].pobj);
828  hoc_freearay(sym);
829  } else {
830  sym->type = OBJECTVAR;
832  }
833  nsub = (pc++)->i;
834  if (nsub) {
835  size = hoc_arayinfo_install(sym, nsub);
836  } else {
837  size = 1;
838  }
839  hoc_objectdata[sym->u.oboff].pobj = pobj = (Object**) emalloc(size * sizeof(Object*));
840  for (i = 0; i < size; i++) {
841  pobj[i] = (Object*) 0;
842  }
843 }
844 
845 void hoc_cmp_otype(void) { /* NUMBER, OBJECTVAR, or STRING must be the type */
846  int type;
847  type = (pc++)->i;
848 }
849 
850 void hoc_known_type(void) {
851  int type;
852  type = ((pc++)->i);
853 }
854 
855 void hoc_objectvar(void) { /* object variable symbol at pc+1. */
856  /* pointer to correct object left on stack */
857  Objectdata* odsav;
858  Object* obsav = 0;
859  Symlist* slsav;
860  Symbol* obs;
861  Object** obp;
862 #if PDEBUG
863  printf("code for hoc_objectvar()\n");
864 #endif
865  obs = (pc++)->sym;
866  if (obs->cpublic == 2) {
867  obs = obs->u.sym;
868  odsav = hoc_objectdata_save();
869  obsav = hoc_thisobject;
870  slsav = hoc_symlist;
872  hoc_thisobject = 0;
874  }
875  obp = OPOBJ(obs);
876  if (ISARRAY(obs)) {
877  hoc_pushobj(obp + araypt(obs, OBJECTVAR));
878  } else {
879  hoc_pushobj(obp);
880  }
881  if (obsav) {
883  hoc_thisobject = obsav;
884  hoc_symlist = slsav;
885  }
886 }
887 
888 void hoc_objectarg(void) { /* object arg index at pc+1. */
889  /* pointer to correct object left on stack */
890  int i;
891  Object** obp;
892 #if PDEBUG
893  printf("code for hoc_objectarg()\n");
894 #endif
895  i = (pc++)->i;
896  if (i == 0) {
897  i = hoc_argindex();
898  }
899  obp = hoc_objgetarg(i);
900  hoc_pushobj(obp);
901 }
902 
903 void hoc_constobject(void) { /* template at pc, index at pc+1, objpointer left on stack*/
904  char buf[200];
905  Object* obj;
906  hoc_Item* q;
907  cTemplate* t = (pc++)->sym->u.ctemplate;
908  int index = (int) hoc_xpop();
909  ITERATE(q, t->olist) {
910  obj = OBJ(q);
911  if (obj->index == index) {
913  return;
914  } else if (obj->index > index) {
915  break;
916  }
917  }
918  sprintf(buf, "%s[%d]\n", t->sym->name, index);
919  hoc_execerror("Object ID doesn't exist:", buf);
920 }
921 
922 Object* hoc_name2obj(const char* name, int index) {
923  char buf[200];
924  Object* obj;
925  hoc_Item* q;
926  cTemplate* t;
927  Symbol* sym;
929  if (!sym) {
931  }
932  if (!sym || sym->type != TEMPLATE) {
933  hoc_execerror(name, "is not a template");
934  }
935  t = sym->u.ctemplate;
936  ITERATE(q, t->olist) {
937  obj = OBJ(q);
938  if (obj->index == index) {
939  return obj;
940  } else if (obj->index > index) {
941  break;
942  }
943  }
944  return nullptr;
945 }
946 
947 void hoc_object_id(void) {
948  Object* ob;
949 
950  ob = *(hoc_objgetarg(1));
951  if (ifarg(2) && chkarg(2, 0., 1.) == 1.) {
952  hoc_ret();
953  if (ob) {
954  pushx((double) ob->index);
955  } else {
956  pushx(-1.);
957  }
958  } else {
959  hoc_ret();
960  pushx((double) ((size_t) ob));
961  }
962 }
963 
964 #if CABLE
965 static void range_suffix(Symbol* sym, int nindex, int narg) {
966  int bdim = 0;
967  if (ISARRAY(sym)) {
968  if (nindex != sym->arayinfo->nsub) {
969  bdim = 1;
970  }
971  } else {
972  if (nindex != 0) {
973  bdim = 1;
974  }
975  }
976  if (bdim) {
977  hoc_execerror(sym->name, "wrong number of array dimensions");
978  }
979 
980  if (sym->type == RANGEVAR) {
981  hoc_pushi(narg);
982  hoc_pushs(sym);
983  } else if (sym->subtype == USERPROPERTY) {
984  if (narg) {
985  hoc_execerror(sym->name, "section property can't have argument");
986  }
987  hoc_pushs(sym);
988  } else {
989  hoc_execerror(sym->name, "suffix not a range variable or section property");
990  }
991 }
992 
993 void connect_obsec_syntax(void) {
994  connect_obsec_ = 1;
995 }
996 
997 #endif
998 
999 void hoc_object_component(void) { /* number of indices at pc+2, number of args at pc+3,
1000  symbol at pc+1 */
1001  /* object pointer on stack after indices */
1002  /* if component turns out to be an object then make sure pointer
1003  to correct object, symbol, etc is left on stack for evaluation,
1004  assignment, etc. */
1005  Symbol *sym0, *sym = 0;
1006  int nindex, narg, cplus, isfunc;
1007  Object *obp, *obsav;
1008  Objectdata* psav;
1009  int* ptid;
1010  Symbol** psym;
1011 
1012 #if PDEBUG
1013  printf("code for hoc_object_component()\n");
1014 #endif
1015  sym0 = (pc++)->sym;
1016  nindex = (pc++)->i;
1017  narg = (pc++)->i;
1018  ptid = &(pc++)->i;
1019  psym = &(pc++)->sym;
1020  isfunc = (pc++)->i;
1021 
1022 #if CABLE
1023  if (section_object_seen) {
1024  section_object_seen = 0;
1025  range_suffix(sym0, nindex, narg);
1026  return;
1027  }
1028  if (connect_obsec_) {
1029  narg += nindex;
1030  nindex = 0;
1031  }
1032 #endif
1033  if (nindex) {
1034  if (narg) {
1035  hoc_execerror("[...](...) syntax only allowed for array range variables:", sym0->name);
1036  }
1037  } else {
1038  nindex = narg;
1039  }
1040 
1041  obp = hoc_obj_look_inside_stack(nindex);
1042  if (obp) {
1043 #if USE_PYTHON
1044  if (obp->ctemplate->sym == nrnpy_pyobj_sym_) {
1045  if (isfunc & 2) {
1046  /* this is the final left hand side of an
1047  assignment to the method of a PythonObject
1048  and we need to put the PythonObject and the
1049  method with all its info onto the stack so that
1050  a proper __setattro__ or __setitem__ can be
1051  accomplished in the next hoc_object_asgn
1052  */
1053  if (isfunc & 1) {
1054  hoc_execerror("Cannot assign to a PythonObject function call:", sym0->name);
1055  }
1056  pushi(nindex);
1057  pushs(sym0);
1058  hoc_push_object(obp);
1059  /* note obp is now on stack twice */
1060  /* hpoasgn will pop both */
1061  } else {
1062  (*nrnpy_py2n_component)(obp, sym0, nindex, isfunc);
1063  }
1064  return;
1065  }
1066 #endif
1067  if (obp->ctemplate->id == *ptid) {
1068  sym = *psym;
1069  } else {
1070  if (obp->aliases == 0 || (sym = ivoc_alias_lookup(sym0->name, obp)) == 0) {
1071  /* lookup only has to be done once if the name is not an alias
1072  and the ptid of the object is still the same. */
1073  sym = hoc_table_lookup(sym0->name, obp->ctemplate->symtable);
1074  if (!sym || sym->cpublic != PUBLIC_TYPE) {
1075  fprintf(stderr,
1076  "%s not a public member of %s\n",
1077  sym0->name,
1078  obp->ctemplate->sym->name);
1079  hoc_execerror(obp->ctemplate->sym->name, sym0->name);
1080  }
1081  *ptid = obp->ctemplate->id;
1082  *psym = sym;
1083  }
1084  }
1085  } else {
1086  hoc_execerror(sym0->name, ": object prefix is NULL");
1087  }
1088 
1089  psav = hoc_objectdata_save();
1090  obsav = hoc_thisobject;
1091  cplus = (obp->ctemplate->sym->subtype & (CPLUSOBJECT | JAVAOBJECT));
1092  if (!cplus) { /* c++ classes don't have a hoc dataspace */
1093  hoc_objectdata = obp->u.dataspace;
1094  hoc_thisobject = obp;
1095  }
1096  switch (sym->type) {
1097  case OBJECTVAR:
1098  if (nindex) {
1099  if (!ISARRAY(sym) || OPARINFO(sym)->nsub != nindex) {
1100  hoc_execerror(sym->name, ":not right number of subscripts");
1101  }
1102  nindex = araypt(sym, OBJECTVAR);
1103  }
1104  hoc_pop_defer();
1105  hoc_pushobj(OPOBJ(sym) + nindex);
1106  break;
1107  case VAR:
1108  if (cplus) {
1109  double* pd;
1110  if (nindex) {
1111  if (!ISARRAY(sym) || sym->arayinfo->nsub != nindex) {
1112  hoc_execerror(sym->name, ":not right number of subscripts");
1113  }
1114  }
1115  hoc_pushs(sym);
1116  (*obp->ctemplate->steer)(obp->u.this_pointer);
1117  pd = hoc_pxpop();
1118  /* cannot pop a temporary object til after the pd is used in
1119  case (e.g. Vector.x) the pointer is a field in the object
1120  (often the pd has nothing to do with the object)*/
1121  hoc_pop_defer(); /* corresponding unref_defer soon */
1122  hoc_pushpx(pd);
1123  } else {
1124  if (nindex) {
1125  if (!ISARRAY(sym) || OPARINFO(sym)->nsub != nindex) {
1126  hoc_execerror(sym->name, ":not right number of subscripts");
1127  }
1128  nindex = araypt(sym, OBJECTVAR);
1129  }
1130  hoc_pop_defer(); /*finally get rid of symbol */
1131  hoc_pushpx(OPVAL(sym) + nindex);
1132  }
1133  break;
1134  case STRING:
1135  if (nindex) {
1136  hoc_execerror(sym->name, ": string can't have function arguments or array indices");
1137  }
1138  hoc_pop_defer();
1139  hoc_pushstr(OPSTR(sym));
1140  break;
1141  case PROCEDURE:
1142  case FUNCTION: {
1143  double d = 0.;
1144  call_ob_proc(obp, sym, nindex);
1145  if (hoc_returning) {
1146  break;
1147  }
1148  if (sym->type == FUNCTION) {
1149  d = hoc_xpop();
1150  }
1151  hoc_pop_defer();
1152  hoc_pushx(d);
1153  break;
1154  }
1155  case HOCOBJFUNCTION:
1156  case OBFUNCTION: {
1157  Object** d;
1158  call_ob_proc(obp, sym, nindex);
1159  if (hoc_returning) {
1160  break;
1161  }
1162  d = hoc_objpop();
1163  if (*d) {
1164  (*d)->refcount++;
1165  } /* nopop may unref if temp obj.*/
1166  hoc_pop_defer();
1167  hoc_pushobj(d);
1168  if (*d) {
1169  (*d)->refcount--;
1170  } /* see the nopop may unref comment */
1171  hoc_tobj_unref(d);
1172  break;
1173  }
1174  case STRFUNCTION: {
1175  char** d;
1176  call_ob_proc(obp, sym, nindex);
1177  if (hoc_returning) {
1178  break;
1179  }
1180  d = hoc_strpop();
1181  hoc_pop_defer();
1182  hoc_pushstr(d);
1183  break;
1184  }
1185 #if CABLE
1186  case SECTIONREF: {
1187  extern Symbol* nrn_sec_sym;
1188  Section* sec;
1189  extern Section* nrn_sectionref_steer(Section * sec, Symbol * sym, int* pnindex);
1190  section_object_seen = 1;
1191  sec = (Section*) obp->u.this_pointer;
1192  if (sym != nrn_sec_sym) {
1193  sec = nrn_sectionref_steer(sec, sym, &nindex);
1194  }
1195  if (nrn_inpython_ == 2) {
1196  section_object_seen = 0;
1197  hoc_pop_defer();
1199  hoc_thisobject = obsav;
1200  return;
1201  }
1202  if (connect_obsec_) {
1203  double x = 0.0;
1204  connect_obsec_ = 0;
1205  if (nindex != 1) {
1206  hoc_execerror(sym->name, ": bad connect syntax");
1207  }
1208  x = hoc_xpop();
1209  hoc_pop_defer();
1210  hoc_pushx(x);
1211  } else {
1212  if (nindex) {
1213  hoc_execerror(sym->name, ":no subscript allowed");
1214  }
1215  hoc_pop_defer();
1216  }
1217  if (!sec->prop) {
1218  hoc_execerror("Section was deleted", (char*) 0);
1219  }
1220  nrn_pushsec(sec);
1221  break;
1222  }
1223  case SECTION: {
1224  double x = 0.0;
1225  section_object_seen = 1;
1226  if (connect_obsec_) {
1227  x = hoc_xpop();
1228  if (!nindex) {
1229  hoc_execerror(sym->name, ": bad connect syntax");
1230  }
1231  --nindex;
1232  }
1233  if (nindex) {
1234  if (!ISARRAY(sym) || OPARINFO(sym)->nsub != nindex) {
1235  hoc_execerror(sym->name, ":not right number of subscripts");
1236  }
1237  nindex = araypt(sym, OBJECTVAR);
1238  }
1239  hoc_pop_defer();
1240  if (connect_obsec_) {
1241  hoc_pushx(x);
1242  connect_obsec_ = 0;
1243  }
1244  ob_sec_access_push(*(OPSECITM(sym) + nindex));
1245  break;
1246  }
1247 #endif /*CABLE*/
1248  case ITERATOR: {
1249  if ((pc++)->i != ITERATOR) {
1250  hoc_execerror(sym->name, ":ITERATOR can only be used in a for statement");
1251  }
1252  call_ob_iter(obp, sym, nindex);
1253  if (hoc_returning) {
1254  break;
1255  }
1256  hoc_pop_defer();
1257  hoc_nopop(); /* get rid of iterator statement context */
1258  break;
1259  }
1260  default:
1261  if (cplus) {
1262  double* pd;
1263  if (nindex) {
1264  if (!ISARRAY(sym) || sym->arayinfo->nsub != nindex) {
1265  hoc_execerror(sym->name, ":not right number of subscripts");
1266  }
1267  }
1268  hoc_pushs(sym);
1269  (*obp->ctemplate->steer)(obp->u.this_pointer);
1270  pd = hoc_pxpop();
1271  hoc_pop_defer();
1272  hoc_pushpx(pd);
1273  } else {
1274  hoc_execerror(sym->name, ": can't push that type onto stack");
1275  }
1276  break;
1277  case OBJECTALIAS:
1278  if (nindex) {
1279  hoc_execerror(sym->name, ": is an alias and cannot have subscripts");
1280  }
1281  hoc_pop_defer();
1282  hoc_push_object(sym->u.object_);
1283  break;
1284  case VARALIAS:
1285  if (nindex) {
1286  hoc_execerror(sym->name, ": is an alias and cannot have subscripts");
1287  }
1288  hoc_pop_defer();
1289  hoc_pushpx(sym->u.pval);
1290  break;
1291  }
1293  hoc_thisobject = obsav;
1294 }
1295 
1296 void hoc_object_eval(void) {
1297  int type;
1298 #if PDEBUG
1299  printf("code for hoc_object_eval\n");
1300 #endif
1301  type = hoc_stacktype();
1302  if (type == VAR) {
1303  hoc_pushx(*(hoc_pxpop()));
1304  } else if (type == SYMBOL) {
1305 #if CABLE
1307  if (d->sym->type == RANGEVAR) {
1308  Symbol* sym = hoc_spop();
1309  int narg = hoc_ipop();
1310  struct Section* sec = nrn_sec_pop();
1311  double x;
1312  if (narg) {
1313  x = hoc_xpop();
1314  } else {
1315  x = .5;
1316  }
1317  hoc_pushx(*(nrn_rangepointer(sec, sym, x)));
1318  } else if (d->sym->type == VAR && d->sym->subtype == USERPROPERTY) {
1319  extern double cable_prop_eval(Symbol*);
1321  }
1322 #endif
1323  }
1324 }
1325 
1326 void hoc_ob_pointer(void) {
1327  int type;
1328  Symbol* sym;
1329 #if PDEBUG
1330  printf("code for hoc_ob_pointer\n");
1331 #endif
1332  type = hoc_stacktype();
1333  if (type == VAR) {
1334  } else if (type == SYMBOL) {
1335 #if CABLE
1337  if (d->sym->type == RANGEVAR) {
1338  Symbol* sym = hoc_spop();
1339  int nindex = hoc_ipop();
1340  struct Section* sec = nrn_sec_pop();
1341  double x;
1342  if (nindex) {
1343  x = hoc_xpop();
1344  } else {
1345  x = .5;
1346  }
1347  hoc_pushpx(nrn_rangepointer(sec, sym, x));
1348  } else if (d->sym->type == VAR && d->sym->subtype == USERPROPERTY) {
1350  } else {
1351  hoc_execerror("Not a double pointer", 0);
1352  }
1353 
1354 #else
1355  hoc_execerror("Not a double pointer", 0);
1356 #endif
1357  } else {
1358  hoc_execerror("Not a double pointer", 0);
1359  }
1360 }
1361 
1362 void hoc_asgn_obj_to_str(void) { /* string on stack */
1363  char *d, **pstr;
1364  d = *(hoc_strpop());
1365  pstr = hoc_strpop();
1366  hoc_assign_str(pstr, d);
1367 }
1368 
1369 void hoc_object_asgn(void) {
1370  int type1, type2, op;
1371  op = (pc++)->i;
1372  type1 = hoc_stacktype();
1373  type2 = hoc_inside_stacktype(1);
1374 #if CABLE
1375  if (type2 == SYMBOL) {
1377  if (d->sym->type == RANGEVAR) {
1378  type2 = RANGEVAR;
1379  } else if (d->sym->type == VAR && d->sym->subtype == USERPROPERTY) {
1380  type2 = USERPROPERTY;
1381  }
1382  }
1383  if (type2 == RANGEVAR && type1 == NUMBER) {
1384  double d = hoc_xpop();
1385  struct Section* sec;
1386  Symbol* sym = hoc_spop();
1387  int nindex = hoc_ipop();
1388  sec = nrn_sec_pop();
1389  if (nindex) {
1390  double* pd;
1391  pd = nrn_rangepointer(sec, sym, hoc_xpop());
1392  if (op) {
1393  d = hoc_opasgn(op, *pd, d);
1394  }
1395  *pd = d;
1396  } else {
1397  nrn_rangeconst(sec, sym, &d, op);
1398  }
1399  hoc_pushx(d);
1400  return;
1401  } else if (type2 == USERPROPERTY && type1 == NUMBER) {
1402  double d = hoc_xpop();
1403  cable_prop_assign(hoc_spop(), &d, op);
1404  hoc_pushx(d);
1405  return;
1406  }
1407 #endif
1408  switch (type2) {
1409  case VAR: {
1410  double d, *pd;
1411  d = hoc_xpop();
1412  pd = hoc_pxpop();
1413  if (op) {
1414  d = hoc_opasgn(op, *pd, d);
1415  }
1416  *pd = d;
1417  hoc_pushx(d);
1418  } break;
1419  case OBJECTVAR: {
1420  Object **d, **pd;
1421  if (op) {
1422  hoc_execerror("Invalid assignment operator for object", (char*) 0);
1423  }
1424  d = hoc_objpop();
1425  pd = hoc_objpop();
1426  if (d != pd) {
1427  Object* tobj = *d;
1428  if (tobj) {
1429  (tobj)->refcount++;
1430  }
1431  hoc_tobj_unref(d);
1432  hoc_dec_refcount(pd);
1433  *pd = tobj;
1434  }
1435  hoc_pushobj(pd);
1436  } break;
1437  case STRING: {
1438  char *d, **pd;
1439  if (op) {
1440  hoc_execerror("Invalid assignment operator for string", (char*) 0);
1441  }
1442  d = *(hoc_strpop());
1443  pd = hoc_strpop();
1444  hoc_assign_str(pd, d);
1445  hoc_pushstr(pd);
1446  } break;
1447 #if USE_PYTHON
1448  case OBJECTTMP: { /* should be PythonObject */
1449  Object* o;
1450  int stkindex = hoc_obj_look_inside_stack_index(1);
1452  assert(o->ctemplate->sym == nrnpy_pyobj_sym_);
1453  if (op) {
1454  hoc_execerror("Invalid assignment operator for PythonObject", (char*) 0);
1455  }
1456  (*nrnpy_hpoasgn)(o, type1);
1457  hoc_stkobj_unref(o, stkindex);
1458  } break;
1459 #endif
1460  default:
1461  hoc_execerror("Cannot assign to left hand side", (char*) 0);
1462  }
1463 }
1464 
1465 /* if the name isn't a template then look in the top level symbol table.
1466 This allows objects to create objects of any class defined at the top level
1467 */
1469  if (s->type != TEMPLATE) {
1470  Symbol* s1;
1472  if (!s1 || s1->type != TEMPLATE) {
1473  hoc_execerror(s->name, "is not a template");
1474  }
1475  s = s1;
1476  }
1477  return s;
1478 }
1479 
1480 /* pushes old symtable and template name on template stack.
1481 And creates new symtable. The new symtable
1482 is used for all non-builtin names until an endtemplate is reached
1483 */
1484 static int template_id;
1485 
1487  Symbol* t;
1488  int type;
1489  t = hoc_decl(t1);
1490 
1491 #if PDEBUG
1492  printf("begin template %s\n", t->name);
1493 #endif
1494  type = t->type;
1495  if (type == TEMPLATE) {
1496  hoc_execerror(t->name, ": a template cannot be redefined");
1497  extern void hoc_free_symspace(Symbol*);
1499  } else if (type != UNDEF) {
1500  hoc_execerror(t->name, "already used as something besides template");
1501  }
1502  t->u.ctemplate = (cTemplate*) emalloc(sizeof(cTemplate));
1503  t->type = TEMPLATE;
1504  t->u.ctemplate->sym = t;
1505  t->u.ctemplate->symtable = (Symlist*) 0;
1506  t->u.ctemplate->dataspace_size = 0;
1507  t->u.ctemplate->constructor = 0;
1508  t->u.ctemplate->destructor = 0;
1509  t->u.ctemplate->is_point_ = 0;
1510  t->u.ctemplate->steer = 0;
1511  t->u.ctemplate->checkpoint = 0;
1512  t->u.ctemplate->id = ++template_id;
1518  pushtemplatesym(t);
1519  hoc_in_template = 1;
1520  hoc_objectdata = (Objectdata*) 0;
1521  hoc_thisobject = nullptr;
1522  hoc_symlist = t->u.ctemplate->symtable;
1523 }
1524 
1526  Symbol *ts, *s;
1527 #if PDEBUG
1528  printf("end template %s\n", t->name);
1529 #endif
1530  ts = (poptemplate())->sym;
1531  if (strcmp(ts->name, t->name) != 0) {
1532  hoc_execerror(t->name, "- end template mismatched with begin");
1533  }
1536  ts->u.ctemplate->count = 0;
1537  ts->u.ctemplate->index = 0;
1538  ts->u.ctemplate->olist = hoc_l_newlist();
1539  ts->u.ctemplate->observers = nullptr;
1542  hoc_thisobject = (poptemplate())->o;
1543  hoc_in_template = (poptemplate())->i;
1544  hoc_objectdata = (poptemplate())->odata;
1545  icntobjectdata = (poptemplate())->i;
1546  ts->u.ctemplate->init = s = hoc_table_lookup("init", ts->u.ctemplate->symtable);
1547  if (s && s->type != PROCEDURE) {
1548  hoc_execerror("'init' can only be used as the initialization procedure for new objects",
1549  nullptr);
1550  }
1551  ts->u.ctemplate->unref = s = hoc_table_lookup("unref", ts->u.ctemplate->symtable);
1552  if (s && s->type != PROCEDURE) {
1553  hoc_execerror(
1554  "'unref' can only be used as the callback procedure when the reference count is "
1555  "decremented",
1556  nullptr);
1557  }
1558 }
1559 
1560 void class2oc(const char* name,
1561  void* (*cons)(Object*),
1562  void (*destruct)(void*),
1563  Member_func* m,
1564  int (*checkpoint)(void**),
1565  Member_ret_obj_func* mobjret,
1566  Member_ret_str_func* strret) {
1567  extern int hoc_main1_inited_;
1568  Symbol *tsym, *s;
1569  cTemplate* t;
1570  int i;
1571 
1572  if (hoc_lookup(name)) {
1573  hoc_execerror(name, "already being used as a name");
1574  }
1575  tsym = hoc_install(name, UNDEF, 0.0, &hoc_symlist);
1576  tsym->subtype = CPLUSOBJECT;
1577  hoc_begintemplate(tsym);
1578  t = tsym->u.ctemplate;
1581  }
1582  t->constructor = cons;
1583  t->destructor = destruct;
1584  t->steer = 0;
1585  t->checkpoint = checkpoint;
1586  if (m)
1587  for (i = 0; m[i].name; ++i) {
1588  s = hoc_install(m[i].name, FUNCTION, 0.0, &hoc_symlist);
1589  s->u.u_proc->defn.pfd_vp = m[i].member;
1590  hoc_add_publiclist(s);
1591  }
1592  if (mobjret)
1593  for (i = 0; mobjret[i].name; ++i) {
1594  s = hoc_install(mobjret[i].name, OBFUNCTION, 0.0, &hoc_symlist);
1595  s->u.u_proc->defn.pfo_vp = mobjret[i].member;
1596  hoc_add_publiclist(s);
1597  }
1598  if (strret)
1599  for (i = 0; strret[i].name; ++i) {
1600  s = hoc_install(strret[i].name, STRFUNCTION, 0.0, &hoc_symlist);
1601  s->u.u_proc->defn.pfs_vp = strret[i].member;
1602  hoc_add_publiclist(s);
1603  }
1604  hoc_endtemplate(tsym);
1605 }
1606 
1607 
1609  Symbol* ss;
1610  if (templatestackp == templatestack) {
1611  if (s == hoc_table_lookup(s->name, hoc_built_in_symlist)) {
1612  hoc_execerror(s->name, ": Redeclaring at top level");
1613  }
1614  return s;
1615  }
1616  ss = hoc_table_lookup(s->name, hoc_symlist);
1617  if (!ss) {
1618  ss = hoc_install(s->name, UNDEF, 0.0, &hoc_symlist);
1619  }
1620  return ss;
1621 }
1622 
1624  Symbol* ss;
1625 #if PDEBUG
1626  printf("public name %s with type %d\n", s->name, s->type);
1627 #endif
1628  if (templatestackp == templatestack) {
1629  hoc_execerror("Not in a template\n", 0);
1630  }
1631  ss = hoc_decl(s);
1632  ss->cpublic = PUBLIC_TYPE;
1633 }
1634 
1636  Symbol* s0;
1637  if (templatestackp == templatestack) {
1638  hoc_execerror("Not in a template\n", 0);
1639  }
1640  if (s->cpublic == PUBLIC_TYPE) {
1641  hoc_execerror(s->name, "can't be public and external");
1642  }
1643  s->cpublic = EXTERNAL_TYPE;
1645  if (!s0) {
1646  hoc_execerror(s->name, "not declared at the top level");
1647  }
1648  s->type = s0->type;
1649  s->subtype = s0->subtype;
1650  switch (s->type) {
1651  case FUNCTION:
1652  case PROCEDURE:
1653  case ITERATOR:
1654  case HOCOBJFUNCTION:
1655  s->u.u_proc = s0->u.u_proc;
1656  break;
1657  case TEMPLATE:
1658  s->u.ctemplate = s0->u.ctemplate;
1659  break;
1660  case STRING:
1661  case OBJECTVAR:
1662  case VAR:
1663  case SECTION:
1664  s->arayinfo = s0->arayinfo;
1665  s->u.sym = s0;
1666  break;
1667  default:
1668  hoc_execerror(s->name, "type is not allowed external");
1669  break;
1670  }
1671 }
1672 
1673 void hoc_ob_check(int type) {
1674  int t;
1675  t = ipop();
1676  if (type == -1) {
1677  if (t == OBJECTVAR) { /* don't bother to check */
1679  codei(0);
1680  }
1681  } else if (type) {
1682  if (t == OBJECTVAR) { /* must check dynamically */
1683 #if PDEBUG
1684  printf("dymnamic checking of type=%d\n", type);
1685 #endif
1687  codei(type);
1688  } else if (type != t) { /* static check */
1689  hoc_execerror("Type mismatch", (char*) 0);
1690  }
1691  } else {
1692  if (t != OBJECTVAR) {
1694  codei(t);
1695  }
1696  }
1697 }
1698 
1700  /* look in all object variables that point to
1701  objects with this template and null them */
1702  Symbol* s;
1703  int total, i;
1704  Object** obp;
1705 
1706  if (sl)
1707  for (s = sl->first; s; s = s->next) {
1708  if (s->type == OBJECTVAR && s->cpublic != 2) {
1709  total = hoc_total_array_data(s, data);
1710  for (i = 0; i < total; i++) {
1711  obp = data[s->u.oboff].pobj + i;
1712  if (*obp) {
1713 #if 1
1714  if ((*obp)->ctemplate == ctemplate) {
1715  hoc_dec_refcount(obp);
1716  } else if (s->subtype != CPLUSOBJECT) {
1717  /* descend to look for more */
1718  hoc_free_allobjects(ctemplate,
1719  (*obp)->ctemplate->symtable,
1720  (*obp)->u.dataspace);
1721  }
1722 #else
1723  if (s->subtype != CPLUSOBJECT) {
1724  /* descend to look for more */
1725  hoc_free_allobjects(ctemplate,
1726  (*obp)->ctemplate->symtable,
1727  (*obp)->u.dataspace);
1728  }
1729  if ((*obp)->ctemplate == ctemplate) {
1730  hoc_dec_refcount(obp);
1731  }
1732 #endif
1733  }
1734  }
1735  }
1736  }
1737 }
1738 
1739 #define objectpath hoc_objectpath_impl
1740 #define pathprepend hoc_path_prepend
1741 
1742 void pathprepend(char* path, const char* name, const char* indx) {
1743  char buf[200];
1744  if (path[0]) {
1745  strcpy(buf, path);
1746  sprintf(path, "%s%s.%s", name, indx, buf);
1747  } else {
1748  sprintf(path, "%s%s", name, indx);
1749  }
1750 }
1751 
1752 int objectpath(Object* ob, Object* oblook, char* path, int depth) {
1753  /* recursively build the pathname to the object */
1754  Symbol* s;
1755  Symlist* sl;
1756  int total, i;
1757  Objectdata* od;
1758  Object** obp;
1759 
1760  if (ob == oblook) {
1761  return 1;
1762  }
1763  if (oblook) {
1764  if (depth++ > 5) {
1765  hoc_warning("objectpath depth > 4 for", oblook->ctemplate->sym->name);
1766  return 0;
1767  }
1768  if (oblook->ctemplate->constructor) {
1769  return ivoc_list_look(ob, oblook, path, depth);
1770  } else {
1771  od = oblook->u.dataspace;
1772  sl = oblook->ctemplate->symtable;
1773  }
1774  } else {
1775  od = hoc_top_level_data;
1777  }
1778  if (sl)
1779  for (s = sl->first; s; s = s->next) {
1780  if (s->type == OBJECTVAR && s->cpublic != 2) {
1781  total = hoc_total_array_data(s, od);
1782  for (i = 0; i < total; i++) {
1783  obp = od[s->u.oboff].pobj + i;
1784  if (*obp && *obp != oblook && objectpath(ob, *obp, path, depth)) {
1785  pathprepend(path, s->name, hoc_araystr(s, i, od));
1786  return 1;
1787  }
1788  }
1789  }
1790  }
1791  return 0;
1792 }
1793 
1795  static char path[512];
1796  path[0] = '\0';
1797  if (objectpath(ob, nullptr, path, 0)) {
1798  return path;
1799  } else {
1800 #if 0
1801  hoc_warning("Couldn't find a pathname to the object pointer",
1802  ob->ctemplate->sym->name);
1803  return (char*)0;
1804 #else
1805  return hoc_object_name(ob);
1806 #endif
1807  }
1808 }
1809 
1810 void hoc_obj_ref(Object* obj) {
1811  if (obj) {
1812  ++obj->refcount;
1813  }
1814 }
1815 
1816 void hoc_dec_refcount(Object** pobj) {
1817  Object* obj;
1818 
1819  obj = *pobj;
1820  if (obj == (Object*) 0) {
1821  return;
1822  }
1823  *pobj = (Object*) 0;
1824  assert(obj->refcount > 0);
1825  hoc_obj_unref(obj);
1826 }
1827 
1828 void hoc_obj_unref(Object* obj) {
1829  Object* obsav;
1830 
1831  if (!obj) {
1832  return;
1833  }
1834 #if 0
1835 printf("unreffing %s with refcount %d\n", hoc_object_name(obj), obj->refcount);
1836 #endif
1837  --obj->refcount;
1838  if (obj->ctemplate->unref) {
1839  int i = obj->refcount;
1840  pushx((double) i);
1841  ++obj->unref_recurse_cnt;
1842  call_ob_proc(obj, obj->ctemplate->unref, 1);
1843  --obj->unref_recurse_cnt;
1844  }
1845  if (obj->refcount <= 0 && obj->unref_recurse_cnt == 0) {
1846  if (obj->aliases) {
1847  ivoc_free_alias(obj);
1848  }
1849  if (obj->observers) {
1850  hoc_obj_disconnect(obj);
1851  }
1852  hoc_l_delete(obj->itm_me);
1853  if (obj->ctemplate->observers) {
1854  hoc_template_notify(obj, 0);
1855  }
1856  if (obj->ctemplate->sym->subtype & (CPLUSOBJECT | JAVAOBJECT)) {
1857  (obj->ctemplate->destructor)(obj->u.this_pointer);
1858  } else {
1859  obsav = hoc_thisobject;
1860  hoc_thisobject = obj;
1861  free_objectdata(obj->u.dataspace, obj->ctemplate);
1862  obj->u.dataspace = (Objectdata*) 0;
1863  hoc_thisobject = obsav;
1864  }
1865  if (--obj->ctemplate->count <= 0) {
1866  obj->ctemplate->index = 0;
1867  }
1868  obj->ctemplate = nullptr;
1869  /* for testing purposes we don't free the object in order
1870  to make sure no object variable ever uses a freed object */
1871 #if 1
1872  hoc_free_object(obj);
1873 #endif
1874  }
1875 }
1876 
1877 static void free_objectdata(Objectdata* od, cTemplate* ctemplate) {
1878  Symbol* s;
1879  int i, total;
1880  Objectdata* psav;
1881  Object** objp;
1882 
1883  psav = hoc_objectdata;
1884  hoc_objectdata = od;
1885  if (ctemplate->symtable)
1886  for (s = ctemplate->symtable->first; s; s = s->next) {
1887  if (s->cpublic != 2) {
1888  switch (s->type) {
1889  case VAR:
1890  /*printf("free_objectdata %s\n", s->name);*/
1893  break;
1894  case STRING:
1895  hoc_free_pstring(OPSTR(s));
1897  break;
1898  case OBJECTVAR:
1899  objp = OPOBJ(s);
1900  if (strcmp("this", s->name) != 0) {
1901  total = hoc_total_array(s);
1902  for (i = 0; i < total; i++) {
1903  hoc_dec_refcount(objp + i);
1904  }
1905  }
1907  free(objp);
1908  break;
1909 #if CABLE
1910  case SECTION:
1911  total = hoc_total_array(s);
1912  for (i = 0; i < total; ++i) {
1913  sec_free(*(OPSECITM(s) + i));
1914  }
1915  free(OPSECITM(s));
1917  break;
1918 #endif
1919  }
1920  }
1921  }
1922 #if CABLE
1923  if (ctemplate->is_point_) {
1924  void* v = od[ctemplate->dataspace_size - 1]._pvoid;
1925  if (v) {
1926  /* printf("Free point process\n");*/
1928  }
1929  }
1930 #endif
1931  hoc_objectdata = psav;
1932  if (od) {
1933  free((char*) od);
1934  }
1935 }
1936 
1937 
1938 static void hoc_allobjects1(Symlist* sl, int nspace);
1939 static void hoc_allobjects2(Symbol* s, int nspace);
1940 
1941 void hoc_allobjects(void) {
1942  int n = 0;
1943  if (ifarg(1)) {
1944  if (hoc_is_str_arg(1)) {
1946  } else {
1947  Object** o = hoc_objgetarg(1);
1948  if (*o) {
1949  n = (*o)->refcount;
1950  }
1951  }
1952  } else {
1955  }
1956  hoc_ret();
1957  pushx((double) n);
1958 }
1959 
1960 void hoc_allobjects1(Symlist* sl, int nspace) {
1961  Symbol* s;
1962  cTemplate* t;
1963  Object* o;
1964  hoc_Item* q;
1965  int i;
1966  if (sl)
1967  for (s = sl->first; s; s = s->next) {
1968  if (s->type == TEMPLATE) {
1969  t = s->u.ctemplate;
1970  ITERATE(q, t->olist) {
1971  o = OBJ(q);
1972  for (i = 0; i < nspace; ++i) {
1973  Printf(" ");
1974  }
1975  Printf("%s with %d refs\n", hoc_object_name(o), o->refcount);
1976  }
1977  hoc_allobjects1(t->symtable, nspace + 1);
1978  }
1979  }
1980 }
1981 
1982 void hoc_allobjects2(Symbol* s, int nspace) {
1983  cTemplate* t;
1984  Object* o;
1985  hoc_Item* q;
1986  int i;
1987  if (s && s->type == TEMPLATE) {
1988  t = s->u.ctemplate;
1989  ITERATE(q, t->olist) {
1990  o = OBJ(q);
1991  for (i = 0; i < nspace; ++i) {
1992  Printf(" ");
1993  }
1994  Printf("%s with %d refs\n", hoc_object_name(o), o->refcount);
1995  }
1996  }
1997 }
1998 
1999 static void hoc_list_allobjref(Symlist*, Objectdata*, int);
2000 
2001 void hoc_allobjectvars(void) {
2003  hoc_ret();
2004  pushx(0.);
2005 }
2006 
2007 static void hoc_list_allobjref(Symlist* sl, Objectdata* data, int depth) {
2008  /* look in all object variables that point to
2009  objects and print them */
2010  Symbol* s;
2011  int total, i, id;
2012  Object** obp;
2013 
2014  if (sl)
2015  for (s = sl->first; s; s = s->next) {
2016  if (s->type == OBJECTVAR && s->cpublic != 2) {
2017  total = hoc_total_array_data(s, data);
2018  for (i = 0; i < total; i++) {
2019  obp = data[s->u.oboff].pobj + i;
2020  for (id = 0; id < depth; id++) {
2021  Printf(" ");
2022  }
2023  if (*obp) {
2024  Printf("obp %s[%d] -> %s with %d refs.\n",
2025  s->name,
2026  i,
2027  hoc_object_name(*obp),
2028  (*obp)->refcount);
2029  } else {
2030  Printf("obp %s[%d] -> NULL\n", s->name, i);
2031  }
2032  if (*obp && !(*obp)->recurse && s->subtype != CPLUSOBJECT &&
2033  (*obp)->u.dataspace != data /* not this */
2034  ) {
2035  /* descend to look for more */
2036  (*obp)->recurse = 1;
2037  hoc_list_allobjref((*obp)->ctemplate->symtable,
2038  (*obp)->u.dataspace,
2039  depth + 1);
2040  (*obp)->recurse = 0;
2041  }
2042  }
2043  }
2044  }
2045 }
2046 
2047 void check_obj_type(Object* obj, const char* type_name) {
2048  char buf[100];
2049  if (!obj || strcmp(obj->ctemplate->sym->name, type_name) != 0) {
2050  if (obj) {
2051  sprintf(buf, "object type is %s instead of", obj->ctemplate->sym->name);
2052  } else {
2053  sprintf(buf, "object type is nil instead of");
2054  }
2055  hoc_execerror(buf, type_name);
2056  }
2057 }
2058 
2059 int is_obj_type(Object* obj, const char* type_name) {
2060  if (obj && strcmp(obj->ctemplate->sym->name, type_name) == 0) {
2061  return 1;
2062  } else {
2063  return 0;
2064  }
2065 }
2066 
2067 
2069 #if USE_PYTHON
2070  // The PyObject* reference is not incremented. Use only as last resort
2072  return (*nrnpy_opaque_obj2pyobj_p_)(ho);
2073  }
2074 #endif
2075  return nullptr;
2076 }
void nrn_rangeconst(Section *sec, Symbol *s, double *pd, int op)
Definition: cabcode.cpp:958
void nrn_pushsec(Section *sec)
Definition: cabcode.cpp:99
double cable_prop_eval(Symbol *sym)
Definition: cabcode.cpp:1518
void cable_prop_assign(Symbol *sym, double *pd, int op)
Definition: cabcode.cpp:1598
Section * nrn_sec_pop(void)
Definition: cabcode.cpp:751
double * nrn_rangepointer(Section *sec, Symbol *s, double d)
Definition: cabcode.cpp:1335
void new_sections(Object *ob, Symbol *sym, Item **pitm, int size)
Definition: cabcode.cpp:289
#define symlist
Definition: cabcode.cpp:17
double * cable_prop_eval_pointer(Symbol *sym)
Definition: cabcode.cpp:1536
void ob_sec_access_push(Item *qsec)
Definition: cabcode.cpp:824
short index
Definition: cabvars.h:10
short type
Definition: cabvars.h:9
Symbol * hoc_table_lookup(const char *, Symlist *)
Definition: symbol.cpp:61
Inst * Code(Pfrv f)
Definition: code.cpp:2614
void push_frame(Symbol *sp, int narg)
Definition: code.cpp:1364
void pushx(double d)
Definition: code.cpp:658
void pushi(int d)
Definition: code.cpp:726
Inst * codei(int f)
Definition: code.cpp:2619
void pushs(Symbol *d)
Definition: code.cpp:721
int araypt(Symbol *sp, int type)
Definition: code.cpp:2416
void hoc_iterator_object(Symbol *sym, int argcount, Inst *beginpc, Inst *endpc, Object *ob)
Definition: code.cpp:1047
Inst * pc
Definition: code.cpp:145
int ipop(void)
Definition: code.cpp:887
void execute(Inst *p)
Definition: code.cpp:2661
void pop_frame(void)
Definition: code.cpp:1375
void connect_obsec_syntax(void)
double t
Definition: cvodeobj.cpp:59
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)
static int indx
Definition: deriv.cpp:294
double chkarg(int, double low, double high)
Definition: code2.cpp:638
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:754
static void destruct(void *v)
Definition: grglyph.cpp:205
static void * cons(Object *o)
Definition: grglyph.cpp:198
char buf[512]
Definition: init.cpp:13
char * hoc_object_pathname(Object *ob)
Definition: hoc_oop.cpp:1794
Object * hoc_name2obj(const char *name, int index)
Definition: hoc_oop.cpp:922
void hoc_obj_set(int i, Object *obj)
Definition: hoc_oop.cpp:65
void hoc_construct_point(Object *, int)
Definition: hocmech.cpp:52
int hoc_obj_run(const char *cmd, Object *ob)
Brief explanation of hoc_obj_run.
Definition: hoc_oop.cpp:322
void * nrn_opaque_obj2pyobj(Object *ho)
Definition: hoc_oop.cpp:2068
void hoc_pushstr(char **d)
Definition: code.cpp:680
double hoc_call_func(Symbol *s, int narg)
Definition: code.cpp:1462
void hoc_free_val_array(double *, size_t)
Definition: symbol.cpp:383
int ivoc_list_look(Object *ob, Object *oblook, char *path, int)
Definition: oclist.cpp:503
void hoc_new_object_asgn(Object **obp, Symbol *st, void *v)
Definition: hoc_oop.cpp:485
size_t hoc_total_array_data(Symbol *s, Objectdata *obd)
Definition: hoc_oop.cpp:94
int hoc_arayinfo_install(Symbol *sp, int nsub)
Definition: hoc.cpp:601
Object ** hoc_temp_objvar(Symbol *symtemp, void *v)
Definition: hoc_oop.cpp:491
int hoc_argindex(void)
Definition: code.cpp:1639
void hoc_template_notify(Object *ob, int message)
Definition: ocobserv.cpp:41
void hoc_pushpx(double *d)
Definition: code.cpp:716
int hoc_inside_stacktype(int i)
Definition: code.cpp:784
void hoc_pushobj(Object **d)
Definition: code.cpp:663
Object * hoc_obj_get(int i)
Definition: hoc_oop.cpp:56
void hoc_freearay(Symbol *sp)
Definition: hoc.cpp:640
int hoc_obj_look_inside_stack_index(int i)
Definition: code.cpp:780
Symbol * hoc_install(const char *, int, double, Symlist **)
void hoc_free_object(Object *)
Definition: symbol.cpp:388
int hoc_is_str_arg(int narg)
Definition: code.cpp:752
int hoc_errno_check(void)
Definition: math.cpp:109
void hoc_free_pstring(char **)
Definition: symbol.cpp:399
Objectdata * hoc_objectdata
Definition: hoc_oop.cpp:123
void hoc_assign_str(char **cpp, const char *buf)
Definition: code.cpp:2350
size_t hoc_total_array(Symbol *s)
Definition: hoc_oop.cpp:82
double hoc_opasgn(int op, double dest, double src)
Definition: code.cpp:1668
double hoc_call_objfunc(Symbol *s, int narg, Object *ob)
Definition: hoc_oop.cpp:389
int is_obj_type(Object *obj, const char *type_name)
Definition: hoc_oop.cpp:2059
void hoc_ret()
int hoc_oc(const char *buf)
Definition: hoc.cpp:1471
void hoc_warning(const char *, const char *)
void check_obj_type(Object *obj, const char *type_name)
Definition: hoc_oop.cpp:2047
void hoc_obj_disconnect(Object *)
Definition: ocobserv.cpp:9
void hoc_obj_ref(Object *obj)
Definition: hoc_oop.cpp:1810
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:72
void ivoc_free_alias(Object *ob)
Definition: strfun.cpp:112
void hoc_dec_refcount(Object **pobj)
Definition: hoc_oop.cpp:1816
void hoc_install_object_data_index(Symbol *sp)
Definition: hoc_oop.cpp:304
double * hoc_pxpop(void)
Definition: code.cpp:838
void hoc_stkobj_unref(Object *o, int stkindex)
Definition: code.cpp:282
void hoc_oop_initaftererror(void)
Definition: hoc_oop.cpp:417
Symbol * hoc_lookup(const char *)
double hoc_xpop(void)
void hoc_obj_unref(Object *obj)
Definition: hoc_oop.cpp:1828
Symbol * ivoc_alias_lookup(const char *name, Object *ob)
Definition: strfun.cpp:104
void hoc_free_allobjects(cTemplate *ctemplate, Symlist *sl, Objectdata *data)
Definition: hoc_oop.cpp:1699
void hoc_pushi(int)
char * hoc_araystr(Symbol *sym, int index, Objectdata *obd)
Definition: code.cpp:2367
void hoc_push_object(Object *d)
Definition: code.cpp:673
Symbol * hoc_spop(void)
HocStr * hocstr_create(size_t size)
Definition: hoc.cpp:945
int hoc_main1_inited_
Definition: hoc.cpp:884
void hocstr_delete(HocStr *hs)
Definition: hoc.cpp:959
void free_arrayinfo(Arrayinfo *a)
Definition: hoc.cpp:652
#define pushtemplatesym(arg)
Definition: hoc_oop.cpp:213
void oc_save_hoc_oop(Object **a1, Objectdata **a2, int *a4, Symlist **a5)
Definition: hoc_oop.cpp:430
Objectdata * hoc_objectdata_restore(Objectdata *obdsav)
Definition: hoc_oop.cpp:143
static void call_constructor(Object *, Symbol *, int)
Definition: hoc_oop.cpp:683
void hoc_objectvar(void)
Definition: hoc_oop.cpp:855
#define pushtemplatesymlist(arg)
Definition: hoc_oop.cpp:216
void hoc_allobjects(void)
Definition: hoc_oop.cpp:1941
#define pushtemplatei(arg)
Definition: hoc_oop.cpp:219
#define OBJ_STACK_SIZE
Definition: hoc_oop.cpp:239
static Object * obj_stack_[OBJ_STACK_SIZE+1]
Definition: hoc_oop.cpp:240
static newobj1_err_t * newobj1_err_
Definition: hoc_oop.cpp:517
static int newobj1_err_size_
Definition: hoc_oop.cpp:516
static Templatedatum * poptemplate(void)
Definition: hoc_oop.cpp:206
static Symbol * hoc_obj_
Definition: hoc_oop.cpp:42
void hoc_allobjectvars(void)
Definition: hoc_oop.cpp:2001
void hoc_newobj1_err()
unref partially constructed objects controlled by current longjump handle
Definition: hoc_oop.cpp:546
static Templatedatum templatestack[NTEMPLATESTACK]
Definition: hoc_oop.cpp:203
void hoc_install_hoc_obj(void)
Definition: hoc_oop.cpp:44
static void call_ob_iter(Object *ob, Symbol *sym, int narg)
Definition: hoc_oop.cpp:782
Symbol * hoc_decl(Symbol *s)
Definition: hoc_oop.cpp:1608
int hoc_in_template
Definition: hoc_oop.cpp:126
Objectdata * hoc_objectdata_save(void)
Definition: hoc_oop.cpp:133
void hoc_external_var(Symbol *s)
Definition: hoc_oop.cpp:1635
void hoc_object_asgn(void)
Definition: hoc_oop.cpp:1369
void hoc_newobj(void)
Definition: hoc_oop.cpp:655
static int template_id
Definition: hoc_oop.cpp:1484
void hoc_asgn_obj_to_str(void)
Definition: hoc_oop.cpp:1362
int hoc_max_builtin_class_id
Definition: hoc_oop.cpp:40
Symbol * hoc_which_template(Symbol *s)
Definition: hoc_oop.cpp:1468
void hoc_constobject(void)
Definition: hoc_oop.cpp:903
#define objectpath
Definition: hoc_oop.cpp:1739
static void free_objectdata(Objectdata *, cTemplate *)
Definition: hoc_oop.cpp:1877
void hoc_obvar_declare(Symbol *sym, int type, int pmes)
Definition: hoc_oop.cpp:152
void hoc_exec_cmd(void)
Definition: hoc_oop.cpp:356
int hoc_print_first_instance
Definition: hoc_oop.cpp:38
void(* oc_jump_target_)()
Definition: hoc.cpp:686
void hoc_object_id(void)
Definition: hoc_oop.cpp:947
static void hoc_list_allobjref(Symlist *, Objectdata *, int)
Definition: hoc_oop.cpp:2007
void hoc_cmp_otype(void)
Definition: hoc_oop.cpp:845
void hoc_object_component(void)
Definition: hoc_oop.cpp:999
void * nrn_get_hoc_jmp()
If one of the two jmp_buf is controlling the longjmp hoc_newobj1_err needs handle to know how much to...
Definition: hoc.cpp:697
#define pushtemplateo(arg)
Definition: hoc_oop.cpp:225
void hoc_ob_check(int type)
Definition: hoc_oop.cpp:1673
void pop_newobj1_err()
pop the now fully constructed object
Definition: hoc_oop.cpp:540
void hoc_endtemplate(Symbol *t)
Definition: hoc_oop.cpp:1525
Object * hoc_newobj1(Symbol *sym, int narg)
Definition: hoc_oop.cpp:565
static Templatedatum * templatestackp
Definition: hoc_oop.cpp:204
void call_ob_proc(Object *ob, Symbol *sym, int narg)
Definition: hoc_oop.cpp:715
void class2oc(const char *name, void *(*cons)(Object *), void(*destruct)(void *), Member_func *m, int(*checkpoint)(void **), Member_ret_obj_func *mobjret, Member_ret_str_func *strret)
Definition: hoc_oop.cpp:1560
Object * hoc_new_object(Symbol *symtemp, void *v)
Definition: hoc_oop.cpp:457
void hoc_object_push(void)
Definition: hoc_oop.cpp:243
void hoc_newobj_ret(void)
Definition: hoc_oop.cpp:651
static void hoc_allobjects2(Symbol *s, int nspace)
Definition: hoc_oop.cpp:1982
void hoc_object_eval(void)
Definition: hoc_oop.cpp:1296
void hoc_object_pushed(void)
Definition: hoc_oop.cpp:265
static int icntobjectdata
Definition: hoc_oop.cpp:121
Object * nrn_get_gui_redirect_obj()
Definition: hoc_oop.cpp:711
static void chktemplate(void)
Definition: hoc_oop.cpp:229
void hoc_begintemplate(Symbol *t1)
Definition: hoc_oop.cpp:1486
#define NTEMPLATESTACK
Definition: hoc_oop.cpp:202
#define PUBLIC_TYPE
Definition: hoc_oop.cpp:33
static int obj_stack_loc
Definition: hoc_oop.cpp:241
void oc_restore_hoc_oop(Object **a1, Objectdata **a2, int *a4, Symlist **a5)
Definition: hoc_oop.cpp:446
void hoc_object_pop(void)
Definition: hoc_oop.cpp:273
void hoc_objvardecl(void)
Definition: hoc_oop.cpp:812
void hoc_ob_pointer(void)
Definition: hoc_oop.cpp:1326
void hoc_add_publiclist(Symbol *s)
Definition: hoc_oop.cpp:1623
void * nrn_get_oji()
Return handle for the current longjump buffer info.
Definition: ocjump.cpp:129
static void hoc_allobjects1(Symlist *sl, int nspace)
Definition: hoc_oop.cpp:1960
static int icnttoplevel
Definition: hoc_oop.cpp:125
Objectdata * hoc_top_level_data
Definition: hoc_oop.cpp:124
void hoc_newobj_arg(void)
Definition: hoc_oop.cpp:640
#define pathprepend
Definition: hoc_oop.cpp:1740
static void push_newobj1_err(Object *ob)
save partially constructed object and controlling longjump handle
Definition: hoc_oop.cpp:520
#define pushtemplateodata(arg)
Definition: hoc_oop.cpp:222
static int newobj1_err_index_
Definition: hoc_oop.cpp:515
void hoc_push_current_object(void)
Definition: hoc_oop.cpp:129
void hoc_objectarg(void)
Definition: hoc_oop.cpp:888
void hoc_known_type(void)
Definition: hoc_oop.cpp:850
int hoc_resize_toplevel(int more)
Definition: hoc_oop.cpp:292
static Object * gui_redirect_obj_
Definition: hoc_oop.cpp:710
#define EXTERNAL_TYPE
Definition: hoc_oop.cpp:34
Object * hoc_thisobject
Definition: hoc_oop.cpp:122
#define NEWOBJ1_ERR_SIZE
If hoc_newob1 fails after creating a new object, that object needs to be unreffed.
Definition: hoc_oop.cpp:506
#define assert(ex)
Definition: hocassrt.h:32
void * erealloc(void *ptr, size_t n)
Definition: symbol.cpp:263
#define OBJECTALIAS
Definition: hocdec.h:107
#define USERPROPERTY
Definition: hocdec.h:94
#define JAVAOBJECT
Definition: hocdec.h:105
void * ecalloc(size_t n, size_t size)
Definition: symbol.cpp:215
#define ISARRAY(arg)
Definition: hocdec.h:164
#define OBJECTTMP
Definition: hocdec.h:101
#define OPOBJ(sym)
Definition: hocdec.h:308
#define gargstr
Definition: hocdec.h:14
#define OPARINFO(sym)
Definition: hocdec.h:311
#define CPLUSOBJECT
Definition: hocdec.h:104
#define OPSECITM(sym)
Definition: hocdec.h:309
union Objectdata Objectdata
#define OPSTR(sym)
Definition: hocdec.h:307
#define NOT_PARALLEL_SUB(c1)
Definition: hocdec.h:379
#define OPVAL(sym)
Definition: hocdec.h:306
#define STOP
Definition: hocdec.h:66
#define VARALIAS
Definition: hocdec.h:108
#define OBJ(q)
Definition: hoclist.h:67
hoc_List * hoc_l_newlist()
hoc_Item * hoc_l_lappendobj(hoc_List *, struct Object *)
void hoc_l_delete(hoc_Item *)
int special_pnt_call(Object *ob, Symbol *sym, int narg)
Definition: hocmech.cpp:96
Datum * hoc_look_inside_stack(int, int)
Definition: code.cpp:765
Object ** hoc_objgetarg(int)
Definition: code.cpp:1587
void
Symlist * hoc_top_level_symlist
Definition: code2.cpp:690
Symlist * hoc_built_in_symlist
Definition: ivocmac.cpp:76
Symlist * hoc_symlist
int ifarg(int)
Definition: code.cpp:1581
void hoc_pushx(double)
static int narg()
Definition: ivocvect.cpp:150
Object ** hoc_temp_objptr(Object *)
Definition: code.cpp:216
#define v
Definition: md1redef.h:4
#define sec
Definition: md1redef.h:13
#define id
Definition: md1redef.h:33
#define i
Definition: md1redef.h:12
#define ITERATE(itm, lst)
Definition: model.h:25
#define SYMBOL
Definition: model.h:102
#define Sprintf
Definition: model.h:233
#define Printf
Definition: model.h:237
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
int hoc_stacktype()
Definition: code.cpp:731
int section_object_seen
void sec_free(hoc_Item *)
Definition: solve.cpp:521
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
void destroy_point_process(void *)
Definition: point.cpp:75
int nrnmpi_myid_world
char ** hoc_strpop()
Definition: code.cpp:879
Object * hoc_obj_look_inside_stack(int)
Definition: code.cpp:770
Symbol * nrnpy_pyobj_sym_
int nrn_inpython_
Definition: hoc.cpp:37
Object ** hoc_objpop()
Definition: code.cpp:860
void hoc_pushs(Symbol *)
void(* nrnpy_hpoasgn)(Object *, int)
void(* nrnpy_py2n_component)(Object *, Symbol *, int, int)
void *(* nrnpy_opaque_obj2pyobj_p_)(Object *)
int hoc_ipop()
void hoc_pop_defer()
Definition: code.cpp:257
void hoc_nopop()
FILE * hoc_fin
#define STRING
Definition: bbslsrv.cpp:9
#define data
Definition: rbtqueue.cpp:49
#define ne
Definition: redef.h:94
#define call
Definition: redef.h:34
int hoc_returning
Definition: code.cpp:148
sl
Definition: seclist.cpp:181
hoc_tobj_unref(obp)
o
Definition: seclist.cpp:175
Section * nrn_sectionref_steer(Section *sec, Symbol *sym, int *pnindex)
Definition: secref.cpp:310
Symbol * nrn_sec_sym
Definition: secref.cpp:27
#define NULL
Definition: sptree.h:16
void hoc_free_symspace(Symbol *)
Definition: symbol.cpp:271
int nsub
Definition: hocdec.h:70
int refcount
Definition: hocdec.h:71
int sub[1]
Definition: hocdec.h:72
Definition: hocstr.h:7
char * buf
Definition: hocstr.h:8
const char * name
Definition: hoc_membf.h:7
double(* member)(void *)
Definition: hoc_membf.h:8
const char * name
Definition: hoc_membf.h:12
struct Object **(* member)(void *)
Definition: hoc_membf.h:13
const char * name
Definition: hoc_membf.h:17
const char **(* member)(void *)
Definition: hoc_membf.h:18
Definition: hocdec.h:227
void * aliases
Definition: hocdec.h:239
void * this_pointer
Definition: hocdec.h:232
Objectdata * dataspace
Definition: hocdec.h:231
HocStruct hoc_Item * secelm_
Definition: hocdec.h:242
int index
Definition: hocdec.h:229
short unref_recurse_cnt
Definition: hocdec.h:245
void * observers
Definition: hocdec.h:243
int refcount
Definition: hocdec.h:228
HocStruct hoc_Item * itm_me
Definition: hocdec.h:241
short recurse
Definition: hocdec.h:244
union Object::@39 u
Inst defn
Definition: hocdec.h:76
int refcount
Definition: section.h:40
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
short type
Definition: model.h:58
long subtype
Definition: model.h:59
HocStruct Symbol * next
Definition: hocdec.h:162
HocStruct Object * object_
Definition: hocdec.h:138
union Symbol::@18 u
char * name
Definition: model.h:72
double * pval
Definition: hocdec.h:137
HocStruct cTemplate * ctemplate
Definition: hocdec.h:152
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
HocStruct Symbol * first
Definition: hocdec.h:85
int dataspace_size
Definition: hocdec.h:198
Symbol * unref
Definition: hocdec.h:201
Symlist * symtable
Definition: hocdec.h:197
Symbol * init
Definition: hocdec.h:200
hoc_List * olist
Definition: hocdec.h:204
void * observers
Definition: hocdec.h:206
int count
Definition: hocdec.h:203
int is_point_
Definition: hocdec.h:199
int index
Definition: hocdec.h:202
Object * ob
Definition: hoc_oop.cpp:508
void * oji
Definition: hoc_oop.cpp:509
Definition: hocdec.h:177
HocStruct Object * obj
Definition: hocdec.h:183
Symbol * sym
Definition: hocdec.h:179
HocStruct Object ** pobj
Definition: hocdec.h:182
Definition: hocdec.h:51
Pfrv pf
Definition: hocdec.h:52
HocUnion Inst * in
Definition: hocdec.h:60
int i
Definition: hocdec.h:63
Pfrs_vp pfs_vp
Definition: hocdec.h:59
HocStruct Symbol * sym
Definition: hocdec.h:61
Pfro_vp pfo_vp
Definition: hocdec.h:58
Pfrd_vp pfd_vp
Definition: hocdec.h:57
char ** ppstr
Definition: hocdec.h:219
void * _pvoid
Definition: hocdec.h:224
Arrayinfo * arayinfo
Definition: hocdec.h:223
double * pval
Definition: hocdec.h:218
HocStruct Object ** pobj
Definition: hocdec.h:220
HocStruct hoc_Item ** psecitm
Definition: hocdec.h:221
Objectdata * odata
Definition: hoc_oop.cpp:198
Symlist * symlist
Definition: hoc_oop.cpp:197
Symbol * sym
Definition: hoc_oop.cpp:196
Object * o
Definition: hoc_oop.cpp:199