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