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