1 /*
2 
3 -Disclaimer
4 
5    THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE
6    CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S.
7    GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE
8    ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE
9    PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS"
10    TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY
11    WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A
12    PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC
13    SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
14    SOFTWARE AND RELATED MATERIALS, HOWEVER USED.
15 
16    IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA
17    BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT
18    LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19    INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS,
20    REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE
21    REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY.
22 
23    RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF
24    THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY
25    CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE
26    ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE.
27 
28 */
29 
30 /*
31  CSPICE private macro file.
32 
33 -Particulars
34 
35    Current list of macros (spelling counts)
36 
37      BLANK
38      C2F_MAP_CELL
39      C2F_MAP_CELL2
40      C2F_MAP_CELL3
41      CELLINIT
42      CELLINIT2
43      CELLINIT3
44      CELLISSETCHK
45      CELLISSETCHK2
46      CELLISSETCHK2_VAL
47      CELLISSETCHK3
48      CELLISSETCHK3_VAL
49      CELLISSETCHK_VAL
50      CELLMATCH2
51      CELLMATCH2_VAL
52      CELLMATCH3
53      CELLMATCH3_VAL
54      CELLTYPECHK
55      CELLTYPECHK2
56      CELLTYPECHK2_VAL
57      CELLTYPECHK3
58      CELLTYPECHK3_VAL
59      CELLTYPECHK_VAL
60      CHKFSTR
61      CHKFSTR_VAL
62      CHKOSTR
63      CHKOSTR_VAL
64      CHKPTR
65      Constants
66      Even
67      F2C_MAP_CELL
68      Index values
69      MOVED
70      MOVEI
71      MaxAbs
72      MaxVal
73      MinAbs
74      MinVal
75      Odd
76      SpiceError
77      TolOrFail
78 
79 -Restrictions
80 
81    This is a private macro file for use within CSPICE.
82    Do not use or alter any entry.  Or else!
83 
84 -Author_and_Institution
85 
86    N.J. Bachman    (JPL)
87    E.D. Wright     (JPL)
88 
89 -Version
90 
91    -CSPICE Version 5.0.0, 07-FEB-2017   (NJB)
92 
93       Updated MaxAbs and MinAbs macros to cast their input arguments
94       to type double.
95 
96    -CSPICE Version 4.3.0, 18-SEP-2013   (NJB)
97 
98       Bug fix: missing comma was added to argument list
99       in body of macro CELLTYPECHK3_VAL.
100 
101    -CSPICE Version 4.2.0, 16-FEB-2005   (NJB)
102 
103       Bug fix:  in the macro C2F_MAP_CELL, error checking has been
104       added after the sequence of calls to ssizec_ and scardc_.
105       If either of these routines signals an error, the dynamically
106       allocated memory for the "Fortran cell" is freed.
107 
108    -CSPICE Version 4.1.0, 06-DEC-2002   (NJB)
109 
110       Bug fix:  added previous missing, bracketing parentheses to
111       references to input cell pointer argument in macro
112       CELLINIT.
113 
114       Changed CELLINIT macro so it no longer initializes to zero
115       length all strings in data array of a character cell.  Instead,
116       strings are terminated with a null in their final element.
117 
118    -CSPICE Version 4.0.0, 22-AUG-2002   (NJB)
119 
120        Added macro definitions to support CSPICE cells and sets:
121 
122           C2F_MAP_CELL
123           C2F_MAP_CELL2
124           C2F_MAP_CELL3
125           CELLINIT
126           CELLINIT2
127           CELLINIT3
128           CELLISSETCHK
129           CELLISSETCHK2
130           CELLISSETCHK2_VAL
131           CELLISSETCHK3
132           CELLISSETCHK3_VAL
133           CELLISSETCHK_VAL
134           CELLMATCH2
135           CELLMATCH2_VAL
136           CELLMATCH3
137           CELLMATCH3_VAL
138           CELLTYPECHK
139           CELLTYPECHK2
140           CELLTYPECHK2_VAL
141           CELLTYPECHK3
142           CELLTYPECHK3_VAL
143           CELLTYPECHK_VAL
144           F2C_MAP_CELL
145 
146    -CSPICE Version 3.0.0, 09-JAN-1998   (NJB)
147 
148        Added output string check macros CHKOSTR and CHKOSTR_VAL.
149        Removed variable name arguments from macros
150 
151           CHKPTR
152           CHKPTR_VAL
153           CHKFSTR
154           CHKRSTR_VAL
155 
156        The strings containing names of the checked variables are now
157        generated from the variables themselves via the # operator.
158 
159    -CSPICE Version 2.0.0, 03-DEC-1997   (NJB)
160 
161        Added pointer check macro CHKPTR and Fortran string check macro
162        CHKFSTR.
163 
164    -CSPICE Version 1.0.0, 25-OCT-1997   (EDW)
165 */
166 
167 
168 
169 #include <math.h>
170 #include <string.h>
171 #include "SpiceZdf.h"
172 
173 
174 #define MOVED( arrfrm, ndim, arrto )                \
175                                                     \
176         ( memmove ( (void*)               (arrto) , \
177                     (void*)               (arrfrm), \
178                     sizeof (SpiceDouble) * (ndim)  ) )
179 
180 
181 
182 
183 
184 #define MOVEI( arrfrm, ndim, arrto )               \
185                                                    \
186         ( memmove ( (void*)            (arrto) ,   \
187                     (void*)            (arrfrm),   \
188                     sizeof (SpiceInt) * (ndim)    ) )
189 
190 
191 
192 
193 
194 /*
195 Define a tolerance test for those pesky double precision reals.
196 True if the difference is less than the tolerance, false otherwise.
197 The tolerance refers to a percentage. x, y and tol should be declared
198 double.  All values are assumed to be non-zero.  Okay?
199 */
200 
201 #define TolOrFail( x, y, tol )            \
202                                           \
203         ( fabs( x-y ) < ( tol * fabs(x) ) )
204 
205 
206 
207 
208 
209 /*
210 Simple error output through standard SPICE error system .  Set the error
211 message and the type
212 */
213 
214 #define SpiceError( errmsg, errtype )   \
215                                         \
216         {                               \
217         setmsg_c ( errmsg  );           \
218         sigerr_c ( errtype );           \
219         }
220 
221 
222 
223 
224 
225 
226 /*
227 Return a value which is the maximum/minimum of the absolute values of
228 two values.
229 */
230 
231 #define MaxAbs(a,b)                                                     \
232                                                                         \
233            ( fabs((double)(a)) >= fabs((double)(b)) ?                   \
234                                   fabs((double)(a)) : fabs((double)(b)) )
235 
236 #define MinAbs(a,b)                                                     \
237                                                                         \
238            ( fabs((double)(a)) <  fabs((double)(b)) ?                   \
239                                   fabs((double)(a)) : fabs((double)(b)) )
240 
241 
242 /*
243 Return a value which is the maximum/minimum value of two values.
244 */
245 
246 #define MaxVal(A,B) ( (A) >= (B) ? (A) : (B) )
247 #define MinVal(A,B) ( (A) <  (B) ? (A) : (B) )
248 
249 
250 
251 
252 
253 /*
254 Determine whether a value is even or odd
255 */
256 #define Even( x ) ( ( (x) & 1 ) == 0 )
257 #define Odd ( x ) ( ( (x) & 1 ) != 0 )
258 
259 
260 
261 
262 
263 /*
264 Array indexes for vectors.
265 */
266 
267 #define  SpiceX         0
268 #define  SpiceY         1
269 #define  SpiceZ         2
270 #define  SpiceVx        3
271 #define  SpiceVy        4
272 #define  SpiceVz        5
273 
274 
275 
276 
277 /*
278 Physical constants and dates.
279 */
280 
281 #define  B1900     2415020.31352
282 #define  J1900     2415020.0
283 #define  JYEAR     31557600.0
284 #define  TYEAR     31556925.9747
285 #define  J1950     2433282.5
286 #define  SPD       86400.0
287 #define  B1950     2433282.42345905
288 #define  J2100     2488070.0
289 #define  CLIGHT    299792.458
290 #define  J2000     2451545.0
291 
292 
293 
294 
295 
296 /*
297 Common literal values.
298 */
299 
300 #define  NULLCHAR  ( (SpiceChar   )   0 )
301 #define  NULLCPTR  ( (SpiceChar * )   0 )
302 #define  BLANK     ( (SpiceChar   ) ' ' )
303 
304 
305 
306 /*
307 Macro CHKPTR is used for checking for a null pointer.  CHKPTR uses
308 the constants
309 
310    CHK_STANDARD
311    CHK_DISCOVER
312    CHK_REMAIN
313 
314 to control tracing behavior.  Values  and meanings are:
315 
316    CHK_STANDARD          Standard tracing.  If an error
317                          is found, signal it, check out
318                          and return.
319 
320    CHK_DISCOVER          Discovery check-in.  If an
321                          error is found, check in, signal
322                          the error, check out, and return.
323 
324    CHK_REMAIN            If an error is found, signal it.
325                          Do not check out or return.  This
326                          would allow the caller to clean up
327                          before returning, if necessary.
328                          In such cases the caller must test
329                          failed_c() after the macro call.
330 
331 CHKPTR should be used in void functions.  In non-void functions,
332 use CHKPTR_VAL, which is defined below.
333 
334 */
335 
336 #define  CHK_STANDARD   1
337 #define  CHK_DISCOVER   2
338 #define  CHK_REMAIN     3
339 
340 #define  CHKPTR( errHandling, modname, pointer )                     \
341                                                                      \
342          if ( (void *)(pointer) == (void *)0 )                       \
343          {                                                           \
344             if ( (errHandling) == CHK_DISCOVER  )                    \
345             {                                                        \
346                chkin_c ( modname );                                  \
347             }                                                        \
348                                                                      \
349             setmsg_c ( "Pointer \"#\" is null; a non-null "          \
350                        "pointer is required."             );         \
351             errch_c  ( "#", (#pointer)                    );         \
352             sigerr_c ( "SPICE(NULLPOINTER)"               );         \
353                                                                      \
354             if (    ( (errHandling) == CHK_DISCOVER  )               \
355                  || ( (errHandling) == CHK_STANDARD  )   )           \
356             {                                                        \
357                chkout_c ( modname );                                 \
358                return;                                               \
359             }                                                        \
360          }
361 
362 
363 #define  CHKPTR_VAL( errHandling, modname, pointer, retval )         \
364                                                                      \
365          if ( (void *)(pointer) == (void *)0 )                       \
366          {                                                           \
367             if ( (errHandling) == CHK_DISCOVER  )                    \
368             {                                                        \
369                chkin_c ( modname );                                  \
370             }                                                        \
371                                                                      \
372             setmsg_c ( "Pointer \"#\" is null; a non-null "          \
373                        "pointer is required."             );         \
374             errch_c  ( "#", (#pointer)                    );         \
375             sigerr_c ( "SPICE(NULLPOINTER)"               );         \
376                                                                      \
377             if (    ( (errHandling) == CHK_DISCOVER  )               \
378                  || ( (errHandling) == CHK_STANDARD  )   )           \
379             {                                                        \
380                chkout_c ( modname );                                 \
381                return   ( retval  );                                 \
382             }                                                        \
383          }
384 
385 
386 /*
387 Macro CHKFSTR checks strings that are to be passed to Fortran or
388 f2c'd Fortran routines.  Such strings must have non-zero length,
389 and their pointers must be non-null.
390 
391 CHKFSTR should be used in void functions.  In non-void functions,
392 use CHKFSTR_VAL, which is defined below.
393 */
394 
395 #define  CHKFSTR( errHandling, modname, string )                     \
396                                                                      \
397          CHKPTR ( errHandling, modname, string );                    \
398                                                                      \
399          if (     (  (void *)string    !=  (void *)0  )              \
400               &&  (   strlen(string)   ==  0          )  )           \
401          {                                                           \
402             if ( (errHandling) == CHK_DISCOVER  )                    \
403             {                                                        \
404                chkin_c ( modname );                                  \
405             }                                                        \
406                                                                      \
407             setmsg_c ( "String \"#\" has length zero." );            \
408             errch_c  ( "#", (#string)                  );            \
409             sigerr_c ( "SPICE(EMPTYSTRING)"            );            \
410                                                                      \
411             if (    ( (errHandling) == CHK_DISCOVER  )               \
412                  || ( (errHandling) == CHK_STANDARD  )   )           \
413             {                                                        \
414                chkout_c ( modname );                                 \
415                return;                                               \
416             }                                                        \
417          }
418 
419 #define  CHKFSTR_VAL( errHandling, modname, string, retval )         \
420                                                                      \
421          CHKPTR_VAL( errHandling, modname, string, retval);          \
422                                                                      \
423          if (     (  (void *)string    !=  (void *)0  )              \
424               &&  (   strlen(string)   ==  0          )  )           \
425          {                                                           \
426             if ( (errHandling) == CHK_DISCOVER  )                    \
427             {                                                        \
428                chkin_c ( modname );                                  \
429             }                                                        \
430                                                                      \
431             setmsg_c ( "String \"#\" has length zero." );            \
432             errch_c  ( "#", (#string)                  );            \
433             sigerr_c ( "SPICE(EMPTYSTRING)"            );            \
434                                                                      \
435             if (    ( (errHandling) == CHK_DISCOVER  )               \
436                  || ( (errHandling) == CHK_STANDARD  )   )           \
437             {                                                        \
438                chkout_c ( modname );                                 \
439                return    ( retval );                                 \
440             }                                                        \
441          }
442 
443 
444 /*
445 Macro CHKOSTR checks output string pointers and the associated
446 string length values supplied as input arguments.  Output string
447 pointers must be non-null, and the string lengths must be at
448 least 2, so Fortran routine can write at least one character to
449 the output string, and so a null terminator can be appended.
450 CHKOSTR should be used in void functions.  In non-void functions,
451 use CHKOSTR_VAL, which is defined below.
452 */
453 
454 #define  CHKOSTR( errHandling, modname, string, length )             \
455                                                                      \
456          CHKPTR ( errHandling, modname, string );                    \
457                                                                      \
458          if (     (  (void *)string    !=  (void *)0  )              \
459               &&  (   length            <  2          )  )           \
460          {                                                           \
461             if ( (errHandling) == CHK_DISCOVER  )                    \
462             {                                                        \
463                chkin_c ( modname );                                  \
464             }                                                        \
465                                                                      \
466             setmsg_c ( "String \"#\" has length #; must be >= 2." ); \
467             errch_c  ( "#", (#string)                  );            \
468             errint_c ( "#", (length)                   );            \
469             sigerr_c ( "SPICE(STRINGTOOSHORT)"         );            \
470                                                                      \
471             if (    ( (errHandling) == CHK_DISCOVER  )               \
472                  || ( (errHandling) == CHK_STANDARD  )   )           \
473             {                                                        \
474                chkout_c ( modname );                                 \
475                return;                                               \
476             }                                                        \
477          }
478 
479 
480 #define  CHKOSTR_VAL( errHandling, modname, string, length, retval ) \
481                                                                      \
482          CHKPTR_VAL( errHandling, modname, string, retval );         \
483                                                                      \
484          if (     (  (void *)string    !=  (void *)0  )              \
485               &&  (   length            <  2          )  )           \
486          {                                                           \
487             if ( (errHandling) == CHK_DISCOVER  )                    \
488             {                                                        \
489                chkin_c ( modname );                                  \
490             }                                                        \
491                                                                      \
492             setmsg_c ( "String \"#\" has length #; must be >= 2." ); \
493             errch_c  ( "#", (#string)                  );            \
494             errint_c ( "#", (length)                   );            \
495             sigerr_c ( "SPICE(STRINGTOOSHORT)"         );            \
496                                                                      \
497             if (    ( (errHandling) == CHK_DISCOVER  )               \
498                  || ( (errHandling) == CHK_STANDARD  )   )           \
499             {                                                        \
500                chkout_c ( modname );                                 \
501                return   ( retval  );                                 \
502             }                                                        \
503          }
504 
505 
506    /*
507    Definitions for Cells and Sets
508    */
509 
510 
511    /*
512    Cell initialization macros
513    */
514    #define CELLINIT( cellPtr )                                       \
515                                                                      \
516       if ( !( (cellPtr)->init )  )                                   \
517       {                                                              \
518          if (  (cellPtr)->dtype  ==  SPICE_CHR  )                    \
519          {                                                           \
520             /*                                                       \
521             Make sure all elements of the data array, including      \
522             the control area, start off null-terminated.  We place   \
523             the null character in the final element of each string,  \
524             so as to avoid wiping out data that may have been        \
525             assigned to the data array prior to initialization.      \
526             */                                                       \
527             SpiceChar  * sPtr;                                       \
528             SpiceInt     i;                                          \
529             SpiceInt     nmax;                                       \
530                                                                      \
531             nmax  = SPICE_CELL_CTRLSZ + (cellPtr)->size;             \
532                                                                      \
533             for ( i = 1;  i <= nmax;  i++ )                          \
534             {                                                        \
535                sPtr  =          (SpiceChar *)((cellPtr)->base)       \
536                          +  i * (cellPtr)->length                    \
537                          -  1;                                       \
538                                                                      \
539                *sPtr = NULLCHAR;                                     \
540             }                                                        \
541          }                                                           \
542          else                                                        \
543          {                                                           \
544             zzsynccl_c ( C2F, (cellPtr) );                           \
545          }                                                           \
546                                                                      \
547          (cellPtr)->init = SPICETRUE;                                \
548       }
549 
550 
551    #define CELLINIT2( cellPtr1, cellPtr2 )                           \
552                                                                      \
553       CELLINIT ( cellPtr1 );                                         \
554       CELLINIT ( cellPtr2 );
555 
556 
557    #define CELLINIT3( cellPtr1, cellPtr2, cellPtr3 )                 \
558                                                                      \
559       CELLINIT ( cellPtr1 );                                         \
560       CELLINIT ( cellPtr2 );                                         \
561       CELLINIT ( cellPtr3 );
562 
563 
564    /*
565    Data type checking macros:
566    */
567    #define CELLTYPECHK( errHandling, modname, dType, cellPtr1 )      \
568                                                                      \
569          if ( (cellPtr1)->dtype != (dType) )                         \
570          {                                                           \
571             SpiceChar  * typstr[3] =                                 \
572             {                                                        \
573               "character", "double precision", "integer"             \
574             };                                                       \
575                                                                      \
576             if ( (errHandling) == CHK_DISCOVER  )                    \
577             {                                                        \
578                chkin_c ( modname );                                  \
579             }                                                        \
580                                                                      \
581             setmsg_c ( "Data type of # is #; expected type "         \
582                        "is #."                                );     \
583             errch_c  ( "#", (#cellPtr1)                       );     \
584             errch_c  ( "#", typstr[ (cellPtr1)->dtype ]       );     \
585             errch_c  ( "#", typstr[  dType            ]       );     \
586             sigerr_c ( "SPICE(TYPEMISMATCH)"                  );     \
587                                                                      \
588             if (    ( (errHandling) == CHK_DISCOVER  )               \
589                  || ( (errHandling) == CHK_STANDARD  )   )           \
590             {                                                        \
591                chkout_c ( modname );                                 \
592                return;                                               \
593             }                                                        \
594          }
595 
596 
597    #define CELLTYPECHK_VAL( errHandling,  modname,                   \
598                             dType,        cellPtr1,  retval )        \
599                                                                      \
600          if ( (cellPtr1)->dtype != (dType) )                         \
601          {                                                           \
602             SpiceChar  * typstr[3] =                                 \
603             {                                                        \
604               "character", "double precision", "integer"             \
605             };                                                       \
606                                                                      \
607             if ( (errHandling) == CHK_DISCOVER  )                    \
608             {                                                        \
609                chkin_c ( modname );                                  \
610             }                                                        \
611                                                                      \
612             setmsg_c ( "Data type of # is #; expected type "         \
613                        "is #."                                );     \
614             errch_c  ( "#", (#cellPtr1)                       );     \
615             errch_c  ( "#", typstr[ (cellPtr1)->dtype ]       );     \
616             errch_c  ( "#", typstr[  dType            ]       );     \
617             sigerr_c ( "SPICE(TYPEMISMATCH)"                  );     \
618                                                                      \
619             if (    ( (errHandling) == CHK_DISCOVER  )               \
620                  || ( (errHandling) == CHK_STANDARD  )   )           \
621             {                                                        \
622                chkout_c ( modname );                                 \
623                return (retval);                                      \
624             }                                                        \
625          }
626 
627 
628    #define CELLTYPECHK2( errHandling,  modname,  dtype,              \
629                          cellPtr1,     cellPtr2         )            \
630                                                                      \
631        CELLTYPECHK( errHandling, modname, dtype, cellPtr1 );         \
632        CELLTYPECHK( errHandling, modname, dtype, cellPtr2 );
633 
634 
635 
636    #define CELLTYPECHK2_VAL( errHandling,  modname,  dtype,          \
637                              cellPtr1,     cellPtr2, retval )        \
638                                                                      \
639        CELLTYPECHK_VAL( errHandling, modname, dtype, cellPtr1,       \
640                         retval                                 );    \
641        CELLTYPECHK_VAL( errHandling, modname, dtype, cellPtr2,       \
642                         retval                                 );
643 
644 
645 
646    #define CELLTYPECHK3( errHandling,  modname,   dtype,             \
647                          cellPtr1,     cellPtr2,  cellPtr3  )        \
648                                                                      \
649        CELLTYPECHK( errHandling, modname, dtype, cellPtr1 );         \
650        CELLTYPECHK( errHandling, modname, dtype, cellPtr2 );         \
651        CELLTYPECHK( errHandling, modname, dtype, cellPtr3 );
652 
653 
654    #define CELLTYPECHK3_VAL( errHandling, modname,  dtype,           \
655                              cellPtr1,    cellPtr2, cellPtr3,        \
656                              retval                            )     \
657                                                                      \
658        CELLTYPECHK_VAL( errHandling, modname, dtype, cellPtr1,       \
659                         retval                                 );    \
660        CELLTYPECHK_VAL( errHandling, modname, dtype, cellPtr2,       \
661                         retval                                 );    \
662        CELLTYPECHK_VAL( errHandling, modname, dtype, cellPtr3,       \
663                         retval                                 );
664 
665 
666 
667    #define CELLMATCH2( errHandling, modname, cellPtr1, cellPtr2 )    \
668                                                                      \
669          if ( (cellPtr1)->dtype != (cellPtr2)->dtype )               \
670          {                                                           \
671             SpiceChar  * typstr[3] =                                 \
672             {                                                        \
673               "character", "double precision", "integer"             \
674             };                                                       \
675                                                                      \
676             if ( (errHandling) == CHK_DISCOVER  )                    \
677             {                                                        \
678                chkin_c ( modname );                                  \
679             }                                                        \
680                                                                      \
681             setmsg_c ( "Data type of # is #; data type of # "        \
682                        "is #, but types must match."          );     \
683             errch_c  ( "#", (#cellPtr1)                       );     \
684             errch_c  ( "#", typstr[ (cellPtr1)->dtype ]       );     \
685             errch_c  ( "#", (#cellPtr2)                       );     \
686             errch_c  ( "#", typstr[ (cellPtr2)->dtype ]       );     \
687             sigerr_c ( "SPICE(TYPEMISMATCH)"                  );     \
688                                                                      \
689             if (    ( (errHandling) == CHK_DISCOVER  )               \
690                  || ( (errHandling) == CHK_STANDARD  )   )           \
691             {                                                        \
692                chkout_c ( modname );                                 \
693                return;                                               \
694             }                                                        \
695          }
696 
697    #define CELLMATCH2_VAL( errHandling, modname,                     \
698                            cellPtr1,    cellPtr2, retval )           \
699                                                                      \
700          if ( (cellPtr1)->dtype != (cellPtr2)->dtype )               \
701          {                                                           \
702             SpiceChar  * typstr[3] =                                 \
703             {                                                        \
704               "character", "double precision", "integer"             \
705             };                                                       \
706                                                                      \
707             if ( (errHandling) == CHK_DISCOVER  )                    \
708             {                                                        \
709                chkin_c ( modname );                                  \
710             }                                                        \
711                                                                      \
712             setmsg_c ( "Data type of # is #; data type of # "        \
713                        "is #, but types must match."          );     \
714             errch_c  ( "#", (#cellPtr1)                       );     \
715             errch_c  ( "#", typstr [ (cellPtr1)->dtype ]      );     \
716             errch_c  ( "#", (#cellPtr2)                       );     \
717             errch_c  ( "#", typstr [ (cellPtr2)->dtype ]      );     \
718             sigerr_c ( "SPICE(TYPEMISMATCH)"                  );     \
719                                                                      \
720             if (    ( (errHandling) == CHK_DISCOVER  )               \
721                  || ( (errHandling) == CHK_STANDARD  )   )           \
722             {                                                        \
723                chkout_c ( modname );                                 \
724                return   ( retval  );                                 \
725             }                                                        \
726          }
727 
728 
729    #define CELLMATCH3( errHandling, modname,                         \
730                        cellPtr1,    cellPtr2,  cellPtr3 )            \
731                                                                      \
732        CELLMATCH2 ( errHandling, modname, cellPtr1, cellPtr2 );      \
733        CELLMATCH2 ( errHandling, modname, cellPtr2, cellPtr3 );
734 
735 
736 
737 
738    #define CELLMATCH3_VAL( errHandling, modname,  cellPtr1,          \
739                            cellPtr2,    cellPtr3, retval    )        \
740                                                                      \
741        CELLMATCH2_VAL ( errHandling, modname,                        \
742                         cellPtr1,    cellPtr2, retval );             \
743                                                                      \
744        CELLMATCH2_VAL ( errHandling, modname,                        \
745                         cellPtr2,    cellPtr3, retval );
746 
747    /*
748    Set checking macros:
749    */
750    #define CELLISSETCHK( errHandling, modname, cellPtr1 )            \
751                                                                      \
752          if ( !(cellPtr1)->isSet )                                   \
753          {                                                           \
754             if ( (errHandling) == CHK_DISCOVER  )                    \
755             {                                                        \
756                chkin_c ( modname );                                  \
757             }                                                        \
758                                                                      \
759             setmsg_c ( "Cell # must be sorted and have unique "      \
760                        "values in order to be a CSPICE set. "        \
761                        "The isSet flag in this cell is SPICEFALSE, " \
762                        "indicating the cell may have been modified " \
763                        "by a routine that doesn't preserve these "   \
764                        "properties."                          );     \
765             errch_c  ( "#", (#cellPtr1)                       );     \
766             sigerr_c ( "SPICE(NOTASET)"                       );     \
767                                                                      \
768             if (    ( (errHandling) == CHK_DISCOVER  )               \
769                  || ( (errHandling) == CHK_STANDARD  )   )           \
770             {                                                        \
771                chkout_c ( modname );                                 \
772                return;                                               \
773             }                                                        \
774          }
775 
776 
777    #define CELLISSETCHK_VAL( errHandling,  modname,                  \
778                              cellPtr1,     retval  )                 \
779                                                                      \
780          if ( !(cellPtr1)->isSet )                                   \
781          {                                                           \
782             if ( (errHandling) == CHK_DISCOVER  )                    \
783             {                                                        \
784                chkin_c ( modname );                                  \
785             }                                                        \
786                                                                      \
787             setmsg_c ( "Cell # must be sorted and have unique "      \
788                        "values in order to be a CSPICE set. "        \
789                        "The isSet flag in this cell is SPICEFALSE, " \
790                        "indicating the cell may have been modified " \
791                        "by a routine that doesn't preserve these "   \
792                        "properties."                          );     \
793             errch_c  ( "#", (#cellPtr1)                       );     \
794             sigerr_c ( "SPICE(NOTASET)"                       );     \
795                                                                      \
796             if (    ( (errHandling) == CHK_DISCOVER  )               \
797                  || ( (errHandling) == CHK_STANDARD  )   )           \
798             {                                                        \
799                chkout_c ( modname );                                 \
800                return (retval);                                      \
801             }                                                        \
802          }
803 
804 
805    #define CELLISSETCHK2( errHandling,  modname,                     \
806                           cellPtr1,     cellPtr2 )                   \
807                                                                      \
808        CELLISSETCHK( errHandling, modname, cellPtr1 );               \
809        CELLISSETCHK( errHandling, modname, cellPtr2 );
810 
811 
812 
813    #define CELLISSETCHK2_VAL( errHandling,  modname,                 \
814                               cellPtr1,     cellPtr2, retval )       \
815                                                                      \
816        CELLISSETCHK_VAL( errHandling, modname, cellPtr1, retval );   \
817        CELLISSETCHK_VAL( errHandling, modname, cellPtr2, retval );   \
818 
819 
820 
821    #define CELLISSETCHK3( errHandling,  modname,                     \
822                           cellPtr1,     cellPtr2,  cellPtr3  )       \
823                                                                      \
824        CELLISSETCHK ( errHandling, modname, cellPtr1 );              \
825        CELLISSETCHK ( errHandling, modname, cellPtr2 );              \
826        CELLISSETCHK ( errHandling, modname, cellPtr3 );
827 
828 
829    #define CELLISSETCHK3_VAL( errHandling, modname,  cellPtr1,       \
830                               cellPtr2,    cellPtr3, retval    )     \
831                                                                      \
832        CELLISSETCHK_VAL ( errHandling, modname, cellPtr1, retval );  \
833        CELLISSETCHK_VAL ( errHandling, modname, cellPtr2, retval );  \
834        CELLISSETCHK_VAL ( errHandling, modname, cellPtr3, retval );
835 
836 
837    /*
838    C-to-Fortran and Fortran-to-C character cell translation macros:
839    */
840 
841    /*
842    Macros that map one or more character C cells to dynamically
843    allocated Fortran-style character cells:
844    */
845    #define C2F_MAP_CELL( caller, CCell, fCell, fLen )                \
846                                                                      \
847       {                                                              \
848          /*                                                          \
849          fCell and fLen are to be passed by reference, as if this    \
850          macro were a function.                                      \
851                                                                      \
852                                                                      \
853          Caution: dynamically allocates array fCell, which is to be  \
854          freed by caller!                                            \
855          */                                                          \
856          SpiceInt                ndim;                               \
857          SpiceInt                lenvals;                            \
858                                                                      \
859                                                                      \
860          ndim     =  (CCell)->size  +  SPICE_CELL_CTRLSZ;            \
861          lenvals  =  (CCell)->length;                                \
862                                                                      \
863          C2F_MapFixStrArr ( (caller),      ndim,    lenvals,         \
864                             (CCell)->base, (fLen),  (fCell)  );      \
865                                                                      \
866          if ( !failed_c() )                                          \
867          {                                                           \
868             /*                                                       \
869             Explicitly set the control area info in the Fortran cell.\
870             */                                                       \
871             ssizec_ ( ( integer * ) &((CCell)->size),                \
872                       ( char    * ) *(fCell),                        \
873                       ( ftnlen    ) *(fLen)           );             \
874                                                                      \
875             scardc_ ( ( integer * ) &((CCell)->card),                \
876                       ( char    * ) *(fCell),                        \
877                       ( ftnlen    ) *(fLen)           );             \
878                                                                      \
879             if ( failed_c() )                                        \
880             {                                                        \
881                /*                                                    \
882                Setting size or cardinality of the Fortran cell       \
883                can fail, for example if the cell's string length     \
884                is too short.                                         \
885                */                                                    \
886                free ( *(fCell) );                                    \
887             }                                                        \
888          }                                                           \
889       }
890 
891 
892    #define C2F_MAP_CELL2( caller, CCell1, fCell1, fLen1,             \
893                                   CCell2, fCell2, fLen2 )            \
894                                                                      \
895       {                                                              \
896          C2F_MAP_CELL( caller, CCell1, fCell1, fLen1 );              \
897                                                                      \
898          if ( !failed_c() )                                          \
899          {                                                           \
900             C2F_MAP_CELL( caller, CCell2, fCell2, fLen2 );           \
901                                                                      \
902             if ( failed_c() )                                        \
903             {                                                        \
904                free ( *(fCell1) );                                   \
905             }                                                        \
906          }                                                           \
907       }
908 
909 
910    #define C2F_MAP_CELL3( caller, CCell1, fCell1, fLen1,             \
911                                   CCell2, fCell2, fLen2,             \
912                                   CCell3, fCell3, fLen3 )            \
913                                                                      \
914       {                                                              \
915          C2F_MAP_CELL2( caller, CCell1, fCell1, fLen1,               \
916                                 CCell2, fCell2, fLen2  );            \
917                                                                      \
918          if ( !failed_c() )                                          \
919          {                                                           \
920             C2F_MAP_CELL( caller, CCell3, fCell3, fLen3 );           \
921                                                                      \
922             if ( failed_c() )                                        \
923             {                                                        \
924                free ( *(fCell1) );                                   \
925                free ( *(fCell2) );                                   \
926             }                                                        \
927          }                                                           \
928       }
929 
930 
931 
932    /*
933    Macro that maps a Fortran-style character cell to a C cell
934    (Note: this macro frees the Fortran cell):
935    */
936 
937    #define F2C_MAP_CELL( fCell, fLen, CCell )                        \
938                                                                      \
939       {                                                              \
940          SpiceInt                card;                               \
941          SpiceInt                lenvals;                            \
942          SpiceInt                ndim;                               \
943          SpiceInt                nBytes;                             \
944          SpiceInt                size;                               \
945          void                  * array;                              \
946                                                                      \
947          ndim     =  (CCell)->size  +  SPICE_CELL_CTRLSZ;            \
948          lenvals  =  (CCell)->length;                                \
949          array    =  (CCell)->base;                                  \
950                                                                      \
951          /*                                                          \
952          Capture the size and cardinality of the Fortran cell.       \
953          */                                                          \
954          if ( !failed_c() )                                          \
955          {                                                           \
956             size = sizec_ (  ( char      * ) (fCell),                \
957                              ( ftnlen      ) fLen     );             \
958                                                                      \
959             card = cardc_ (  ( char      * ) (fCell),                \
960                              ( ftnlen      ) fLen     );             \
961          }                                                           \
962                                                                      \
963                                                                      \
964          /*                                                          \
965          Copy the Fortran array into the output array.               \
966          */                                                          \
967                                                                      \
968          nBytes = ndim * fLen * sizeof(SpiceChar);                   \
969          memmove ( array, fCell, nBytes );                           \
970          /*                                                          \
971          Convert the output array from Fortran to C style.           \
972          */                                                          \
973          F2C_ConvertTrStrArr ( ndim, lenvals, (SpiceChar *)array );  \
974                                                                      \
975          /*                                                          \
976          Sync the size and cardinality of the C cell.                \
977          */                                                          \
978          if ( !failed_c() )                                          \
979          {                                                           \
980             (CCell)->size = size;                                    \
981             (CCell)->card = card;                                    \
982          }                                                           \
983       }
984 
985 
986 
987 /*
988    End of header SpiceZmc.h
989 */
990