1
0
Fork 0
flightgear/Main/fg_debug.c

264 lines
7.6 KiB
C
Raw Normal View History

1998-01-27 02:54:43 +00:00
/**************************************************************************
* fg_debug.c -- Flight Gear debug utility functions
*
* Written by Paul Bleisch, started January 1998.
*
* Copyright (C) 1998 Paul Bleisch, pbleisch@acm.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* (Log is kept at end of this file)
**************************************************************************/
#include <string.h>
1998-01-27 02:54:43 +00:00
#include <stdio.h>
#include <stdarg.h>
1998-01-27 02:54:43 +00:00
#include <stdlib.h>
#include <Include/cmdargs.h> // Line to command line arguments
#include <Main/fg_debug.h>
static int fg_DebugSem = 1;
fgDebugClass fg_DebugClass = FG_ALL; // Need visibility for
fgDebugPriority fg_DebugPriority = FG_INFO; // command line processing.
1998-01-27 02:54:43 +00:00
static fgDebugCallback fg_DebugCallback = NULL;
FILE *fg_DebugOutput = NULL; // Visibility needed for command line processor.
// This can be set to a FILE from the command
// line. If not, it will be set to stderr.
1998-01-27 02:54:43 +00:00
/* TODO: Actually make this thing thread safe */
#ifdef USETHREADS
#define FG_GRABDEBUGSEM while( --fg_DebugSem < 0 ) { fg_DebugSem++; }
1998-01-27 02:54:43 +00:00
#define FG_RELEASEDEBUGSEM fg_DebugSem++;
#else
#define FG_GRABDEBUGSEM
#define FG_RELEASEDEBUGSEM
1998-01-27 02:54:43 +00:00
#endif
/* Used for convienence initialization from env variables.
*/
static struct {
char *str;
1998-02-01 03:34:59 +00:00
fgDebugClass dbg_class;
1998-01-27 02:54:43 +00:00
} fg_DebugClasses[] = {
{ "FG_NONE", 0x00000000 },
{ "FG_TERRAIN", 0x00000001 },
{ "FG_ASTRO", 0x00000002 },
{ "FG_FLIGHT", 0x00000004 },
{ "FG_INPUT", 0x00000008 },
{ "FG_GL", 0x00000010 },
{ "FG_VIEW", 0x00000020 },
{ "FG_COCKPIT", 0x00000040 },
{ "FG_GENERAL", 0x00000080 },
{ "FG_MATH", 0x00000100 },
{ "FG_EVENT", 0x00000200 },
{ "FG_AIRCRAFT",0x00000400 },
1998-01-27 02:54:43 +00:00
/* Do not edit below here, last entry should be null */
{ "FG_ALL", 0xFFFFFFFF },
{ NULL, 0 } };
static fgDebugClass fgDebugStrToClass( char *str );
/* fgInitDebug =============================================================*/
void fgInitDebug( void )
{
char *pszClass, *pszPrio, *pszFile;
// Support for log file/alt debug output via command line, environment or
// reasonable default.
if( strlen( logArgbuf ) > 3) { // First check for command line option
fg_DebugOutput = fopen(logArgbuf, "a+" ); // Assumed that we will append.
}
if( !fg_DebugOutput ) { // If not set on command line, environment?
pszFile = getenv( "FG_DEBUGFILE" );
if( pszFile ) { // There is such an environmental variable.
fg_DebugOutput = fopen( pszFile, "a+" );
}
}
1998-01-27 02:54:43 +00:00
if( !fg_DebugOutput ) { // If neither command line nor environment
fg_DebugOutput = stderr; // then we use the fallback position
}
1998-01-27 02:54:43 +00:00
FG_GRABDEBUGSEM;
fg_DebugSem = fg_DebugSem; /* shut up GCC */
1998-01-27 02:54:43 +00:00
// Test command line option overridge of debug priority. If the value
// is in range (properly optioned) the we will override both defaults
// and the environmental value.
1998-01-27 02:54:43 +00:00
if ((priorityArgValue >= FG_BULK) && (priorityArgValue <= FG_ABORT)) {
fg_DebugPriority = priorityArgValue;
}
else { // Either not set or out of range. We will not warn the user.
pszPrio = getenv( "FG_DEBUGPRIORITY" );
if( pszPrio ) {
fg_DebugPriority = atoi( pszPrio );
fprintf( stderr,
"fg_debug.c: Environment overrides default debug priority (%d)\n",
fg_DebugPriority );
}
}
if ((debugArgValue >= FG_ALL) && (debugArgValue < FG_UNDEFD)) {
fg_DebugPriority = priorityArgValue;
}
else { // Either not set or out of range. We will not warn the user.
pszClass = getenv( "FG_DEBUGCLASS" );
if( pszClass ) {
fg_DebugClass = fgDebugStrToClass( pszClass );
fprintf( stderr,
"fg_debug.c: Environment overrides default debug class (0x%08X)\n",
fg_DebugClass );
}
}
1998-01-27 02:54:43 +00:00
FG_RELEASEDEBUGSEM;
}
/* fgDebugStrToClass ======================================================*/
fgDebugClass fgDebugStrToClass( char *str )
{
char *hex = "0123456789ABCDEF";
char *hexl = "0123456789abcdef";
char *pt, *p, *ph, ps = 1;
1998-01-27 02:54:43 +00:00
unsigned int val = 0, i;
if( str == NULL ) {
return 0;
}
/* Check for 0xXXXXXX notation */
if( (p = strstr( str, "0x")) ) {
p++; p++;
while (*p) {
if( (ph = strchr(hex,*p)) || (ph = strchr(hexl,*p)) ){
val <<= 4;
val += ph-hex;
p++;
}
else {
/* fprintf( stderr, "Error in hex string '%s'\n", str );
*/
return FG_NONE;
}
}
}
else {
/* Must be in string format */
p = str;
ps = 1;
while( ps ) {
while( *p && (*p==' ' || *p=='\t') ) p++; /* remove whitespace */
pt = p; /* mark token */
while( *p && (*p!='|') ) p++; /* find OR or EOS */
ps = *p; /* save value at p so we can attempt to be bounds safe */
*p++ = 0; /* terminate token */
/* determine value for token */
i=0;
while( fg_DebugClasses[i].str &&
strncmp( fg_DebugClasses[i].str, pt, strlen(fg_DebugClasses[i].str)) ) i++;
if( fg_DebugClasses[i].str == NULL ) {
fprintf( stderr, "fg_debug.c: Could not find message class '%s'\n", pt );
} else {
1998-02-01 03:34:59 +00:00
val |= fg_DebugClasses[i].dbg_class;
1998-01-27 02:54:43 +00:00
}
}
}
return (fgDebugClass)val;
}
/* fgSetDebugOutput =======================================================*/
void fgSetDebugOutput( FILE *out )
{
FG_GRABDEBUGSEM;
fflush( fg_DebugOutput );
fg_DebugOutput = out;
FG_RELEASEDEBUGSEM;
}
/* fgSetDebugLevels =======================================================*/
1998-02-01 03:34:59 +00:00
void fgSetDebugLevels( fgDebugClass dbg_class, fgDebugPriority prio )
1998-01-27 02:54:43 +00:00
{
FG_GRABDEBUGSEM;
1998-02-01 03:34:59 +00:00
fg_DebugClass = dbg_class;
1998-01-27 02:54:43 +00:00
fg_DebugPriority = prio;
FG_RELEASEDEBUGSEM;
}
/* fgRegisterDebugCallback ================================================*/
fgDebugCallback fgRegisterDebugCallback( fgDebugCallback callback )
{
fgDebugCallback old;
FG_GRABDEBUGSEM;
old = fg_DebugCallback;
fg_DebugCallback = callback;
FG_RELEASEDEBUGSEM;
return old;
}
/* fgPrintf ===============================================================*/
1998-02-01 03:34:59 +00:00
int fgPrintf( fgDebugClass dbg_class, fgDebugPriority prio, char *fmt, ... )
1998-01-27 02:54:43 +00:00
{
char szOut[1024+1];
va_list ap;
1998-01-27 02:54:43 +00:00
int ret = 0;
// If no action to take, then don't bother with the semaphore activity
// Slight speed benefit.
1998-01-27 02:54:43 +00:00
1998-02-01 03:34:59 +00:00
if( !(dbg_class & fg_DebugClass) || (prio < fg_DebugPriority) ) {
return ret; // Its zero anyway. But we might think about changing
// it upon some error condition?
}
FG_GRABDEBUGSEM;
/* ret = vsprintf( szOut, fmt, (&fmt+1)); (but it didn't work, thus ... */
va_start (ap, fmt);
ret = vsprintf( szOut, fmt, ap);
va_end (ap);
1998-01-27 02:54:43 +00:00
1998-02-01 03:34:59 +00:00
if( fg_DebugCallback!=NULL && fg_DebugCallback(dbg_class, prio, szOut) ) {
1998-01-27 02:54:43 +00:00
FG_RELEASEDEBUGSEM;
return ret;
}
1998-01-27 02:54:43 +00:00
else {
fprintf( fg_DebugOutput, szOut );
FG_RELEASEDEBUGSEM;
if( prio == FG_EXIT ) {
exit(0);
}
1998-01-27 02:54:43 +00:00
else if( prio == FG_ABORT ) {
abort();
}
}
return ret;
}
// Revision history?
//