]> git.mxchange.org Git - flightgear.git/blob - Main/fg_debug.c
Miscellaneous weekend tweaks. Fixed? a cache problem that caused whole
[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  * $Id$
23  * (Log is kept at end of this file)
24  **************************************************************************/
25
26 #include <string.h>
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30
31 #include <Include/cmdargs.h> // Line to command line arguments
32 #include <Main/fg_debug.h>
33
34 static int             fg_DebugSem      = 1;
35 fgDebugClass           fg_DebugClass    = FG_ALL;  // Need visibility for
36 fgDebugPriority        fg_DebugPriority = FG_INFO; // command line processing.
37 static fgDebugCallback fg_DebugCallback = NULL;
38
39 FILE *fg_DebugOutput = NULL;  // Visibility needed for command line processor.
40                               // This can be set to a FILE from the command
41                               // line. If not, it will be set to stderr.
42
43 /* TODO: Actually make this thing thread safe */
44 #ifdef USETHREADS
45 #define FG_GRABDEBUGSEM  while( --fg_DebugSem < 0 ) { fg_DebugSem++; }
46 #define FG_RELEASEDEBUGSEM fg_DebugSem++;
47 #else
48 #define FG_GRABDEBUGSEM
49 #define FG_RELEASEDEBUGSEM
50 #endif
51
52 /* Used for convienence initialization from env variables.
53  */
54 static struct {
55   char *str;
56   fgDebugClass dbg_class;
57 } fg_DebugClasses[] = {
58   { "FG_NONE",    0x00000000 },
59   { "FG_TERRAIN", 0x00000001 },
60   { "FG_ASTRO",   0x00000002 },
61   { "FG_FLIGHT",  0x00000004 },
62   { "FG_INPUT",   0x00000008 },
63   { "FG_GL",      0x00000010 },
64   { "FG_VIEW",    0x00000020 },
65   { "FG_COCKPIT", 0x00000040 },
66   { "FG_GENERAL", 0x00000080 },
67   { "FG_MATH",    0x00000100 },
68   { "FG_EVENT",   0x00000200 },
69   { "FG_AIRCRAFT",0x00000400 },
70
71   /* Do not edit below here, last entry should be null */
72   { "FG_ALL",     0xFFFFFFFF },
73   { NULL, 0 } };
74
75 static fgDebugClass fgDebugStrToClass( char *str );
76
77
78 /* fgInitDebug =============================================================*/
79 void fgInitDebug( void )
80 {
81   char *pszClass, *pszPrio, *pszFile;
82
83   // Support for log file/alt debug output via command line, environment or
84   // reasonable default.
85
86   if( strlen( logArgbuf ) > 3) {   // First check for command line option
87     fg_DebugOutput = fopen(logArgbuf, "a+" );  // Assumed that we will append.
88     }
89
90   if( !fg_DebugOutput ) {          // If not set on command line, environment?
91     pszFile = getenv( "FG_DEBUGFILE" );
92     if( pszFile ) {          // There is such an environmental variable.
93       fg_DebugOutput = fopen( pszFile, "a+" );
94       }
95     }
96
97   if( !fg_DebugOutput ) {         // If neither command line nor environment
98     fg_DebugOutput = stderr;      // then we use the fallback position
99     }                       
100
101   FG_GRABDEBUGSEM;
102   fg_DebugSem = fg_DebugSem;  /* shut up GCC */
103
104   // Test command line option overridge of debug priority. If the value
105   // is in range (properly optioned) the we will override both defaults
106   // and the environmental value.
107
108   if ((priorityArgValue >= FG_BULK) && (priorityArgValue <= FG_ABORT)) {
109     fg_DebugPriority = priorityArgValue;
110     }
111   else {  // Either not set or out of range. We will not warn the user.
112     pszPrio = getenv( "FG_DEBUGPRIORITY" );
113     if( pszPrio ) {
114       fg_DebugPriority = atoi( pszPrio );
115       fprintf( stderr,
116            "fg_debug.c: Environment overrides default debug priority (%d)\n",
117            fg_DebugPriority );
118       }
119     }
120
121
122   if ((debugArgValue >= FG_ALL) && (debugArgValue < FG_UNDEFD)) {
123     fg_DebugPriority = priorityArgValue;
124     }
125   else {  // Either not set or out of range. We will not warn the user.
126     pszClass = getenv( "FG_DEBUGCLASS" );
127     if( pszClass ) {
128       fg_DebugClass = fgDebugStrToClass( pszClass );
129       fprintf( stderr,
130             "fg_debug.c: Environment overrides default debug class (0x%08X)\n",
131                   fg_DebugClass );
132       }
133     }
134
135   FG_RELEASEDEBUGSEM;
136 }
137
138 /* fgDebugStrToClass ======================================================*/
139 fgDebugClass fgDebugStrToClass( char *str )
140 {
141   char *hex = "0123456789ABCDEF";
142   char *hexl = "0123456789abcdef";
143   char *pt, *p, *ph, ps = 1;
144   unsigned int val = 0, i;
145   
146   if( str == NULL ) {
147     return 0;
148   }
149
150   /* Check for 0xXXXXXX notation */
151   if( (p = strstr( str, "0x")) ) {
152     p++; p++;
153     while (*p) {
154       if( (ph = strchr(hex,*p)) || (ph = strchr(hexl,*p)) ){
155         val <<= 4;
156         val += ph-hex;
157         p++;
158       }
159       else {
160         /* fprintf( stderr, "Error in hex string '%s'\n", str ); 
161          */
162         return FG_NONE;
163       }
164     }
165   }
166   else {
167     /* Must be in string format */
168     p = str;
169     ps = 1;
170     while( ps ) {
171       while( *p && (*p==' ' || *p=='\t') ) p++; /* remove whitespace */
172       pt = p; /* mark token */
173       while( *p && (*p!='|') ) p++; /* find OR or EOS */
174       ps = *p; /* save value at p so we can attempt to be bounds safe */
175       *p++ = 0; /* terminate token */
176       /* determine value for token */
177       i=0; 
178       while( fg_DebugClasses[i].str && 
179              strncmp( fg_DebugClasses[i].str, pt, strlen(fg_DebugClasses[i].str)) ) i++;
180       if( fg_DebugClasses[i].str == NULL ) {
181         fprintf( stderr, "fg_debug.c: Could not find message class '%s'\n", pt ); 
182       } else {
183         val |= fg_DebugClasses[i].dbg_class;
184       }
185     }
186   }
187   return (fgDebugClass)val;
188 }
189
190
191 /* fgSetDebugOutput =======================================================*/
192 void fgSetDebugOutput( FILE *out )
193 {
194   FG_GRABDEBUGSEM;
195   fflush( fg_DebugOutput );
196   fg_DebugOutput = out;
197   FG_RELEASEDEBUGSEM;
198 }
199
200
201 /* fgSetDebugLevels =======================================================*/
202 void fgSetDebugLevels( fgDebugClass dbg_class, fgDebugPriority prio )
203 {
204   FG_GRABDEBUGSEM;
205   fg_DebugClass = dbg_class;
206   fg_DebugPriority = prio;
207   FG_RELEASEDEBUGSEM;
208 }
209
210
211 /* fgRegisterDebugCallback ================================================*/
212 fgDebugCallback fgRegisterDebugCallback( fgDebugCallback callback )
213 {
214   fgDebugCallback old;
215   FG_GRABDEBUGSEM;
216   old = fg_DebugCallback;
217   fg_DebugCallback = callback;
218   FG_RELEASEDEBUGSEM;
219   return old;
220 }
221
222
223 /* fgPrintf ===============================================================*/
224 int fgPrintf( fgDebugClass dbg_class, fgDebugPriority prio, char *fmt, ... )
225 {
226   char szOut[1024+1];
227   va_list ap;
228   int ret = 0;
229
230   // If no action to take, then don't bother with the semaphore activity
231   // Slight speed benefit.
232
233   if( !(dbg_class & fg_DebugClass) || (prio < fg_DebugPriority) ) {
234     return ret;        // Its zero anyway. But we might think about changing
235                        // it upon some error condition?
236   }
237
238   FG_GRABDEBUGSEM;
239
240   /* ret = vsprintf( szOut, fmt, (&fmt+1)); (but it didn't work, thus ... */
241   va_start (ap, fmt);
242   ret = vsprintf( szOut, fmt, ap);
243   va_end (ap);
244
245   if( fg_DebugCallback!=NULL && fg_DebugCallback(dbg_class, prio, szOut) ) {
246     FG_RELEASEDEBUGSEM;
247     return ret;
248   }
249   else {
250     fprintf( fg_DebugOutput, szOut );
251     FG_RELEASEDEBUGSEM;
252     if( prio == FG_EXIT ) {
253       exit(0);
254     }
255     else if( prio == FG_ABORT ) {
256       abort();
257     }
258   }
259   return ret;  
260
261
262
263 /* $Log$
264 /* Revision 1.7  1998/02/16 13:39:43  curt
265 /* Miscellaneous weekend tweaks.  Fixed? a cache problem that caused whole
266 /* tiles to occasionally be missing.
267 /*
268  */