Skip to content

[Medium] Switches cannot be turned off from the CLI, breaking documented YAML-override precedence #131

@zhaozhiwen

Description

@zhaozhiwen

There is no CLI syntax to disable a switch. A switch enabled in a YAML file cannot be overridden off on the command line, contradicting the documented "command line options overwrite YAML file(s)" precedence.

Affected files

  • gemc/goptions/goptions.cc:163-172 (CLI switch handling — only turnOn())
  • gemc/goptions/goptions.cc:332-334 (YAML switch handling — only turnOn())
  • gemc/goptions/goptions.cc:513 (documented precedence: "command line options overwrite YAML file(s)")
  • gemc/goptions/gswitch.h:60-69 (turnOn() / turnOff() both exist)

Details
On the CLI, a switch is only recognized in the no-= branch, where it is unconditionally turned on:

else {
    // Treat as a switch: -gui, -i, etc.
    const string& possibleSwitch = argStr;
    if (switches.find(possibleSwitch) != switches.end()) {
        switches[possibleSwitch].turnOn();
    }
    else {
        cerr << "The switch " << possibleSwitch << " is not known to this system." << endl;
        exit(EC__NOOPTIONFOUND);
    }
}

Anything containing = is routed to the option path (line 128 eqPos != string::npos). So -gui=false is parsed as option gui, doesOptionExist("gui") is false (it is a switch, not an option), and the program exits with "The option gui is not known to this system." (line 158).

GSwitch already provides turnOff() (gswitch.h:69), but it is unreachable from parsing. Consequently a YAML gui: true (handled at line 333 switches[name].turnOn()) can never be overridden off from the CLI, directly contradicting the precedence note printed at line 513.

Impact
Users cannot disable a YAML-enabled switch (e.g. turn off gui for a batch run) without editing the YAML file. The stated CLI-over-YAML precedence is false for switches.

Proposed fix
Before the eqPos != string::npos option branch, intercept -<switch>=<bool> tokens whose key is a known switch and route to turnOn()/turnOff(). This adds an explicit off syntax (-gui=false / -gui=true) while leaving option parsing untouched.

 			if (eqPos != string::npos) {
 				string keyPart   = argStr.substr(0, eqPos);
 				string valuePart = argStr.substr(eqPos + 1);
 
+				// Switch with explicit boolean value: -gui=false / -gui=true
+				if (switches.find(keyPart) != switches.end()) {
+					if (valuePart == "true" || valuePart == "1")       switches[keyPart].turnOn();
+					else if (valuePart == "false" || valuePart == "0") switches[keyPart].turnOff();
+					else {
+						cerr << "The switch " << keyPart << " accepts only true/false." << endl;
+						exit(EC__NOOPTIONFOUND);
+					}
+					continue;
+				}
+
 				// Strip outer quotes if present (e.g., -gstreamer="[...]")
 				if (!valuePart.empty() && valuePart.front() == '"' && valuePart.back() == '"') {

turnOff() already exists in gswitch.h, so no change to GSwitch is required. The bare -gui form continues to work via the existing no-= branch.


Split out from #102 (one issue per bug). Found via an AI-assisted code review with manual verification against commit 5f8ce875.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions