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