NEURON
modl.cpp
Go to the documentation of this file.
1 #include <../../nmodlconf.h>
2 
3 /*
4  * int main(int argc, char *argv[]) --- returns 0 if translation is
5  * successful. Diag will exit with 1 if error.
6  *
7  * ---The overall strategy of the translation consists of three phases.
8  *
9  * 1) read in the whole file as a sequence of tokens, parsing as we go. Most of
10  * the trivial C translation such as appending ';' to statements is performed
11  * in this phase as is the creation of the symbol table. Item lists maintain
12  * the proper token order. Ater a whole block is read in, nontrivial
13  * manipulation may be performed on the entire block.
14  *
15  * 2) Some blocks and statements can be manipulated only after the entire file
16  * has been read in. The solve statement is an example since it can be
17  * analysed only after we know what is the type of the associated block. The
18  * kinetic block is another example whose translation depends on the SOLVE
19  * method and so cannot be processed until the whole input file has been
20  * read.
21  *
22  * 3) Output the lists.
23  *
24  * void openfiles(int argc, char *argv[]) parse the argument list, and open
25  * files. Print usage message and exit if no argument
26  *
27  */
28 
29 /*
30  * In order to interface this process with merge, a second argument is
31  * allowed which gives the complete input filename. The first argument
32  * still gives the prefix of the .c and .var files.
33  */
34 
35 /* the first arg may also be a file.mod (containing the .mod suffix)*/
36 
37 #include <getopt.h>
38 
39 #if MAC
40 #include <sioux.h>
41 #endif
42 #if HAVE_STDLIB_H
43 #include <stdlib.h>
44 #endif
45 #include "modl.h"
46 FILE
47  * fin, /* input file descriptor for filename.mod */
48  /* or file2 from the second argument */
49  *fparout, /* output file descriptor for filename.var */
50  *fcout; /* output file descriptor for filename.c */
51 #if SIMSYS
52 FILE *fctlout, /* filename.ctl */
53  *fnumout; /* filename.num */
54 #endif
55 
56 
57 char* modprefix;
58 
59 char* finname;
60 
61 #if LINT
62 char *clint;
63 int ilint;
64 Item *qlint;
65 #endif
66 
67 int nmodl_text = 1;
69 
70 extern int yyparse();
71 extern int mkdir_p(const char*);
72 
73 #if NMODL && VECTORIZE
74 extern int vectorize;
75 extern int numlist;
76 extern char* nmodl_version_;
77 extern int usederivstatearray;
78 #endif
79 
80 /*SUPPRESS 763*/
81 static char pgm_name[] = "nmodl";
82 extern char *RCS_version;
83 extern char *RCS_date;
84 
85 static struct option long_options[] = {
86  {"version", no_argument, 0, 'v'},
87  {"help", no_argument, 0, 'h'},
88  {"outdir", required_argument, 0, 'o'},
89  {0,0,0,0}
90 };
91 
92 static void show_options(char** argv) {
93  fprintf(stderr, "Source to source compiler from NMODL to C\n");
94  fprintf(stderr, "Usage: %s [options] Inputfile\n", argv[0]);
95  fprintf(stderr, "Options:\n");
96  fprintf(stderr, "\t-o | --outdir <OUTPUT_DIRECTORY> directory where output files will be written\n");
97  fprintf(stderr, "\t-h | --help print this message\n");
98  fprintf(stderr, "\t-v | --version print version number\n");
99 }
100 
101 static void openfiles(char* given_filename, char* output_dir);
102 
103 int main(int argc, char** argv) {
104  int option = -1;
105  int option_index = 0;
106  char* output_dir = NULL;
107 
108  if (argc < 2) {
109  show_options(argv);
110  exit(1);
111  }
112 
113  while ( (option = getopt_long (argc, argv, ":vho:", long_options, &option_index)) != -1) {
114  switch (option) {
115  case 'v':
116  printf("%s\n", nmodl_version_);
117  exit(0);
118 
119  case 'o':
120  output_dir = strdup(optarg);
121  break;
122 
123  case 'h':
124  show_options(argv);
125  exit(0);
126 
127  case ':':
128  fprintf(stderr, "%s: option '-%c' requires an argument\n", argv[0], optopt);
129  exit (-1);
130 
131  case '?':
132  default:
133  fprintf(stderr, "%s: invalid option `-%c' \n", argv[0], optopt);
134  exit (-1);
135  }
136  }
137  if ((argc - optind) > 1) {
138  fprintf(stderr, "%s: Warning several input files specified on command line but only one will be processed\n", argv[0]);
139  }
140 
141  filetxtlist = newlist();
142 
143 #if MAC
144  SIOUXSettings.asktosaveonclose = false;
145 #if !SIMSYS
146  Fprintf(stderr, "%s %s %s\n",
148 #endif
149 #endif
150 
151  init(); /* keywords into symbol table, initialize
152  * lists, etc. */
153 
154  finname = argv[optind];
155 
156  openfiles(finname, output_dir); /* .mrg else .mod, .var, .c */
157 #if NMODL || HMODL
158 #else
159 #if !SIMSYS
160  Fprintf(stderr, "Translating %s into %s.c and %s.var\n", finname,
162 #endif
163 #endif
164  IGNORE(yyparse());
165  /*
166  * At this point all blocks are fully processed except the kinetic
167  * block and the solve statements. Even in these cases the
168  * processing doesn't involve syntax since the information is
169  * held in intermediate lists of specific structure.
170  *
171  */
172 
173  /*
174  * go through the list of solve statements and construct the model()
175  * code
176  */
177  solvhandler();
178  netrec_discon();
179  /*
180  * NAME's can be used in many cases before they were declared and
181  * no checking up to this point has been done to make sure that
182  * names have been used in only one way.
183  *
184  */
185  consistency();
186 #if 0 && !_CRAY && NMODL && VECTORIZE
187 /* allowing Kinetic models to be vectorized on cray. So nonzero numlist is
188 no longer adequate for saying we can not */
189  if (numlist) {
190  vectorize = 0;
191  }
192 #endif
193  chk_thread_safe();
194  parout(); /* print .var file.
195  * Also #defines which used to be in defs.h
196  * are printed into .c file at beginning.
197  */
198  c_out(); /* print .c file */
199 #if HMODL || NMODL
200 #else
201  IGNORE(fclose(fparout));
202 #endif
203 #if SIMSYS
204  IGNORE(fclose(fctlout));
205  IGNORE(fclose(fnumout));
206 #endif
207 
208 #if !defined NMODL_TEXT
209 #define NMODL_TEXT 1
210 #endif
211 #if NMODL && NMODL_TEXT
212 #if 0
213 /* test: temp.txt should be identical to text of input file except for INCLUDE */
214 {
215  FILE* f = fopen("temp.txt", "w");
216  assert(f);
217  Item* q;
218  ITERATE(q, filetxtlist) {
219  char* s = STR(q);
220  fprintf(f, "%s", s);
221  }
222  fclose(f);
223 }
224 #endif
225  if (nmodl_text) {
226  Item* q;
227  char* pf = NULL;
228 #if HAVE_REALPATH && !defined(NRN_AVOID_ABSOLUTE_PATHS)
229  pf = realpath(finname, NULL);
230 #endif
231  fprintf(fcout, "\n#if NMODL_TEXT\nstatic const char* nmodl_filename = \"%s\";\nstatic const char* nmodl_file_text = \n", pf ? pf : finname);
232  if (pf) { free(pf); }
233  ITERATE(q, filetxtlist) {
234  char* s = STR(q);
235  char* cp;
236  fprintf(fcout, " \"");
237  /* Escape double quote, backslash, and end each line with \n */
238  for (cp = s; *cp; ++cp) {
239  if (*cp =='"' || *cp == '\\' ) {
240  fprintf(fcout, "\\");
241  }
242  if (*cp == '\n') {
243  fprintf(fcout, "\\n\"");
244  }
245  fputc(*cp, fcout);
246  }
247  }
248  fprintf(fcout, " ;\n#endif\n");
249 }
250 #endif
251 
252  IGNORE(fclose(fcout));
253 
254 #if NMODL && VECTORIZE
255  if (vectorize) {
256  Fprintf(stderr, "Thread Safe\n");
257  }
258  if (usederivstatearray) {
259 fprintf(stderr, "Derivatives of STATE array variables are not translated correctly and compile time errors will be generated.\n");
260 fprintf(stderr, "The %s.c file may be manually edited to fix these errors.\n", modprefix);
261  }
262 #endif
263 
264 #if LINT
265  { /* for lex */
266  extern int yytchar, yylineno;
267  extern FILE *yyin;
268  IGNORE(yyin);
269  IGNORE(yytchar);
270  IGNORE(yylineno);
271  IGNORE(yyinput());
272  yyunput(ilint);
273  yyoutput(ilint);
274  }
275 #endif
276 #if MAC
277  printf("Done\n");
278  SIOUXSettings.autocloseonquit = true;
279 #endif
280  free(modprefix); /* allocated in openfiles below */
281  return 0;
282 }
283 
284 static void openfiles(char* given_filename, char* output_dir) {
285  char s[NRN_BUFSIZE];
286 
287  char output_filename [NRN_BUFSIZE];
288  char input_filename [NRN_BUFSIZE];
289  modprefix = strdup (given_filename); // we want to keep original string to open input file
290  // find last '.' after last '/' that delimit file name from extension
291  // we are not bothering to deal with filenames that begin with a . but do
292  // want to deal with paths like ../foo/hh
293  char* first_ext_char = strrchr(modprefix, '.');
294  if (strrchr(modprefix, '/') > first_ext_char) {
295  first_ext_char = NULL;
296  }
297 
298  Sprintf(input_filename, "%s", given_filename);
299 
300  if(first_ext_char) *first_ext_char = '\0'; // effectively cut the extension from prefix if it exist in given_filename
301  if ((fin = fopen(input_filename, "r")) == (FILE *) 0) { // first try to open given_filename
302  Sprintf(input_filename, "%s.mod", given_filename); // if it dont work try to add ".mod" extension and retry
303  Sprintf(finname, "%s.mod", given_filename); // finname is still a global variable, so we need to update it
304  if ((fin = fopen(input_filename, "r")) == (FILE *) 0) {
305  diag("Can't open input file: ", input_filename);
306  }
307  }
308  if (output_dir) {
309  if(mkdir_p(output_dir) != 0) {
310  fprintf(stderr, "Can't create output directory %s\n", output_dir);
311  exit(1);
312  }
313  char* basename = strrchr(modprefix,'/');
314  if (basename) {
315  Sprintf(output_filename, "%s%s.c", output_dir, basename);
316  } else {
317  Sprintf(output_filename, "%s/%s.c", output_dir, modprefix);
318  }
319  } else {
320  Sprintf(output_filename, "%s.c", modprefix);
321  }
322 
323  if ((fcout = fopen(output_filename, "w")) == (FILE *) 0) {
324  diag("Can't create C file: ", output_filename);
325  }
326  Fprintf(stderr, "Translating %s into %s\n", input_filename, output_filename);
327 
328 #if HMODL || NMODL
329 #else
330  Sprintf(s, "%s.var", modprefix);
331  if ((fparout = fopen(s, "w")) == (FILE *) 0) {
332  diag("Can't create variable file: ", s);
333  }
334 #endif
335 #if SIMSYS
336  Sprintf(s, "%s.ctl", modprefix);
337  if ((fctlout = fopen(s, "w")) == (FILE *) 0) {
338  diag("Can't create variable file: ", s);
339  }
340  Sprintf(s, "%s.num", modprefix);
341  if ((fnumout = fopen(s, "w")) == (FILE *) 0) {
342  diag("Can't create C file: ", s);
343  }
344 #endif
345 }
346 
347 static std::string str_replace(std::string str, const std::string& search_str, const std::string& replace_str)
348 {
349  if (search_str.empty()) {
350  return str;
351  }
352 
353  size_t pos;
354  while ( (pos = str.find(search_str)) != std::string::npos ) {
355  str.replace(pos, search_str.size(), replace_str);
356  }
357 
358  return str;
359 }
360 
361 // Post-adjustments for VERBATIM blocks (i.e make them compatible with CPP).
362 void verbatim_adjust(char* q) {
363  // template is a reserved CPP keyword
364  const std::string repl = str_replace(q, "u.template", "u.ctemplate");
365  Fprintf(fcout, "%s", repl.c_str());
366 }
#define assert(ex)
Definition: hocassrt.h:26
static void openfiles(char *given_filename, char *output_dir)
Definition: modl.cpp:284
List * filetxtlist
Definition: modl.cpp:68
FILE * fparout
Definition: modl.cpp:47
char * finname
Definition: modl.cpp:59
#define diag(s)
Definition: fmenu.cpp:188
void parout()
Definition: nocpout.cpp:225
char * RCS_date
Definition: version.cpp:5
#define ITERATE(itm, lst)
Definition: model.h:25
int numlist
Definition: solve.cpp:38
char * modprefix
Definition: modl.cpp:57
void chk_thread_safe()
Definition: nocpout.cpp:2708
#define NRN_BUFSIZE
Definition: model.h:13
void solvhandler()
Definition: solve.cpp:133
#define Fprintf
Definition: model.h:249
#define IGNORE(arg)
Definition: model.h:262
char * nmodl_version_
Definition: nocpout.cpp:11
Definition: model.h:15
void init()
Definition: init.cpp:169
void c_out()
Definition: cout.cpp:252
_CONST char * s
Definition: system.cpp:74
static char pgm_name[]
Definition: modl.cpp:81
#define printf
Definition: mwprefix.h:26
FILE * fin
Definition: modl.cpp:47
fprintf(stderr, "Don't know the location of params at %p\, pp)
int mkdir_p(const char *)
Definition: io.cpp:464
int nmodl_text
Definition: modl.cpp:67
List * newlist()
Definition: list.cpp:50
int yyparse()
NMODL parser global flags / functions.
static std::string str_replace(std::string str, const std::string &search_str, const std::string &replace_str)
Definition: modl.cpp:347
void verbatim_adjust(char *q)
Definition: modl.cpp:362
#define STR(q)
Definition: model.h:87
int vectorize
static void show_options(char **argv)
Definition: modl.cpp:92
static struct option long_options[]
Definition: modl.cpp:85
int main(int argc, char **argv)
Definition: modl.cpp:103
char * RCS_version
Definition: version.cpp:4
void netrec_discon()
#define Sprintf
Definition: model.h:248
static int argc
Definition: inithoc.cpp:53
size_t q
FILE * fopen()
return NULL
Definition: cabcode.cpp:461
FILE * fcout
Definition: modl.cpp:47
void consistency()
Definition: consist.cpp:21
static char ** argv
Definition: inithoc.cpp:54