From 1767929536f77a10c34f11ba97a97f2f5c6b7e87 Mon Sep 17 00:00:00 2001
From: Letter N <24603524+LetterN@users.noreply.github.com>
Date: Thu, 7 Dec 2023 23:06:53 +0800
Subject: [PATCH] Add --help for DMCompiler (#1547)
* a
* cosmetic change
* wiki link
* update help text
---
DMCompiler/Program.cs | 282 ++++++++++++++++++++++--------------------
1 file changed, 151 insertions(+), 131 deletions(-)
diff --git a/DMCompiler/Program.cs b/DMCompiler/Program.cs
index 8cbd5c0a3e..4c89e178f5 100644
--- a/DMCompiler/Program.cs
+++ b/DMCompiler/Program.cs
@@ -4,163 +4,183 @@
using System.Linq;
using Robust.Shared.Utility;
-namespace DMCompiler {
- internal struct Argument {
- /// The text we found that's in the '--whatever' format. May be null if no such text was present.
- public string? Name;
- /// The value, either set in a '--whatever=whoever' format or just left by itself anonymously. May be null.
- public string? Value;
- }
+namespace DMCompiler;
- internal static class Program {
- private static void Main(string[] args) {
- if (!TryParseArguments(args, out DMCompilerSettings settings)) {
- Environment.Exit(1);
- return;
- }
+internal struct Argument {
+ /// The text we found that's in the '--whatever' format. May be null if no such text was present.
+ public string? Name;
+ /// The value, either set in a '--whatever=whoever' format or just left by itself anonymously. May be null.
+ public string? Value;
+}
- if (!DMCompiler.Compile(settings)) {
- //Compile errors, exit with an error code
- Environment.Exit(1);
- }
+internal static class Program {
+ private static void Main(string[] args) {
+ if (!TryParseArguments(args, out DMCompilerSettings settings)) {
+ Environment.Exit(1);
+ return;
}
- /// Helper for TryParseArguments(), to turn the arg array into something better-parsed.
- private static IEnumerable StringArrayToArguments(string[] args) {
- List retArgs = new(args.Length);
- for(var i = 0; i < args.Length;i+=1) {
- string firstString = args[i];
- if(string.IsNullOrWhiteSpace(firstString)) // Is this possible? I don't even know. (IsNullOrWhiteSpace also checks if the string is empty, btw)
- continue;
- if(!firstString.StartsWith("--")) { // If it's a value-only argument
- retArgs.Add(new Argument { Value = firstString });
- continue;
- }
- firstString = firstString.TrimStart('-');
- var split = firstString.Split('=');
- if(split.Length == 1) { // If it's a name-only argument
- if(firstString == "define" && i + 1 < args.Length) { // Weird snowflaking to make our define syntax work
- i+=1;
- if(!args[i].StartsWith("--")) { // To make the error make a schmidge more sense
- retArgs.Add(new Argument {Name = firstString, Value = args[i] });
- }
+ if (!DMCompiler.Compile(settings)) {
+ //Compile errors, exit with an error code
+ Environment.Exit(1);
+ }
+ }
+
+ /// Helper for TryParseArguments(), to turn the arg array into something better-parsed.
+ private static IEnumerable StringArrayToArguments(string[] args) {
+ List retArgs = new(args.Length);
+ for(var i = 0; i < args.Length;i+=1) {
+ var firstString = args[i];
+ if(string.IsNullOrWhiteSpace(firstString)) // Is this possible? I don't even know. (IsNullOrWhiteSpace also checks if the string is empty, btw)
+ continue;
+ if(!firstString.StartsWith("--")) { // If it's a value-only argument
+ retArgs.Add(new Argument { Value = firstString });
+ continue;
+ }
+ firstString = firstString.TrimStart('-');
+ var split = firstString.Split('=');
+ if(split.Length == 1) { // If it's a name-only argument
+ if(firstString == "define" && i + 1 < args.Length) { // Weird snowflaking to make our define syntax work
+ i+=1;
+ if(!args[i].StartsWith("--")) { // To make the error make a schmidge more sense
+ retArgs.Add(new Argument {Name = firstString, Value = args[i] });
}
- retArgs.Add(new Argument { Name = firstString });
- continue;
}
- retArgs.Add(new Argument { Name = split[0], Value = split[1] });
+ retArgs.Add(new Argument { Name = firstString });
+ continue;
}
-
- return retArgs.AsEnumerable();
+ retArgs.Add(new Argument { Name = split[0], Value = split[1] });
}
- private static bool HasValidDMExtension(string filename) {
- string extension = Path.GetExtension(filename);
- return !String.IsNullOrEmpty(extension) && (extension == ".dme" || extension == ".dm");
- }
+ return retArgs.AsEnumerable();
+ }
- private static bool TryParseArguments(string[] args, out DMCompilerSettings settings) {
- settings = new();
- settings.Files = new List();
-
- bool skipBad = args.Contains("--skip-bad-args");
-
- foreach (Argument arg in StringArrayToArguments(args)) {
- switch (arg.Name) {
- case "suppress-unimplemented": settings.SuppressUnimplementedWarnings = true; break;
- case "dump-preprocessor": settings.DumpPreprocessor = true; break;
- case "no-standard": settings.NoStandard = true; break;
- case "verbose": settings.Verbose = true; break;
- case "skip-bad-args": break;
- case "define":
- string[] parts = arg.Value.Split('=', 2); // Only split on the first = in case of stuff like "--define AAA=0==1"
- if (parts.Length == 0) {
- Console.WriteLine("Compiler arg 'define' requires macro identifier for definition directive");
- return false;
- }
- DebugTools.Assert(parts.Length <= 2);
- settings.MacroDefines ??= new();
- settings.MacroDefines[parts[0]] = parts.Length > 1 ? parts[1] : "";
- break;
- case "wall":
- case "notices-enabled":
- settings.NoticesEnabled = true;
- break;
- case "pragma-config": {
- if(arg.Value is null || !HasValidDMExtension(arg.Value)) {
- if(skipBad) {
- DMCompiler.ForcedWarning($"Compiler arg 'pragma-config' requires filename of valid DM file, skipping");
- continue;
- }
- Console.WriteLine("Compiler arg 'pragma-config' requires filename of valid DM file");
- return false;
- }
- settings.PragmaFileOverride = arg.Value;
- break;
- }
- case "version": {
- if(arg.Value is null) {
- if(skipBad) {
- DMCompiler.ForcedWarning("Compiler arg 'version' requires a full BYOND build (e.g. --version=514.1584), skipping");
- continue;
- }
- Console.WriteLine("Compiler arg 'version' requires a full BYOND build (e.g. --version=514.1584)");
- return false;
- }
+ private static bool HasValidDMExtension(string filename) {
+ var extension = Path.GetExtension(filename);
+ return !string.IsNullOrEmpty(extension) && (extension == ".dme" || extension == ".dm");
+ }
- var split = arg.Value.Split('.', StringSplitOptions.RemoveEmptyEntries);
- if (split.Length != 2 || !int.TryParse(split[0], out _) || !int.TryParse(split[1], out _)) { // We want to make sure that they *are* ints but the preprocessor takes strings
- if(skipBad) {
- DMCompiler.ForcedWarning("Compiler arg 'version' requires a full BYOND build (e.g. --version=514.1584), skipping");
- continue;
- }
- Console.WriteLine("Compiler arg 'version' requires a full BYOND build (e.g. --version=514.1584)");
- return false;
- }
+ private static void PrintHelp() {
+ Console.WriteLine("DM Compiler for OpenDream");
+ Console.WriteLine("For more information please visit https://github.com/OpenDreamProject/OpenDream/wiki");
+ Console.WriteLine("Usage: ./DMCompiler [options] [file].dme\n");
+ Console.WriteLine("Options and arguments:");
+ Console.WriteLine("--help : Show this help");
+ Console.WriteLine("--version [VER].[BUILD] : Used to set the DM_VERSION and DM_BUILD macros");
+ Console.WriteLine("--skip-bad-args : Skip arguments the compiler doesn't recognize");
+ Console.WriteLine("--suppress-unimplemented : Do not warn about unimplemented proc and var uses");
+ Console.WriteLine("--dump-preprocessor : This saves the result of preprocessing (#include, #if, defines, etc) in a file called preprocessor_dump.dm beside the given DME file.");
+ Console.WriteLine("--no-standard : This disables objects and procs that are usually built-into every DM program by not including DMStandard.dm.");
+ Console.WriteLine("--define [KEY=VAL] : Add extra defines to the compilation");
+ Console.WriteLine("--verbose : Show verbose output during compile");
+ Console.WriteLine("--notices-enabled : Show notice output during compile");
+ Console.WriteLine("--pragma-config [file].dm : Configure the error/warning/notice/ignore level of compiler messages");
+ }
- settings.DMVersion = split[0];
- settings.DMBuild = split[1];
- break;
+ private static bool TryParseArguments(string[] args, out DMCompilerSettings settings) {
+ settings = new DMCompilerSettings {
+ Files = new List()
+ };
+
+ var skipBad = args.Contains("--skip-bad-args");
+
+ foreach (Argument arg in StringArrayToArguments(args)) {
+ switch (arg.Name) {
+ case "help":
+ PrintHelp();
+ return false;
+ case "suppress-unimplemented": settings.SuppressUnimplementedWarnings = true; break;
+ case "dump-preprocessor": settings.DumpPreprocessor = true; break;
+ case "no-standard": settings.NoStandard = true; break;
+ case "verbose": settings.Verbose = true; break;
+ case "skip-bad-args": break;
+ case "define":
+ var parts = arg.Value?.Split('=', 2); // Only split on the first = in case of stuff like "--define AAA=0==1"
+ if (parts is { Length: 0 }) {
+ Console.WriteLine("Compiler arg 'define' requires macro identifier for definition directive");
+ return false;
}
- case null: { // Value-only argument
- if (arg.Value is null) // A completely empty argument? This should be a bug.
+ DebugTools.Assert(parts is { Length: <= 2 });
+ settings.MacroDefines ??= new Dictionary();
+ settings.MacroDefines[parts[0]] = parts.Length > 1 ? parts[1] : "";
+ break;
+ case "wall":
+ case "notices-enabled":
+ settings.NoticesEnabled = true;
+ break;
+ case "pragma-config": {
+ if(arg.Value is null || !HasValidDMExtension(arg.Value)) {
+ if(skipBad) {
+ DMCompiler.ForcedWarning($"Compiler arg 'pragma-config' requires filename of valid DM file, skipping");
continue;
- if (HasValidDMExtension(arg.Value)) {
- settings.Files.Add(arg.Value);
- break;
}
+ Console.WriteLine("Compiler arg 'pragma-config' requires filename of valid DM file");
+ return false;
+ }
+ settings.PragmaFileOverride = arg.Value;
+ break;
+ }
+ case "version": {
+ if(arg.Value is null) {
if(skipBad) {
- DMCompiler.ForcedWarning($"Invalid compiler arg '{arg.Value}', skipping");
- } else {
- Console.WriteLine($"Invalid arg '{arg}'");
- return false;
+ DMCompiler.ForcedWarning("Compiler arg 'version' requires a full BYOND build (e.g. --version=514.1584), skipping");
+ continue;
+ }
+ Console.WriteLine("Compiler arg 'version' requires a full BYOND build (e.g. --version=514.1584)");
+ return false;
+ }
+
+ var split = arg.Value.Split('.', StringSplitOptions.RemoveEmptyEntries);
+ if (split.Length != 2 || !int.TryParse(split[0], out _) || !int.TryParse(split[1], out _)) { // We want to make sure that they *are* ints but the preprocessor takes strings
+ if(skipBad) {
+ DMCompiler.ForcedWarning("Compiler arg 'version' requires a full BYOND build (e.g. --version=514.1584), skipping");
+ continue;
}
+ Console.WriteLine("Compiler arg 'version' requires a full BYOND build (e.g. --version=514.1584)");
+ return false;
+ }
+ settings.DMVersion = split[0];
+ settings.DMBuild = split[1];
+ break;
+ }
+ case null: { // Value-only argument
+ if (arg.Value is null) // A completely empty argument? This should be a bug.
+ continue;
+ if (HasValidDMExtension(arg.Value)) {
+ settings.Files.Add(arg.Value);
break;
}
- default: {
- if (skipBad) {
- DMCompiler.ForcedWarning($"Unknown compiler arg '{arg.Name}', skipping");
- break;
- } else {
- Console.WriteLine($"Unknown arg '{arg}'");
- return false;
- }
+ if (skipBad) {
+ DMCompiler.ForcedWarning($"Invalid compiler arg '{arg.Value}', skipping");
+ } else {
+ Console.WriteLine($"Invalid arg '{arg}'");
+ return false;
}
+
+ break;
}
- }
+ default: {
+ if (skipBad) {
+ DMCompiler.ForcedWarning($"Unknown compiler arg '{arg.Name}', skipping");
+ break;
+ }
- if (settings.Files.Count == 0)
- {
- Console.WriteLine("At least one DME or DM file must be provided as an argument");
- return false;
- } else {
- foreach(var file in settings.Files) {
- Console.WriteLine($"Compiling {Path.GetFileName(file)} on {settings.DMVersion}.{settings.DMBuild}");
+ Console.WriteLine($"Unknown arg '{arg}'");
+ return false;
}
}
+ }
- return true;
+ if (settings.Files.Count == 0) {
+ PrintHelp();
+ return false;
}
+
+ foreach(var file in settings.Files) {
+ Console.WriteLine($"Compiling {Path.GetFileName(file)} on {settings.DMVersion}.{settings.DMBuild}");
+ }
+
+ return true;
}
}