I have ~16k lines of 1998 vintage C code (~50 main progs) which built flawlessly under gcc at that time but now fails with many \"lvalue required as left operand of assignme
In addition to changing the code to take an address, cast the pointer, and dereference, it will likely also be necessary to employ the "no_strict_aliasing" option. C99 added some rules, with the intention of facilitating optimization, which negate C's model of the system state as being a bunch of unsigned char[]
. The most infamous of these is the Strict Aliasing Rule. While code which casts pointers as a means of saying "interpret the thing pointed to by this pointer as a X" may compile, writing to a pointer using one type and reading using another will generally yield Undefined Behavior, and some compilers will interpret that as license to behave in rather strange and bizarre ways unconstrained by laws of time and causality.
gcc is no longer allowing you to assign to a cast.
i.e.
((CELL *)(cell)->car) = free_list;
is no longer legal. Instead of casting the lhs to match the rhs, it would rather you cast the rhs to match the lhs. One way around this is to take the address of the lvalue, cast it as a pointer, and then dereference that pointer, so the assignment is to a pointer dereference instead of a cast.
i.e.
*((CELL **)&(cell)->car) = free_list;
This can be handled by updating the macros, so it should be quite painless...
i.e.
#define cell_car(c) (*((CELL **)&(c)->car))
etc...
This macro can then be used as either an lvalue or an rvalue.