#!/usr/bin/env python3
# vim: set ft=python:
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 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. ``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
# 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.


# Extract dependency information from the output of `make -d`, generating a
# list of top-level targets (which are assumed to be generated/output files)
# and a list of leaf dependencies (which are assumed to be the base input
# files). Read the make dependency information from stdin and write the results
# to the specified files.

from __future__ import print_function

import argparse
import re
import sys


class Parser(object):

    fileNamePattern         = r"`([^']+)'"
    rePrerequisite          = re.compile(r"Prerequisite {} is .* than target {}".format(fileNamePattern, fileNamePattern))
    reMustRemakeTarget      = re.compile(r"Must remake target {}".format(fileNamePattern))
    reWasConsideredAlready  = re.compile(r"{} was considered already.".format(fileNamePattern))
    rePruningFile           = re.compile(r"Pruning file {}.".format(fileNamePattern))

    def __init__(self):
        self.targets = {}
        self.prereqs = {}

    def nextLine(self, input):
        while True:
            line = input.readline()
            if not line: break
            line = line.strip()
            if line: yield line

    def addTarget(self, target):
        if target != 'all' and target != 'force':
            self.targets[target] = 1

    def addPrereq(self, prereq):
        if prereq != 'all' and prereq != 'force':
            self.prereqs[prereq] = 1

    def doParse(self, input):

        # Pull out everything that looks like a target or prerequisite.

        for line in self.nextLine(input):
            m = Parser.rePrerequisite.search(line)
            if m:
                self.addTarget(m.group(2))
                self.addPrereq(m.group(1))
                continue

            m = Parser.reMustRemakeTarget.search(line)
            if m:
                self.addTarget(m.group(1))
                continue

            m = Parser.reWasConsideredAlready.search(line)
            if m:
                self.addTarget(m.group(1))
                continue

            m = Parser.rePruningFile.search(line)
            if m:
                self.addPrereq(m.group(1))
                continue

        # Regarding prerequisites, we're interested in only those that aren't
        # also targets. We only want ones that don't have build rules, and
        # hence must already exist. Those are our inputs.

        for key in self.targets.keys():
            self.prereqs.pop(key, None)

    def printInputs(self, inputsFile):
        with open(inputsFile, 'w') as toFile:
            [ print("{}".format(f), file = toFile) for f in sorted(self.prereqs.keys()) ]

    def printOutputs(self, outputsFile):
        with open(outputsFile, 'w') as toFile:
            [ print("{}".format(f), file = toFile) for f in sorted(self.targets.keys()) ]


def parseArgs():
    parser = argparse.ArgumentParser()

    parser.add_argument(
        '--input',
        metavar='<xcfilelist>',
        type=str,
        required = True,
        help='path to the xcfilelist holding input files')

    parser.add_argument(
        '--output',
        metavar='<xcfilelist>',
        type=str,
        required = True,
        help='path to the xcfilelist holding output/generated files')

    return parser.parse_args()


def main():
    args = parseArgs()
    parser = Parser()

    parser.doParse(sys.stdin)
    parser.printInputs(args.input)
    parser.printOutputs(args.output)


if __name__ == '__main__':
    main()
