]> git.mxchange.org Git - flightgear.git/blob - Lib/Debug/fg_debug.c
Merge FG_Lib as subdirectory
[flightgear.git] / Lib / Debug / fg_debug.c
1 /* -*- Mode: C++ -*-
2  *
3  * fg_debug.c -- Flight Gear debug utility functions
4  *
5  * Written by Paul Bleisch, started January 1998. 
6  *
7  * Copyright (C) 1998 Paul Bleisch, pbleisch@acm.org
8  *
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.
13  *
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.
18  *
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.
22  *
23  * $Id$
24  * (Log is kept at end of this file)
25  **************************************************************************/
26
27
28 #include <string.h>
29 #include <stdio.h>
30 #include <stdarg.h>
31 #include <stdlib.h>
32
33 #include <Include/cmdargs.h> // Line to command line arguments
34
35 #include "fg_debug.h"
36
37
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;
42
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.
46
47 /* TODO: Actually make this thing thread safe */
48 #ifdef USETHREADS
49 #define FG_GRABDEBUGSEM  while( --fg_DebugSem < 0 ) { fg_DebugSem++; }
50 #define FG_RELEASEDEBUGSEM fg_DebugSem++;
51 #else
52 #define FG_GRABDEBUGSEM
53 #define FG_RELEASEDEBUGSEM
54 #endif
55
56 /* Used for convienence initialization from env variables.
57  */
58 static struct {
59     char *str;
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 },
75
76     /* Do not edit below here, last entry should be null */
77     { "FG_ALL",       0xFFFFFFFF },
78     { NULL, 0 } 
79 };
80
81 static fgDebugClass fgDebugStrToClass( char *str );
82
83
84 /* fgInitDebug =============================================================*/
85 void fgInitDebug( void ) {
86     char *pszClass, *pszPrio, *pszFile;
87
88     // Support for log file/alt debug output via command line, environment or
89     // reasonable default.
90
91     /*
92     if( strlen( logArgbuf ) > 3) {   // First check for command line option
93         // Assumed that we will append.
94         fg_DebugOutput = fopen(logArgbuf, "a+" );
95     }
96     */
97
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+" );
102         }
103     }
104
105     if( !fg_DebugOutput ) {         // If neither command line nor environment
106         fg_DebugOutput = stderr;      // then we use the fallback position
107     }
108     
109     FG_GRABDEBUGSEM;
110     fg_DebugSem = fg_DebugSem;  /* shut up GCC */
111
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.
115
116     /*
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.
120     */
121         pszPrio = getenv( "FG_DEBUGPRIORITY" );
122         if( pszPrio ) {
123             fg_DebugPriority = atoi( pszPrio );
124             fprintf( stderr,
125                      "fg_debug.c: Environment overrides default debug priority (%d)\n",
126                      fg_DebugPriority );
127         }
128     /* } */
129
130
131     /*
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.
135     */
136         pszClass = getenv( "FG_DEBUGCLASS" );
137         if( pszClass ) {
138             fg_DebugClass = fgDebugStrToClass( pszClass );
139             fprintf( stderr,
140                      "fg_debug.c: Environment overrides default debug class (0x%08X)\n",
141                      fg_DebugClass );
142         }
143     /* } */
144
145     FG_RELEASEDEBUGSEM;
146 }
147
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;
154   
155     if( str == NULL ) {
156         return 0;
157     }
158
159     /* Check for 0xXXXXXX notation */
160     p = strstr( str, "0x");
161     if( p ) {
162         p++; p++;
163         while (*p) {
164             ph = strchr(hex,*p);
165             if ( ph ) {
166                 val <<= 4;
167                 val += ph-hex;
168                 p++;
169             } else {
170                 ph = strchr(hexl,*p);
171                 if ( ph ) {
172                     val <<= 4;
173                     val += ph-hex;
174                     p++;
175                 } else {
176                     // fprintf( stderr, "Error in hex string '%s'\n", str ); 
177                     return FG_NONE;
178                 }
179             }
180         }
181     } else {
182         /* Must be in string format */
183         p = str;
184         ps = 1;
185         while( ps ) {
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 */
192             i=0; 
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 ) {
197                 fprintf( stderr,
198                          "fg_debug.c: Could not find message class '%s'\n",
199                          pt ); 
200             } else {
201                 val |= fg_DebugClasses[i].dbg_class;
202             }
203         }
204     }
205     return (fgDebugClass)val;
206 }
207
208
209 /* fgSetDebugOutput =======================================================*/
210 void fgSetDebugOutput( FILE *out ) {
211     FG_GRABDEBUGSEM;
212     fflush( fg_DebugOutput );
213     fg_DebugOutput = out;
214     FG_RELEASEDEBUGSEM;
215 }
216
217
218 /* fgSetDebugLevels =======================================================*/
219 void fgSetDebugLevels( fgDebugClass dbg_class, fgDebugPriority prio ) {
220     FG_GRABDEBUGSEM;
221     fg_DebugClass = dbg_class;
222     fg_DebugPriority = prio;
223     FG_RELEASEDEBUGSEM;
224 }
225
226
227 /* fgRegisterDebugCallback ================================================*/
228 fgDebugCallback fgRegisterDebugCallback( fgDebugCallback callback ) {
229     fgDebugCallback old;
230     FG_GRABDEBUGSEM;
231     old = fg_DebugCallback;
232     fg_DebugCallback = callback;
233     FG_RELEASEDEBUGSEM;
234     return old;
235 }
236
237
238 /* fgPrintf ===============================================================*/
239 int fgPrintf( fgDebugClass dbg_class, fgDebugPriority prio, char *fmt, ... ) {
240     char szOut[1024+1];
241     va_list ap;
242     int ret = 0;
243
244     // If no action to take, then don't bother with the semaphore
245     // activity Slight speed benefit.
246
247     // printf("dbg_class = %d  fg_DebugClass = %d\n", dbg_class, fg_DebugClass);
248     // printf("prio = %d  fg_DebugPriority = %d\n", prio, fg_DebugPriority);
249
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
254
255             // "ret" is zero anyway. But we might think about changing
256             // it upon some error condition?
257             return ret;
258         }
259     }
260
261     FG_GRABDEBUGSEM;
262
263     /* ret = vsprintf( szOut, fmt, (&fmt+1)); (but it didn't work, thus ... */
264     va_start (ap, fmt);
265     ret = vsprintf( szOut, fmt, ap);
266     va_end (ap);
267
268     if( fg_DebugCallback!=NULL && fg_DebugCallback(dbg_class, prio, szOut) ) {
269         FG_RELEASEDEBUGSEM;
270         return ret;
271     } else {
272         fprintf( fg_DebugOutput, szOut );
273         FG_RELEASEDEBUGSEM;
274         if( prio == FG_EXIT ) {
275             exit(0);
276         } else if( prio == FG_ABORT ) {
277             abort();
278         }
279     }
280     return ret;  
281 }
282
283
284 /* $Log$
285 /* Revision 1.4  1998/06/01 17:49:44  curt
286 /* Rewrote a slightly ambiguous code fragment (contributed by Charlie Hotchkiss)
287 /*
288  * Revision 1.3  1998/05/07 23:03:54  curt
289  * Added an entry for AUTOPILOT.
290  *
291  * Revision 1.2  1998/04/21 17:03:45  curt
292  * Prepairing for C++ integration.
293  *
294  * Revision 1.1  1998/04/18 03:52:04  curt
295  * Moved to Lib directory and created a libDebug.
296  *
297  * Revision 1.10  1998/03/14 00:31:21  curt
298  * Beginning initial terrain texturing experiments.
299  *
300  * Revision 1.9  1998/03/09 22:44:58  curt
301  * Modified so that you can specify FG_DEBUGCLASS ***or*** FG_DEBUG_PRIORITY
302  *
303  * Revision 1.8  1998/03/09 22:11:00  curt
304  * Processed through the format-o-matic.
305  *
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.
309  *
310  */