[HN Gopher] Dennis Ritchie's first C compiler (c. 1972)
       ___________________________________________________________________
        
       Dennis Ritchie's first C compiler (c. 1972)
        
       Author : jnord
       Score  : 355 points
       Date   : 2021-03-11 02:51 UTC (20 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | tirrex wrote:
       | https://github.com/mortdeus/legacy-cc/blob/ccbe90a2803e2cc7e...
       | 
       | "auto" exists in the initial version.
        
         | volta83 wrote:
         | And what does it mean there? (automatic storage duration)
        
           | tirrex wrote:
           | Do you mean automatic type deduction?
           | 
           | Edit : I know it's also storage specifier but it also does
           | type deduction here, hope I'm not confused with the
           | terminology
        
             | volta83 wrote:
             | It doesn't do type deduction there.
             | 
             | In original C you could declare variables without a type,
             | and these variables with auto have no type.
             | 
             | So this "auto" is essentially saying "this variable without
             | a type uses automatic storage". That's a completely
             | different language feature from "deduce the type of this
             | variable".
        
               | mianos wrote:
               | A variable without a type is 'int' so ```auto xx;```
               | means an int on the function local variable stack.
        
               | tirrex wrote:
               | Thanks.
        
             | jcelerier wrote:
             | here it means automatic storage duration
        
             | nix-zarathustra wrote:
             | No, it doesn't do type deduction. Without specifying the
             | type, it assumes a type of int. Everything in C revolves
             | around ints.
        
           | jstanley wrote:
           | It means it lives on the stack, so it "exists" until the
           | function returns.
        
             | wruza wrote:
             | That is true, but more nuanced. https://www.tutorialspoint.
             | com/cprogramming/c_storage_classe...
        
       | [deleted]
        
       | astroanax wrote:
       | The original keywords - https://github.com/mortdeus/legacy-
       | cc/blob/master/last1120c/...
       | 
       | Interestingly, long was commented
        
         | rightbyte wrote:
         | There is no short or unsigned either. Maybe int modifiers were
         | pending work?
         | 
         | for is missing too.
        
         | josephg wrote:
         | It makes sense long would have needed a comment. It needs a
         | comment because "long" and "double" are terrible names for data
         | types. Long _what_? Double length _what_? Those type names
         | could easily have opposite meanings and meant long floating
         | point  / double length integer. WORD/DWORD are nearly as bad -
         | calling something a "word" incorrectly implies the data type
         | has something to do with strings.
         | 
         | If you don't believe me, ask a non programmer friend what kind
         | of thing an "integer" is in a computer program. Then ask them
         | to guess what kind of thing a "long" is.
         | 
         | The only saving grace of these terms is they're relatively easy
         | to memorise. int_16/int_32/int_64 and float_32/float_64 (or
         | i32/i64/f32/f64/...) are much better names, and I'm relieved
         | that's the direction most modern languages are taking.
         | 
         | (Edit: Oops I thought Microsoft came up with the names WORD /
         | DWORD. Thanks for the correction!)
        
           | yiyus wrote:
           | > ask a non programmer
           | 
           | Why should a non programmer understand programming terms?
           | Words have different meanings in different contexts. That's
           | how words work. There is no need to make these terms
           | understandable to anyone. The layman does not need to
           | understand the meaning of long or word in C source code.
           | 
           | Ask a non-golf player what is an eagle or ask a physicist, a
           | mathematician and a politic the meaning of power.
           | 
           | Word and long may have been poor word choices, but asking a
           | non-programmer is not a good way to test it.
        
             | josephg wrote:
             | Good variable names (and type names) matter for legibility.
             | They should be clear, unambiguous, short, memorable and
             | suggestive. Unambiguous is usually more important than
             | short and memorable.
             | 
             | The word 'long' is ambiguous and unmemorable. And the type
             | "word" is actively misleading. If you called a variable or
             | class 'long', it wouldn't pass code review. And for good
             | reason.
             | 
             | 'Power' is an excellent example of what good technical
             | terms look like. "Power" has a specific technical meaning
             | in each of those fields, but in each case the technical
             | meaning is suggested by the everyday meaning of the word
             | "power". Ask a non-physicist to guess what "power" means in
             | a physics context and they'll probably get pretty close.
             | Ask a non-programmer to guess what "integer" means in
             | programming and they'll get close. Similarly computing
             | words like "panic", "signal", "file", "output", "stream",
             | "motherboard" etc are great terms because they all suggest
             | their technical meaning. You don't have to understand
             | anything about operating systems to have an intuition about
             | what "the computer panicked" means.
             | 
             | Some technical terms you just have to learn - like "GPU" or
             | "CRDT". But at least those terms aren't misleading. I have
             | no problem with the term "double precision floatingpoint"
             | because at least its specific.
             | 
             | "long", "double", "short" and "word" are bad terms because
             | they sound like you should be able to guess what they mean,
             | but that is a game you will lose. And to make matters
             | worse, 'long', 'double' and 'short' are all adjectives in
             | the english language, but used in C as nouns[1]. They're
             | the worst.
             | 
             | [1] All well named types are named after a noun. This is
             | true in every language.
        
               | bregma wrote:
               | "long" and "short" are adjectives in C. The types are
               | "long int" and "short int" and the "int" is implied if
               | it's not present. A declaration like
               | auto long sum;
               | 
               | Declares a variable named "sum" of type "long int" and of
               | automatic storage duration.
               | 
               | The "double" comes from double-precision floating point.
               | In the 1970s and 1980s anyone who came near a computer
               | would know what that meant. Anyone who ever had to use a
               | log table or slide rule (which was anyone doing math
               | professionally) would know exactly what that meant.
               | 
               | There are good sound reasons for the well-chosen
               | keywords. Just because one is ignorant of those reasons
               | does not mean they were not good choices.
        
               | _kst_ wrote:
               | Well, you can certainly think of "long" and "short" as
               | adjectives, but the grammar doesn't treat them that way.
               | 
               | "long", "short", "signed", "unsigned", "int", "float",
               | and "double" are all _type specifiers_. The language
               | specification includes an exhaustive list of the valid
               | combinations of type specifiers, including which ones
               | refer to the same type. The specifiers can legally appear
               | in an order. For example,  "short", "signed short", and
               | "int short signed", among others, all refer to the same
               | type. (They're referred to as "multisets" because "long"
               | and "long long" are distinct.)
        
               | flohofwoe wrote:
               | You really need to consider the context before making
               | broad statements like this.
               | 
               | By your own standards, "word" and "long (word)" are
               | actually excellent terms, because they're conventions
               | used by the underlying hardware, and using the same
               | conventions absolutely makes sense for a programming
               | language that's close to the hardware:
               | 
               | https://en.wikipedia.org/wiki/Word_(computer_architecture
               | )
        
             | msla wrote:
             | Or ask a non-mathematician what a ring, a field, and a
             | group are.
        
             | oblio wrote:
             | > Ask a non-golf player what is an eagle or ask a
             | physicist, a mathematician and a politic (sic) the meaning
             | of power.
             | 
             | All those fields could do with less jargon. Especially
             | since in many cases there is a common word.
             | 
             | Lawyers especially give me the impression that they use
             | jargon to obscure their field from regular folks.
             | 
             | Our field, being new, should not make the same mistakes,
             | but yet, here we are, where the default "file viewer" on
             | Unix is cat, the pager is called "more", etc.
             | 
             | I don't see any reason why those types could not have had
             | descriptive names from the start. Well, there was one, lack
             | of experience, so -\\_(tsu)_/-
        
               | mywittyname wrote:
               | > Lawyers especially give me the impression that they use
               | jargon to obscure their field from regular folks.
               | 
               | Really? You think that lawyers (and physicians) use
               | Latin/Greek words in order to confuse _regular folks_?
               | 
               | These fields are very old, and changing the meaning of
               | something _Mens Rea_ or _lateral malleolus_ is going to
               | require A) an exact drop-in replacement which will
               | probably just as obscure, B) retraining of an entire set
               | of people.
               | 
               | Our field is similar in that we have a mountain of jargon
               | that's largely inaccessible to _regular folks_. The point
               | of those words are not to converse with _regular folks_
               | but to convey information to others in the field with as
               | little ambiguity as possible.
        
               | tomatocracy wrote:
               | In England many Latin terms were replaced with English
               | terms in 1998 with the adoption of the new Civil
               | Procedure Rules in an effort to make justice "more
               | accessible" (alongside other reforms). These arguably
               | actually added confusion - for example it's much more
               | obvious that a "writ" is a specialist term versus "claim"
               | which replaced it.
        
               | thechao wrote:
               | Dejargonification is great; I agree that jargon is a real
               | barrier to entry. However, after having dealt with
               | lawyers (and doctors of all stripes: MDs, PhDs, ...),
               | I've come to see jargon for what it is: a weakly typed
               | pointer. It's exactly analogous to a struct of function
               | pointers with a user cookie in C.
               | 
               | Jargon lets you summarize whole concepts in one word. A
               | lot of jargon is functional in the math/programming
               | sense: you can pass 'arguments' to the jargon. The jargon
               | adds levels of abstraction that let the users communicate
               | faster, with less error, and higher precision.
               | 
               | For instance, the distinction between _civil_ and
               | _criminal_ matters; or the distinction between
               | _malfeasance_ , _misdemeanor_ , and _felony_.
        
             | titzer wrote:
             | It's about cognitive load. The more jargon diverges from
             | concepts you _already_ have learned and used for years, the
             | more difficult it is to adapt. As an experiment, try
             | replacing all of your variable names and types with
             | numbered variables: v1, v2, v3, etc. Then compare to
             | replacing them with words: not completely random words, but
             | with completely misleading words, like the complete
             | opposite of what they represent, length /height,
             | mass/speed, etc. You'll find the latter is maddeningly hard
             | to deal with, because your brain keeps bringing a whole lot
             | of context that is just wrong, so you are constantly
             | fighting your own brain.
             | 
             | Intuitive things come from prior experience. They are a
             | kind of inertia that you just have to work with.
        
               | greggyb wrote:
               | Jargon that builds on intuition can be its own problem.
               | Jargon, by its very definition, has explicit technical
               | meaning in a specific domain. Intuition in words is based
               | on vernacular usage. It is vanishingly unlikely that the
               | vernacular usage aligns with the domain-specific usage of
               | a given term. This leads to plenty of false assumptions,
               | and forces people to disambiguate jargon-usage vs
               | vernacular-usage, which may both be found in a single
               | piece of writing.
               | 
               | See economics for a great example of jargon-vernacular
               | crossover.
        
               | titzer wrote:
               | > Jargon that builds on intuition can be its own problem.
               | 
               | Sure it can, which is why you gotta be double-careful
               | naming things and not try to take metaphors too far. A
               | jargon term needs to crisply identify the crux of the
               | concept and not confuse with irrelevant or misleading
               | details.
        
               | greggyb wrote:
               | > A jargon term needs to crisply identify the crux of the
               | concept and not confuse with irrelevant or misleading
               | details.
               | 
               | Agreed. I've never seen a vernacular term fill this role
               | well.
               | 
               | If you need to learn the technical concepts either way to
               | be effective, might as well give them a name that _doesn
               | 't_ conflict with another definition most people know.
        
               | titzer wrote:
               | I think "binary tree" is a decent example. It's not only
               | a visual depiction of how the data structure is laid out,
               | but the metaphor of "leaves" does also transfer over. It
               | is possible to take it too far, trying to fit "bark" into
               | the concept, which is of course, silly. Calling it a
               | "dubranchion" or some such would be a disaster, IMHO.
        
           | wruza wrote:
           | int is neither 32 nor 64. Its width corresponded to a
           | platform's register width, which is now even more blurred
           | because today's 64 bit is often too big for practical use and
           | CPUs have separate instructions for 16/32/64 bit operations,
           | and we agreed that int should be likely 32 and long 64, but
           | the latter depends on a platform ABI. So ints with modifiers
           | may be 16, 32, 64 or even 128 on some future platform. intN_t
           | are different fixed-width types (see also int_leastN_t,
           | int_mostN_t, etc in stdint.h; see also limits.h).
           | 
           | Also, don't forget about short, it feels so sad and alone!
        
           | zokier wrote:
           | > Microsoft's WORD/DWORD are nearly as bad. Don't call
           | something a "word" if it doesn't store characters.
           | 
           | "Word" as a term has been in the wide use since at least
           | 50s-60s, you can't really blame MS for that
           | 
           | https://en.wikipedia.org/wiki/Word_(computer_architecture)
        
           | kps wrote:
           | (a) FORTRAN used 'DOUBLE PRECISION' since the '50s, so
           | 'double' would be immediately obvious.
           | 
           | (b) Many important machines had word sizes that were not a
           | multiple of 8.
        
           | elvis70 wrote:
           | That made me curious. From section 2.2 of the 2nd edition of
           | K&R, 'long' is not a type but a qualifier that applies to
           | integers (not floats though), so you can declare a 'long int'
           | type if you prefer.
        
           | iasmseanyoung wrote:
           | Yes, int_16/int_32 or something like that makes a lot more
           | sense. Today, not when this compiler was written.
           | 
           | The PDP-9, PDP-10, and PDP-18 have 18 bits registers. The
           | world had not settled on 16/32/64 bits at all.
           | 
           | Even the intel 80286 far/fat pointers are 24 bits.
        
             | doctor_eval wrote:
             | Unsure why you're being downvoted, IIRC the original C
             | programmers reference spoke explicitly about how "int"
             | meant the most efficient unit of storage on the target
             | machine.
             | 
             | Admittedly I read that more than 30 years ago :-O
        
               | fanf2 wrote:
               | An int in C was 16 bits until about 1980 when Unix
               | started being ported to larger machines. C and Unix were
               | originally just for the PDP11.
        
               | kps wrote:
               | Unix was _originally_ written for an 18-bit machine.
        
               | fanf2 wrote:
               | That was before C which is what we are talking about.
        
               | skissane wrote:
               | As this paper [0] explains, the initial version of the C
               | compiler for PDP-11 Unix was finished in 1972. And less
               | than a year later (1973), people had ported the C
               | compiler (but not Unix) to Honeywell 6000 series
               | mainframes, and shortly thereafter to IBM 370 series
               | mainframes as well. (Note the text of the paper says "IBM
               | 310" in a couple of places - that's a typo/transcription
               | error for "370".) Both were "larger machines" - the
               | Honeywell 6000 had 36 bit integer arithmetic with 18 bit
               | addressing; the IBM 370 had 32 bit integer arithmetic
               | with 24 bit addressing.
               | 
               | Alan Snyder's 1974 masters thesis [1] describes the
               | Honeywell 6000 GCOS port in some detail. In 1977, there
               | were three different ports of Unix underway - Interdata
               | 7/32 port at Wollongong University in Australia,
               | Interdata 8/32 port at Bell Labs, and IBM 370 mainframe
               | port at Princeton University - and those three had C
               | compilers too.
               | 
               | [0] https://www.bell-labs.com/usr/dmr/www/portpap.pdf
               | 
               | [1] https://apps.dtic.mil/dtic/tr/fulltext/u2/a010218.pdf
               | (his actual thesis was submitted to MIT in 1974; this PDF
               | is a 1975 republication of his thesis as an MIT Project
               | MAC technical report)
        
               | skissane wrote:
               | Here's something cool: the source code to Snyder's
               | compiler: https://github.com/PDP-10/Snyder-C-compiler
        
               | skissane wrote:
               | C's type naming had real value when it was first
               | designed, at a time when the industry hadn't yet fully
               | standardised on the 8-bit byte, 32/64-bit words, IEEE
               | floating point, etc.
               | 
               | The fact that "int" could be 16-bits on a PDP-11, 32 on
               | an IBM 370, 36 on a PDP-10 or Honeywell 6000 - that was a
               | real aid for portability in those days.
               | 
               | But nowadays, that's really historical baggage that
               | causes more problems than it solves, yet we are stuck
               | with it. I think if one was designing C today, one would
               | probably use something like
               | i8,i16,i32,i64,u8,u16,u32,u64,f32,f64,etc instead.
               | 
               | When I write C code, I use stdint.h a lot. I think that's
               | the best option.
        
           | Symbiote wrote:
           | It could not be clearer that you didn't read the page
           | referenced by the comment you replied to.
           | 
           | "long" was commented _out_.
        
           | bpgate wrote:
           | No, the names are fine and self evident after glancing
           | through K&R for 15 min.
           | 
           | The real mistake in retrospect is that _int_ and _long_ are
           | platform dependent. This is an amazing time sink when writing
           | portable programs.
           | 
           | For some reason C programmers looked down on the exact width
           | integer types for a long time.
           | 
           | The base types should have been exact width from the start,
           | and the cool sounding names like _int_ and _long_ should have
           | been typedefs.
           | 
           | In practice, I consider this a larger problem than the often
           | cited _NULL_.
        
             | jeffrallen wrote:
             | And that creat has no e on the end.
        
               | Koshkin wrote:
               | It's a perfectly good word in Romanian.
        
             | flohofwoe wrote:
             | It made more sense in an era when computers hadn't settled
             | on 8-bit bytes yet. A better idea (not mine) is to separate
             | the variable type from the storage type. There should be
             | only one integer variable type with the same width as a CPU
             | register (e.g. always 64-bit on today's CPUs), and storage
             | types should be more flexible and explicit (e.g. 8, 16, 32,
             | 64 bits, or even any bit-width).
        
           | innocenat wrote:
           | Float doesn't make sense either. What is floating?
           | 
           | (I know it's floating point, but it's the same as
           | long/double).
        
             | layer8 wrote:
             | String doesn't make sense either. But that's how words
             | acquire new meanings.
        
               | bregma wrote:
               | It's short for "Hollerith string". Nobody wants to type
               | out that man's name every time they want to deal with the
               | data type. Also, most programmers know zero about
               | computer science.
        
               | layer8 wrote:
               | That seems to be inaccurate. According to Wikipedia,
               | string constants in FORTRAN 66 were named in honor of
               | Hollerith, and the actual wording in the standard is:
               | "4.2.6 Hollerith Type. A Hollerith datum is a string of
               | characters. This string may consist of any characters
               | capable of representation in the processor. The blank
               | character is a valid and significant character in a
               | Hollerith datum." Apparently the term "string of
               | characters" is assumed to be self-explanatory here, and
               | independent of the "Hollerith" nomenclature. The
               | connection to Hollerith is via punched cards, for which
               | the _encoding_ of characters as bit patterns (hole
               | patterns) was defined; but Hollerith doesn't seem to be
               | directly related to the concept of character strings as
               | such.
               | 
               | It is probably rather by chance that we ended up with the
               | term "string (of characters)", as opposed to for example
               | "sequence of characters". In a different universe we
               | might be talking about charseqs (rhymes with parsecs)
               | instead of strings.
        
               | OGWhales wrote:
               | > Also, most programmers know zero about computer
               | science.
               | 
               | What made you say that?
        
               | Koshkin wrote:
               | I have known a very good programmer, I'd say one of the
               | best I have met, and he had extremely, surprisingly
               | little knowledge of computer science and math (not having
               | a formal education may have been a contributing factor).
               | He coded in JS and Ruby.
        
               | Koshkin wrote:
               | Well, 'character string' could, too, make a strange
               | impression on an uninitiated.
        
           | _kst_ wrote:
           | > It makes sense long would have needed a comment.
           | 
           | I think you misunderstood. There's no explanatory comment.
           | The "long" keyword is commented _out_ , meaning that it was
           | planned but not yet implemented.                   ...
           | init("int", 0);                 init("char", 1);
           | init("float", 2);                 init("double", 3);
           | /*      init("long", 4);  */                 init("auto", 5);
           | init("extern", 6);                 init("static", 7);
           | ...
        
           | [deleted]
        
           | coliveira wrote:
           | In C, long is not the name of a data type, it is a modifier.
           | It turns out that C standard type is integer, so if you say
           | long without another data type (such as double, for example),
           | this means long int.
        
       | cptnapalm wrote:
       | For the hobbyists and the curious using 2.11 BSD, its C compiler
       | is the end of the line for development of the Ritchie C compiler,
       | as far as I know.
        
       | bullen wrote:
       | So how do you "bootstrap" compile this? I mean without cheating,
       | say on a rebuilt computer after all computers where destroyed?
        
         | flyinghamster wrote:
         | Hand-compile it for the initial bootstrap would be one way to
         | go. That, or write a minimal C in assembler, then make it self-
         | hosting, then expand it into the full implementation.
         | 
         | Edit: Elsewhere in-thread, retrac posted a detailed summary of
         | how C developed from B.
        
       | bumbada wrote:
       | It is very interesting how many hardcoded magic numbers it has.
       | No headers and defines because they did not existed yet?.
       | 
       | The full compiler is super compressed. Hundreds of lines per
       | file. It would be great if there was an explanation of the
       | general idea of the design somewhere.
        
         | Cthulhu_ wrote:
         | I'm only seeing a few thousand lines of code, so I think it
         | would fit in someone's head easily enough. Might be the numbers
         | were on paper.
        
       | dboreham wrote:
       | Brings back some memories because this was the first "large"
       | program available to me for study when I was first learning to
       | program, around 1978.
       | 
       | Having talked my way into using the local university EE dept's
       | 11/45, I found the source tree was mounted (they had a 90MB CDC
       | "washing machine" drive) and decided to print it out on the
       | 132-col Tally dot-matrix printer.
       | 
       | Some minutes into this, the sysadmin bursts into the terminal
       | room, angrily asking "who's running this big print job".
       | 
       | I timidly raise my hand. He asks what I'm printing. I tell him
       | the C compiler source code because I want to figure out how it
       | works. He responds "Oh, that's ok then, no problem, let me know
       | if you need more paper loaded or a new ribbon".
        
       | rightbyte wrote:
       | This is gold. I like how the files are named 00 01 10 11 because
       | long filenames are scary.                   hshsiz 100;
       | hshlen 800; /* 8*hshsiz */         hshtab[800];
       | 
       | These were at file scope. I assume they default to int, but when
       | was the demand for = added?
        
         | wott wrote:
         | For those who wonder, the extract comes from
         | https://github.com/mortdeus/legacy-cc/blob/ccbe90a2803e2cc7e...
         | 
         | IMO, it is close to Assembly:
         | 
         | * you reserve space and possibly set an original value with
         | "hshsiz DB 100" or "paraml DB ?"
         | 
         | * assignment is a different business which involves a runtime
         | instruction (MOV)
         | 
         | Hence the same difference (no = sign for the first, passive,
         | compile-time operation; an = sign for the second, active,
         | runtime operation) in this proto-C.
         | 
         | (Of course, this doesn't answer your question of "when" did the
         | syntax of those 2 operation fuse :-) )
        
         | kps wrote:
         | Long filenames are scary when your system has a 2.5MB disk.
        
       | dibyendu wrote:
       | I tried to find the last version that Dennis wrote: my findings
       | are here:
       | 
       | https://github.com/dibyendumajumdar/C
        
       | userbinator wrote:
       | Previous discussion:
       | 
       | https://news.ycombinator.com/item?id=14669709
       | 
       | https://news.ycombinator.com/item?id=5748672
        
       | jb1991 wrote:
       | well, this sure looks wasteful:
       | 
       | https://github.com/mortdeus/legacy-cc/blob/master/prestruct/...
        
         | tyingq wrote:
         | Explanation: https://news.ycombinator.com/item?id=5748762
        
           | lisper wrote:
           | Why not just:
           | 
           | char waste[however-many-bytes-are-needed];
           | 
           | ?
        
             | TonyTrapp wrote:
             | Can't say for sure if it's the reason in this particular
             | situation, but that would require dynamic memory
             | allocation, and while it may seem backwards to reserve more
             | memory than potentially needed on old memory-constrained
             | systems, it is a pattern you see very frequently because on
             | those systems, you actually know exactly how much memory
             | you have. As a result, you know exactly how much memory you
             | can "waste".
             | 
             | Especially on single-tasking systems, it doesn't matter how
             | much memory you waste, because no other program is affected
             | by it.
             | 
             | Or in other words: If you know you are guaranteed to have x
             | KB of memory available and no other program can steal it,
             | and you know that you don't need more than y KB, then why
             | allocate up to y KB dynamically when you can just straight-
             | up allocate y KB statically, which is less work?
        
               | fanf2 wrote:
               | External arrays are static, they do not involve any
               | dynamic allocation.
        
               | TonyTrapp wrote:
               | It's not clear from the question whether GP just wonders
               | about the strange syntax used to reserve the space or
               | about allocating a fixed amount of memory. The "however-
               | many-bytes-are-needed" part sounded to me like they
               | thought that a dynamic amount of memory should be
               | allocated.
        
               | swiley wrote:
               | IMO the way C programmers avoid dynamic memory allocation
               | because it's so painful is probably the best feature of
               | the language.
        
             | IncRnd wrote:
             | That's allocated in a different segment.
        
               | lisper wrote:
               | It is now. Was it then? AFAICT from
               | https://en.wikipedia.org/wiki/PDP-11 none of the PDP-X
               | machines had a segmented architecture.
        
               | IncRnd wrote:
               | Even so, https://sourceware.org/binutils/docs/as/PDP_002d
               | 11_002dPseud....                 9.34.2 Assembler
               | Directives       The PDP-11 version of as has a few
               | machine dependent       assembler directives.
               | .bss       Switch to the bss section.            ...
        
       | amyjess wrote:
       | I have to say, the way indentation and brackets were done here
       | looks like it's just inviting subtle bugs. Take this for example:
       | if (peekc) {           c = peekc;           peekc = 0;          }
       | else           if (eof)            return(0); else            c =
       | getchar();
        
         | yitchelle wrote:
         | It would have made code review a nightmarish activity for the
         | team.
        
           | wruza wrote:
           | Why nightmarish? A reviewer may explain that it is prone for
           | other human to overlook the end of conditional and go sleep
           | as usual. I never understood the emotional component of
           | blaming someone's _personal_ code styles, as if it were a
           | religion with sacrifices and blasphemy instead of just a
           | practical way of coding in a heterogeneous team.
           | 
           | This triggers me because many people jump on "bad c0de" in
           | the forums, but then you read some practical code on github,
           | and it is (a) not as perfectly beautiful as they imagine at
           | all and (b) is still readable without nightmares they
           | promised and (c) the algorithms and structure itself requires
           | programmer's perception and understanding levels far beyond
           | the "it's monday morning so i feel like missing an end of
           | statement in a hand-written scanner" anyway.
        
         | code_sloth wrote:
         | If you judge the coding style of the early 1970s with modern
         | standards, it isn't going to look great. 50 years is a loooong
         | time.
         | 
         | dmr was one of, if not _the_ first C programmer(s).
        
           | kiwidrew wrote:
           | And he was almost certainly using ed(1) as his editor and a
           | mechanical teletype at 7.5 or 10.0 characters per second as
           | his terminal...
           | 
           | The C language (and all of Unix) was designed to be very
           | terse as a consequence.
        
             | Koshkin wrote:
             | I try ed(1) once in a while and I find it pretty usable
             | (and even rather efficient if you know what you are doing).
             | cat(1) also works if you just want to type a new text.
             | 
             | Speaking of terseness, I _love_ the the fact that C does
             | not have  'fn'.
        
               | rootbear wrote:
               | We used to speak of a great Unix systems programmer as
               | someone who could write device drivers with cat and have
               | them compile and run the first time.
        
               | siltpotato wrote:
               | Before I look up `man cat`, what can you do with `cat`
               | other than just see what's in a file?
        
               | Crespyl wrote:
               | When not given a file, cat will just read from stdin, so
               | you can use "cat > file.c", write some text, and send EOF
               | with ^D when you're done.
               | 
               | Obviously, there's no way to go back and edit anything
               | mid-stream, you have to write the whole thing out in one
               | shot.
        
               | Koshkin wrote:
               | The backspace does work within the line.
        
             | oblio wrote:
             | That period lasted what, 10 years after Unix was created?
             | And we'll be stuck with those decisions decades if not
             | centuries.
             | 
             | Similar story with the design of QDOS / MS-DOS / Windows
             | and nowadays with Android. Both designed for super
             | underpowered machines that basically went away less than a
             | decade after they were launched and that will be hobbled
             | because of those early decisions for a long, long time.
        
               | compiler-guy wrote:
               | We will be hobbled with these decisions for a long time
               | precisely because the complete package of trade offs the
               | designers made were so successful.
               | 
               | If they had gone for wart-free on properly powered
               | hardware, they would be stuck back in Multics land or
               | living with the gnu Hurd--cancelled for being over budget
               | or moving so slowly that projects that actually
               | accomplish what the users need overtake them.
               | 
               | Do I wish that C had fixed its operator precedence
               | problem? Sure. But the trade offs as a total package make
               | a lot of sense.
        
               | colejohnson66 wrote:
               | Is there an explanation on _why_ C's operator precedence
               | is weird? Such as: why does the bitwise AND have higher
               | precedence than logical AND?
        
             | tralarpa wrote:
             | Was it different for the designers of ALGOL/SIMULA/Pascal?
        
               | kiwidrew wrote:
               | Yeah, those languages were IIRC designed to be edited
               | offline (as a deck of punch cards) and submitted to a
               | mainframe via high-speed card reader as a batch job.
        
               | tralarpa wrote:
               | Very interesting when you think about it. A language
               | created in 2009 (Go) owes its syntax to a language from
               | 1969 (B), and the latter looks like it does because it
               | was designed during a short transition period between
               | offline editing (1960s) and electronic terminals (1970s).
               | 
               | And there are people claiming that computer scientists
               | are not conservative :)
               | 
               | To what extend this explanation is correct is another
               | question... The article by Denis Richie says "Other
               | fiddles in the transition from BCPL to B were introduced
               | as a matter of taste, and some remain controversial, for
               | example the decision to use the single character = for
               | assignment instead of :=".
               | 
               | It's a kind of butterfly effect :) Mr. Richie prefered
               | "=" over ":=" and fifty years later a server crashes
               | somewhere because somebody wrote a=b=c instead of a=b==c.
        
               | ktpsns wrote:
               | Actually the transition from "offline editing" and
               | "electronic terminals" was not short at all. Teletypes
               | (aka "typewriters which can recieve content encoded in
               | electricity, next to the user keyboard") date back way
               | beyond computers, and were still in use in the 1980s (but
               | evventually superseded by fax). Teletypes were cheaper,
               | faster and more convenient then video terminals. Don't
               | underestimate of having a printout of your session,
               | especially when being online (i.e. connected to the
               | mainframe or mini computer) is something valuable and
               | your terminal is "dumb" and has no storage (except
               | paper).
        
               | amyjess wrote:
               | And for a lot of people, the lightbulb goes off once they
               | realize what 'tty' stands for...
        
               | Wildgoose wrote:
               | My first usage of a computer was on a printed teletype.
               | My last such use was probably around 1985. They were
               | around for a long time.
        
         | rightbyte wrote:
         | If you can only read it line by line:
         | return(0); else
         | 
         | makes a bit of sense.
        
         | bawolff wrote:
         | I dont think it would look that out of place if he was using
         | the ternary operator which is the same thing after all.
         | 
         | E.g.:                 if (peekc) {         c = peekc;
         | peekc = 0;       } else         eof ?           return(0) :
         | c = getchar();
         | 
         | The first else clause sill looks weird, but the final part
         | isn't nearly as out of place (well i guess assigning in a
         | ternary would be weird, but in terms of indentation) and its
         | not like we actually changed anything.
        
           | andreareina wrote:
           | Can't return in a ternary.
        
             | amelius wrote:
             | Correct, return is not an expression. But then again, he
             | could if he wanted to, as the language designer ;)
        
               | Koshkin wrote:
               | Wouldn't it be wonderful if we could write
               | a = return b;
        
               | colejohnson66 wrote:
               | What would that even do? Return b, but then set b to a
               | right before "deleting" a? That would serve no purpose.
        
               | Maken wrote:
               | Maybe it was not worth the extra work.
        
         | amw-zero wrote:
         | The difference between Dennis Ritchie and the average
         | programmer of today is, Dennis Ritchie did not write bugs in
         | the first place.
        
           | Koshkin wrote:
           | Well, some say (I disagree) that C is a bug.
        
       | neatze wrote:
       | It is surreal feeling when looking at first code, not sure how to
       | explain why it is the case.
        
         | inopinatus wrote:
         | I felt the same upon seeing an actual Dead Sea Scroll at the
         | Jordan Museum in Amman.
         | 
         | The feeling dissipated somewhat when our guide explained that
         | it's a treasure map
        
       | RcouF1uZ4gsC wrote:
       | Very interesting. Does anyone have any idea how the C compiler
       | was bootstrapped. Was it first written in B, or was it written in
       | PDP-11 assembler?
        
         | QuantumG wrote:
         | Flint knives and bear skins.
        
           | dboreham wrote:
           | Abacus
        
         | AntiRush wrote:
         | The basic sequence was:
         | 
         | - Rewrite B compiler in B (generating threaded code)
         | 
         | - Extend B to a language Ritchie called NB (new B). This
         | compiler generated PDP assembly There is no version of the NB
         | compiler known to exist.
         | 
         | - Continue extending NB until it became the very early versions
         | of C.
         | 
         | You can read the longer version of this history here:
         | 
         | https://www.bell-labs.com/usr/dmr/www/chist.html
        
         | 0x003 wrote:
         | I think it was written in B as Ritchie extended B for the
         | PDP-11. By that point the B compiler was written in B
         | 
         | https://sci-hub.do/10.1145/155360.155580
        
           | EGreg wrote:
           | Real programmers use butterflies
        
             | macksd wrote:
             | A reference to https://xkcd.com/378/, for those wondering.
        
         | retrac wrote:
         | It was written in B. And B was written in B. To trace the
         | bootstrap up into the high level, you have to go further back
         | than the PDP-11. To bootstrap B on the PDP-7 and GE-635
         | machines he had access too, Ritchie wrote the minimum subset
         | required to compile a compiler in B, in a language known as TMG
         | (in the vein of, and a big influence on, Yacc and similar).
         | This minimal bootstrap was then used to compile a B compiler
         | written in B, and further development was self-hosted.
         | 
         | Later, the language would be retargeted to the PDP-11 while on
         | the PDP-7. Various changes, like byte-addressed rather than
         | word-addressed memory, led to it morphing into C after it was
         | moved. There was no clear line between B and C -- the language
         | was self-hosting the whole time as it changed from B into C.
         | 
         | Mr. Ritchie wrote a history from his perspective published in
         | 1993. I've mostly just summarized it above. It's available
         | here:
         | https://web.archive.org/web/20150611114355/https://www.bell-...
        
           | systemvoltage wrote:
           | When people say bootstrapping, is this how all computer
           | languages came to be? Or there has been multiple attempts at
           | bootstrapping? What I'm getting at is whether all languages
           | have a single root.
        
             | musicale wrote:
             | Interesting article on how the original CDC 6000 Pascal
             | compilers were bootstrapped (including the scanned source
             | code listings as PDFs!?!):
             | 
             | http://pascal.hansotten.com/niklaus-wirth/cdc-6000-pascal-
             | co...
             | 
             | "The method used to create the first Pascal compiler,
             | described by U. Ammann in The Zurich Implementation, was to
             | write the compiler in a subset of unrevised Pascal itself,
             | then hand-translate the code to SCALLOP, a CDC specific
             | language. The compiler was then bootstrapped, or compiled
             | using the Pascal source code and the SCALLOP based
             | compiler, to get a working compiler that was written in
             | Pascal itself. Then, the compiler was extended to accept
             | the full unrevised Pascal language."
        
             | rzzzt wrote:
             | Bootstrapping can also get recursive, eg. GCC and binutils
             | are bootstrapped by compiling their sources with the GCC
             | you already have on your build system; the result of this
             | is an intermediary compiler, which is then used to compile
             | the sources of itself again. (I should look up the
             | following bit, but IIRC, the second generation result
             | compiles the sources a third time, and the last two outputs
             | are compared -- they should be equal, barring any non-
             | deterministic optimizations.)
        
             | yiyus wrote:
             | Chuck Moore is an interesting example of someone who has
             | bootstrapped several languages without touching a C
             | compiler. He has written systems directly in machine code,
             | and has gone as far as designing his own chips to directly
             | run Forth and ColorForth.
        
             | pabs3 wrote:
             | Some languages have multiple implementations in different
             | languages. The Bootstrappable Builds folks are working on
             | proper bootstrap for everything.
             | 
             | https://bootstrappable.org/
             | https://bootstrapping.miraheze.org/wiki/Main_Page
        
             | retrac wrote:
             | Yes, bootstrapping with regard to languages is the trick of
             | getting that first compiler running so you can compile the
             | rest of the compiler.
             | 
             | It has been done many times. The first assemblers were
             | written directly in machine language. The first compilers
             | were written in assembly. Many implementations of FORTRAN,
             | ALGOL, COBOL, etc. As late as the 1970s it was not unknown
             | to write a new high level language directly in machine
             | code. Steve Woz's BASIC for the Apple II was "hand-
             | assembled", as he put it.
             | 
             | So, taken literally, certainly not. People still do it
             | today as a hobby or educational project.
             | 
             | But if we take the question in a looser sense? Yes kind of,
             | at least in the UNIXish world. No one has implemented a
             | serious high level systems language, except in a high level
             | systems language, for a long time now. Rust, for example,
             | was initially implemented in Ocaml. And normally that's
             | what would be called the first Rust bootstrap. But OCaml
             | was implemented in C, probably compiled by Clang or GCC.
             | GCC was written in C and... so on.
             | 
             | Often one finds it does lead back to DMR at a PDP-7. On the
             | other hand, I strongly suspect something like IBM's COBOL
             | compiler for their mainframes (still supported and
             | maintained today!) would not have such a heritage.
        
               | divs1210 wrote:
               | > No one has implemented a serious high level systems
               | language, except in a high level systems language, for a
               | long time now.
               | 
               | LuaJIT is a prominent counterexample. The base
               | interpreter in written in assembly for performance. It
               | comes with its own tradeoffs, especially portability.
        
               | [deleted]
        
               | wahern wrote:
               | LuaJIT uses it's DynASM library for both static and JIT
               | code generation. DynASM is implemented in a mixture of
               | Lua and C, and Lua is of course implemented using C. So
               | LuaJIT actually depends on a C compiler to generate
               | assembly. Plus, not all of LuaJIT is implemented using
               | assembly, only some critical hotspots (e.g. the bytecode
               | interpreter loop). The rest is just C.
               | 
               | DynASM is actually really cool.
               | 
               | I almost forgot: apropos bootstrapping, because LuaJIT
               | requires Lua to build, it includes a single-file,
               | stripped down version of PUC Lua 5.1 which it can build
               | to bootstrap itself if the host lacks a Lua interpreter.
        
               | jashmatthews wrote:
               | LuaJIT 1.x uses DynASM for JIT but LuaJIT 2.x doesn't and
               | instead uses the IR to ASM compiler in
               | https://github.com/LuaJIT/LuaJIT/blob/v2.1/src/lj_asm.c
               | 
               | A program using DynASM doesn't depend on Lua or a C
               | compiler to generate assembly at runtime but you need
               | both to build it.
        
               | monkeybutton wrote:
               | IBM's COBOL was implemented in PL/X, which traces its
               | heritage to PL/S. PL/S itself was developed as a
               | replacement for using assembler.
        
               | systemvoltage wrote:
               | Fascinating and inspiring, thank you for taking the time
               | to distill it so clearly.
        
               | [deleted]
        
               | musicale wrote:
               | > Steve Woz's BASIC for the Apple II was "hand-
               | assembled", as he put it.
               | 
               | Very cool - so basically (haha) Woz's integer BASIC was
               | bootstrapped by writing it in assembly language and
               | translating it into machine code by hand.
               | 
               | I wonder if someone (Woz?) has written a 6502 assembler
               | in integer BASIC to allow it to bootstrap itself?
        
               | rob74 wrote:
               | I'm not an expert, but I guess "bootstrapping" only
               | applies to _compilers_ , and Apple II BASIC was an
               | _interpreter_. An interpreter doesn 't have to compile
               | itself, only run the programs you give it. So on an 8-bit
               | computer the priority is to have an implementation that
               | (a, and most importantly) takes up as little space as
               | possible and (b) is reasonably fast.
        
               | [deleted]
        
               | sn41 wrote:
               | There are metacircular interpreters, like in Scheme (see
               | SICP [1]). But this is rare, compared to bootstrapping
               | compilers.
               | 
               | [1]
               | https://mitpress.mit.edu/sites/default/files/sicp/full-
               | text/...
        
               | wazoox wrote:
               | The Apple ][ has a monitor in ROM that allows to enter
               | machine code directly. The legend says that for the Apple
               | I, Woz knew the complete integer basic machine code and
               | could type it live into the monitor.
        
               | flyinghamster wrote:
               | Also, the monitor on pre-][+ machines with integer BASIC
               | also had a mini-assembler, so short assembly programs
               | could be typed in as such instead of keying in the bytes.
               | Both versions of the monitor had a mini-disassembler.
               | 
               | On the other hand, I still remember at least a few 6502
               | hex opcodes, not that I have any use for that information
               | anymore. The instruction set is small enough that it
               | doesn't surprise me that Woz would have it memorized.
        
               | compiler-guy wrote:
               | I'm not aware of any basic that is implemented in itself.
               | There must be one or two somewhere, but typically for
               | systems like the apple ii or Commodore PET, basic was
               | implemented always in assembly.
               | 
               | So most weren't exactly bootstrapped the way we are
               | talking here.
        
             | brianpan wrote:
             | I don't know if I'm stating the obvious, but you only need
             | to bootstrap if you're writing a compiler in the language
             | it's compiling. So any language compiler written in a
             | different language isn't bootstrapped.
             | 
             | Even if you're using a loose definition of "root" as in a
             | parent language is any language involved in writing another
             | language, I doubt there is one root. There are certainly
             | have been languages and computer architectures (with
             | assembly languages) that are independent islands.
        
           | pabs3 wrote:
           | I like that the Bootstrappable Builds folks are working on a
           | bootstrap process that goes from a small amount of machine
           | code (~512 bytes) all the way up to a full Linux distro,
           | including compilers/interpreters for modern languages.
           | 
           | https://bootstrappable.org/
        
             | kiwidrew wrote:
             | Nice, I hadn't heard of this project before!
             | 
             | In particular BOOTSTRA [1] looks really fun. I have also
             | toyed with the idea of using MS-DOS 3.30 as a guaranteed-
             | ubiquitous build environment.
             | 
             | It comes with a filesystem, a text editor (EDLIN.EXE), an
             | object file linker (yup!), a debugger/assembler (DEBUG.EXE
             | is an amazing tool), a programming language with decent
             | string handling (GWBASIC.EXE), and a command interpreter
             | with batch file scripting to glue it all together.
             | 
             | Not sure I would write the assembler as batch files though,
             | that is really hardcore. :)
             | 
             | That entire build environment would fit on a single 360KB
             | floppy.
             | 
             | [1] https://github.com/mniip/BOOTSTRA
        
               | pabs3 wrote:
               | I don't think that BOOTSTRA is in any way involved in the
               | process bootrappable.org are working on, which starts
               | with hex0 (the 512B machine code binary seed), proceeds
               | through a ton of layers and eventually reaches non-
               | interactive bash.
               | 
               | https://github.com/fosslinux/live-
               | bootstrap/blob/master/part...
        
               | pwdisswordfish0 wrote:
               | What is "guaranteed-ubiquitous" about DOS 3.30?
        
       | andi999 wrote:
       | So do I get this right: this is not the first C compiler (since
       | that one would be written in B) and the first C compiler written
       | in C?
        
         | Jeema101 wrote:
         | Thank you for pointing this out. It obviously can't be his
         | first C compiler because it's written in C! :)
         | 
         | I'm not even sure it's the first C compiler written in C,
         | though - it just says in the github description "the very first
         | c compiler known to exist in the wild."
         | 
         | Regardless, if it's from 1972 it's a very early version.
        
           | mywittyname wrote:
           | > Thank you for pointing this out. It obviously can't be his
           | first C compiler because it's written in C! :)
           | 
           | This isn't obvious to me.
           | 
           | I just assumed that the first iteration was compiled by hand
           | to bootstrap a minimum workable version. Then the language
           | would be extended slightly, and that version would be
           | compiled with the compiler v. n-1 until a full-feature
           | compiler is made.
           | 
           | It makes sense to write a compiler in a different language,
           | but given the era, I could see hand-compilation still being a
           | thing.
        
       ___________________________________________________________________
       (page generated 2021-03-11 23:03 UTC)