NEURON
secref.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 /*
3 Section reference
4 Allows sections to be stored as variables and passed as arguments by
5 using an object as a label for a particular section.
6 
7 Usage is:
8 
9 objectvar s1, s2
10 soma s1 = new SectionRef()
11 print s1.sec.L // prints length of soma
12 s2 = s1
13 s2.sec {psection()} // makes soma the currently accessed section for a statement
14 
15 access s1.sec // soma becomes the default section
16 */
17 
18 #include <stdlib.h>
19 #include "section.h"
20 #include "parse.hpp"
21 #include "classreg.h"
22 #include "code.h"
23 #include "oc_ansi.h"
24 
27 
30  if (!sec || !sec->prop || !sec->prop->dparam[0].get<Symbol*>()) {
31  hoc_execerror("section is unnamed", (char*) 0);
32  }
33  auto* sym = sec->prop->dparam[0].get<Symbol*>();
34  auto* ob = sec->prop->dparam[6].get<Object*>();
35  auto i = sec->prop->dparam[5].get<int>();
36  if (ob) {
37  return ob->u.dataspace[sym->u.oboff].psecitm + i;
38  } else {
39  return hoc_top_level_data[sym->u.oboff].psecitm + i;
40  }
41 }
42 
43 /*ARGSUSED*/
44 static void* cons(Object* ho) {
45  Section* sec = nrn_secarg(1);
47  return (void*) (sec);
48 }
49 
50 static void destruct(void* v) {
51  Section* sec = (Section*) v;
53 }
54 
55 #if 0
56 static double dummy(void* v) {
57  Section* sec = (Section*)v;
58  printf("%s\n", secname(sec));
59  return 0.;
60 }
61 #endif
62 
63 static double s_unname(void* v) {
64  hoc_Item** pitm;
65  Section* sec;
66  sec = (Section*) v;
67 #if USE_PYTHON
68  /* Python Sections cannot be unnamed, return 0.0 */
69  if (sec->prop && sec->prop->dparam[PROP_PY_INDEX].get<void*>()) {
70  return 0.0;
71  }
72 #endif
73  pitm = sec2pitm(sec);
74  *pitm = (hoc_Item*) 0;
75  auto* ob = sec->prop->dparam[6].get<Object*>();
76  if (ob) {
77  // Avoid use of freed memory in CellBuild when making a section
78  // after deleting a section when continuous create is on.
79  // CellBuild repeatedly creates a single CellBuildTopology[0].dummy
80  // section and then unnames and renamed it at the top level.
81  ob->secelm_ = nullptr;
82  sec->prop->dparam[6] = static_cast<Object*>(nullptr);
83  }
84  sec->prop->dparam[0] = static_cast<Symbol*>(nullptr);
85  return 1.;
86 }
87 
88 static double s_rename(void* v) {
91 
92  char* name;
93  Section* sec;
94  Symbol* sym;
95  hoc_Item* qsec;
96  hoc_Item** pitm;
97  Object *ob, *olist;
98  Objectdata* obdsav;
99  int i, index, size, n;
100 
101  sec = (Section*) v;
102  if (!sec->prop) {
103  Printf("SectionRef[???].sec is a deleted section\n");
104  return 0.;
105  }
106 #if USE_PYTHON
107  /* Python Sections cannot be renamed, return 0.0 */
108  if (sec->prop->dparam[PROP_PY_INDEX].get<void*>()) {
109  return 0.;
110  }
111 #endif
112  qsec = sec->prop->dparam[8].get<hoc_Item*>();
113  if (sec->prop->dparam[0].get<Symbol*>()) {
114  Printf("%s must first be unnamed\n", secname(sec));
115  return 0.;
116  }
117 
118  name = gargstr(1);
119  size = 0;
120  index = 0;
121  if (ifarg(2)) {
122  olist = *hoc_objgetarg(2);
123  size = ivoc_list_count(olist);
124  assert(size > 0);
125  }
127  obdsav = hoc_objectdata;
129  if (sym) {
130  if (sym->type != SECTION || (sym->arayinfo && sym->arayinfo->nsub > 1)) {
131  Printf("The new name already exists and is not a SECTION or has a dimension > 1\n");
132  hoc_objectdata = obdsav;
133  return 0;
134  }
135  /* check that it points to no sections */
137  pitm = hoc_top_level_data[sym->u.oboff].psecitm;
138  for (i = 0; i < n; ++i) {
139  if (pitm[i]) {
140  Printf("Previously existing %s[%d] points to a section which is being deleted\n",
141  sym->name,
142  i);
143  sec_free(pitm[i]);
144  }
145  }
146  if (sym->arayinfo) {
147  hoc_freearay(sym);
148  }
149  free(pitm);
150  } else {
151  sym = hoc_install(name, SECTION, 0., &hoc_top_level_symlist);
153  }
154  if (size) {
155  hoc_pushx((double) size);
156  hoc_arayinfo_install(sym, 1);
157  hoc_top_level_data[sym->u.oboff].psecitm = pitm = (hoc_Item**) ecalloc(size,
158  sizeof(hoc_Item*));
159  } else {
160  hoc_top_level_data[sym->u.oboff].psecitm = pitm = (hoc_Item**) ecalloc(1,
161  sizeof(hoc_Item*));
162  }
163 
164  if (size == 0) {
165  pitm[index] = qsec;
166  sec->prop->dparam[0] = {neuron::container::do_not_search, sym};
167  sec->prop->dparam[5] = index;
168  sec->prop->dparam[6] = static_cast<Object*>(nullptr);
169  OPSECITM(sym)[0] = qsec;
170  } else {
171  for (i = 0; i < size; ++i) {
172  ob = ivoc_list_item(olist, i);
173  /*assert(is_obj_type(ob, "SectionRef")*/
174  sec = (Section*) ob->u.this_pointer;
175  if (!sec->prop) {
176  Printf("%s references a deleted section\n", hoc_object_name(ob));
177  hoc_objectdata = obdsav;
178  return 0;
179  }
180  if (sec->prop->dparam[0].get<Symbol*>()) {
181  Printf("Item %d of second list arg, %s, must first be unnamed\n", i, secname(sec));
182  return 0;
183  }
184  qsec = sec->prop->dparam[8].get<hoc_Item*>();
185  sec->prop->dparam[0] = sym;
186  sec->prop->dparam[5] = i;
187  sec->prop->dparam[6] = static_cast<Object*>(nullptr);
188  OPSECITM(sym)[i] = qsec;
189  }
190  }
191 #if 0
192  printf("SectionRef[???}.rename");
193  i = sec->prop->dparam[5].i;
194  if (ob) {
195  pitm = ob->u.dataspace[sym->u.oboff].psecitm;
196  }else{
197  pitm = hoc_top_level_data[sym->u.oboff].psecitm;
198  }
199  printf("%s\n", secname(sec));
200  printf("sec->prop->dparam[0].sym->name = %s\n", sym->name);
201  printf("dparam[5].i = %d dparam[6].obj = %s\n", i, hoc_object_name(ob));
202  printf("sym->u.oboff = %d\n", sym->u.oboff);
203  if (ob) {
204  printf("ob->u.dataspace[sym->u.oboff].psecitm = %lx\n", pitm);
205  }else{
206  printf("hoc_top_level_data[sym->u.oboff].psecitm = %lx\n", pitm);
207  }
208  printf("hocSEC(pitm[i]) = %s\n", secname(hocSEC(pitm[i])));
209  if (sym->arayinfo) {
210  Arrayinfo* a;
211  int j;
212  a = sym->arayinfo;
213  printf("symbol array info ");
214  for (j=0; j < a->nsub; ++j) {
215  printf("[%d]", a->sub[j]);
216  }
217  printf("\n");
218  if (ob) {
219  a = ob->u.dataspace[sym->u.oboff + 1].arayinfo;
220  printf("dataspace array info ");
221  for (j=0; j < a->nsub; ++j) {
222  printf("[%d]", a->sub[j]);
223  }
224  printf("\n");
225  }
226  }else{
227  printf("scalar\n");
228  }
229 #endif
230  hoc_objectdata = obdsav;
231  return 1.0;
232 }
233 
235  int n;
236  if (!sec->prop) {
237  hoc_execerror("Section was deleted", (char*) 0);
238  }
239  for (n = 0, sec = sec->child; sec; sec = sec->sibling) {
240  ++n;
241  }
242  return n;
243 }
244 
245 static double s_nchild(void* v) {
247  return (double) nrn_secref_nchild((Section*) v);
248 }
249 
250 static double s_has_parent(void* v) {
251  Section* sec = (Section*) v;
253  if (!sec->prop) {
254  hoc_execerror("Section was deleted", (char*) 0);
255  }
256  return (double) (sec->parentsec != (Section*) 0);
257 }
258 
259 static double s_has_trueparent(void* v) {
260  Section* sec = (Section*) v;
262  if (!sec->prop) {
263  hoc_execerror("Section was deleted", (char*) 0);
264  }
265  return (double) (nrn_trueparent(sec) != (Section*) 0);
266 }
267 
268 static double s_exists(void* v) {
270  Section* sec = (Section*) v;
271  return (double) (sec->prop != (Prop*) 0);
272 }
273 
274 static double s_cas(void* v) { /* return 1 if currently accessed section */
275  Section* sec = (Section*) v;
276  Section* cas = chk_access();
278  if (!sec->prop) {
279  hoc_execerror("Section was deleted", (char*) 0);
280  }
281  if (sec == cas) {
282  return 1.;
283  }
284  return 0.;
285 }
286 
287 static Member_func members[] = {{"sec", s_rename}, /* will actually become a SECTIONREF below */
288  {"parent", s_rename},
289  {"trueparent", s_rename},
290  {"root", s_rename},
291  {"child", s_rename},
292  {"nchild", s_nchild},
293  {"has_parent", s_has_parent},
294  {"has_trueparent", s_has_trueparent},
295  {"exists", s_exists},
296  {"rename", s_rename},
297  {"unname", s_unname},
298  {"is_cas", s_cas},
299  {nullptr, nullptr}};
300 
302  Section* s = 0;
303  if (sym == nrn_parent_sym) {
304  s = sec->parentsec;
305  if (!s) {
306  if (nrn_inpython_ == 1) {
307  hoc_warning("SectionRef has no parent for ", secname(sec));
308  nrn_inpython_ = 2;
309  return NULL;
310  } else {
311  hoc_execerror("SectionRef has no parent for ", secname(sec));
312  }
313  }
314  } else if (sym == nrn_trueparent_sym) {
315  s = nrn_trueparent(sec);
316  if (!s) {
317  if (nrn_inpython_) {
318  hoc_warning("SectionRef has no parent for ", secname(sec));
319  nrn_inpython_ = 2;
320  return NULL;
321  } else {
322  hoc_execerror("SectionRef has no parent for ", secname(sec));
323  }
324  }
325  } else if (sym == nrn_root_sym) {
326  for (s = sec; s->parentsec; s = s->parentsec) {
327  }
328  } else if (sym == nrn_child_sym) {
329  int index, i;
330  if (*pnindex == 0) {
331  if (nrn_inpython_) {
332  hoc_warning("SectionRef.child[index]", (char*) 0);
333  nrn_inpython_ = 2;
334  return NULL;
335  } else {
336  hoc_execerror("SectionRef.child[index]", (char*) 0);
337  }
338  }
339  // modeldb 114355 uses legacy syntax SectionRef.child(i). Allow
340  // though there is no ndim on stack.
341  bool ok = hoc_stack_type_is_ndim() ? (hoc_pop_ndim() == 1) : (*pnindex == 1);
342  if (!ok) {
343  hoc_execerror("SectionRef.child[index] must have only one dimension", NULL);
344  }
345  index = (int) hoc_xpop();
346  --*pnindex;
347  for (i = 0, s = sec->child; i < index && s; s = s->sibling) {
348  ++i;
349  }
350  if (i != index || !s) {
351  if (nrn_inpython_) {
352  hoc_warning("SectionRef.child index too large for", secname(sec));
353  nrn_inpython_ = 2;
354  return NULL;
355  } else {
356  hoc_execerror("SectionRef.child index too large for", secname(sec));
357  }
358  }
359  }
360  return s;
361 }
362 
363 void SectionRef_reg(void) {
364  Symbol *s, *sr;
365 
366  class2oc("SectionRef", cons, destruct, members, nullptr, nullptr);
367  /* now make the sec variable an actual SECTIONREF */
368  sr = hoc_lookup("SectionRef");
369  s = hoc_table_lookup("sec", sr->u.ctemplate->symtable);
370  s->type = SECTIONREF;
371  nrn_sec_sym = s;
372  s = hoc_table_lookup("parent", sr->u.ctemplate->symtable);
373  s->type = SECTIONREF;
374  nrn_parent_sym = s;
375  s = hoc_table_lookup("trueparent", sr->u.ctemplate->symtable);
376  s->type = SECTIONREF;
378  s = hoc_table_lookup("root", sr->u.ctemplate->symtable);
379  s->type = SECTIONREF;
380  nrn_root_sym = s;
381  s = hoc_table_lookup("child", sr->u.ctemplate->symtable);
382  s->type = SECTIONREF;
383  nrn_child_sym = s;
384  s->arayinfo = (Arrayinfo*) emalloc(sizeof(Arrayinfo));
385  ;
386  s->arayinfo->refcount = 1;
387  s->arayinfo->a_varn = nullptr;
388  s->arayinfo->nsub = 1;
389  s->arayinfo->sub[0] = 0;
390 }
Section * chk_access()
Definition: cabcode.cpp:449
const char * secname(Section *sec)
name of section (for use in error messages)
Definition: cabcode.cpp:1674
Section * nrn_trueparent(Section *sec)
Definition: cabcode.cpp:1577
void class2oc(const char *, ctor_f *cons, dtor_f *destruct, Member_func *, Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1631
Symbol * hoc_table_lookup(const char *, Symlist *)
Definition: symbol.cpp:48
char * gargstr(int narg)
Definition: code2.cpp:227
HocReturnType hoc_return_type_code
Definition: code.cpp:42
#define v
Definition: md1redef.h:11
#define sec
Definition: md1redef.h:20
#define i
Definition: md1redef.h:19
double hoc_xpop()
Definition: code.cpp:903
Object * ivoc_list_item(Object *olist, int i)
Definition: oclist.cpp:402
size_t hoc_total_array_data(const Symbol *s, Objectdata *obd)
Definition: hoc_oop.cpp:95
int hoc_arayinfo_install(Symbol *sp, int nsub)
Definition: hoc.cpp:528
int ivoc_list_count(Object *)
Definition: oclist.cpp:396
void hoc_freearay(Symbol *sp)
Definition: hoc.cpp:567
Symbol * hoc_install(const char *, int, double, Symlist **)
Definition: symbol.cpp:77
bool hoc_stack_type_is_ndim()
Definition: code.cpp:314
Objectdata * hoc_objectdata
Definition: hoc_oop.cpp:122
int hoc_pop_ndim()
Definition: code.cpp:933
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:73
void hoc_install_object_data_index(Symbol *sp)
Definition: hoc_oop.cpp:297
Symbol * hoc_lookup(const char *)
Definition: symbol.cpp:59
#define assert(ex)
Definition: hocassrt.h:24
#define OPSECITM(sym)
Definition: hocdec.h:237
#define hocSEC(q)
Definition: hoclist.h:87
Object ** hoc_objgetarg(int)
Definition: code.cpp:1614
Symlist * hoc_top_level_symlist
Definition: code2.cpp:677
void hoc_pushx(double)
Definition: code.cpp:779
printf
Definition: extdef.h:5
const char * name
Definition: init.cpp:16
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
void * ecalloc(size_t n, size_t size)
Definition: nrnoc_aux.cpp:85
static void * emalloc(size_t size)
Definition: mpispike.cpp:30
void hoc_warning(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:44
constexpr do_not_search_t do_not_search
Definition: data_handle.hpp:11
if(ncell==0)
Definition: cellorder.cpp:785
void section_ref(Section *)
Definition: solve.cpp:520
void section_unref(Section *)
Definition: solve.cpp:509
void sec_free(hoc_Item *)
Definition: solve.cpp:467
int const size_t const size_t n
Definition: nrngsl.h:10
size_t j
s
Definition: multisend.cpp:521
int ifarg(int)
Definition: code.cpp:1607
short index
Definition: cabvars.h:11
int nrn_inpython_
Definition: hoc.cpp:52
Objectdata * hoc_top_level_data
Definition: hoc_oop.cpp:123
HOC interpreter function declarations (included by hocdec.h)
static double dummy
Definition: ocptrvector.cpp:23
Section * nrn_secarg(int i)
Definition: seclist.cpp:70
void SectionRef_reg(void)
Definition: secref.cpp:363
static double s_has_parent(void *v)
Definition: secref.cpp:250
Section * nrn_sectionref_steer(Section *sec, Symbol *sym, int *pnindex)
Definition: secref.cpp:301
Symbol * nrn_parent_sym
Definition: secref.cpp:25
Symbol * nrn_child_sym
Definition: secref.cpp:25
static double s_has_trueparent(void *v)
Definition: secref.cpp:259
static Member_func members[]
Definition: secref.cpp:287
Symbol * nrn_sec_sym
Definition: secref.cpp:25
static hoc_Item ** sec2pitm(Section *sec)
Definition: secref.cpp:28
int nrn_secref_nchild(Section *sec)
Definition: secref.cpp:234
static void destruct(void *v)
Definition: secref.cpp:50
static double s_unname(void *v)
Definition: secref.cpp:63
static void * cons(Object *ho)
Definition: secref.cpp:44
Symbol * nrn_root_sym
Definition: secref.cpp:25
static double s_rename(void *v)
Definition: secref.cpp:88
static double s_nchild(void *v)
Definition: secref.cpp:245
static double s_exists(void *v)
Definition: secref.cpp:268
static double s_cas(void *v)
Definition: secref.cpp:274
Symbol * nrn_trueparent_sym
Definition: secref.cpp:26
#define PROP_PY_INDEX
Definition: section.h:230
#define NULL
Definition: spdefs.h:105
int nsub
Definition: hocdec.h:61
int sub[1]
Definition: hocdec.h:63
Definition: hocdec.h:173
void * this_pointer
Definition: hocdec.h:178
Objectdata * dataspace
Definition: hocdec.h:177
hoc_Item * secelm_
Definition: hocdec.h:184
union Object::@47 u
Definition: section.h:231
Definition: model.h:47
union Symbol::@28 u
short type
Definition: model.h:48
cTemplate * ctemplate
Definition: hocdec.h:126
char * name
Definition: model.h:61
int oboff
Definition: hocdec.h:111
Arrayinfo * arayinfo
Definition: hocdec.h:130
Definition: hocdec.h:75
Symlist * symtable
Definition: hocdec.h:148
hoc_Item ** psecitm
Definition: hocdec.h:167
Arrayinfo * arayinfo
Definition: hocdec.h:169
int Printf(const char *fmt, Args... args)
Definition: logger.hpp:18