]> git.mxchange.org Git - flightgear.git/blob - Main/fg_debug.c
73022fae09b1c0de3922fedfba8b920afed84ad3
[flightgear.git] / Main / fg_debug.c
1 /**************************************************************************
2  * fg_debug.c -- Flight Gear debug utility functions
3  *
4  * Written by Paul Bleisch, started January 1998. 
5  *
6  * Copyright (C) 1998 Paul Bleisch, pbleisch@acm.org
7  *
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.
12  *
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.
17  *
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.
21  *
22  * (Log is kept at end of this file)
23  **************************************************************************/
24
25 #include <string.h>
26 #include <Main/fg_debug.h>
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30
31 static int fg_DebugSem = 1;
32 static fgDebugClass fg_DebugClass = FG_ALL;
33 static fgDebugPriority fg_DebugPriority = FG_INFO;
34 static fgDebugCallback fg_DebugCallback = NULL;
35
36 #ifndef __CYGWIN32__
37     static FILE *fg_DebugOutput = stderr;
38 #else /* __CYGWIN32__ */
39     static FILE *fg_DebugOutput = NULL;
40 #endif /* __CYGWIN32 */
41
42 /* TODO: Actually make this thing thread safe */
43 #ifdef USETHREADS
44 #define FG_GRABDEBUGSEM  while( --fg_DebugSem < 0 ) { fg_DebugSem++; } 
45 #define FG_RELEASEDEBUGSEM fg_DebugSem++;
46 #else
47 #define FG_GRABDEBUGSEM
48 #define FG_RELEASEDEBUGSEM 
49 #endif
50
51 /* Used for convienence initialization from env variables.
52  */
53 static struct {
54   char *str;
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
69   /* Do not edit below here, last entry should be null */
70   { "FG_ALL",     0xFFFFFFFF },
71   { NULL, 0 } };
72
73 static fgDebugClass fgDebugStrToClass( char *str );
74
75
76 /* fgInitDebug =============================================================*/
77 void fgInitDebug( void )
78 {
79   char *pszClass, *pszPrio;
80
81 #ifdef __CYGWIN32__
82     fg_DebugOutput = stderr;
83 #endif /* __CYGWIN32 */
84
85   FG_GRABDEBUGSEM;
86   fg_DebugSem=fg_DebugSem;  /* shut up GCC */
87
88   pszPrio = getenv( "FG_DEBUGPRIORITY" );
89   if( pszPrio ) {
90     fg_DebugPriority = atoi( pszPrio );
91     fprintf( stderr, "fg_debug.c: Environment overrides default debug priority (%d)\n",
92              fg_DebugPriority );
93   }
94
95   pszClass = getenv( "FG_DEBUGCLASS" );
96   if( pszClass ) {
97     fg_DebugClass = fgDebugStrToClass( pszClass );
98     fprintf( stderr, "fg_debug.c: Environment overrides default debug class (0x%08X)\n",
99              fg_DebugClass );
100   }
101
102   FG_RELEASEDEBUGSEM;
103 }
104
105 /* fgDebugStrToClass ======================================================*/
106 fgDebugClass fgDebugStrToClass( char *str )
107 {
108   char *hex = "0123456789ABCDEF";
109   char *hexl = "0123456789abcdef";
110   char *pt, *p, *ph, ps=1;
111   unsigned int val = 0, i;
112   
113   if( str == NULL ) {
114     return 0;
115   }
116
117   /* Check for 0xXXXXXX notation */
118   if( (p = strstr( str, "0x")) ) {
119     p++; p++;
120     while (*p) {
121       if( (ph = strchr(hex,*p)) || (ph = strchr(hexl,*p)) ){
122         val <<= 4;
123         val += ph-hex;
124         p++;
125       }
126       else {
127         /* fprintf( stderr, "Error in hex string '%s'\n", str ); 
128          */
129         return FG_NONE;
130       }
131     }
132   }
133   else {
134     /* Must be in string format */
135     p = str;
136     ps = 1;
137     while( ps ) {
138       while( *p && (*p==' ' || *p=='\t') ) p++; /* remove whitespace */
139       pt = p; /* mark token */
140       while( *p && (*p!='|') ) p++; /* find OR or EOS */
141       ps = *p; /* save value at p so we can attempt to be bounds safe */
142       *p++ = 0; /* terminate token */
143       /* determine value for token */
144       i=0; 
145       while( fg_DebugClasses[i].str && 
146              strncmp( fg_DebugClasses[i].str, pt, strlen(fg_DebugClasses[i].str)) ) i++;
147       if( fg_DebugClasses[i].str == NULL ) {
148         fprintf( stderr, "fg_debug.c: Could not find message class '%s'\n", pt ); 
149       } else {
150         val |= fg_DebugClasses[i].dbg_class;
151       }
152     }
153   }
154   return (fgDebugClass)val;
155 }
156
157
158 /* fgSetDebugOutput =======================================================*/
159 void fgSetDebugOutput( FILE *out )
160 {
161   FG_GRABDEBUGSEM;
162   fflush( fg_DebugOutput );
163   fg_DebugOutput = out;
164   FG_RELEASEDEBUGSEM;
165 }
166
167
168 /* fgSetDebugLevels =======================================================*/
169 void fgSetDebugLevels( fgDebugClass dbg_class, fgDebugPriority prio )
170 {
171   FG_GRABDEBUGSEM;
172   fg_DebugClass = dbg_class;
173   fg_DebugPriority = prio;
174   FG_RELEASEDEBUGSEM;
175 }
176
177
178 /* fgRegisterDebugCallback ================================================*/
179 fgDebugCallback fgRegisterDebugCallback( fgDebugCallback callback )
180 {
181   fgDebugCallback old;
182   FG_GRABDEBUGSEM;
183   old = fg_DebugCallback;
184   fg_DebugCallback = callback;
185   FG_RELEASEDEBUGSEM;
186   return old;
187 }
188
189
190 /* fgPrintf ===============================================================*/
191 int fgPrintf( fgDebugClass dbg_class, fgDebugPriority prio, char *fmt, ... )
192 {
193   char szOut[1024+1];
194   va_list ap;
195   int ret = 0;
196
197   FG_GRABDEBUGSEM;
198
199   if( !(dbg_class & fg_DebugClass) || (prio < fg_DebugPriority) ) {
200     FG_RELEASEDEBUGSEM;
201     return 0;
202   } 
203
204   /* ret = vsprintf( szOut, fmt, (&fmt+1)); (but it didn't work, thus ... */
205   va_start (ap, fmt);
206   ret = vsprintf( szOut, fmt, ap);
207   va_end (ap);
208
209   if( fg_DebugCallback!=NULL && fg_DebugCallback(dbg_class, prio, szOut) ) {
210     FG_RELEASEDEBUGSEM;
211     return ret;
212   } 
213   else {
214     fprintf( fg_DebugOutput, szOut );
215     FG_RELEASEDEBUGSEM;
216     if( prio == FG_EXIT ) {
217       exit(0);
218     } 
219     else if( prio == FG_ABORT ) {
220       abort();
221     }
222   }
223   return ret;  
224
225