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"); 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 Options toOptions(string inputFile, string outputFile) const 109 { 110 Options options = toOptions(); 111 112 options.inputFile = inputFile.asAbsNormPath; 113 options.outputFile = outputFile.asAbsNormPath; 114 115 return options; 116 } 117 118 Options toOptions() const 119 { 120 import std.algorithm.iteration : map; 121 import std.array; 122 123 Options options; 124 options.inputFiles = inputFiles.map!(path => path.asAbsNormPath).array; 125 options.language = language; 126 options.enableComments = enableComments; 127 options.packageName = packageName; 128 options.publicSubmodules = publicSubmodules; 129 options.normalizeModules = normalizeModules; 130 options.reduceAliases = reduceAliases; 131 options.translateMacros = translateMacros; 132 options.aliasEnumMembers = aliasEnumMembers; 133 options.renameEnumMembers = renameEnumMembers; 134 options.portableWCharT = portableWCharT; 135 options.zeroParamIsVararg = zeroParamIsVararg; 136 options.singleLineFunctionSignatures = singleLineFunctionSignatures; 137 options.spaceAfterFunctionName = spaceAfterFunctionName; 138 options.skipDefinitions = setFromList(skipDefinitions); 139 options.skipSymbols = setFromList(skipSymbols); 140 options.printDiagnostics = printDiagnostics; 141 options.collisionAction = collisionAction; 142 options.globalAttributes = globalAttributes; 143 144 return options; 145 } 146 } 147 148 template makeGetOptArgs(alias config) 149 { 150 import std.meta; 151 152 template expand(alias spelling) 153 { 154 alias member = Alias!(__traits(getMember, config, spelling)); 155 156 static if ( 157 __traits(compiles, &__traits(getMember, config, spelling)) && 158 __traits(getAttributes, member).length == 2) 159 { 160 auto ptr() @property 161 { 162 return &__traits(getMember, config, spelling); 163 } 164 165 auto formatHelp(alias spelling)(string help) 166 { 167 import std.algorithm; 168 import std.format; 169 import std..string; 170 import std.range; 171 172 Configuration config; 173 174 string suffix; 175 176 static if (is(typeof(member) == bool) || is(typeof(member) == enum)) 177 { 178 auto default_ = "[default]"; 179 180 if (help.canFind(default_)) 181 { 182 help = help.replace( 183 default_, 184 format("[default: %s]", __traits(getMember, config, spelling))); 185 186 static if (is(typeof(member) == bool)) 187 { 188 suffix = "=true|false"; 189 } 190 else 191 { 192 suffix = format( 193 "=%s", 194 join([ __traits(allMembers, typeof(member)) ], "|")); 195 } 196 } 197 } 198 else 199 { 200 auto beginning = findSplitBefore(help, "<"); 201 202 if (!beginning[0].empty) 203 { 204 auto placeholder = findSplitAfter(beginning[1], ">"); 205 206 if (!placeholder[0].empty) 207 suffix = format(" %s", placeholder[0]); 208 } 209 } 210 211 return format("%s!%s", suffix, help); 212 } 213 214 alias expand = AliasSeq!( 215 __traits(getAttributes, __traits(getMember, config, spelling))[0], 216 formatHelp!spelling( 217 __traits(getAttributes, __traits(getMember, config, spelling))[1]), 218 ptr); 219 } 220 else 221 { 222 alias expand = AliasSeq!(); 223 } 224 } 225 226 alias makeGetOptArgs = staticMap!(expand, __traits(allMembers, typeof(config))); 227 } 228