FlightGear - Options - FG(12)

index back

Wednesday, 10 February 2005.

RE: sglog().setLogLevels( SG_ALL, SG_ALERT );

This started off as me trying to understand why, an
option command to FlightGear --log-level=info, did MORE
than expected, and ended up adding another command
line option -

--log-class=[none|all],
or a list, like 'terrain|io|event|general|...' ...

As a 'developer', running FG to 'test' something,
I may want to 'alter' the classes (sgDebugClass),
like say -

in main.cxx - abt-line 692 -
sglog().setLogLevels( (SG_ALL & ~(SG_EVENT)), SG_DEBUG );

All works as 'expected'. Then I want to 'reduce' the
output, so I add the item --log-level=info to the
input commands (command line, system.fgfsrc, ...) BUT
the class reverts to SG_ALL.

What is happening here?

The command --log-level is handled in options.cxx,
where the static int fgOptLogLevel( const char *arg )
service parses the input, BUT before that -
abt-line 901 - it does -

logbuf::set_log_classes(SG_ALL);

which FORCES the classes back to SG_ALL. Why is
this being done? There seems no purpose, other than,
if you change the Priority, then you *MUST* revert
to SG_ALL classes ???

I also note that the global properties are set as
follows, UNCONDITIONALLY to 'all' -
fgSetString("/sim/logging/classes", "all");
fgSetString("/sim/logging/priority", arg);

Keeping sgDebugClass, which is a BIT field, as
a string, needs a 'table' to xlate each BIT
to a string ... reverting to 'all', if all BIT were
on ... that is a BIT-to-text/text-to-BIT xlate ...

I see, in fg_props.cxx, the 'table' - abt-line 59 -
// Default property bindings (not yet handled by any module).
struct LogClassMapping {
sgDebugClass c;
string name;
LogClassMapping(sgDebugClass cc, string nname) { c = cc; name = nname; }
};

Why the comment 'not yet handled by any module'? Other
than meaning sort of not-yet-used, or tested ...

