The original Bourne shell was written in a *very* strange style of C, which shows that even in 1979, some of the original Unix greats disdained C's famed terseness & wanted _keywords_ instead of punctuation marks.

TIL it has a name: it's known as "Bournegol".

https://oldhome.schmorp.de/marc/bournegol.html

Marc Lehmann's "Bournegol Page"

Bournegol

@lproven pre-ANSI C is weird anyway, but ... AAAARRGRGGGHHHHH MY EYES ARE ON FIRE

@DrHyde @lproven

I have written real code in BCPL and pre-ANSI C is a pure and perfect gem by comparison. The only major syntactical problem in classic C is the prefix pointer indirection operator.

@resuna @DrHyde

The mere fact that C is bad does not preclude the possibility that its ancestors may not have been even worse.

@lproven @resuna @DrHyde I used to teach a course that was nominally students' second exposure to (modern-ish) C and as a result I have a damn *list* of its syntactic design errors, most of which go all the way back to the original.

@zwol @lproven @DrHyde

There are some issues but at least they swapped equals-minus to minus-equals. Octal constants are a niggling annoyance. But the only critical mistake I think was making pointer indirection prefix. Most of the other syntactic difficulties are consequences of that. I discussed it briefly with Dennis at Usenix and he said that they had thought about changing it but by that time they had three sites using C and they thought it would be disruptive.

@resuna @lproven @DrHyde Yeah *some* of the problems would go away with postfix pointer dereference, but the inside-out complex declarator structure, the fact that "struct X { ... };" and "struct { ... } X;" are both valid and mean two very different things, and the excessive number of operator precedence levels have nothing to do with pointers. Just to name three.

@zwol @lproven @DrHyde

The inside out type declaration is due entirely to the prefix pointer dereference.

@resuna @lproven @DrHyde Not true. `int (fptr*)(int)` is not an improvement on `int (*fptr)(int)`.

@zwol @lproven @DrHyde

int fptr*(int);

Making both pointer and function indirection postfix means you don't need (all (the (extra) parens)). It's not "inside-out" any more. It's linear.

@resuna @lproven @DrHyde The name of the declarand is still in the middle, and you have to read first to the right (for the arguments) then to the left (for the return type) and THEN back to the middle (asterisk means it's not a function but a pointer TO a function being declared).

That's the inside-out-ness. That's what confuses students the most.

To not be inside-out, it would need to be something like `var fptr: *((int) -> int)` or `var fptr: ((int) -> int)*`.

@zwol @resuna @lproven @DrHyde the committee would later duplicate this madness with const, which is prefix most of the time.

@vathpela @resuna @lproven @DrHyde People tend to *write* qualifiers as if they're prefix but they are actually *parsed* as "postfix unless there isn't anything to the left to qualify, in which case prefix".

Sorry if I'm telling you something you already know. I have had to write a full parser for C declarations, from scratch, twice, and debug other people's attempts more times than I can remember.

@zwol @resuna @lproven @DrHyde yeah, it's just that it'll drive you crazy when trying to deal with const pointers. Just a wild choice.

@zwol @lproven @DrHyde

So you're actually saying it should be "var fptr*(int) -> int;"

I can see an argument for that but it's practically syntactic sugar, it's a much smaller issue than having to disambiguate "*fptr(int)" with "(*fptr)(int)". Prefix pointers require you to continually switch from left to right over and over again as you parse the expression.

@resuna @lproven @DrHyde I give up. I don't know how to make you believe that the C declarator syntax requires people to read back and forth and back and forth *even when no pointers are involved* and it's one of the most common things for people who are just starting to learn C to struggle with.

@lproven @DrHyde

The only differences between C declaration syntax and any other algol-derived language are the type name being at the front instead of the end, and the mess created by having indirection operators with two different syntaxes.

@resuna @lproven @DrHyde I *said* I give up. Please stop.
@zwol @resuna @lproven ugh, precedence. People moan at me for using unnecessary parentheses. They are wrong.
@zwol @lproven @resuna does the list start with "literally everything to do with pointers"?
@DrHyde @lproven @resuna Semantic design errors are a separate list.