stdlib savetxt(unit, x, ...) checks
inquire(unit=unit, opened=opened, write=writable)
if (.not. opened .or. writable(1:1) /= 'Y') call error_stop
to verify the unit can be written before emitting any data. Two gaps:
1. afs_inquire_unit / afs_inquire_file had no parameter for write=,
read=, or readwrite=, so the caller's writable variable was left
at uninitialized stack data — savetxt always concluded the unit
was not writable.
2. The IR's Stmt::Inquire lowering never extracted these three specs
from the AST, so even adding runtime params would have silently
passed null buffers.
Add (read_buf, write_buf, readwrite_buf) trios to both runtime
functions and to both call-emission sites in IR. Populate based on
the connected unit's Action: Read => YES/NO/NO, Write => NO/YES/NO,
ReadWrite => YES/YES/YES, disconnected => UNKNOWN.
Make Action Copy so the action-cap helper can take it by value
without cloning at every call site.
write(unit, fmt, iostat=ios, iomsg=iomsg) values would leave the user's
ios variable at its uninitialized stack value on success — only error
paths are even capable of writing it, and there are none in the runtime
yet. Stdlib's universal pattern is
if (ios/=0) call error_stop(msg=trim(iomsg))
so on a successful write the user's program would die with a spurious
ERROR STOP because ios was random garbage. Resolve the iostat= control
target up front and store i32(0) after afs_fmt_end / lower_write_items_adv
returns, both for unit-targeted writes and for internal-buffer writes.
Combined with 4986129 (descriptor-aware section iteration), savetxt
now writes example.dat / example.csv / example2.dat / example3.dat
correctly with three rows of data each. Remaining savetxt failure is
a separate output_unit (stdout via unit 6) handling bug.