3 * fg_debug.c -- Flight Gear debug utility functions
5 * Written by Paul Bleisch, started January 1998.
7 * Copyright (C) 1998 Paul Bleisch, pbleisch@acm.org
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * (Log is kept at end of this file)
25 **************************************************************************/
33 #include <Include/cmdargs.h> // Line to command line arguments
38 static int fg_DebugSem = 1;
39 fgDebugClass fg_DebugClass = FG_NONE; // Need visibility for
40 fgDebugPriority fg_DebugPriority = FG_INFO; // command line processing.
41 static fgDebugCallback fg_DebugCallback = NULL;
43 FILE *fg_DebugOutput = NULL; // Visibility needed for command line processor.
44 // This can be set to a FILE from the command
45 // line. If not, it will be set to stderr.
47 /* TODO: Actually make this thing thread safe */
49 #define FG_GRABDEBUGSEM while( --fg_DebugSem < 0 ) { fg_DebugSem++; }
50 #define FG_RELEASEDEBUGSEM fg_DebugSem++;
52 #define FG_GRABDEBUGSEM
53 #define FG_RELEASEDEBUGSEM
56 /* Used for convienence initialization from env variables.
60 fgDebugClass dbg_class;
61 } fg_DebugClasses[] = {
62 { "FG_NONE", 0x00000000 },
63 { "FG_TERRAIN", 0x00000001 },
64 { "FG_ASTRO", 0x00000002 },
65 { "FG_FLIGHT", 0x00000004 },
66 { "FG_INPUT", 0x00000008 },
67 { "FG_GL", 0x00000010 },
68 { "FG_VIEW", 0x00000020 },
69 { "FG_COCKPIT", 0x00000040 },
70 { "FG_GENERAL", 0x00000080 },
71 { "FG_MATH", 0x00000100 },
72 { "FG_EVENT", 0x00000200 },
73 { "FG_AIRCRAFT", 0x00000400 },
74 { "FG_AUTOPILOT", 0x00000800 },
76 /* Do not edit below here, last entry should be null */
77 { "FG_ALL", 0xFFFFFFFF },
81 static fgDebugClass fgDebugStrToClass( char *str );
84 /* fgInitDebug =============================================================*/
85 void fgInitDebug( void ) {
86 char *pszClass, *pszPrio, *pszFile;
88 // Support for log file/alt debug output via command line, environment or
89 // reasonable default.
92 if( strlen( logArgbuf ) > 3) { // First check for command line option
93 // Assumed that we will append.
94 fg_DebugOutput = fopen(logArgbuf, "a+" );
98 if( !fg_DebugOutput ) { // If not set on command line, environment?
99 pszFile = getenv( "FG_DEBUGFILE" );
100 if( pszFile ) { // There is such an environmental variable.
101 fg_DebugOutput = fopen( pszFile, "a+" );
105 if( !fg_DebugOutput ) { // If neither command line nor environment
106 fg_DebugOutput = stderr; // then we use the fallback position
110 fg_DebugSem = fg_DebugSem; /* shut up GCC */
112 // Test command line option overridge of debug priority. If the value
113 // is in range (properly optioned) the we will override both defaults
114 // and the environmental value.
117 if ((priorityArgValue >= FG_BULK) && (priorityArgValue <= FG_ABORT)) {
118 fg_DebugPriority = priorityArgValue;
119 } else { // Either not set or out of range. We will not warn the user.
121 pszPrio = getenv( "FG_DEBUGPRIORITY" );
123 fg_DebugPriority = atoi( pszPrio );
125 "fg_debug.c: Environment overrides default debug priority (%d)\n",
132 if ((debugArgValue >= FG_ALL) && (debugArgValue < FG_UNDEFD)) {
133 fg_DebugPriority = priorityArgValue;
134 } else { // Either not set or out of range. We will not warn the user.
136 pszClass = getenv( "FG_DEBUGCLASS" );
138 fg_DebugClass = fgDebugStrToClass( pszClass );
140 "fg_debug.c: Environment overrides default debug class (0x%08X)\n",
148 /* fgDebugStrToClass ======================================================*/
149 fgDebugClass fgDebugStrToClass( char *str ) {
150 char *hex = "0123456789ABCDEF";
151 char *hexl = "0123456789abcdef";
152 char *pt, *p, *ph, ps = 1;
153 unsigned int val = 0, i;
159 /* Check for 0xXXXXXX notation */
160 p = strstr( str, "0x");
170 ph = strchr(hexl,*p);
176 // fprintf( stderr, "Error in hex string '%s'\n", str );
182 /* Must be in string format */
186 while( *p && (*p==' ' || *p=='\t') ) p++; /* remove whitespace */
187 pt = p; /* mark token */
188 while( *p && (*p!='|') ) p++; /* find OR or EOS */
189 ps = *p; /* save value at p so we can attempt to be bounds safe */
190 *p++ = 0; /* terminate token */
191 /* determine value for token */
193 while( fg_DebugClasses[i].str &&
194 strncmp( fg_DebugClasses[i].str, pt,
195 strlen(fg_DebugClasses[i].str)) ) i++;
196 if( fg_DebugClasses[i].str == NULL ) {
198 "fg_debug.c: Could not find message class '%s'\n",
201 val |= fg_DebugClasses[i].dbg_class;
205 return (fgDebugClass)val;
209 /* fgSetDebugOutput =======================================================*/
210 void fgSetDebugOutput( FILE *out ) {
212 fflush( fg_DebugOutput );
213 fg_DebugOutput = out;
218 /* fgSetDebugLevels =======================================================*/
219 void fgSetDebugLevels( fgDebugClass dbg_class, fgDebugPriority prio ) {
221 fg_DebugClass = dbg_class;
222 fg_DebugPriority = prio;
227 /* fgRegisterDebugCallback ================================================*/
228 fgDebugCallback fgRegisterDebugCallback( fgDebugCallback callback ) {
231 old = fg_DebugCallback;
232 fg_DebugCallback = callback;
238 /* fgPrintf ===============================================================*/
239 int fgPrintf( fgDebugClass dbg_class, fgDebugPriority prio, char *fmt, ... ) {
244 // If no action to take, then don't bother with the semaphore
245 // activity Slight speed benefit.
247 // printf("dbg_class = %d fg_DebugClass = %d\n", dbg_class, fg_DebugClass);
248 // printf("prio = %d fg_DebugPriority = %d\n", prio, fg_DebugPriority);
250 if( !(dbg_class & fg_DebugClass) ) {
251 // Failed to match a specific debug class
252 if ( prio < fg_DebugPriority ) {
253 // priority is less than requested
255 // "ret" is zero anyway. But we might think about changing
256 // it upon some error condition?
263 /* ret = vsprintf( szOut, fmt, (&fmt+1)); (but it didn't work, thus ... */
265 ret = vsprintf( szOut, fmt, ap);
268 if( fg_DebugCallback!=NULL && fg_DebugCallback(dbg_class, prio, szOut) ) {
272 fprintf( fg_DebugOutput, szOut );
274 if( prio == FG_EXIT ) {
276 } else if( prio == FG_ABORT ) {
285 /* Revision 1.4 1998/06/01 17:49:44 curt
286 /* Rewrote a slightly ambiguous code fragment (contributed by Charlie Hotchkiss)
288 * Revision 1.3 1998/05/07 23:03:54 curt
289 * Added an entry for AUTOPILOT.
291 * Revision 1.2 1998/04/21 17:03:45 curt
292 * Prepairing for C++ integration.
294 * Revision 1.1 1998/04/18 03:52:04 curt
295 * Moved to Lib directory and created a libDebug.
297 * Revision 1.10 1998/03/14 00:31:21 curt
298 * Beginning initial terrain texturing experiments.
300 * Revision 1.9 1998/03/09 22:44:58 curt
301 * Modified so that you can specify FG_DEBUGCLASS ***or*** FG_DEBUG_PRIORITY
303 * Revision 1.8 1998/03/09 22:11:00 curt
304 * Processed through the format-o-matic.
306 * Revision 1.7 1998/02/16 13:39:43 curt
307 * Miscellaneous weekend tweaks. Fixed? a cache problem that caused whole
308 * tiles to occasionally be missing.