1 /**************************************************************************
2 * fg_debug.c -- Flight Gear debug utility functions
4 * Written by Paul Bleisch, started January 1998.
6 * Copyright (C) 1998 Paul Bleisch, pbleisch@acm.org
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * (Log is kept at end of this file)
23 **************************************************************************/
30 #include <Include/cmdargs.h> // Line to command line arguments
31 #include <Main/fg_debug.h>
33 static int fg_DebugSem = 1;
34 fgDebugClass fg_DebugClass = FG_ALL; // Need visibility for
35 fgDebugPriority fg_DebugPriority = FG_INFO; // command line processing.
36 static fgDebugCallback fg_DebugCallback = NULL;
38 FILE *fg_DebugOutput = NULL; // Visibility needed for command line processor.
39 // This can be set to a FILE from the command
40 // line. If not, it will be set to stderr.
42 /* TODO: Actually make this thing thread safe */
44 #define FG_GRABDEBUGSEM while( --fg_DebugSem < 0 ) { fg_DebugSem++; }
45 #define FG_RELEASEDEBUGSEM fg_DebugSem++;
47 #define FG_GRABDEBUGSEM
48 #define FG_RELEASEDEBUGSEM
51 /* Used for convienence initialization from env variables.
55 fgDebugClass dbg_class;
56 } fg_DebugClasses[] = {
57 { "FG_NONE", 0x00000000 },
58 { "FG_TERRAIN", 0x00000001 },
59 { "FG_ASTRO", 0x00000002 },
60 { "FG_FLIGHT", 0x00000004 },
61 { "FG_INPUT", 0x00000008 },
62 { "FG_GL", 0x00000010 },
63 { "FG_VIEW", 0x00000020 },
64 { "FG_COCKPIT", 0x00000040 },
65 { "FG_GENERAL", 0x00000080 },
66 { "FG_MATH", 0x00000100 },
67 { "FG_EVENT", 0x00000200 },
68 { "FG_AIRCRAFT",0x00000400 },
70 /* Do not edit below here, last entry should be null */
71 { "FG_ALL", 0xFFFFFFFF },
74 static fgDebugClass fgDebugStrToClass( char *str );
77 /* fgInitDebug =============================================================*/
78 void fgInitDebug( void )
80 char *pszClass, *pszPrio, *pszFile;
82 // Support for log file/alt debug output via command line, environment or
83 // reasonable default.
85 if( strlen( logArgbuf ) > 3) { // First check for command line option
86 fg_DebugOutput = fopen(logArgbuf, "a+" ); // Assumed that we will append.
89 if( !fg_DebugOutput ) { // If not set on command line, environment?
90 pszFile = getenv( "FG_DEBUGFILE" );
91 if( pszFile ) { // There is such an environmental variable.
92 fg_DebugOutput = fopen( pszFile, "a+" );
96 if( !fg_DebugOutput ) { // If neither command line nor environment
97 fg_DebugOutput = stderr; // then we use the fallback position
101 fg_DebugSem = fg_DebugSem; /* shut up GCC */
103 // Test command line option overridge of debug priority. If the value
104 // is in range (properly optioned) the we will override both defaults
105 // and the environmental value.
107 if ((priorityArgValue >= FG_BULK) && (priorityArgValue <= FG_ABORT)) {
108 fg_DebugPriority = priorityArgValue;
110 else { // Either not set or out of range. We will not warn the user.
111 pszPrio = getenv( "FG_DEBUGPRIORITY" );
113 fg_DebugPriority = atoi( pszPrio );
115 "fg_debug.c: Environment overrides default debug priority (%d)\n",
121 if ((debugArgValue >= FG_ALL) && (debugArgValue < FG_UNDEFD)) {
122 fg_DebugPriority = priorityArgValue;
124 else { // Either not set or out of range. We will not warn the user.
125 pszClass = getenv( "FG_DEBUGCLASS" );
127 fg_DebugClass = fgDebugStrToClass( pszClass );
129 "fg_debug.c: Environment overrides default debug class (0x%08X)\n",
137 /* fgDebugStrToClass ======================================================*/
138 fgDebugClass fgDebugStrToClass( char *str )
140 char *hex = "0123456789ABCDEF";
141 char *hexl = "0123456789abcdef";
142 char *pt, *p, *ph, ps = 1;
143 unsigned int val = 0, i;
149 /* Check for 0xXXXXXX notation */
150 if( (p = strstr( str, "0x")) ) {
153 if( (ph = strchr(hex,*p)) || (ph = strchr(hexl,*p)) ){
159 /* fprintf( stderr, "Error in hex string '%s'\n", str );
166 /* Must be in string format */
170 while( *p && (*p==' ' || *p=='\t') ) p++; /* remove whitespace */
171 pt = p; /* mark token */
172 while( *p && (*p!='|') ) p++; /* find OR or EOS */
173 ps = *p; /* save value at p so we can attempt to be bounds safe */
174 *p++ = 0; /* terminate token */
175 /* determine value for token */
177 while( fg_DebugClasses[i].str &&
178 strncmp( fg_DebugClasses[i].str, pt, strlen(fg_DebugClasses[i].str)) ) i++;
179 if( fg_DebugClasses[i].str == NULL ) {
180 fprintf( stderr, "fg_debug.c: Could not find message class '%s'\n", pt );
182 val |= fg_DebugClasses[i].dbg_class;
186 return (fgDebugClass)val;
190 /* fgSetDebugOutput =======================================================*/
191 void fgSetDebugOutput( FILE *out )
194 fflush( fg_DebugOutput );
195 fg_DebugOutput = out;
200 /* fgSetDebugLevels =======================================================*/
201 void fgSetDebugLevels( fgDebugClass dbg_class, fgDebugPriority prio )
204 fg_DebugClass = dbg_class;
205 fg_DebugPriority = prio;
210 /* fgRegisterDebugCallback ================================================*/
211 fgDebugCallback fgRegisterDebugCallback( fgDebugCallback callback )
215 old = fg_DebugCallback;
216 fg_DebugCallback = callback;
222 /* fgPrintf ===============================================================*/
223 int fgPrintf( fgDebugClass dbg_class, fgDebugPriority prio, char *fmt, ... )
229 // If no action to take, then don't bother with the semaphore activity
230 // Slight speed benefit.
232 if( !(dbg_class & fg_DebugClass) || (prio < fg_DebugPriority) ) {
233 return ret; // Its zero anyway. But we might think about changing
234 // it upon some error condition?
239 /* ret = vsprintf( szOut, fmt, (&fmt+1)); (but it didn't work, thus ... */
241 ret = vsprintf( szOut, fmt, ap);
244 if( fg_DebugCallback!=NULL && fg_DebugCallback(dbg_class, prio, szOut) ) {
249 fprintf( fg_DebugOutput, szOut );
251 if( prio == FG_EXIT ) {
254 else if( prio == FG_ABORT ) {