NEURON
symdir.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <stdlib.h>
3 #include <InterViews/resource.h>
4 #include <stdio.h>
5 #include "ocobserv.h"
6 #include "utils/enumerate.h"
7 
8 #include "nrniv_mf.h"
9 #include "nrnoc2iv.h"
10 
11 #include "membfunc.h"
12 #include "parse.hpp"
13 #include "hoclist.h"
14 extern Symlist* hoc_symlist;
17 #include "string.h"
18 #include "symdir.h"
19 
20 #include "nrnsymdiritem.h"
21 
22 const char* concat(const char* s1, const char* s2) {
23  static char* tmp = 0;
24  int l1 = strlen(s1);
25  int l2 = strlen(s2);
26  if (tmp) {
27  delete[] tmp;
28  }
29  tmp = new char[l1 + l2 + 1];
30  std::snprintf(tmp, l1 + l2 + 1, "%s%s", s1, s2);
31  return (const char*) tmp;
32 }
33 
34 class SymDirectoryImpl: public Observer {
35  public:
36  void disconnect(Observable*); // watching an object
37  void update(Observable*); // watching a template
38  private:
39  friend class SymDirectory;
43 
44  std::vector<SymbolItem*> symbol_lists_;
45  std::string path_;
46 
47  void load(int type);
48  void load(int type, Symlist*);
49  // void load(Symbol*);
50  void load_section();
51  void load_object();
52  void load_aliases();
53  void load_template();
54  void load_mechanism(const Prop*, int, const char*);
55  void append(Symbol* sym, Objectdata* od, Object* o = NULL);
56  void append(Object*);
57  void un_append(Object*);
58  void make_pathname(const char*, const char*, const char*, int s = '.');
59  void sort();
60 };
61 
62 static int compare_entries(const SymbolItem* e1, const SymbolItem* e2) {
63  int i = strcmp(e1->name().c_str(), e2->name().c_str());
64  if (i == 0) {
65  return e1->array_index() > e2->array_index();
66  }
67  return i > 0;
68 };
69 
71  std::sort(symbol_lists_.begin(), symbol_lists_.end(), compare_entries);
72 }
73 
74 // SymDirectory
75 SymDirectory::SymDirectory(const std::string& parent_path,
76  Object* parent_obj,
77  Symbol* sym,
78  int array_index,
79  int) {
80  impl_ = new SymDirectoryImpl();
81  impl_->sec_ = NULL;
82  impl_->obj_ = NULL;
83  impl_->t_ = NULL;
84  Objectdata* obd;
85  if (parent_obj) {
86  obd = parent_obj->u.dataspace;
87  } else {
88  // obd = hoc_objectdata;
89  obd = hoc_top_level_data;
90  }
91  int suffix = '.';
92  if (sym->type == TEMPLATE) {
93  suffix = '_';
94  }
95  impl_->make_pathname(parent_path.c_str(),
96  sym->name,
97  hoc_araystr(sym, array_index, obd),
98  suffix);
99  switch (sym->type) {
100  case SECTION:
101  if (object_psecitm(sym, obd)[array_index]) {
102  impl_->sec_ = hocSEC(object_psecitm(sym, obd)[array_index]);
104  impl_->load_section();
105  }
106  break;
107  case OBJECTVAR:
108  impl_->obj_ = object_pobj(sym, obd)[array_index];
109  if (impl_->obj_) {
111  impl_->load_object();
112  }
113  break;
114  case TEMPLATE:
115  impl_->t_ = sym->u.ctemplate;
117  impl_->load_template();
118  break;
119  case OBJECTALIAS:
120  impl_->obj_ = sym->u.object_;
121  if (impl_->obj_) {
123  impl_->load_object();
124  }
125  break;
126  default:
127  hoc_execerror("Don't know how to make a directory out of", path().c_str());
128  break;
129  }
130  impl_->sort();
131 }
133  impl_ = new SymDirectoryImpl();
134  impl_->sec_ = NULL;
135  impl_->obj_ = ob;
136  impl_->t_ = NULL;
137  int suffix = '.';
138  impl_->make_pathname("", hoc_object_name(ob), "", '.');
140  impl_->load_object();
141  impl_->sort();
142 }
143 
144 bool SymDirectory::is_pysec(int index) const {
145  SymbolItem* si = impl_->symbol_lists_.at(index);
146  return si->pysec_ ? true : false;
147 }
149  SymbolItem* si = impl_->symbol_lists_.at(index);
150  SymDirectory* d = new SymDirectory();
151  if (si->pysec_type_ == PYSECOBJ) {
153  } else {
154  d->impl_->sec_ = (Section*) si->pysec_;
155  section_ref(d->impl_->sec_);
156  d->impl_->load_section();
157  }
158  d->impl_->path_ = concat(path().c_str(), si->name().c_str());
159  d->impl_->path_ = concat(d->impl_->path_.c_str(), ".");
160  d->impl_->sort();
161  return d;
162 }
163 
165  impl_ = new SymDirectoryImpl();
166  impl_->sec_ = NULL;
167  impl_->obj_ = NULL;
168  impl_->t_ = NULL;
169 }
170 
172  ParseTopLevel ptl;
173  ptl.save();
174  impl_ = new SymDirectoryImpl();
175  impl_->sec_ = NULL;
176  impl_->obj_ = NULL;
177  impl_->t_ = NULL;
178  impl_->path_ = "";
179  impl_->load(type);
180  impl_->sort();
181  ptl.restore();
182 }
183 
185  for (auto& item: impl_->symbol_lists_) {
186  delete item;
187  }
188  impl_->symbol_lists_.clear();
189  impl_->symbol_lists_.shrink_to_fit();
190  if (impl_->obj_) {
192  }
193  if (impl_->t_) {
195  }
196  if (impl_->sec_) {
198  }
199  delete impl_;
200 }
202  for (auto& item: symbol_lists_) {
203  delete item;
204  }
205  symbol_lists_.clear();
206  symbol_lists_.shrink_to_fit();
207  obj_ = NULL;
208 }
209 
211  if (t_) { // watching a template
212  ClassObservable* co = (ClassObservable*) obs;
213  Object* ob = co->object();
214  switch (co->message()) {
216  un_append(ob);
217  break;
219  append(ob);
220  break;
221  }
222  }
223 }
225  Object* ob = object();
226  Symbol* sym = symbol(index);
227  // printf("::variable index=%d sym=%s ob=%s\n", index,
228  // sym?sym->name:"SYM0",hoc_object_name(ob));
229  if (sym)
230  switch (sym->type) {
231  case VAR:
232  if (ob && ob->ctemplate->constructor) {
233  extern double* ivoc_vector_ptr(Object*, int);
234  if (is_obj_type(ob, "Vector")) {
235  return ivoc_vector_ptr(ob, index);
236  } else {
237  return NULL;
238  }
239  } else {
240  Objectdata* od;
241  if (ob) {
242  od = ob->u.dataspace;
243  } else if (sym->subtype == USERDOUBLE) {
244  return sym->u.pval + array_index(index);
245  } else {
246  od = hoc_objectdata;
247  }
248  return od[sym->u.oboff].pval + array_index(index);
249  }
250  case RANGEVAR:
251  if (ob && ob->ctemplate->is_point_) {
252  return static_cast<double*>(point_process_pointer(
253  (Point_process*) ob->u.this_pointer, sym, array_index(index)));
254  }
255  break;
256  }
257  else {
258  char buf[256], *cp;
259  Sprintf(buf, "%s%s", path().c_str(), name(index).c_str());
260  if (whole_vector(index)) { // rangevar case for [all]
261  // replace [all] with [0]
262  cp = strstr(buf, "[all]");
263  assert(cp);
264  *(++cp) = '0';
265  for (++cp; cp[2]; ++cp) {
266  *cp = cp[2];
267  }
268  *cp = '\0';
269  }
270  return hoc_val_pointer(buf);
271  }
272  return NULL;
273 }
274 
276  return impl_->symbol_lists_.at(index)->whole_vector();
277 }
278 
279 const std::string& SymDirectory::path() const {
280  return impl_->path_;
281 }
282 int SymDirectory::count() const {
283  return impl_->symbol_lists_.size();
284 }
285 const std::string& SymDirectory::name(int index) const {
286  return impl_->symbol_lists_.at(index)->name();
287 }
288 int SymDirectory::array_index(int i) const {
289  return impl_->symbol_lists_.at(i)->array_index();
290 }
291 
292 int SymDirectory::index(const std::string& name) const {
293  for (const auto&& [i, symbol]: enumerate(impl_->symbol_lists_)) {
294  if (name == symbol->name()) {
295  return i;
296  }
297  }
298  return -1;
299 }
300 void SymDirectory::whole_name(int index, std::string& s) const {
301  auto s1 = impl_->path_;
302  auto s2 = name(index);
303  s = s1 + s2;
304 }
306  return impl_->symbol_lists_.at(index)->is_directory();
307 }
308 bool SymDirectory::match(const std::string&, const std::string&) {
309  return true;
310 }
312  return impl_->symbol_lists_.at(index)->symbol();
313 }
315  return impl_->obj_;
316 }
317 
319  return impl_->symbol_lists_.at(index)->object();
320 }
321 
322 // SymbolItem
323 SymbolItem::SymbolItem(const char* n, int whole_array) {
324  symbol_ = NULL;
325  index_ = 0;
326  ob_ = NULL;
327  name_ = n;
328  whole_array_ = whole_array;
329  pysec_type_ = 0;
330  pysec_ = NULL;
331 }
332 SymbolItem::SymbolItem(Symbol* sym, Objectdata* od, int index, int whole_array) {
333  symbol_ = sym;
334  ob_ = NULL;
335  whole_array_ = whole_array;
336  if (is_array(*sym)) {
337  if (whole_array_) {
338  name_ = concat(sym->name, "[all]");
339  } else {
340  if (od) {
341  name_ = concat(sym->name, hoc_araystr(sym, index, od));
342  } else {
343  char buf[50];
344  Sprintf(buf, "[%d]", index);
345  name_ = concat(sym->name, buf);
346  }
347  }
348  } else {
349  name_ = sym->name;
350  }
351  index_ = index;
352  pysec_type_ = 0;
353  pysec_ = NULL;
354 }
355 
357  return whole_array_;
358 }
359 
361  symbol_ = NULL;
362  index_ = 0;
363  ob_ = ob;
364  char buf[10];
365  Sprintf(buf, "%d", ob->index);
366  name_ = buf;
367  pysec_type_ = 0;
368  pysec_ = NULL;
369 }
370 
372  ob_ = NULL;
373  name_ = "Deleted";
374 }
375 
377 
379  if (symbol_)
380  switch (symbol_->type) {
381  case SECTION:
382  case OBJECTVAR:
383  case TEMPLATE:
384  case OBJECTALIAS:
385  // case SECTIONLIST:
386  // case MECHANISM:
387  return true;
388  }
389  if (ob_) {
390  return true;
391  }
392  if (pysec_) {
393  return true;
394  }
395  return false;
396 }
397 
398 void SymDirectoryImpl::make_pathname(const char* parent,
399  const char* name,
400  const char* index,
401  int suffix) {
402  char buf[200];
403  Sprintf(buf, "%s%s%s%c", parent, name, index, suffix);
404  path_ = buf;
405 }
406 
407 
409  switch (type) {
410  case TEMPLATE:
413  break;
414  case RANGEVAR:
416  break;
417  case PYSEC:
418  path_ = "_pysec.";
420  break;
421  default:
424  Objectdata* sav = hoc_objectdata;
427  hoc_objectdata = sav;
428  }
431  }
432  }
433 }
434 
436  for (Symbol* sym = sl->first; sym; sym = sym->next) {
437  if (type == -1) {
438  switch (sym->type) {
439  case SECTION:
440  case OBJECTVAR:
441  case VAR:
442  case TEMPLATE:
443  append(sym, hoc_objectdata);
444  }
445  } else if (sym->type == type) {
446  append(sym, hoc_objectdata);
447  }
448  }
449 }
450 
452  Symlist* sl = obj_->ctemplate->symtable;
453  Objectdata* od;
454  if (obj_->ctemplate->constructor) {
455  od = NULL;
456  } else {
457  od = obj_->u.dataspace;
458  }
459  if (obj_->aliases) {
460  load_aliases();
461  }
462  if (sl)
463  for (Symbol* s = sl->first; s; s = s->next) {
464  if (s->cpublic) {
465  append(s, od, obj_);
466  }
467  }
468 }
469 
472  if (!a)
473  return;
474  for (const auto& [_, s]: a->symtab_) {
475  append(s, nullptr, obj_);
476  }
477 }
478 
480  hoc_Item* q;
481  ITERATE(q, t_->olist) {
482  append(OBJ(q));
483  }
484 }
485 
487  char xarg[20];
488  char buf[100];
489  Section* sec = sec_;
490  int n = sec->nnode;
491 
492  int i = 0;
493  double x = nrn_arc_position(sec, sec->pnode[0]);
494  Sprintf(xarg, "( %g )", x);
495  Sprintf(buf, "v%s", xarg);
496  symbol_lists_.push_back(new SymbolItem(buf));
497  nrn_pushsec(sec);
498  Node* nd = sec->pnode[i];
499  for (const Prop* p = nd->prop; p; p = p->next) {
500  load_mechanism(p, 0, xarg);
501  }
502  nrn_popsec();
503 }
504 
505 void SymDirectoryImpl::load_mechanism(const Prop* p, int vartype, const char* xarg) {
506  int type = p->_type;
507  if (memb_func[type].is_point) {
508  return;
509  }
510  char buf[200];
511  Symbol* msym = memb_func[type].sym;
512  int cnt = msym->s_varn;
513  for (int i = 0; i < cnt; ++i) {
514  const Symbol* sym = msym->u.ppsym[i];
515  if (nrn_vartype(sym) == vartype || vartype == 0) {
516  if (is_array(*sym)) {
517  int n = hoc_total_array_data(sym, 0);
518  if (n > 5) {
519  Sprintf(buf, "%s[all]%s", sym->name, xarg);
520  symbol_lists_.push_back(new SymbolItem(buf, n));
521  }
522  Sprintf(buf, "%s[%d]%s", sym->name, 0, xarg);
523  symbol_lists_.push_back(new SymbolItem(buf));
524  Sprintf(buf, "%s[%d]%s", sym->name, n - 1, xarg);
525  symbol_lists_.push_back(new SymbolItem(buf));
526  } else {
527  Sprintf(buf, "%s%s", sym->name, xarg);
528  symbol_lists_.push_back(new SymbolItem(buf));
529  }
530  }
531  }
532 }
533 
535  if (is_array(*sym)) {
536  int i, n = 1;
537  if (od) {
538  n = hoc_total_array_data(sym, od);
539  } else { // Vector
540  if (is_obj_type(o, "Vector")) {
541  extern int ivoc_vector_size(Object*);
542  n = ivoc_vector_size(o);
543  }
544  }
545  if (n > 5 && sym->type == VAR) {
546  symbol_lists_.push_back(new SymbolItem(sym, od, 0, n));
547  }
548  for (i = 0; i < n; ++i) {
549  symbol_lists_.push_back(new SymbolItem(sym, od, i));
550  if (i > 5) {
551  break;
552  }
553  }
554  if (i < n - 1) {
555  symbol_lists_.push_back(new SymbolItem(sym, od, n - 1));
556  }
557  } else {
558  symbol_lists_.push_back(new SymbolItem(sym, od, 0));
559  }
560 }
561 
563  symbol_lists_.push_back(new SymbolItem(ob));
564 }
566  for (auto& symbol: symbol_lists_) {
567  if (symbol->object() == ob) {
568  symbol->no_object();
569  break;
570  }
571  }
572 }
void nrn_pushsec(Section *sec)
Definition: cabcode.cpp:130
double nrn_arc_position(Section *sec, Node *node)
Definition: cabcode.cpp:1755
void nrn_popsec(void)
Definition: cabcode.cpp:154
static void Detach(cTemplate *, Observer *)
Definition: ocobserv.cpp:54
static void Attach(cTemplate *, Observer *)
Definition: ocobserv.cpp:46
int message()
Definition: ocobserv.h:47
Object * object()
Definition: ocobserv.h:44
std::map< std::string, Symbol * > symtab_
Definition: symdir.h:21
static void Detach(Object *, Observer *)
Definition: ocobserv.cpp:23
static void Attach(Object *, Observer *)
Definition: ocobserv.cpp:16
void save()
Definition: oc2iv.cpp:53
void restore()
Definition: oc2iv.cpp:71
virtual int count() const
Definition: symdir.cpp:282
Object * obj(int index)
Definition: symdir.cpp:318
int array_index(int index) const
Definition: symdir.cpp:288
virtual ~SymDirectory()
Definition: symdir.cpp:184
virtual double * variable(int index)
Definition: symdir.cpp:224
virtual bool is_pysec(int index) const
Definition: symdir.cpp:144
virtual int whole_vector(int index)
Definition: symdir.cpp:275
virtual int index(const std::string &) const
Definition: symdir.cpp:292
static bool match(const std::string &name, const std::string &pattern)
Definition: symdir.cpp:308
Symbol * symbol(int index) const
Definition: symdir.cpp:311
virtual void whole_name(int index, std::string &) const
Definition: symdir.cpp:300
Object * object() const
Definition: symdir.cpp:314
SymDirectory * newsymdir(int index)
Definition: symdir.cpp:148
SymDirectoryImpl * impl_
Definition: symdir.h:56
virtual const std::string & name(int index) const
Definition: symdir.cpp:285
virtual const std::string & path() const
Definition: symdir.cpp:279
virtual bool is_directory(int index) const
Definition: symdir.cpp:305
void load_template()
Definition: symdir.cpp:479
void load(int type)
Definition: symdir.cpp:408
Section * sec_
Definition: symdir.cpp:40
void load_mechanism(const Prop *, int, const char *)
Definition: symdir.cpp:505
void disconnect(Observable *)
Definition: symdir.cpp:201
void load_object()
Definition: symdir.cpp:451
std::vector< SymbolItem * > symbol_lists_
Definition: symdir.cpp:44
void un_append(Object *)
Definition: symdir.cpp:565
Object * obj_
Definition: symdir.cpp:41
void load_aliases()
Definition: symdir.cpp:470
void update(Observable *)
Definition: symdir.cpp:210
void load_section()
Definition: symdir.cpp:486
void make_pathname(const char *, const char *, const char *, int s='.')
Definition: symdir.cpp:398
void append(Symbol *sym, Objectdata *od, Object *o=NULL)
Definition: symdir.cpp:534
std::string path_
Definition: symdir.cpp:45
cTemplate * t_
Definition: symdir.cpp:42
int whole_vector()
Definition: symdir.cpp:356
~SymbolItem()
Definition: symdir.cpp:376
Symbol * symbol_
Definition: nrnsymdiritem.h:30
Object * ob_
Definition: nrnsymdiritem.h:32
std::string name_
Definition: nrnsymdiritem.h:29
int whole_array_
Definition: nrnsymdiritem.h:33
bool is_directory() const
Definition: symdir.cpp:378
int array_index() const
Definition: nrnsymdiritem.h:22
SymbolItem(const char *, int whole_array=0)
Definition: symdir.cpp:323
void * pysec_
Definition: nrnsymdiritem.h:27
void no_object()
Definition: symdir.cpp:371
const std::string & name() const
Definition: nrnsymdiritem.h:18
#define cnt
Definition: tqueue.hpp:44
#define sec
Definition: md1redef.h:20
#define i
Definition: md1redef.h:19
constexpr auto enumerate(T &&iterable)
Definition: enumerate.h:90
char buf[512]
Definition: init.cpp:13
size_t hoc_total_array_data(const Symbol *s, Objectdata *obd)
Definition: hoc_oop.cpp:95
Objectdata * hoc_objectdata
Definition: hoc_oop.cpp:122
double * hoc_val_pointer(const char *s)
Definition: code2.cpp:728
int is_obj_type(Object *obj, const char *type_name)
Definition: hoc_oop.cpp:2110
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:73
char * hoc_araystr(Symbol *sym, int index, Objectdata *obd)
Definition: code.cpp:2281
#define assert(ex)
Definition: hocassrt.h:24
#define OBJECTALIAS
Definition: hocdec.h:94
#define USERDOUBLE
Definition: hocdec.h:84
bool is_array(const Symbol &sym)
Definition: hocdec.h:136
#define hocSEC(q)
Definition: hoclist.h:87
#define OBJ(q)
Definition: hoclist.h:88
double * ivoc_vector_ptr(Object *o, int index)
Definition: ivocvect.cpp:3843
int ivoc_vector_size(Object *o)
Definition: ivocvect.cpp:3838
#define ITERATE(itm, lst)
Definition: model.h:18
const char * name
Definition: init.cpp:16
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.
Definition: wrap_sprintf.h:14
if(ncell==0)
Definition: cellorder.cpp:785
static char suffix[256]
Definition: nocpout.cpp:135
void section_ref(Section *)
Definition: solve.cpp:520
void section_unref(Section *)
Definition: solve.cpp:509
int const size_t const size_t n
Definition: nrngsl.h:10
size_t q
size_t p
s
Definition: multisend.cpp:521
neuron::container::data_handle< double > point_process_pointer(Point_process *, Symbol *, int)
Definition: point.cpp:239
short index
Definition: cabvars.h:11
std::vector< Memb_func > memb_func
Definition: init.cpp:145
short type
Definition: cabvars.h:10
int nrn_vartype(const Symbol *sym)
Definition: eion.cpp:503
void nrn_symdir_load_pysec(std::vector< SymbolItem * > &sl, void *)
#define xarg(i)
Object ** object_pobj(Symbol *sym, Objectdata *od)
Definition: oc2iv.h:79
hoc_Item ** object_psecitm(Symbol *sym, Objectdata *od)
Definition: oc2iv.h:82
#define NULL
Definition: spdefs.h:105
Definition: section.h:105
Prop * prop
Definition: section.h:190
Definition: hocdec.h:173
void * aliases
Definition: hocdec.h:181
void * this_pointer
Definition: hocdec.h:178
Objectdata * dataspace
Definition: hocdec.h:177
int index
Definition: hocdec.h:175
cTemplate * ctemplate
Definition: hocdec.h:180
union Object::@47 u
A point process is computed just like regular mechanisms.
Definition: section_fwd.hpp:77
Definition: section.h:231
Definition: model.h:47
Symbol * next
Definition: hocdec.h:133
union Symbol::@28 u
Symbol ** ppsym
Definition: hocdec.h:125
Object * object_
Definition: hocdec.h:113
short type
Definition: model.h:48
long subtype
Definition: model.h:49
cTemplate * ctemplate
Definition: hocdec.h:126
unsigned s_varn
Definition: hocdec.h:129
char * name
Definition: model.h:61
double * pval
Definition: hocdec.h:112
int oboff
Definition: hocdec.h:111
Definition: hocdec.h:75
Symbol * first
Definition: hocdec.h:76
Symlist * symtable
Definition: hocdec.h:148
hoc_List * olist
Definition: hocdec.h:155
void *(* constructor)(struct Object *)
Definition: hocdec.h:158
int is_point_
Definition: hocdec.h:150
static int compare_entries(const SymbolItem *e1, const SymbolItem *e2)
Definition: symdir.cpp:62
const char * concat(const char *s1, const char *s2)
Definition: symdir.cpp:22
Symlist * hoc_top_level_symlist
Definition: symdir.cpp:16
Symlist * hoc_symlist
Definition: symbol.cpp:34
Objectdata * hoc_top_level_data
Definition: hoc_oop.cpp:123
Symlist * hoc_built_in_symlist
Definition: symbol.cpp:28
double * pval
Definition: hocdec.h:164