1 /*
2 * get.c -- Read entities from files.
3 *
4 * Copyright (C) 1994-97 K. Scott Hunziker.
5 * Copyright (C) 1990-94 The Boeing Company.
6 *
7 * See the file COPYING for license, warranty, and permission details.
8 */
9
10 static char rcsid[] =
11 "$Id: get.c,v 1.3 1997/06/06 03:47:52 ksh Exp $";
12
13 #include <stdio.h>
14 #include "get.h"
15 #include "put.h"
16 #include "entity.h"
17 #include "scalar.h"
18 #include "vector.h"
19 #include "matrix.h"
20 #include "table.h"
21 #include "function.h"
22 #include "file_io.h"
23
24 /* Keep a list of pointers to the entities we've read. */
25
26 static ENTITY **ent_list;
27 static int ent_length; /* length of ent_list */
28 static int seq_num;
29
30 ENTITY *
bi_get(n,fname)31 bi_get (n, fname)
32 int n;
33 ENTITY *fname;
34 {
35 /*
36 * This routine reads an entity from a file. The file is in Algae's
37 * "native" binary format, which is essentially a mirror of the C
38 * structures. Someday we'll have to formalize this...
39 *
40 * If no args are given (n==0), then we read from stdin.
41 */
42
43 ENTITY *ret;
44
45 FILE *stream = fname ? find_file (entity_to_string (fname),
46 FILE_INPUT) : stdin;
47
48 if (stream)
49 {
50 seq_num = 0;
51 ent_length = 100;
52 ent_list = MALLOC (ent_length * sizeof (ENTITY *));
53 ret = get_entity (stream);
54 FREE (ent_list);
55 }
56 else
57 {
58 ret = NULL;
59 }
60
61 return ret;
62 }
63
64 ENTITY *
get_entity(stream)65 get_entity (stream)
66 FILE *stream;
67 {
68 /* Read an entity from `stream'. (See `bi_get'.) */
69
70 ENTITY *ret;
71 CLASS c;
72 char header[6];
73 int ver, seq, this_seq;
74
75 /* Check the header and version. */
76
77 header[5] = '\0';
78 if (fread (header, 1, 5, stream) < 5)
79 {
80 READ_WARN (stream);
81 return NULL;
82 }
83
84 if (strcmp (header, "\177Alki"))
85 {
86 /* Maybe it's ancient? */
87
88 if (header[0] == '\0' &&
89 header[1] == '\0' &&
90 header[2] == '\014' &&
91 header[3] == '\373')
92 {
93 char s[3];
94 if (fread (s, 1, 3, stream) < 3)
95 {
96 READ_WARN (stream);
97 return NULL;
98 }
99 ver = 0;
100 c = (CLASS) s[2];
101 }
102 else
103 {
104 warn ("Not a valid Algae binary file.");
105 return NULL;
106 }
107 }
108 else
109 {
110 char v;
111 if (fread (&v, 1, 1, stream) < 1)
112 {
113 READ_WARN (stream);
114 return NULL;
115 }
116
117 ver = (int) v;
118 if (ver > (char) FILE_FORMAT)
119 {
120 warn ("Incompatible binary file version.");
121 return NULL;
122 }
123
124 /*
125 * Read the reference tag. If it's zero, read the entity and keep
126 * its pointer on the entity list. If the tag is not zero, then it's
127 * a reference to the previously read entity with that sequence
128 * number.
129 */
130
131 if (!READ_INT (&seq, stream))
132 return NULL;
133 if (seq < 0 || seq > seq_num)
134 {
135 warn ("Invalid reference in binary file.");
136 return NULL;
137 }
138 if (seq)
139 return copy_entity (ent_list[seq - 1]);
140
141 if (!READ_INT (&c, stream))
142 return NULL;
143 }
144
145 this_seq = seq_num++;
146
147 if (c >= NUM_CLASS)
148 {
149 warn ("Invalid entity in file.");
150 return NULL;
151 }
152
153 switch (c)
154 {
155 case scalar:
156 ret = get_scalar (stream, ver);
157 break;
158 case vector:
159 ret = get_vector (stream, ver);
160 break;
161 case matrix:
162 ret = get_matrix (stream, ver);
163 break;
164 case table:
165 ret = get_table (stream, ver);
166 break;
167 case function:
168 ret = get_function (stream, ver);
169 break;
170 default:
171 BAD_CLASS (c);
172 return NULL;
173 }
174
175 if (seq_num >= ent_length)
176 {
177 ent_length += 100;
178 ent_list = REALLOC (ent_list, ent_length * sizeof (ENTITY *));
179 }
180
181 return ent_list[this_seq] = ret;
182 }
183
184 size_t
fread_int(ptr,n,stream)185 fread_int (ptr, n, stream)
186 char *ptr;
187 size_t n;
188 FILE *stream;
189 {
190 return fread (ptr, 4, n, stream);
191 }
192
193 size_t
fread_int_reverse(ptr,n,stream)194 fread_int_reverse (ptr, n, stream)
195 char *ptr;
196 size_t n;
197 FILE *stream;
198 {
199 size_t w = 0;
200 char t;
201
202 assert (sizeof (int) == 4);
203 assert (ptr != NULL);
204 assert (n > 0);
205
206 do
207 {
208 if (fread (ptr, 4, 1, stream) < 1)
209 return w;
210 t = ptr[0]; ptr[0] = ptr[3]; ptr[3] = t;
211 t = ptr[1]; ptr[1] = ptr[2]; ptr[2] = t;
212 }
213 while (ptr += 4, ++w < n);
214
215 return w;
216 }
217
218 size_t
fread_double(ptr,n,stream)219 fread_double (ptr, n, stream)
220 char *ptr;
221 size_t n;
222 FILE *stream;
223 {
224 return fread (ptr, 8, n, stream);
225 }
226
227 size_t
fread_double_reverse(ptr,n,stream)228 fread_double_reverse (ptr, n, stream)
229 char *ptr;
230 size_t n;
231 FILE *stream;
232 {
233 char t;
234 size_t w = 0;
235
236 assert (sizeof (double) == 8);
237 assert (ptr != NULL);
238 assert (n > 0);
239
240 do
241 {
242 if (fread (ptr, 8, 1, stream) < 1)
243 return w;
244 t = ptr[0]; ptr[0] = ptr[7]; ptr[7] = t;
245 t = ptr[1]; ptr[1] = ptr[6]; ptr[6] = t;
246 t = ptr[2]; ptr[2] = ptr[5]; ptr[5] = t;
247 t = ptr[3]; ptr[3] = ptr[4]; ptr[4] = t;
248 }
249 while (ptr += 8, ++w < n);
250
251 return w;
252 }
253
254 #if BINARY_FORMAT == CRAY_FLOAT
255
256 static char *cray_format_error = "Error converting from IEEE to Cray format.";
257
258 size_t
fread_int_cray(ptr,n,stream)259 fread_int_cray (ptr, n, stream)
260 char *ptr;
261 size_t n;
262 FILE *stream;
263 {
264 int type = 1;
265 int bitoff = 0;
266 int num;
267 char *buf = MALLOC (n * 4);
268
269 num = fread (buf, 4, n, stream);
270 if (IEG2CRAY (&type, &num, buf, &bitoff, ptr))
271 {
272 fail (cray_format_error);
273 FREE (buf);
274 raise_exception ();
275 }
276
277 FREE (buf);
278 return num;
279 }
280
281 size_t
fread_double_cray(ptr,n,stream)282 fread_double_cray (ptr, n, stream)
283 char *ptr;
284 size_t n;
285 FILE *stream;
286 {
287 int type = 8;
288 int bitoff = 0;
289 int num;
290 void *buf = MALLOC (n * 8);
291
292 num = fread (buf, 8, n, stream);
293 if (IEG2CRAY (&type, &num, buf, &bitoff, ptr))
294 {
295 fail (cray_format_error);
296 FREE (buf);
297 raise_exception ();
298 }
299
300 FREE (buf);
301 return num;
302 }
303
304 size_t
fread_int_cray_reverse(ptr,n,stream)305 fread_int_cray_reverse (ptr, n, stream)
306 char *ptr;
307 size_t n;
308 FILE *stream;
309 {
310 int type = 1;
311 int bitoff = 0;
312 int num;
313 char *buf = MALLOC (n * 4);
314
315 num = fread (buf, 4, n, stream);
316 reverse_words (buf, 4, n);
317 if (IEG2CRAY (&type, &num, buf, &bitoff, ptr))
318 {
319 fail (cray_format_error);
320 FREE (buf);
321 raise_exception ();
322 }
323
324 FREE (buf);
325 return num;
326 }
327
328 size_t
fread_double_cray_reverse(ptr,n,stream)329 fread_double_cray_reverse (ptr, n, stream)
330 char *ptr;
331 size_t n;
332 FILE *stream;
333 {
334 int type = 8;
335 int bitoff = 0;
336 int num;
337 void *buf = MALLOC (n * 8);
338
339 num = fread (buf, 8, n, stream);
340 reverse_words (buf, 4, n);
341 if (IEG2CRAY (&type, &num, buf, &bitoff, ptr))
342 {
343 fail (cray_format_error);
344 FREE (buf);
345 raise_exception ();
346 }
347
348 FREE (buf);
349 return num;
350 }
351
352 #endif
353