# Copyright (C) 2011 Apple 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 INC. AND ITS 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 APPLE INC. OR ITS 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.

require "config"
require "ast"

OFFSET_HEADER_MAGIC_NUMBERS = [ 0x2e43fd66, 0x4379bfba ]
OFFSET_MAGIC_NUMBERS = [ 0x5c577ac7, 0x0ff5e755 ]

#
# MissingMagicValuesException
#
# Thrown when magic values are missing from the binary.
#

class MissingMagicValuesException < Exception
end

#
# offsetsList(ast)
# sizesList(ast)
# constsLists(ast)
#
# Returns a list of offsets, sizeofs, and consts used by the AST.
#

def offsetsList(ast)
    ast.filter(StructOffset).uniq.sort
end

def sizesList(ast)
    ast.filter(Sizeof).uniq.sort
end

def constsList(ast)
    ast.filter(ConstExpr).uniq.sort
end

def readInt(endianness, bytes)
    if endianness == :little
        # Little endian
        number = (bytes[0] << 0  |
                  bytes[1] << 8  |
                  bytes[2] << 16 |
                  bytes[3] << 24 |
                  bytes[4] << 32 |
                  bytes[5] << 40 |
                  bytes[6] << 48 |
                  bytes[7] << 56)
    else
        # Big endian
        number = (bytes[0] << 56 |
                  bytes[1] << 48 |
                  bytes[2] << 40 |
                  bytes[3] << 32 |
                  bytes[4] << 24 |
                  bytes[5] << 16 |
                  bytes[6] << 8  |
                  bytes[7] << 0)
    end
    if number > 0x7fffffff_ffffffff
        number -= 1 << 64
    end
    number
end

def prepareMagic(endianness, numbers)
    magicBytes = []
    numbers.each {
        | number |
        currentBytes = []
        8.times {
            currentBytes << (number & 0xff)
            number >>= 8
        }
        if endianness == :big
            currentBytes.reverse!
        end
        magicBytes += currentBytes
    }
    magicBytes
end

def fileBytes(file)
    fileBytes = []
    File.open(file, "rb") {
        | inp |
        loop {
            byte = inp.getbyte
            break unless byte
            fileBytes << byte
        }
    }
    fileBytes
end

def sliceByteArrays(byteArray, pattern)
    result = []
    lastSlicePoint = 0
    (byteArray.length - pattern.length + 1).times {
        | index |
        foundOne = true
        pattern.length.times {
            | subIndex |
            if byteArray[index + subIndex] != pattern[subIndex]
                foundOne = false
                break
            end
        }
        if foundOne
            result << byteArray[lastSlicePoint...index]
            lastSlicePoint = index + pattern.length
        end
    }

    result << byteArray[lastSlicePoint...(byteArray.length)]

    result
end

#
# offsetsAndConfigurationIndex(file) ->
#     [[offsets, index], ...]
#
# Parses the offsets from a file and returns a list of offsets and the
# index of the configuration that is valid in this build target.
#

def offsetsAndConfigurationIndex(file)
    fileBytes = fileBytes(file)
    result = {}

    [:little, :big].each {
        | endianness |
        headerMagicBytes = prepareMagic(endianness, OFFSET_HEADER_MAGIC_NUMBERS)
        magicBytes = prepareMagic(endianness, OFFSET_MAGIC_NUMBERS)

        bigArray = sliceByteArrays(fileBytes, headerMagicBytes)
        unless bigArray.size <= 1
            bigArray[1..-1].each {
                | configArray |
                array = sliceByteArrays(configArray, magicBytes)
                index = readInt(endianness, array[1])
                offsets = []
                array[2..-1].each {
                    | data |
                    offsets << readInt(endianness, data)
                }
                result[index] = offsets
            }
        end
    }

    raise MissingMagicValuesException unless result.length >= 1

    # result is {index1=>offsets1, index2=>offsets2} but we want to return
    # [[offsets1, index1], [offsets2, index2]].
    return result.map {
        | pair |
        pair.reverse
    }
end

#
# offsetsAndConfigurationIndex(file) ->
#     [[offsets, index], ...]
#
# Parses the offsets from a file and all its variants and returns a list of
# offsets and the index of the configuration that is valid in this build target.
#

def offsetsAndConfigurationIndexForVariants(file, variants)
    results = []
    variants.each {
        | current_variant |
        suffix = ""
        unless current_variant == "normal"
            suffix = "_" + current_variant
        end
        results << offsetsAndConfigurationIndex(file + suffix)
    }
    return results.flatten(1)
end

#
# configurationIndices(file) ->
#     [[offsets, index], ...]
#
# Parses the configurations from a file and returns a list of the indices of
# the configurations that are valid in this build target.
#

def configurationIndices(file)
    fileBytes = fileBytes(file)
    result = []

    [:little, :big].each {
        | endianness |
        headerMagicBytes = prepareMagic(endianness, OFFSET_HEADER_MAGIC_NUMBERS)

        bigArray = sliceByteArrays(fileBytes, headerMagicBytes)
        unless bigArray.size <= 1
            bigArray[1..-1].each {
                | configArray |
                result << readInt(endianness, configArray)
            }
        end
    }

    raise MissingMagicValuesException unless result.length >= 1

    return result
end

#
# configurationIndicesForVariants(file, variants) ->
#     [[offsets, index], ...]
#
# Parses the configurations from a file and all its variants and returns a list
# of the indices of the configurations that are valid in this build target.
#

def configurationIndicesForVariants(file, variants)
    results = []
    variants.each {
        | current_variant |
        suffix = ""
        unless current_variant == "normal"
            suffix = "_" + current_variant
        end
        results << configurationIndices(file + suffix)
    }
    return results.flatten(1)
end

#
# buildOffsetsMap(ast, extractedConstants) -> map
#
# Builds a mapping between StructOffset, Sizeof, and ConstExpr nodes and their values.
#

def buildOffsetsMap(ast, extractedConstants)
    map = {}
    astOffsetsList = offsetsList(ast)
    astSizesList = sizesList(ast)
    astConstsList = constsList(ast)

    raise unless astOffsetsList.size + astSizesList.size + astConstsList.size == extractedConstants.size
    astOffsetsList.each_with_index {
        | structOffset, index |
        map[structOffset] = extractedConstants.shift
    }
    astSizesList.each_with_index {
        | sizeof, index |
        map[sizeof] = extractedConstants.shift
    }
    astConstsList.each_with_index {
        | const, index |
        map[const] = extractedConstants.shift
    }
    map
end

