why would it take several thousands of lines of code?
The "C-style" version of my example would, as I said, build an explicit call graph and run an allocation algorithm on it. I would take thousands of lines to do that, and probably spend months getting it to work. I imagine you could do better.
I don't know what "building an explicit call graph" looks like in this context, nor do I know what "an allocation algorithm" would be in this case. You wrote a simple piece of C code that looks fine (?) and doesn't really look like it's not "C-style", so I don't have a clue how that might translate into your idea of what "C-style" means, and I really can't even fathom what a thousand-lines version of this is supposed to be.
"Forth-style" code does the minimum possible work to get the job done and breaks up functionality into small, re-usable pieces.
"C-style" code solves problems in a methodical fashion and has a tendency toward monolithic, generalized solutions.
I've seen many C coding guidelines that recommend breaking tasks into small functions and re-using them as much as is practical. The idea of "small, re-usable pieces" is kind of just a programming platitude, though; I don't think it has much to do with the language at all. I don't know what your experience with C is, but there's small specialized code and there is monolithic libraries too, but I really don't get why you think that "C-style" has to mean some gargantuan overwrought library. ?
What do you think of, say, DOOM's C source code
? Does this look like "C-style" to you?
Your statements almost seem like a distortion of the definition of a "functional" programming language vs an "imperative", though I've been looking at Forth again since you mentioned it, and I don't think Forth fits the definition of "functional programming" either, though these things don't actually have to be a language feature-- they can apply to tendencies of style too. More pure functional languages tend to impose that you work certain ways, e.g. in Haskell it tends to be very impractical to debug large complicated functions, so if you don't break things into small pieces your program will probably just die. So... language design can often strongly guide you to write in a certain way.
I don't understand from your description how this relates to Forth and C, though.
There are as many dialects of Forth as there are Forth programmers. Writing your own compiler is pretty much a rite of passage, and the language's entire shtick is domain-specific customization. Portability is unheard of.
Honnestly this makes FORTH sound as a terrible language, perhaps even worse than assembly.
From what I can tell, Forth's strongest point is that it's exceedingly simple and easy to write an interpreter/compiler for. I don't really see how this aids the task of programming itself, but it does seem to make it very portable/implementable and customizable, which is a practical advantage in some situations.
It seems specifically designed to produce small binary bytecode, by having very little language features. I can see how it could produce smaller binaries than native assembly or C (and the interpreter implementation itself would be small too), but none of this seems to be an aid to the programmer. Coding Forth you have to "think" in RPN because the language does every operation it can through the stack. You get smaller code the more things you can cascade through the stack. (I did mention earlier, though, that I think translating ideas into RPN is a burden that has been shifted to the programmer here that can easily be done by a compiler.)
I'm reminded a little of SWEET16
where Woz wrote a bytecode interpreter for doing 16-bit stuff on the 6502 but with small code.
It's pretty common to write small bytecode interpreters in C or assembly, though, enabling you to use both a compact bytecode and efficient native code in tandem. "Small" code isn't the exclusive domain of Forth; Forth is just a language that seems to get a lot of functionality out of relatively few moving parts.