I've dealt with a lot of these 80s C "vintage" codebases. If you want to hear some horror stories, I've dealt with ones where a single function was bigger than the entire codebase you're talking about (single functions that spanned over 20,000 lines of code with about 30 levels of indentation using a one-space indentation style and 50 or so variables declared at the top).
Even though your codebase is so teeny in size, I recommend approaching it from a thorough test-oriented perspective if the code is really complex in a way where you kind of need to reverse engineer it. Of course if you feel like you can reconstruct the program in Java without this kind of reverse engineering process, this might be a case where it's excusable to kind of start a new canvas from scratch.
If it is complex though and you don't feel confident that you can replicate the original software's functionality easily then...
Wrap In C to Desired Interface
Even C allows object-oriented programming. You can model objects like this (C++):
class Foo
{
public:
Foo();
~Foo();
void do_something(int blah);
private:
float x;
int y;
};
... in C like so:
// In header file:
struct Foo* foo_create();
void foo_destroy(struct Foo* foo);
void foo_do_something(struct Foo* foo, int blah);
// In source file:
struct Foo
{
float y;
int x;
};
...
... there are even ways to emulate inheritance and polymorphism through composition and function pointers.
With this strategy, you can start extracting C interfaces over this messy blob of code which are well-designed, conform to SOLID principles, etc.
I recommend this strongly over the temptation to refactor the code directly where the iterations might start to seem endless as you get knee-deep in implementation details while simultaneously trying to find a sane structure out of it. Boldly create wrapper interfaces instead which model your final Java interface goals right from the start.
You could also potentially wrap this code into C++ classes given the ease of interoperability between C and C++ which might make it even easier to port this to Java. The initial versions might be stateless and just call functions in the C codebase if they're based on a bunch of globals, but don't let that impact your interface designs. Design them like they have encapsulated state.
Focus on getting the public interfaces right. You can do all kinds of inefficient trickery under the hood to make these interfaces work against this convoluted codebase. The initial goal here is to reshape the design and structure, not implementation (that comes last).
Write Tests for New Wrappers
Now write tests for these wrapper interfaces you construct, making sure they conform to your interface requirements. You also want to apply possibly a more integrated mindset here testing for correct output. The process of constructing these tests and wrapper interfaces will also rapidly accelerate your understanding of how the legacy code works.
Keep going until you've covered the entire codebase and established an acceptable structure, translating things on the way. The result should be a public interface which is suitable to you. Then start porting the client code in your codebase to start utilizing these interfaces.
Port to Java
Last but not least, port this to Java and replicate the same interfaces and tests. At this point, you should have a good enough understanding to fill in the implementations.
This is a very long and exhaustive route to solving the problem, but it shouldn't take that long given the teeny size of this codebase. I ended up doing this kind of stuff for millions upon millions of lines of code, so this should seem like a vacation in comparison.
Alternate Approach
An alternate approach mentioned already is just start off from the Java side. The reason I recommend starting off wrapping and testing from the C side is that I'm assuming the value of this convoluted piece of code relates to the outputs it provides over a given set of inputs. It can increase the rate at which you learn and understand the program by wrapping and testing it initially in the same language it was originally written, albeit very roundabout, and also makes sure your tests don't miss some subtle behavior in the original which might need to be preserved.