forked from xiemaisi/acg.js
-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathmain.js
More file actions
120 lines (101 loc) · 3.19 KB
/
main.js
File metadata and controls
120 lines (101 loc) · 3.19 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
/*******************************************************************************
* Copyright (c) 2013 Max Schaefer.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Max Schaefer - initial API and implementation
*******************************************************************************/
var bindings = require('./bindings'),
astutil = require('./astutil'),
pessimistic = require('./pessimistic'),
semioptimistic = require('./semioptimistic'),
diagnostics = require('./diagnostics'),
callbackCounter = require('./callbackCounter'),
requireJsGraph = require('./requireJsGraph');
ArgumentParser = require('argparse').ArgumentParser;
var argParser = new ArgumentParser({
addHelp: true,
description: 'Call graph generator'
});
argParser.addArgument(
[ '--fg' ],
{ nargs: 0,
help: 'print flow graph' }
);
argParser.addArgument(
[ '--cg' ],
{ nargs: 0,
help: 'print call graph' }
);
argParser.addArgument(
[ '--time' ],
{ nargs: 0,
help: 'print timings' }
);
argParser.addArgument(
[ '--strategy' ],
{ help: 'interprocedural propagation strategy; one of NONE, ONESHOT (default), DEMAND, and FULL (not yet implemented) '}
);
argParser.addArgument(
[ '--countCB' ],
{ nargs: 0,
help: 'Counts the number of callbacks.'
}
);
argParser.addArgument(
[ '--reqJs' ],
{ nargs: 0,
help: 'Make a RequireJS dependency graph.'
}
);
var r = argParser.parseKnownArgs();
var args = r[0],
files = r[1];
args.strategy = args.strategy || 'ONESHOT';
if (!args.strategy.match(/^(NONE|ONESHOT|DEMAND|FULL)$/)) {
argParser.printHelp();
process.exit(-1);
}
if (args.strategy === 'FULL') {
console.warn('strategy FULL not implemented yet; using DEMAND instead');
args.strategy = 'DEMAND';
}
var times = [];
if (args.time) console.time("parsing ");
var ast = astutil.buildAST(files);
if (args.time) console.timeEnd("parsing ");
if (args.time) console.time("bindings ");
bindings.addBindings(ast);
if (args.time) console.timeEnd("bindings ");
if (args.time) console.time("callgraph");
var cg;
if (args.strategy === 'NONE' || args.strategy === 'ONESHOT')
cg = pessimistic.buildCallGraph(ast, args.strategy === 'NONE');
else if (args.strategy === 'DEMAND')
cg = semioptimistic.buildCallGraph(ast);
if (args.time) console.timeEnd("callgraph");
if (args.fg)
console.log(cg.fg.dotify());
if (args.countCB)
callbackCounter.countCallbacks(ast);
if (args.reqJs)
requireJsGraph.makeRequireJsGraph(ast).forEach(function(edge) {
console.log(edge.toString());
});
if (args.cg) {
function pp(v) {
if (v.type === 'CalleeVertex')
return astutil.ppPos(v.call);
if (v.type === 'FuncVertex')
return astutil.ppPos(v.func);
if (v.type === 'NativeVertex')
return v.name;
throw new Error("strange vertex: " + v);
}
cg.edges.iter(function (call, fn) {
console.log(pp(call) + " -> " + pp(fn));
});
}