Live data from Hacker News

Dennis Ritchie's first C compiler on Github

github.com

81–88 of 88 posts

Re: Dennis Ritchie's first C compiler on Github

#81

Earlier quoted context omitted.

Shadowing keywords is perfectly valid, although I believe you can't shadow keywords in standard headers so that compiler writers don't need to worry about it. It gives rise to some "useful" C/C++ features that should never be used, like if you want to access private members in foo.cpp, do #define private public #include "foo.cpp" #undef private

I can imagine some insidious menace adding this to the top of a file: #define public protected

I once someone jokingly do (the second only always works in C, not C++)

    #define else
    #define struct union
Evil!

Re: Dennis Ritchie's first C compiler on Github

#82
post #76

Earlier quoted context omitted.

Don't confuse the tab character with the tab key . The key is great. I use it all the time. Of course I don't want to press the space bar twelve times instead of tabbing three times. Of course I don't want sloppy indentation with 7 or 9 spaces instead of 8. Is this an actual problem? I've literally never seen either one in ~25 years of using languages that need indentation. The editor takes care of it. The problem wi…

Just use tabs for indentation and spaces for alignment.

While you might do so, anyone you collaborate with will probably not do that. Why? Because almost every code editor in existence comes with that option turned off. And many of them don't even have that option at all! If you expect your codevelopers to manually adjust the alignment to be spaces rather than tabs on each line they edit, when their editor doesn't even distinguish tabs from spaces, oh boy.

Tabs just don't work out in a collaborative environment. It is too complicated for a heterogenous editing environment to get correct, so no such environment gets it correct in practice and code ends up a huge mess.

Re: Dennis Ritchie's first C compiler on Github

#83
post #69
post #55

Can anyone explain the naming of files? c00.c, c01.c etc

c0 is the first pass (c to intermediate), c1 is the second pass (intermediate to assembly), c2 is the optimizer. c0 is built from files beginning with 'c0' and so on.

Thanks for the explanation

Re: Dennis Ritchie's first C compiler on Github

#84
Can anyone get this to compile and run?

Does anyone know what hardware the assembly language files are for?

Maybe you could produce a modified version with the archaic features removed, compile it with a modern compiler, then use the binary produced to compile an unmodified version. Or maybe there are still binaries of really old compilers that can understand this code floating around out there.

Any ideas?

Re: Dennis Ritchie's first C compiler on Github

#85
post #17
post #4

Earlier quoted context omitted.

Looks like a very early dialect. C assumes everything is an int unless specified otherwise. You can declare parameter types after the function name. So: init(s, t) char s[]; { would be equivalent to: int init(char s[], int t) { This still works with modern compilers. I'd be interested if anyone has any more info about this: waste() /* waste space */ { waste(waste(waste),waste(waste),waste(waste)); waste(waste(waste),…

That was the standard way of declaring parameter types until ANSI C in 1989. C actually copied the current style back from C++.

ANSI C didn't drop old-style (non-prototype) function declarations and definitions -- nor did C99 or C11. They've been officially obsolescent since 1989, but they're still fully supported by any conforming compiler.

Re: Dennis Ritchie's first C compiler on Github

#86
post #57

I don't understand this main(argc, argv) int argv[]; { Is that still valid today?

It's called a K&R style function definition, which was the way to do it back in the day . Basically, you define your parameter names first, then you define the parameter types immediately after the function but before the opening curly brace. It's definitely not recommended today and can result in undefined behavior if your compiler doesn't recognize it. If you're working with legacy code, though, I'm pretty sure you…

The 1999 ISO C standard dropped the "implicit int" rule, so this:

    main(argc, argv)
    char *argv[];
    {
        /* ... */
    }
is illegal (strictly speaking, it's a "constraint violation"). Note that it's

    char *argv[]
not

    int argv[]
But this:

    int main(argc, argv)
    int argc;
    char *argv[];
    {
        /* ... */
    }
is still perfectly valid.

As for this:

    int main(int argc, unsigned long long argv[]) {
      char *firstarg = (void *)(argv[1]);
      printf("%s", firstarg);
    }
it's not a constraint violation, but its behavior is undefined (unless your compiler specifically supports and documents that particular form as an extension).

Re: Dennis Ritchie's first C compiler on Github

#87

Earlier quoted context omitted.

In an appropriately powerful language, it could be a function call.

Which is exactly why you don't do it in a language where it isn't.

Why should a developer have to have headspace for a special class of construct? And what difference does it make in practice whether it is a keyword or a function - why do you think it's so important that they are obviously different in the code - does their being part of a special category have any practical implications?

Re: Dennis Ritchie's first C compiler on Github

#88
post #86

Earlier quoted context omitted.

It's called a K&R style function definition, which was the way to do it back in the day . Basically, you define your parameter names first, then you define the parameter types immediately after the function but before the opening curly brace. It's definitely not recommended today and can result in undefined behavior if your compiler doesn't recognize it. If you're working with legacy code, though, I'm pretty sure you…

The 1999 ISO C standard dropped the "implicit int" rule, so this: main(argc, argv) char *argv[]; { /* ... */ } is illegal (strictly speaking, it's a "constraint violation"). Note that it's char *argv[] not int argv[] But this: int main(argc, argv) int argc; char *argv[]; { /* ... */ } is still perfectly valid. As for this: int main(int argc, unsigned long long argv[]) { char *firstarg = (void *)(argv[1]); printf("%s"…

We're talking about the code from the actual source files, not the standard.

Look here (lines 22 and 23): https://github.com/mortdeus/legacy-cc/blob/master/prestruct/...

The compiler code states int argv[], not char argv[] (I assumed this is why the OP asked for clarification in the first place, since char argv[] is much more common).

You're right, in theory this is undefined behavior, but in practice on a 32-bit system, sizeof(int) will almost always be equal to sizeof(void *). I was just demonstrating how one could recreate the code in the compiler while on a 64-bit architecture.

Post reply on HN