]> git.mxchange.org Git - flightgear.git/blob - Main/fg_debug.c
Initial revision.
[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 <Main/fg_debug.h>
26 #include <varargs.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <strings.h> /* probably not portable */
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 static FILE *fg_DebugOutput = stderr;
36
37 /* TODO: Actually make this thing thread safe */
38 #ifdef USETHREADS
39 #define FG_GRABDEBUGSEM  while( --fg_DebugSem < 0 ) { fg_DebugSem++; } 
40 #define FG_RELEASEDEBUGSEM fg_DebugSem++;
41 #else
42 #define FG_GRABDEBUGSEM
43 #define FG_RELEASEDEBUGSEM 
44 #endif
45
46 /* Used for convienence initialization from env variables.
47  */
48 static struct {
49   char *str;
50   fgDebugClass class;
51 } fg_DebugClasses[] = {
52   { "FG_NONE",    0x00000000 },
53   { "FG_TERRAIN", 0x00000001 },
54   { "FG_ASTRO",   0x00000002 },
55   { "FG_FLIGHT",  0x00000004 },
56   { "FG_INPUT",   0x00000008 },
57   { "FG_GL",      0x00000010 },
58   { "FG_VIEW",    0x00000020 },
59   { "FG_COCKPIT", 0x00000040 },
60   { "FG_GENERAL", 0x00000080 },
61   { "FG_MATH",    0x00000100 },
62   { "FG_EVENT",   0x00000200 },
63
64   /* Do not edit below here, last entry should be null */
65   { "FG_ALL",     0xFFFFFFFF },
66   { NULL, 0 } };
67
68 static fgDebugClass fgDebugStrToClass( char *str );
69
70
71 /* fgInitDebug =============================================================*/
72 void fgInitDebug( void )
73 {
74   char *pszClass, *pszPrio;
75
76   FG_GRABDEBUGSEM;
77   fg_DebugSem=fg_DebugSem;  /* shut up GCC */
78
79   pszPrio = getenv( "FG_DEBUGPRIORITY" );
80   if( pszPrio ) {
81     fg_DebugPriority = atoi( pszPrio );
82     fprintf( stderr, "fg_debug.c: Environment overrides default debug priority (%d)\n",
83              fg_DebugPriority );
84   }
85
86   pszClass = getenv( "FG_DEBUGCLASS" );
87   if( pszClass ) {
88     fg_DebugClass = fgDebugStrToClass( pszClass );
89     fprintf( stderr, "fg_debug.c: Environment overrides default debug class (0x%08X)\n",
90              fg_DebugClass );
91   }
92
93   FG_RELEASEDEBUGSEM;
94 }
95
96 /* fgDebugStrToClass ======================================================*/
97 fgDebugClass fgDebugStrToClass( char *str )
98 {
99   char *hex = "0123456789ABCDEF";
100   char *hexl = "0123456789abcdef";
101   char *pt, *p, *ph, ps=1;
102   unsigned int val = 0, i;
103   
104   if( str == NULL ) {
105     return 0;
106   }
107
108   /* Check for 0xXXXXXX notation */
109   if( (p = strstr( str, "0x")) ) {
110     p++; p++;
111     while (*p) {
112       if( (ph = strchr(hex,*p)) || (ph = strchr(hexl,*p)) ){
113         val <<= 4;
114         val += ph-hex;
115         p++;
116       }
117       else {
118         /* fprintf( stderr, "Error in hex string '%s'\n", str ); 
119          */
120         return FG_NONE;
121       }
122     }
123   }
124   else {
125     /* Must be in string format */
126     p = str;
127     ps = 1;
128     while( ps ) {
129       while( *p && (*p==' ' || *p=='\t') ) p++; /* remove whitespace */
130       pt = p; /* mark token */
131       while( *p && (*p!='|') ) p++; /* find OR or EOS */
132       ps = *p; /* save value at p so we can attempt to be bounds safe */
133       *p++ = 0; /* terminate token */
134       /* determine value for token */
135       i=0; 
136       while( fg_DebugClasses[i].str && 
137              strncmp( fg_DebugClasses[i].str, pt, strlen(fg_DebugClasses[i].str)) ) i++;
138       if( fg_DebugClasses[i].str == NULL ) {
139         fprintf( stderr, "fg_debug.c: Could not find message class '%s'\n", pt ); 
140       } else {
141         val |= fg_DebugClasses[i].class;
142       }
143     }
144   }
145   return (fgDebugClass)val;
146 }
147
148
149 /* fgSetDebugOutput =======================================================*/
150 void fgSetDebugOutput( FILE *out )
151 {
152   FG_GRABDEBUGSEM;
153   fflush( fg_DebugOutput );
154   fg_DebugOutput = out;
155   FG_RELEASEDEBUGSEM;
156 }
157
158
159 /* fgSetDebugLevels =======================================================*/
160 void fgSetDebugLevels( fgDebugClass class, fgDebugPriority prio )
161 {
162   FG_GRABDEBUGSEM;
163   fg_DebugClass = class;
164   fg_DebugPriority = prio;
165   FG_RELEASEDEBUGSEM;
166 }
167
168
169 /* fgRegisterDebugCallback ================================================*/
170 fgDebugCallback fgRegisterDebugCallback( fgDebugCallback callback )
171 {
172   fgDebugCallback old;
173   FG_GRABDEBUGSEM;
174   old = fg_DebugCallback;
175   fg_DebugCallback = callback;
176   FG_RELEASEDEBUGSEM;
177   return old;
178 }
179
180
181 /* fgPrintf ===============================================================*/
182 int fgPrintf( fgDebugClass class, fgDebugPriority prio, char *fmt, ... )
183 {
184   char szOut[1024+1];
185   int ret = 0;
186
187   FG_GRABDEBUGSEM;
188
189   if( !(class & fg_DebugClass) || (prio < fg_DebugPriority) ) {
190     FG_RELEASEDEBUGSEM;
191     return 0;
192   } 
193   ret = vsprintf( szOut, fmt, (&fmt+1));
194
195   if( fg_DebugCallback!=NULL && fg_DebugCallback(class, prio, szOut) ) {
196     FG_RELEASEDEBUGSEM;
197     return ret;
198   } 
199   else {
200     fprintf( fg_DebugOutput, szOut );
201     FG_RELEASEDEBUGSEM;
202     if( prio == FG_EXIT ) {
203       exit(0);
204     } 
205     else if( prio == FG_ABORT ) {
206       abort();
207     }
208   }
209   return ret;  
210
211