NEURON
io.cpp
Go to the documentation of this file.
1 #include <../../nmodlconf.h>
2 /* /local/src/master/nrn/src/modlunit/io.c,v 1.2 1997/11/24 16:19:09 hines Exp */
3 
4 /* file.mod input routines */
5 #include <stdlib.h>
6 #include "model.h"
7 #include <ctype.h>
8 #if MAC && TARGET_API_MAC_CARBON
9 #include <SIOUX.h>
10 #endif
11 #undef METHOD
12 #include "parse1.hpp"
13 Item* lastok; /*should be last token accepted by parser that gives
14 successful reduction */
15 
16 /*
17  * We painfully constuct our own input buffer so that when user errors occur
18  * we can print the whole line. Often, even this is not enough if the error
19  * is at the end of a line. We also count lines so the user can go right to
20  * the error in most cases
21  */
22 static int linenum = 0;
23 static char inlinebuf[600], *inlinep = inlinebuf + 30, *ctp = inlinebuf + 30;
24 static int file_stack_empty();
25 
26 char* Fgets(char* buf, int size, FILE* f) {
27  char* p = buf;
28  int c, i;
29  for (i = 0; i < size; ++i) {
30  c = getc(f);
31  if (c == EOF || c == 26 || c == 4) { /* ^Z and ^D are end of file */
32  /* some editors don't put a newline at last line */
33  if (p > buf) {
34  ungetc(c, f);
35  c = '\n';
36  } else {
37  break;
38  }
39  }
40  if (c == '\r') {
41  int c2 = getc(f);
42  if (c2 != '\n') {
43  ungetc(c2, f);
44  }
45  c = '\n';
46  }
47  *p++ = c;
48  if (c == '\n') {
49  *p = '\0';
50  return buf;
51  }
52  }
53  if (i >= size) {
54  buf[size - 1] = 0;
55  diag("Line too long:", buf);
56  }
57  return (char*) 0;
58 }
59 
60 int Getc() {
61  int c;
62  if (ctp == (char*) 0 || *ctp == '\0') {
63  ctp = Fgets(inlinep, 512, fin);
64  if (ctp)
65  linenum++;
66  }
67  if (ctp == (char*) 0) {
68  ctp = inlinep;
69  *ctp = '\0';
70  if (file_stack_empty()) {
71  return EOF;
72  } else {
74  return Getc();
75  }
76  }
77  c = *ctp++;
78  return c;
79 }
80 
81 int unGetc(int c) {
82  if (c == EOF)
83  return c;
84  if (ctp > inlinebuf) {
85  ctp--;
86  *ctp = c;
87  } else {
88  diag("internal error in unGetc", "");
89  }
90  return c;
91 }
92 
93 char* Gets(char* buf) {
94  char* cp;
95  int c;
96 
97  cp = buf;
98  while ((c = Getc()) != EOF && c != '\n') {
99  *cp++ = c;
100  }
101  if (c == '\n') {
102  *cp++ = c;
103  *cp++ = '\0';
104  return buf;
105  } else if (c == EOF) {
106  return (char*) 0;
107  } else {
108  diag("internal error in Gets()", "");
109  }
110  return (char*) 0;
111 }
112 
113 /* two arguments so we can pass a name to construct an error message. */
114 void diag(char* s1, char* s2) {
115  char* cp;
116  Item *q1, *q2, *q;
117 
118  Fprintf(stderr, "%s", s1);
119  if (s2) {
120  Fprintf(stderr, "%s", s2);
121  }
122  if (lex_tok) {
123  /*EMPTY*/
124  for (q2 = lastok; q2->itemtype != NEWLINE && q2 != intoken; q2 = q2->next) {
125  ;
126  }
127  /*EMPTY*/
128  for (q1 = lastok->prev; q1->itemtype != NEWLINE && q1 != intoken; q1 = q1->prev) {
129  ;
130  }
131  if (q2 == intoken) {
132  Fprintf(stderr, " at end of file in file %s\n", finname);
133  } else {
134  Fprintf(stderr, " at line %d in file %s\n", q2->itemsubtype, finname);
135  }
136  assert(q1 != q2);
137  for (q = q1->next; q != q2; q = q->next) {
138  switch (q->itemtype) {
139  case SYMBOL:
140  Fprintf(stderr, "%s", SYM(q)->name);
141  break;
142  case STRING:
143  Fprintf(stderr, "%s", STR(q));
144  break;
145  case NEWLINE:
146  Fprintf(stderr, "\n");
147  break;
148  default:
149  /*SUPPRESS 622*/
150  assert(0);
151  }
152  if (q == lastok) {
153  Fprintf(stderr, "<<ERROR>>");
154  }
155  }
156  } else if (fin) {
157  Fprintf(stderr, " at line %d in file %s\n", linenum, finname);
158  Fprintf(stderr, "%s", inlinep);
159  if (ctp >= inlinep) {
160  for (cp = inlinep; cp < ctp - 1; cp++) {
161  if (*cp == '\t') {
162  Fprintf(stderr, "\t");
163  } else {
164  Fprintf(stderr, " ");
165  }
166  }
167  Fprintf(stderr, "^");
168  }
169  }
170  Fprintf(stderr, "\n");
171 #if MAC && TARGET_API_MAC_CARBON
172  SIOUXSettings.autocloseonquit = true;
173  RunApplicationEventLoop();
174 #endif
175  exit(1);
176 }
177 
178 Symbol* _SYM(Item* q, char* file, int line) {
179  if (!q || q->itemtype != SYMBOL) {
180  internal_error(q, file, line);
181  }
182  return (Symbol*) ((q)->element);
183 }
184 
185 char* _STR(Item* q, char* file, int line) {
186  if (!q || q->itemtype != STRING) {
187  internal_error(q, file, line);
188  }
189  return (char*) ((q)->element);
190 }
191 
192 Item* _ITM(Item* q, char* file, int line) {
193  if (!q || q->itemtype != ITEM) {
194  internal_error(q, file, line);
195  }
196  return (Item*) ((q)->element);
197 }
198 
199 Item** _ITMA(Item* q, char* file, int line) {
200  if (!q || q->itemtype != ITEMARRAY) {
201  internal_error(q, file, line);
202  }
203  return (Item**) ((q)->element);
204 }
205 
206 List* _LST(Item* q, char* file, int line) {
207  if (!q || q->itemtype != LIST) {
208  internal_error(q, file, line);
209  }
210  return (List*) ((q)->element);
211 }
212 
213 void internal_error(Item* q, char* file, int line) {
214  Fprintf(stderr, "Internal error in file \"%s\", line %d\n", file, line);
215  Fprintf(stderr, "The offending item has the structure:\n");
216  debugitem(q);
217  exit(1);
218 }
219 
220 
221 typedef struct FileStackItem {
222  char* inlinep;
223  char* ctp;
224  int linenum;
225  FILE* fp;
228 
229 static List* filestack;
230 
231 static int getprefix(char* prefix, char* s) {
232  char* cp;
233  strcpy(prefix, s);
234  for (cp = prefix + strlen(prefix); cp + 1 != prefix; --cp) {
235  if (*cp == '/') {
236  break;
237  }
238  *cp = '\0';
239  }
240  return (prefix[0] != '\0');
241 }
242 
243 static FILE* include_open(char* fname, int err) {
244  FILE* f = (FILE*) 0;
245  FileStackItem* fsi;
246  char *dirs, *colon;
247  char buf2[200];
248  if (fname[0] == '/') { /* highest precedence is complete filename */
249  return fopen(fname, "r");
250  }
251 
252  fsi = (FileStackItem*) (SYM(filestack->prev));
253  if (getprefix(buf, fsi->finname)) {
254  strcat(buf, fname);
255  f = fopen(buf, "r"); /* first try in directory of last file */
256  if (f) {
257  strcpy(fname, buf);
258  return f;
259  }
260  if (err)
261  fprintf(stderr, "Couldn't open: %s\n", buf);
262  }
263  f = fopen(fname, "r"); /* next try current working directory */
264  if (f) {
265  return f;
266  }
267  sprintf(buf, "../%s", fname); /* Next try next dir up. */
268  if ((f = fopen(buf, "r")) != NULL)
269  return f;
270 
271  if (err)
272  fprintf(stderr, "Couldn't open: %s\n", fname);
273  /* try all the directories in the environment variable */
274  /* a colon separated list of directories */
275  dirs = getenv("MODL_INCLUDE");
276  if (dirs) {
277  strcpy(buf, dirs);
278  dirs = buf;
279  colon = dirs;
280  for (dirs = colon; *dirs; dirs = colon) {
281  for (; *colon; ++colon) {
282  if (*colon == ':') {
283  *colon = '\0';
284  ++colon;
285  break;
286  }
287  }
288  strcpy(buf2, dirs);
289  strcat(buf2, "/");
290  strcat(buf2, fname);
291  f = fopen(buf2, "r");
292  if (f) {
293  strcpy(fname, buf2);
294  return f;
295  }
296  if (err)
297  fprintf(stderr, "Couldn't open: %s\n", buf2);
298  }
299  }
300  return f;
301 }
302 
304  char fname[200];
305  FileStackItem* fsi;
306  if (!filestack) {
307  filestack = newlist();
308  }
309  strcpy(fname, STR(q) + 1);
310  fname[strlen(fname) - 1] = '\0';
311  fsi = (FileStackItem*) emalloc(sizeof(FileStackItem));
312  lappendsym(filestack, (Symbol*) fsi);
313 
314  fsi->inlinep = inlinep;
315  fsi->ctp = ctp;
316  fsi->linenum = linenum;
317  fsi->fp = fin;
318  strcpy(fsi->finname, finname);
319 
320  if ((fin = include_open(fname, 0)) == (FILE*) 0) {
321  include_open(fname, 1);
322  diag("Couldn't open ", fname);
323  }
324  fprintf(stderr, "INCLUDEing %s\n", fname);
325  strcpy(finname, fname);
326  ctp = (char*) 0;
327  linenum = 0;
328 }
329 
331  FileStackItem* fsi;
332  fsi = (FileStackItem*) (SYM(filestack->prev));
334  linenum = fsi->linenum;
335  inlinep = fsi->inlinep;
336  fclose(fin);
337  fin = fsi->fp;
338  strcpy(finname, fsi->finname);
339  free(fsi);
340 }
341 
342 static int file_stack_empty() {
343  if (!filestack) {
344  return 1;
345  }
346  return (filestack->next == filestack);
347 }
348 
349 /* io.c,v
350  * Revision 1.2 1997/11/24 16:19:09 hines
351  * modlunit port to MAC (not complete)
352  *
353  * Revision 1.1.1.1 1994/10/12 17:22:48 hines
354  * NEURON 3.0 distribution
355  *
356  * Revision 1.7 1994/09/20 14:43:18 hines
357  * port to dec alpha
358  *
359  * Revision 1.6 1994/05/23 17:56:02 hines
360  * error in handling MODL_INCLUDE when no file exists
361  *
362  * Revision 1.5 1994/05/18 18:08:13 hines
363  * INCLUDE "file"
364  * tries originalpath/file ./file MODL_INCLUDEpaths/file
365  *
366  * Revision 1.4 1993/02/01 15:15:45 hines
367  * static functions should be declared before use
368  *
369  * Revision 1.3 92/02/17 12:30:55 hines
370  * constant states with a compartment size didn't have space allocated
371  * to store the compartment size.
372  *
373  * Revision 1.2 91/01/07 14:17:06 hines
374  * in kinunit, wrong itemsubtype. Fix lint messages
375  *
376  * Revision 1.1 90/11/13 16:10:17 hines
377  * Initial revision
378  * */
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
char * Gets(char *buf)
Definition: io.cpp:93
char finname[NRN_BUFSIZE]
Definition: model.cpp:37
char buf[512]
Definition: init.cpp:13
List * intoken
Definition: init.cpp:12
#define assert(ex)
Definition: hocassrt.h:32
static char line[MAXLINE]
Definition: ivecop.c:35
char * getenv(const char *s)
Definition: macprt.cpp:67
#define i
Definition: md1redef.h:12
void debugitem(Item *q)
Definition: model.cpp:193
#define STR(q)
Definition: model.h:87
#define ITEMARRAY
Definition: model.h:105
#define SYMBOL
Definition: model.h:102
#define ITEM
Definition: model.h:103
#define SYM(q)
Definition: model.h:86
Item * lex_tok
Definition: model.h:184
#define NRN_BUFSIZE
Definition: model.h:13
#define LIST
Definition: model.h:104
#define Fprintf
Definition: model.h:234
char * name
Definition: init.cpp:16
static char * inlinep
Definition: io.cpp:23
void pop_file_stack()
Definition: io.cpp:330
List * _LST(Item *q, char *file, int line)
Definition: io.cpp:206
void internal_error(Item *q, char *file, int line)
Definition: io.cpp:213
static char * ctp
Definition: io.cpp:23
static int getprefix(char *prefix, char *s)
Definition: io.cpp:231
struct FileStackItem FileStackItem
Item * lastok
Definition: io.cpp:13
int unGetc(int c)
Definition: io.cpp:81
static char inlinebuf[600]
Definition: io.cpp:23
Item * _ITM(Item *q, char *file, int line)
Definition: io.cpp:192
static int linenum
Definition: io.cpp:22
static List * filestack
Definition: io.cpp:229
Symbol * _SYM(Item *q, char *file, int line)
Definition: io.cpp:178
static FILE * include_open(char *fname, int err)
Definition: io.cpp:243
char * Fgets(char *buf, int size, FILE *f)
Definition: io.cpp:26
void diag(char *s1, char *s2)
Definition: io.cpp:114
char * _STR(Item *q, char *file, int line)
Definition: io.cpp:185
int Getc()
Definition: io.cpp:60
Item ** _ITMA(Item *q, char *file, int line)
Definition: io.cpp:199
static int file_stack_empty()
Definition: io.cpp:342
void include_file(Item *q)
Definition: io.cpp:303
char * emalloc(unsigned n)
Definition: list.cpp:166
List * newlist()
Definition: list.cpp:47
Item * lappendsym(List *list, Symbol *sym)
Definition: list.cpp:142
static struct prefix prefix[]
#define fprintf
Definition: mwprefix.h:30
size_t q
size_t p
static double remove(void *v)
Definition: ocdeck.cpp:207
#define STRING
Definition: bbslsrv.cpp:9
#define fin
Definition: redef.h:60
FILE * fopen()
#define NULL
Definition: sptree.h:16
char * inlinep
Definition: io.cpp:222
char finname[NRN_BUFSIZE]
Definition: io.cpp:226
int linenum
Definition: io.cpp:224
char * ctp
Definition: io.cpp:223
FILE * fp
Definition: io.cpp:225
Definition: model.h:15
struct Item * prev
Definition: model.h:20
short itemtype
Definition: model.h:16
short itemsubtype
Definition: model.h:17
struct Item * next
Definition: model.h:19
Definition: model.h:57
static const char * fname(const char *name)
Definition: nrnbbs.cpp:113