1 /*
2 
3 -Procedure zzerror ( Cat and return the long, short, and traceback
4                      error strings)
5 
6 -Abstract
7 
8    The default CSPICE behavior signals an exit on a CSPICE error.
9    This action often conflicts with the error model used by other
10    programming languages: IDL, Perl, MATLAB, etc. zzerrorinit
11    and zzerror implement logic to permit easy use of another
12    error model.
13 
14    zzerror retrieves the long error message, the short error,
15    message and the call trace back, assembling those components
16    into a single string for return to the caller. This call also
17    resets the failed_c() state.
18 
19 -Disclaimer
20 
21    THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE
22    CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S.
23    GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE
24    ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE
25    PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS"
26    TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY
27    WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A
28    PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC
29    SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
30    SOFTWARE AND RELATED MATERIALS, HOWEVER USED.
31 
32    IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA
33    BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT
34    LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND,
35    INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS,
36    REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE
37    REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY.
38 
39    RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF
40    THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY
41    CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE
42    ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE.
43 
44 -Required_Reading
45 
46    None.
47 
48 -Keywords
49 
50    error
51 
52 */
53 
54 #include <string.h>
55 #include <stdio.h>
56 
57 #include "SpiceUsr.h"
58 #include "SpiceZfc.h"
59 #include "SpiceZst.h"
60 #include "zzerror.h"
61 
62 #define     MSG_LEN             2024
63 #define     TRC_LEN             32
64 #define     MAXMOD              100
65 #define     OUT_LEN             2*MSG_LEN
66 
zzerror(long cnt)67 const char * zzerror( long cnt )
68 
69 /*
70 
71 -Brief_I/O
72 
73    Variable  I/O  Description
74    --------  ---  --------------------------------------------------
75    cnt        I   Either a flag (less than 0) indicating a scalar or an
76                   array index.
77 
78    The function returns a string version of the SPICE error output.
79 
80 -Detailed_Input
81 
82    cnt        A long integer defining the index of a vector at which
83               the error signaled or a negative value indicating the
84               error occurred during a scalar operation.
85 
86 -Detailed_Output
87 
88    The function returns a pointer to a string (char *), the string
89    containing the SPICE short and long error messages, plus
90    the full trace back. If the error signaled during a vectorized
91    operation, the error string includes the vector index at failure.
92 
93 -Parameters
94 
95    MSG_LEN    one half the max length of the return string. The return
96               string has dimension 2*MSG_LEN.
97 
98    TRC_LEN    the max length of a string returned from trcnam_.
99 
100    MAXMOD     is the maximum storage depth for names in the
101               traceback stack. Value copied from trcpkg.f.
102 
103 -Exceptions
104 
105    1) If trcdep_ returns a 'depth' value larger than the maximum depth
106       as assigned to MAXMOD, the routine returns a SPICE(BUG) error
107       and error message to the caller.
108 
109 -Files
110 
111    None.
112 
113 -Particulars
114 
115    All interface functions immediately check failed_c() after
116    calling CSPICE. When failed_c() returns SPICETRUE,
117    the interface performs the appropriate action to return the
118    error state to the interpreter.
119 
120    Call after detecting a failed_c() event.
121 
122    The user should call zzerrorinit prior to a zzerror call.
123    zzerrorinit places the error subsystem in the RETURN/NULL
124    state.
125 
126    This routine makes a call to reset_c to reset the error
127    system to an non-error state. The call causes the following:
128 
129       failed_c returns `false' value until another error signal.
130 
131       return_c returns `false' value until another error signal.
132 
133       getsms_ and getlms_ return blank strings.
134 
135       The traceback routines return a traceback of the current
136       active call chain, not the active call chain at the time
137       of the last error.
138 
139 -Examples
140 
141    Expected use, check failed, return the error string:
142 
143       /.
144       Initialize the error system to RETURN/NULL
145       ./
146       zzerrorinit();
147 
148          ... CSPICE calls ...
149 
150       /.
151       Check for a failure, return the error string if
152       failed_c returns true.
153       ./
154       if( failed_c() )
155          {
156          error_str = zzerror( index );
157 
158          /.
159          Return the error string traceback to
160          the calling program.
161          ./
162          error_return( error_str );
163          }
164 
165    Example of a string returned by zzerror:
166 
167       In scalar context-
168 
169       SPICE(NOLEAPSECONDS): [str2et_c->STR2ET->TTRANS] The variable
170       that points to the leapseconds (DELTET/DELTA_AT) could not be
171       located in the kernel pool.  It is likely that the leapseconds
172       kernel has not been loaded via the routine FURNSH.
173 
174       In a vector context-
175 
176       cspice_str2et, 'Jan 1, 2049', et
177       et_vec = dindgen(5)*10000d + et
178 
179       cspice_spkezr, 'MOON', et_vec, 'J2000', 'NONE', 'EARTH', starg, ltime
180 
181       Creates the string
182 
183       SPICE(SPKINSUFFDATA): [spkezr_c->SPKEZR->SPKEZ->SPKGEO]
184       Insufficient ephemeris data has been loaded to compute the
185       state of 301 (MOON) relative to 399 (EARTH) at the
186       ephemeris epoch 2050 JAN 01 01:07:44.183. Failure at input
187       vector index 3154.
188 
189 -Restrictions
190 
191    Use with the SPICE error system in RETURN mode and the error
192    device set to NULL.
193 
194 -Literature_References
195 
196    None.
197 
198 -Author_and_Institution
199 
200    E. D. Wright    (JPL)
201 
202 -Version
203 
204    CSPICE 1.1.1 08-MAR-2007 (EDW)
205 
206       Corrected spelling mistake in error message string.
207 
208    CSPICE 1.1.0 24-APR-2006 (EDW)
209 
210       Version 1.0.0 contained an extraneous chkin_c call which caused a
211       cascade of 'zzerror_c' strings prefixed to error strings. This call
212       bug was removed.
213 
214       Replaced LDPOOL reference in header docs with FURNSH.
215 
216    CSPICE 1.0.0 17-OCT-2005 (EDW)
217 
218       Initial release to CSPICE
219 
220 -Index_Entries
221 
222    error message
223 
224 -&
225 
226 */
227    {
228 
229    /*
230    Local variables. Tag the 'msg_short' as static so the memory
231    remains after return.
232 
233    We append to 'msg_short' hence the reason for it having the
234    largest size.
235 
236    */
237    static char msg_short [OUT_LEN];
238    char        msg_long  [MSG_LEN];
239    char        trname    [TRC_LEN];
240 
241 
242    /*
243    Define an error message string for the case if the trcdep_
244    call returns a value larger than MAXMOD.
245    */
246    char      * depth_err = "SPICE(BUG): [zzerror]. An error "
247                            "occurred during the processing of a SPICE "
248                            "error signal. The trcdep_ routine "
249                            "returned a depth, %i, larger than the "
250                            "maximum allowed depth, %i. Please "
251                            "contact NAIF.";
252 
253    SpiceInt    i;
254 
255    SpiceInt    depth;
256    SpiceChar   trlist[MAXMOD*TRC_LEN];
257 
258 
259    /*
260    Zero out the char arrays, just-in-case.
261    */
262    memset( msg_short, 0, 2 *MSG_LEN        );
263    memset( msg_long,  0,    MSG_LEN        );
264    memset( trlist,    0,    MAXMOD*TRC_LEN );
265 
266    /*
267    Retrieve the depth of the call traceback stack.
268    */
269    (void) trcdep_( &depth );
270 
271    /*
272    Check 'depth' as less-than or equal-to MAXMOD. Signal a
273    SPICE error if not confirmed.
274    */
275    if ( depth > MAXMOD )
276       {
277       reset_c();
278 
279       sprintf(msg_short, depth_err, depth, MAXMOD );
280       return(msg_short);
281       }
282 
283 
284    /*
285    Loop over the number of items in the trace list.
286    Index starts at 1 as trcnam_ is an f2c'd routine.
287    */
288    for ( i=1; i<= depth; i++)
289       {
290 
291       /*
292       Retrieve the name (as a FORTRAN string) of the ith routine's name
293       from the trace stack. No SPICE call name has a string length longer
294       than TRC_LEN characters.
295       */
296       (void) trcnam_( (integer *) &i, trname, (ftnlen) TRC_LEN );
297 
298       /*
299       The f2c code returns a FORTRAN type string, so null terminate
300       the string for C.
301       */
302       F2C_ConvertStr( TRC_LEN, trname);
303 
304       /*
305       Create the trace list string by concatenation. Add '->' as a
306       marker between the routine names except on the first pass through
307       the loop.
308       */
309       if ( i != 1 )
310          {
311          strcat( trlist, "->" );
312          }
313       strcat( trlist, trname );
314 
315       }
316 
317    /*
318    Retrieve the short message from the error subsystem. The string has
319    form "SPICE(MSGNAME)".
320    */
321    (void) getsms_(msg_short, (SpiceInt) sizeof msg_short);
322 
323    /*
324    Null terminate the FORTRAN 'msg_short' string for use in C routines.
325    */
326    F2C_ConvertStr( 2*MSG_LEN, msg_short);
327 
328    /*
329    Obtain the long message string, a brief description of the error.
330    */
331    (void) getlms_(msg_long, (ftnlen) sizeof(msg_long));
332 
333    /*
334    Null terminate the FORTRAN 'msg_long' string for use in C routines.
335    */
336    F2C_ConvertStr( MSG_LEN, msg_long);
337 
338    /*
339    Remember to reset the error system, so subsequent calls work.
340    */
341    reset_c();
342 
343    /*
344    Combine the short, long and trace strings into a single string, then
345    return the string.
346    */
347    sprintf( msg_short + strlen(msg_short),
348             ": [%s] %s", trlist, msg_long );
349 
350    /*
351    Add the index value for errors from vectorized functions. Scalar
352    functions set 'cnt' to anything less than zero (normally -1 or -2).
353    */
354    if ( cnt >= 0 )
355       {
356       sprintf( msg_short + strlen(msg_short),
357                " Failure occurred at input vector index %ld.", cnt);
358       }
359 
360    return(msg_short);
361    }
362 
363