1 /** 2 * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved. 3 * Authors: Wojciech Szęszoł 4 * Version: Initial created: May 21, 2016 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 */ 7 module dstep.translator.Options; 8 9 import clang.Util; 10 11 import dstep.translator.ConvertCase; 12 13 enum Language 14 { 15 c, 16 objC 17 } 18 19 enum CollisionAction 20 { 21 ignore, 22 rename, 23 abort 24 } 25 26 struct Options 27 { 28 import clang.Cursor: Cursor; 29 30 string[] inputFiles; 31 string inputFile; 32 string outputFile; 33 Language language = Language.c; 34 string packageName; 35 bool enableComments = true; 36 bool publicSubmodules = false; 37 bool normalizeModules = false; 38 bool keepUntranslatable = false; 39 bool reduceAliases = true; 40 bool translateMacros = true; 41 bool portableWCharT = true; 42 bool zeroParamIsVararg = false; 43 bool singleLineFunctionSignatures = false; 44 bool spaceAfterFunctionName = true; 45 bool aliasEnumMembers = false; 46 bool renameEnumMembers = false; 47 Set!string skipDefinitions; 48 Set!string skipSymbols; 49 bool printDiagnostics = true; 50 CollisionAction collisionAction = CollisionAction.rename; 51 const(string)[] globalAttributes; 52 const(string)[] globalImports; 53 bool delegate(ref const(Cursor)) isWantedCursorForTypedefs; 54 55 string toString() const 56 { 57 import std.format : format; 58 59 return format( 60 "Options(outputFile = %s, language = %s, enableComments = %s, " ~ 61 "reduceAliases = %s, portableWCharT = %s)", 62 outputFile, 63 language, 64 enableComments, 65 reduceAliases, 66 portableWCharT); 67 } 68 } 69 70 string fullModuleName(string packageName, string path, bool normalize = true) 71 { 72 import std.algorithm; 73 import std.path : baseName, stripExtension; 74 import std.range; 75 import std.uni; 76 import std.utf; 77 78 dchar replace(dchar c) 79 { 80 if (c == '_' || c.isWhite) 81 return '_'; 82 else if (c.isPunctuation) 83 return '.'; 84 else 85 return c; 86 } 87 88 bool discard(dchar c) 89 { 90 return c.isAlphaNum || c == '_' || c == '.'; 91 } 92 93 bool equivalent(dchar a, dchar b) 94 { 95 return (a == '.' || a == '_') && (b == '.' || b == '_'); 96 } 97 98 auto moduleBaseName = stripExtension(baseName(path)); 99 auto moduleName = moduleBaseName.map!replace.filter!discard.uniq!equivalent; 100 101 102 if (normalize) 103 { 104 auto segments = moduleName.split!(x => x == '.'); 105 auto normalized = segments.map!(x => x.toUTF8.toSnakeCase).join('.'); 106 return only(packageName, normalized).join('.'); 107 } 108 else 109 { 110 return only(packageName, moduleName.toUTF8).join('.'); 111 } 112 } 113 114 unittest 115 { 116 assert(fullModuleName("pkg", "foo") == "pkg.foo"); 117 assert(fullModuleName("pkg", "Foo") == "pkg.foo"); 118 assert(fullModuleName("pkg", "Foo.ext") == "pkg.foo"); 119 120 assert(fullModuleName("pkg", "Foo-bar.ext") == "pkg.foo.bar"); 121 assert(fullModuleName("pkg", "Foo_bar.ext") == "pkg.foo_bar"); 122 assert(fullModuleName("pkg", "Foo@bar.ext") == "pkg.foo.bar"); 123 assert(fullModuleName("pkg", "Foo~bar.ext") == "pkg.foo.bar"); 124 assert(fullModuleName("pkg", "Foo bar.ext") == "pkg.foo_bar"); 125 126 assert(fullModuleName("pkg", "Foo__bar.ext") == "pkg.foo_bar"); 127 assert(fullModuleName("pkg", "Foo..bar.ext") == "pkg.foo.bar"); 128 assert(fullModuleName("pkg", "Foo#$%#$%#bar.ext") == "pkg.foo.bar"); 129 assert(fullModuleName("pkg", "Foo_#$%#$%#bar.ext") == "pkg.foo_bar"); 130 131 assert(fullModuleName("pkg", "FooBarBaz.ext") == "pkg.foo_bar_baz"); 132 assert(fullModuleName("pkg", "FooBar.BazQux.ext") == "pkg.foo_bar.baz_qux"); 133 134 assert(fullModuleName("pkg", "FooBarBaz.ext", false) == "pkg.FooBarBaz"); 135 assert(fullModuleName("pkg", "FooBar.BazQux.ext", false) == "pkg.FooBar.BazQux"); 136 }