-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.d
More file actions
322 lines (294 loc) · 7.91 KB
/
Copy pathmain.d
File metadata and controls
322 lines (294 loc) · 7.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
// Copyright Brian Schott (Sir Alaran) 2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module main;
import std.algorithm;
import std.array;
import std.conv;
import std.file;
import std.getopt;
import std.path;
import std.stdio;
import std.range;
import std.lexer;
import std.d.lexer;
import std.d.parser;
import highlighter;
import stats;
import ctags;
import astprinter;
import imports;
import outliner;
import analysis.run;
int main(string[] args)
{
version (unittest)
{
return 0;
}
else
{
return run(args);
}
}
int run(string[] args)
{
// Make backtraces work in Linux
version(linux) {
import backtrace;
PrintOptions options;
options.detailedForN = 2; //number of frames to show code for
options.numberOfLinesBefore = 3; //number of lines of code to show before the specific line
options.numberOfLinesAfter = 3; //number of lines of code to show after the specific line
options.colored = false; //enable colored output for the backtrace
options.stopAtDMain = true; //show stack traces after the entry point of the D code
backtrace.install(stderr, options);
}
bool sloc;
bool highlight;
bool ctags;
bool recursive;
bool help;
bool tokenCount;
bool syntaxCheck;
bool ast;
bool imports;
bool muffin;
bool outline;
bool tokenDump;
bool styleCheck;
try
{
getopt(args, "sloc|l", &sloc, "highlight", &highlight,
"ctags|c", &ctags, "recursive|r|R", &recursive, "help|h", &help,
"tokenCount|t", &tokenCount, "syntaxCheck|s", &syntaxCheck,
"ast|xml", &ast, "imports|i", &imports, "outline|o", &outline,
"tokenDump", &tokenDump, "styleCheck", &styleCheck,
"muffinButton", &muffin);
}
catch (ConvException e)
{
stderr.writeln(e.msg);
return 1;
}
if (muffin)
{
stdout.writeln(
` ___________
__(#*O 0** @%*)__
_(%*o#*O%*0 #O#%##@)_
(*#@%#o*@ #o%O*%@ #o #)
\=====================/
|I|I|I|I|I|I|I|I|I|I|
|I|I|I|I|I|I|I|I|I|I|
|I|I|I|I|I|I|I|I|I|I|
|I|I|I|I|I|I|I|I|I|I|`);
return 0;
}
if (help)
{
printHelp(args[0]);
return 0;
}
auto optionCount = count!"a"([sloc, highlight, ctags, tokenCount,
syntaxCheck, ast, imports, outline, tokenDump, styleCheck]);
if (optionCount > 1)
{
stderr.writeln("Too many options specified");
return 1;
}
else if (optionCount < 1)
{
printHelp(args[0]);
return 1;
}
StringCache* cache = new StringCache(StringCache.defaultBucketCount);
if (tokenDump || highlight)
{
bool usingStdin = args.length == 1;
ubyte[] bytes = usingStdin ? readStdin() : readFile(args[1]);
LexerConfig config;
config.whitespaceBehavior = WhitespaceBehavior.include;
config.stringBehavior = StringBehavior.source;
config.commentBehavior = CommentBehavior.include;
config.specialTokenBehavior = SpecialTokenBehavior.include;
auto tokens = byToken(bytes, config, cache);
if (highlight)
{
highlighter.highlight(tokens, args.length == 1 ? "stdin" : args[1]);
return 0;
}
else if (tokenDump)
{
writeln("text blank\tindex\tline\tcolumn\ttype");
foreach (token; tokens)
{
writefln("<<%20s>>%b\t%d\t%d\t%d\t%d", token.text is null ? str(token.type) : token.text,
token.text !is null, token.index, token.line, token.column, token.type);
}
return 0;
}
}
else if (ctags)
{
stdout.printCtags(expandArgs(args, recursive));
}
else if (styleCheck)
{
stdout.analyze(expandArgs(args, recursive), AnalyzerCheck.all);
}
else if (syntaxCheck)
{
stdout.syntaxCheck(expandArgs(args, recursive));
}
else
{
bool usingStdin = args.length == 1;
if (sloc || tokenCount)
{
if (usingStdin)
{
LexerConfig config;
config.whitespaceBehavior = WhitespaceBehavior.include;
config.stringBehavior = StringBehavior.source;
config.commentBehavior = CommentBehavior.include;
auto tokens = byToken(readStdin(), config, cache);
if (tokenCount)
printTokenCount(stdout, "stdin", tokens);
else
printLineCount(stdout, "stdin", tokens);
}
else
{
ulong count;
foreach (f; expandArgs(args, recursive))
{
LexerConfig config;
config.whitespaceBehavior = WhitespaceBehavior.skip;
config.stringBehavior = StringBehavior.source;
config.commentBehavior = CommentBehavior.include;
auto tokens = byToken(readFile(f), config, cache);
if (tokenCount)
count += printTokenCount(stdout, f, tokens);
else
count += printLineCount(stdout, f, tokens);
}
writefln("total:\t%d", count);
}
}
else if (imports || ast || outline)
{
auto tokens = byToken(usingStdin ? readStdin() : readFile(args[1]));
auto mod = parseModule(tokens.array(), usingStdin ? "stdin" : args[1],
null, &doNothing);
if (imports)
{
auto visitor = new ImportPrinter;
visitor.callVisit(mod);
foreach (imp; visitor.imports[])
writeln(imp);
}
else if (ast)
{
auto printer = new XMLPrinter;
printer.output = stdout;
printer.callVisit(mod);
}
else if (outline)
{
auto outliner = new Outliner(stdout);
outliner.callVisit(mod);
}
}
}
return 0;
}
string[] expandArgs(string[] args, bool recursive)
{
if (recursive)
{
string[] rVal;
foreach (arg; args[1 ..$])
{
if (isFile(arg) && arg.endsWith(`.d`) || arg.endsWith(`.di`))
rVal ~= arg;
else foreach (item; dirEntries(arg, SpanMode.breadth).map!(a => a.name))
{
if (isFile(item) && (item.endsWith(`.d`) || item.endsWith(`.di`)))
rVal ~= item;
else
continue;
}
}
return rVal;
}
else
return args[1 .. $];
}
ubyte[] readStdin()
{
auto sourceCode = appender!(ubyte[])();
ubyte[4096] buf;
while (true)
{
auto b = stdin.rawRead(buf);
if (b.length == 0)
break;
sourceCode.put(b);
}
return sourceCode.data;
}
ubyte[] readFile(string fileName)
{
if (!exists(fileName))
{
stderr.writefln("%s does not exist", fileName);
return [];
}
File f = File(fileName);
ubyte[] sourceCode = uninitializedArray!(ubyte[])(to!size_t(f.size));
f.rawRead(sourceCode);
return sourceCode;
}
void printHelp(string programName)
{
stderr.writefln(
`
Usage: %s options
options:
--help | -h
Prints this help message
--sloc | -l [sourceFiles]
Prints the number of logical lines of code in the given
source files. If no files are specified, input is read from stdin.
--tokenCount | -t [sourceFiles]
Prints the number of tokens in the given source files. If no files are
specified, input is read from stdin.
--highlight [sourceFile] - Syntax-highlight the given source file. The
resulting HTML will be written to standard output. If no files are
specified, input is read from stdin.
--imports | -i [sourceFile]
Prints modules imported by the given source file. If no files are
specified, input is read from stdin.
--syntaxCheck | -s [sourceFile]
Lexes and parses sourceFile, printing the line and column number of any
syntax errors to stdout. One error or warning is printed per line.
If no files are specified, input is read from stdin.
--styleCheck [sourceFiles]
Lexes and parses sourceFiles, printing the line and column number of any
style guideline violations to stdout.
--ctags | -c sourceFile
Generates ctags information from the given source code file. Note that
ctags information requires a filename, so stdin cannot be used in place
of a filename.
--ast | --xml sourceFile
Generates an XML representation of the source files abstract syntax
tree. If no files are specified, input is read from stdin.
--recursive | -R | -r
When used with --ctags, --tokenCount, or --sloc, dscanner will produce
ctags output for all .d and .di files contained within the given
directories and its sub-directories.`,
programName);
}
void doNothing(string, size_t, size_t, string, bool) {}