1 #include <../../nrnconf.h>
39 diag(
"Multiple declaration of ", sym->
name);
49 if (
n->u.str == (
char*) 0)
61 if (
n->u.str == (
char*) 0)
85 if (!(
s->subtype &
PARM)) {
88 diag(
s->name,
"can't be declared a parameter by default");
108 diag(
"Only one independent variable can be defined", (
char*) 0);
150 diag(
n->name,
"tolerance can be specified only for a STATE");
152 if (
n->u.str == (
char*) 0)
162 diag(
"START not legal except in STATE block", (
char*) 0);
179 if (
n->type != NAME &&
n->type != PRIME) {
180 diag(
n->name,
"can't be a STATE");
209 if (
q->itemtype ==
STRING && strcmp(
STR(
q),
"") == 0) {
212 }
else if (
q->next->itemtype ==
SYMBOL && strcmp(
SYM(
q->next)->name,
")") == 0) {
222 for (
q = q1;
q != q2;
q =
q->next) {
226 if (
q->next->itemtype ==
SYMBOL && strcmp(
SYM(
q->next)->name,
"(") == 0) {
243 if (q1->
next == q2) {
247 for (
q = q1->
next;
q != q2;
q =
q->next) {
248 if (strcmp(
SYM(
q)->
name,
",") != 0) {
257 Symbol *name1, *name2, *lagval;
270 diag(
"INDEPENDENT variable must be declared to process",
"the LAG statement");
273 diag(name1->
name,
"not a STATE or DEPENDENT variable");
276 diag(name2->
name,
"not a CONSTANT or PARAMETER");
294 "%s = lag(%s, %s, %s, %d);\n",
304 "%s = *lag(&(%s), %s, %s, 0);\n",
314 static int reset_fun_cnt = 0;
317 Sprintf(
buf,
"&_reset, &_freset%d,", reset_fun_cnt);
319 Sprintf(
buf,
"static double _freset%d;\n", reset_fun_cnt);
356 fprintf(
fcout,
"\n#if %d\n", 0);
358 fprintf(
fcout,
"#endif\n");
374 Sprintf(
buf,
"\nstatic void %s(_internalthreadargsproto_);",
STR(
q));
380 "static void _check_table_thread(_threadargsprotocomma_ int _type, "
381 "_nrn_model_sorted_token const& _sorted_token) {\n"
382 " if (gind != 0 && _thread != nullptr) { _globals = _thread[_gth].get<double*>(); } \n"
383 " _nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml, _type};\n"
385 " auto* const _ml = &_lmr;\n");
412 from =
LST(
q =
q->next);
413 to =
LST(
q =
q->next);
414 ntab = atoi(
STR(
q =
q->next));
415 depend =
LST(
q =
q->next);
424 Sprintf(
buf,
"_check_%s(_threadargs_);\n", fname);
427 if (
type == FUNCTION1) {
429 diag(
"TABLE stmt in FUNCTION cannot have a table name list", (
char*) 0);
435 diag(
"TABLE stmt in PROCEDURE must have a table name list", (
char*) 0);
438 if (arglist->
next == arglist || arglist->
next->
next != arglist) {
439 diag(
"FUNCTION or PROCEDURE containing a TABLE stmt\n",
"must have exactly one argument");
453 if (
type == FUNCTION1) {
455 Sprintf(
buf,
"static double _n_%s(double);\n", fname);
457 Sprintf(
buf,
"static double _n_%s(_internalthreadargsprotocomma_ double _lv);\n", fname);
461 Sprintf(
buf,
"static void _n_%s(double);\n", fname);
463 Sprintf(
buf,
"static void _n_%s(_internalthreadargsprotocomma_ double _lv);\n", fname);
469 Sprintf(
buf,
"static double _mfac_%s, _tmin_%s;\n", fname, fname);
478 Sprintf(
buf,
"static void _check_%s();\n", fname);
481 Sprintf(
buf,
"static void _check_%s() {\n", fname);
483 Sprintf(
buf,
"static void _check_%s(_internalthreadargsproto_) {\n", fname);
497 " for (_i=0; _i < %d; _i++) {\
498 _t_%s[_i] = makevector(%d*sizeof(double)); }\n",
503 Sprintf(
buf,
" _t_%s = makevector(%d*sizeof(double));\n",
s->name, ntab + 1);
521 Sprintf(
buf,
" _dx = (_tmax - _tmin_%s)/%d.; _mfac_%s = 1./_dx;\n", fname, ntab, fname);
523 Sprintf(
buf,
" for (_i=0, _x=_tmin_%s; _i < %d; _x += _dx, _i++) {\n", fname, ntab + 1);
525 if (
type == FUNCTION1) {
528 Sprintf(
buf,
" _t_%s[_i] = _f_%s(_x);\n",
s->name, fname);
530 Sprintf(
buf,
" _t_%s[_i] = _f_%s(_threadargscomma_ _x);\n",
s->name, fname);
536 Sprintf(
buf,
" _f_%s(_threadargscomma_ _x);\n", fname);
542 " for (_j = 0; _j < %d; _j++) { _t_%s[_j][_i] = %s[_j];\n}",
565 if (
type == FUNCTION1) {
573 Sprintf(
buf,
"%s(_internalthreadargsprotocomma_ double %s) {", fname, arg->
name);
578 Sprintf(
buf,
"\n#if 0\n_check_%s(_threadargs_);\n#endif\n", fname);
580 if (
type == FUNCTION1) {
587 if (
type != FUNCTION1) {
593 if (
type == FUNCTION1) {
600 Sprintf(
buf,
"_n_%s(_internalthreadargsprotocomma_ double %s){", fname, arg->
name);
607 if (
type == FUNCTION1) {
614 if (
type != FUNCTION1) {
620 Sprintf(
buf,
"_xi = _mfac_%s * (%s - _tmin_%s);\n", fname, arg->
name, fname);
623 if (
type == FUNCTION1) {
630 " for (_j = 0; _j < %d; _j++) { %s[_j] = _xi;\n}",
641 if (
type == FUNCTION1) {
649 "for (_j = 0; _j < %d; _j++) { %s[_j] = _t_%s[_j][0];\n}",
663 if (
type == FUNCTION1) {
671 "for (_j = 0; _j < %d; _j++) { %s[_j] = _t_%s[_j][%d];\n}",
677 Sprintf(
buf,
"%s = _t_%s[%d];\n",
s->name,
s->name, ntab);
686 if (
type == FUNCTION1) {
689 "return _t_%s[_i] + (_xi - (double)_i)*(_t_%s[_i+1] - _t_%s[_i]);\n",
700 "for (_j = 0; _j < %d; _j++) {double *_t = _t_%s[_j];",
704 Sprintf(
buf,
"%s[_j] = _t[_i] + _theta*(_t[_i+1] - _t[_i]);}\n",
s->name);
707 "%s = _t_%s[_i] + _theta*(_t_%s[_i+1] - _t_%s[_i]);\n",
722 Sprintf(
buf,
"static double *_t_%s[%d];\n",
s->name,
s->araydim);
745 Sprintf(
buf,
"\nstatic double _hoc_%s(void* _vptr) {\n double _r;\n",
n->name);
747 Sprintf(
buf,
"\nstatic void _hoc_%s(void) {\n double _r;\n",
n->name);
750 "\nstatic double _npy_%s(Prop* _prop) {\n"
751 " double _r{0.0};\n",
756 "Datum* _ppvar; Datum* _thread; NrnThread* _nt;\n");
759 " auto* const _pnt = static_cast<Point_process*>(_vptr);\n"
760 " auto* const _p = _pnt->_prop;\n"
762 " hoc_execerror(\"POINT_PROCESS data instance not valid\", NULL);\n"
767 " _nrn_mechanism_cache_instance _ml_real{_p};\n"
768 " auto* const _ml = &_ml_real;\n"
769 " size_t const _iml{};\n"
770 " _ppvar = _nrn_mechanism_access_dparam(_p);\n"
771 " _thread = _extcall_thread.data();\n"
772 " double* _globals = nullptr;\n"
773 " if (gind != 0 && _thread != nullptr) { _globals = _thread[_gth].get<double*>(); }\n"
774 " _nt = static_cast<NrnThread*>(_pnt->_vnt);\n");
779 "_nrn_mechanism_cache_instance _ml_real{_local_prop};\n"
780 "auto* const _ml = &_ml_real;\n"
781 "size_t const _iml{};\n"
782 "_ppvar = _local_prop ? _nrn_mechanism_access_dparam(_local_prop) : nullptr;\n"
783 "_thread = _extcall_thread.data();\n"
784 "double* _globals = nullptr;\n"
785 "if (gind != 0 && _thread != nullptr) { _globals = _thread[_gth].get<double*>(); }\n"
786 "_nt = nrn_threads;\n");
789 " neuron::legacy::set_globals_from_prop(_prop, _ml_real, _ml, _iml);\n"
790 " _ppvar = _nrn_mechanism_access_dparam(_prop);\n");
793 "_nrn_mechanism_cache_instance _ml_real{_prop};\n"
794 "auto* const _ml = &_ml_real;\n"
795 "size_t const _iml{};\n"
796 "_ppvar = _nrn_mechanism_access_dparam(_prop);\n"
797 "_thread = _extcall_thread.data();\n"
798 "double* _globals = nullptr;\n"
799 "if (gind != 0 && _thread != nullptr) { _globals = _thread[_gth].get<double*>(); }\n"
800 "_nt = nrn_threads;\n");
804 Sprintf(
buf,
"\n#if 1\n _check_%s(_threadargs_);\n#endif\n",
n->name);
815 for (
i = 0;
i <
n->varnum; ++
i) {
818 if (
i + 1 <
n->varnum) {
859 if (strcmp(
SYM(qname)->
name,
"nrn_pointing") == 0) {
868 }
else if (strcmp(
SYM(qname)->
name,
"state_discontinuity") == 0) {
869 if (blocktype == NETRECEIVE) {
877 for (
q =
qexpr;
q != qpar2;
q =
q->next) {
888 "Notice: Use of state_discontinuity is not thread safe except in a "
889 "NET_RECEIVE block");
898 }
else if (strcmp(
SYM(qname)->
name,
"net_send") == 0) {
904 if (blocktype == NETRECEIVE) {
906 }
else if (blocktype == INITIAL1) {
907 Insertstr(qpar1->
next,
"_tqitem, nullptr, _ppvar[1].get<Point_process*>(),");
909 diag(
"net_send allowed only in INITIAL and NET_RECEIVE blocks", (
char*) 0);
911 }
else if (strcmp(
SYM(qname)->
name,
"net_event") == 0) {
913 if (blocktype == NETRECEIVE) {
916 diag(
"net_event",
"only allowed in NET_RECEIVE block");
918 }
else if (strcmp(
SYM(qname)->
name,
"net_move") == 0) {
922 if (blocktype == NETRECEIVE) {
925 diag(
"net_move",
"only allowed in NET_RECEIVE block");
946 for (
i = 0,
q = qpar1->
next;
q != qpar2;
q =
q->next) {
955 diag(
"FUNCTION_TABLE declaration must have one or more arguments:",
s->name);
959 Sprintf(
buf,
"return hoc_func_table(_ptable_%s, %d, _arg);\n",
s->name,
i);
968 t->no_threadargs = 1;
975 Sprintf(
buf,
"{\n\thoc_spec_table(&_ptable_%s, %d);\n\treturn 0.;\n}\n",
s->name,
i);
977 Sprintf(
buf,
"\nstatic void* _ptable_%s = (void*)0;\n",
s->name);
987 if (blocktype != NETRECEIVE) {
988 diag(
"\"WATCH\" statement only allowed in NET_RECEIVE block", (
char*) 0);
993 " Datum* _ppvar; Datum* _thread{};\n"
994 " NrnThread* _nt{static_cast<NrnThread*>(_pnt->_vnt)};\n");
996 " auto* const _prop = _pnt->_prop;\n"
997 " _nrn_mechanism_cache_instance _ml_real{_prop};\n"
998 " auto* const _ml = &_ml_real;\n"
1000 " _ppvar = _nrn_mechanism_access_dparam(_prop);\n"
1001 " v = NODEV(_pnt->node);\n"
1006 if (
SYM(dir)->
name[0] ==
'<') {
1017 "\nstatic void _watch_alloc(Datum* _ppvar) {\n"
1018 " auto* _pnt = _ppvar[1].get<Point_process*>();\n");
1021 " _nrn_watch_allocate(_watch_array, _watch%d_cond, %d, _pnt, %s);\n",
1028 " _nrn_watch_activate(_watch_array, _watch%d_cond, %d, _pnt, _watch_rm++, %s);\n",
1039 fprintf(stderr,
"Notice: %s\n",
s);
1047 replacstr(q1,
"/* PROTECT */_NMODLMUTEXLOCK\n");
1048 q =
insertstr(q2->
next,
"\n _NMODLMUTEXUNLOCK /* end PROTECT */\n");
1054 static int toggle = 0;
1057 diag(
"MUTEXLOCK invoked after MUTEXLOCK", (
char*) 0);
1062 }
else if (on == 0) {
1064 diag(
"MUTEXUNLOCK invoked with no earlier MUTEXLOCK", (
char*) 0);
1071 diag(
"MUTEXUNLOCK not invoked after MUTEXLOCK", (
char*) 0);
static double abstol(void *v)
static HocParmLimits limits[]
std::map< std::string, const char * > extdef_rand
Symbol * ifnew_parminstall(const char *name, const char *num, const char *units, const char *limits)
void printlist(List *list)
#define ITERATE(itm, lst)
Symbol * lookup(const char *)
Symbol * install(const char *, int)
char * stralloc(const char *buf, char *rel)
void movelist(Item *q1, Item *q2, List *s)
void move(Item *q1, Item *q2, Item *q3)
Item * linsertstr(List *list, const char *str)
void replacstr(Item *q, const char *s)
Item * lappenditem(List *list, Item *item)
Item * insertstr(Item *item, const char *str)
Item * lappendsym(List *list, Symbol *sym)
Item * lappendstr(List *list, const char *str)
void freelist(List *list)
List * newlist()
The following routines support the concept of a list.
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.
void netrec_asgn(Item *varname, Item *equal, Item *expr, Item *lastok)
void hocfunc_setdata_item(Symbol *, Item *)
void vectorize_substitute(Item *q, const char *str)
NMODL parser global flags / functions.
int const size_t const size_t n
static double remove(void *v)
void depinstall(int type, Symbol *n, int index, const char *from, const char *to, const char *units, Item *qs, int makeconst, const char *abstol)
void add_reset_args(Item *q)
static Symbol * last_func_using_table
void add_nrnthread_arg(Item *q)
static List * check_table_statements
static void npyfunc(Symbol *n, int hack)
void parm_array_install(Symbol *n, const char *num, char *units, char *limits, int index)
static int func_arg_examine(Item *qpar, Item *qend)
List * state_discon_list_
void defarg(Item *q1, Item *q2)
Item * protect_astmt(Item *q1, Item *q2)
void hocfunc(Symbol *n, Item *qpar1, Item *qpar2)
void threadsafe(const char *s)
int check_tables_threads(List *p)
void vectorize_scan_for_func(Item *q1, Item *q2)
void statdefault(Symbol *n, int index, const char *units, Item *qs, int makeconst)
void hocfunchack(Symbol *n, Item *qpar1, Item *qpar2, int hack)
void parminstall(Symbol *n, const char *num, const char *units, const char *limits)
Item * vectorize_replacement_item(Item *)
static const char * indepunits
static List * check_table_thread_list
void function_table(Symbol *s, Item *qpar1, Item *qpar2, Item *qb1, Item *qb2)
void explicit_decl(Item *q)
void table_massage(List *tablist, Item *qtype, Item *qname, List *arglist)
void indepinstall(Symbol *n, const char *from, const char *to, const char *with, const char *units)
static void funchack(Symbol *n, bool ishoc, int hack)
void lag_stmt(Item *q1, int blocktype)
void vectorize_use_func(Item *qname, Item *qpar1, Item *qexpr, Item *qpar2, int blocktype)
void nrnmutex(int on, Item *q)
void watchstmt(Item *par1, Item *dir, Item *par2, Item *flag, int blocktype)
static struct table * table