NEURON
strfun.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <stdlib.h>
3 #include "classreg.h"
4 #include "code.h"
5 #include "oc2iv.h"
6 #include <string.h>
7 #include <regex>
8 // for alias
9 #include <symdir.h>
10 #include <oclist.h>
11 #include <parse.hpp>
12 // for references
13 #include <hoclist.h>
14 #if HAVE_IV
15 #include <ocbox.h>
16 #endif
17 
18 #include "utils/logger.hpp"
19 
22 extern int nrn_is_artificial(int);
23 
24 static double l_substr(void*) {
25  char* s1 = gargstr(1);
26  char* s2 = gargstr(2);
27  char* p = strstr(s1, s2);
29  if (p) {
30  return double(p - s1);
31  } else {
32  return -1.;
33  }
34 }
35 
36 static double l_len(void*) {
38  return double(strlen(gargstr(1)));
39 }
40 
41 
42 // Clean the text so we keep only the first line Imitation of std::multiline in our case
43 
44 static std::string imitate_multiline(const std::string& text) {
45  static const std::regex r(R"(^(.*)(\n|$))");
46  std::smatch sm;
47  std::regex_search(text, sm, r);
48  return sm[1];
49 }
50 
51 
52 static double l_head(void*) {
53  std::string text = imitate_multiline(gargstr(1));
54  int i = -1;
55  std::string result{};
56  try {
57  std::regex r(gargstr(2), std::regex::egrep);
58  if (std::smatch sm; std::regex_search(text, sm, r)) {
59  i = sm.position();
60  result = sm.prefix().str();
61  }
62  } catch (const std::regex_error& e) {
63  Fprintf(stderr, fmt::format("{}\n", e.what()).c_str());
64  }
65  char** head = hoc_pgargstr(3);
66  hoc_assign_str(head, result.c_str());
68  return double(i);
69 }
70 
71 static double l_tail(void*) {
72  std::string text = imitate_multiline(gargstr(1));
73  int i = -1;
74  std::string result{};
75  try {
76  std::regex r(gargstr(2), std::regex::egrep);
77  if (std::smatch sm; std::regex_search(text, sm, r)) {
78  i = sm.position() + sm.length();
79  result = sm.suffix().str();
80  }
81  } catch (const std::regex_error& e) {
82  Fprintf(stderr, fmt::format("{}\n", e.what()).c_str());
83  }
84  char** tail = hoc_pgargstr(3);
85  hoc_assign_str(tail, result.c_str());
87  return double(i);
88 }
89 
90 static double l_ltrim(void*) {
91  std::string s(gargstr(1));
92  std::string chars = " \r\n\t\f\v";
93  if (ifarg(3)) {
94  chars = gargstr(3);
95  }
96  s.erase(0, s.find_first_not_of(chars));
97 
98  char** ret = hoc_pgargstr(2);
99  hoc_assign_str(ret, s.c_str());
100  return 0.;
101 }
102 
103 static double l_rtrim(void*) {
104  std::string s(gargstr(1));
105  std::string chars = " \r\n\t\f\v";
106  if (ifarg(3)) {
107  chars = gargstr(3);
108  }
109  s.erase(s.find_last_not_of(chars) + 1);
110 
111  char** ret = hoc_pgargstr(2);
112  hoc_assign_str(ret, s.c_str());
113  return 0.;
114 }
115 
116 static double l_left(void*) {
117  std::string text(gargstr(1));
118  std::string newtext = text.substr(0, int(chkarg(2, 0, strlen(gargstr(1)))));
119  hoc_assign_str(hoc_pgargstr(1), newtext.c_str());
120  return 1.;
121 }
122 
123 static double l_right(void*) {
124  std::string text(gargstr(1));
125  std::string newtext = text.substr(int(chkarg(2, 0, strlen(gargstr(1)))));
126  hoc_assign_str(hoc_pgargstr(1), newtext.c_str());
127  return 1.;
128 }
129 
130 static double l_is_name(void*) {
132  return hoc_lookup(gargstr(1)) ? 1. : 0.;
133 }
134 
135 
136 extern void hoc_free_symspace(Symbol*);
137 extern Object* hoc_newobj1(Symbol*, int);
139 
140 extern Symbol* ivoc_alias_lookup(const char* name, Object* ob) {
141  Symbol* s{};
142  IvocAliases* a = (IvocAliases*) ob->aliases;
143  if (a) {
144  s = a->lookup(name);
145  }
146  return s;
147 }
148 
149 extern void ivoc_free_alias(Object* ob) {
150  IvocAliases* a = (IvocAliases*) ob->aliases;
151  if (a)
152  delete a;
153 }
154 
155 
156 static double l_alias(void*) {
157  char* name;
158  Object* ob = *hoc_objgetarg(1);
159  IvocAliases* a = (IvocAliases*) ob->aliases;
160  Symbol* sym;
161 
162  if (!ifarg(2)) { // remove them all
163  if (a) {
164  delete a;
165  }
166  return 0.;
167  }
168  name = gargstr(2);
169  if (!a) {
170  a = new IvocAliases(ob);
171  }
172  sym = a->lookup(name);
173  if (sym) {
174  a->remove(sym);
175  }
176  if (ifarg(3)) {
177  sym = a->install(name);
178  if (hoc_is_object_arg(3)) {
179  sym->u.object_ = *hoc_objgetarg(3);
180  hoc_obj_ref(sym->u.object_);
181  sym->type = OBJECTALIAS;
182  } else {
183  sym->u.pval = hoc_pgetarg(3);
184  sym->type = VARALIAS;
185  }
186  }
187  return 0.;
188 }
189 
190 static Object** l_alias_list(void*) {
191  // Assumes that a hoc String exists with constructor that takes a strdef
192  Object* ob = *hoc_objgetarg(1);
193  IvocAliases* a = (IvocAliases*) ob->aliases;
194  OcList* list = new OcList();
195  list->ref();
196  Symbol* sl = hoc_lookup("List");
198  if (!st || st->type != TEMPLATE) {
199  hoc_execerror("String is not a HOC template", 0);
200  }
201  Object** po = hoc_temp_objvar(sl, list);
202  (*po)->refcount++;
203  int id = (*po)->index;
204  if (a) {
205  for (auto& kv: a->symtab_) {
206  Symbol* sym = kv.second;
207  hoc_pushstr(&sym->name);
208  Object* sob = hoc_newobj1(st, 1);
209  list->append(sob);
210  --sob->refcount;
211  }
212  }
213  (*po)->refcount--;
214  return po;
215 }
216 
217 // does o refer to ob
218 static int l_ref2(Object* o, Object* ob, int nr) {
219  int i, total;
220  if (!o) {
221  return nr;
222  }
223  if (o->ctemplate->constructor) {
224  return nr;
225  }
226  Symlist* sl = o->ctemplate->symtable;
227  Symbol* s;
228  if (sl)
229  for (s = sl->first; s; s = s->next) {
230  if (s->type == OBJECTVAR && s->cpublic < 2) {
231  total = hoc_total_array_data(s, o->u.dataspace);
232  for (i = 0; i < total; ++i) {
233  Object** obp = o->u.dataspace[s->u.oboff].pobj + i;
234  if (*obp == ob) {
235  if (total == 1) {
236  Printf(" %s.%s\n", hoc_object_name(o), s->name);
237  } else {
238  Printf(" %s.%s[%d]\n", hoc_object_name(o), s->name, i);
239  }
240  ++nr;
241  }
242  }
243  }
244  }
245  return nr;
246 }
247 
248 // does data refer to ob
249 static int l_ref1(Symlist* sl, Objectdata* data, Object* ob, int nr) {
250  int i, total;
251  Symbol* s;
252  if (sl)
253  for (s = sl->first; s; s = s->next) {
254  if (s->type == OBJECTVAR && s->cpublic < 2) {
255  total = hoc_total_array_data(s, data);
256  for (i = 0; i < total; ++i) {
257  Object** obp = data[s->u.oboff].pobj + i;
258  if (*obp == ob) {
259  if (total == 1) {
260  Printf(" %s\n", s->name);
261  } else {
262  Printf(" %s[%d]\n", s->name, i);
263  }
264  ++nr;
265  }
266  }
267  }
268  }
269  return nr;
270 }
271 static int l_ref0(Symlist* sl, Object* ob, int nr) {
272  Symbol* s;
273  cTemplate* t;
274  if (sl)
275  for (s = sl->first; s; s = s->next) {
276  if (s->type == TEMPLATE) {
277  t = s->u.ctemplate;
278  hoc_Item* q;
279  ITERATE(q, t->olist) {
280  nr = l_ref2(OBJ(q), ob, nr);
281  }
282  }
283  }
284  return nr;
285 }
286 
287 static int l_ref3(Symbol* s, Object* ob, int nr) {
288 #if HAVE_IV
289  hoc_Item* q;
290  ITERATE(q, s->u.ctemplate->olist) {
291  OcBox* b = (OcBox*) (OBJ(q)->u.this_pointer);
292  if (b->keep_ref() == ob) {
293  Printf(" %s.ref\n", hoc_object_name(OBJ(q)));
294  ++nr;
295  }
296  }
297  return nr;
298 #else
299  return 0;
300 #endif
301 }
302 
303 static int l_ref4(Symbol* s, Object* ob, int nr) {
304  hoc_Item* q;
305  long i;
306  ITERATE(q, s->u.ctemplate->olist) {
307  OcList* list = (OcList*) (OBJ(q)->u.this_pointer);
308  if (list->refs_items())
309  for (i = 0; i < list->count(); ++i) {
310  if (list->object(i) == ob) {
311  Printf(" %s.object(%ld)\n", hoc_object_name(OBJ(q)), i);
312  ++nr;
313  }
314  }
315  }
316  return nr;
317 }
318 
319 static double l_ref(void*) {
320  Object* ob = *hoc_objgetarg(1);
321  int nr = ob ? ob->refcount : 0;
322  Printf("%s has %d references\n", hoc_object_name(ob), nr);
324  if (nr == 0) {
325  return 0.;
326  }
327  nr = 0;
329  nr = l_ref0(hoc_top_level_symlist, ob, nr);
330  // any due to boxes
331  nr = l_ref3(hoc_table_lookup("HBox", hoc_built_in_symlist), ob, nr);
332  nr = l_ref3(hoc_table_lookup("VBox", hoc_built_in_symlist), ob, nr);
333  nr = l_ref4(hoc_table_lookup("List", hoc_built_in_symlist), ob, nr);
334 
335  Printf(" found %d of them\n", nr);
336  return (double) nr;
337 }
338 
339 static double l_is_point(void*) {
340  Object* ob = *hoc_objgetarg(1);
342  return double(ob ? ob->ctemplate->is_point_ : 0);
343 }
344 
345 static double l_is_artificial(void*) {
346  Object* ob = *hoc_objgetarg(1);
347  int type = ob ? ob->ctemplate->is_point_ : 0;
349  if (type == 0) {
350  return 0.;
351  }
352  return nrn_is_artificial(type) ? type : 0;
353 }
354 
355 static Member_func l_members[] = {{"substr", l_substr},
356  {"len", l_len},
357  {"head", l_head},
358  {"tail", l_tail},
359  {"ltrim", l_ltrim},
360  {"rtrim", l_rtrim},
361  {"right", l_right},
362  {"left", l_left},
363  {"is_name", l_is_name},
364  {"alias", l_alias},
365  {"references", l_ref},
366  {"is_point_process", l_is_point},
367  {"is_artificial", l_is_artificial},
368  {nullptr, nullptr}};
369 
370 static Member_ret_obj_func l_obj_members[] = {{"alias_list", l_alias_list}, {nullptr, nullptr}};
371 
372 static void* l_cons(Object*) {
373  return nullptr;
374 }
375 
377  class2oc("StringFunctions", l_cons, nullptr, l_members, l_obj_members, nullptr);
378 }
379 
380 
382  ob_ = ob;
383  ob_->aliases = (void*) this;
384 }
385 
387  ob_->aliases = nullptr;
388  for (auto& kv: symtab_) {
389  Symbol* sym = kv.second;
390  hoc_free_symspace(sym);
391  free(sym->name);
392  free(sym);
393  }
394 }
396  const auto& it = symtab_.find(name);
397  if (it != symtab_.end()) {
398  return it->second;
399  }
400  return nullptr;
401 }
403  Symbol* sp;
404  sp = (Symbol*) emalloc(sizeof(Symbol));
405  sp->name = static_cast<char*>(emalloc(strlen(name) + 1));
406  strcpy(sp->name, name);
407  sp->type = VARALIAS;
408  sp->cpublic = 0; // cannot be 2 or cannot be freed
409  sp->extra = nullptr;
410  sp->arayinfo = nullptr;
411  symtab_.try_emplace(sp->name, sp);
412  return sp;
413 }
415  hoc_free_symspace(sym);
416  auto it = symtab_.find(sym->name);
417  symtab_.erase(it);
418  free(sym->name);
419  free(sym);
420 }
Object * ob_
Definition: symdir.h:20
virtual ~IvocAliases()
Definition: strfun.cpp:386
Symbol * install(const char *)
Definition: strfun.cpp:402
void remove(Symbol *)
Definition: strfun.cpp:414
Symbol * lookup(const char *)
Definition: strfun.cpp:395
IvocAliases(Object *)
Definition: strfun.cpp:381
std::map< std::string, Symbol * > symtab_
Definition: symdir.h:21
Definition: ocbox.h:9
void keep_ref(Object *)
Definition: oclist.h:11
long count()
Definition: oclist.cpp:175
bool refs_items()
Definition: oclist.h:24
Object * object(long)
Definition: oclist.cpp:219
virtual void ref() const
Definition: resource.cpp:42
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 i
Definition: md1redef.h:19
double chkarg(int, double low, double high)
Definition: code2.cpp:626
int hoc_is_object_arg(int narg)
Definition: code.cpp:876
void hoc_pushstr(char **d)
Definition: code.cpp:800
size_t hoc_total_array_data(const Symbol *s, Objectdata *obd)
Definition: hoc_oop.cpp:95
Object ** hoc_temp_objvar(Symbol *symtemp, void *v)
Definition: hoc_oop.cpp:484
void hoc_assign_str(char **cpp, const char *buf)
Definition: code.cpp:2263
void hoc_obj_ref(Object *obj)
Definition: hoc_oop.cpp:1844
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:73
void ivoc_free_alias(Object *ob)
Definition: strfun.cpp:149
double * hoc_pgetarg(int narg)
Definition: oc_ansi.h:253
Symbol * hoc_lookup(const char *)
Definition: symbol.cpp:59
Symbol * ivoc_alias_lookup(const char *name, Object *ob)
Definition: strfun.cpp:140
char ** hoc_pgargstr(int narg)
Definition: code.cpp:1623
#define OBJECTALIAS
Definition: hocdec.h:94
#define VARALIAS
Definition: hocdec.h:95
#define OBJ(q)
Definition: hoclist.h:88
Object ** hoc_objgetarg(int)
Definition: code.cpp:1614
#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
static void * emalloc(size_t size)
Definition: mpispike.cpp:30
if(ncell==0)
Definition: cellorder.cpp:785
size_t q
size_t p
s
Definition: multisend.cpp:521
int ifarg(int)
Definition: code.cpp:1607
short type
Definition: cabvars.h:10
#define text
Definition: plot.cpp:60
static int l_ref2(Object *o, Object *ob, int nr)
Definition: strfun.cpp:218
static double l_is_artificial(void *)
Definition: strfun.cpp:345
static double l_tail(void *)
Definition: strfun.cpp:71
static double l_left(void *)
Definition: strfun.cpp:116
static int l_ref3(Symbol *s, Object *ob, int nr)
Definition: strfun.cpp:287
Symlist * hoc_top_level_symlist
Definition: symdir.cpp:16
static int l_ref4(Symbol *s, Object *ob, int nr)
Definition: strfun.cpp:303
static double l_len(void *)
Definition: strfun.cpp:36
void StringFunctions_reg()
Definition: strfun.cpp:376
static void * l_cons(Object *)
Definition: strfun.cpp:372
static double l_rtrim(void *)
Definition: strfun.cpp:103
static Object ** l_alias_list(void *)
Definition: strfun.cpp:190
static double l_substr(void *)
Definition: strfun.cpp:24
static std::string imitate_multiline(const std::string &text)
Definition: strfun.cpp:44
Object * hoc_newobj1(Symbol *, int)
Definition: hoc_oop.cpp:497
static Member_ret_obj_func l_obj_members[]
Definition: strfun.cpp:370
static double l_ref(void *)
Definition: strfun.cpp:319
void hoc_free_symspace(Symbol *)
Definition: symbol.cpp:166
static double l_head(void *)
Definition: strfun.cpp:52
static int l_ref1(Symlist *sl, Objectdata *data, Object *ob, int nr)
Definition: strfun.cpp:249
static double l_right(void *)
Definition: strfun.cpp:123
int nrn_is_artificial(int)
Definition: init.cpp:222
static double l_is_name(void *)
Definition: strfun.cpp:130
Objectdata * hoc_top_level_data
Definition: hoc_oop.cpp:123
static int l_ref0(Symlist *sl, Object *ob, int nr)
Definition: strfun.cpp:271
Symlist * hoc_built_in_symlist
Definition: symbol.cpp:28
static Member_func l_members[]
Definition: strfun.cpp:355
static double l_ltrim(void *)
Definition: strfun.cpp:90
static double l_is_point(void *)
Definition: strfun.cpp:339
static double l_alias(void *)
Definition: strfun.cpp:156
Definition: hocdec.h:173
void * aliases
Definition: hocdec.h:181
Objectdata * dataspace
Definition: hocdec.h:177
int refcount
Definition: hocdec.h:174
cTemplate * ctemplate
Definition: hocdec.h:180
union Object::@47 u
Definition: model.h:47
union Symbol::@28 u
short cpublic
Definition: hocdec.h:107
Object * object_
Definition: hocdec.h:113
short type
Definition: model.h:48
char * name
Definition: model.h:61
HocSymExtension * extra
Definition: hocdec.h:131
Arrayinfo * arayinfo
Definition: hocdec.h:130
Definition: hocdec.h:75
Symbol * first
Definition: hocdec.h:76
Symlist * symtable
Definition: hocdec.h:148
void *(* constructor)(struct Object *)
Definition: hocdec.h:158
int is_point_
Definition: hocdec.h:150
Object ** pobj
Definition: hocdec.h:166
int Fprintf(FILE *stream, const char *fmt, Args... args)
Definition: logger.hpp:8
int Printf(const char *fmt, Args... args)
Definition: logger.hpp:18