#!/bin/sh set -eu base="${TMPDIR-/tmp}/mcpu-cpp-include-next-$$" mkdir -p "$base/wrapper" "$base/system" "$base/after" "$base/local" trap 'rm -rf "$base"' EXIT HUP INT TERM cat > "$base/config" < "$base/main.c" <<'EOT' #include #include "local/local.h" #if 0 #include_next #endif EOT cat > "$base/wrapper/wrapped.h" <<'EOT' wrapper_begin #line 500 "virtual/wrapped.h" #define NEXT_WRAPPED #include_next NEXT_WRAPPED wrapper_end EOT cat > "$base/system/wrapped.h" <<'EOT' system_begin #include_next "wrapped.h" system_end EOT cat > "$base/after/wrapped.h" <<'EOT' after_header EOT cat > "$base/local/local.h" <<'EOT' local_header #include_next EOT cat > "$base/wrapper/from_chain.h" <<'EOT' from_chain_wrapper EOT "$MCPU_CPP" --config-file "$base/config" \ -isystem "$base/wrapper" -idirafter "$base/after" \ "$base/main.c" -o "$base/out" # The wrapper header found through -isystem continues into the configured # system include root, then that header continues into -idirafter. The quote # form of #include_next must not re-search the current source directory. awk ' /wrapper_begin/ { a = NR } /system_begin/ { b = NR } /after_header/ { c = NR } /system_end/ { d = NR } /wrapper_end/ { e = NR } END { exit !(a && a < b && b < c && c < d && d < e) } ' "$base/out" # A header found by ordinary quoted-source-directory lookup has no configured # search entry to skip, so include_next begins with the configured chain. grep '^local_header$' "$base/out" >/dev/null grep '^from_chain_wrapper$' "$base/out" >/dev/null # Macro-expanded include_next operands use the same include operand parser. grep '^system_begin$' "$base/out" >/dev/null # Inactive conditional branches must not execute include_next. ! grep 'never.h' "$base/out" >/dev/null # If no later search entry contains the file, include_next is an error rather # than falling back to the directory that supplied the current header. cat > "$base/wrapper/last.h" <<'EOT' #include_next EOT cat > "$base/last-main.c" <<'EOT' #include EOT if "$MCPU_CPP" --config-file "$base/config" \ -isystem "$base/wrapper" "$base/last-main.c" \ -o "$base/last.out" 2>"$base/last.err"; then echo '#include_next unexpectedly found the current header again' >&2 exit 1 fi grep "cannot find include_next file 'last.h'" "$base/last.err" >/dev/null