#!/usr/bin/python
#
# Copyright (C) 2009 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Copyright (c) 2009 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Generate aggregate .cpp files that include multiple V8 binding .cpp files.

This can be a single output file, to preserve symbol space; or multiple output
files, to reduce maximum compilation unit size and allow parallel compilation.

Usage:
aggregate_generated_bindings.py COMPONENT_DIR IDL_FILES_LIST -- OUTPUT_FILE1 OUTPUT_FILE2 ...

COMPONENT_DIR is the relative directory of a component, e.g., 'core', 'modules'.
IDL_FILES_LIST is a text file containing the IDL file paths, so the command
line doesn't exceed OS length limits.
OUTPUT_FILE1 etc. are filenames of output files.

Design doc: http://www.chromium.org/developers/design-documents/idl-build
"""

import errno
import os
import re
import sys

from utilities import idl_filename_to_interface_name, read_idl_files_list_from_file

# A regexp for finding Conditional attributes in interface definitions.
CONDITIONAL_PATTERN = re.compile(
    r'\['
    r'[^\]]*'
    r'Conditional=([\_0-9a-zA-Z]*)'
    r'[^\]]*'
    r'\]\s*'
    r'((callback|partial)\s+)?'
    r'interface\s+'
    r'\w+\s*'
    r'(:\s*\w+\s*)?'
    r'{',
    re.MULTILINE)

COPYRIGHT_TEMPLATE = """/*
 * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
 *
 * This file was generated by the action_derivedsourcesallinone.py script.
 *
 * Copyright (C) 2009 Google Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
"""


def extract_conditional(idl_file_path):
    """Find [Conditional] interface extended attribute."""
    with open(idl_file_path) as idl_file:
        idl_contents = idl_file.read()

    match = CONDITIONAL_PATTERN.search(idl_contents)
    if not match:
        return None
    return match.group(1)


def extract_meta_data(file_paths):
    """Extracts conditional and interface name from each IDL file."""
    meta_data_list = []

    for file_path in file_paths:
        if not file_path.endswith('.idl'):
            print 'WARNING: non-IDL file passed: "%s"' % file_path
            continue
        if not os.path.exists(file_path):
            print 'WARNING: file not found: "%s"' % file_path
            continue

        # Extract interface name from file name
        interface_name = idl_filename_to_interface_name(file_path)

        meta_data = {
            'conditional': extract_conditional(file_path),
            'name': interface_name,
        }
        meta_data_list.append(meta_data)

    return meta_data_list


def generate_content(component_dir, files_meta_data_this_partition, prefix):
    # Add fixed content.
    output = [COPYRIGHT_TEMPLATE,
              '#define NO_IMPLICIT_ATOMICSTRING\n\n']

    # List all includes segmented by if and endif.
    prev_conditional = None
    files_meta_data_this_partition.sort(key=lambda e: e['conditional'])
    for meta_data in files_meta_data_this_partition:
        conditional = meta_data['conditional']
        if prev_conditional != conditional:
            if prev_conditional:
                output.append('#endif\n')
            if conditional:
                output.append('\n#if ENABLE(%s)\n' % conditional)
        prev_conditional = conditional

        output.append('#include "bindings/%s/%s/%s%s.cpp"\n' %
                      (component_dir, prefix.lower(), prefix, meta_data['name']))

    if prev_conditional:
        output.append('#endif\n')

    return ''.join(output)


def write_content(content, output_file_name):
    parent_path, file_name = os.path.split(output_file_name)
    if not os.path.exists(parent_path):
        print 'Creating directory: %s' % parent_path
        os.makedirs(parent_path)
    with open(output_file_name, 'w') as f:
        f.write(content)


def main(args):
    if len(args) <= 4:
        raise Exception('Expected at least 5 arguments.')
    if (args[1] == '--dart'):
        component_dir = args[2]
        input_file_name = args[3]
        prefix = 'Dart'
    else:
        component_dir = args[1]
        input_file_name = args[2]
        prefix = 'V8'
    in_out_break_index = args.index('--')
    output_file_names = args[in_out_break_index + 1:]

    idl_file_names = read_idl_files_list_from_file(input_file_name)
    files_meta_data = extract_meta_data(idl_file_names)
    total_partitions = len(output_file_names)
    for partition, file_name in enumerate(output_file_names):
        files_meta_data_this_partition = [
                meta_data for meta_data in files_meta_data
                if hash(meta_data['name']) % total_partitions == partition]
        file_contents = generate_content(component_dir,
                                         files_meta_data_this_partition,
                                         prefix)
        write_content(file_contents, file_name)


if __name__ == '__main__':
    sys.exit(main(sys.argv))
