3
arp242 6 days ago

Gotta love the user-friendliness of these old Unix tools:

  if (argc<4) {
      error("Arg count");
      exit(1);
  }

Rendello 6 days ago

SQLite error messages are similarly spartan. I wrote a SQLite extension recently and didn't find it difficult to have detailed/dynamic error messages, so it may have just been a preference of the author.

Amlal 6 days ago

Ah, yes, was that because of a lack of inline assembly? I feel like these could be replaced by 'nop' operations.

johnisgood 6 days ago

What is the point of it?

aap_ 6 days ago

It's an awkward way to reserve memory. The important detail here is that both compiler phases do this, and the way the programs are linked guarantees that the reserved region has the same address in both phases. Therefore an expression tree involving pointers can be passed to the second phase very succinctly. Not pretty, no, but hardware limitations force you to do come up with strange solutions sometimes.

colejohnson66 6 days ago

Here's the actual code that references the 'ospace' from before 'waste': https://github.com/mortdeus/legacy-cc/blob/936e12cfc756773cb...

johnisgood 6 days ago

Thank you! Is it relevant today at all, or is there an use-case for it today?

aap_ 6 days ago

No, if you need fixed addresses i suppose a linker script would be the way to go? Or in this case you'd just serialize the data such that it doesn't contain any pointers in the first place.

ddulaney 6 days ago

If you even can with ASLR. Most modern boxes would disable stuff like this.

mananaysiempre 6 days ago

There are better tools to do this these days—with the GNU toolchain, for example, you’d use a linker script and make sure you’re building a non-position-independent static executable. Alternatively, you could use self-relative pointers: instead of having foo_t *foo and putting p there, have ptrdiff_t foo and put ((char *)p - (char *)&foo) there.

fxtentacle 6 days ago

It's an obscure way to statically allocate memory for the ospace pointer.

account42 5 days ago

What's the advantage over an array though, which would allow you to better control the size without making assumptions about code generation.

edit: http://cm.bell-labs.co/who/dmr/primevalC.html (linked from another comment has the answer):

> A second, less noticeable, but astonishing peculiarity is the space allocation: temporary storage is allocated that deliberately overwrites the beginning of the program, smashing its initialization code to save space. The two compilers differ in the details in how they cope with this. In the earlier one, the start is found by naming a function; in the later, the start is simply taken to be 0. This indicates that the first compiler was written before we had a machine with memory mapping, so the origin of the program was not at location 0, whereas by the time of the second, we had a PDP-11 that did provide mapping. (See the Unix History paper). In one of the files (prestruct-c/c10.c) the kludgery is especially evident.

So I guess it has to be a function in order to be placed in front of main() so the buffer can overflow into the no longer needed code at the start of it.

rasjani 6 days ago

Without actually knowing, i'd guess that would generate bytecode's that could be modified later by patching the resulting binary ?

I remember few buddies using similar pattern in ASM that just added n NOP's into code to allow patching and thus eliminating possible recompilation..

ChrisMarshallNY 6 days ago

I suspect that’s it.

There was a lot of self-modification, going on, in those days. Old machine language stuff had very limited resources, so we often modified code, or reused code space.

agumonkey 6 days ago

warm up the stack ? (no idea to be honest)

tanelpoder 6 days ago

The C alternative for the hardware "halt and catch fire" instruction?

kps 6 days ago

The C alternative for the Fortran COMMON block.