Skip to content

Wire NOTE messages into CLI output with severity prefixes#292

Merged
spe-ciellt merged 1 commit intogerbv:developfrom
SourceParts:fix/cli-message-severity
Mar 1, 2026
Merged

Wire NOTE messages into CLI output with severity prefixes#292
spe-ciellt merged 1 commit intogerbv:developfrom
SourceParts:fix/cli-message-severity

Conversation

@rampageservices
Copy link
Copy Markdown
Contributor

Summary

  • Add GERB_NOTE macro (G_LOG_LEVEL_INFO) and emit NOTE messages through g_log in gerb_stats.c
  • Replace g_log_default_handler passthrough with a custom formatter that prints clean fatal:/error:/warning:/note: prefixes to stderr
  • Add --quiet/-q flag to suppress note-level messages
  • Wire up the existing --log/-l flag to actually write prefixed messages to a file

Context

PR #282 (Gerber X2 attributes) added GERBV_MESSAGE_NOTE messages for X2 attribute commands. The NOTE case in gerbv_stats_add_error() had a break with no g_log() call — messages were stored in the error list but never emitted to stderr. Messages that did reach stderr used GLib's default format (** (process): WARNING **: text) with no clean prefix. The --log flag was parsed but never connected.

Changes

src/gerbv.hGERB_NOTE(...) macro mapping to G_LOG_LEVEL_INFO

src/gerb_stats.c — Wire empty GERBV_MESSAGE_NOTE case to GERB_NOTE()

src/main.c:

  • Custom callbacks_temporary_handle_log_messages that formats with severity prefixes, respects --quiet, writes to log file, and preserves log_array_tmp for GUI replay
  • --quiet/-q option (longopts, opt_options, switch case, help text)
  • --log/-l file open after option parsing, fclose on both CLI exit and GUI return paths

Test plan

  • Build: cd build && cmake .. && make — clean, no warnings
  • X2 file without --quiet: shows note: Ignoring Gerber X2 attribute...
  • X2 file with --quiet: note suppressed, no output
  • Bad file: error: and warning: prefixes shown correctly
  • --log /tmp/gerbv.log: log file written with prefixed messages
  • Test suite: 94 passed, 10 pre-existing rendering mismatches (unrelated)

Fixes #291

@spe-ciellt spe-ciellt added the fix Solution for a potential problem or omission. label Feb 28, 2026
@spe-ciellt
Copy link
Copy Markdown
Contributor

Issues

Fragile quiet-mode comparison. GLib log levels are bitmasks, not an ordered scale — higher numeric values mean less severe:

G_LOG_LEVEL_ERROR    = 4
G_LOG_LEVEL_WARNING  = 16
G_LOG_LEVEL_INFO     = 64   ← what NOTE uses
G_LOG_LEVEL_DEBUG    = 128

The condition:

if (quietMode && level >= G_LOG_LEVEL_INFO)
    goto handle_fatal;

happens to suppress INFO and DEBUG correctly by accident, but reads as if INFO is "high severity". It also silently suppresses G_LOG_LEVEL_DEBUG without any documentation. The correct idiom is an explicit bitmask:

if (quietMode && (level & (G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG)))
    goto handle_fatal;

goto violates codebase style. main.c and the rest of the codebase don't use goto. The handle_fatal: label jump can be replaced with a plain if/else without any loss of clarity.

One exit(1) path may not close the log file. The fclose(logFile) calls are added before exit(0) and at GTK cleanup, but the exit(1) at "A valid file was not loaded" (after argument parsing, after the log file is already opened) appears to be missed. On most systems exit() flushes stdio anyway, but it is an inconsistency.

"message" prefix may confuse users. GERB_MESSAGE() uses G_LOG_LEVEL_MESSAGE which the PR labels "message:" on stderr. Most Unix CLI tools use "info:" for that severity. Minor naming issue but worth considering.

--quiet suppresses notes during pass 1 of getopt only from pass 2 onward. Any messages emitted during pass 1 of the two-pass getopt loop won't be suppressed because quietMode is set in pass 2. In practice almost no messages are emitted during option parsing, so this is unlikely to matter.

