Every fec error message was written to stderr, and COMMAND.COM can only redirect handle 1 -- ">" is the whole vocabulary, "2>" is not parsed at all. So a failing compile recorded exit code 1 and a zero-byte log, and the actual message went to a screen nobody reads. Confirmed directly: `FEC.EXE --check` on a fixture that must fail produced rc=1 and 0 bytes of stdout. That is why an unexpected compiler failure was undiagnosable. It also means the M6 reject cases have only ever asserted "exit code was nonzero" -- the error text they nominally check has never been observable to the runner. Add fe_diag_stream(), which resolves once to stdout when FE_DIAG_STDOUT is set and stderr otherwise, and route diag.c and driver.c through it. The default is unchanged, so interactive use keeps writing to stderr; the runner sets the variable in RUN.BAT. The stderr references in check.c and emit_c.c are the Ferro language's own std.io.stderr writer and are deliberately untouched. Verified in DOSBox-X: 155 passed. A rejecting compile now records its message, source excerpt and caret in RESULTS\<key>.LOG. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BScg8CF1sAAM2zVHAu5zvW
33 lines
1.0 KiB
C
33 lines
1.0 KiB
C
#ifndef FE_DIAG_H
|
|
#define FE_DIAG_H
|
|
|
|
#include <stdio.h>
|
|
|
|
typedef struct FeLoc {
|
|
const char *file;
|
|
unsigned long line;
|
|
unsigned long col;
|
|
} FeLoc;
|
|
|
|
typedef struct FeDiags {
|
|
unsigned long errors;
|
|
unsigned long warnings;
|
|
const char *source;
|
|
unsigned long source_len;
|
|
} FeDiags;
|
|
|
|
/* Stream diagnostics are written to. Defaults to stderr; returns stdout when
|
|
FE_DIAG_STDOUT is set in the environment. DOS offers no way to redirect
|
|
handle 2 -- COMMAND.COM understands ">" and nothing else -- so under the test
|
|
runner every error message would otherwise be written straight to the screen
|
|
and lost. Interactive use is unaffected: both streams reach the console. */
|
|
FILE *fe_diag_stream(void);
|
|
|
|
void fe_diags_init(FeDiags *d, const char *source, unsigned long source_len);
|
|
void fe_diag_error(FeDiags *d, FeLoc loc, const char *msg);
|
|
void fe_diag_errorf(FeDiags *d, FeLoc loc, const char *msg, const char *arg);
|
|
void fe_diag_note(FeLoc loc, const char *msg);
|
|
void fe_diag_note_src(FeDiags *d, FeLoc loc, const char *msg);
|
|
|
|
#endif
|