NEURON
datapath.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <map>
3 #include <cstdio>
4 #include <InterViews/resource.h>
5 #include <OS/string.h>
6 #include <OS/list.h>
7 #include "hoclist.h"
8 #include <nrnpython_config.h>
9 #if HAVE_IV
10 #include "graph.h"
11 #endif
12 #include "datapath.h"
13 #include "ivocvect.h"
14 
15 #if !defined(CABLE)
16 // really belongs in vector.cpp but this is convenient since it will be
17 // present in ivoc but not in nrniv
18 void nrn_vecsim_add(void*, bool) {
19  printf("nrn_vecsym_add implemented in nrniv\n");
20 }
21 void nrn_vecsim_remove(void*) {
22  printf("nrn_vecsym_remove implemented in nrniv\n");
23 }
24 #if HAVE_IV
25 void graphLineRecDeleted(GraphLine*) {}
26 void Graph::simgraph() {}
29 #endif
30 // another hack so ivoc will have these names which nrniv gets elsewhere
32 void bbs_done() {}
33 void bbs_handle() {}
35 
36 #ifdef WIN32
37 void* dll_lookup(struct DLL*, const char*) {
38  return NULL;
39 }
40 struct DLL* dll_load(const char*) {
41  return NULL;
42 }
43 #endif
44 #endif
45 
46 #if CABLE
47 #include "nrnoc2iv.h"
48 #include "membfunc.h"
49 #else
50 #include "oc2iv.h"
51 #endif
52 
53 #include "parse.hpp"
57 
58 /*static*/ class PathValue {
59  public:
60  PathValue();
61  ~PathValue();
64  double original;
65  char* str;
66 };
68  path = NULL;
69  str = NULL;
70  sym = NULL;
71 }
73  if (path) {
74  delete path;
75  }
76 }
77 
78 using StringList = std::vector<char*>;
79 
81  private:
82  friend class HocDataPaths;
83  HocDataPathImpl(int, int);
85 
86  void search();
87  void found(double*, const char*, Symbol*);
88  void found(char**, const char*, Symbol*);
89  PathValue* found_v(void*, const char*, Symbol*);
90 
91  void search(Objectdata*, Symlist*);
92  void search_vectors();
93 #if CABLE
94  void search_pysec();
95  void search(Section*);
96  void search(Node*, double x);
97  void search(Point_process*, Symbol*);
98  void search(Prop*, double x);
99 #endif
100  private:
101  std::map<void*, PathValue*> table_;
105 };
106 
107 #define sentinal 123456789.e15
108 
110 
111 HocDataPaths::HocDataPaths(int size, int pathstyle) {
112  if (!sym_vec) {
114 #if CABLE
120 #endif
121  }
122  impl_ = new HocDataPathImpl(size, pathstyle);
123 }
124 
126  delete impl_;
127 }
128 
130  return impl_->pathstyle_;
131 }
132 
133 void HocDataPaths::append(double* pd) {
134  // printf("HocDataPaths::append\n");
135  if (pd && impl_->table_.find((void*) pd) == impl_->table_.end()) {
136  impl_->table_.emplace((void*) pd, new PathValue);
137  ++impl_->count_;
138  }
139 }
140 
142  // printf("HocDataPaths::search\n");
143  impl_->search();
144  if (impl_->count_ > impl_->found_so_far_) {
145  // printf("HocDataPaths:: didn't find paths to all the pointers\n");
146  // this has proved to be too often a false alarm since most panels are
147  // in boxes controlled by objects which have no reference but are
148  // deleted when the window is closed
149  }
150 }
151 
153  assert(impl_->pathstyle_ != 2);
154  // printf("HocDataPaths::retrieve\n");
155  const auto& it = impl_->table_.find((void*) pd);
156  if (it != impl_->table_.end()) {
157  return it->second->path;
158  }
159  return nullptr;
160 }
161 
163  // printf("HocDataPaths::retrieve\n");
164  const auto& it = impl_->table_.find((void*) pd);
165  if (it != impl_->table_.end()) {
166  return it->second->sym;
167  }
168  return nullptr;
169 }
170 
171 void HocDataPaths::append(char** pd) {
172  // printf("HocDataPaths::append\n");
173  if (*pd && impl_->table_.find((void*) pd) == impl_->table_.end()) {
174  PathValue* pv = new PathValue;
175  pv->str = *pd;
176  impl_->table_.emplace((void*) pd, pv);
177  ++impl_->count_;
178  }
179 }
180 
182  // printf("HocDataPaths::retrieve\n");
183  const auto& it = impl_->table_.find((void*) pd);
184  if (it != impl_->table_.end()) {
185  return it->second->path;
186  }
187  return nullptr;
188 }
189 
190 /*------------------------------*/
191 HocDataPathImpl::HocDataPathImpl(int size, int pathstyle) {
192  pathstyle_ = pathstyle;
193  size_ = size;
194  count_ = 0;
195  found_so_far_ = 0;
196 }
197 
199  for (auto& kv: table_) {
200  PathValue* pv = kv.second;
201  delete pv;
202  }
203 }
204 
206  found_so_far_ = 0;
207  for (auto& it: table_) {
208  PathValue* pv = it.second;
209  if (pv->str) {
210  char** pstr = (char**) it.first;
211  *pstr = nullptr;
212  } else {
213  double* pd = (double*) it.first;
214  pv->original = *pd;
215  *pd = sentinal;
216  }
217  }
218  if (pathstyle_ > 0) {
221  } else {
224  }
225 #if CABLE
226  if (found_so_far_ < count_) {
227  search_pysec();
228  }
229 #endif
230  if (found_so_far_ < count_) {
231  search_vectors();
232  }
233  for (auto& it: table_) {
234  PathValue* pv = it.second;
235  if (pv->str) {
236  char** pstr = (char**) it.first;
237  *pstr = pv->str;
238  } else {
239  double* pd = (double*) it.first;
240  *pd = pv->original;
241  }
242  }
243 }
244 
245 PathValue* HocDataPathImpl::found_v(void* v, const char* buf, Symbol* sym) {
246  PathValue* pv;
247  if (pathstyle_ != 2) {
248  char path[500];
249  CopyString cs("");
250  for (const auto& str: strlist_) {
251  sprintf(path, "%s%s.", cs.string(), str);
252  cs = path;
253  }
254  sprintf(path, "%s%s", cs.string(), buf);
255  const auto& it = table_.find(v);
256  if (it == table_.end()) {
257  hoc_warning("table lookup failed for pointer for-", path);
258  return nullptr;
259  }
260  pv = it->second;
261  if (!pv->path) {
262  pv->path = new CopyString(path);
263  pv->sym = sym;
264  ++found_so_far_;
265  }
266  // printf("HocDataPathImpl::found %s\n", path);
267  } else {
268  const auto& it = table_.find(v);
269  if (it == table_.end()) {
270  hoc_warning("table lookup failed for pointer for-", sym->name);
271  return nullptr;
272  }
273  pv = it->second;
274  if (!pv->sym) {
275  pv->sym = sym;
276  ++found_so_far_;
277  }
278  }
279  return pv;
280 }
281 
282 void HocDataPathImpl::found(double* pd, const char* buf, Symbol* sym) {
283  PathValue* pv = found_v((void*) pd, buf, sym);
284  if (pv) {
285  *pd = pv->original;
286  }
287 }
288 
289 void HocDataPathImpl::found(char** pstr, const char* buf, Symbol* sym) {
290  PathValue* pv = found_v((void*) pstr, buf, sym);
291  if (pv) {
292  *pstr = pv->str;
293  } else {
294  hoc_assign_str(pstr, "couldn't find");
295  }
296 }
297 
299  Symbol* sym;
300  int i, total;
301  char buf[200];
302  CopyString cs("");
303  if (sl)
304  for (sym = sl->first; sym; sym = sym->next) {
305  if (sym->cpublic != 2) {
306  switch (sym->type) {
307  case VAR: {
308  double* pd;
309  if (sym->subtype == NOTUSER) {
310  pd = object_pval(sym, od);
311  total = hoc_total_array_data(sym, od);
312  } else if (sym->subtype == USERDOUBLE) {
313  pd = sym->u.pval;
314  total = 1;
315  } else {
316  break;
317  }
318  for (i = 0; i < total; ++i) {
319  if (pd[i] == sentinal) {
320  sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od));
321  cs = buf;
322  found(pd + i, cs.string(), sym);
323  }
324  }
325  } break;
326  case STRING: {
327  char** pstr = object_pstr(sym, od);
328  if (*pstr == NULL) {
329  sprintf(buf, "%s", sym->name);
330  cs = buf;
331  found(pstr, cs.string(), sym);
332  }
333  } break;
334  case OBJECTVAR: {
335  if (pathstyle_ > 0) {
336  break;
337  }
338  Object** obp = object_pobj(sym, od);
339  total = hoc_total_array_data(sym, od);
340  for (i = 0; i < total; ++i)
341  if (obp[i] && !obp[i]->recurse) {
342  cTemplate* t = (obp[i])->ctemplate;
343  if (!t->constructor) {
344  // not the this pointer
345  if (obp[i]->u.dataspace != od) {
346  sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od));
347  cs = buf;
348  strlist_.push_back((char*) cs.string());
349  obp[i]->recurse = 1;
350  search(obp[i]->u.dataspace, obp[i]->ctemplate->symtable);
351  obp[i]->recurse = 0;
352  strlist_.pop_back();
353  }
354  } else {
355  /* point processes */
356 #if CABLE
357  if (t->is_point_) {
358  sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od));
359  cs = buf;
360  strlist_.push_back((char*) cs.string());
361  search((Point_process*) obp[i]->u.this_pointer, sym);
362  strlist_.pop_back();
363  }
364 #endif
365  /* seclists, object lists */
366  }
367  }
368  } break;
369 #if CABLE
370  case SECTION: {
371  total = hoc_total_array_data(sym, od);
372  for (i = 0; i < total; ++i) {
373  hoc_Item** pitm = object_psecitm(sym, od);
374  if (pitm[i]) {
375  sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od));
376  cs = buf;
377  strlist_.push_back((char*) cs.string());
378  search(hocSEC(pitm[i]));
379  strlist_.pop_back();
380  }
381  }
382  } break;
383 #endif
384  case TEMPLATE: {
385  cTemplate* t = sym->u.ctemplate;
386  hoc_Item* q;
387  ITERATE(q, t->olist) {
388  Object* obj = OBJ(q);
389  sprintf(buf, "%s[%d]", sym->name, obj->index);
390  cs = buf;
391  strlist_.push_back((char*) cs.string());
392  if (!t->constructor) {
393  search(obj->u.dataspace, t->symtable);
394  } else {
395 #if CABLE
396  if (t->is_point_) {
397  search((Point_process*) obj->u.this_pointer, sym);
398  }
399 #endif
400  }
401  strlist_.pop_back();
402  }
403  } break;
404  }
405  }
406  }
407 }
408 
410  char buf[200];
411  CopyString cs("");
413  hoc_Item* q;
414  ITERATE(q, t->olist) {
415  Object* obj = OBJ(q);
416  sprintf(buf, "%s[%d]", sym_vec->name, obj->index);
417  cs = buf;
418  strlist_.push_back((char*) cs.string());
419  Vect* vec = (Vect*) obj->u.this_pointer;
420  int size = vec->size();
421  double* pd = vector_vec(vec);
422  for (size_t i = 0; i < size; ++i) {
423  if (pd[i] == sentinal) {
424  sprintf(buf, "x[%zu]", i);
425  found(pd + i, buf, sym_vec);
426  }
427  }
428  strlist_.pop_back();
429  }
430 }
431 
432 #if CABLE
433 
434 void HocDataPathImpl::search_pysec() {
435 #if USE_PYTHON
436  CopyString cs("");
437  hoc_Item* qsec;
438  // ForAllSections(sec)
439  ITERATE(qsec, section_list) {
440  Section* sec = hocSEC(qsec);
441  if (sec->prop && sec->prop->dparam[PROP_PY_INDEX]._pvoid) {
442  cs = secname(sec);
443  strlist_.push_back((char*) cs.string());
444  search(sec);
445  strlist_.pop_back();
446  }
447  }
448 #endif
449 }
450 
452  if (sec->prop->dparam[2].val == sentinal) {
453  found(&sec->prop->dparam[2].val, "L", sym_L);
454  }
455  if (sec->prop->dparam[4].val == sentinal) {
456  found(&sec->prop->dparam[4].val, "rallbranch", sym_rallbranch);
457  }
458  if (sec->prop->dparam[7].val == sentinal) {
459  found(&sec->prop->dparam[7].val, "Ra", sym_Ra);
460  }
461  if (!sec->parentsec && sec->parentnode) {
462  search(sec->parentnode, sec->prop->dparam[1].val);
463  }
464  for (int i = 0; i < sec->nnode; ++i) {
465  search(sec->pnode[i], nrn_arc_position(sec, sec->pnode[i]));
466  }
467 }
468 void HocDataPathImpl::search(Node* nd, double x) {
469  char buf[100];
470  CopyString cs("");
471  if (NODEV(nd) == sentinal) {
472  sprintf(buf, "v(%g)", x);
473  found(&NODEV(nd), buf, sym_v);
474  }
475 
476 #if EXTRACELLULAR
477  if (nd->extnode) {
478  int i;
479  for (i = 0; i < nlayer; ++i) {
480  if (nd->extnode->v[i] == sentinal) {
481  if (i == 0) {
482  sprintf(buf, "vext(%g)", x);
483  } else {
484  sprintf(buf, "vext[%d](%g)", i, x);
485  }
486  found(&(nd->extnode->v[i]), buf, sym_vext);
487  }
488  }
489  }
490 #endif
491 
492  Prop* p;
493  for (p = nd->prop; p; p = p->next) {
494  if (!memb_func[p->type].is_point) {
495  search(p, x);
496  }
497  }
498 }
499 
501  if (pp->prop) {
502  search(pp->prop, -1);
503  }
504 }
505 
506 void HocDataPathImpl::search(Prop* prop, double x) {
507  char buf[200];
508  int type = prop->type;
509  Symbol* sym = memb_func[type].sym;
510  Symbol* psym;
511  double* pd;
512  int i, imax, k = 0, ir, kmax = sym->s_varn;
513 
514  for (k = 0; k < kmax; ++k) {
515  psym = sym->u.ppsym[k];
516  if (psym->subtype == NRNPOINTER) {
517  continue;
518  }
519  ir = psym->u.rng.index;
520  if (memb_func[type].hoc_mech) {
521  pd = prop->ob->u.dataspace[ir].pval;
522  } else {
523  pd = prop->param + ir;
524  }
525  imax = hoc_total_array_data(psym, 0);
526  for (i = 0; i < imax; ++i) {
527  if (pd[i] == sentinal) {
528  if (x < 0) {
529  sprintf(buf, "%s%s", psym->name, hoc_araystr(psym, i, 0));
530  } else {
531  sprintf(buf, "%s%s(%g)", psym->name, hoc_araystr(psym, i, 0), x);
532  }
533  found(pd + i, buf, psym);
534  }
535  }
536  }
537 }
538 
539 #endif
#define CopyString
Definition: _defines.h:2
const char * secname(Section *sec)
Definition: cabcode.cpp:1776
double nrn_arc_position(Section *sec, Node *node)
Definition: cabcode.cpp:1867
Memb_func * memb_func
Definition: init.cpp:123
short type
Definition: cabvars.h:9
void simgraph()
void record_uninstall()
void record_install()
HocDataPathImpl(int, int)
Definition: datapath.cpp:191
PathValue * found_v(void *, const char *, Symbol *)
Definition: datapath.cpp:245
std::map< void *, PathValue * > table_
Definition: datapath.cpp:101
void search_vectors()
Definition: datapath.cpp:409
StringList strlist_
Definition: datapath.cpp:102
void found(double *, const char *, Symbol *)
Definition: datapath.cpp:282
String * retrieve(double *)
Definition: datapath.cpp:152
Symbol * retrieve_sym(double *)
Definition: datapath.cpp:162
virtual ~HocDataPaths()
Definition: datapath.cpp:125
HocDataPathImpl * impl_
Definition: datapath.h:24
void append(double *)
Definition: datapath.cpp:133
HocDataPaths(int=1000, int pathstyle=0)
Definition: datapath.cpp:111
void search()
Definition: datapath.cpp:141
char * str
Definition: datapath.cpp:65
CopyString * path
Definition: datapath.cpp:62
~PathValue()
Definition: datapath.cpp:72
Symbol * sym
Definition: datapath.cpp:63
double original
Definition: datapath.cpp:64
Definition: string.h:34
const char * string() const
Definition: string.h:139
Symbol * hoc_table_lookup(const char *, Symlist *)
Definition: symbol.cpp:61
double t
Definition: cvodeobj.cpp:59
sprintf(buf, " if (secondorder) {\n" " int _i;\n" " for (_i = 0; _i < %d; ++_i) {\n" " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n" " }}\n", numeqn, listnum, listnum)
char buf[512]
Definition: init.cpp:13
size_t hoc_total_array_data(Symbol *s, Objectdata *obd)
Definition: hoc_oop.cpp:94
void hoc_assign_str(char **cpp, const char *buf)
Definition: code.cpp:2350
void hoc_warning(const char *, const char *)
void bbs_done()
Definition: datapath.cpp:32
char * hoc_araystr(Symbol *sym, int index, Objectdata *obd)
Definition: code.cpp:2367
#define assert(ex)
Definition: hocassrt.h:32
#define USERDOUBLE
Definition: hocdec.h:93
#define NOTUSER
Definition: hocdec.h:91
#define hocSEC(q)
Definition: hoclist.h:66
#define OBJ(q)
Definition: hoclist.h:67
int bbs_poll_
Definition: datapath.cpp:31
void nrnbbs_context_wait()
Definition: datapath.cpp:34
#define sentinal
Definition: datapath.cpp:107
static Symbol * sym_L
Definition: datapath.cpp:109
static Symbol * sym_Ra
Definition: datapath.cpp:109
static Symbol * sym_vext
Definition: datapath.cpp:109
static Symbol * sym_v
Definition: datapath.cpp:109
static Symbol * sym_rallbranch
Definition: datapath.cpp:109
void nrn_vecsim_remove(void *)
Definition: datapath.cpp:21
static Symbol * sym_vec
Definition: datapath.cpp:109
Symlist * hoc_top_level_symlist
Definition: code2.cpp:690
std::vector< char * > StringList
Definition: datapath.cpp:78
void nrn_vecsim_add(void *, bool)
Definition: datapath.cpp:18
void bbs_handle()
Definition: datapath.cpp:33
Objectdata * hoc_top_level_data
Definition: hoc_oop.cpp:124
Symlist * hoc_built_in_symlist
Definition: ivocmac.cpp:76
double * vector_vec(Vect *v)
Definition: ivocvect.cpp:328
#define Vect
Definition: ivocvect.h:14
#define v
Definition: md1redef.h:4
#define sec
Definition: md1redef.h:13
#define i
Definition: md1redef.h:12
#define prop
Definition: md1redef.h:29
#define ITERATE(itm, lst)
Definition: model.h:25
#define printf
Definition: mwprefix.h:26
#define NRNPOINTER
Definition: nocpout.cpp:100
size_t q
size_t p
hoc_List * section_list
Definition: init.cpp:102
static philox4x32_key_t k
Definition: nrnran123.cpp:11
char ** object_pstr(Symbol *sym, Objectdata *od)
Definition: oc2iv.h:74
Object ** object_pobj(Symbol *sym, Objectdata *od)
Definition: oc2iv.h:77
hoc_Item ** object_psecitm(Symbol *sym, Objectdata *od)
Definition: oc2iv.h:80
double * object_pval(Symbol *sym, Objectdata *od)
Definition: oc2iv.h:68
#define STRING
Definition: bbslsrv.cpp:9
static Symbol * pv[4]
Definition: partial.cpp:80
sl
Definition: seclist.cpp:181
#define PROP_PY_INDEX
Definition: section.h:212
#define NODEV(n)
Definition: section.h:115
#define nlayer
Definition: section.h:188
#define NULL
Definition: sptree.h:16
double * v
Definition: section.h:196
int is_point
Definition: membfunc.h:53
Symbol * sym
Definition: membfunc.h:38
Definition: section.h:133
struct Extnode * extnode
Definition: section.h:161
struct Prop * prop
Definition: section.h:152
Definition: hocdec.h:227
void * this_pointer
Definition: hocdec.h:232
Objectdata * dataspace
Definition: hocdec.h:231
int index
Definition: hocdec.h:229
short recurse
Definition: hocdec.h:244
union Object::@39 u
Prop * prop
Definition: section.h:265
Definition: section.h:214
Definition: model.h:57
HocStruct Symbol * sym
Definition: hocdec.h:156
short cpublic
Note: public is a reserved keyword.
Definition: hocdec.h:125
HocStruct Symbol ** ppsym
Definition: hocdec.h:150
short type
Definition: model.h:58
struct Symbol::@37::@38 rng
long subtype
Definition: model.h:59
HocStruct Symbol * next
Definition: hocdec.h:162
union Symbol::@18 u
unsigned s_varn
Definition: hocdec.h:158
char * name
Definition: model.h:72
char * str
Definition: model.h:63
double * pval
Definition: hocdec.h:137
HocStruct cTemplate * ctemplate
Definition: hocdec.h:152
Definition: hocdec.h:84