1 /* Copyright (C) by GFD-Dennou Club, 1999-2000.  All rights reserved. */
2 #include "sys/types.h"
3 #include "sys/stat.h"
4 #include "libtinyf2c.h"
5 
6 #undef abs
7 #undef min
8 #undef max
9 #include "stdlib.h"
10 #include "fio.h"
11 #include "fmt.h"	/* for struct syl */
12 
13 /*global definitions*/
14 unit f__units[MXUNIT];	/*unit table*/
15 flag f__init;	/*0 on entry, 1 after initializations*/
16 cilist *f__elist;	/*active external io list*/
17 icilist *f__svic;	/*active internal io list*/
18 flag f__reading;	/*1 if reading, 0 if writing*/
19 flag f__cplus,f__cblank;
20 char *f__fmtbuf;	/*format */
21 flag f__external;	/*1 if external io, 0 if internal */
22 
23 int (*f__getn)(void);	/* for formatted input */
24 void (*f__putn)(int);	/* for formatted output */
25 int (*f__doed)(struct syl*, char*, ftnlen),(*f__doned)(struct syl*);
26 int (*f__dorevert)(void),(*f__donewrec)(void),(*f__doend)(void);
27 
28 flag f__sequential;	/*1 if sequential io, 0 if direct*/
29 flag f__formatted;	/*1 if formatted io, 0 if unformatted*/
30 FILE *f__cf;	/*current file*/
31 unit *f__curunit;	/*current unit*/
32 int f__recpos;	/*place in current record*/
33 int f__cursor, f__hiwater, f__scale;
34 char *f__icptr;
35 
36 /*error messages*/
37 char *F_err[] =
38 {
39 	"error in format",				/* 100 */
40 	"illegal unit number",				/* 101 */
41 	"formatted io not allowed",			/* 102 */
42 	"unformatted io not allowed",			/* 103 */
43 	"direct io not allowed",			/* 104 */
44 	"sequential io not allowed",			/* 105 */
45 	"can't backspace file",				/* 106 */
46 	"null file name",				/* 107 */
47 	"can't stat file",				/* 108 */
48 	"unit not connected",				/* 109 */
49 	"off end of record",				/* 110 */
50 	"truncation failed in endfile",			/* 111 */
51 	"incomprehensible list input",			/* 112 */
52 	"out of free space",				/* 113 */
53 	"unit not connected",				/* 114 */
54 	"read unexpected character",			/* 115 */
55 	"bad logical input field",			/* 116 */
56 	"bad variable type",				/* 117 */
57 	"bad namelist name",				/* 118 */
58 	"variable not in namelist",			/* 119 */
59 	"no end record",				/* 120 */
60 	"variable count incorrect",			/* 121 */
61 	"subscript for scalar variable",		/* 122 */
62 	"invalid array section",			/* 123 */
63 	"substring out of bounds",			/* 124 */
64 	"subscript out of bounds",			/* 125 */
65 	"can't read file",				/* 126 */
66 	"can't write file",				/* 127 */
67 	"'new' file exists",				/* 128 */
68 	"can't append to file",				/* 129 */
69 	"non-positive record number"			/* 130 */
70 };
71 #define MAXERR (sizeof(F_err)/sizeof(char *)+100)
72 
73 /* to check wether the file can be seeked or not
74  */
f__canseek(FILE * f)75 f__canseek(FILE *f) /*SYSDEP*/
76 {
77 	struct stat x;
78 
79 	if (fstat(fileno(f),&x) < 0)
80 		return(0);
81 	switch(x.st_mode & S_IFMT) {
82 	case S_IFDIR:
83 	case S_IFREG:
84 		if(x.st_nlink > 0)	/* !pipe */
85 			return(1);
86 		else
87 			return(0);
88 	case S_IFCHR:
89 		if(isatty(fileno(f)))
90 			return(0);
91 		return(1);
92 #ifdef S_IFBLK
93 	case S_IFBLK:
94 		return(1);
95 #endif
96 	}
97 	return(0);	/* who knows what it is? */
98 }
99 
100 /* when there are some serious error occur, we will stop the program
101  */
f__fatal(int n,char * s)102 void f__fatal(int n, char *s)
103 {
104 	if(n<100 && n>=0)
105 		perror(s); /*SYSDEP*/
106 	else if(n >= (int)MAXERR || n < -1)
107 		fprintf(stderr,"%s: illegal error number %d\n",s,n);
108 	else if(n == -1)
109 		fprintf(stderr,"%s: end of file\n",s);
110 	else
111 		fprintf(stderr,"%s: %s\n",s,F_err[n-100]);
112 	if (f__curunit) {
113 		fprintf(stderr,"apparent state: unit %d ",
114 			(int)(f__curunit-f__units));
115 		fprintf(stderr, f__curunit->ufnm ? "named %s\n" : "(unnamed)\n",
116 			f__curunit->ufnm);
117 	}
118 	else
119 		fprintf(stderr,"apparent state: internal I/O\n");
120 	if (f__fmtbuf)
121 		fprintf(stderr,"last format: %s\n",f__fmtbuf);
122 	fprintf(stderr,"lately %s %s %s %s",f__reading?"reading":"writing",
123 		f__sequential?"sequential":"direct",f__formatted?"formatted":"unformatted",
124 		f__external?"external":"internal");
125 	sig_die(" IO", 1);
126 }
127 
128 /*initialization routine*/
f_init(Void)129 VOID f_init(Void)
130 {
131 	unit *p;
132 
133 	f__init=1;
134 	p= &f__units[0];
135 	p->ufd=stderr;
136 	p->useek=f__canseek(stderr);
137 	p->ufmt=1;
138 	p->uwrt=1;
139 	p = &f__units[5];
140 	p->ufd=stdin;
141 	p->useek=f__canseek(stdin);
142 	p->ufmt=1;
143 	p->uwrt=0;
144 	p= &f__units[6];
145 	p->ufd=stdout;
146 	p->useek=f__canseek(stdout);
147 	p->ufmt=1;
148 	p->uwrt=1;
149 }
150 
151 /* check wether the  file can be read
152  */
f__nowreading(unit * x)153 f__nowreading(unit *x)
154 {
155 	long loc;
156 	int ufmt, urw;
157 	extern char *f__r_mode[], *f__w_mode[];
158 
159 	if (x->urw & 1)
160 		goto done;
161 	if (!x->ufnm)
162 		goto cantread;
163 	ufmt = x->url ? 0 : x->ufmt;
164 	loc = ftell(x->ufd);
165 	urw = 3;
166 	if (!freopen(x->ufnm, f__w_mode[ufmt|2], x->ufd)) {
167 		urw = 1;
168 		if(!freopen(x->ufnm, f__r_mode[ufmt], x->ufd)) {
169  cantread:
170 			errno = 126;
171 			return 1;
172 		}
173 	}
174 	fseek(x->ufd,loc,SEEK_SET);
175 	x->urw = urw;
176  done:
177 	x->uwrt = 0;
178 	return 0;
179 }
180 
181 /* check wether the  file can be write
182  */
f__nowwriting(unit * x)183 f__nowwriting(unit *x)
184 {
185 	long loc;
186 	int ufmt;
187 	extern char *f__w_mode[];
188 
189 	if (x->urw & 2)
190 		goto done;
191 	if (!x->ufnm)
192 		goto cantwrite;
193 	ufmt = x->url ? 0 : x->ufmt;
194 	if (x->uwrt == 3) { /* just did write, rewind */
195 		if (!(f__cf = x->ufd = freopen(x->ufnm,f__w_mode[ufmt],x->ufd)))
196 			goto cantwrite;
197 		x->urw = 2;
198 	}else {
199 		loc=ftell(x->ufd);
200 		if (!(f__cf = x->ufd =
201 			freopen(x->ufnm, f__w_mode[ufmt |= 2], x->ufd)))
202 		{
203 			x->ufd = NULL;
204  cantwrite:
205 			errno = 127;
206 			return(1);
207 		}
208 		x->urw = 3;
209 		fseek(x->ufd,loc,SEEK_SET);
210 	}
211  done:
212 	x->uwrt = 1;
213 	return 0;
214 }
215 
err__fl(int f,int m,char * s)216 int err__fl(int f, int m, char *s)
217 {
218 	if (!f)
219 		f__fatal(m, s);
220 	if (f__doend)
221 		(*f__doend)();
222 	return errno = m;
223 }
224