NEURON
pysecname2sec.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 #include <stdio.h>
4 #include <hocparse.h>
5 #include <nrnpython_config.h>
6 
7 #include <parse.hpp>
8 
9 #include <nrnoc2iv.h>
10 
11 #include "nrnsymdiritem.h"
12 
13 #include <string>
14 #include <map>
15 
16 static bool activated = false; // true on first use of hoc __pysec.
17 
19 typedef std::pair<CorStype, void*> CellorSec;
20 typedef std::map<const std::string, CellorSec > Name2CellorSec;
22 
23 #define hoc_acterror(a,b) printf("%s %s\n", a, b)
24 
25 static void activate() {
26 #if USE_PYTHON
27  if (!activated) {
28  //printf("first activation\n");
29  activated = true;
30  hoc_Item* qsec;
32  if (sec->prop && sec->prop->dparam[PROP_PY_INDEX]._pvoid) {
34  }
35  }
36  }
37 #endif
38 }
39 
40 Section* nrnpy_pysecname2sec(const char* name) { // could be Cell part or Sec
41  activate();
42  std::string n(name);
43  if (nrn_parsing_pysec_ == (void*)1) {
44  Name2CellorSec::iterator search = n2cs.find(n);
45  if (search != n2cs.end()) {
46  if (search->second.first == SECTYPE) {
47  nrn_parsing_pysec_ = NULL; /* done */
48  return (Section*)search->second.second;
49  }else if (search->second.first == CELLTYPE) {
50  nrn_parsing_pysec_ = search->second.second;
51  }else if (search->second.first == OVERLOADCOUNT) {
53  hoc_acterror(name, " is an overloaded first part name for multiple sections created in python");
54  }
55  } else {
57  hoc_acterror(name, " is not a valid first part name for section created in python");
58  }
59  } else {
61  Name2CellorSec::iterator search = n2s->find(n);
62  if (search != n2s->end()) {
63  if (search->second.first == OVERLOADCOUNT) {
65  hoc_acterror(name, " is an overloaded second part name for multiple sections created in python");
66  }
67  nrn_parsing_pysec_ = NULL; /* done */
68  assert(search->second.first == SECTYPE);
69  return (Section*)search->second.second;
70  } else {
72  hoc_acterror(name, " is not a valid last part name for section created in python");
73  }
74  }
75  return NULL;
76 }
77 
78 // Want to add a Section to a cell but one may already be there or
79 // already be overloaded.
80 static void n2s_add(Name2CellorSec& n2s, std::string n, Section* sec) {
81  Name2CellorSec::iterator search = n2s.find(n);
82  if (search == n2s.end()) {
83  n2s[n] = CellorSec(SECTYPE, sec);
84  }else{
85  CellorSec& cs = search->second;
86  if (cs.first == SECTYPE) {
87  cs.first = OVERLOADCOUNT;
88  cs.second = (void*)2;
89  }else if (cs.first == OVERLOADCOUNT) {
90  cs.second = (void*)((size_t)cs.second + 1);
91  }
92  }
93 }
94 
95 // Want to add a Section to top level but name may already exist. If so
96 // already a Section -- overload 2
97 // already overloaded section -- overload increase by 1
98 // already a cell -- no longer usable, becomes NONETYPE
99 // already NONETYPE -- nothing to do
100 static void n2cs_add_sec(Name2CellorSec& n2cs, std::string sname, Section* sec) {
101  //printf("n2cs_add_sec %s section=%p\n", sname.c_str(), sec);
102  Name2CellorSec::iterator search = n2cs.find(sname);
103  if (search == n2cs.end()) {
104  n2cs[sname] = CellorSec(SECTYPE, sec);
105  }else {
106  CellorSec& cs = search->second;
107  if (cs.first == CELLTYPE) { // conflict so destroy
108  Name2CellorSec* n2s = (Name2CellorSec*)cs.second;
109  delete n2s;
110  cs.first = NONETYPE;
111  cs.second = NULL;
112  }else if (cs.first == SECTYPE) { // overload
113  cs.first = OVERLOADCOUNT;
114  cs.second = (void*)2;
115  }else if (cs.first == OVERLOADCOUNT) { // increase overload
116  cs.second = (void*)((size_t)cs.second + 1);
117  }
118  }
119 }
120 
121 // Want to add a Cell to top level but name may already exist. If so
122 // already a Cell -- nothing to do
123 // already a overloaded section or section -- no longer usable, becomes NONETYPE
124 // already NONETYPE -- nothing to do
125 static Name2CellorSec* n2cs_add_cell(Name2CellorSec& n2cs, std::string cname) {
126  Name2CellorSec::iterator search = n2cs.find(cname);
127  Name2CellorSec* n2s = NULL; // not usable if it stays NULL
128  if (search == n2cs.end()) { // not found add cname, Name2Section*
129  n2s = new Name2CellorSec();
130  n2cs[cname] = CellorSec(CELLTYPE, n2s);
131  } else {
132  CellorSec& cs = search->second;
133  if (cs.first == SECTYPE || cs.first == OVERLOADCOUNT) { // conflict so destroy
134  cs.first = NONETYPE;
135  cs.second = NULL;
136  } else if (cs.first == CELLTYPE) { // exists, ready to use.
137  n2s = (Name2CellorSec*)cs.second;
138  }
139  }
140  return n2s;
141 }
142 
143 void n2cs_add(Name2CellorSec& n2cs, std::string cname, std::string sname, Section* sec) {
144  Name2CellorSec* n2s = n2cs_add_cell(n2cs, cname);
145  //printf("n2cs_add %s %s n2s=%p section=%p\n", cname.c_str(), sname.c_str(), n2s, sec);
146  if (n2s) {
147  n2s_add(*n2s, sname, sec);
148  }
149 }
150 
152  if (!activated) { return; }
153  std::string n(secname(sec));
154  if (n.find("__nrnsec_0x", 0) == 0) { return; }
155  if (n.find("<", 0) != n.npos) { return; }
156  //printf("nrnpy_pysecname2sec_add %s\n", secname(sec));
157  size_t dot = n.find('.', 1);
158  if (dot != n.npos) { // cell.sec
159  std::string cname = n.substr(0, dot);
160  std::string sname = n.substr(dot+1);
161  n2cs_add(n2cs, cname, sname, sec);
162  } else { // sec
163  n2cs_add_sec(n2cs, n, sec);
164  }
165 }
166 
167 static bool decrement(CellorSec& cs) {
168  cs.second = (void*)((size_t)cs.second - 1);
169  return cs.second ? false : true;
170 }
171 
173  if (!activated) { return; }
174  std::string name(secname(sec));
175  //printf("remove %s\n", name.c_str());
176  if (name[0] == '<') {return;}
177 
178  size_t dot = name.find('.', 1);
179  if (dot != name.npos) { // cell.sec
180  std::string cname = name.substr(0, dot);
181  std::string sname = name.substr(dot+1);
182  Name2CellorSec::iterator it = n2cs.find(cname);
183  assert(it != n2cs.end());
184  // must be CELLTYPE or NONETYPE
185  CellorSec& cs = it->second;
186  if (cs.first == CELLTYPE) {
187  Name2CellorSec* n2s = (Name2CellorSec*)cs.second;
188  Name2CellorSec::iterator its = n2s->find(sname);
189  assert(its != n2s->end());
190  // must be SECTYPE or OVERLOADCOUNT
191  CellorSec& css = its->second;
192  if (css.first == SECTYPE) {
193  n2s->erase(its);
194  if (n2s->empty()) {
195  delete n2s;
196  n2cs.erase(it);
197  }
198  }else {
199  assert(css.first == OVERLOADCOUNT);
200  if (decrement(css)) {
201  n2s->erase(its);
202  if (n2s->empty()) {
203  delete n2s;
204  n2cs.erase(it);
205  }
206  }
207  }
208  }else{
209  assert(cs.first == NONETYPE);
210  }
211  }else{ // sec
212  Name2CellorSec::iterator it = n2cs.find(name);
213  assert(it != n2cs.end());
214  // must be SECTYPE, NONETYPE, or OVERLOADCOUNT
215  CellorSec& cs = it->second;
216  if (cs.first == SECTYPE) {
217  n2cs.erase(it);
218  }else if (cs.first == OVERLOADCOUNT) {
219  if (decrement(cs)) {
220  n2cs.erase(it);
221  }
222  }else{
223  assert(cs.first == NONETYPE);
224  }
225  }
226 #if 0
227  if (n2cs.empty()) {
228  printf("pysecname2sec is empty\n");
229  }
230 #endif
231 }
232 
233 void nrn_symdir_load_pysec(SymbolList& sl, void* v) {
234  activate();
235  if (!v) {
236  // top level items are any of the four types
237  for (Name2CellorSec::iterator it = n2cs.begin(); it != n2cs.end(); ++it) {
238  CellorSec& cs = it->second;
239  if (cs.first != NONETYPE && cs.first != OVERLOADCOUNT) {
240  SymbolItem* si = new SymbolItem(it->first.c_str(), 0);
241  si->pysec_type_ = cs.first == CELLTYPE ? PYSECOBJ : PYSECNAME;
242  si->pysec_ = (Section*)cs.second;
243  sl.append(si);
244  }
245  }
246  }else{
247  // in cell items are either OVERLOADCOUNT or SECTYPE
248  Name2CellorSec* n2s = (Name2CellorSec*)v;
249  for (Name2CellorSec::iterator it = n2s->begin(); it != n2s->end(); ++it) {
250  CellorSec& cs = it->second;
251  if (cs.first == SECTYPE) {
252  SymbolItem* si = new SymbolItem(it->first.c_str(), 0);
253  si->pysec_type_ = PYSECNAME;
254  si->pysec_ = (Section*)cs.second;
255  sl.append(si);
256  }
257  }
258  }
259 }
void nrnpy_pysecname2sec_remove(Section *sec)
#define assert(ex)
Definition: hocassrt.h:26
CorStype
static void n2s_add(Name2CellorSec &n2s, std::string n, Section *sec)
#define v
Definition: md1redef.h:4
static Name2CellorSec n2cs
sl
Definition: seclist.cpp:186
int const size_t const size_t n
Definition: nrngsl.h:12
Section * nrnpy_pysecname2sec(const char *name)
#define printf
Definition: mwprefix.h:26
const char * secname(Section *sec)
Definition: cabcode.cpp:1787
static Name2CellorSec * n2cs_add_cell(Name2CellorSec &n2cs, std::string cname)
#define PROP_PY_INDEX
Definition: section.h:211
void nrnpy_pysecname2sec_add(Section *sec)
#define ForAllSections(sec)
Definition: section.h:317
void n2cs_add(Name2CellorSec &n2cs, std::string cname, std::string sname, Section *sec)
char * name
Definition: init.cpp:16
void nrn_symdir_load_pysec(SymbolList &sl, void *v)
#define hoc_acterror(a, b)
std::pair< CorStype, void * > CellorSec
static bool decrement(CellorSec &cs)
static void n2cs_add_sec(Name2CellorSec &n2cs, std::string sname, Section *sec)
sec
Definition: solve.cpp:885
static void activate()
std::map< const std::string, CellorSec > Name2CellorSec
static bool activated
void * nrn_parsing_pysec_
return NULL
Definition: cabcode.cpp:461