OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2006-2008 the V8 project authors. All rights reserved. | 3 # Copyright 2006-2008 the V8 project authors. All rights reserved. |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 15 matching lines...) Expand all Loading... | |
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | 29 |
30 # This is a utility for converting JavaScript source code into C-style | 30 # This is a utility for converting JavaScript source code into C-style |
31 # char arrays. It is used for embedded JavaScript code in the V8 | 31 # char arrays. It is used for embedded JavaScript code in the V8 |
32 # library. | 32 # library. |
33 | 33 |
34 import os, re, sys, string | 34 import os, re, sys, string |
35 import jsmin | 35 import jsmin |
36 import bz2 | |
37 | |
38 | |
39 def ToCAsciiArray(lines): | |
40 result = [] | |
41 for chr in lines: | |
42 value = ord(chr) | |
43 assert value < 128 | |
44 result.append(str(value)) | |
45 return ", ".join(result) | |
36 | 46 |
37 | 47 |
38 def ToCArray(lines): | 48 def ToCArray(lines): |
39 result = [] | 49 result = [] |
40 for chr in lines: | 50 for chr in lines: |
41 value = ord(chr) | 51 result.append(str(ord(chr))) |
42 assert value < 128 | |
43 result.append(str(value)) | |
44 result.append("0") | |
45 return ", ".join(result) | 52 return ", ".join(result) |
46 | 53 |
47 | 54 |
48 def RemoveCommentsAndTrailingWhitespace(lines): | 55 def RemoveCommentsAndTrailingWhitespace(lines): |
49 lines = re.sub(r'//.*\n', '\n', lines) # end-of-line comments | 56 lines = re.sub(r'//.*\n', '\n', lines) # end-of-line comments |
50 lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments. | 57 lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments. |
51 lines = re.sub(r'\s+\n+', '\n', lines) # trailing whitespace | 58 lines = re.sub(r'\s+\n+', '\n', lines) # trailing whitespace |
52 return lines | 59 return lines |
53 | 60 |
54 | 61 |
(...skipping 25 matching lines...) Expand all Loading... | |
80 | 87 |
81 | 88 |
82 def ParseValue(string): | 89 def ParseValue(string): |
83 string = string.strip() | 90 string = string.strip() |
84 if string.startswith('[') and string.endswith(']'): | 91 if string.startswith('[') and string.endswith(']'): |
85 return string.lstrip('[').rstrip(']').split() | 92 return string.lstrip('[').rstrip(']').split() |
86 else: | 93 else: |
87 return string | 94 return string |
88 | 95 |
89 | 96 |
90 EVAL_PATTERN = re.compile(r'\beval\s*\('); | 97 EVAL_PATTERN = re.compile(r'\beval\s*\(') |
91 WITH_PATTERN = re.compile(r'\bwith\s*\('); | 98 WITH_PATTERN = re.compile(r'\bwith\s*\(') |
92 | 99 |
93 | 100 |
94 def Validate(lines, file): | 101 def Validate(lines, file): |
95 lines = RemoveCommentsAndTrailingWhitespace(lines) | 102 lines = RemoveCommentsAndTrailingWhitespace(lines) |
96 # Because of simplified context setup, eval and with is not | 103 # Because of simplified context setup, eval and with is not |
97 # allowed in the natives files. | 104 # allowed in the natives files. |
98 eval_match = EVAL_PATTERN.search(lines) | 105 eval_match = EVAL_PATTERN.search(lines) |
99 if eval_match: | 106 if eval_match: |
100 raise ("Eval disallowed in natives: %s" % file) | 107 raise ("Eval disallowed in natives: %s" % file) |
101 with_match = WITH_PATTERN.search(lines) | 108 with_match = WITH_PATTERN.search(lines) |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
205 | 212 |
206 HEADER_TEMPLATE = """\ | 213 HEADER_TEMPLATE = """\ |
207 // Copyright 2011 Google Inc. All Rights Reserved. | 214 // Copyright 2011 Google Inc. All Rights Reserved. |
208 | 215 |
209 // This file was generated from .js source files by SCons. If you | 216 // This file was generated from .js source files by SCons. If you |
210 // want to make changes to this file you should either change the | 217 // want to make changes to this file you should either change the |
211 // javascript source files or the SConstruct script. | 218 // javascript source files or the SConstruct script. |
212 | 219 |
213 #include "v8.h" | 220 #include "v8.h" |
214 #include "natives.h" | 221 #include "natives.h" |
222 #include "utils.h" | |
215 | 223 |
216 namespace v8 { | 224 namespace v8 { |
217 namespace internal { | 225 namespace internal { |
218 | 226 |
219 %(source_lines)s\ | 227 %(source_lines)s\ |
220 | 228 |
229 %(raw_source_lines)s\ | |
230 | |
221 template <> | 231 template <> |
222 int NativesCollection<%(type)s>::GetBuiltinsCount() { | 232 int NativesCollection<%(type)s>::GetBuiltinsCount() { |
223 return %(builtin_count)i; | 233 return %(builtin_count)i; |
224 } | 234 } |
225 | 235 |
226 template <> | 236 template <> |
227 int NativesCollection<%(type)s>::GetDebuggerCount() { | 237 int NativesCollection<%(type)s>::GetDebuggerCount() { |
228 return %(debugger_count)i; | 238 return %(debugger_count)i; |
229 } | 239 } |
230 | 240 |
231 template <> | 241 template <> |
232 int NativesCollection<%(type)s>::GetIndex(const char* name) { | 242 int NativesCollection<%(type)s>::GetIndex(const char* name) { |
233 %(get_index_cases)s\ | 243 %(get_index_cases)s\ |
234 return -1; | 244 return -1; |
235 } | 245 } |
236 | 246 |
237 template <> | 247 template <> |
238 Vector<const char> NativesCollection<%(type)s>::GetScriptSource(int index) { | 248 int NativesCollection<%(type)s>::GetRawScriptSize(int index) { |
239 %(get_script_source_cases)s\ | 249 %(get_raw_script_size_cases)s\ |
250 return -1; | |
251 } | |
252 | |
253 template <> | |
254 Vector<const char> NativesCollection<%(type)s>::GetRawScriptSource(int index) { | |
255 %(get_raw_script_source_cases)s\ | |
240 return Vector<const char>("", 0); | 256 return Vector<const char>("", 0); |
241 } | 257 } |
242 | 258 |
243 template <> | 259 template <> |
244 Vector<const char> NativesCollection<%(type)s>::GetScriptName(int index) { | 260 Vector<const char> NativesCollection<%(type)s>::GetScriptName(int index) { |
245 %(get_script_name_cases)s\ | 261 %(get_script_name_cases)s\ |
246 return Vector<const char>("", 0); | 262 return Vector<const char>("", 0); |
247 } | 263 } |
248 | 264 |
265 template <> | |
266 Vector<const byte> NativesCollection<%(type)s>::GetScriptSource(int index) { | |
267 %(get_script_source_cases)s\ | |
268 static const byte empty[] = { 0 }; | |
269 return Vector<const byte>(empty, 0); | |
270 } | |
271 | |
272 template <> | |
273 void NativesCollection<%(type)s>::SetRawScriptSource(int index, Vector<const c har> raw_source) { | |
274 %(set_raw_script_source_cases)s\ | |
275 } | |
276 | |
249 } // internal | 277 } // internal |
250 } // v8 | 278 } // v8 |
251 """ | 279 """ |
252 | 280 |
253 | 281 |
254 SOURCE_DECLARATION = """\ | 282 SOURCE_DECLARATION = """\ |
255 static const char %(id)s[] = { %(data)s }; | 283 static const byte %(id)s[] = { %(data)s }; |
256 """ | 284 """ |
257 | 285 |
258 | 286 |
259 GET_DEBUGGER_INDEX_CASE = """\ | 287 RAW_SOURCE_COMPRESSION_DECLARATION = """\ |
288 static const char* %(raw_id)s = NULL; | |
289 """ | |
290 | |
291 | |
292 RAW_SOURCE_DECLARATION = """\ | |
293 static const char* %(raw_id)s = reinterpret_cast<const char*>(%(id)s); | |
294 """ | |
295 | |
296 | |
297 GET_INDEX_CASE = """\ | |
260 if (strcmp(name, "%(id)s") == 0) return %(i)i; | 298 if (strcmp(name, "%(id)s") == 0) return %(i)i; |
261 """ | 299 """ |
262 | 300 |
263 | 301 |
264 GET_DEBUGGER_SCRIPT_SOURCE_CASE = """\ | 302 GET_RAW_SCRIPT_SIZE_CASE = """\ |
265 if (index == %(i)i) return Vector<const char>(%(id)s, %(length)i); | 303 if (index == %(i)i) return %(raw_length)i; |
266 """ | 304 """ |
267 | 305 |
268 | 306 |
269 GET_DEBUGGER_SCRIPT_NAME_CASE = """\ | 307 GET_RAW_SCRIPT_SOURCE_CASE = """\ |
308 if (index == %(i)i) return Vector<const char>(%(raw_id)s, %(raw_length)i); | |
309 """ | |
310 | |
311 | |
312 GET_SCRIPT_NAME_CASE = """\ | |
270 if (index == %(i)i) return Vector<const char>("%(name)s", %(length)i); | 313 if (index == %(i)i) return Vector<const char>("%(name)s", %(length)i); |
271 """ | 314 """ |
272 | 315 |
316 | |
317 GET_SCRIPT_SOURCE_CASE = """\ | |
318 if (index == %(i)i) return Vector<const byte>(%(id)s, %(length)i); | |
319 """ | |
320 | |
321 | |
322 SET_RAW_SOURCE_CASE = """\ | |
323 if (index == %(i)i) { ASSERT(%(raw_length)i == raw_source.length()); %(raw_i d)s = raw_source.start(); } | |
324 """ | |
325 | |
273 def JS2C(source, target, env): | 326 def JS2C(source, target, env): |
274 ids = [] | 327 ids = [] |
275 debugger_ids = [] | 328 debugger_ids = [] |
276 modules = [] | 329 modules = [] |
277 # Locate the macros file name. | 330 # Locate the macros file name. |
278 consts = [] | 331 consts = [] |
279 macros = [] | 332 macros = [] |
280 for s in source: | 333 for s in source: |
281 if 'macros.py' == (os.path.split(str(s))[1]): | 334 if 'macros.py' == (os.path.split(str(s))[1]): |
282 (consts, macros) = ReadMacros(ReadLines(str(s))) | 335 (consts, macros) = ReadMacros(ReadLines(str(s))) |
283 else: | 336 else: |
284 modules.append(s) | 337 modules.append(s) |
285 | 338 |
286 # Build source code lines | 339 # Build source code lines |
287 source_lines = [ ] | 340 source_lines = [ ] |
341 raw_source_lines = [ ] | |
288 | 342 |
289 minifier = jsmin.JavaScriptMinifier() | 343 minifier = jsmin.JavaScriptMinifier() |
290 | 344 |
291 for module in modules: | 345 for module in modules: |
292 filename = str(module) | 346 filename = str(module) |
293 debugger = filename.endswith('-debugger.js') | 347 debugger = filename.endswith('-debugger.js') |
294 lines = ReadFile(filename) | 348 lines = ReadFile(filename) |
295 lines = ExpandConstants(lines, consts) | 349 lines = ExpandConstants(lines, consts) |
296 lines = ExpandMacros(lines, macros) | 350 lines = ExpandMacros(lines, macros) |
297 Validate(lines, filename) | 351 Validate(lines, filename) |
298 lines = minifier.JSMinify(lines) | 352 lines = minifier.JSMinify(lines) |
299 data = ToCArray(lines) | 353 raw_length = len(lines) |
354 if env['COMPRESSION'] == 'bz2': | |
Vitaly Repeshko
2011/06/06 10:08:23
I think we can get better compression by gluing to
mnaganov (inactive)
2011/06/06 13:40:18
Good idea! This also simplifies code.
| |
355 lines = bz2.compress(lines, 9) | |
Vitaly Repeshko
2011/06/06 10:08:23
9 seems to be the default compression level so we
mnaganov (inactive)
2011/06/06 13:40:18
Done.
| |
356 length = len(lines) | |
357 if env['COMPRESSION'] == 'off': | |
358 data = ToCAsciiArray(lines) | |
359 else: | |
360 data = ToCArray(lines) | |
300 id = (os.path.split(filename)[1])[:-3] | 361 id = (os.path.split(filename)[1])[:-3] |
301 if debugger: id = id[:-9] | 362 if debugger: id = id[:-9] |
302 if debugger: | 363 if debugger: |
303 debugger_ids.append((id, len(lines))) | 364 debugger_ids.append((id, raw_length, length)) |
304 else: | 365 else: |
305 ids.append((id, len(lines))) | 366 ids.append((id, raw_length, length)) |
367 raw_id = 'raw_' + id | |
306 source_lines.append(SOURCE_DECLARATION % { 'id': id, 'data': data }) | 368 source_lines.append(SOURCE_DECLARATION % { 'id': id, 'data': data }) |
369 if env['COMPRESSION'] == 'off': | |
370 raw_source_lines.append(RAW_SOURCE_DECLARATION % { 'raw_id': raw_id, 'id': id }) | |
Vitaly Repeshko
2011/06/06 10:08:23
Let's at least fit the code lines in 80 cols.
mnaganov (inactive)
2011/06/06 13:40:18
Done.
| |
371 else: | |
372 raw_source_lines.append(RAW_SOURCE_COMPRESSION_DECLARATION % { 'raw_id': r aw_id, 'id': id }) | |
307 | 373 |
308 # Build debugger support functions | 374 # Build debugger support functions |
309 get_index_cases = [ ] | 375 get_index_cases = [ ] |
376 get_raw_script_size_cases = [ ] | |
377 get_raw_script_source_cases = [ ] | |
378 get_script_name_cases = [ ] | |
310 get_script_source_cases = [ ] | 379 get_script_source_cases = [ ] |
311 get_script_name_cases = [ ] | 380 set_raw_script_source_cases = [ ] |
312 | 381 |
313 i = 0 | 382 i = 0 |
314 for (id, length) in debugger_ids: | 383 for (id, raw_length, length) in debugger_ids: |
315 native_name = "native %s.js" % id | 384 native_name = "native %s.js" % id |
316 get_index_cases.append(GET_DEBUGGER_INDEX_CASE % { 'id': id, 'i': i }) | 385 raw_id = 'raw_' + id |
317 get_script_source_cases.append(GET_DEBUGGER_SCRIPT_SOURCE_CASE % { | 386 get_index_cases.append(GET_INDEX_CASE % { 'id': id, 'i': i }) |
318 'id': id, | 387 get_raw_script_size_cases.append(GET_RAW_SCRIPT_SIZE_CASE % { |
319 'length': length, | 388 'raw_length': raw_length, |
320 'i': i | 389 'i': i |
321 }) | 390 }) |
322 get_script_name_cases.append(GET_DEBUGGER_SCRIPT_NAME_CASE % { | 391 get_raw_script_source_cases.append(GET_RAW_SCRIPT_SOURCE_CASE % { |
323 'name': native_name, | 392 'raw_id': raw_id, |
324 'length': len(native_name), | 393 'raw_length': raw_length, |
325 'i': i | 394 'i': i |
326 }); | 395 }) |
396 get_script_name_cases.append(GET_SCRIPT_NAME_CASE % { | |
397 'name': native_name, | |
398 'length': len(native_name), | |
399 'i': i | |
400 }) | |
401 get_script_source_cases.append(GET_SCRIPT_SOURCE_CASE % { | |
402 'id': id, | |
403 'length': length, | |
404 'i': i | |
405 }) | |
406 set_raw_script_source_cases.append(SET_RAW_SOURCE_CASE % { | |
407 'raw_id': raw_id, | |
408 'raw_length': raw_length, | |
409 'i': i | |
410 }) | |
327 i = i + 1 | 411 i = i + 1 |
328 | 412 |
329 for (id, length) in ids: | 413 for (id, raw_length, length) in ids: |
330 native_name = "native %s.js" % id | 414 native_name = "native %s.js" % id |
331 get_index_cases.append(GET_DEBUGGER_INDEX_CASE % { 'id': id, 'i': i }) | 415 raw_id = 'raw_' + id |
332 get_script_source_cases.append(GET_DEBUGGER_SCRIPT_SOURCE_CASE % { | 416 get_index_cases.append(GET_INDEX_CASE % { 'id': id, 'i': i }) |
333 'id': id, | 417 get_raw_script_size_cases.append(GET_RAW_SCRIPT_SIZE_CASE % { |
334 'length': length, | 418 'raw_length': raw_length, |
335 'i': i | 419 'i': i |
336 }) | 420 }) |
337 get_script_name_cases.append(GET_DEBUGGER_SCRIPT_NAME_CASE % { | 421 get_raw_script_source_cases.append(GET_RAW_SCRIPT_SOURCE_CASE % { |
338 'name': native_name, | 422 'raw_id': raw_id, |
339 'length': len(native_name), | 423 'raw_length': raw_length, |
340 'i': i | 424 'i': i |
341 }); | 425 }) |
426 get_script_name_cases.append(GET_SCRIPT_NAME_CASE % { | |
427 'name': native_name, | |
428 'length': len(native_name), | |
429 'i': i | |
430 }) | |
431 get_script_source_cases.append(GET_SCRIPT_SOURCE_CASE % { | |
432 'id': id, | |
433 'length': length, | |
434 'i': i | |
435 }) | |
436 set_raw_script_source_cases.append(SET_RAW_SOURCE_CASE % { | |
437 'raw_id': raw_id, | |
438 'raw_length': raw_length, | |
439 'i': i | |
440 }) | |
342 i = i + 1 | 441 i = i + 1 |
343 | 442 |
344 # Emit result | 443 # Emit result |
345 output = open(str(target[0]), "w") | 444 output = open(str(target[0]), "w") |
346 output.write(HEADER_TEMPLATE % { | 445 output.write(HEADER_TEMPLATE % { |
347 'builtin_count': len(ids) + len(debugger_ids), | 446 'builtin_count': len(ids) + len(debugger_ids), |
348 'debugger_count': len(debugger_ids), | 447 'debugger_count': len(debugger_ids), |
349 'source_lines': "\n".join(source_lines), | 448 'source_lines': "\n".join(source_lines), |
449 'raw_source_lines': "\n".join(raw_source_lines), | |
350 'get_index_cases': "".join(get_index_cases), | 450 'get_index_cases': "".join(get_index_cases), |
451 'get_raw_script_size_cases': "".join(get_raw_script_size_cases), | |
452 'get_raw_script_source_cases': "".join(get_raw_script_source_cases), | |
453 'get_script_name_cases': "".join(get_script_name_cases), | |
351 'get_script_source_cases': "".join(get_script_source_cases), | 454 'get_script_source_cases': "".join(get_script_source_cases), |
352 'get_script_name_cases': "".join(get_script_name_cases), | 455 'set_raw_script_source_cases': "".join(set_raw_script_source_cases), |
353 'type': env['TYPE'] | 456 'type': env['TYPE'] |
354 }) | 457 }) |
355 output.close() | 458 output.close() |
356 | 459 |
357 def main(): | 460 def main(): |
358 natives = sys.argv[1] | 461 natives = sys.argv[1] |
359 type = sys.argv[2] | 462 type = sys.argv[2] |
360 source_files = sys.argv[3:] | 463 compression = sys.argv[3] |
361 JS2C(source_files, [natives], { 'TYPE': type }) | 464 source_files = sys.argv[4:] |
465 JS2C(source_files, [natives], { 'TYPE': type, 'COMPRESSION': compression }) | |
362 | 466 |
363 if __name__ == "__main__": | 467 if __name__ == "__main__": |
364 main() | 468 main() |
OLD | NEW |