LogClassMapping log_class_mappings [] = {
LogClassMapping(SG_NONE, "none"),
LogClassMapping(SG_TERRAIN, "terrain"),
LogClassMapping(SG_ASTRO, "astro"),
... etc ... growing list ...

// a string, separated by '|' characters, is prepared by -
static const char * getLoggingClasses () {
sgDebugClass classes = logbuf::get_log_classes();
static string result = ""; // FIXME
for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
if ((classes&log_class_mappings[i].c) > 0) {
if (!result.empty())
result += '|';
...

this is called from static void addLoggingClass
(const string &name) {...
Why is there a 'FIXME' comment? Other than 'results'
is a static to fg_props.cxx ... and should be
'somewhere-else' .. it is ok here ...

static void setLoggingClasses (const char * c) {
does the 'setting' from an a|b|c|d type input string,
which calls addLoggingClass(name);

Also noted, in fg_props.cxx - abt-line 474 - does
the following -
void FGProperties::bind () { // Simulation
fgTie("/sim/logging/priority", getLoggingPriority, setLoggingPriority);
fgTie("/sim/logging/classes", getLoggingClasses, setLoggingClasses);
...

Like, static int fgOptLogLevel( const char *arg ), it seems
all the stuff is there to support another 'option', perhaps
an addition to options.xml, in the -
<section>
<name>strings/debugging-options</name>
section, like, per log_class_mappings -
<option>
<name>log-class</name>
<arg>{none,terrain,astro,flight,input,gl,view,cockpit,general,math,event,aircraft,autopilot,io,clipper,network,instrumentation,systems</arg>
<description>strings/log-class-desc</description>
</option>

and a static int fgOptLogClass( const char *arg ) -
in options.cxx - abt-line 894 -
static int
fgOptLogClass( const char *arg )
{
setLoggingClasses(arg);
char * cp = getLoggingClasses();
fgSetString("/sim/logging/classes", cp);
}

Add table line to enumeration -
enum OptionType { OPTION_BOOL, OPTION_STRING, OPTION_DOUBLE, OPTION_INT, OPTION_CHANNEL, OPTION_FUNC };
struct OptionDesc {
- abt-line 1325 -

{"log-class", true, OPTION_FUNC, "", false, "", fgOptLogClass },

And we support --log-class=all, or none, or terrrain|astro|... ... I hope!

Opps, first I had to 'undo' the 'static' nature, like,
in fg_props.cxx -
//static const char *
const char * getLoggingClasses () {

and add, in options.cxx -
extern const char * getLoggingClasses () {

and likewise -
extern void setLoggingClasses (const char * c);

Oh, and I remember to 'remove' the 'offending code,
like in options.cxx ...

static int fgOptLogLevel( const char *arg ) {
// fgSetString("/sim/logging/classes", "all");
fgSetString("/sim/logging/priority", arg);
string priority = arg;
// logbuf::set_log_classes(SG_ALL);
if (priority == "bulk") {
...

That should do it ...
static int fgOptLogClass( const char *arg ) {
extern void setLoggingClasses (const char * c);
setLoggingClasses(arg);
extern const char * getLoggingClasses ();
const char * cp = getLoggingClasses();
fgSetString("/sim/logging/classes", cp);
return FG_OPTIONS_OK;
}

Of course this meant adding 'single' setting
functions to SimGear ... I add the set of 4
to SimGear\source\simgear\debug\logstream.hxx
sgDebugClass getLogClasses ();
sgDebugPriority getLogPriority ();
void setLogClasses (sgDebugClass c);
void setLogPriority (sgDebugPriority p);
and implement the 'services' in
SimGear\source\simgear\debug\logstream.cxx

In the first DEBUG run, found I had 'edited' the
WRONG system.fgfsrc ... one of the 'problems' of
having 'several' runtime environments ... ;=))

In the LOG output, not the following, which
looks like a 'repeat' ... I had 'seen' this happen
lots earlier, when my system.fgfsrc was read ... hmmmm

Loaded new panel from Aircraft/c172/Panels/c172-vfr-panel.xml
Adding subsystem input
Adding subsystem replay
Set logging classes to terrain|astro|flight|input|gl|view|cockpit|general|math|a
ircraft|autopilot|io|clipper|network|instrumentation|systems|terrain|astro|fligh
t|input|gl|view|cockpit|general|math|aircraft|autopilot|io|clipper|network|instr
umentation|systems|terrain|astro|flight|input|gl|view|cockpit|general|math|aircr
aft|autopilot|io|clipper|network|instrumentation|systems
Initializing old dialog commands:
old-save-dialog
...

but it should be 'working' ... it is ;=)) ... the 'event'
updates are NOT shown in the output ... thank you
for such a versatile system ... and a chance to code in
it ...

With a little bit of XML, and a little bit of C/C++
code, and any OPTION is yours for the creation.

Now, to SUMMARISE, and POST -

Choose a SUBJECT, maybe -

RE: add option --log-class, and 'fix' --log-level

The following 6 patches will ADD --log-class,
as a command, and stop --log-level from setting
'all' regardless ....

In diff format, the changes were in 6 files,
2 in SimGear, 4 in FlightGear (1 data, 3 source)
SG1. SimGear\source\simgear\debug\logstream.hxx
SG2. SimGear\source\simgear\debug\logstream.cxx
FG1. FlightGear\data\options.xml
FG2. FlightGear\source\src\Main\fg_commands.cxx
FG3. FlightGear\source\src\Main\fg_props.cxx
FG4. FlightGear\source\src\Main\options.cxx

The specific changes were -

SG1. Add 4 new 'services' to get/set the log class and
level SEPARATELY ;-))
SimGear\source\simgear\debug\logstream.hxx
260,263d259
< sgDebugClass getLogClasses ();
< sgDebugPriority getLogPriority ();
< void setLogClasses (sgDebugClass c);
< void setLogPriority (sgDebugPriority p);

SG2. Implement the 'services'
SimGear\source\simgear\debug\logstream.cxx
91,106d90
< // perhaps add - Feb 2005
< sgDebugClass logstream::getLogClasses () {
< return logbuf::get_log_classes ();
< }
<
< void logstream::setLogClasses (sgDebugClass c) {
< logbuf::set_log_classes(c);
< }
<
< sgDebugPriority logstream::getLogPriority () {
< return logbuf::get_log_priority () ;
< }
<
< void logstream::setLogPriority (sgDebugPriority p) {
< logbuf::set_log_priority(p);
< }

Then the FlightGear changes

FG1. Establish the option in XML
diffu <base_dir>\data\options.xml
930a931,936
> <name>log-class</name>
> <arg>{none,terrain,astro,flight,input,gl,view,cockpit,general,math,event,aircraft,autopilot,io,clipper,network,instrumentation,systems</arg>
> <description>strings/log-class-desc</description>
> </option>
>
> <option>

FG2. Avoid re-setting SG_ALL
diffu <base_dir>\source\src\Main\fg_commands.cxx
1144,1145c1144,1147
< sglog().setLogLevels( SG_ALL, (sgDebugPriority)arg->getIntValue() );
<
---
> //sglog().setLogLevels( SG_ALL, (sgDebugPriority)arg->getIntValue() );
> sglog().setLogLevels( sglog().getLogClasses(), (sgDebugPriority)arg->getIntValue() );
> // *OR* if there was a
> // sglog().setLogPriority( (sgDebugPriority)arg->getIntValue() );

FG3. Make these functions 'globally' available
diffu <base_dir>\source\src\Main\fg_props.cxx
94c94,95
< static const char *
---
> //static const char *
> const char *
127c128,129
< static void
---
> // static void
> void

FG4. Add the 'decode' function for the new option,
stop the log-level 'decode' function re-setting,
and add the new 'service' to the table ...
diffu <base_dir>\source\src\Main\options.cxx
894a895,905
> fgOptLogClass( const char *arg )
> {
> extern void setLoggingClasses (const char * c);
> setLoggingClasses(arg);
> extern const char * getLoggingClasses ();
> const char * cp = getLoggingClasses();
> fgSetString("/sim/logging/classes", cp);
> return FG_OPTIONS_OK;
> }
>
> static int
897c908
< fgSetString("/sim/logging/classes", "all");
---
> // fgSetString("/sim/logging/classes", "all");
901c912
< logbuf::set_log_classes(SG_ALL);
---
> // logbuf::set_log_classes(SG_ALL);
1317a1329
> {"log-class", true, OPTION_FUNC, "", false, "", fgOptLogClass },

a voila ... it all works, as expected ... have not checked
the 'binding' fully, that is setting props on-the-fly ... but
by 'removing' say 'event' from the class list, I can now
run fg, with my so altered system.fgfsrc file,
and watch what I am doing better, WITHOUT reading the
VERY INFORMATIVE sun, moon, star, updates ... ;=))

And a big thanks for the SG_LOG(class, level, "stuff") function,
macro, that contains, was designed with, such 'flexibility' ...

Hope it helps, and makes it to cvs ...

Regards,

Geoff.

PS: If you want to read 'more' about adding this option,
the research, some 'reasoning', explanations, ...
I have added a fg section to my site -
geoffmclane.com/fg/fgfs-012.htm
where there is a sort of PLOG - programmer's log? ;=))

EOF

index back