NEURON
symbol.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 /* /local/src/master/nrn/src/oc/symbol.cpp,v 1.9 1999/02/25 18:01:58 hines Exp */
3 /* version 7.2.1 2-jan-89 */
4 
5 #if HAVE_POSIX_MEMALIGN
6 #define HAVE_MEMALIGN 1
7 #endif
8 #if defined(DARWIN) /* posix_memalign seems not to work on Darwin 10.6.2 */
9 #undef HAVE_MEMALIGN
10 #endif
11 #if HAVE_MEMALIGN
12 #undef _XOPEN_SOURCE /* avoid warnings about redefining this */
13 #define _XOPEN_SOURCE 600
14 #endif
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include "hoc.h"
20 #include "ocfunc.h"
21 #include "parse.hpp"
22 #include "hoclist.h"
23 #if MAC
24 #undef HAVE_MALLOC_H
25 #endif
26 #if HAVE_MALLOC_H
27 #include <malloc.h>
28 #endif
29 #if HAVE_ALLOC_H
30 #include <alloc.h> /* at least for turbo C 2.0 */
31 #endif
32 
33 #include "nrnmpiuse.h"
34 
35 #if defined(__APPLE__) && defined(__MACH__)
36 #include <mach/mach.h>
37 #endif
38 
39 #if OOP
40 Symlist* hoc_built_in_symlist = nullptr; /* keywords, built-in functions,
41  all name linked into hoc. Look in this list last */
42 Symlist* hoc_top_level_symlist = nullptr; /* all user names seen at top-level
43  (non-public names inside templates do not appear here) */
45 #endif /*OOP*/
46 
47 Symlist* symlist = nullptr; /* the current user symbol table: linked list */
48 Symlist* p_symlist = nullptr; /* current proc, func, or temp table */
49  /* containing constants, strings, and auto */
50  /* variables. Discarding these lists at */
51  /* appropriate times prevents storage leakage. */
52 
53 void print_symlist(const char* s, Symlist* tab) {
54  Printf("%s\n", s);
55  if (tab)
56  for (Symbol* sp = tab->first; sp != nullptr; sp = sp->next) {
57  Printf("%s %p\n", sp->name, sp);
58  }
59 }
60 
61 Symbol* hoc_table_lookup(const char* s, Symlist* tab) /* find s in specific table */
62 {
63  if (tab)
64  for (Symbol* sp = tab->first; sp != nullptr; sp = sp->next) {
65  if (strcmp(sp->name, s) == 0) {
66  return sp;
67  }
68  }
69  return nullptr;
70 }
71 
72 Symbol* lookup(const char* s) /* find s in symbol table */
73  /* look in p_symlist then built_in_symlist then symlist */
74 {
75  Symbol* sp;
76 
77  if ((sp = hoc_table_lookup(s, p_symlist)) != nullptr) {
78  return sp;
79  }
80  if ((sp = hoc_table_lookup(s, symlist)) != nullptr) {
81  return sp;
82  }
83 #if OOP
84  if ((sp = hoc_table_lookup(s, hoc_built_in_symlist)) != nullptr) {
85  return sp;
86  }
87 #endif
88 
89  return nullptr; /* nullptr ==> not found */
90 }
91 
92 Symbol* install(/* install s in the list symbol table */
93  const char* s,
94  int t,
95  double d,
96  Symlist** list) {
97  Symbol* sp = (Symbol*) emalloc(sizeof(Symbol));
98  sp->name = (char*) emalloc((unsigned) (strlen(s) + 1)); /* +1 for '\0' */
99  Strcpy(sp->name, s);
100  sp->type = t;
101  sp->subtype = NOTUSER;
102  sp->defined_on_the_fly = 0;
103  sp->cpublic = 0;
104  sp->s_varn = 0;
105  sp->arayinfo = nullptr;
106  sp->extra = nullptr;
107  if (!(*list)) {
108  *list = (Symlist*) emalloc(sizeof(Symlist));
109  (*list)->first = (*list)->last = nullptr;
110  }
111  hoc_link_symbol(sp, *list);
112  switch (t) {
113  case NUMBER:
114  sp->u.pnum = (double*) emalloc(sizeof(double));
115  *sp->u.pnum = d;
116  break;
117  case VAR:
119  OPVAL(sp) = (double*) emalloc(sizeof(double));
120  *(OPVAL(sp)) = d;
121  break;
122  case PROCEDURE:
123  case FUNCTION:
124  case FUN_BLTIN:
125  case OBFUNCTION:
126  case STRFUNCTION:
127  sp->u.u_proc = (Proc*) ecalloc(1, sizeof(Proc));
128  sp->u.u_proc->list = nullptr;
129  sp->u.u_proc->size = 0;
130  break;
131  default:
132  sp->u.pnum = nullptr;
133  break;
134  }
135  return sp;
136 }
137 
138 Symbol* hoc_install_var(const char* name, double* pval) {
139  Symbol* s = hoc_install(name, UNDEF, 0., &symlist);
140  s->type = VAR;
141  s->u.pval = pval;
142  s->subtype = USERDOUBLE;
143  return s;
144 }
145 
147  assert(list);
148 
149  if (list->first == s) {
150  list->first = s->next;
151  if (list->last == s) {
152  list->last = nullptr;
153  }
154  } else {
155  Symbol* sp;
156  for (sp = list->first; sp != nullptr; sp = sp->next) {
157  if (sp->next == s) {
158  break;
159  }
160  }
161  assert(sp);
162  sp->next = s->next;
163  if (list->last == s) {
164  list->last = sp;
165  }
166  }
167  s->next = nullptr;
168 }
169 
170 void hoc_link_symbol(Symbol* sp, Symlist* list) {
171  /* put at end of list */
172  if (list->last) {
173  list->last->next = sp;
174  } else {
175  list->first = sp;
176  }
177  list->last = sp;
178  sp->next = nullptr;
179 }
180 
181 static int emalloc_error = 0;
182 
183 extern "C" void hoc_malchk(void) {
184  if (emalloc_error) {
185  emalloc_error = 0;
186  execerror("out of memory", nullptr);
187  }
188 }
189 
190 extern "C" void* hoc_Emalloc(size_t n) { /* check return from malloc */
191  void* p = malloc(n);
192  if (p == nullptr)
193  emalloc_error = 1;
194  return p;
195 }
196 
197 void* emalloc(size_t n) {
198  void* p = hoc_Emalloc(n);
199  if (emalloc_error) {
200  hoc_malchk();
201  }
202  return p;
203 }
204 
205 extern "C" void* hoc_Ecalloc(size_t n, size_t size) { /* check return from calloc */
206  if (n == 0) {
207  return nullptr;
208  }
209  void* p = calloc(n, size);
210  if (p == nullptr)
211  emalloc_error = 1;
212  return p;
213 }
214 
215 extern "C" void* ecalloc(size_t n, size_t size) {
216  void* p = hoc_Ecalloc(n, size);
217  if (emalloc_error) {
218  hoc_malchk();
219  }
220  return p;
221 }
222 
223 void* nrn_cacheline_alloc(void** memptr, size_t size) {
224 #if HAVE_MEMALIGN
225  static int memalign_is_working = 1;
226  if (memalign_is_working) {
227  if (posix_memalign(memptr, 64, size) != 0) {
228  fprintf(stderr, "posix_memalign not working, falling back to using malloc\n");
229  memalign_is_working = 0;
230  *memptr = hoc_Emalloc(size);
231  hoc_malchk();
232  }
233  } else
234 #endif
235  *memptr = hoc_Emalloc(size);
236  hoc_malchk();
237  return *memptr;
238 }
239 
240 void* nrn_cacheline_calloc(void** memptr, size_t nmemb, size_t size) {
241 #if HAVE_MEMALIGN
242  nrn_cacheline_alloc(memptr, nmemb * size);
243  memset(*memptr, 0, nmemb * size);
244 #else
245  *memptr = hoc_Ecalloc(nmemb, size);
246  hoc_malchk();
247 #endif
248  return *memptr;
249 }
250 
251 void* hoc_Erealloc(void* ptr, size_t size) { /* check return from realloc */
252  if (!ptr) {
253  return hoc_Emalloc(size);
254  }
255  void* p = realloc(ptr, size);
256  if (p == nullptr) {
257  free(ptr);
258  emalloc_error = 1;
259  }
260  return p;
261 }
262 
263 extern "C" void* erealloc(void* ptr, size_t size) {
264  void* p = hoc_Erealloc(ptr, size);
265  if (emalloc_error) {
266  hoc_malchk();
267  }
268  return p;
269 }
270 
271 void hoc_free_symspace(Symbol* s1) { /* frees symbol space. Marks it UNDEF */
272  if (s1 && s1->cpublic != 2) {
273  switch (s1->type) {
274  case UNDEF:
275  case STRING:
276  case VAR:
277  break;
278  case NUMBER:
279  free((char*) (s1->u.pnum));
280  break;
281  case CSTRING:
282  free(s1->u.cstr);
283  break;
284  case PROCEDURE:
285  case FUNCTION:
286  if (s1->u.u_proc != nullptr) {
287  if (s1->u.u_proc->defn.in != STOP)
288  free((char*) s1->u.u_proc->defn.in);
289  free_list(&(s1->u.u_proc->list));
290  free((char*) s1->u.u_proc);
291  }
292  break;
293  case AUTO:
294  case AUTOOBJ:
295  break;
296  case TEMPLATE:
298  free_list(&(s1->u.ctemplate->symtable));
299  {
300  hoc_List* l = s1->u.ctemplate->olist;
301  if (l->next == l) {
303  free(s1->u.ctemplate);
304  } else {
305  hoc_warning("didn't free all objects created with the old template:", s1->name);
306  }
307  }
308  break;
309  case OBJECTVAR:
310 #if 0 /* should have been freed above, otherwise I don't know the exact objects*/
311  if (s1->arayinfo) {int i, j, k=0;
312  for (i = 0; i < s1->arayinfo->nsub; i++) {
313  for (j=0; j < s1->arayinfo->sub[i]; j++) {
314  hoc_dec_refcount(OPOBJ(s1) + k);
315  ++k;
316  }
317  }
318  }else{
319  hoc_dec_refcount(OPOBJ(s1));
320  }
321  free((char *)OPOBJ(s1));
322 #endif
323  break;
324  case OBJECTALIAS:
325  hoc_obj_unref(s1->u.object_);
326  break;
327  case VARALIAS:
328  break;
329  default:
330  Fprintf(stderr,
331  "In free_symspace may not free all of %s of type=%d\n",
332  s1->name,
333  s1->type);
334  }
335  if (s1->arayinfo != nullptr) {
337  s1->arayinfo = nullptr;
338  }
339  }
340  if (s1->extra) {
341  if (s1->extra->parmlimits) {
342  free(s1->extra->parmlimits);
343  }
344  if (s1->extra->units) {
345  free(s1->extra->units);
346  }
347  free(s1->extra);
348  s1->extra = nullptr;
349  }
350  s1->type = UNDEF;
351 }
352 
354  if (!sym->extra) {
355  sym->extra = (HocSymExtension*) ecalloc(1, sizeof(HocSymExtension));
356  }
357 }
358 
359 void free_list(Symlist** list) { /* free the space in a symbol table */
360  if (!*list) {
361  return;
362  }
363 
364  Symbol* s1 = (*list)->first;
365  while (s1) {
366  Symbol* s2 = s1->next;
367  hoc_free_symspace(s1);
368  if (s1->name) {
369  free(s1->name);
370  }
371  free((char*) s1);
372  s1 = s2;
373  }
374  free((char*) (*list));
375  *list = nullptr;
376 }
377 
378 void hoc_free_val(double* p) {
379  notify_freed(p);
380  free(p);
381 }
382 
383 void hoc_free_val_array(double* p, size_t size) {
384  notify_freed_val_array(p, size);
385  free(p);
386 }
387 
389  if (p) {
391  free(p);
392  }
393 }
394 
395 void hoc_free_string(char* p) {
396  free(p);
397 }
398 
399 void hoc_free_pstring(char** p) {
400  notify_freed((void*) p);
401  if (*p) {
402  free(*p);
403  free(p);
404  }
405 }
406 
407 extern "C" size_t nrn_mallinfo(int item) {
408 #if defined(__APPLE__) && defined(__MACH__)
409  /* OSX ------------------------------------------------------
410  * Returns the current resident set size (physical memory use) measured
411  * in bytes, or zero if the value cannot be determined on this OS.
412  */
413  struct mach_task_basic_info info;
414  mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
415  if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t) &info, &infoCount) !=
416  KERN_SUCCESS)
417  return (size_t) 0L; /* Can't access? */
418  return (size_t) info.resident_size;
419 #elif HAVE_MALLINFO || HAVE_MALLINFO2
420  // *nix platforms with mallinfo[2]()
421  size_t r;
422  // prefer mallinfo2, fall back to mallinfo
423 #if HAVE_MALLINFO2
424  auto const m = mallinfo2();
425 #else
426  auto const m = mallinfo();
427 #endif
428  if (item == 1) {
429  r = m.uordblks;
430  } else if (item == 2) {
431  r = m.hblkhd;
432  } else if (item == 3) {
433  r = m.arena;
434  } else if (item == 4) {
435  r = m.fordblks;
436  } else if (item == 5) {
437  r = m.hblks;
438  } else if (item == 6) {
439  r = m.hblkhd + m.arena;
440  } else {
441  r = m.hblkhd + m.uordblks;
442  }
443  return r;
444 #else
445  /* UNSUPPORTED PLATFORM ------------------------------------ */
446  return 0;
447 #endif
448 }
449 
450 void hoc_mallinfo() {
451  int const i = chkarg(1, 0, 6);
452  auto const x = nrn_mallinfo(i);
453  hoc_ret();
454  hoc_pushx(x);
455 }
double t
Definition: cvodeobj.cpp:59
double chkarg(int, double low, double high)
Definition: code2.cpp:638
void hoc_unlink_symbol(Symbol *s, Symlist *list)
Definition: symbol.cpp:146
void sym_extra_alloc(Symbol *sym)
Definition: symbol.cpp:353
void hoc_free_val_array(double *p, size_t size)
Definition: symbol.cpp:383
void * hoc_Emalloc(size_t n)
Definition: symbol.cpp:190
void * hoc_Ecalloc(size_t n, size_t size)
Definition: symbol.cpp:205
void hoc_free_string(char *p)
Definition: symbol.cpp:395
size_t nrn_mallinfo(int item)
Definition: symbol.cpp:407
void * nrn_cacheline_calloc(void **memptr, size_t nmemb, size_t size)
Definition: symbol.cpp:240
void notify_freed_val_array(double *p, size_t size)
Definition: ivoc.cpp:101
Symbol * hoc_install(const char *, int, double, Symlist **)
void hoc_free_object(Object *p)
Definition: symbol.cpp:388
void * hoc_Erealloc(void *ptr, size_t size)
Definition: symbol.cpp:251
void hoc_free_pstring(char **p)
Definition: symbol.cpp:399
void notify_pointer_freed(void *pt)
Definition: ivoc.cpp:81
Symbol * hoc_table_lookup(const char *s, Symlist *tab)
Definition: symbol.cpp:61
void hoc_malchk(void)
Definition: symbol.cpp:183
void hoc_ret()
void hoc_warning(const char *, const char *)
void * nrn_cacheline_alloc(void **memptr, size_t size)
Definition: symbol.cpp:223
Symbol * hoc_install_var(const char *name, double *pval)
Definition: symbol.cpp:138
void hoc_dec_refcount(Object **pobj)
Definition: hoc_oop.cpp:1816
void hoc_install_object_data_index(Symbol *sp)
Definition: hoc_oop.cpp:304
void hoc_obj_unref(Object *obj)
Definition: hoc_oop.cpp:1828
void hoc_free_allobjects(cTemplate *ctemplate, Symlist *sl, Objectdata *data)
Definition: hoc_oop.cpp:1699
void notify_freed(void *p)
Definition: ivoc.cpp:93
void hoc_link_symbol(Symbol *sp, Symlist *list)
Definition: symbol.cpp:170
void free_arrayinfo(Arrayinfo *a)
Definition: hoc.cpp:652
#define assert(ex)
Definition: hocassrt.h:32
#define OBJECTALIAS
Definition: hocdec.h:107
#define USERDOUBLE
Definition: hocdec.h:93
#define NOTUSER
Definition: hocdec.h:91
#define OPOBJ(sym)
Definition: hocdec.h:308
#define OPVAL(sym)
Definition: hocdec.h:306
#define STOP
Definition: hocdec.h:66
#define VARALIAS
Definition: hocdec.h:108
void hoc_l_freelist(hoc_List **)
void hoc_pushx(double)
#define pval
Definition: md1redef.h:32
#define i
Definition: md1redef.h:12
#define Strcpy
Definition: model.h:238
#define Printf
Definition: model.h:237
#define Fprintf
Definition: model.h:234
char * name
Definition: init.cpp:16
Symbol * install(char *s, int t)
Definition: symbol.cpp:49
List * symlist[128]
Definition: symbol.cpp:8
Symbol * lookup(char *s)
Definition: symbol.cpp:21
#define fprintf
Definition: mwprefix.h:30
static List * info
int const size_t const size_t n
Definition: nrngsl.h:11
#define FUNCTION(a, b)
Definition: nrngsl.h:6
size_t p
size_t j
static philox4x32_key_t k
Definition: nrnran123.cpp:11
void * emalloc(size_t n)
Definition: symbol.cpp:197
void * erealloc(void *ptr, size_t size)
Definition: symbol.cpp:263
void hoc_free_val(double *p)
Definition: symbol.cpp:378
void hoc_mallinfo()
Definition: symbol.cpp:450
Symlist * hoc_top_level_symlist
Definition: symbol.cpp:42
void * ecalloc(size_t n, size_t size)
Definition: symbol.cpp:215
static int emalloc_error
Definition: symbol.cpp:181
Symlist * p_symlist
Definition: symbol.cpp:48
void print_symlist(const char *s, Symlist *tab)
Definition: symbol.cpp:53
void hoc_free_symspace(Symbol *s1)
Definition: symbol.cpp:271
Objectdata * hoc_top_level_data
Definition: hoc_oop.cpp:124
Symlist * hoc_built_in_symlist
Definition: symbol.cpp:40
void free_list(Symlist **list)
Definition: symbol.cpp:359
#define STRING
Definition: bbslsrv.cpp:9
#define execerror
Definition: section.h:36
int nsub
Definition: hocdec.h:70
int sub[1]
Definition: hocdec.h:72
float * parmlimits
Definition: hocdec.h:111
char * units
Definition: hocdec.h:112
Definition: hocdec.h:227
Definition: hocdec.h:75
Inst defn
Definition: hocdec.h:76
unsigned long size
Definition: hocdec.h:77
HocStruct Symlist * list
Definition: hocdec.h:78
Definition: model.h:57
Proc * u_proc
Definition: hocdec.h:145
short cpublic
Note: public is a reserved keyword.
Definition: hocdec.h:125
short type
Definition: model.h:58
double * pnum
Definition: hocdec.h:140
long subtype
Definition: model.h:59
HocStruct Symbol * next
Definition: hocdec.h:162
char * cstr
Definition: hocdec.h:139
HocStruct Object * object_
Definition: hocdec.h:138
union Symbol::@18 u
unsigned s_varn
Definition: hocdec.h:158
char * name
Definition: model.h:72
HocSymExtension * extra
Definition: hocdec.h:160
double * pval
Definition: hocdec.h:137
HocStruct cTemplate * ctemplate
Definition: hocdec.h:152
Arrayinfo * arayinfo
Definition: hocdec.h:159
short defined_on_the_fly
Definition: hocdec.h:129
Definition: hocdec.h:84
HocStruct Symbol * first
Definition: hocdec.h:85
HocStruct Symbol * last
Definition: hocdec.h:86
Symlist * symtable
Definition: hocdec.h:197
hoc_List * olist
Definition: hocdec.h:204
struct hoc_Item * next
Definition: hoclist.h:50
HocUnion Inst * in
Definition: hocdec.h:60