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