-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmake-inc
More file actions
executable file
·274 lines (226 loc) · 7.04 KB
/
Copy pathmake-inc
File metadata and controls
executable file
·274 lines (226 loc) · 7.04 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
#!/usr/bin/env qore
# -*- mode: qore; indent-tabs-mode: nil -*-
%requires qore >= 2.3
%requires Util
%requires FsUtil
%new-style
%strict-args
%require-types
%enable-all-warnings
%exec-class MakeInc
hashdecl JarClassInfo {
# java name (ex: java/lang/Class)
string jname;
# binary name (ex: java.lang.Class)
string bname;
# C++ class variable name
string cpp_var;
# binary class data variable name
string class_data_var_name;
# length of class data
int len;
# length of compressed data
int compressed_len;
}
class MakeInc {
private {
# command-line options
hash<auto> opts;
# list of classes
list<hash<JarClassInfo>> jar_classes;
date pstart;
date accum = 0s;
const Opts = {
"test": "T,test",
"verbose": "v,verbose:i+",
"help": "h,help",
};
const BlockSize = 4096;
const LineSize = 12;
}
constructor() {
GetOpt g(Opts);
opts = g.parse3(\ARGV);
*string file = shift ARGV;
if (opts.help || !exists file) {
usage();
}
*string outname = shift ARGV;
if (exists outname) {
if (is_dir(outname)) {
outname = dirname(outname) + DirSep + basename(getName(file));
}
} else {
outname = getName(file);
}
if (file =~ /\.class$/) {
doClass(file, outname);
} else if (file =~ /\.jar$/) {
doJar(file, outname);
} else {
printf("%y: unrecognized file type\n", file);
}
}
private doJar(string file, string outname) {
if (opts.verbose) {
printf("processing %s -> %s\n", file, outname);
}
string orig_outname = outname;
# get abolute paths to files
file = normalize_dir(file);
outname = normalize_dir(outname);
TmpDir tmp();
# unzip jar
chdir(tmp.path);
string cmd = "unzip ";
if (opts.verbose < 2) {
cmd += "-q ";
}
cmd += sprintf("%y", file);
system(cmd);
#FileInputStream f(file);
StreamWriter w(new FileOutputStream(outname));
if (!opts.verbose) {
printf("generating %s: ", orig_outname);
}
pstart = now_us();
# scan dirs
scanDirs(w, tmp.path);
if (!opts.verbose) {
print(" done\n");
}
# output class map
w.print("DLLLOCAL cmap_t jar_cmap = {\n");
map w.printf(" {%y, {%d, %d, %s}},\n", $1.bname, $1.compressed_len, $1.len, $1.class_data_var_name),
jar_classes;
w.print("};\n");
}
private scanDirs(StreamWriter w, string path, *string jpath) {
if (opts.test && (now_us() - pstart) > 2s) {
return;
}
Dir d();
d.chdir(path);
list<string> targ = d.listDirs("^(?!.*?META-INF).*$");
foreach string name in (targ) {
*string njpath = jpath;
if (exists jpath) {
njpath += "/";
}
njpath += name;
scanDirs(w, path + "/" + name, njpath);
}
# process inner classes first
targ = d.listFiles(".*\\$.*\\.class$");
map processClass(w, path, jpath, $1), targ;
targ = d.listFiles("^(?!.*?\\$).*\\.class$");
map processClass(w, path, jpath, $1), targ;
}
private processClass(StreamWriter w, string path, string jpath, string name) {
if (opts.test && (now_us() - pstart) > 2s) {
return;
}
*string jname = jpath;
if (exists jpath) {
jname += "/";
}
jname += name;
jname =~ s/\.class$//;
string file = path + "/" + name;
if (opts.verbose) {
printf("processing %y: ", jname);
} else {
print(".");
flush();
}
string bname = jname;
bname =~ s/\//./g;
string vname = jname;
vname =~ s/[-\/\$]/_/g;
string class_data_var_name = sprintf("java_%s_class_data", vname);
date start = now_us();
int len;
int compressed_len = doClassFile(new FileInputStream(file), w, file, class_data_var_name, True, \len);
hash<JarClassInfo> info({
"jname": jname,
"bname": bname,
"cpp_var": vname,
"class_data_var_name": class_data_var_name,
"len": len,
"compressed_len": compressed_len,
});
w.print("\n");
# XXX DEBUG
date delta = now_us() - start;
accum += delta;
if (opts.verbose) {
# XXX DEBUG
printf("%y ", delta);
printf("%d bytes\n", info.len);
}
jar_classes += info;
}
private doClass(string file, string outname) {
if (opts.verbose) {
printf("processing %s -> %s\n", file, outname);
}
FileInputStream f(file);
StreamWriter w(new FileOutputStream(outname));
string cpp_var = basename(file);
{
int i = cpp_var.rfind(".");
if (i != -1) {
splice cpp_var, i;
}
}
cpp_var =~ s/\$/_/g;
cpp_var = sprintf("java_org_qore_jni_%s_class", cpp_var);
int len = doClassFile(f, w, file, cpp_var);
string oname = basename(file);
oname =~ s/[\.\$]/_/g;
w.printf("\nstatic unsigned int java_org_qore_jni_%s_len = %d;\n", oname, len);
}
private int doClassFile(InputStream f, StreamWriter w, string file, string cpp_var, *bool compress, *reference<int> orig_size) {
w.printf("// generated from %s\nstatic unsigned char %s[] = {", file, cpp_var);
hash<StatInfo> statinfo = hstat(file);
*binary b = f.read(statinfo.size);
if (!b)
return 0;
if (compress) {
orig_size = b.size();
# compress data
b = bzip2(b, 9);
}
int size = b.size();
# Fast path: one C++ call replaces the per-byte Qore printf loop.
# ~170x faster on a 1 MB payload per the qore-bench harness.
# Output is byte-exact with the old loop: each line starts with
# "\n " then 12 bytes of " 0xNN,". Requires Qore >= 2.3 for
# <binary>::toHexArray (the %requires qore line at the top of this
# file gates it).
if (size > 0) {
w.write("\n ");
w.write(b.toHexArray(" 0x", ",", LineSize, "\n "));
}
w.print("\n};\n");
return size;
}
static usage() {
printf("usage: %s [options] class|jar [output_file]
-h,--help this help text
-v,--verbose[=ARG] verbosity level
",
get_script_name());
exit(1);
}
static string getName(string name) {
int i = name.rfind(".");
if (i != -1)
splice name, i;
name += ".inc";
i = name.rfind(DirSep);
if (i != -1)
splice name, i + 1, 0, "JavaClass";
return name;
}
}