I’m writing a C preprocessor (don’t even ask) and it’s horrible. I literally have the c90 and c99 specs in front of me and still keep using clang to preprocess code snippets to see what it does with edge cases. The whole thing has vibes of “write a formal spec that describes this exact awful C program using 50x as much english text as code in the program”. Also “#pragma once” is awful.
@nickappleton re: pragma once: just the impossibility to know whether the same file appears at different paths, or why? (I kind of find it more elegant than classical include guards, and just wished it was implemented based on comparing the file content, unparsedly, i.e., xxhash(file) unequal-> not the same file, else byte-wise comparison)

@funkylab it’s really to do with it not being standardised more than anything else. Like what is the expectation of preprocessing the following file lol.h

#ifndef foo
#define foo
#else
#pragma once
#endif
#include "lol.h"
Yo

Is it a single “Yo” or two lines of “Yo”?

If it was defined that it needed to be the first thing in a file following whitespace, I think i’f be fine with it.

@nickappleton See the point! But the `#if` semantics is sufficiently well defined: your `#else\n#pragma once` must be skipped on first inclusion. Skipped pragmas aren't directives that are encountered, so they don't "do" anything.
Please tell me there's no implementation that only prints one "Yo"! (I can see situations where you want conditional once-only inclusion, for example in single-header libs.)
@funkylab I agree with you about the semantics around if directives in this particular example. The unclear part is the definition of what “#pragma once” actually does. You could argue that in the second processing of the file, when it sees the pragma, it knows that the file is already being processed lower in the file stack. So you could reason: maybe it should abort the processing and assume the file had been processed.
@funkylab But yeah, the more I figure out, the more it seems like the answer to every edge case is: “whatever the easiest thing would be to implement is the answer”
@nickappleton ah interesting angle! But since the preprocessor behaviour (and also wording of the C std) is always immediate (it just either "emits" or "skips" things when something happens), I'd count that as surprise. There's no backtracking in the preprocessor!
@nickappleton yep, exactly, that's the easiest thing.