#!/bin/sh set -eu base="${TMPDIR-/tmp}/mcpu-cpp-pragma-once-$$" mkdir -p "$base" trap 'rm -rf "$base"' EXIT HUP INT TERM cat > "$base/once.h" <<'EOT' #pragma once ONCE_BODY EOT ln -s once.h "$base/once-link.h" ln "$base/once.h" "$base/once-hard.h" cat > "$base/self.h" <<'EOT' #pragma once SELF_BEGIN #include "self.h" SELF_END EOT cat > "$base/inactive.h" <<'EOT' #if 0 #pragma once #endif INACTIVE_BODY EOT cat > "$base/main.c" <<'EOT' #include "once.h" #include "once.h" #include "once-link.h" #include "once-hard.h" #include "self.h" #include "inactive.h" #include "inactive.h" #pragma pack(push, 1) EOT "$MCPU_CPP" --no-config "$base/main.c" -o "$base/out" # The same physical file is processed only once, even through a symbolic link # and a hard link. #pragma once itself is consumed by the preprocessor. test "$(grep -c '^ONCE_BODY$' "$base/out")" -eq 1 ! grep '^#pragma once$' "$base/out" >/dev/null # Marking happens as soon as the active directive is seen, so a file may safely # include itself after #pragma once without recursive inclusion. test "$(grep -c '^SELF_BEGIN$' "$base/out")" -eq 1 test "$(grep -c '^SELF_END$' "$base/out")" -eq 1 # An inactive #pragma once has no effect. test "$(grep -c '^INACTIVE_BODY$' "$base/out")" -eq 2 # Other pragmas are not consumed; they remain available to the later compiler. grep '^#pragma pack(push, 1)$' "$base/out" >/dev/null # -dD does not make #pragma once reappear; unrelated pragmas are still kept. "$MCPU_CPP" --no-config -dD "$base/main.c" -o "$base/dd.out" ! grep '^#pragma once$' "$base/dd.out" >/dev/null grep '^#pragma pack(push, 1)$' "$base/dd.out" >/dev/null # A non-file input stream has no physical identity. The directive is simply # consumed and must not turn stdin preprocessing into an error. printf '#pragma once\nSTDIN_BODY\n' | \ "$MCPU_CPP" --no-config > "$base/stdin.out" grep '^STDIN_BODY$' "$base/stdin.out" >/dev/null ! grep '^#pragma once$' "$base/stdin.out" >/dev/null