NEURON
parsact.cpp
Go to the documentation of this file.
1 #include <../../nmodlconf.h>
2 
3 /*
4  * some parse actions to reduce size of parse.ypp the installation routines can
5  * also be used, e.g. in sens to automattically construct variables
6  */
7 
8 #include <stdlib.h>
9 #include "modl.h"
10 #include "parse1.hpp"
11 
12 Symbol *scop_indep; /* independent used by SCoP */
13 Symbol *indepsym; /* only one independent variable */
14 Symbol *stepsym; /* one or fewer stepped variables */
15 List *indeplist; /* FROM TO WITH START UNITS */
16 List* watch_alloc; /* text of the void _watch_alloc(Datum*) function */
17 extern List *syminorder; /* Order in which variables are output to
18  * .var file */
19 
20 #if CVODE
21 extern List* state_discon_list_;
22 extern int net_send_seen_;
23 extern int net_event_seen_;
24 extern int watch_seen_;
25 #endif
26 
30 extern int artificial_cell;
31 extern int vectorize;
32 extern int assert_threadsafe;
33 
34 int type_change(Symbol* sym, int level);
35 
36 static long previous_subtype; /* subtype at the sym->level */
37 static char *previous_str; /* u.str on last install */
38 
39 void explicit_decl(int level, Item* q)
40 {
41  /* used to be inside parse1.ypp without the lastvars condition
42  Without the condition it served two purposes.
43  1) variables explicitly declared were so marked so that they
44  would appear first in the .var file. Unmarked variables
45  appear last.
46  2) Give error message if a variable was explicitly declared
47  more than once.
48  Now, the merge program produces declaration blocks from
49  submodels with a prepended LAST_VARS keyword. This implies
50  1) that variables in such blocks should appear last (if they
51  don't appear at the top level) and
52  2) multiple declarations are not errors.
53  Hence we merely enclose the old code in an if statement
54  The question arises, on multiple declarations, which value
55  does the .var file get. In the current implementation it
56  is the last one seen. If this is not right (and a better
57  method would be keep the value declared closest to the root)
58  then it will be the responsibility of merge to delete
59  multiple declarations.
60  */
61  /* Solving the multiple declaration problem.
62  merge now gives the level number of the declaration with
63  the root file having level number 0, all its submodels having
64  level number 1, submodels of level 1 submodels having level 2,
65  etc. The rule is that the lowest level declaration is used.
66  If two declarations exist at the same level then it is an
67  error unless their u.str are identical. Since, by the time
68  this routine is called the latest declaration has already been
69  installed, each installation routine saves the previous u.str
70  in a static variable. Also a new field is added to the
71  symbol structure to keep track of its level. At this time
72  we retain the EXPLICIT_DECL field for explicit declarations
73  at the root level. The default level when the symbol is
74  allocated is 100.
75  */
76 
77  Symbol *sym;
78 
79  sym = SYM(q);
80  if (!level) { /* No multiple declarations at the root level and
81  the symbol is marked explicitly declared */
82  if (sym->usage & EXPLICIT_DECL) {
83  diag("Multiple declaration of ", sym->name);
84  }
85  sym->usage |= EXPLICIT_DECL;
86  }
87  /* this ensures that declared PRIMES will appear in .var file */
88  sym->usage |= DEP;
89 
90  if (level >= sym->level) {
92  }
93  /* resolve possible type conflicts */
94  if (type_change(sym, level)) {
95  return;
96  }
97  /* resolve which declaration takes precedence */
98  if (level < sym->level) { /* new one takes precedence */
99  sym->level = level;
100  }else if (level > sym->level) { /* old one takes precedence */
101  sym->u.str = previous_str;
102  }else if (strcmp(sym->u.str, previous_str) != 0) { /* not identical */
103  diag(sym->name, "has different values at same level");
104  }
105 }
106 
107 /* restricted type changes are allowed in hierarchical models with each
108 one producing a message. Notice that multiple declarations at level 0 are
109 caught as errors in the function above. */
110 
111 int type_change(Symbol* sym, int level) /*return 1 if type change, 0 otherwise*/
112 {
113  long s, d, c;
114 
115  s = sym->subtype & STAT;
116  d = sym->subtype & DEP;
117  c = sym->subtype & PARM;
118 
119  if (s && c) {
120  sym->subtype &= ~c;
121 Fprintf(stderr, "Notice: %s is promoted from a PARAMETER to a STATE\n", sym->name);
122  if (previous_subtype & STAT) {
123  sym->u.str = previous_str;
124  }
125  }else if (s && d) {
126  sym->subtype &= ~d;
127 Fprintf(stderr, "WARNING: %s is promoted from an ASSIGNED to a STATE\n", sym->name);
128  if (previous_subtype & STAT) {
129  sym->u.str = previous_str;
130  }
131  }else if (d && c) {
132  sym->subtype &= ~c;
133 Fprintf(stderr, "Notice: %s is promoted from a PARAMETER to an ASSIGNED\n", sym->name);
134  if (previous_subtype & DEP) {
135  sym->u.str = previous_str;
136  }
137  }else{
138  return 0;
139  }
140  if (level < sym->level) {
141  sym->level = level;
142  }
143  return 1;
144 }
145 
146 void parm_array_install(Symbol* n, char* num, char* units, char* limits, int index)
147 {
148  char buf[NRN_BUFSIZE];
149 
151  previous_str = n->u.str;
152  if (n->u.str == (char *) 0)
153  Lappendsym(syminorder, n);
154  n->subtype |= PARM;
155  n->subtype |= ARRAY;
156  n->araydim = index;
157  Sprintf(buf, "[%d]\n%s\n%s\n%s\n", index, num, units, limits);
158  n->u.str = stralloc(buf, (char *) 0);
159 }
160 
161 void parminstall(Symbol* n, char* num, char* units, char* limits)
162 {
163  char buf[NRN_BUFSIZE];
164 
166  previous_str = n->u.str;
167  if (n->u.str == (char *) 0)
168  Lappendsym(syminorder, n);
169  n->subtype |= PARM;
170  Sprintf(buf, "\n%s\n%s\n%s\n", num, units, limits);
171  n->u.str = stralloc(buf, (char *) 0);
172 }
173 
174 /* often we want to install a parameter by default but only
175 if the user hasn't declared it herself.
176 */
177 Symbol *ifnew_parminstall(char* name, char* num, char* units, char* limits)
178 {
179  Symbol *s;
180 
181  if ((s = lookup(name)) == SYM0) {
182  s = install(name, NAME);
183  parminstall(s, num, units, limits);
184  }
185  if (!(s->subtype)) {
186  /* can happen when PRIME used in MATCH */
187  parminstall(s, num, units, limits);
188  }
189  if (!(s->subtype & (PARM | STEP1))) {
190  /* special case is scop_indep can be a PARM but not indepsym */
191  if (scop_indep == indepsym || s != scop_indep) {
192  diag(s->name, "can't be declared a parameter by default");
193  }
194  }
195  return s;
196 }
197 
198 void steppedinstall(Symbol* n, Item* q1, Item* q2, char* units)
199 {
200  int i;
201 
202  char buf[NRN_BUFSIZE];
203  static int seestep = 0;
204 
206  previous_str = n->u.str;
207  if (seestep) {
208  diag("Only one STEPPED variable can be defined", (char *) 0);
209  }
210  seestep = 1;
211  stepsym = n;
212  i = 0;
213  Strcpy(buf, "\n");
214  Strcat(buf, STR(q1));
215  while (q1 != q2) {
216  q1 = q1->next;
217  Strcat(buf, SYM(q1)->name); /* , is a symbol */
218  q1 = q1->next;
219  Strcat(buf, STR(q1));
220  i++;
221  if (i > 5) {
222  diag("Maximum of 5 steps in a stepped variable",
223  (char *) 0);
224  }
225  }
226  Strcat(buf, "\n");
227  Strcat(buf, units);
228  Strcat(buf, "\n");
229  n->subtype |= STEP1;
230  n->u.str = stralloc(buf, (char *) 0);
231 }
232 
233 static char *indepunits = "";
234 #if NMODL
235 int using_default_indep;
236 #endif
237 
238 void indepinstall(Symbol* n, char* from, char* to, char* with, Item* qstart, char* units, int scop)
239 {
240  char buf[NRN_BUFSIZE];
241 
242 /* scop_indep may turn out to be different from indepsym. If this is the case
243  then indepsym will be a constant in the .var file (see parout.c).
244  If they are the same, then u.str gets the info from SCOP.
245 */
246 if (!scop) {
247 #if NMODL
248  if (using_default_indep) {
249  using_default_indep = 0;
250  if (indepsym != n) {
251  indepsym->subtype &= ~INDEP;
252  parminstall(indepsym, "0", "ms", "");
253  }
254  indepsym = (Symbol*)0;
255 
256  }
257 #endif
258  if (indepsym) {
259 diag("Only one independent variable can be defined", (char *) 0);
260  }
261  indeplist = newlist();
262  Lappendstr(indeplist, from);
263  Lappendstr(indeplist, to);
264  Lappendstr(indeplist, with);
265  if (qstart) {
266  Lappendstr(indeplist, STR(qstart));
267  }else{
268  Lappendstr(indeplist, from);
269  }
270  Lappendstr(indeplist, units);
271  n->subtype |= INDEP;
272  indepunits = stralloc(units, (char *) 0);
273  if (n != scop_indep) {
274  Sprintf(buf, "\n%s*%s(%s)\n%s\n", from, to, with, units);
275  n->u.str = stralloc(buf, (char *) 0);
276  }
277  indepsym = n;
278  if (!scop_indep) {
279  scop_indep = indepsym;
280  }
281 }else{
282  n->subtype |= INDEP;
283  Sprintf(buf, "\n%s*%s(%s)\n%s\n", from, to, with, units);
284  n->u.str = stralloc(buf, (char *) 0);
285  scop_indep = n;
286 }
287 }
288 
289 /*
290  * installation of dependent and state variables type 0 -- dependent; 1 --
291  * state index 0 -- scalar; otherwise -- array qs -- item pointer to START
292  * const string makeconst 0 -- do not make a default constant for state 1 --
293  * make sure name0 exists For states Dname and name0 are normally created.
294  * However Dname will not appear in the .var file unless it is used -- see
295  * parout.c.
296  */
297 void depinstall(int type, Symbol* n, int index, char* from, char* to, char* units, Item* qs, int makeconst, char* abstol)
298 {
299  char buf[NRN_BUFSIZE], *pstr;
300  int c;
301 
302  if (!type && strlen(abstol)>0) {
303  printf("abstol = |%s|\n", abstol);
304  diag(n->name, "tolerance can be specified only for a STATE");
305  }
306  pstr = n->u.str; /* make it work even if recursive */
307  if (n->u.str == (char *) 0)
308  Lappendsym(syminorder, n);
309  if (type) {
310  n->subtype |= STAT;
311  c = ':';
312  statdefault(n, index, units, qs, makeconst);
313  } else {
314  n->subtype |= DEP;
315  c = ';';
316  if (qs) {
317  diag("START not legal except in STATE block", (char *) 0);
318  }
319  }
320  if (index) {
321  Sprintf(buf, "[%d]\n%s%c%s\n%s\n%s\n", index, from, c, to, units, abstol);
322  n->araydim = index;
323  n->subtype |= ARRAY;
324  } else {
325  Sprintf(buf, "\n%s%c%s\n%s\n%s\n", from, c, to, units, abstol);
326  }
327  n->u.str = stralloc(buf, (char *) 0);
329  previous_str = pstr;
330 }
331 
332 void statdefault(Symbol* n, int index, char* units, Item* qs, int makeconst)
333 {
334  char nam[256], *un;
335  Symbol *s;
336 
337  if (n->type != NAME && n->type != PRIME) {
338  diag(n->name, "can't be a STATE");
339  }
340  if (makeconst) {
341  Sprintf(nam, "%s0", n->name);
342  s = ifnew_parminstall(nam, "0", units, "");
343  if (qs) { /*replace with proper default*/
344  parminstall(s, STR(qs), units, "");
345  }
346  }
347  Sprintf(nam, "%s/%s", units, indepunits);
348  un = stralloc(nam, (char *) 0);
349  Sprintf(nam, "D%s", n->name);
350  if ((s = lookup(nam)) == SYM0) { /* install the prime as a DEP */
351  s = install(nam, PRIME);
352  depinstall(0, s, index, "0", "1", un, ITEM0, 0, "");
353  }
354 }
355 
356 /* the problem is that qpar->next may already have a _p, ..., _nt
357 vectorize_substitute, and qpar->next is often normally "" instead of ')'
358 for the no arg case.
359 */
360 static int func_arg_examine(Item* qpar, Item* qend) {
361  Item* q;
362  int b = 1; /* real args exist case */
363  q = qpar->next;
364  if (q->itemtype == SYMBOL && strcmp(SYM(q)->name, ")") == 0) {
365  b = 0; /* definitely no arg */
366  }
367  if (q->itemtype == STRING && strcmp(STR(q), "") == 0) {
369  b = 2; /* _p,..._nt already there */
370  } else if (q->next->itemtype == SYMBOL && strcmp(SYM(q->next)->name, ")") == 0) {
371  b = 0; /* definitely no arg */
372  }
373  }
374  return b;
375 }
376 
378  Item* q, *qq;
379  int b;
380  return;
381  for (q = q1; q != q2; q = q->next) {
382  if (q->itemtype == SYMBOL) {
383  Symbol* s = SYM(q);
384  if ((s->usage & FUNCT) && !(s->subtype & (EXTDEF))) {
385  if (q->next->itemtype == SYMBOL && strcmp(SYM(q->next)->name, "(") == 0) {
386  int b = func_arg_examine(q->next, q2);
387  if (b == 0) { /* no args */
388  vectorize_substitute(q->next, "(_p, _ppvar, _thread, _nt");
389  }else if (b == 1) { /* real args */
390  vectorize_substitute(q->next, "(_p, _ppvar, _thread, _nt,");
391  } /* else no _p.._nt already there */
392  }
393  }
394  }
395  }
396 }
397 
398 void defarg(Item* q1, Item* q2) /* copy arg list and define as doubles */
399 {
400  Item *q3, *q;
401 
402  if (q1->next == q2) {
403 #if VECTORIZE
404  vectorize_substitute(insertstr(q2, ""), "_threadargsproto_");
405 #endif
406  return;
407  }
408  for (q = q1->next; q != q2; q = q->next) {
409  if (strcmp(SYM(q)->name, ",") != 0) {
410  insertstr(q, "double");
411  }
412  }
413 #if VECTORIZE
414  vectorize_substitute(insertstr(q1->next, ""), "_threadargsprotocomma_");
415 #endif
416 }
417 
418 void lag_stmt(Item* q1, int blocktype) /* LAG name1 BY name2 */
419 {
420  Symbol *name1, *name2, *lagval;
421 
422  /*ARGSUSED*/
423  /* parse */
424  name1 = SYM(q1->next);
425  remove(q1->next);
426  remove(q1->next);
427  name2 = SYM(q1->next);
428  remove(q1->next);
429  name1->usage |= DEP;
430  name2->usage |= DEP;
431  /* check */
432  if (!indepsym) {
433  diag("INDEPENDENT variable must be declared to process",
434  "the LAG statement");
435  }
436  if (!(name1->subtype & (DEP | STAT))) {
437  diag(name1->name, "not a STATE or DEPENDENT variable");
438  }
439  if (!(name2->subtype & (PARM | nmodlCONST))) {
440  diag(name2->name, "not a CONSTANT or PARAMETER");
441  }
442  Sprintf(buf, "lag_%s_%s", name1->name, name2->name);
443  if (lookup(buf)) {
444  diag(buf, "already in use");
445  }
446  /* create */
447  lagval = install(buf, NAME);
448  lagval->usage |= DEP;
449  lagval->subtype |= DEP;
450  if (name1->subtype & ARRAY) {
451  lagval->subtype |= ARRAY;
452  lagval->araydim = name1->araydim;
453  }
454  if (lagval->subtype & ARRAY) {
455  Sprintf(buf, "static double *%s;\n", lagval->name);
457  Sprintf(buf, "%s = lag(%s, %s, %s, %d);\n", lagval->name,
458  name1->name, indepsym->name, name2->name, lagval->araydim);
459  }else{
460  Sprintf(buf, "static double %s;\n", lagval->name);
462  Sprintf(buf, "%s = *lag(&(%s), %s, %s, 0);\n", lagval->name,
463  name1->name, indepsym->name, name2->name);
464  }
465  replacstr(q1, buf);
466 }
467 
468 void queue_stmt(Item* q1, Item* q2)
469 {
470  Symbol *s;
471  static int first=1;
472 
473  if (first) {
474  first = 0;
475  Linsertstr(initfunc, "initqueue();\n");
476  }
477  if (SYM(q1)->type == PUTQ) {
478  replacstr(q1, "enqueue(");
479  }else{
480  replacstr(q1, "dequeue(");
481  }
482 
483  s = SYM(q2);
484  s->usage |= DEP;
485  if (!(s->subtype)) {
486  diag(s->name, "not declared");
487  }
488  if (s->subtype & ARRAY) {
489  Sprintf(buf, "%s, %d);\n", s->name, s->araydim);
490  }else{
491  Sprintf(buf, "&(%s), 1);\n", s->name);
492  }
493  replacstr(q2, buf);
494 }
495 
497 {
498  static int reset_fun_cnt=0;
499 
500  reset_fun_cnt++;
501  Sprintf(buf, "&_reset, &_freset%d,", reset_fun_cnt);
502  Insertstr(q->next, buf);
503  Sprintf(buf, "static double _freset%d;\n", reset_fun_cnt);
505 }
506 
508 {
509  vectorize_substitute(insertstr(q->next, "nrn_threads,"), "_nt,");
510 }
511 
512 /* table manipulation */
513 /* arglist must have exactly one argument
514  tablist contains 1) list of names to be looked up (must be empty if
515  qtype is FUNCTION and nonempty if qtype is PROCEDURE).
516  2) From expression list
517  3) To expression list
518  4) With integer string
519  5) DEPEND list as list of names
520  The qname does not have a _l if a function. The arg names all have _l
521  prefixes.
522 */
523 /* checking and creation of table has been moved to separate function called
524  static _check_func.
525 */
526 /* to allow vectorization the table functions are separated into
527  name robust function. makes sure
528  table is uptodate (calls check_name)
529  _check_name if table not up to date then builds table
530  _f_name analytic
531  _n_name table lookup with no checking if usetable=1
532  otherwise calls _f_name.
533 */
534 
537 
538 void check_tables() {
539  /* for threads do this differently */
540  if (check_table_statements) {
541  fprintf(fcout, "\n#if %d\n", 0);
542  printlist(check_table_statements);
543  fprintf(fcout, "#endif\n");
544  }
545 }
546 
547 /* this way we can make sure the tables are up to date in the main thread
548 at critical points in the finitialize, nrn_fixed_step, etc. The only
549 requirement is that the function that generates the table not use
550 any except GLOBAL parameters and assigned vars not requiring
551 an initial value, because we are probably going to
552 call this with nonsense _p, _ppvar, and _thread
553 */
556  Item* q;
557  if (check_table_thread_list) {
558  ITERATE(q, check_table_thread_list) {
559  sprintf(buf, "\nstatic void %s(double*, Datum*, Datum*, NrnThread*);", STR(q));
560  lappendstr(p, buf);
561  }
562  lappendstr(p, "\nstatic void _check_table_thread(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt, int _type) {\n");
563  ITERATE(q, check_table_thread_list) {
564  sprintf(buf, " %s(_p, _ppvar, _thread, _nt);\n", STR(q));
565  lappendstr(p, buf);
566  }
567  lappendstr(p, "}\n");
568  return 1;
569  }
570  return 0;
571 }
572 
573 void table_massage(List* tablist, Item* qtype, Item* qname, List* arglist)
574 {
575  Symbol *fsym, *s, *arg=0;
576  char* fname;
577  List *table, *from, *to, *depend;
578  int type, ntab;
579  Item *q;
580 
581  if (!tablist) {
582  return;
583  }
584  fsym = SYM(qname);
585  last_func_using_table = fsym;
586  fname = fsym->name;
587  table = LST(q = tablist->next);
588  from = LST(q = q->next);
589  to = LST(q = q->next);
590  ntab = atoi(STR(q = q->next));
591  depend = LST(q = q->next);
592  type = SYM(qtype)->type;
593 
594  ifnew_parminstall("usetable", "1", "", "0 1");
595  if (!check_table_statements) {
596  check_table_statements = newlist();
597  }
598  sprintf(buf, "_check_%s();\n", fname);
599  q = lappendstr(check_table_statements, buf);
600  sprintf(buf, "_check_%s(_p, _ppvar, _thread, _nt);\n", fname);
602  /*checking*/
603  if (type == FUNCTION1) {
604  if (table) {
605 diag("TABLE stmt in FUNCTION cannot have a table name list", (char *)0);
606  }
607  table = newlist();
608  Lappendsym(table, fsym);
609  }else{
610  if (!table) {
611 diag("TABLE stmt in PROCEDURE must have a table name list", (char *)0);
612  }
613  }
614  if (arglist->next == arglist || arglist->next->next != arglist) {
615 diag("FUNCTION or PROCEDURE containing a TABLE stmt\n",
616 "must have exactly one argument");
617  }else{
618  arg = SYM(arglist->next);
619  }
620  if (!depend) {
621  depend = newlist();
622  }
623 
624  /*translation*/
625  /* new name for original function */
626  Sprintf(buf, "_f_%s", fname);
627  SYM(qname) = install(buf, fsym->type);
628  SYM(qname)->subtype = fsym->subtype;
629  SYM(qname)->varnum = fsym->varnum;
630  if (type == FUNCTION1) {
631  fsym->subtype |= FUNCT;
632  Sprintf(buf, "static double _n_%s(double);\n", fname);
633  q = linsertstr(procfunc, buf);
634 #if VECTORIZE
635  Sprintf(buf, "static double _n_%s(_threadargsprotocomma_ double _lv);\n", fname);
637 #endif
638  }else{
639  fsym->subtype |= PROCED;
640  Sprintf(buf, "static void _n_%s(double);\n", fname);
641  q = linsertstr(procfunc, buf);
642 #if VECTORIZE
643  Sprintf(buf, "static void _n_%s(_threadargsprotocomma_ double _lv);\n", fname);
645 #endif
646  }
647  fsym->usage |= FUNCT;
648 
649  /* declare communication between func and check_func */
650  Sprintf(buf, "static double _mfac_%s, _tmin_%s;\n",
651  fname, fname);
653 
654  /* create the check function */
655  if (!check_table_thread_list) {
656  check_table_thread_list = newlist();
657  }
658  sprintf(buf, "_check_%s", fname);
659  lappendstr(check_table_thread_list, buf);
660  Sprintf(buf, "static void _check_%s();\n", fname);
661  q = insertstr(procfunc, buf);
662  vectorize_substitute(q, "");
663  Sprintf(buf, "static void _check_%s() {\n", fname);
664  q = lappendstr(procfunc, buf);
665  Sprintf(buf, "static void _check_%s(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt) {\n", fname);
667  Lappendstr(procfunc, " static int _maktable=1; int _i, _j, _ix = 0;\n");
668  Lappendstr(procfunc, " double _xi, _tmax;\n");
669  ITERATE(q, depend) {
670  Sprintf(buf, " static double _sav_%s;\n", SYM(q)->name);
672  }
673  lappendstr(procfunc, " if (!usetable) {return;}\n");
674  /*allocation*/
675  ITERATE(q, table) {
676  s = SYM(q);
677  if (s->subtype & ARRAY) {
678  Sprintf(buf, " for (_i=0; _i < %d; _i++) {\
679  _t_%s[_i] = makevector(%d*sizeof(double)); }\n", s->araydim, s->name, ntab+1);
680  }else{
681  Sprintf(buf, " _t_%s = makevector(%d*sizeof(double));\n",
682  s->name, ntab+1);
683  }
685  }
686  /* check dependency */
687  ITERATE(q, depend) {
688  Sprintf(buf, " if (_sav_%s != %s) { _maktable = 1;}\n",
689  SYM(q)->name, SYM(q)->name);
691  }
692  /* make the table */
693  Lappendstr(procfunc, " if (_maktable) { double _x, _dx; _maktable=0;\n");
694  Sprintf(buf, " _tmin_%s = ", fname);
696  move(from->next, from->prev, procfunc);
697  Sprintf(buf, ";\n _tmax = ");
699  move(to->next, to->prev, procfunc);
700  Lappendstr(procfunc, ";\n");
701  Sprintf(buf," _dx = (_tmax - _tmin_%s)/%d.; _mfac_%s = 1./_dx;\n",
702  fname, ntab, fname);
704  Sprintf(buf," for (_i=0, _x=_tmin_%s; _i < %d; _x += _dx, _i++) {\n",
705  fname, ntab+1);
707  if (type == FUNCTION1) {
708  ITERATE(q, table) {
709  s = SYM(q);
710  Sprintf(buf, " _t_%s[_i] = _f_%s(_x);\n", s->name, fname);
712 #if VECTORIZE
713  Sprintf(buf, " _t_%s[_i] = _f_%s(_p, _ppvar, _thread, _nt, _x);\n", s->name, fname);
715 #endif
716  }
717  }else{
718  Sprintf(buf, " _f_%s(_x);\n", fname);
720 #if VECTORIZE
721  Sprintf(buf, " _f_%s(_p, _ppvar, _thread, _nt, _x);\n", fname);
723 #endif
724  ITERATE(q, table) {
725  s = SYM(q);
726  if (s->subtype & ARRAY) {
727 Sprintf(buf, " for (_j = 0; _j < %d; _j++) { _t_%s[_j][_i] = %s[_j];\n}",
728 s->araydim, s->name, s->name);
729  }else{
730 Sprintf(buf, " _t_%s[_i] = %s;\n", s->name, s->name);
731  }
733  }
734  }
735  Lappendstr(procfunc, " }\n"); /*closes loop over _i index*/
736  /* save old dependency values */
737  ITERATE(q, depend) {
738  s = SYM(q);
739  Sprintf(buf, " _sav_%s = %s;\n", s->name, s->name);
741  }
742  Lappendstr(procfunc, " }\n"); /* closes if(maktable)) */
743  Lappendstr(procfunc, "}\n\n");
744 
745 
746  /* create the new function (steers to analytic or table) */
747  /*declaration*/
748  if (type == FUNCTION1) {
749 #define GLOBFUNC 1
750 #if !GLOBFUNC
751  Lappendstr(procfunc, "static int");
752 #endif
753  Lappendstr(procfunc, "double");
754  }else{
755  Lappendstr(procfunc, "static int");
756  }
757  Sprintf(buf, "%s(double %s){",
758  fname, arg->name);
760 #if VECTORIZE
761  Sprintf(buf, "%s(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt, double %s) {",
762  fname, arg->name);
764 #endif
765  /* check the table */
766  Sprintf(buf, "_check_%s();\n", fname);
767  q = lappendstr(procfunc, buf);
768 #if VECTORIZE
769  Sprintf(buf, "\n#if 0\n_check_%s(_p, _ppvar, _thread, _nt);\n#endif\n", fname);
771 #endif
772  if (type == FUNCTION1) {
773  Lappendstr(procfunc, "return");
774  }
775  Sprintf(buf, "_n_%s(%s);\n", fname, arg->name);
777 #if VECTORIZE
778  Sprintf(buf, "_n_%s(_p, _ppvar, _thread, _nt, %s);\n", fname, arg->name);
780 #endif
781  if (type != FUNCTION1) {
782  Lappendstr(procfunc, "return 0;\n");
783  }
784  Lappendstr(procfunc, "}\n\n"); /* end of new function */
785 
786  /* _n_name function for table lookup with no checking */
787  if (type == FUNCTION1) {
788  Lappendstr(procfunc, "static double");
789  }else{
790  Lappendstr(procfunc, "static void");
791  }
792  Sprintf(buf, "_n_%s(double %s){",
793  fname, arg->name);
795 #if VECTORIZE
796  Sprintf(buf, "_n_%s(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt, double %s){",
797  fname, arg->name);
799 #endif
800  Lappendstr(procfunc, "int _i, _j;\n");
801  Lappendstr(procfunc, "double _xi, _theta;\n");
802 
803  /* usetable */
804  Lappendstr(procfunc, "if (!usetable) {\n");
805  if (type == FUNCTION1) {
806  Lappendstr(procfunc, "return");
807  }
808  Sprintf(buf, "_f_%s(%s);", fname, arg->name);
810 #if VECTORIZE
811  Sprintf(buf, "_f_%s(_p, _ppvar, _thread, _nt, %s);", fname, arg->name);
813 #endif
814  if (type != FUNCTION1) {
815  Lappendstr(procfunc, "return;");
816  }
817  Lappendstr(procfunc, "\n}\n");
818 
819  /* table lookup */
820  Sprintf(buf, "_xi = _mfac_%s * (%s - _tmin_%s);\n",
821  fname, arg->name, fname);
823  Lappendstr(procfunc, "if (isnan(_xi)) {\n");
824  if (type == FUNCTION1) {
825  Lappendstr(procfunc, " return _xi; }\n");
826  }else{
827  ITERATE(q, table) {
828  s = SYM(q);
829  if (s->subtype & ARRAY) {
830 Sprintf(buf, " for (_j = 0; _j < %d; _j++) { %s[_j] = _xi;\n}",
831 s->araydim, s->name);
832  }else{
833 Sprintf(buf, " %s = _xi;\n", s->name);
834  }
836  }
837  Lappendstr(procfunc, " return;\n }\n");
838  }
839  Lappendstr(procfunc, "if (_xi <= 0.) {\n");
840  if (type == FUNCTION1) {
841  Sprintf(buf, "return _t_%s[0];\n", SYM(table->next)->name);
843  }else{
844  ITERATE(q, table) {
845  s = SYM(q);
846  if (s->subtype & ARRAY) {
847 Sprintf(buf, "for (_j = 0; _j < %d; _j++) { %s[_j] = _t_%s[_j][0];\n}",
848 s->araydim, s->name, s->name);
849  }else{
850 Sprintf(buf, "%s = _t_%s[0];\n", s->name, s->name);
851  }
853  }
854  Lappendstr(procfunc, "return;");
855  }
856  Lappendstr(procfunc, "}\n");
857  Sprintf(buf, "if (_xi >= %d.) {\n", ntab);
859  if (type == FUNCTION1) {
860  Sprintf(buf, "return _t_%s[%d];\n", SYM(table->next)->name, ntab);
862  }else{
863  ITERATE(q, table) {
864  s = SYM(q);
865  if (s->subtype & ARRAY) {
866 Sprintf(buf, "for (_j = 0; _j < %d; _j++) { %s[_j] = _t_%s[_j][%d];\n}",
867 s->araydim, s->name, s->name, ntab);
868  }else{
869 Sprintf(buf, "%s = _t_%s[%d];\n", s->name, s->name, ntab);
870  }
872  }
873  Lappendstr(procfunc, "return;");
874  }
875  Lappendstr(procfunc, "}\n");
876  /* table interpolation */
877  Lappendstr(procfunc, "_i = (int) _xi;\n");
878  if (type == FUNCTION1) {
879  s = SYM(table->next);
880 Sprintf(buf, "return _t_%s[_i] + (_xi - (double)_i)*(_t_%s[_i+1] - _t_%s[_i]);\n",
881  s->name, s->name, s->name);
883  }else{
884  Lappendstr(procfunc, "_theta = _xi - (double)_i;\n");
885  ITERATE(q, table) {
886  s = SYM(q);
887  if (s->subtype & ARRAY) {
888 Sprintf(buf, "for (_j = 0; _j < %d; _j++) {double *_t = _t_%s[_j];",
889 s->araydim, s->name);
891 Sprintf(buf, "%s[_j] = _t[_i] + _theta*(_t[_i+1] - _t[_i]);}\n",
892  s->name);
893  }else{
894 Sprintf(buf, "%s = _t_%s[_i] + _theta*(_t_%s[_i+1] - _t_%s[_i]);\n",
895 s->name, s->name, s->name, s->name);
896  }
898  }
899  }
900  Lappendstr(procfunc, "}\n\n"); /* end of new function */
901 
902  /* table declaration */
903  ITERATE(q, table) {
904  s = SYM(q);
905  if (s->subtype & ARRAY) {
906  Sprintf(buf, "static double *_t_%s[%d];\n",
907  s->name, s->araydim);
908  }else{
909  Sprintf(buf, "static double *_t_%s;\n", s->name);
910  }
912  }
913 
914  /*cleanup*/
915  freelist(&table);
916  freelist(&depend);
917  freelist(&from);
918  freelist(&to);
919 }
920 
921 #if HMODL || NMODL
922 void hocfunchack(Symbol* n, Item* qpar1, Item* qpar2, int hack)
923 {
924 #if NOCMODL
925  extern int point_process;
926 #endif
927  Item *q;
928  int i;
929 #if VECTORIZE
930  Item* qp=0;
931 #endif
932 
933  if (point_process) {
934  Sprintf(buf, "\nstatic double _hoc_%s(void* _vptr) {\n double _r;\n", n->name);
935  }else{
936  Sprintf(buf, "\nstatic void _hoc_%s(void) {\n double _r;\n", n->name);
937  }
940  double* _p; Datum* _ppvar; Datum* _thread; NrnThread* _nt;\n\
941 ");
942  if (point_process) {
943  vectorize_substitute(lappendstr(procfunc, " _hoc_setdata(_vptr);\n"), "\
944  _p = ((Point_process*)_vptr)->_prop->param;\n\
945  _ppvar = ((Point_process*)_vptr)->_prop->dparam;\n\
946  _thread = _extcall_thread;\n\
947  _nt = (NrnThread*)((Point_process*)_vptr)->_vnt;\n\
948 ");
949  }else{
951  if (_extcall_prop) {_p = _extcall_prop->param; _ppvar = _extcall_prop->dparam;}else{ _p = (double*)0; _ppvar = (Datum*)0; }\n\
952  _thread = _extcall_thread;\n\
953  _nt = nrn_threads;\n\
954 ");
955  }
956 #if VECTORIZE
957  if (n == last_func_using_table) {
958  qp = lappendstr(procfunc, "");
959  sprintf(buf,"\n#if 1\n _check_%s(_p, _ppvar, _thread, _nt);\n#endif\n", n->name);
961  }
962 #endif
963  if (n->subtype & FUNCT) {
964  Lappendstr(procfunc, "_r = ");
965  }else{
966  Lappendstr(procfunc, "_r = 1.;\n");
967  }
968  Lappendsym(procfunc, n);
969  lappendstr(procfunc, "(");
970 #if VECTORIZE
971  qp = lappendstr(procfunc, "");
972 #endif
973  for (i=0; i < n->varnum; ++i) {
974  Sprintf(buf, "*getarg(%d)", i+1);
976  if (i+1 < n->varnum) {
977  Lappendstr(procfunc, ",");
978  }
979  }
980 #if NOCMODL
981  if (point_process) {
982  Lappendstr(procfunc, ");\n return(_r);\n}\n");
983  }else
984 #endif
985  Lappendstr(procfunc, ");\n hoc_retpushx(_r);\n}\n");
986 #if VECTORIZE
987  if (i) {
988  vectorize_substitute(qp, "_p, _ppvar, _thread, _nt,");
989  }else if (!hack) {
990  vectorize_substitute(qp, "_p, _ppvar, _thread, _nt");
991  }
992 #endif
993 }
994 
995 void hocfunc(Symbol* n, Item* qpar1, Item* qpar2) /*interface between modl and hoc for proc and func */
996 {
997  /* Hack prevents FUNCTION_TABLE bug of 'double table_name()' extra args
998  replacing the double in 'double name(...) */
999  hocfunchack(n, qpar1, qpar2, 0);
1000 }
1001 
1002 #if VECTORIZE
1003 /* ARGSUSED */
1004 void vectorize_use_func(Item* qname, Item* qpar1, Item* qexpr, Item* qpar2, int blocktype)
1005 {
1006  Item* q;
1007  if (SYM(qname)->subtype & EXTDEF) {
1008  if (strcmp(SYM(qname)->name, "nrn_pointing") == 0) {
1009  Insertstr(qpar1->next, "&");
1010  }else if (strcmp(SYM(qname)->name, "state_discontinuity") == 0) {
1011 #if CVODE
1012  if (blocktype == NETRECEIVE) {
1013  Item* qeq = NULL;
1014  /* convert to state = expr form and process with netrec_discon(...) */
1015  replacstr(qname, "");
1016  replacstr(qpar1, "");
1017  replacstr(qpar2, "");
1018  /* qexpr begins state, expr */
1019  /* find the first , and replace by = */
1020  for (q = qexpr; q != qpar2; q = q->next) {
1021  if (q->itemtype == SYMBOL && strcmp(SYM(q)->name, ",") == 0) {
1022  qeq = q;
1023  replacstr(qeq, "=");
1024  break;
1025  }
1026  }
1027  assert(qeq);
1028  netrec_asgn(qexpr, qeq, qeq->next, qpar2);
1029  }else{
1030 fprintf(stderr, "Notice: Use of state_discontinuity is not thread safe except in a NET_RECEIVE block");
1031  vectorize = 0;
1032  if (!state_discon_list_) {
1033  state_discon_list_ = newlist();
1034  Linsertstr(procfunc, "extern int state_discon_flag_;\n");
1035  }
1036  lappenditem(state_discon_list_, qpar1->next);
1037  Insertstr(qpar1->next, "-1, &");
1038  }
1039 #endif
1040  }else if (strcmp(SYM(qname)->name, "net_send") == 0) {
1041  net_send_seen_ = 1;
1042  if (artificial_cell) {
1043  replacstr(qname, "artcell_net_send");
1044  }
1045  Insertstr(qexpr, "t + ");
1046  if (blocktype == NETRECEIVE) {
1047  Insertstr(qpar1->next, "_tqitem, _args, _pnt,");
1048  }else if (blocktype == INITIAL1){
1049  Insertstr(qpar1->next, "_tqitem, (double*)0, _ppvar[1]._pvoid,");
1050  }else{
1051 diag("net_send allowed only in INITIAL and NET_RECEIVE blocks", (char*)0);
1052  }
1053  }else if (strcmp(SYM(qname)->name, "net_event") == 0) {
1054  net_event_seen_ = 1;
1055  if (blocktype == NETRECEIVE) {
1056  Insertstr(qpar1->next, "_pnt,");
1057  }else{
1058 diag("net_event", "only allowed in NET_RECEIVE block");
1059  }
1060  }else if (strcmp(SYM(qname)->name, "net_move") == 0) {
1061  if (artificial_cell) {
1062  replacstr(qname, "artcell_net_move");
1063  }
1064  if (blocktype == NETRECEIVE) {
1065  Insertstr(qpar1->next, "_tqitem, _pnt,");
1066  }else{
1067 diag("net_move", "only allowed in NET_RECEIVE block");
1068  }
1069  }
1070  return;
1071  }
1072 #if 1
1073  if (qexpr) {
1074  q = insertstr(qpar1->next, "_threadargscomma_");
1075  }else{
1076  q = insertstr(qpar1->next, "_threadargs_");
1077  }
1078 #else
1079  q = insertstr(qpar1->next, "");
1080  if (qexpr) {
1081  vectorize_substitute(q, "_p, _ppvar, _thread, _nt,");
1082  }else{
1083  vectorize_substitute(q, "_p, _ppvar, _thread, _nt");
1084  }
1085 #endif
1086 }
1087 #endif
1088 
1089 #endif
1090 
1091 void function_table(Symbol* s, Item* qpar1, Item* qpar2, Item* qb1, Item* qb2) /* s ( ... ) { ... } */
1092 {
1093  Symbol* t;
1094  int i;
1095  Item* q, *q1, *q2;
1096  for (i=0, q=qpar1->next; q != qpar2; q = q->next) {
1097 #if VECTORIZE
1098  if (q->itemtype == STRING || SYM(q)->name[0] != '_') {
1099  continue;
1100  }
1101 #endif
1102  sprintf(buf, "_arg[%d] = %s;\n", i, SYM(q)->name);
1103  insertstr(qb2, buf);
1104  ++i;
1105  }
1106  if (i == 0) {
1107  diag("FUNCTION_TABLE declaration must have one or more arguments:",
1108  s->name);
1109  }
1110  sprintf(buf, "double _arg[%d];\n", i);
1111  insertstr(qb1->next, buf);
1112  sprintf(buf, "return hoc_func_table(_ptable_%s, %d, _arg);\n", s->name, i);
1113  insertstr(qb2, buf);
1114  insertstr(qb2, "}\n/* "); /* kludge to avoid a bad vectorize_substitute */
1115  insertstr(qb2->next, " */\n");
1116 
1117  sprintf(buf, "table_%s", s->name);
1118  t = install(buf, NAME);
1119  t->subtype |= FUNCT;
1120  t->usage |= FUNCT;
1121  t->no_threadargs = 1;
1122  t->varnum = 0;
1123 
1124  sprintf(buf,"double %s", t->name);
1126  q1 = lappendsym(procfunc, SYM(qpar1));
1127  q2 = lappendsym(procfunc, SYM(qpar2));
1128  sprintf(buf,"{\n\thoc_spec_table(&_ptable_%s, %d);\n\treturn 0.;\n}\n",
1129  s->name, i);
1131  sprintf(buf, "\nstatic void* _ptable_%s = (void*)0;\n", s->name);
1133  hocfunchack(t, q1, q2, 1);
1134 }
1135 
1136 void watchstmt(Item* par1, Item* dir, Item* par2, Item* flag, int blocktype )
1137 {
1138  if (!watch_seen_) {
1139  ++watch_seen_;
1140  }
1141  if (blocktype != NETRECEIVE) {
1142  diag("\"WATCH\" statement only allowed in NET_RECEIVE block", (char*)0);
1143  }
1144  sprintf(buf, "\nstatic double _watch%d_cond(Point_process* _pnt) {\n",
1145  watch_seen_);
1147  vectorize_substitute(lappendstr(procfunc, ""),(char*)"\tdouble* _p; Datum* _ppvar; Datum* _thread; NrnThread* _nt;\n\t_thread= (Datum*)0; _nt = (NrnThread*)_pnt->_vnt;\n");
1148  sprintf(buf, "\t_p = _pnt->_prop->param; _ppvar = _pnt->_prop->dparam;\n\tv = NODEV(_pnt->node);\n return ");
1150  movelist(par1, par2, procfunc);
1151  movelist(dir->next, par2, procfunc);
1152  if (SYM(dir)->name[0] == '<') {
1153  insertstr(par1, "-(");
1154  insertstr(par2->next, ")");
1155  }
1156  replacstr(dir, ") - (");
1157  lappendstr(procfunc, ";\n}\n");
1158 
1159  // nrn_watch_allocate function called from core2nrn_watch_activate.
1160  if (!watch_alloc) {
1161  watch_alloc = newlist();
1162  lappendstr(watch_alloc,
1163 "\nstatic void _watch_alloc(Datum* _ppvar) {\n"
1164 " Point_process* _pnt = (Point_process*)_ppvar[1]._pvoid;\n"
1165  );
1166  }
1167  sprintf(buf,
1168  " _nrn_watch_allocate(_watch_array, _watch%d_cond, %d, _pnt, %s);\n",
1169  watch_seen_, watch_seen_, STR(flag));
1170  lappendstr(watch_alloc, buf);
1171 
1172  sprintf(buf,
1173  " _nrn_watch_activate(_watch_array, _watch%d_cond, %d, _pnt, _watch_rm++, %s);\n",
1174  watch_seen_, watch_seen_, STR(flag));
1175  replacstr(flag, buf);
1176 
1177  ++watch_seen_;
1178 }
1179 
1180 void threadsafe(char* s) {
1181  if (!assert_threadsafe) {
1182  fprintf(stderr, "Notice: %s\n", s);
1183  vectorize = 0;
1184  }
1185 }
1186 
1187 
1188 Item* protect_astmt(Item* q1, Item* q2) { /* PROTECT, ';' */
1189  Item* q;
1190  replacstr(q1, "/* PROTECT */_NMODLMUTEXLOCK\n");
1191  q = insertstr(q2->next, "\n _NMODLMUTEXUNLOCK /* end PROTECT */\n");
1192  protect_include_ = 1;
1193  return q;
1194 }
1195 
1196 void nrnmutex(int on, Item* q) { /* MUTEXLOCK or MUTEXUNLOCK */
1197  static int toggle = 0;
1198  if (on == 1) {
1199  if (toggle != 0) {
1200  diag("MUTEXLOCK invoked after MUTEXLOCK", (char*)0);
1201  }
1202  toggle = 1;
1203  replacstr(q, "_NMODLMUTEXLOCK\n");
1204  protect_include_ = 1;
1205  }else if (on == 0) {
1206  if (toggle != 1) {
1207  diag("MUTEXUNLOCK invoked with no earlier MUTEXLOCK", (char*)0);
1208  }
1209  toggle = 0;
1210  replacstr(q, "_NMODLMUTEXUNLOCK\n");
1211  protect_include_ = 1;
1212  }else{
1213  if (toggle != 0) {
1214  diag("MUTEXUNLOCK not invoked after MUTEXLOCK", (char*)0);
1215  }
1216  toggle = 0;
1217  }
1218 }
#define PARM
Definition: modl.h:190
char * stralloc(char *buf, char *rel)
Definition: list.cpp:208
#define Lappendsym
Definition: model.h:259
short itemtype
Definition: model.h:16
static int func_arg_examine(Item *qpar, Item *qend)
Definition: parsact.cpp:360
#define assert(ex)
Definition: hocassrt.h:26
short type
Definition: cabvars.h:10
List * watch_alloc
Definition: parsact.cpp:16
Symbol * stepsym
Definition: parsact.cpp:14
static int point_process
Definition: nrnunit.cpp:11
List * syminorder
Definition: init.cpp:10
int usage
Definition: model.h:66
#define PROCED
Definition: model.h:120
List * initfunc
Definition: init.cpp:8
short type
Definition: model.h:58
#define diag(s)
Definition: fmenu.cpp:188
void hocfunc(Symbol *n, Item *qpar1, Item *qpar2)
static HocParmLimits limits[]
Definition: extcelln.cpp:33
void nrnmutex(int on, Item *q)
Definition: parsact.cpp:1196
#define DEP
Definition: model.h:116
void parminstall(Symbol *n, char *num, char *units, char *limits)
Definition: parsact.cpp:161
#define ITERATE(itm, lst)
Definition: model.h:25
#define SYM(q)
Definition: model.h:86
static char * previous_str
Definition: parsact.cpp:37
void table_massage(List *tablist, Item *qtype, Item *qname, List *arglist)
Definition: parsact.cpp:573
#define ITEM0
Definition: model.h:22
size_t p
Item * lappendsym(List *list, Symbol *sym)
Definition: list.cpp:161
static int first
Definition: fmenu.cpp:186
List * initlist
Definition: init.cpp:8
char * name
Definition: model.h:72
#define NRN_BUFSIZE
Definition: model.h:13
static long previous_subtype
Definition: parsact.cpp:36
int check_tables_threads(List *p)
Definition: parsact.cpp:555
void netrec_asgn(Item *varname, Item *equal, Item *expr, Item *lastok)
struct Item * prev
Definition: model.h:20
void add_reset_args(Item *q)
Definition: parsact.cpp:496
#define Fprintf
Definition: model.h:249
void vectorize_use_func(Item *qname, Item *qpar1, Item *qexpr, Item *qpar2, int blocktype)
#define SYMBOL
Definition: model.h:102
struct Item * next
Definition: model.h:19
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
static List * check_table_statements
Definition: parsact.cpp:535
void indepinstall(Symbol *n, char *from, char *to, char *with, Item *qstart, char *units, int scop)
Definition: parsact.cpp:238
static double abstol(void *v)
Definition: cvodeobj.cpp:185
#define Strcat
Definition: model.h:254
Definition: model.h:15
List * indeplist
Definition: parsact.cpp:15
Symbol * ifnew_parminstall(char *name, char *num, char *units, char *limits)
Definition: parsact.cpp:177
#define Insertstr
Definition: model.h:255
#define install
Definition: redef.h:82
int protect_include_
Definition: parsact.cpp:28
int const size_t const size_t n
Definition: nrngsl.h:12
void lag_stmt(Item *q1, int blocktype)
Definition: parsact.cpp:418
void movelist(Item *q1, Item *q2, List *s)
Definition: list.cpp:245
_CONST char * s
Definition: system.cpp:74
#define ARRAY
Definition: model.h:118
void statdefault(Symbol *n, int index, char *units, Item *qs, int makeconst)
Definition: parsact.cpp:332
void explicit_decl(int level, Item *q)
Definition: parsact.cpp:39
void threadsafe(char *s)
Definition: parsact.cpp:1180
void depinstall(int type, Symbol *n, int index, char *from, char *to, char *units, Item *qs, int makeconst, char *abstol)
Definition: parsact.cpp:297
Item * lappendstr(List *list, char *str)
Definition: list.cpp:149
static List * check_table_thread_list
Definition: parsact.cpp:554
#define printf
Definition: mwprefix.h:26
List * procfunc
Definition: init.cpp:9
void vectorize_substitute(Item *q, char *str)
void watchstmt(Item *par1, Item *dir, Item *par2, Item *flag, int blocktype)
Definition: parsact.cpp:1136
static const char * fname(const char *name)
Definition: nrnbbs.cpp:108
#define STRING
Definition: bbslsrv.cpp:9
Symbol * scop_indep
Definition: parsact.cpp:12
int assert_threadsafe
Item * linsertstr(List *list, char *str)
Definition: list.cpp:143
Symbol * indepsym
Definition: parsact.cpp:13
fprintf(stderr, "Don't know the location of params at %p\, pp)
Item * protect_astmt(Item *q1, Item *q2)
Definition: parsact.cpp:1188
Definition: model.h:57
char * name
Definition: init.cpp:16
int type_change(Symbol *sym, int level)
Definition: parsact.cpp:111
#define LST(q)
Definition: model.h:90
List * newlist()
Definition: list.cpp:50
void units(unit *)
Definition: units.cpp:736
virtual void move(const Event &e)
Definition: ocinput.h:19
#define Strcpy
Definition: model.h:253
#define FUNCT
Definition: model.h:119
#define EXTDEF
Definition: model.h:131
#define Lappendstr
Definition: model.h:260
short level
Definition: model.h:71
void add_nrnthread_arg(Item *q)
Definition: parsact.cpp:507
NMODL parser global flags / functions.
void queue_stmt(Item *q1, Item *q2)
Definition: parsact.cpp:468
#define lookup
Definition: redef.h:90
long subtype
Definition: model.h:59
Item * lappenditem(List *list, Item *item)
Definition: list.cpp:167
void parm_array_install(Symbol *n, char *num, char *units, char *limits, int index)
Definition: parsact.cpp:146
#define EXPLICIT_DECL
Definition: model.h:137
int artificial_cell
Definition: nocpout.cpp:153
#define STR(q)
Definition: model.h:87
void function_table(Symbol *s, Item *qpar1, Item *qpar2, Item *qb1, Item *qb2)
Definition: parsact.cpp:1091
Item * insertstr(Item *item, char *str)
Definition: list.cpp:108
int protect_
Definition: parsact.cpp:27
int araydim
Definition: model.h:67
void freelist(List **plist)
Definition: list.cpp:61
long subtype
Definition: init.cpp:122
void vectorize_scan_for_func(Item *q1, Item *q2)
Definition: parsact.cpp:377
#define i
Definition: md1redef.h:12
void printlist(List *list)
Definition: model.cpp:163
#define c
static Symbol * last_func_using_table
Definition: parsact.cpp:536
#define arg
Definition: redef.h:28
List * firstlist
Definition: init.cpp:8
#define Linsertstr
Definition: model.h:258
char buf[512]
Definition: init.cpp:13
#define STAT
Definition: model.h:117
void check_tables()
Definition: parsact.cpp:538
#define STEP1
Definition: model.h:129
void replacstr(Item *q, char *s)
Definition: list.cpp:250
static Item * qexpr[3]
Definition: units1.cpp:69
#define Sprintf
Definition: model.h:248
union Symbol::@18 u
#define SYM0
Definition: model.h:74
static char * indepunits
Definition: parsact.cpp:233
double t
Definition: init.cpp:123
size_t q
#define INDEP
Definition: model.h:115
#define nmodlCONST
Definition: modl.h:211
int varnum
Definition: model.h:69
char * str
Definition: model.h:63
void defarg(Item *q1, Item *q2)
Definition: parsact.cpp:398
return NULL
Definition: cabcode.cpp:461
static struct table * table
FILE * fcout
Definition: model.cpp:33
short index
Definition: cabvars.h:11
void steppedinstall(Symbol *n, Item *q1, Item *q2, char *units)
Definition: parsact.cpp:198
Item * vectorize_replacement_item(Item *)
int vectorize
void hocfunchack(Symbol *n, Item *qpar1, Item *qpar2, int hack)