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 bool delegate(ref const(Cursor)) isWantedCursorForTypedefs; 53 54 string toString() const 55 { 56 import std.format : format; 57 58 return format( 59 "Options(outputFile = %s, language = %s, enableComments = %s, " ~ 60 "reduceAliases = %s, portableWCharT = %s)", 61 outputFile, 62 language, 63 enableComments, 64 reduceAliases, 65 portableWCharT); 66 } 67 } 68 69 string fullModuleName(string packageName, string path, bool normalize = true) 70 { 71 import std.algorithm; 72 import std.path : baseName, stripExtension; 73 import std.range; 74 import std.uni; 75 import std.utf; 76 77 dchar replace(dchar c) 78 { 79 if (c == '_' || c.isWhite) 80 return '_'; 81 else if (c.isPunctuation) 82 return '.'; 83 else 84 return c; 85 } 86 87 bool discard(dchar c) 88 { 89 return c.isAlphaNum || c == '_' || c == '.'; 90 } 91 92 bool equivalent(dchar a, dchar b) 93 { 94 return (a == '.' || a == '_') && (b == '.' || b == '_'); 95 } 96 97 auto moduleBaseName = stripExtension(baseName(path)); 98 auto moduleName = moduleBaseName.map!replace.filter!discard.uniq!equivalent; 99 100 101 if (normalize) 102 { 103 auto segments = moduleName.split!(x => x == '.'); 104 auto normalized = segments.map!(x => x.toUTF8.toSnakeCase).join('.'); 105 return only(packageName, normalized).join('.'); 106 } 107 else 108 { 109 return only(packageName, moduleName.toUTF8).join('.'); 110 } 111 } 112 113 unittest 114 { 115 assert(fullModuleName("pkg", "foo") == "pkg.foo"); 116 assert(fullModuleName("pkg", "Foo") == "pkg.foo"); 117 assert(fullModuleName("pkg", "Foo.ext") == "pkg.foo"); 118 119 assert(fullModuleName("pkg", "Foo-bar.ext") == "pkg.foo.bar"); 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 125 assert(fullModuleName("pkg", "Foo__bar.ext") == "pkg.foo_bar"); 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 130 assert(fullModuleName("pkg", "FooBarBaz.ext") == "pkg.foo_bar_baz"); 131 assert(fullModuleName("pkg", "FooBar.BazQux.ext") == "pkg.foo_bar.baz_qux"); 132 133 assert(fullModuleName("pkg", "FooBarBaz.ext", false) == "pkg.FooBarBaz"); 134 assert(fullModuleName("pkg", "FooBar.BazQux.ext", false) == "pkg.FooBar.BazQux"); 135 }