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