rocq/theories/Getopt.v
Trusted getopt_long boundary. Admission describes memory independently of parsing success: arbitrary NUL-terminated argument contents are allowed. The result relation deliberately abstracts scanning order, abbreviations and diagnostics, not capability provenance. It is a safety contract, not a functional specification of GNU getopt.
The client supplies a projection from its ONE libc world, initialized parser representation, in-progress representation and a frame relation preserving locale and authoritative shutdown/stdout state. Private roots include diagnostic stderr state when needed; they must not include caller-owned storage. Native adequacy and safepoint coverage remain trusted obligations, not new runtime axioms.
A selected x86-64 option record is 32 bytes: name at 0, has_arg at 8, flag at 16 and val at 24. Padding is not interpreted.
Logical witnesses for one call family. Argument pointers include their exact capabilities; subsequent calls may permute only the tail. No bound on string contents is imposed beyond C termination.
| getopt_argc | : Z | |
| getopt_argv | : ptr | |
| getopt_arguments | : listptr × listZ | |
| getopt_optstring | : ptr | |
| getopt_short_options | : listZ | |
| getopt_longopts | : ptr | |
| getopt_options | : listlong_option | |
| getopt_longindex | : ptr |
Physical cells are references supplied by startup/linking. The four values alone do NOT establish initialization of glibc's private parser. Reads, writes and release ownership are separate authorities.
| getopt_optarg_cell | : ptr | |
| getopt_optind_cell | : ptr | |
| getopt_opterr_cell | : ptr | |
| getopt_optopt_cell | : ptr | |
| getopt_errno_cell | : ptr | |
| getopt_optarg | : ptr | |
| getopt_optind | : Z | |
| getopt_opterr | : Z | |
| getopt_optopt | : Z | |
| getopt_errno | : Z | |
| getopt_reads | : listspan | |
| getopt_roots | : listspan | |
| getopt_owned | : listZ |
Canonical signed C int, stored/returned as its unsigned W bits.
Writable aligned int cell with an independently specified value.
Optional out-int: null is absence, not a writable null span.
Pointer slots, including the exact null sentinel. Each native byte is canonical independently of the aggregate pointer load; consumers can reconstruct exact byte pieces after argv permutation.
argv0 is fixed; GNU permutation moves whole tail pointers, never merely their address bits. argc=0 admits just the sentinel.
Argument strings are borrowed, readable C strings.
A writable argv vector and one capability-exact permitted ordering.
All records and names are readable; optional flag writes require their own authority. A null name terminates the table.
The five actual argument words, independent of any result.
Caller admission includes the entire sentinel-terminated table and every optional writable flag/index, even on an unknown option.
Public exposed state is coherent with memory. A separate rep premise certifies initialized continuation or reset optind=0, including GNU ordering/environment and any interior nextchar borrow.
A pointer borrow into any argv string, including its NUL, retains the original capability. Empty --greeting= is therefore admitted.
Null or an argv borrow, never a fresh owned allocation.
Spans protected against all writes, including private/errno roots. Separation is about storage, not restrictions on argument bytes.
Optional writable output span.
Exposed writable cells, distinct from private parser roots.
Caller-owned outputs remain separate from parser-private spans.
No character-buffer writes are authorized by parsing.
The separate output pieces do not overlap. This intentionally excludes aliased flag/index/state outputs, whose last-write behavior is not specified here; it excludes no Hello argument contents.
The argv slots and strings supply borrowed capabilities for optarg and permutation, but do not delegate private ownership.
Disjoint protected bytes and write spans. Representation must also keep private release rights exclusive of all caller objects.
Private releases name live heap objects and exclude every caller capability-bearing input/output object, not merely its byte span.
Normal outcomes preserve protected bytes AND shadow entries.
Physical public cell identities never change across a call.
Private projection capabilities come from explicitly enumerated private pointers or new objects, NOT complete pointer slots inside caches, which may contain a caller's optarg/nextchar borrow.
Private authority can only descend from old private authority or born objects. In particular storing optarg never makes its argv object a parser root or an owned allocation eligible for release.
Drop GNU's leading ordering marker, then the error marker.
First occurrence of a short option selects its argument mode. Native char is signed on this target; high bytes are sign-extended.
Mode zero has no optarg, mode one needs a nonnull argv borrow, and mode two permits either. No ownership is transferred.
Abstract result classification. Long success reports its table index and writes its flag, or returns val when the flag is absent. A required argument always yields a nonnull readable argv borrow. Errors and end-of-options have null optarg. Scanning order is left abstract; this relation promises no termination or exact diagnostics.
GNU diagnostics are stderr acceptance only; the caller-owned errno cell may change even when no diagnostic is emitted.
Ready admission does not equate reset with arbitrary writable state. Private ownership/liveness and noninterference belong to rep.
Logical prefix endpoints use an in-progress representation, not completed parser state at arbitrary native cutpoints. Resource ends inherit only this prefix relation, not the normal postcondition.
Normal completion restores represented option state and all input borrows for positive argc. The argc=0 early return exports private optarg/optopt, not necessarily their old public values or a borrow into this empty argv. optind is in range; opterr is unchanged. optopt is deliberately not overconstrained on successful paths.
Exact W/P/P/P/P arguments and W result, even when discarded.
Trusted family over a projection of the existing libc world. The supplied stable relation must preserve effective locale names, text, codec and epoch and the one shutdown/stdout inventory. requests accounts for diagnostic/private allocations; there is no promise of purity, ordinary malloc NULL, or native adequacy.
The exact capability of a borrowed optarg is never replaced by a stronger Obj capability having the same address.
Explore proof 3 tactics
Initial goal
intros input p q & text & offset & Hin & Hrange & →
exists q, text
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Permutation preserves argv's full pointer inventory.
Explore proof 5 tactics
Initial goal
intros | p ps | q qs H ; simpl in H ; try contradiction
2 open–apply Permutation_refl
–destruct H as → H
apply perm_skip
exact H
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Every option result is a normal W return, never an exit request.
Explore proof 2 tactics
Initial goal
intros W input view rep xs m w born trace ending m′ w′ _ & _ & _ & _ & code & H & _
eauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Required arguments cannot be a null optarg, even for empty strings.
Explore proof 3 tactics
Initial goal
intros input p Harg Hnonnull
specialize Hnonnulleq_refl
split ; destruct Harg ; contradiction | assumption | assumption
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The post exposes exactly the ordinary pointer-load protocol main uses: address bytes together with the original capability in aux.
Explore proof 3 tactics
Initial goal
intros World input view rep xs m w born trace ending m′ w′ _ & _ & Hcell _ & _
apply exposed_pointer_load
exact Hcell
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Runtime-facing lemmas for this machine instance. Sibling functor applications are generative; using these inside Logic requires the separately reviewed exact-instance integration, not an alias claim.
Both normal and resource endpoints expose the actual finite effect path and stable composite world. Only normal endpoints restore the postcondition; a failed allocation does not imply parser completion.
Explore proof 14 tactics
Initial goal
intros World input view rep inflight stable requests r args xs s m w trace ending s′ m′ w′ Hcall
destruct Hcall as trace ending s′ m′ w′ born Habi Hpre He Hp Hpost Hresource Hvalues Hexit | why trace s′ m′ w′ born Habi Hpre He Hp Hfailure Hresource
2 openfocused goal
–split ; exact Hpre |
2 opendeferred goal
exists born
2 opendeferred goal
split ; exact He |
2 opendeferred goal
split ; exact Hp |
2 opendeferred goal
auto
deferred goal
–split ; exact Hpre |
exists born
split ; exact He |
split ; exact Hp |
right
exists why
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Slot controls separate canonical bytes from their aggregate load. The noncanonical null encoding cancels 256 against -1 * 256.
Canonical zero bytes admit both an argv entry and its sentinel.
Explore proof 2 tactics
Initial goal
cbn [ getopt_slots ]
repeat split ; try reflexivity ; try lia ; intros k Hk ; change 0 ≤ 0 < 256 ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
These integers decode to zero but are not native memory bytes.
Merely specifying the loaded pointer does not exclude this memory.
Explore proof 2 tactics
Initial goal
vm_compute
repeat split ; congruence
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Bounds apply to the final null slot too, not only nonnull entries.
Explore proof 4 tactics
Initial goal
intros _ Hbytes
specialize Hbytes0 ltac:lia
change 0 ≤ 256 < 256 in Hbytes
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.