gvpr: fix: wrap members needing cleanup in a struct and outline
When seeing this code, the compiler emitted numerous warnings like:
gvpr.c: In function ‘gvpr’:
gvpr.c:929:17: warning: variable ‘prog’ might be clobbered by
‘longjmp’ or ‘vfork’ [-Wclobbered]
parse_prog *prog = 0;
^~~~
What it is trying to tell us is that this code violates the assumptions of
`setjmp`/`longjmp`. Referencing any non-volatile stack-allocated variable after
a `longjmp` is undefined behavior.¹
This change extracts all the members that need to be referenced after `longjmp`
into a wrapper function. This basically puts a function call boundary in a place
such that the code no longer violates assumptions of the C standard. It is a
little awkward that we have to do this by hand, as the transformation is
mechanical and the compiler technically has enough information to do this for
us. But `setjmp`/`longjmp` come from the old world and are low level mechanisms.
If the compiler sees a call to them, it assumes you are doing something unusual
and want to do it exactly as you wrote.
While making this adjustment, some white space is adjusted and some coercion to
boolean is changed to explicit comparisons against `NULL`.
I do not understand why, but after this change the compiler still believes
`nextg` can be clobbered by a `longjmp`. While this is true, `nextg` is not used
after `longjmp`-ing back to `gvpr_core`, so I do not know why the compiler
thinks it needs to warn us about this.
Gitlab: #1801
¹ This restriction stems from how `setjmp`/`longjmp` work on certain platforms.
If a variable is live in a register instead of on the stack, it is not
guaranteed to be restored during a `longjmp`. Hence why the value of such
variables is undefined after a `longjmp`.