@@ -23,8 +23,10 @@ limitations under the License.
2323#include < sys/types.h>
2424#include < sys/wait.h>
2525
26+ #include < fstream>
2627#include < memory>
2728#include < regex>
29+ #include < sstream>
2830#include < unordered_set>
2931
3032#include " absl/strings/escaping.h"
@@ -119,6 +121,13 @@ ParserOptions::ParserOptions(std::string_view defaultMessage) : Util::Options(de
119121 return true ;
120122 },
121123 " Output `make` dependency rule only (passed to preprocessor)" );
124+ registerOption (
125+ " -P" , nullptr ,
126+ [this ](const char *) {
127+ savePreprocessed = true ;
128+ return true ;
129+ },
130+ " Saves preprocessed P4 to repro.p4 and do not exit compilation." );
122131 registerOption (
123132 " -MD" , nullptr ,
124133 [this ](const char *) {
@@ -421,6 +430,18 @@ const char *ParserOptions::getIncludePath() const {
421430 return path.c_str ();
422431}
423432
433+ // From (folder, file.ext, suffix) returns
434+ // folder/file-suffix.ext
435+ static std::filesystem::path makeFileName (const std::filesystem::path &folder,
436+ const std::filesystem::path &name,
437+ std::string_view baseSuffix) {
438+ std::filesystem::path newName (name.stem ());
439+ newName += baseSuffix;
440+ newName += name.extension ();
441+
442+ return folder / newName;
443+ }
444+
424445std::optional<ParserOptions::PreprocessorResult> ParserOptions::preprocess () const {
425446 FILE *in = nullptr ;
426447
@@ -455,19 +476,25 @@ std::optional<ParserOptions::PreprocessorResult> ParserOptions::preprocess() con
455476 }
456477 return std::nullopt ;
457478 }
458- return ParserOptions::PreprocessorResult (in, &closeFile);
459- }
460479
461- // From (folder, file.ext, suffix) returns
462- // folder/file-suffix.ext
463- static std::filesystem::path makeFileName (const std::filesystem::path &folder,
464- const std::filesystem::path &name,
465- std::string_view baseSuffix) {
466- std::filesystem::path newName (name.stem ());
467- newName += baseSuffix;
468- newName += name.extension ();
480+ if (savePreprocessed) {
481+ std::filesystem::path fileName = makeFileName (dumpFolder, " repro.p4" , " " );
482+ std::stringstream stream;
483+ char *line = nullptr ;
484+ size_t len = 0 ;
485+ ssize_t read = 0 ;
469486
470- return folder / newName;
487+ while ((read = getline (&line, &len, in)) != -1 ) {
488+ stream << line;
489+ }
490+ std::ofstream filestream{fileName};
491+ if (filestream) {
492+ if (Log::verbose ()) std::cerr << " Writing preprocessed P4 to " << fileName << std::endl;
493+ filestream << stream.str ();
494+ }
495+ filestream.close ();
496+ }
497+ return ParserOptions::PreprocessorResult (in, &closeFile);
471498}
472499
473500bool ParserOptions::isv1 () const { return langVersion == ParserOptions::FrontendVersion::P4_14; }
0 commit comments