make ANSI C compatible
[unix-history] / usr / src / usr.bin / f77 / libI77 / rsnmle.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)rsnmle.c 5.4 %G%
7 */
8
9/*
10 * name-list read
11 */
12
13#include "fio.h"
14#include "lio.h"
15#include "nmlio.h"
16#include <ctype.h>
17
18LOCAL char *nml_rd;
19
20static int ch;
21LOCAL nameflag;
22LOCAL char var_name[VL+1];
23
24#define SP 1
25#define B 2
26#define AP 4
27#define EX 8
28#define INTG 16
29#define RL 32
30#define LGC 64
31#define IRL (INTG | RL | LGC )
32#define isblnk(x) (ltab[x+1]&B) /* space, tab, newline */
33#define issep(x) (ltab[x+1]&SP) /* space, tab, newline, comma */
34#define isapos(x) (ltab[x+1]&AP) /* apost., quote mark */
35#define isexp(x) (ltab[x+1]&EX) /* d, e, D, E */
36#define isint(x) (ltab[x+1]&INTG) /* 0-9, plus, minus */
37#define isrl(x) (ltab[x+1]&RL) /* 0-9, plus, minus, period */
38#define islgc(x) (ltab[x+1]&LGC) /* 0-9, period, t, f, T, F */
39
40#define GETC (ch=t_getc())
41#define UNGETC() ungetc(ch,cf)
42
43LOCAL char *lchar;
44LOCAL double lx,ly;
45LOCAL int ltype;
46int t_getc(), ungetc();
47
48LOCAL char ltab[128+1] =
49{ 0, /* offset one for EOF */
50/* 0- 15 */ 0,0,0,0,0,0,0,0,0,SP|B,SP|B,0,0,0,0,0, /* TAB,NEWLINE */
51/* 16- 31 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
52/* 32- 47 */ SP|B,0,AP,0,0,0,0,AP,0,0,0,RL|INTG,SP,RL|INTG,RL|LGC,0, /* space,",',comma,., */
53/* 48- 63 */ IRL,IRL,IRL,IRL,IRL,IRL,IRL,IRL,IRL,IRL,0,0,0,0,0,0, /* digits */
54/* 64- 79 */ 0,0,0,0,EX,EX,LGC,0,0,0,0,0,0,0,0,0, /* D,E,F */
55/* 80- 95 */ 0,0,0,0,LGC,0,0,0,0,0,0,0,0,0,0,0, /* T */
56/* 96-111 */ 0,0,0,0,EX,EX,LGC,0,0,0,0,0,0,0,0,0, /* d,e,f */
57/* 112-127 */ 0,0,0,0,LGC,0,0,0,0,0,0,0,0,0,0,0 /* t */
58};
59
60s_rsne(a) namelist_arglist *a;
61{
62 int n;
63 struct namelistentry *entry;
64 int nelem, vlen, vtype;
65 char *nmlist_nm, *addr;
66
67 nml_rd = "namelist read";
68 reading = YES;
69 formatted = NAMELIST;
70 fmtbuf = "ext namelist io";
71 if(n=c_le(a,READ)) return(n);
72 getn = t_getc;
73 ungetn = ungetc;
74 leof = curunit->uend;
75 if(curunit->uwrt && ! nowreading(curunit)) err(errflag, errno, nml_rd)
76
77 /* look for " &namelistname " */
78 nmlist_nm = a->namelist->namelistname;
79 while(isblnk(GETC)) ;
80 /* check for "&end" (like IBM) or "$end" (like DEC) */
81 if(ch != '&' && ch != '$') goto rderr;
82 /* save it - write out using the same character as used on input */
83 namelistkey_ = ch;
84 while( *nmlist_nm )
85 if( GETC != *nmlist_nm++ )
86 {
87 nml_rd = "incorrect namelist name";
88 goto rderr;
89 }
90 if(!isblnk(GETC)) goto rderr;
91 while(isblnk(GETC)) ;
92 if(leof) goto rderr;
93 UNGETC();
94
95 while( GETC != namelistkey_ )
96 {
97 UNGETC();
98 /* get variable name */
99 if(!nameflag && rd_name(var_name)) goto rderr;
100
101 entry = a->namelist->names;
102 /* loop through namelist entries looking for this variable name */
103 while( entry->varname[0] != 0 )
104 {
105 if( strcmp(entry->varname, var_name) == 0 ) goto got_name;
106 entry++;
107 }
108 nml_rd = "incorrect variable name";
109 goto rderr;
110got_name:
111 if( n = get_pars( entry, &addr, &nelem, &vlen, &vtype ))
112 goto rderr_n;
113 while(isblnk(GETC)) ;
114 if(ch != '=') goto rderr;
115
116 nameflag = NO;
117 if(n = l_read( nelem, addr, vlen, vtype )) goto rderr_n;
118 while(isblnk(GETC));
119 if(ch == ',') while(isblnk(GETC));
120 UNGETC();
121 if(leof) goto rderr;
122 }
123 /* check for 'end' after '&' or '$'*/
124 if(GETC!='e' || GETC!='n' || GETC!='d' )
125 goto rderr;
126 /* flush to next input record */
127flush:
128 while(GETC != '\n' && ch != EOF);
129 return(ch == EOF ? EOF : OK);
130
131rderr:
132 if(leof)
133 n = EOF;
134 else
135 n = F_ERNMLIST;
136rderr_n:
137 if(n == EOF ) err(endflag,EOF,nml_rd);
138 /* flush after error in case restart I/O */
139 if(ch != '\n') while(GETC != '\n' && ch != EOF) ;
140 err(errflag,n,nml_rd)
141}
142
143#define MAXSUBS 7
144
145LOCAL
146get_pars( entry, addr, nelem, vlen, vtype )
147struct namelistentry *entry;
148char **addr; /* beginning address to read into */
149int *nelem, /* number of elements to read */
150 *vlen, /* length of elements */
151 *vtype; /* type of elements */
152{
153 int offset, i, n,
154 *dimptr, /* points to dimensioning info */
155 ndim, /* number of dimensions */
156 baseoffset, /* offset of corner element */
157 *span, /* subscript span for each dimension */
158 subs[MAXSUBS], /* actual subscripts */
159 subcnt = -1; /* number of actual subscripts */
160
161
162 /* get element size and base address */
163 *vlen = entry->typelen;
164 *addr = entry->varaddr;
165
166 /* get type */
167 switch ( *vtype = entry->type ) {
168 case TYSHORT:
169 case TYLONG:
170 case TYREAL:
171 case TYDREAL:
172 case TYCOMPLEX:
173 case TYDCOMPLEX:
174 case TYLOGICAL:
175 case TYCHAR:
176 break;
177 default:
178 fatal(F_ERSYS,"unknown type in rsnmle");
179 }
180
181 /* get number of elements */
182 dimptr = entry->dimp;
183 if( dimptr==NULL )
184 { /* scalar */
185 *nelem = 1;
186 return(OK);
187 }
188
189 if( GETC != '(' )
190 { /* entire array */
191 *nelem = dimptr[1];
192 UNGETC();
193 return(OK);
194 }
195
196 /* get element length, number of dimensions, base, span vector */
197 ndim = dimptr[0];
198 if(ndim<=0 || ndim>MAXSUBS) fatal(F_ERSYS,"illegal dimensions");
199 baseoffset = dimptr[2];
200 span = dimptr+3;
201
202 /* get subscripts from input data */
203 while(ch!=')') {
204 if( ++subcnt > MAXSUBS-1 ) return F_ERNMLIST;
205 if(n=get_int(&subs[subcnt])) return n;
206 GETC;
207 if(leof) return EOF;
208 if(ch != ',' && ch != ')') return F_ERNMLIST;
209 }
210 if( ++subcnt != ndim ) return F_ERNMLIST;
211
212 offset = subs[ndim-1];
213 for( i = ndim-2; i>=0; i-- )
214 offset = subs[i] + span[i]*offset;
215 offset -= baseoffset;
216 *nelem = dimptr[1] - offset;
217 if( offset < 0 || offset >= dimptr[1] )
218 return F_ERNMLIST;
219 *addr = *addr + (*vlen)*offset;
220 return OK;
221}
222
223LOCAL
224get_int(subval)
225int *subval;
226{
227 int sign=0, value=0, cnt=0;
228
229 /* look for sign */
230 if(GETC == '-') sign = -1;
231 else if(ch == '+') ;
232 else UNGETC();
233 if(ch == EOF) return(EOF);
234
235 while(isdigit(GETC))
236 {
237 value = 10*value + ch-'0';
238 cnt++;
239 }
240 UNGETC();
241 if(ch == EOF) return EOF;
242 if(cnt == 0 ) return F_ERNMLIST;
243 if(sign== -1) value = -value;
244 *subval = value;
245 return OK;
246}
247
248LOCAL
249rd_name(ptr)
250char *ptr;
251{
252 /* read a variable name from the input stream */
253 char *init = ptr-1;
254
255 if(!isalpha(GETC)) {
256 UNGETC();
257 return(ERROR);
258 }
259 *ptr++ = ch;
260 while(isalnum(GETC))
261 {
262 if(ptr-init > VL ) return(ERROR);
263 *ptr++ = ch;
264 }
265 *ptr = '\0';
266 UNGETC();
267 return(OK);
268}
269
270LOCAL
271t_getc()
272{ int ch;
273 static newline = YES;
274rd:
275 if(curunit->uend) {
276 leof = EOF;
277 return(EOF);
278 }
279 if((ch=getc(cf))!=EOF)
280 {
281 if(ch == '\n') newline = YES;
282 else if(newline==YES)
283 { /* skip first character on each line for namelist */
284 newline = NO;
285 goto rd;
286 }
287 return(ch);
288 }
289 if(feof(cf))
290 { curunit->uend = YES;
291 leof = EOF;
292 }
293 else clearerr(cf);
294 return(EOF);
295}
296
297LOCAL
298l_read(number,ptr,len,type) ftnint number,type; flex *ptr; ftnlen len;
299{ int i,n;
300 double *yy;
301 float *xx;
302
303 lcount = 0;
304 for(i=0;i<number;i++)
305 {
306 if(leof) return EOF;
307 if(lcount==0)
308 {
309 ltype = NULL;
310 if(i!=0)
311 { /* skip to comma */
312 while(isblnk(GETC));
313 if(leof) return(EOF);
314 if(ch == namelistkey_)
315 { UNGETC();
316 return(OK);
317 }
318 if(ch != ',' ) return(F_ERNMLIST);
319 }
320 while(isblnk(GETC));
321 if(leof) return(EOF);
322 UNGETC();
323 if(i!=0 && ch == namelistkey_) return(OK);
324
325 switch((int)type)
326 {
327 case TYSHORT:
328 case TYLONG:
329 if(!isint(ch)) return(OK);
330 ERRNM(l_R(1));
331 break;
332 case TYREAL:
333 case TYDREAL:
334 if(!isrl(ch)) return(OK);
335 ERRNM(l_R(1));
336 break;
337 case TYCOMPLEX:
338 case TYDCOMPLEX:
339 if(!isdigit(ch) && ch!='(') return(OK);
340 ERRNM(l_C());
341 break;
342 case TYLOGICAL:
343 if(!islgc(ch)) return(OK);
344 ERRNM(l_L());
345 if(nameflag) return(OK);
346 break;
347 case TYCHAR:
348 if(!isdigit(ch) && !isapos(ch)) return(OK);
349 ERRNM(l_CHAR());
350 break;
351 }
352
353 if(leof) return(EOF);
354 /* peek at next character -
355 should be separator or namelistkey_ */
356 GETC; UNGETC();
357 if(!issep(ch) && (ch != namelistkey_))
358 return( leof?EOF:F_ERNMLIST );
359 }
360
361 if(!ltype) return(F_ERNMLIST);
362 switch((int)type)
363 {
364 case TYSHORT:
365 ptr->flshort=lx;
366 break;
367 case TYLOGICAL:
368 if(len == sizeof(short))
369 ptr->flshort = lx;
370 else
371 ptr->flint = lx;
372 break;
373 case TYLONG:
374 ptr->flint=lx;
375 break;
376 case TYREAL:
377 ptr->flreal=lx;
378 break;
379 case TYDREAL:
380 ptr->fldouble=lx;
381 break;
382 case TYCOMPLEX:
383 xx=(float *)ptr;
384 *xx++ = ly;
385 *xx = lx;
386 break;
387 case TYDCOMPLEX:
388 yy=(double *)ptr;
389 *yy++ = ly;
390 *yy = lx;
391 break;
392 case TYCHAR:
393 b_char(lchar,(char *)ptr,len);
394 break;
395 }
396 if(lcount>0) lcount--;
397 ptr = (flex *)((char *)ptr + len);
398 }
399 if(lcount>0) return F_ERNMLIST;
400 return(OK);
401}
402
403LOCAL
404get_repet()
405{
406 double lc;
407 if(isdigit(GETC))
408 { UNGETC();
409 rd_int(&lc);
410 lcount = (int)lc;
411 if(GETC!='*')
412 if(leof) return(EOF);
413 else return(F_ERREPT);
414 }
415 else
416 { lcount = 1;
417 UNGETC();
418 }
419 return(OK);
420}
421
422LOCAL
423l_R(flg) int flg;
424{ double a,b,c,d;
425 int da,db,dc,dd;
426 int i,sign=0;
427 a=b=c=d=0;
428 da=db=dc=dd=0;
429
430 if( flg ) /* real */
431 {
432 da=rd_int(&a); /* repeat count ? */
433 if(GETC=='*')
434 {
435 if (a <= 0.) return(F_ERNREP);
436 lcount=(int)a;
437 db=rd_int(&b); /* whole part of number */
438 }
439 else
440 { UNGETC();
441 db=da;
442 b=a;
443 lcount=1;
444 }
445 }
446 else /* complex */
447 {
448 db=rd_int(&b);
449 }
450
451 if(GETC=='.' && isdigit(GETC))
452 { UNGETC();
453 dc=rd_int(&c); /* fractional part of number */
454 }
455 else
456 { UNGETC();
457 dc=0;
458 c=0.;
459 }
460 if(isexp(GETC))
461 dd=rd_int(&d); /* exponent */
462 else if (ch == '+' || ch == '-')
463 { UNGETC();
464 dd=rd_int(&d);
465 }
466 else
467 { UNGETC();
468 dd=0;
469 }
470 if(db<0 || b<0)
471 { sign=1;
472 b = -b;
473 }
474 for(i=0;i<dc;i++) c/=10.;
475 b=b+c;
476 if (dd > 0)
477 { for(i=0;i<d;i++) b *= 10.;
478 for(i=0;i< -d;i++) b /= 10.;
479 }
480 lx=sign?-b:b;
481 ltype=TYLONG;
482 return(OK);
483}
484
485LOCAL
486rd_int(x) double *x;
487{ int sign=0,i=0;
488 double y=0.0;
489 if(GETC=='-') sign = -1;
490 else if(ch=='+') sign=0;
491 else UNGETC();
492 while(isdigit(GETC))
493 { i++;
494 y=10*y + ch-'0';
495 }
496 UNGETC();
497 if(sign) y = -y;
498 *x = y;
499 return(y==0.0?sign:i); /* 0:[+]&&y==0, -1:-&&y==0, >0:#digits&&y!=0 */
500}
501
502LOCAL
503l_C()
504{ int n;
505 if(n=get_repet()) return(n); /* get repeat count */
506 if(GETC!='(') err(errflag,F_ERNMLIST,"no (")
507 while(isblnk(GETC));
508 UNGETC();
509 l_R(0); /* get real part */
510 ly = lx;
511 while(isblnk(GETC)); /* get comma */
512 if(leof) return(EOF);
513 if(ch!=',') return(F_ERNMLIST);
514 while(isblnk(GETC));
515 UNGETC();
516 if(leof) return(EOF);
517 l_R(0); /* get imag part */
518 while(isblnk(GETC));
519 if(ch!=')') err(errflag,F_ERNMLIST,"no )")
520 ltype = TYCOMPLEX;
521 return(OK);
522}
523
524LOCAL
525l_L()
526{
527 int n, keychar=ch, scanned=NO;
528 if(ch=='f' || ch=='F' || ch=='t' || ch=='T')
529 {
530 scanned=YES;
531 if(rd_name(var_name))
532 return(leof?EOF:F_ERNMLIST);
533 while(isblnk(GETC));
534 UNGETC();
535 if(ch == '=' || ch == '(')
536 { /* found a name, not a value */
537 nameflag = YES;
538 return(OK);
539 }
540 }
541 else
542 {
543 if(n=get_repet()) return(n); /* get repeat count */
544 if(GETC=='.') GETC;
545 keychar = ch;
546 }
547 switch(keychar)
548 {
549 case 't':
550 case 'T':
551 lx=1;
552 break;
553 case 'f':
554 case 'F':
555 lx=0;
556 break;
557 default:
558 if(ch==EOF) return(EOF);
559 else err(errflag,F_ERNMLIST,"logical not T or F");
560 }
561 ltype=TYLOGICAL;
562 if(scanned==NO)
563 {
564 while(!issep(GETC) && ch!=EOF) ;
565 UNGETC();
566 }
567 if(ch == EOF ) return(EOF);
568 return(OK);
569}
570
571#define BUFSIZE 128
572LOCAL
573l_CHAR()
574{ int size,i,n;
575 char quote,*p;
576 if(n=get_repet()) return(n); /* get repeat count */
577 if(isapos(GETC)) quote=ch;
578 else if(ch == EOF) return EOF;
579 else return F_ERNMLIST;
580 ltype=TYCHAR;
581 if(lchar!=NULL) free(lchar);
582 size=BUFSIZE-1;
583 p=lchar=(char *)malloc(BUFSIZE);
584 if(lchar==NULL) return (F_ERSPACE);
585 for(i=0;;)
586 { while( GETC!=quote && ch!='\n' && ch!=EOF && ++i<size )
587 *p++ = ch;
588 if(i==size)
589 {
590 newone:
591 size += BUFSIZE;
592 lchar=(char *)realloc(lchar, size+1);
593 if(lchar==NULL) return( F_ERSPACE );
594 p=lchar+i-1;
595 *p++ = ch;
596 }
597 else if(ch==EOF) return(EOF);
598 else if(ch=='\n')
599 { if(*(p-1) == '\\') *(p-1) = ch;
600 }
601 else if(GETC==quote)
602 { if(++i<size) *p++ = ch;
603 else goto newone;
604 }
605 else
606 { UNGETC();
607 *p = '\0';
608 return(OK);
609 }
610 }
611}