1 /*
2  * CalmaReadio.c --
3  *
4  * Input of Calma GDS-II stream format.
5  * Low-level input.
6  *
7  *     *********************************************************************
8  *     * Copyright (C) 1985, 1990 Regents of the University of California. *
9  *     * Permission to use, copy, modify, and distribute this              *
10  *     * software and its documentation for any purpose and without        *
11  *     * fee is hereby granted, provided that the above copyright          *
12  *     * notice appear in all copies.  The University of California        *
13  *     * makes no representations about the suitability of this            *
14  *     * software for any purpose.  It is provided "as is" without         *
15  *     * express or implied warranty.  Export of this software outside     *
16  *     * of the United States of America may require an export license.    *
17  *     *********************************************************************
18  */
19 
20 #ifndef lint
21 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdio.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
22 #endif  /* not lint */
23 
24 #include <stdio.h>
25 #include <sys/types.h>
26 
27 #include <netinet/in.h>
28 
29 #include "utils/magic.h"
30 #include "utils/geometry.h"
31 #include "tiles/tile.h"
32 #include "utils/utils.h"
33 #include "utils/hash.h"
34 #include "database/database.h"
35 #include "database/databaseInt.h"
36 #include "utils/malloc.h"
37 #include "utils/tech.h"
38 #include "cif/cif.h"
39 #include "cif/CIFint.h"
40 #include "cif/CIFread.h"
41 #include "utils/signals.h"
42 #include "windows/windows.h"
43 #include "dbwind/dbwind.h"
44 #include "utils/styles.h"
45 #include "textio/textio.h"
46 #include "calma/calmaInt.h"
47 
48 /* Forward declarations */
49 bool calmaReadR8();
50 bool calmaSkipBytes();
51 
52 
53 /*
54  * ----------------------------------------------------------------------------
55  *
56  * calmaReadTransform --
57  *
58  * Read a CALMA_STRANS, CALMA_MAG, CALMA_ANGLE sequence and construct
59  * the corresponding geometric transform.
60  *
61  * Results:
62  *	TRUE normally, FALSE on EOF or fatal syntax error.
63  *
64  * Side effects:
65  *	Consumes input.
66  *	Modifies the Transform pointed to by 'ptrans'.
67  *
68  * ----------------------------------------------------------------------------
69  */
70 
71 bool
calmaReadTransform(ptrans,name)72 calmaReadTransform(ptrans, name)
73     Transform *ptrans;	/* Fill in this transform */
74     char *name;		/* Name of subcell (for errors) */
75 {
76     int nbytes, rtype, flags, angle;
77     double dangle;
78     double dmag;
79     Transform t;
80 
81     /* Default is the identity transform */
82     *ptrans = GeoIdentityTransform;
83 
84     /* Is there any transform at all? */
85     READRH(nbytes, rtype);
86     if (nbytes < 0) return (FALSE);
87     if (rtype != CALMA_STRANS)
88     {
89 	UNREADRH(nbytes, rtype);
90 	return (TRUE);
91     }
92     if (nbytes != 6)
93     {
94 	(void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH);
95 	return (FALSE);
96     }
97     READI2(flags);
98 
99     /* Look for magnification and angle */
100     READRH(nbytes, rtype);
101     if (nbytes < 0) return (FALSE);
102     if (rtype == CALMA_MAG)
103     {
104 	if (nbytes != CALMAHEADERLENGTH + 8)
105 	{
106 	    (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH);
107 	    return (FALSE);
108 	}
109 	if (!calmaReadR8(&dmag)) return (FALSE);
110 
111         if (dmag != (double)((int)(dmag + 0.5)))
112 	{
113 	    CalmaReadError("Non-integer magnification (%g) in transform\n", dmag);
114 	    CalmaReadError("Rounding to %d.\n", (int)(dmag + 0.5));
115 	}
116 	GeoScaleTrans(ptrans, (int)(dmag + 0.5), &t);
117 	*ptrans = t;
118     }
119     else UNREADRH(nbytes, rtype);
120 
121     READRH(nbytes, rtype);
122     if (nbytes < 0) return (FALSE);
123     dangle = 0.0;
124     if (rtype == CALMA_ANGLE)
125     {
126 	if (nbytes != CALMAHEADERLENGTH + 8)
127 	{
128 	    (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH);
129 	    return (FALSE);
130 	}
131 	if (!calmaReadR8(&dangle)) return (FALSE);
132     }
133     else UNREADRH(nbytes, rtype);
134 
135     /* Make sure the angle is Manhattan */
136     angle = (int) dangle;
137     while (angle < 0) angle += 360;
138     while (angle > 360) angle -= 360;
139     switch (angle)
140     {
141 	case 360:
142 	    angle = 0;
143 	    break;
144 	case 0:	case 90: case 180: case 270:
145 	    break;
146 	default:
147 	    CalmaReadError("Non-Manhattan angle (%d) in transform\n", angle);
148 	    if (angle < 45) angle = 0;
149 	    else if (angle < 135) angle = 90;
150 	    else if (angle < 225) angle = 180;
151 	    else if (angle < 315) angle = 270;
152 	    else angle = 0;
153 	    CalmaReadError("    Rounding to %d degrees.\n", angle);
154     }
155 
156     /*
157      * Construct the transform.
158      * Magic angles are clockwise; Calma angles are counterclockwise.
159      */
160     if (flags & CALMA_STRANS_UPSIDEDOWN)
161     {
162 	GeoTransTrans(ptrans, &GeoUpsideDownTransform, &t);
163 	*ptrans = t;
164     }
165     switch (angle)
166     {
167 	case 90:
168 	    GeoTransTrans(ptrans, &Geo270Transform, &t);
169 	    *ptrans = t;
170 	    break;
171 	case 180:
172 	    GeoTransTrans(ptrans, &Geo180Transform, &t);
173 	    *ptrans = t;
174 	    break;
175 	case 270:
176 	    GeoTransTrans(ptrans, &Geo90Transform, &t);
177 	    *ptrans = t;
178 	    break;
179     }
180 
181     return (TRUE);
182 }
183 
184 /*
185  * ----------------------------------------------------------------------------
186  *
187  * calmaReadI2Record --
188  *
189  * Read a record that should contain a two-byte integer.
190  *
191  * Results:
192  *	TRUE on success, FALSE if the record type we read is not
193  *	what we're expecting, or if it is of the wrong size.
194  *
195  * Side effects:
196  *	Consumes input.
197  *	Stores the result value in *pvalue (note that this is a normal
198  *	int, even though we're reading only 16 bits from the input).
199  *
200  * ----------------------------------------------------------------------------
201  */
202 
203 bool
calmaReadI2Record(type,pvalue)204 calmaReadI2Record(type, pvalue)
205     int type;		/* Type of record expected */
206     int *pvalue;	/* Store value here */
207 {
208     int nbytes, rtype, n;
209 
210     READRH(nbytes, rtype);
211     if (nbytes < 0)
212 	goto eof;
213     if (type != rtype)
214     {
215 	calmaUnexpected(type, rtype);
216 	return (FALSE);
217     }
218 
219     /* Read the value */
220     READI2(n);
221     if (feof(calmaInputFile)) goto eof;
222     *pvalue = n;
223     return (TRUE);
224 
225 eof:
226     CalmaReadError("Unexpected EOF.\n");
227     return (FALSE);
228 }
229 
230 /*
231  * ----------------------------------------------------------------------------
232  *
233  * calmaReadI4Record --
234  *
235  * Read a record that should contain a four-byte integer.
236  *
237  * Results:
238  *	TRUE on success, FALSE if the record type we read is not
239  *	what we're expecting, or if it is of the wrong size.
240  *
241  * Side effects:
242  *	Consumes input.
243  *	Stores the result value in *pvalue.
244  *
245  * ----------------------------------------------------------------------------
246  */
247 
248 bool
calmaReadI4Record(type,pvalue)249 calmaReadI4Record(type, pvalue)
250     int type;		/* Type of record expected */
251     int *pvalue;	/* Store value here */
252 {
253     int nbytes, rtype, n;
254 
255     READRH(nbytes, rtype);
256     if (nbytes < 0)
257 	goto eof;
258     if (type != rtype)
259     {
260 	calmaUnexpected(type, rtype);
261 	return (FALSE);
262     }
263 
264     /* Read the value */
265     READI4(n);
266     if (feof(calmaInputFile)) goto eof;
267     *pvalue = n;
268     return (TRUE);
269 
270 eof:
271     CalmaReadError("Unexpected EOF.\n");
272     return (FALSE);
273 }
274 
275 /*
276  * ----------------------------------------------------------------------------
277  *
278  * calmaReadStringRecord --
279  *
280  * Read a record that should contain an ASCII string.
281  *
282  * Results:
283  *	TRUE on success, FALSE if the record type we read is not
284  *	what we're expecting.
285  *
286  * Side effects:
287  *	Consumes input.
288  *	Allocates memory for string str (must be freed by the caller)
289  *	Stores the result in the string pointed to by 'str'.
290  *
291  * ----------------------------------------------------------------------------
292  */
293 
294 bool
calmaReadStringRecord(type,str)295 calmaReadStringRecord(type, str)
296     int type;
297     char **str;
298 {
299     int nbytes, rtype;
300 
301     READRH(nbytes, rtype);
302     if (nbytes < 0)
303 	goto eof;
304 
305     if (type != rtype)
306     {
307 	calmaUnexpected(type, rtype);
308 	return (FALSE);
309     }
310 
311     nbytes -= CALMAHEADERLENGTH;
312     *str = (char *) mallocMagic(nbytes + 1);
313     if (fread(*str, sizeof (char), nbytes, calmaInputFile) != nbytes)
314 	goto eof;
315 
316     *(*str + nbytes) = '\0';
317     return (TRUE);
318 
319 eof:
320     CalmaReadError("Unexpected EOF.\n");
321     return (FALSE);
322 }
323 
324 /*
325  * ----------------------------------------------------------------------------
326  *
327  * calmaReadR8 --
328  *
329  * Read a single 8-byte real number in Calma stream format.
330  * Convert to internal double-precision format and store in
331  * the double pointed to by 'pd'.
332  *
333  * Results:
334  *	TRUE on success, FALSE if EOF is encountered.
335  *
336  * Side effects:
337  *	Consumes input.
338  *	Stores the result in the *pd.
339  *
340  * ----------------------------------------------------------------------------
341  */
342 
343 bool
calmaReadR8(pd)344 calmaReadR8(pd)
345     double *pd;		/* Store result in *pd */
346 {
347     int i, exponent;
348     unsigned char dchars[8];
349     double mantissa, d;
350     bool isneg;
351 
352     if (fread((char *) dchars, sizeof (char), sizeof dchars,
353 		calmaInputFile) != sizeof dchars)
354 	return (FALSE);
355 
356     /* Extract the sign and exponent */
357     exponent = dchars[0];
358     if (isneg = (exponent & 0x80))
359 	exponent &= ~0x80;
360     exponent -= 64;
361 
362     /* Construct the mantissa */
363     mantissa = 0.0;
364     for (i = 7; i > 0; i--)
365     {
366 	mantissa += dchars[i];
367 	mantissa /= 256.0;
368     }
369 
370     /* Now raise the mantissa to the exponent */
371     d = mantissa;
372     if (exponent > 0)
373     {
374 	while (exponent-- > 0)
375 	    d *= 16.0;
376     }
377     else if (exponent < 0)
378     {
379 	while (exponent++ < 0)
380 	    d /= 16.0;
381     }
382 
383     /* Make it negative if necessary */
384     if (isneg)
385 	d = -d;
386 
387     *pd = d;
388     return (TRUE);
389 }
390 
391 /*
392  * ----------------------------------------------------------------------------
393  *
394  * calmaSkipSet --
395  *
396  * Skip all records falling in a specified set of types.
397  * Leave the input stream positioned to the start of the first
398  * record not in the specified set.
399  *
400  * The array pointed to by 'skipwhat' contains the record types
401  * of all records to be skipped, terminated with -1.
402  *
403  * Results:
404  *	None.
405  *
406  * Side effects:
407  *	Consumes input.
408  *
409  * ----------------------------------------------------------------------------
410  */
411 
412 void
calmaSkipSet(skipwhat)413 calmaSkipSet(skipwhat)
414     int *skipwhat;
415 {
416     int *skipp;
417     int nbytes, rtype;
418 
419     for (;;)
420     {
421 	READRH(nbytes, rtype);
422 	if (nbytes < 0)
423 	    return;
424 
425 	for (skipp = skipwhat; *skipp >= 0; skipp++)
426 	    if (*skipp == rtype)
427 		goto skipit;
428 
429 	UNREADRH(nbytes, rtype);
430 	break;
431 
432 skipit:
433 	(void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH);
434     }
435 }
436 
437 /*
438  * ----------------------------------------------------------------------------
439  *
440  * calmaSkipExact --
441  *
442  * Skip a single stream record, which must be of the type 'type'.
443  * Leave the input positioned to the start of the record following
444  * this one.  Complain if the record is not the one expected.
445  *
446  * Results:
447  *	TRUE if successful, FALSE if we encountered an error and
448  *	the caller should abort.
449  *
450  * Side effects:
451  *	Consumes input.
452  *
453  * ----------------------------------------------------------------------------
454  */
455 
456 bool
calmaSkipExact(type)457 calmaSkipExact(type)
458     int type;
459 {
460     int nbytes, rtype;
461 
462     /* Eat up the record header */
463     READRH(nbytes, rtype);
464 
465     if (nbytes < 0)
466 	goto eof;
467 
468     /* Skip remainder of record */
469     if (!calmaSkipBytes(nbytes - CALMAHEADERLENGTH))
470 	goto eof;
471 
472     if (rtype != type)
473     {
474 	calmaUnexpected(type, rtype);
475 	return (FALSE);
476     }
477 
478     return (TRUE);
479 
480 eof:
481     CalmaReadError("Unexpected EOF.\n");
482     return (FALSE);
483 }
484 
485 /*
486  * ----------------------------------------------------------------------------
487  *
488  * calmaSkipTo --
489  *
490  * Skip to a record of a particular type.  Leaves the input stream
491  * positioned AFTER the record whose type is given by 'what'.
492  *
493  * Results:
494  *	TRUE if we found this record, FALSE if EOF was encountered.
495  *
496  * Side effects:
497  *	Consumes input.
498  *
499  * ----------------------------------------------------------------------------
500  */
501 
502 bool
calmaSkipTo(what)503 calmaSkipTo(what)
504     int what;
505 {
506     int nbytes, rtype;
507 
508     do
509     {
510 	READRH(nbytes, rtype);
511 	if (nbytes < 0)
512 	    return (FALSE);
513 	calmaSkipBytes(nbytes - CALMAHEADERLENGTH);
514     } while (rtype != what);
515 
516     return (TRUE);
517 }
518 
519 /*
520  * ----------------------------------------------------------------------------
521  *
522  * calmaSkipBytes --
523  *
524  * Skip 'nbytes' bytes from the input.
525  * WARNING: this procedure doesn't know about input saved via UNREADRH(),
526  * so if the caller wants this input to be discarded, it must call READRH()
527  * itself.
528  *
529  * Results:
530  *	TRUE if successful, FALSE if EOF was encountered.
531  *
532  * Side effects:
533  *	Consumes nbytes of input.
534  *
535  * ----------------------------------------------------------------------------
536  */
537 
538 bool
calmaSkipBytes(nbytes)539 calmaSkipBytes(nbytes)
540     int nbytes;	/* Skip this many bytes */
541 {
542     while (nbytes-- > 0)
543 	if (getc(calmaInputFile) < 0)
544 	    return (FALSE);
545 
546     return (TRUE);
547 }
548