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