Updating command line switches should update the man page as well. I'm not sure if is up to date, but from now I think it is good idea to keep that updated as well.

GERBV_MESSAGE_NOTE messages were stored in the error list but never
emitted to stderr, making them invisible in CLI mode. The log handler
also used GLib's default format with no clean prefixes, and the --log
flag was parsed but never connected.

- Add GERB_NOTE macro mapping to G_LOG_LEVEL_INFO
- Emit NOTE messages through g_log in gerb_stats.c
- Replace g_log_default_handler with custom formatter that prints
  clean "fatal/error/warning/info/note:" prefixes to stderr
- Add --quiet/-q flag to suppress note-level and debug messages
- Wire up --log/-l to write prefixed messages to a file
- Preserve GUI replay via log_array_tmp storage
- Delegate to g_log_default_handler only for fatal (abort)
- Parse --quiet in getopt pass 1 so it takes effect before pass 2
- Close log file on all exit paths for consistency
- Update man page with -q/--quiet and revised -l/--log descriptions

Fixes gerbv#291
@rampageservices rampageservices force-pushed the fix/cli-message-severity branch from ada0d95 to 7ab3584 Compare March 1, 2026 05:45
@rampageservices
Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review. All six points addressed:

  1. Fragile quiet-mode comparison — Replaced level >= G_LOG_LEVEL_INFO with explicit bitmask (level & (G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG)).

  2. goto violates codebase style — Replaced goto/label with an if/else block. The quiet-mode check now wraps the print logic in a negated condition, and the fatal handler runs unconditionally after.

  3. Missed exit(1) log file closure — Added if (logFile) fclose(logFile) before both exit(1) paths at "A valid file was not loaded" (single-file export check and default export switch case).

  4. "message" prefix — Changed G_LOG_LEVEL_MESSAGE prefix from "message" to "info".

  5. --quiet only from pass 2 — Added case 'q' to the pass 1 getopt loop so quietMode is set before any messages can be emitted during pass 2 option parsing.

  6. Man page — Added -q|--quiet entry and updated -l|--log description to reflect the new behavior (writes prefixed messages to file in addition to stderr).

Force-pushed with --force-with-lease.

@rampageservices
Copy link
Copy Markdown
Contributor Author

One concern: I'm uneasy about the naming where G_LOG_LEVEL_MESSAGE maps to "info" and G_LOG_LEVEL_INFO maps to "note". It feels inverted — "message" becoming the more informational label and "info" being demoted to "note" reads backwards. Open to suggestions on better naming here.

@spe-ciellt
Copy link
Copy Markdown
Contributor

I agree with you. You can swap them around if you want to. I don't know if that will cause any problems in other part of the code. If it is too many changes in other places of the code maybe we should leave it at the moment and drop an issue for future reference?

It would also be great if this could be documented somewhere. Currently I am a bit overwhelmed by all PRs coming in (I am positive, don't get me wrong). But keep this in mind for the future. ;)

@rampageservices
Copy link
Copy Markdown
Contributor Author

@spe-ciellt No urgency at all on any of our PRs — take your time. We really appreciate the decades of work you've put into gerbv, and the credit and attribution in the project. It's great to see a release happening after so long!

On the naming swap: I checked the scope — GERB_MESSAGE appears ~45 times across 10 files, GERB_NOTE is only in gerb_stats.c. So swapping them would be a mechanical rename but it touches a lot of call sites. I think the cleanest approach is to do the swap (rename GERB_MESSAGE → maps to "note:", GERB_NOTE → maps to "info:") in a separate follow-up PR so this one can land as-is. I'll drop an issue to track it and document the log level mapping there.

@spe-ciellt spe-ciellt merged commit ebd5bc0 into gerbv:develop Mar 1, 2026
2 checks passed
@spe-ciellt spe-ciellt self-assigned this Mar 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Solution for a potential problem or omission.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI output should differentiate message severity levels

2 participants