1 /** 2 * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved. 3 * Authors: Jacob Carlborg 4 * Version: Initial created: Oct 1, 2011 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 */ 7 module dstep.driver.Application; 8 9 import std.getopt; 10 import std.stdio : writeln, stderr; 11 import Path = std.path : setExtension; 12 13 import DStack = dstack.application.Application; 14 15 import mambo.core._; 16 import mambo.util.Singleton; 17 import mambo.util.Use; 18 19 import clang.c.Index; 20 21 import clang.Compiler; 22 import clang.Index; 23 import clang.TranslationUnit; 24 import clang.Util; 25 26 import dstep.core.Exceptions; 27 import dstep.translator.Translator; 28 29 class Application : DStack.Application 30 { 31 mixin Singleton; 32 33 enum Version = "0.2.1"; 34 35 private 36 { 37 string[] inputFiles; 38 39 Index index; 40 TranslationUnit translationUnit; 41 DiagnosticVisitor diagnostics; 42 43 Language language; 44 string[] argsToRestore; 45 bool helpFlag; 46 Compiler compiler; 47 } 48 49 protected override void run () 50 { 51 handleArguments; 52 inputFiles ~= arguments.argument.input; 53 startConversion(inputFiles.first); 54 } 55 56 protected override void setupArguments () 57 { 58 arguments.sloppy = true; 59 arguments.passThrough = true; 60 61 arguments.argument("input", "input files"); 62 63 arguments('o', "output", "Write output to") 64 .params(1) 65 .defaults(&defaultOutputFilename); 66 67 arguments('x', "language", "Treat subsequent input files as having type <language>") 68 .params(1) 69 .restrict("c", "c-header", "objective-c", "objective-c-header") 70 .on(&handleLanguage); 71 72 arguments("objective-c", "Treat source input file as Objective-C input."); 73 } 74 75 private: 76 77 string defaultOutputFilename () 78 { 79 return Path.setExtension(arguments.argument.input, "d"); 80 } 81 82 void startConversion (string file) 83 { 84 if (arguments["objective-c"]) 85 argsToRestore ~= "-ObjC"; 86 87 index = Index(false, false); 88 translationUnit = TranslationUnit.parse(index, file, compilerArgs, 89 compiler.extraHeaders); 90 91 if (!translationUnit.isValid) 92 throw new DStepException("An unknown error occurred"); 93 94 diagnostics = translationUnit.diagnostics; 95 96 scope (exit) 97 clean; 98 99 if (handleDiagnostics) 100 { 101 Translator.Options options; 102 options.outputFile = arguments.output; 103 options.language = language; 104 105 auto translator = new Translator(file, translationUnit, options); 106 translator.translate; 107 } 108 } 109 110 void clean () 111 { 112 translationUnit.dispose; 113 index.dispose; 114 } 115 116 bool anyErrors () 117 { 118 return diagnostics.length > 0; 119 } 120 121 void handleArguments () 122 { 123 // FIXME: Cannot use type inference here, probably a bug. Results in segfault. 124 if (arguments.rawArgs.any!((string e) => e == "-ObjC")) 125 handleObjectiveC(); 126 } 127 128 void handleObjectiveC () 129 { 130 argsToRestore ~= "-ObjC"; 131 language = Language.objC; 132 } 133 134 void handleLanguage (string language) 135 { 136 switch (language) 137 { 138 case "c": 139 case "c-header": 140 this.language = Language.c; 141 break; 142 143 // Can't handle C++ yet 144 // 145 // case "c++": 146 // case "c++-header": 147 // this.language = Language.cpp; 148 // break; 149 150 case "objective-c": 151 case "objective-c-header": 152 this.language = Language.objC; 153 break; 154 155 default: 156 throw new DStepException(`Unrecognized language "` ~ language ~ `"`); 157 } 158 159 argsToRestore ~= "-x"; 160 argsToRestore ~= language; 161 } 162 163 @property string[] remainingArgs () 164 { 165 return arguments.rawArgs[1 .. $] ~ argsToRestore; 166 } 167 168 string[] extraArgs () 169 { 170 return compiler.extraIncludePaths.map!(e => "-I" ~ e).toArray; 171 } 172 173 string[] compilerArgs () 174 { 175 return remainingArgs ~ extraArgs; 176 } 177 178 bool handleDiagnostics () 179 { 180 bool translate = true; 181 182 foreach (diag ; diagnostics) 183 { 184 auto severity = diag.severity; 185 186 with (CXDiagnosticSeverity) 187 if (translate) 188 translate = !(severity == CXDiagnostic_Error || severity == CXDiagnostic_Fatal); 189 190 writeln(stderr, diag.format); 191 } 192 193 return translate; 194 } 195 196 override protected void showHelp () 197 { 198 helpFlag = true; 199 200 println("Usage: dstep [options] <input>"); 201 println("Version: ", Version); 202 println(); 203 println("Options:"); 204 println(" -o, --output <file> Write output to <file>."); 205 println(" -ObjC, --objective-c Treat source input file as Objective-C input."); 206 println(" -x, --language <language> Treat subsequent input files as having type <language>."); 207 println(" -h, --help Show this message and exit."); 208 println(); 209 println("All options that Clang accepts can be used as well."); 210 println(); 211 println("Use the `-h' flag for help."); 212 } 213 }