1 /** 2 * Copyright: Copyright (c) 2016 Jacob Carlborg. All rights reserved. 3 * Authors: Jacob Carlborg 4 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 5 */ 6 module dstep.Configuration; 7 8 import clang.Util; 9 10 import dstep.translator.Options; 11 12 /** 13 * Aggregation of global configuration options affecting the program 14 */ 15 struct Configuration 16 { 17 /// app version string, generated by the build system 18 enum Version = import("VERSION")[1 .. $]; // strip the leading 'v' 19 20 /// array of file names to translate to D 21 string[] inputFiles; 22 23 /// expected programming language of input files 24 Language language; 25 26 /// show dstep version 27 @("version", "Show dstep version.") 28 bool dstepVersion; 29 30 /// show libclang version 31 @("clang-version", "Show libclang version.") 32 bool clangVersion; 33 34 /// array of parameters needed to be forwarded to clang driver 35 string[] clangParams; 36 37 /// output file name or folder (in case there are many input files) 38 string output; 39 40 /// package name 41 @("package", "Use <package> as package name.") 42 string packageName; 43 44 /// enable translation of comments 45 @("comments", "Translate comments [default].") 46 bool enableComments = true; 47 48 /// use public imports for submodules 49 @("public-submodules", "Use public imports for submodules [default].") 50 bool publicSubmodules = false; 51 52 // rename modules to D conforming form 53 @("normalize-modules", "Rename modules to D conforming form [default].") 54 bool normalizeModules = false; 55 56 /// enable reduction of primitive type aliases 57 @("reduce-aliases", "Reduce primitive type aliases [default].") 58 bool reduceAliases = true; 59 60 /// translate C preprocessor macros if possible 61 @("translate-macros", "Translate C preprocessor macros if possible [default].") 62 bool translateMacros = true; 63 64 /// generate aliases for enum members in global scope 65 @("alias-enum-members", "Generate aliases for enum members in global scope [default].") 66 bool aliasEnumMembers = false; 67 68 /// attempt to rename the enumeration members to D conforming form 69 @("rename-enum-members", "Attempt to rename the enumeration members to D conforming form. [default].") 70 bool renameEnumMembers = false; 71 72 /// translate to wchar_t to core.stdc.stddef.wchar_t 73 @("portable-wchar_t", "Translate wchar_t as core.stdc.stddef.wchar_t [default].") 74 bool portableWCharT = true; 75 76 /// translate functions with empty argument list as vararg 77 @("zero-param-is-vararg", "Translate functions with no arguments as variadic functions [default].") 78 bool zeroParamIsVararg = false; 79 80 /// single line function headers 81 @("single-line-function-signatures", "Keep function signatures in a single line [default].") 82 bool singleLineFunctionSignatures = false; 83 84 /// space after function name 85 @("space-after-function-name", "Put a space after a function name [default].") 86 bool spaceAfterFunctionName = true; 87 88 /// do not translate bodies of following structs and unions 89 @("skip-definition", "Keep only the signature of <symbol>.") 90 string[] skipDefinitions; 91 92 /// do not translate following symbols 93 @("skip", "Skip translation of <symbol>.") 94 string[] skipSymbols; 95 96 /// print diagnostic informations 97 @("print-diagnostics", "Print diagnostic informations [default].") 98 bool printDiagnostics = true; 99 100 /// action to take on symbol collision 101 @("collision-action", "Action to take when translated symbol collides with a preexisting symbol [default].") 102 CollisionAction collisionAction = CollisionAction.rename; 103 104 /// add global attributes 105 @("global-attribute", "Add <attribute> as a global attribute.") 106 string[] globalAttributes; 107 108 /// add global imports 109 @("global-import", "Add <import> as a global import.") 110 string[] globalImports; 111 112 Options toOptions(string inputFile, string outputFile) const 113 { 114 Options options = toOptions(); 115 116 options.inputFile = inputFile.asAbsNormPath; 117 options.outputFile = outputFile.asAbsNormPath; 118 119 return options; 120 } 121 122 Options toOptions() const 123 { 124 import std.algorithm.iteration : map; 125 import std.array; 126 127 Options options; 128 options.inputFiles = inputFiles.map!(path => path.asAbsNormPath).array; 129 options.language = language; 130 options.enableComments = enableComments; 131 options.packageName = packageName; 132 options.publicSubmodules = publicSubmodules; 133 options.normalizeModules = normalizeModules; 134 options.reduceAliases = reduceAliases; 135 options.translateMacros = translateMacros; 136 options.aliasEnumMembers = aliasEnumMembers; 137 options.renameEnumMembers = renameEnumMembers; 138 options.portableWCharT = portableWCharT; 139 options.zeroParamIsVararg = zeroParamIsVararg; 140 options.singleLineFunctionSignatures = singleLineFunctionSignatures; 141 options.spaceAfterFunctionName = spaceAfterFunctionName; 142 options.skipDefinitions = setFromList(skipDefinitions); 143 options.skipSymbols = setFromList(skipSymbols); 144 options.printDiagnostics = printDiagnostics; 145 options.collisionAction = collisionAction; 146 options.globalAttributes = globalAttributes; 147 options.globalImports = globalImports; 148 149 return options; 150 } 151 } 152 153 template makeGetOptArgs(alias config) 154 { 155 import std.meta; 156 157 template expand(alias spelling) 158 { 159 alias member = Alias!(__traits(getMember, config, spelling)); 160 161 static if ( 162 __traits(compiles, &__traits(getMember, config, spelling)) && 163 __traits(getAttributes, member).length == 2) 164 { 165 auto ptr() @property 166 { 167 return &__traits(getMember, config, spelling); 168 } 169 170 auto formatHelp(alias spelling)(string help) 171 { 172 import std.algorithm; 173 import std.format; 174 import std..string; 175 import std.range; 176 177 Configuration config; 178 179 string suffix; 180 181 static if (is(typeof(member) == bool) || is(typeof(member) == enum)) 182 { 183 auto default_ = "[default]"; 184 185 if (help.canFind(default_)) 186 { 187 help = help.replace( 188 default_, 189 format("[default: %s]", __traits(getMember, config, spelling))); 190 191 static if (is(typeof(member) == bool)) 192 { 193 suffix = "=true|false"; 194 } 195 else 196 { 197 suffix = format( 198 "=%s", 199 join([ __traits(allMembers, typeof(member)) ], "|")); 200 } 201 } 202 } 203 else 204 { 205 auto beginning = findSplitBefore(help, "<"); 206 207 if (!beginning[0].empty) 208 { 209 auto placeholder = findSplitAfter(beginning[1], ">"); 210 211 if (!placeholder[0].empty) 212 suffix = format(" %s", placeholder[0]); 213 } 214 } 215 216 return format("%s!%s", suffix, help); 217 } 218 219 alias expand = AliasSeq!( 220 __traits(getAttributes, __traits(getMember, config, spelling))[0], 221 formatHelp!spelling( 222 __traits(getAttributes, __traits(getMember, config, spelling))[1]), 223 ptr); 224 } 225 else 226 { 227 alias expand = AliasSeq!(); 228 } 229 } 230 231 alias makeGetOptArgs = staticMap!(expand, __traits(allMembers, typeof(config))); 232 } 233