From 6d7c578304ef8a04335fec46523ed6eaf42589b3 Mon Sep 17 00:00:00 2001 From: ike709 Date: Thu, 6 Jun 2024 17:17:13 -0700 Subject: [PATCH] Handle `fexists()` in the preprocessor (#1824) Co-authored-by: ike709 Co-authored-by: wixoa --- .../Tests/Preprocessor/fexists_fail.dm | 6 ++++ .../Tests/Preprocessor/fexists_pass.dm | 8 +++++ .../Compiler/DMPreprocessor/DMPreprocessor.cs | 2 +- .../DMPreprocessor/DMPreprocessorParser.cs | 30 +++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 Content.Tests/DMProject/Tests/Preprocessor/fexists_fail.dm create mode 100644 Content.Tests/DMProject/Tests/Preprocessor/fexists_pass.dm diff --git a/Content.Tests/DMProject/Tests/Preprocessor/fexists_fail.dm b/Content.Tests/DMProject/Tests/Preprocessor/fexists_fail.dm new file mode 100644 index 0000000000..599a0028c6 --- /dev/null +++ b/Content.Tests/DMProject/Tests/Preprocessor/fexists_fail.dm @@ -0,0 +1,6 @@ +#if fexists("fake/path.abc") +#error "how could this exist" +#endif + +/proc/RunTest() + return \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/Preprocessor/fexists_pass.dm b/Content.Tests/DMProject/Tests/Preprocessor/fexists_pass.dm new file mode 100644 index 0000000000..1c4db4d611 --- /dev/null +++ b/Content.Tests/DMProject/Tests/Preprocessor/fexists_pass.dm @@ -0,0 +1,8 @@ +#if fexists("fexists_pass.dm") +#warn "yay!" +#else +#error "it doesn't exist" +#endif + +/proc/RunTest() + return diff --git a/DMCompiler/Compiler/DMPreprocessor/DMPreprocessor.cs b/DMCompiler/Compiler/DMPreprocessor/DMPreprocessor.cs index ece72e026e..0b77570fca 100644 --- a/DMCompiler/Compiler/DMPreprocessor/DMPreprocessor.cs +++ b/DMCompiler/Compiler/DMPreprocessor/DMPreprocessor.cs @@ -430,7 +430,7 @@ private List GetLineOfTokens() case TokenType.DM_Preproc_LineSplice: continue; case TokenType.DM_Preproc_Identifier: - if(token.Text == "defined") // need to be careful here to prevent macros in defined() expressions from being clobbered + if(token.Text == "defined" || token.Text == "fexists") // need to be careful here to prevent macros in defined() or fexists() expressions from being clobbered tryIdentifiersAsMacros = false; else if (tryIdentifiersAsMacros && TryMacro(token)) // feeding any novel macro tokens back into the pipeline here continue; diff --git a/DMCompiler/Compiler/DMPreprocessor/DMPreprocessorParser.cs b/DMCompiler/Compiler/DMPreprocessor/DMPreprocessorParser.cs index 020033af96..b631f97151 100644 --- a/DMCompiler/Compiler/DMPreprocessor/DMPreprocessorParser.cs +++ b/DMCompiler/Compiler/DMPreprocessor/DMPreprocessorParser.cs @@ -1,6 +1,7 @@ using DMCompiler.Compiler.DM; using System; using System.Collections.Generic; +using System.IO; namespace DMCompiler.Compiler.DMPreprocessor; @@ -313,6 +314,35 @@ private static void Error(string msg) { } return _defines!.ContainsKey(definedInner.Text) ? 1.0f : 0.0f; + } else if (token.Text == "fexists") { + Advance(); + if (!Check(TokenType.DM_LeftParenthesis)) { + Error("Expected '(' to begin fexists() expression"); + return DegenerateValue; + } + + Token fExistsInner = Current(); + + if (fExistsInner.Type != TokenType.DM_ConstantString) { + Error($"Unexpected token {fExistsInner.PrintableText} - file path expected"); + return DegenerateValue; + } + + Advance(); + if (!Check(TokenType.DM_RightParenthesis)) { + DMCompiler.Emit(WarningCode.DefinedMissingParen, token.Location, + "Expected ')' to end fexists() expression"); + } + + var filePath = Path.GetRelativePath(".", fExistsInner.Value!.ToString()!.Replace('\\', '/')); + + var outputDir = Path.Combine(Path.GetDirectoryName(DMCompiler.Settings.Files?[0]) ?? "/", Path.GetDirectoryName(fExistsInner.Location.SourceFile) ?? "/"); + if (string.IsNullOrEmpty(outputDir)) + outputDir = "./"; + + filePath = Path.Combine(outputDir, filePath); + + return File.Exists(filePath) ? 1.0f : 0.0f; } Error($"Unexpected identifier {token.PrintableText} in preprocessor expression");