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 "hoc_membf.h"
22 #include <nrnpython_config.h>
23 
24 extern int hoc_return_type_code;
25 
28 
31  Symbol* sym;
32  Object* ob;
33  int i;
34  if (!sec || !sec->prop || !sec->prop->dparam[0].sym) {
35  hoc_execerror("section is unnamed", (char*)0);
36  }
37  sym = sec->prop->dparam[0].sym;
38  ob = sec->prop->dparam[6].obj;
39  i = sec->prop->dparam[5].i;
40  if (ob) {
41  return ob->u.dataspace[sym->u.oboff].psecitm + i;
42  }else{
43  return hoc_top_level_data[sym->u.oboff].psecitm + i;
44  }
45 }
46 
47 /*ARGSUSED*/
48 static void* cons(Object* ho) {
49  Section* sec = nrn_secarg(1);
50  section_ref(sec);
51  return (void*)(sec);
52 }
53 
54 static void destruct(void* v) {
55  Section* sec = (Section*)v;
56  section_unref(sec);
57 }
58 
59 #if 0
60 static double dummy(void* v) {
61  Section* sec = (Section*)v;
62  printf("%s\n", secname(sec));
63  return 0.;
64 }
65 #endif
66 
67 static double s_unname(void* v) {
68  hoc_Item** pitm;
69  Section* sec;
70  sec = (Section*)v;
71 #if USE_PYTHON
72  /* Python Sections cannot be unnamed, return 0.0 */
73  if (sec->prop && sec->prop->dparam[PROP_PY_INDEX]._pvoid) {
74  return 0.0;
75  }
76 #endif
77  pitm = sec2pitm(sec);
78  *pitm = (hoc_Item*)0;
79  sec->prop->dparam[0].sym = (Symbol*)0;
80  return 1.;
81 }
82 
83 extern "C" Object* ivoc_list_item(Object*, int);
84 
85 static double s_rename(void* v) {
88 
89  char* name;
90  Section* sec;
91  Symbol* sym;
92  hoc_Item* qsec;
93  hoc_Item** pitm;
94  Object* ob, *olist;
95  Objectdata* obdsav;
96  int i, index, size, n;
97 
98  sec = (Section*)v;
99  if (!sec->prop) {
100  Printf("SectionRef[???].sec is a deleted section\n");
101  return 0.;
102  }
103 #if USE_PYTHON
104  /* Python Sections cannot be renamed, return 0.0 */
105  if (sec->prop->dparam[PROP_PY_INDEX]._pvoid) {
106  return 0.;
107  }
108 #endif
109  qsec = sec->prop->dparam[8].itm;
110  if (sec->prop->dparam[0].sym) {
111  Printf("%s must first be unnamed\n", secname(sec));
112  return 0.;
113  }
114 
115  name = gargstr(1);
116  size = 0;
117  index = 0;
118  if (ifarg(2)) {
119  olist = *hoc_objgetarg(2);
120  size = ivoc_list_count(olist);
121  assert(size > 0);
122  }
123  sym = hoc_table_lookup(name, hoc_top_level_symlist);
124  obdsav = hoc_objectdata;
126  if (sym) {
127  if (sym->type != SECTION || (sym->arayinfo && sym->arayinfo->nsub > 1)) {
128  Printf("The new name already exists and is not a SECTION or has a dimension > 1\n");
129  hoc_objectdata = obdsav;
130  return 0;
131  }
132  /* check that it points to no sections */
133  n = hoc_total_array_data(sym, hoc_top_level_data);
134  pitm = hoc_top_level_data[sym->u.oboff].psecitm;
135  for (i=0; i < n; ++i) {
136  if (pitm[i]) {
137  Printf("Previously existing %s[%d] points to a section which is being deleted\n", sym->name, i);
138  sec_free(pitm[i]);
139  }
140  }
141  if (sym->arayinfo) {
142  hoc_freearay(sym);
143  }
144  free(pitm);
145  }else{
146  sym = hoc_install(name, SECTION, 0., &hoc_top_level_symlist);
148  }
149  if (size) {
150  hoc_pushx((double)size);
151  hoc_arayinfo_install(sym, 1);
152  hoc_top_level_data[sym->u.oboff].psecitm = pitm = (hoc_Item**)ecalloc(size, sizeof(hoc_Item*));
153  }else{
154  hoc_top_level_data[sym->u.oboff].psecitm = pitm = (hoc_Item**)ecalloc(1, sizeof(hoc_Item*));
155  }
156 
157  if (size == 0) {
158  pitm[index] = qsec;
159  sec->prop->dparam[0].sym = sym;
160  sec->prop->dparam[5].i = index;
161  sec->prop->dparam[6].obj = nullptr;
162  OPSECITM(sym)[0] = qsec;
163  }else{
164  for (i=0; i < size; ++i) {
165  ob = ivoc_list_item(olist, i);
166  /*assert(is_obj_type(ob, "SectionRef")*/
167  sec = (Section*)ob->u.this_pointer;
168  if (!sec->prop) {
169  Printf("%s references a deleted section\n", hoc_object_name(ob));
170  hoc_objectdata = obdsav;
171  return 0;
172  }
173  qsec = sec->prop->dparam[8].itm;
174  sec->prop->dparam[0].sym = sym;
175  sec->prop->dparam[5].i = i;
176  sec->prop->dparam[6].obj = nullptr;
177  OPSECITM(sym)[i] = qsec;
178  }
179  }
180 #if 0
181  printf("SectionRef[???}.rename");
182  i = sec->prop->dparam[5].i;
183  if (ob) {
184  pitm = ob->u.dataspace[sym->u.oboff].psecitm;
185  }else{
186  pitm = hoc_top_level_data[sym->u.oboff].psecitm;
187  }
188  printf("%s\n", secname(sec));
189  printf("sec->prop->dparam[0].sym->name = %s\n", sym->name);
190  printf("dparam[5].i = %d dparam[6].obj = %s\n", i, hoc_object_name(ob));
191  printf("sym->u.oboff = %d\n", sym->u.oboff);
192  if (ob) {
193  printf("ob->u.dataspace[sym->u.oboff].psecitm = %lx\n", pitm);
194  }else{
195  printf("hoc_top_level_data[sym->u.oboff].psecitm = %lx\n", pitm);
196  }
197  printf("hocSEC(pitm[i]) = %s\n", secname(hocSEC(pitm[i])));
198  if (sym->arayinfo) {
199  Arrayinfo* a;
200  int j;
201  a = sym->arayinfo;
202  printf("symbol array info ");
203  for (j=0; j < a->nsub; ++j) {
204  printf("[%d]", a->sub[j]);
205  }
206  printf("\n");
207  if (ob) {
208  a = ob->u.dataspace[sym->u.oboff + 1].arayinfo;
209  printf("dataspace array info ");
210  for (j=0; j < a->nsub; ++j) {
211  printf("[%d]", a->sub[j]);
212  }
213  printf("\n");
214  }
215  }else{
216  printf("scalar\n");
217  }
218 #endif
219  hoc_objectdata = obdsav;
220  return 1.0;
221 }
222 
224  int n;
225  if (!sec->prop) {
226  hoc_execerror("Section was deleted", (char*)0);
227  }
228  for (n=0, sec = sec->child; sec; sec = sec->sibling) {
229  ++n;
230  }
231  return n;
232 }
233 
234 static double s_nchild(void* v) {
235  int n;
236  hoc_return_type_code = 1; /* integer */
237  return (double)nrn_secref_nchild((Section*)v);
238 }
239 
240 static double s_has_parent(void* v) {
241  int n;
242  Section* sec = (Section*)v;
243  hoc_return_type_code = 2; /* boolean */
244  if (!sec->prop) {
245  hoc_execerror("Section was deleted", (char*)0);
246  }
247  return (double)(sec->parentsec != (Section*)0);
248 }
249 
250 static double s_has_trueparent(void* v) {
251  int n;
252  Section* sec = (Section*)v;
253  hoc_return_type_code = 2; /* boolean */
254  if (!sec->prop) {
255  hoc_execerror("Section was deleted", (char*)0);
256  }
257  return (double)(nrn_trueparent(sec) != (Section*)0);
258 }
259 
260 static double s_exists(void* v) {
261  int n;
262  hoc_return_type_code = 2; /* boolean */
263  Section* sec = (Section*)v;
264  return (double)(sec->prop != (Prop*)0);
265 }
266 
267 static double s_cas(void* v) { /* return 1 if currently accessed section */
268  Section* sec = (Section*)v;
269  Section* cas = chk_access();
270  hoc_return_type_code = 2; /* boolean */
271  if (!sec->prop) {
272  hoc_execerror("Section was deleted", (char*)0);
273  }
274  if (sec == cas) {
275  return 1.;
276  }
277  return 0.;
278 }
279 
280 static Member_func members[] = {
281  "sec", s_rename, /* will actually become a SECTIONREF below */
282  "parent", s_rename,
283  "trueparent", s_rename,
284  "root", s_rename,
285  "child", s_rename,
286  "nchild", s_nchild,
287  "has_parent", s_has_parent,
288  "has_trueparent", s_has_trueparent,
289  "exists", s_exists,
290  "rename", s_rename,
291  "unname", s_unname,
292  "is_cas", s_cas,
293  0, 0
294 };
295 
297 {
298  Section* s=0;
299  if (sym == nrn_parent_sym) {
300  s = sec->parentsec;
301  if (!s) {
302 if (nrn_inpython_ == 1) {
303  hoc_warning("SectionRef has no parent for ", secname(sec));
304  nrn_inpython_ = 2;
305  return NULL;
306 }else{
307  hoc_execerror("SectionRef has no parent for ", secname(sec));
308 }
309  }
310  }else if (sym == nrn_trueparent_sym) {
311  s = nrn_trueparent(sec);
312  if (!s) {
313 if (nrn_inpython_) {
314  hoc_warning("SectionRef has no parent for ", secname(sec));
315  nrn_inpython_ = 2;
316  return NULL;
317 }else{
318  hoc_execerror("SectionRef has no parent for ", secname(sec));
319 }
320  }
321  }else if (sym == nrn_root_sym) {
322  for (s = sec; s->parentsec; s = s->parentsec) {}
323  }else if (sym == nrn_child_sym) {
324  int index, i;
325  if (*pnindex == 0) {
326 if (nrn_inpython_) {
327  hoc_warning("SectionRef.child[index]", (char*)0);
328  nrn_inpython_ = 2;
329  return NULL;
330 }else{
331  hoc_execerror("SectionRef.child[index]", (char*)0);
332 }
333  }
334  index = (int)hoc_xpop();
335  --*pnindex;
336  for (i=0, s = sec->child; i < index && s; s = s->sibling) {
337  ++i;
338  }
339  if (i != index || !s) {
340 if (nrn_inpython_) {
341  hoc_warning("SectionRef.child index too large for", secname(sec));
342  nrn_inpython_ = 2;
343  return NULL;
344 }else{
345  hoc_execerror("SectionRef.child index too large for", secname(sec));
346 }
347  }
348  }
349  return s;
350 }
351 
352 
353 
354 
355 extern void class2oc(const char *,
356  void *(*cons)(Object *),
357  void (*destruct)(void *),
358  Member_func *,
359  int (*checkpoint)(void **),
362 );
363 
364 
365 void SectionRef_reg(void) {
366  Symbol* s, *sr;
367 
368  class2oc("SectionRef", cons, destruct, members, nullptr, nullptr, nullptr);
369  /* now make the sec variable an actual SECTIONREF */
370  sr = hoc_lookup("SectionRef");
371  s = hoc_table_lookup("sec", sr->u.ctemplate->symtable);
372  s->type = SECTIONREF;
373  nrn_sec_sym = s;
374  s = hoc_table_lookup("parent", sr->u.ctemplate->symtable);
375  s->type = SECTIONREF;
376  nrn_parent_sym = s;
377  s = hoc_table_lookup("trueparent", sr->u.ctemplate->symtable);
378  s->type = SECTIONREF;
379  nrn_trueparent_sym = s;
380  s = hoc_table_lookup("root", sr->u.ctemplate->symtable);
381  s->type = SECTIONREF;
382  nrn_root_sym = s;
383  s = hoc_table_lookup("child", sr->u.ctemplate->symtable);
384  s->type = SECTIONREF;
385  nrn_child_sym = s;
386  s->arayinfo = (Arrayinfo*)emalloc(sizeof(Arrayinfo));;
387  s->arayinfo->refcount = 1;
388  s->arayinfo->a_varn = nullptr;
389  s->arayinfo->nsub = 1;
390  s->arayinfo->sub[0] = 0;
391 }
Symbol * nrn_sec_sym
Definition: secref.cpp:26
Definition: hocdec.h:84
#define Printf
Definition: model.h:252
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
struct Prop * prop
Definition: section.h:62
static double s_has_trueparent(void *v)
Definition: secref.cpp:250
#define assert(ex)
Definition: hocassrt.h:26
static double s_has_parent(void *v)
Definition: secref.cpp:240
static double s_cas(void *v)
Definition: secref.cpp:267
void * _pvoid
Definition: hocdec.h:186
#define hocSEC(q)
Definition: hoclist.h:66
int nrn_inpython_
Definition: hoc.cpp:37
Symbol * nrn_trueparent_sym
Definition: secref.cpp:27
if(status)
short type
Definition: model.h:58
struct Section * parentsec
Definition: section.h:42
int nsub
Definition: hocdec.h:70
struct Section * sibling
Definition: section.h:46
static hoc_Item ** sec2pitm(Section *sec)
Definition: secref.cpp:29
Symbol * hoc_lookup(const char *)
Symlist * symtable
Definition: hocdec.h:196
void * this_pointer
Definition: hocdec.h:231
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:84
Objectdata * hoc_top_level_data
Definition: hoc_oop.cpp:134
char * name
Definition: model.h:72
static double dummy
Definition: ocptrvector.cpp:27
#define v
Definition: md1redef.h:4
int i
Definition: hocdec.h:179
Arrayinfo * arayinfo
Definition: hocdec.h:222
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
Symlist * hoc_top_level_symlist
Definition: code2.cpp:662
int sub[1]
Definition: hocdec.h:72
int const size_t const size_t n
Definition: nrngsl.h:12
static void * cons(Object *ho)
Definition: secref.cpp:48
_CONST char * s
Definition: system.cpp:74
Symbol * nrn_parent_sym
Definition: secref.cpp:26
Objectdata * hoc_objectdata
Definition: hoc_oop.cpp:133
static double s_rename(void *v)
Definition: secref.cpp:85
Objectdata * dataspace
Definition: hocdec.h:230
void sec_free(hoc_Item *)
Definition: solve.cpp:508
Arrayinfo * arayinfo
Definition: hocdec.h:158
#define printf
Definition: mwprefix.h:26
HocStruct Object * obj
Definition: hocdec.h:182
int
Definition: nrnmusic.cpp:71
int hoc_arayinfo_install(Symbol *sp, int nsub)
Definition: hoc.cpp:583
const char * secname(Section *sec)
Definition: cabcode.cpp:1787
void hoc_warning(const char *, const char *)
#define PROP_PY_INDEX
Definition: section.h:211
double hoc_xpop(void)
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
int ivoc_list_count(Object *)
Definition: oclist.cpp:414
Section * nrn_secarg(int iarg)
Definition: seclist.cpp:50
int nrn_secref_nchild(Section *sec)
Definition: secref.cpp:223
size_t j
Definition: model.h:57
Symbol * nrn_root_sym
Definition: secref.cpp:26
Definition: section.h:213
char * name
Definition: init.cpp:16
int hoc_return_type_code
Definition: code.cpp:41
static double s_unname(void *v)
Definition: secref.cpp:67
char * emalloc(unsigned n)
Definition: list.cpp:189
void SectionRef_reg(void)
Definition: secref.cpp:365
int oboff
Definition: hocdec.h:131
int ifarg(int)
Definition: code.cpp:1562
struct Section * child
Definition: section.h:43
Datum * dparam
Definition: section.h:219
void section_ref(Section *)
Definition: solve.cpp:563
void hoc_pushx(double)
Symbol * sym
Definition: hocdec.h:178
static void destruct(void *v)
Definition: secref.cpp:54
void hoc_install_object_data_index(Symbol *sp)
Definition: hoc_oop.cpp:304
HocStruct hoc_Item ** psecitm
Definition: hocdec.h:220
HocStruct hoc_Item * itm
Definition: hocdec.h:184
Definition: hocdec.h:226
HocStruct cTemplate * ctemplate
Definition: hocdec.h:151
Symbol * hoc_table_lookup(const char *, Symlist *)
Definition: symbol.cpp:60
#define i
Definition: md1redef.h:12
void class2oc(const char *, void *(*cons)(Object *), void(*destruct)(void *), Member_func *, int(*checkpoint)(void **), Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1581
sec
Definition: solve.cpp:885
void hoc_freearay(Symbol *sp)
Definition: hoc.cpp:624
Section * nrn_trueparent(Section *sec)
Definition: cabcode.cpp:1676
union Symbol::@18 u
union Object::@54 u
static Member_func members[]
Definition: secref.cpp:280
void section_unref(Section *)
Definition: solve.cpp:552
Object * ivoc_list_item(Object *, int)
Definition: oclist.cpp:419
Object ** hoc_objgetarg(int)
Definition: code.cpp:1568
static double s_nchild(void *v)
Definition: secref.cpp:234
Section * chk_access(void)
Definition: cabcode.cpp:437
unsigned * a_varn
Definition: hocdec.h:69
Section * nrn_sectionref_steer(Section *sec, Symbol *sym, int *pnindex)
Definition: secref.cpp:296
return NULL
Definition: cabcode.cpp:461
short index
Definition: cabvars.h:11
static double s_exists(void *v)
Definition: secref.cpp:260
Symbol * nrn_child_sym
Definition: secref.cpp:26