rewrote (most) in C