--- a/src/Parameters.h 2026-06-11 13:48:41 +++ b/src/Parameters.h 2026-09-29 20:08:47 @@ -167,8 +167,8 @@ class PipeCloser { public: - PipeCloser(const char *_runningTool, FILE *_file) - : runningTool(_runningTool), file(_file) {} + PipeCloser(const char *_runningTool, FILE *_file, bool _isPipe = true) + : runningTool(_runningTool), file(_file), isPipe(_isPipe) {} ~PipeCloser() { (void) close(); } // Issues error message to cout upon error. @@ -182,6 +182,7 @@ private: std::string runningTool; FILE *file; + bool isPipe; // false: a plain file opened with fopen (CMOC_PREPROCESSED) }; --- a/src/Parameters.cpp 2026-06-12 07:09:43 +++ b/src/Parameters.cpp 2026-09-29 20:08:47 @@ -511,7 +511,12 @@ cout << "Preprocessor command: " << cppCommand << endl; extern FILE *yyin; - yyin = popen(cppCommand.c_str(), "r"); + // CMOC_PREPROCESSED=1: the input file is already the preprocessor's output, so read it directly. + // Used where no process can be started (WebAssembly in the browser): the preprocessor runs + // as its own module before this one. + const char *preprocessedEnv = getenv("CMOC_PREPROCESSED"); + const bool inputIsPreprocessed = preprocessedEnv != NULL && preprocessedEnv[0] != '\0'; + yyin = inputIsPreprocessed ? fopen(inputFilename.c_str(), "r") : popen(cppCommand.c_str(), "r"); if (yyin == NULL) { int e = errno; @@ -520,7 +525,7 @@ return EXIT_FAILURE; } - PipeCloser preprocFileCloser("preprocessor", yyin); + PipeCloser preprocFileCloser("preprocessor", yyin, !inputIsPreprocessed); // If this pointer receives an instance of TranslationUnit, that instance will be // destroyed before leaving this function. @@ -750,6 +755,12 @@ { if (file == NULL) return 0; // success: nothing to do + if (!isPipe) + { + fclose(file); + file = NULL; + return 0; + } int status = pclose(file); file = NULL; if (!WIFEXITED(status))