131e7138e1a05e29ceefa8919ae12cb621a48ca7fmads.s.ager#!/usr/bin/env python 2c27e4e79503d86932450a812ce8fd6ee6d9a5bdcager@chromium.org# 30e3f88bd850f46930aa95684377fab02a394ae41ulan@chromium.org# Copyright 2012 the V8 project authors. All rights reserved. 443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# Redistribution and use in source and binary forms, with or without 543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# modification, are permitted provided that the following conditions are 643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# met: 743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# 843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# * Redistributions of source code must retain the above copyright 943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# notice, this list of conditions and the following disclaimer. 1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# * Redistributions in binary form must reproduce the above 1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# copyright notice, this list of conditions and the following 1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# disclaimer in the documentation and/or other materials provided 1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# with the distribution. 1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# * Neither the name of Google Inc. nor the names of its 1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# contributors may be used to endorse or promote products derived 1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# from this software without specific prior written permission. 1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# 1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 3043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# This is a utility for converting JavaScript source code into C-style 3143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# char arrays. It is used for embedded JavaScript code in the V8 3243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# library. 3343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 3443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenimport os, re, sys, string 35245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.orgimport jsmin 36e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.orgimport bz2 3743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 3843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 39e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.orgdef ToCAsciiArray(lines): 4043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen result = [] 4143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen for chr in lines: 4243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen value = ord(chr) 4343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen assert value < 128 4443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen result.append(str(value)) 45e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org return ", ".join(result) 46e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 47e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 48e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.orgdef ToCArray(lines): 49e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org result = [] 50e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org for chr in lines: 51e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org result.append(str(ord(chr))) 5243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return ", ".join(result) 5343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 5443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 5518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgdef RemoveCommentsAndTrailingWhitespace(lines): 5618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org lines = re.sub(r'//.*\n', '\n', lines) # end-of-line comments 5718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments. 5818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org lines = re.sub(r'\s+\n+', '\n', lines) # trailing whitespace 5918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org return lines 6018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org 6118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org 6243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansendef ReadFile(filename): 6343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen file = open(filename, "rt") 6443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen try: 6543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen lines = file.read() 6643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen finally: 6743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen file.close() 6843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return lines 6943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 7043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 7143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansendef ReadLines(filename): 7243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen result = [] 7343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen for line in open(filename, "rt"): 7443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if '#' in line: 7543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen line = line[:line.index('#')] 7643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen line = line.strip() 7743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if len(line) > 0: 7843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen result.append(line) 7943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return result 8043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 8143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 8243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansendef LoadConfigFrom(name): 8343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen import ConfigParser 8443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen config = ConfigParser.ConfigParser() 8543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen config.read(name) 8643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return config 8743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 8843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 8943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansendef ParseValue(string): 9043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen string = string.strip() 9143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if string.startswith('[') and string.endswith(']'): 9243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return string.lstrip('[').rstrip(']').split() 9343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen else: 9443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return string 9543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 9643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 97e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.orgEVAL_PATTERN = re.compile(r'\beval\s*\(') 98e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.orgWITH_PATTERN = re.compile(r'\bwith\s*\(') 9918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org 10018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org 10118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgdef Validate(lines, file): 10218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org lines = RemoveCommentsAndTrailingWhitespace(lines) 10318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org # Because of simplified context setup, eval and with is not 10418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org # allowed in the natives files. 10518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org eval_match = EVAL_PATTERN.search(lines) 10618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org if eval_match: 10718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org raise ("Eval disallowed in natives: %s" % file) 10818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org with_match = WITH_PATTERN.search(lines) 10918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org if with_match: 11018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org raise ("With statements disallowed in natives: %s" % file) 11118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org 11218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org 11343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansendef ExpandConstants(lines, constants): 1144a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com for key, value in constants: 1154a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com lines = key.sub(str(value), lines) 11643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return lines 11743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1187276f14ca716596e0a0d17539516370c1f453847kasper.lund 11943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansendef ExpandMacros(lines, macros): 1204a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com # We allow macros to depend on the previously declared macros, but 1214a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com # we don't allow self-dependecies or recursion. 1224a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com for name_pattern, macro in reversed(macros): 1234a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com pattern_match = name_pattern.search(lines, 0) 1244a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com while pattern_match is not None: 12543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen # Scan over the arguments 12643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen height = 1 1274a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com start = pattern_match.start() 1284a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com end = pattern_match.end() 1294a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com assert lines[end - 1] == '(' 13043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen last_match = end 131659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org arg_index = [0] # Wrap state into array, to work around Python "scoping" 13243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen mapping = { } 13343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen def add_arg(str): 13443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen # Remember to expand recursively in the arguments 13543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen replacement = ExpandMacros(str.strip(), macros) 136659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org mapping[macro.args[arg_index[0]]] = replacement 137659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org arg_index[0] += 1 13843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen while end < len(lines) and height > 0: 13943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen # We don't count commas at higher nesting levels. 14043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if lines[end] == ',' and height == 1: 14143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen add_arg(lines[last_match:end]) 14243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen last_match = end + 1 14343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen elif lines[end] in ['(', '{', '[']: 14443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen height = height + 1 14543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen elif lines[end] in [')', '}', ']']: 14643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen height = height - 1 14743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen end = end + 1 14843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen # Remember to add the last match. 14943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen add_arg(lines[last_match:end-1]) 15043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen result = macro.expand(mapping) 15143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen # Replace the occurrence of the macro with the expansion 15243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen lines = lines[:start] + result + lines[end:] 1534a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com pattern_match = name_pattern.search(lines, start + len(result)) 15443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return lines 15543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 15643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass TextMacro: 15743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen def __init__(self, args, body): 15843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen self.args = args 15943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen self.body = body 16043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen def expand(self, mapping): 16143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen result = self.body 16243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen for key, value in mapping.items(): 16343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen result = result.replace(key, value) 16443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return result 16543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 16643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass PythonMacro: 16743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen def __init__(self, args, fun): 16843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen self.args = args 16943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen self.fun = fun 17043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen def expand(self, mapping): 17143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen args = [] 17243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen for arg in self.args: 17343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen args.append(mapping[arg]) 17443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return str(self.fun(*args)) 17543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 17618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgCONST_PATTERN = re.compile(r'^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$') 17718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgMACRO_PATTERN = re.compile(r'^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$') 17818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgPYTHON_MACRO_PATTERN = re.compile(r'^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$') 17943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1804a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com 18143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansendef ReadMacros(lines): 1824a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com constants = [] 1834a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com macros = [] 18443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen for line in lines: 18543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen hash = line.find('#') 18643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if hash != -1: line = line[:hash] 18743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen line = line.strip() 18843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if len(line) is 0: continue 18943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const_match = CONST_PATTERN.match(line) 19043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if const_match: 19143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen name = const_match.group(1) 19243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen value = const_match.group(2).strip() 1934a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com constants.append((re.compile("\\b%s\\b" % name), value)) 19443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen else: 19543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen macro_match = MACRO_PATTERN.match(line) 19643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if macro_match: 19743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen name = macro_match.group(1) 1980e3f88bd850f46930aa95684377fab02a394ae41ulan@chromium.org args = [match.strip() for match in macro_match.group(2).split(',')] 19943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen body = macro_match.group(3).strip() 2004a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com macros.append((re.compile("\\b%s\\(" % name), TextMacro(args, body))) 20143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen else: 20243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen python_match = PYTHON_MACRO_PATTERN.match(line) 20343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if python_match: 20443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen name = python_match.group(1) 2050e3f88bd850f46930aa95684377fab02a394ae41ulan@chromium.org args = [match.strip() for match in python_match.group(2).split(',')] 20643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen body = python_match.group(3).strip() 20743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen fun = eval("lambda " + ",".join(args) + ': ' + body) 2084a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com macros.append((re.compile("\\b%s\\(" % name), PythonMacro(args, fun))) 20943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen else: 21043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen raise ("Illegal line: " + line) 21143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return (constants, macros) 21243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 21343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 21443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenHEADER_TEMPLATE = """\ 215160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org// Copyright 2011 Google Inc. All Rights Reserved. 21643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 21732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// This file was generated from .js source files by GYP. If you 21843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// want to make changes to this file you should either change the 21932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// javascript source files or the GYP script. 22043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 22143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "v8.h" 22243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "natives.h" 223e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org#include "utils.h" 22443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 22543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansennamespace v8 { 22643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansennamespace internal { 22743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 228e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org static const byte sources[] = { %(sources_data)s }; 229e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 230e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org%(raw_sources_declaration)s\ 23143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2325a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org template <> 2335a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org int NativesCollection<%(type)s>::GetBuiltinsCount() { 23443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return %(builtin_count)i; 23543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 23643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2375a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org template <> 2385d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org int NativesCollection<%(type)s>::GetDebuggerCount() { 2395d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org return %(debugger_count)i; 24043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 24143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2425a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org template <> 2435a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org int NativesCollection<%(type)s>::GetIndex(const char* name) { 24443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen%(get_index_cases)s\ 24543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return -1; 24643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 24743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2485a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org template <> 249e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org int NativesCollection<%(type)s>::GetRawScriptsSize() { 250e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org return %(raw_total_length)i; 251e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org } 252e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 253e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org template <> 254e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org Vector<const char> NativesCollection<%(type)s>::GetRawScriptSource(int index) { 255e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org%(get_raw_script_source_cases)s\ 25643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return Vector<const char>("", 0); 25743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 25843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2595a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org template <> 2605a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org Vector<const char> NativesCollection<%(type)s>::GetScriptName(int index) { 26143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen%(get_script_name_cases)s\ 26243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return Vector<const char>("", 0); 26343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 26443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 265e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org template <> 266e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org Vector<const byte> NativesCollection<%(type)s>::GetScriptsSource() { 267e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org return Vector<const byte>(sources, %(total_length)i); 268e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org } 269e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 270e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org template <> 271e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org void NativesCollection<%(type)s>::SetRawScriptsSource(Vector<const char> raw_source) { 272e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org ASSERT(%(raw_total_length)i == raw_source.length()); 273e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org raw_sources = raw_source.start(); 274e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org } 275e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 27643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} // internal 27743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} // v8 27843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen""" 27943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 28043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 281e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.orgRAW_SOURCES_COMPRESSION_DECLARATION = """\ 282e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org static const char* raw_sources = NULL; 283e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org""" 284e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 285e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 286e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.orgRAW_SOURCES_DECLARATION = """\ 287e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org static const char* raw_sources = reinterpret_cast<const char*>(sources); 28843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen""" 28943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 29043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 291e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.orgGET_INDEX_CASE = """\ 29243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (strcmp(name, "%(id)s") == 0) return %(i)i; 29343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen""" 29443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 29543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 296e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.orgGET_RAW_SCRIPT_SOURCE_CASE = """\ 297e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org if (index == %(i)i) return Vector<const char>(raw_sources + %(offset)i, %(raw_length)i); 29843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen""" 29943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 30043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 301e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.orgGET_SCRIPT_NAME_CASE = """\ 30243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (index == %(i)i) return Vector<const char>("%(name)s", %(length)i); 30343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen""" 30443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 30543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansendef JS2C(source, target, env): 30643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen ids = [] 3075d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org debugger_ids = [] 30843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen modules = [] 30943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen # Locate the macros file name. 310ba5a61b76d901fc18b36ae7bd97eaf938269c96ewhesse@chromium.org consts = [] 311ba5a61b76d901fc18b36ae7bd97eaf938269c96ewhesse@chromium.org macros = [] 31243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen for s in source: 31343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if 'macros.py' == (os.path.split(str(s))[1]): 31443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen (consts, macros) = ReadMacros(ReadLines(str(s))) 31543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen else: 31643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen modules.append(s) 31743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 318c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org minifier = jsmin.JavaScriptMinifier() 319c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org 320e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org module_offset = 0 321e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org all_sources = [] 32218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org for module in modules: 32318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org filename = str(module) 3245d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org debugger = filename.endswith('-debugger.js') 32518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org lines = ReadFile(filename) 32643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen lines = ExpandConstants(lines, consts) 32743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen lines = ExpandMacros(lines, macros) 32818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org Validate(lines, filename) 329c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org lines = minifier.JSMinify(lines) 33018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org id = (os.path.split(filename)[1])[:-3] 3315d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org if debugger: id = id[:-9] 332e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org raw_length = len(lines) 3335d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org if debugger: 334e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org debugger_ids.append((id, raw_length, module_offset)) 33543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen else: 336e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org ids.append((id, raw_length, module_offset)) 337e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org all_sources.append(lines) 338e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org module_offset += raw_length 339e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org total_length = raw_total_length = module_offset 340e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 341e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org if env['COMPRESSION'] == 'off': 342e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org raw_sources_declaration = RAW_SOURCES_DECLARATION 343e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org sources_data = ToCAsciiArray("".join(all_sources)) 344e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org else: 345e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org raw_sources_declaration = RAW_SOURCES_COMPRESSION_DECLARATION 346e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org if env['COMPRESSION'] == 'bz2': 347e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org all_sources = bz2.compress("".join(all_sources)) 348e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org total_length = len(all_sources) 349e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org sources_data = ToCArray(all_sources) 35018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org 3515d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org # Build debugger support functions 35243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen get_index_cases = [ ] 353e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org get_raw_script_source_cases = [ ] 35443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen get_script_name_cases = [ ] 35543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 35643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen i = 0 357e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org for (id, raw_length, module_offset) in debugger_ids + ids: 35843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen native_name = "native %s.js" % id 359e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org get_index_cases.append(GET_INDEX_CASE % { 'id': id, 'i': i }) 360e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org get_raw_script_source_cases.append(GET_RAW_SCRIPT_SOURCE_CASE % { 361e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'offset': module_offset, 362e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'raw_length': raw_length, 363e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'i': i 364e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org }) 365e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org get_script_name_cases.append(GET_SCRIPT_NAME_CASE % { 366e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'name': native_name, 367e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'length': len(native_name), 368e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'i': i 369e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org }) 37043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen i = i + 1 37143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 37243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen # Emit result 37343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen output = open(str(target[0]), "w") 37443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen output.write(HEADER_TEMPLATE % { 3755d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org 'builtin_count': len(ids) + len(debugger_ids), 3765d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org 'debugger_count': len(debugger_ids), 377e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'sources_data': sources_data, 378e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'raw_sources_declaration': raw_sources_declaration, 379e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'raw_total_length': raw_total_length, 380e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'total_length': total_length, 38143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 'get_index_cases': "".join(get_index_cases), 382e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org 'get_raw_script_source_cases': "".join(get_raw_script_source_cases), 3835a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org 'get_script_name_cases': "".join(get_script_name_cases), 3845a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org 'type': env['TYPE'] 38543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen }) 38643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen output.close() 38743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 38843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansendef main(): 38931e7138e1a05e29ceefa8919ae12cb621a48ca7fmads.s.ager natives = sys.argv[1] 390160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org type = sys.argv[2] 391e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org compression = sys.argv[3] 392e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org source_files = sys.argv[4:] 393e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org JS2C(source_files, [natives], { 'TYPE': type, 'COMPRESSION': compression }) 39443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 39543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenif __name__ == "__main__": 39643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen main() 397