ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/dmessage.h
Revision: 2.2
Committed: Sun Jun 1 03:25:17 2025 UTC (6 days, 14 hours ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.1: +1 -0 lines
Log Message:
chore: Added missing RCSid line

File Contents

# User Rev Content
1 greg 2.2 /* RCSid $Id$ */
2 greg 2.1 /*
3     * dmessage.h
4     * panlib
5     *
6     * Depends on <stdio.h>
7     *
8     * Debug and error message logging and recovery.
9     *
10     * Created by gward on Thu May 10 2001.
11     * Modified by plonghurst on Thursday Feb 15 2007.
12     * Copyright (c) 2001 Anyhere Software. All rights reserved.
13     *
14     */
15    
16     #ifndef _DMESSAGE_H_
17     #define _DMESSAGE_H_
18    
19     #ifdef __cplusplus
20     extern "C" {
21     #endif
22    
23     /********************
24     * Type Definitions *
25     ********************/
26    
27     /***********************************************************************
28     * Debug message classes
29     *
30     * If you are unsure what class to report, guess on the high side, which
31     * is less serious. For example, report an error like DMCdata even
32     * when you think it's DMCsystem, unless you really know.
33     * That way, more serious errors will be recorded from higher in the call
34     * tree. The vast majority of errors fall into the DMCdata class.
35     */
36     typedef enum {
37     DMCassert, /* assertion failure */
38     DMCmemory, /* out of memory */
39     DMCsystem, /* system error */
40     DMCparameter, /* program parameter error */
41     DMCresource, /* file/resource unavailable */
42     DMCdata, /* data error */
43     DMCinput, /* input error */
44     DMCwarning, /* warning message */
45     DMCinfo, /* informative output */
46     DMCtrace, /* trace point */
47     DMCnerr /* no error (terminator) */
48     } DMsgClass;
49    
50     /***********************************************************************
51     * Message flags: record, write to logfile, send to stderr,
52     * alert user, exit program, abort
53     */
54     typedef enum {
55     DMFrecord=01, DMFlog=02, DMFstderr=04,
56     DMFalert=010, DMFexit=020, DMFabort=040
57     } DMsgFlag;
58    
59     /************************
60     * Functions and Macros *
61     ************************/
62    
63     /***********************************************************************
64     * int
65     * dmessage(int cls, const char *msg, const char *file, int line);
66     *
67     * Basic call interface to debug message handler. The file name
68     * and line number are generally taken from the ANSI-C __FILE__
69     * and __LINE__ predefined macros. The message class are taken
70     * from the list above, and the message should not contain newlines.
71     * All DMsgClass classes except DMCassert are recoverable and
72     * dmessage() will return. The return value is an or'ing of
73     * DMsgFlags according to what was done.
74     */
75     #ifdef __cplusplus
76     extern int dmessage(DMsgClass cls, const char *msg,
77     const char *file = NULL, int line = 0);
78     #else
79     extern int dmessage(DMsgClass cls, const char *msg,
80     const char *file, int line);
81     #endif
82    
83     /***********************************************************************
84     * int
85     * DMESG(int cls, const char *msg)
86     *
87     * Basic macro call for message reporting. What actually happens to
88     * the message depends on the current settings, controlled by
89     * global variables described in the next section.
90     */
91     #define DMESG(cls, msg) dmessage(cls, msg, __FILE__, __LINE__)
92    
93     /***********************************************************************
94     * int
95     * DTEST(int cnd, int cls, const char *msg)
96     *
97     * Conditional call to DMESG() for convenience. Zero is returned if
98     * the condition (cnd) evaluates to zero, and a collection of DMsgFlags
99     * saying what was done if the condition evaluates to non-zero.
100     */
101     #define DTEST(cnd, cls, msg) ((cnd) ? DMESG(cls, msg) : 0)
102    
103     /***********************************************************************
104     * int
105     * DMESGF(int cls, const char *fmt, va_list..)
106     *
107     * Formatting version of DMESG() takes printf(3) format string
108     * and a variable argument list to format the message.
109     */
110     #define DMESGF(cls, fmt, val) (sprintf(dmessage_buf, fmt, val), \
111     DMESG(cls, dmessage_buf))
112    
113     /***********************************************************************
114     * int
115     * DTESTF(int cnd, DMsgClass cls, const char *fmt, va_list..)
116     *
117     * Formatting version of DTEST() takes printf(3) format string
118     * and a variable argument list to format the message, but only
119     * if the condition (cnd) evaluates to non-zero.
120     */
121     #define DTESTF(cnd, cls, fmt, val) \
122     ((cnd) ? DMESGF(cls, fmt, val) : 0)
123    
124     /***********************************************************************
125     * int
126     * DRESET()
127     *
128     * Reset last error message class. Call before potential error-
129     * producing subroutine, then call DMESC() or DMESCF() afterwards.
130     */
131     #define DRESET() (dmessage_last_class = DMCnerr)
132    
133     /***********************************************************************
134     * int
135     * DMESC(int cls, const char *msg)
136     *
137     * Report only if this error is a higher priority than any since
138     * DRESET() was last called.
139     */
140     #define DMESC(cls, msg) DTEST((cls) < dmessage_last_class, \
141     cls, msg)
142    
143     /***********************************************************************
144     * int
145     * DMESCF(int cls, const char *fmt, va_list..)
146     *
147     * Formatting version of DMESC() takes printf(3) format string, but
148     * only reports if this error is higher priority than any since
149     * DRESET() was last called.
150     */
151     #define DMESCF(cls, fmt, val) DTESTF((cls) < dmessage_last_class, \
152     cls, fmt, val)
153    
154     /***********************************************************************
155     * void
156     * DASSERT(int cnd)
157     *
158     * Replacement for assert() macro; calls DTEST() with DMCassert class
159     * if asc yeilds 0. If NDEBUG is defined, the macro becomes a no-op.
160     */
161     #ifdef NDEBUG
162     #define DASSERT(asc) ((void)0)
163     #else
164     #if defined(__STDC__) || defined(__cplusplus)
165     #define DASSERT(asc) ((void)DTESTF(!(asc), DMCassert, \
166     "assertion failed ! (%s)", #asc))
167     #else
168     #define DASSERT(asc) ((void)DTESTF(!(asc), DMCassert, \
169     "assertion failed ! (%s)", "asc"))
170     #endif
171     #endif
172    
173     /*********************
174     * Global Variabless *
175     *********************/
176    
177     /***********************************************************************
178     * char dmessage_buf[DM_BUF_LEN]
179     *
180     * Buffer to hold formatted message contents temporarily.
181     */
182     #define DM_BUF_LEN 1024
183    
184     extern char dmessage_buf[DM_BUF_LEN];
185    
186     /***********************************************************************
187     * const char * dmessage_class_name[]
188     *
189     * The name of each of class in DMsgClass.
190     */
191     extern const char * dmessage_class_name[];
192    
193     /***********************************************************************
194     * int dmessage_class_flags[]
195     *
196     * Flags indicating what to do with each message class. By default,
197     * the most recent message will be stored in the dmessage_last[] array
198     * (DMFrecord), but if other flags are set, the message will be sent
199     * other places as well. These flags are available to be altered by the
200     * controlling application, and will not be changed from their initial
201     * defaults (DMFrecord at minimum) by any of the dmessage routines.
202     * Beware: if the DMrecord flag is turned off for a given class and
203     * dmessage() fails to do anything, it will return zero and
204     * the DTEST() and DTESTF() macro calls may return zero even
205     * though their condition evaluated to non-zero. This problem is
206     * avoided by keeping DMrecord set for all classes.
207     */
208     extern int dmessage_class_flags[];
209    
210     /***********************************************************************
211     * int dmessage_class_done[]
212     *
213     * Flags indicating what was last done with each message class.
214     * In other words, the last result of dmessage() for each class.
215     */
216     extern int dmessage_class_done[];
217    
218     /***********************************************************************
219     * const char * dmessage_file[]
220     *
221     * Most recent file reported for each error class.
222     */
223     extern const char * dmessage_file[];
224    
225     /***********************************************************************
226     * int dmessage_line[]
227     *
228     * Most recent line number reported for each error class.
229     */
230     extern int dmessage_line[];
231    
232     /***********************************************************************
233     * const char * dmessage_record[]
234     *
235     * Most recent message for each class with the DMFrecord flag set,
236     * exactly as passed to dmessage(). If no message of
237     * a given class has been reported, then the corresponding
238     * dmessage_record pointer will be NULL.
239     */
240     extern const char * dmessage_record[];
241    
242     /***********************************************************************
243     * int dmessage_last_class
244     *
245     * The lowest class message reported so far, set to DMCnerr initially.
246     * The DMESG_LAST macro provides convenient access to most recent error.
247     */
248     extern DMsgClass dmessage_last_class;
249    
250     #define DMESG_LAST (dmessage_record[dmessage_last_class])
251    
252     /***********************************************************************
253     * FILE * dmessage_logfp
254     *
255     * Pointer to open log file. Each message is preceeded by the file
256     * name, line number, and class for log file and stderr output. Data
257     * is flushed after each message. If this pointer is NULL (the default),
258     * then logging is disabled even for classes with the DMFlog flag set.
259     */
260     extern FILE * dmessage_logfp;
261    
262     /***********************************************************************
263     * int (*dmessage_call)(DMsgClass cls, const char *msg,
264     * const char *file, int line)
265     *
266     * Pointer to function called by dmessage() to share error handling.
267     * If assigned, this function is called with the same arguments passed
268     * to dmessage(), independent of the class flag settings. The returned
269     * value is then used as a mask on the class flags to turn off some or
270     * all of the default actions. The flagged actions are considered
271     * "done" and set accordingly in the dmessage_class_done global.
272     * Defaults to NULL.
273     */
274     extern int (*dmessage_call)(DMsgClass cls, const char *msg,
275     const char *file, int line);
276    
277     /***********************************************************************
278     * int (*dmessage_alert)(const char *msg)
279     *
280     * Pointer to function called by dmessage() to alert user.
281     * The function should return non-zero if the user was notified,
282     * or zero if the message could not be displayed for some reason.
283     * Defaults to NULL, which results in no DMFalert action.
284     */
285     extern int (*dmessage_alert)(const char *msg);
286    
287     /***********************************************************************
288     * void (*dmessage_exit)(int status)
289     *
290     * Pointer to function called by dmessage() for classes with the
291     * DMFexit flag set, which is usually reserved for the DMCmemory class.
292     * Defaults to system exit() function, but may be reassigned by the
293     * controlling application. Assigning a value of NULL causes dmessage()
294     * to return from these calls, which might result in a memory fault if
295     * your program does not check for NULL pointer values. In general,
296     * library authors should NOT assume the DMCmemory class calls exit().
297     */
298     extern void (*dmessage_exit)(int status);
299    
300     /***********************************************************************
301     * void (*dmessage_abort)()
302     *
303     * Pointer to function called by dmessage() for classes with the
304     * DMFabort flag set, which is usually reserved for the DMCassert class.
305     * Defaults to system abort() function, but may be reassigned by the
306     * controlling application. Assigning a value of NULL causes dmessage()
307     * to return from these calls, which will probably prove disasterous.
308     * A better idea if the program wants to continue is to use setjmp() and
309     * longjmp() to recover control at a lower point in the call tree. If
310     * assigned, this call should never return.
311     */
312     extern void (*dmessage_abort)();
313    
314     #ifdef __cplusplus
315     }
316     #endif
317    
318     #endif /* ! _DMESSAGE_H_ */