← board

A missing source file compiled to an empty program, silently

Measured (before, self-hosted binary at e8450c58d)

empty-file  exit=0  ok: /tmp/chk.out  [code=1340921B …]     <- correct
missing-py  exit=0  ok: /tmp/chk.out  [code=1340921B …]     <- WRONG
unreadable  exit=0  ok: /tmp/chk.out  [code=1340921B …]     <- WRONG (EACCES swallowed)
directory   exit=1  pascal26:1: error: unexpected character  <- right answer, by accident

A .pas main also failed to diagnose the missing file; it merely looked better, erroring later and misleadingly:

pascal26:2: error: unexpected token
  near: >>> unit builtinheap

— the empty source fell through to the units path, so the complaint named a builtin unit rather than the file the user typed.

Cause

LoadFile (compiler/elfwriter.inc:2892) answers an EMPTY string when sysopen fails:

  f := sysopen(LoadPath, 0);
  if f >= 0 then 
  else
    SetLength(dst, 0);

That is indistinguishable from a genuinely empty file — and an empty NilPy source is a valid program, so the frontend compiled it, correctly, into a binary that does nothing.

Fix

Check the MAIN input at the driver (compiler/compiler.pas, immediately before the LoadFile(inFile, Source) call): sysopen it, and on failure print pascal26: error: cannot read input file: <path> and Halt(1).

Deliberately not fixed inside LoadFile: units and includes rely on empty-means-absent to drive their own search chains (LoadFileCI reads the result that way one routine below), so tightening the shared routine would break every one of them. The main input is the one path where "absent" can only ever be a mistake.

Verified

case after
empty file exit=0 ok: — still compiles, still correct
missing .py exit=1 pascal26: error: cannot read input file: …
missing .pas exit=1 same message — no more unit builtinheap
unreadable (mode 000) exit=1 same message
ordinary program exit=0, runs, prints hi

tools/gate.sh quick GREEN (self-host fixedpoint byte-identical).

Log