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