1 // Copyright Mario Kröplin 2015. 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 6 module main; 7 8 import std.array; 9 import std.stdio; 10 11 int main(string[] args) 12 in 13 { 14 assert(!args.empty); 15 } 16 body 17 { 18 import std.getopt : defaultGetoptPrinter, getopt, GetOptException, GetoptResult; 19 import std.path : baseName; 20 21 GetoptResult result; 22 try 23 { 24 result = getopt(args); 25 } 26 catch (GetOptException exception) 27 { 28 stderr.writeln("error: ", exception.msg); 29 return 1; 30 } 31 if (result.helpWanted) 32 { 33 writefln("Usage: %s [option...] file...", baseName(args[0])); 34 writeln("Reverse engineering of D source code into PlantUML classes."); 35 writeln("If no files are specified, input is read from stdin."); 36 defaultGetoptPrinter("Options:", result.options); 37 return 0; 38 } 39 return process(args[1 .. $]); 40 } 41 42 int process(string[] names) 43 { 44 import dparse.lexer : getTokensForParser, LexerConfig, StringBehavior, StringCache; 45 import dparse.parser : parseModule; 46 47 bool success = true; 48 StringCache cache = StringCache(StringCache.defaultBucketCount); 49 LexerConfig config; 50 config.stringBehavior = StringBehavior.source; 51 52 void outline(ubyte[] sourceCode, string name) 53 { 54 import dparse.rollback_allocator : RollbackAllocator; 55 import outliner : Outliner; 56 import std.typecons : scoped; 57 58 config.fileName = name; 59 auto tokens = getTokensForParser(sourceCode, config, &cache); 60 RollbackAllocator allocator; 61 auto module_ = parseModule(tokens, name, &allocator); 62 auto visitor = scoped!Outliner(stdout, name); 63 visitor.visit(module_); 64 } 65 66 if (names.empty) 67 outline(read(), "stdin"); 68 else 69 { 70 import std.file : FileException, read; 71 72 foreach (name; names) 73 { 74 try 75 { 76 outline(cast(ubyte[]) read(name), name); 77 } 78 catch (FileException exception) 79 { 80 stderr.writeln("error: ", exception.msg); 81 success = false; 82 } 83 } 84 } 85 return success ? 0 : 1; 86 } 87 88 ubyte[] read() 89 { 90 auto content = appender!(ubyte[])(); 91 ubyte[4096] buffer = void; 92 while (!stdin.eof) 93 { 94 auto slice = stdin.rawRead(buffer); 95 if (slice.empty) 96 break; 97 content.put(slice); 98 } 99 return content.data; 100 }