From 1f64e47d6bf109b304d0ebcd3c3097720b1a25bb Mon Sep 17 00:00:00 2001 From: LuisHsu Date: Sat, 23 Mar 2024 02:52:36 -0700 Subject: [PATCH] [PP] Pragma directive --- src/include/PreProcessor.hpp | 8 +++++- src/lib/PreProcessor/PreProcessor.cpp | 40 ++++++++++++++++++++++++++- test/pp_directive/pp_directive.cpp | 39 ++++++++++++++++++++++++++ test/pp_directive/pragma.c | 17 ++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 test/pp_directive/pragma.c diff --git a/src/include/PreProcessor.hpp b/src/include/PreProcessor.hpp index fea8036..d4b79fb 100644 --- a/src/include/PreProcessor.hpp +++ b/src/include/PreProcessor.hpp @@ -43,6 +43,12 @@ struct PreProcessor { PreProcessor(std::filesystem::path path, std::string source, std::vector include_paths = {}); PPToken get(); + struct { + std::optional fp_contract; + std::optional fenv_access; + std::optional cx_limited_value; + } pragma; + #ifndef CCTEST private: #endif @@ -148,7 +154,7 @@ struct PreProcessor { void undef_directive(); void line_directive(); void error_directive(); - // void pragma_directive(PPToken& token); // TODO: + void pragma_directive(); }; } // namespace WasmVM diff --git a/src/lib/PreProcessor/PreProcessor.cpp b/src/lib/PreProcessor/PreProcessor.cpp index e7be3b1..98d14eb 100644 --- a/src/lib/PreProcessor/PreProcessor.cpp +++ b/src/lib/PreProcessor/PreProcessor.cpp @@ -126,7 +126,7 @@ PreProcessor::PPToken PreProcessor::get(){ }else if(direcitve_name == "error"){ error_directive(); }else if(direcitve_name == "pragma"){ - // TODO: + pragma_directive(); }else if(direcitve_name == "include"){ include_directive(); }else{ @@ -378,3 +378,41 @@ void PreProcessor::error_directive(){ } throw Exception::Error(pos, message.str()); } + +void PreProcessor::pragma_directive(){ + Line::iterator cur = skip_whitespace(line.begin(), line.end()); + SourcePos pos = cur->value().pos; + if(cur != line.end() && cur->hold()){ + if(((TokenType::Identifier)cur->value()).sequence == "STDC"){ + cur = skip_whitespace(std::next(cur), line.end()); + if(cur != line.end() && cur->hold()){ + TokenType::Identifier name = cur->value(); + cur = skip_whitespace(std::next(cur), line.end()); + if(cur != line.end() && cur->hold()){ + TokenType::Identifier on_off = cur->value(); + std::optional toggle; + if(on_off.sequence == "ON"){ + toggle = true; + }else if(on_off.sequence == "OFF"){ + toggle = false; + }else if(on_off.sequence == "DEFAULT"){ + toggle.reset(); + }else{ + throw Exception::Error(cur->value().pos, "invalid value of ON/OFF switch"); + } + if(name.sequence == "FP_CONTRACT"){ + pragma.fp_contract.swap(toggle); + return; + }else if(name.sequence == "FENV_ACCESS"){ + pragma.fenv_access.swap(toggle); + return; + }else if(name.sequence == "CX_LIMITED_RANGE"){ + pragma.cx_limited_value.swap(toggle); + return; + } + } + } + } + } + throw Exception::Error(pos, "unknown pragma"); +} \ No newline at end of file diff --git a/test/pp_directive/pp_directive.cpp b/test/pp_directive/pp_directive.cpp index 27559d9..2214a3b 100644 --- a/test/pp_directive/pp_directive.cpp +++ b/test/pp_directive/pp_directive.cpp @@ -213,4 +213,43 @@ Suite pp_directive { PreProcessor pp(std::filesystem::path("error.c")); Throw(Exception::Exception, pp.get()); }) + Test("pragma", { + PreProcessor pp(std::filesystem::path("pragma.c")); + PreProcessor::PPToken token; + pp.get(); + Expect(pp.pragma.fp_contract.has_value() && (pp.pragma.fp_contract.value() == true)); + pp.get(); + + pp.get(); + Expect(pp.pragma.fp_contract.has_value() && (pp.pragma.fp_contract.value() == false)); + pp.get(); + + pp.get(); + Expect(!pp.pragma.fp_contract.has_value()); + pp.get(); + + pp.get(); + Expect(pp.pragma.fenv_access.has_value() && (pp.pragma.fenv_access.value() == true)); + pp.get(); + + pp.get(); + Expect(pp.pragma.fenv_access.has_value() && (pp.pragma.fenv_access.value() == false)); + pp.get(); + + pp.get(); + Expect(!pp.pragma.fenv_access.has_value()); + pp.get(); + + pp.get(); + Expect(pp.pragma.cx_limited_value.has_value() && (pp.pragma.cx_limited_value.value() == true)); + pp.get(); + + pp.get(); + Expect(pp.pragma.cx_limited_value.has_value() && (pp.pragma.cx_limited_value.value() == false)); + pp.get(); + + pp.get(); + Expect(!pp.pragma.cx_limited_value.has_value()); + pp.get(); + }) }; \ No newline at end of file diff --git a/test/pp_directive/pragma.c b/test/pp_directive/pragma.c new file mode 100644 index 0000000..1a567a1 --- /dev/null +++ b/test/pp_directive/pragma.c @@ -0,0 +1,17 @@ +#pragma STDC FP_CONTRACT ON +; +#pragma STDC FP_CONTRACT OFF +; +#pragma STDC FP_CONTRACT DEFAULT +; +#pragma STDC FENV_ACCESS ON +; +#pragma STDC FENV_ACCESS OFF +; +#pragma STDC FENV_ACCESS DEFAULT +; +#pragma STDC CX_LIMITED_RANGE ON +; +#pragma STDC CX_LIMITED_RANGE OFF +; +#pragma STDC CX_LIMITED_RANGE DEFAULT \ No newline at end of file