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