From f486d15139942f5f617c7d02e3aecbc76b1e50c6 Mon Sep 17 00:00:00 2001 From: Kyle Cripps Date: Thu, 27 Feb 2025 13:36:46 -0800 Subject: [PATCH 1/6] Add -P option Signed-off-by: Kyle Cripps --- frontends/common/parser_options.cpp | 49 ++++++++++++++++++++++------- frontends/common/parser_options.h | 2 ++ 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/frontends/common/parser_options.cpp b/frontends/common/parser_options.cpp index 04d387cee3e..bca3e69b542 100644 --- a/frontends/common/parser_options.cpp +++ b/frontends/common/parser_options.cpp @@ -24,8 +24,10 @@ limitations under the License. #include #include +#include #include #include +#include #include #include "absl/strings/escaping.h" @@ -121,6 +123,13 @@ ParserOptions::ParserOptions(std::string_view defaultMessage) : Util::Options(de return true; }, "Output `make` dependency rule only (passed to preprocessor)"); + registerOption( + "-P", nullptr, + [this](const char *) { + savePreprocessed = true; + return true; + }, + "Saves preprocessed P4 to repro.p4 and do not exit compilation."); registerOption( "-MD", nullptr, [this](const char *) { @@ -405,6 +414,18 @@ const char *ParserOptions::getIncludePath() const { return path.c_str(); } +// From (folder, file.ext, suffix) returns +// folder/file-suffix.ext +static std::filesystem::path makeFileName(const std::filesystem::path &folder, + const std::filesystem::path &name, + std::string_view baseSuffix) { + std::filesystem::path newName(name.stem()); + newName += baseSuffix; + newName += name.extension(); + + return folder / newName; +} + std::optional ParserOptions::preprocess() const { FILE *in = nullptr; @@ -439,19 +460,25 @@ std::optional ParserOptions::preprocess() con } return std::nullopt; } - return ParserOptions::PreprocessorResult(in, &closeFile); -} -// From (folder, file.ext, suffix) returns -// folder/file-suffix.ext -static std::filesystem::path makeFileName(const std::filesystem::path &folder, - const std::filesystem::path &name, - std::string_view baseSuffix) { - std::filesystem::path newName(name.stem()); - newName += baseSuffix; - newName += name.extension(); + if (savePreprocessed) { + std::filesystem::path fileName = makeFileName(dumpFolder, "repro.p4", ""); + std::stringstream stream; + char *line = nullptr; + size_t len = 0; + ssize_t read = 0; - return folder / newName; + while ((read = getline(&line, &len, in)) != -1) { + stream << line; + } + std::ofstream filestream{fileName}; + if (filestream) { + if (Log::verbose()) std::cerr << "Writing preprocessed P4 to " << fileName << std::endl; + filestream << stream.str(); + } + filestream.close(); + } + return ParserOptions::PreprocessorResult(in, &closeFile); } bool ParserOptions::isv1() const { return langVersion == ParserOptions::FrontendVersion::P4_14; } diff --git a/frontends/common/parser_options.h b/frontends/common/parser_options.h index 34eef2c4582..cdd49bec791 100644 --- a/frontends/common/parser_options.h +++ b/frontends/common/parser_options.h @@ -82,6 +82,8 @@ class ParserOptions : public Util::Options { std::filesystem::path file; /// if true preprocess only bool doNotCompile = false; + /// if true save preprocessed P4 to repro.p4 + bool savePreprocessed = false; /// Compiler version. cstring compilerVersion; /// if true skip preprocess From de515d5b37f90876aca8c0a5eab1e70f8d8c3eb2 Mon Sep 17 00:00:00 2001 From: Kyle Cripps Date: Tue, 18 Mar 2025 10:30:09 -0700 Subject: [PATCH 2/6] Run cpp twice; Change option name -P -> --save-temps; Rename file to program.p4pp. Signed-off-by: Kyle Cripps --- frontends/common/parser_options.cpp | 33 +++++++++++++++---- frontends/common/parser_options.h | 2 +- ...ssue4365_no_demote_error_to_info.p4-stderr | 1 + ...e4365_no_demote_error_to_warning.p4-stderr | 1 + .../issue4365_no_disable_error.p4-stderr | 1 + 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/frontends/common/parser_options.cpp b/frontends/common/parser_options.cpp index bca3e69b542..1b3c740ba6a 100644 --- a/frontends/common/parser_options.cpp +++ b/frontends/common/parser_options.cpp @@ -124,12 +124,12 @@ ParserOptions::ParserOptions(std::string_view defaultMessage) : Util::Options(de }, "Output `make` dependency rule only (passed to preprocessor)"); registerOption( - "-P", nullptr, + "--save-temps", nullptr, [this](const char *) { savePreprocessed = true; return true; }, - "Saves preprocessed P4 to repro.p4 and do not exit compilation."); + "Saves preprocessed P4 to filename.p4pp and do not exit compilation."); registerOption( "-MD", nullptr, [this](const char *) { @@ -429,13 +429,15 @@ static std::filesystem::path makeFileName(const std::filesystem::path &folder, std::optional ParserOptions::preprocess() const { FILE *in = nullptr; + std::string cmd; + if (file == "-") { in = stdin; } else { #ifdef __clang__ - std::string cmd("cc -E -x c -Wno-comment"); + cmd = "cc -E -x c -Wno-comment"; #else - std::string cmd("cpp"); + cmd = "cpp"; #endif cmd += " -C -undef -nostdinc -x assembler-with-cpp " + preprocessor_options.string() + @@ -462,15 +464,34 @@ std::optional ParserOptions::preprocess() con } if (savePreprocessed) { - std::filesystem::path fileName = makeFileName(dumpFolder, "repro.p4", ""); + if (file == "-") { + ::P4::error(ErrorType::ERR_INVALID, + "--save-temps option is not supported when the " + "input P4 comes from stdin."); + return std::nullopt; + } + + // Run the cpp command a second time to produce a second input stream to write to + // filename.p4pp. + FILE *inSave = popen(cmd.c_str(), "r"); + if (inSave == nullptr) { + ::P4::error(ErrorType::ERR_IO, "Error invoking preprocessor"); + perror(""); + return std::nullopt; + } std::stringstream stream; char *line = nullptr; size_t len = 0; ssize_t read = 0; - while ((read = getline(&line, &len, in)) != -1) { + while ((read = getline(&line, &len, inSave)) != -1) { stream << line; } + closeFile(inSave); + + std::filesystem::path fileName(file.stem()); + fileName += ".p4pp"; + fileName = makeFileName(dumpFolder, fileName, ""); std::ofstream filestream{fileName}; if (filestream) { if (Log::verbose()) std::cerr << "Writing preprocessed P4 to " << fileName << std::endl; diff --git a/frontends/common/parser_options.h b/frontends/common/parser_options.h index cdd49bec791..ffbd68d2653 100644 --- a/frontends/common/parser_options.h +++ b/frontends/common/parser_options.h @@ -82,7 +82,7 @@ class ParserOptions : public Util::Options { std::filesystem::path file; /// if true preprocess only bool doNotCompile = false; - /// if true save preprocessed P4 to repro.p4 + /// if true save preprocessed P4 to filename.p4pp bool savePreprocessed = false; /// Compiler version. cstring compilerVersion; diff --git a/testdata/p4_16_errors_outputs/issue4365_no_demote_error_to_info.p4-stderr b/testdata/p4_16_errors_outputs/issue4365_no_demote_error_to_info.p4-stderr index 75fe7184481..011e575f2fa 100644 --- a/testdata/p4_16_errors_outputs/issue4365_no_demote_error_to_info.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue4365_no_demote_error_to_info.p4-stderr @@ -7,6 +7,7 @@ -U arg Undefine macro (passed to preprocessor) -E Preprocess only, do not compile (prints program on stdout) -M Output `make` dependency rule only (passed to preprocessor) +--save-temps Saves preprocessed P4 to filename.p4pp and do not exit compilation. -MD Output `make` dependency rule to file as side effect (passed to preprocessor) -MF file With -M, specify output file for dependencies (passed to preprocessor) -MG with -M, suppress errors for missing headers (passed to preprocessor) diff --git a/testdata/p4_16_errors_outputs/issue4365_no_demote_error_to_warning.p4-stderr b/testdata/p4_16_errors_outputs/issue4365_no_demote_error_to_warning.p4-stderr index 91a5c3e1d35..262ae6cdd50 100644 --- a/testdata/p4_16_errors_outputs/issue4365_no_demote_error_to_warning.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue4365_no_demote_error_to_warning.p4-stderr @@ -7,6 +7,7 @@ -U arg Undefine macro (passed to preprocessor) -E Preprocess only, do not compile (prints program on stdout) -M Output `make` dependency rule only (passed to preprocessor) +--save-temps Saves preprocessed P4 to filename.p4pp and do not exit compilation. -MD Output `make` dependency rule to file as side effect (passed to preprocessor) -MF file With -M, specify output file for dependencies (passed to preprocessor) -MG with -M, suppress errors for missing headers (passed to preprocessor) diff --git a/testdata/p4_16_errors_outputs/issue4365_no_disable_error.p4-stderr b/testdata/p4_16_errors_outputs/issue4365_no_disable_error.p4-stderr index 5c086bafc0d..780f13c5816 100644 --- a/testdata/p4_16_errors_outputs/issue4365_no_disable_error.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue4365_no_disable_error.p4-stderr @@ -7,6 +7,7 @@ -U arg Undefine macro (passed to preprocessor) -E Preprocess only, do not compile (prints program on stdout) -M Output `make` dependency rule only (passed to preprocessor) +--save-temps Saves preprocessed P4 to filename.p4pp and do not exit compilation. -MD Output `make` dependency rule to file as side effect (passed to preprocessor) -MF file With -M, specify output file for dependencies (passed to preprocessor) -MG with -M, suppress errors for missing headers (passed to preprocessor) From 36b8060a1b591972e50391a788a215b08e2d663e Mon Sep 17 00:00:00 2001 From: kfcripps Date: Mon, 12 May 2025 14:59:24 -0700 Subject: [PATCH 3/6] Do not move cmd decl outside of #ifdef __clang__ Signed-off-by: kfcripps --- frontends/common/parser_options.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frontends/common/parser_options.cpp b/frontends/common/parser_options.cpp index 1b3c740ba6a..f63d5dc9f90 100644 --- a/frontends/common/parser_options.cpp +++ b/frontends/common/parser_options.cpp @@ -429,15 +429,13 @@ static std::filesystem::path makeFileName(const std::filesystem::path &folder, std::optional ParserOptions::preprocess() const { FILE *in = nullptr; - std::string cmd; - if (file == "-") { in = stdin; } else { #ifdef __clang__ - cmd = "cc -E -x c -Wno-comment"; + std::string cmd = "cc -E -x c -Wno-comment"; #else - cmd = "cpp"; + std::string cmd = "cpp"; #endif cmd += " -C -undef -nostdinc -x assembler-with-cpp " + preprocessor_options.string() + From 26673d0fdce8b44093c6777f3f8072c511576ff9 Mon Sep 17 00:00:00 2001 From: kfcripps Date: Mon, 12 May 2025 15:09:33 -0700 Subject: [PATCH 4/6] Open and read from program.p4pp instead of running cpp twice Signed-off-by: kfcripps --- frontends/common/parser_options.cpp | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/frontends/common/parser_options.cpp b/frontends/common/parser_options.cpp index f63d5dc9f90..f1766aa2709 100644 --- a/frontends/common/parser_options.cpp +++ b/frontends/common/parser_options.cpp @@ -462,40 +462,33 @@ std::optional ParserOptions::preprocess() con } if (savePreprocessed) { - if (file == "-") { - ::P4::error(ErrorType::ERR_INVALID, - "--save-temps option is not supported when the " - "input P4 comes from stdin."); - return std::nullopt; - } - - // Run the cpp command a second time to produce a second input stream to write to - // filename.p4pp. - FILE *inSave = popen(cmd.c_str(), "r"); - if (inSave == nullptr) { - ::P4::error(ErrorType::ERR_IO, "Error invoking preprocessor"); - perror(""); - return std::nullopt; - } std::stringstream stream; char *line = nullptr; size_t len = 0; ssize_t read = 0; - while ((read = getline(&line, &len, inSave)) != -1) { + while ((read = getline(&line, &len, in)) != -1) { stream << line; } - closeFile(inSave); + closeFile(in); std::filesystem::path fileName(file.stem()); fileName += ".p4pp"; fileName = makeFileName(dumpFolder, fileName, ""); std::ofstream filestream{fileName}; if (filestream) { - if (Log::verbose()) std::cerr << "Writing preprocessed P4 to " << fileName << std::endl; + if (Log::verbose()) + std::cerr << "Writing preprocessed P4 to " << fileName << std::endl; filestream << stream.str(); } filestream.close(); + + in = fopen(fileName.c_str(), "r"); + if (in == nullptr) { + ::P4::error(ErrorType::ERR_IO, "Error invoking preprocessor"); + perror(""); + return std::nullopt; + } } return ParserOptions::PreprocessorResult(in, &closeFile); } From 07c43e4f689e0475093e83dfc34566e5febeb51a Mon Sep 17 00:00:00 2001 From: Kyle Cripps Date: Mon, 12 May 2025 16:04:01 -0700 Subject: [PATCH 5/6] clang-format Signed-off-by: Kyle Cripps --- frontends/common/parser_options.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontends/common/parser_options.cpp b/frontends/common/parser_options.cpp index f1766aa2709..9abc76803ff 100644 --- a/frontends/common/parser_options.cpp +++ b/frontends/common/parser_options.cpp @@ -477,8 +477,7 @@ std::optional ParserOptions::preprocess() con fileName = makeFileName(dumpFolder, fileName, ""); std::ofstream filestream{fileName}; if (filestream) { - if (Log::verbose()) - std::cerr << "Writing preprocessed P4 to " << fileName << std::endl; + if (Log::verbose()) std::cerr << "Writing preprocessed P4 to " << fileName << std::endl; filestream << stream.str(); } filestream.close(); From a6ce9bd4ede8bb5a5038219be01871a14153e392 Mon Sep 17 00:00:00 2001 From: Kyle Cripps <60898032+kfcripps@users.noreply.github.com> Date: Tue, 27 May 2025 10:26:12 -0700 Subject: [PATCH 6/6] remove unintended changes Signed-off-by: Kyle Cripps <60898032+kfcripps@users.noreply.github.com> --- frontends/common/parser_options.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontends/common/parser_options.cpp b/frontends/common/parser_options.cpp index 9abc76803ff..1f10bdd2b89 100644 --- a/frontends/common/parser_options.cpp +++ b/frontends/common/parser_options.cpp @@ -433,9 +433,9 @@ std::optional ParserOptions::preprocess() con in = stdin; } else { #ifdef __clang__ - std::string cmd = "cc -E -x c -Wno-comment"; + std::string cmd("cc -E -x c -Wno-comment"); #else - std::string cmd = "cpp"; + std::string cmd("cpp"); #endif cmd += " -C -undef -nostdinc -x assembler-with-cpp " + preprocessor_options.string() +