#!/usr/bin/env python

# Copyright 2017 Jose Nelson Amaral
# Copyright 2017 Joao Hoffman
# Copyright 2017 Morgan Redshaw
# Copyright 2017 Erick Ochoa Lopez
# 
# 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.
# 
# 3. Neither the name of the copyright holder 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 HOLDER 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.

import glob
import os
import re

# This first block will read all the .c files and replace any include of the type '#include "dir/inc.h"' for its basename.
for filename in sorted(glob.glob('modified/*.c')):
   f = open(filename, 'r')
   content = f.read()
   value = re.findall(r'#include "(.*?)"', content, re.DOTALL)
   f.close()

   for i in value:
      content = re.sub('#include "'+i+'"', '#include "'+os.path.basename(i)+'"', content)
      f = open(filename, 'w')
      f.write(content)
      f.close()

# This block does the same thing for all the .h files.
for filename in sorted(glob.glob('modified/*.h')):
   f = open(filename, 'r')
   content = f.read()
   value = re.findall(r'#include "(.*?)"', content, re.DOTALL)
   f.close()

   for i in value:
      content = re.sub('#include "'+i+'"', '#include "'+os.path.basename(i)+'"', content)
      f = open(filename, 'w')
      f.write(content)
      f.close()

# This block removes all of the .c inclusions in the .h files.
for filename in sorted(glob.glob('modified/*.h')):
   with open(filename) as f:
      content = f.readlines()
      f.close()
      f = open(filename, 'w')
      for line in content:
         if "#include" not in line:
            f.write(line)
         elif "#include" in line and ".c" not in line:
            f.write(line)
      f.close()

# This block does the same thing, but for .c files.
for filename in sorted(glob.glob('modified/*.c')):
   with open(filename) as f:
      content = f.readlines()
      f.close()
      f = open(filename, 'w')
      for line in content:
         if "#include" not in line:
            f.write(line)
         elif "#include" in line and ".c" not in line:
            f.write(line)
      f.close()

output = open('temp.txt', 'w')

# This block will copy all of the includes and conditions to a temporary file.
for filename in sorted(glob.glob('modified/*.c')):
   with open(filename) as f:
      content = f.readlines()
      f.close()
      basename=os.path.basename(filename)
      
      for line in content:
         if "#if" in line:
            output.write(line)
         elif "#elif" in line:
            output.write(line)
         elif "#endif" in line:
            output.write(line)
         elif "#else" in line:
            output.write(line)
         elif "#include" in line:
            output.write(line)

output.close()

if_depth = 0
out_if_lines = set()

# The temporary file is read and all the includes outside a conditional block will be put into a list.
for line in open('temp.txt', 'r'):
   if "#if" in line:
      if_depth += 1
   elif "#endif" in line:
      if_depth -= 1
   elif "#include" in line:
      if if_depth == 0:
         out_if_lines.add(line)
   

if_depth = 0
lines_seen = set() 
outfile = open(os.path.join('modified', 'includes.c'), 'w')

# The 'includes.c' is finally created. If a include is currently outside a conditional, it will be written only once. If it is not, it will be written inside all of the conditionals. 
for line in open('temp.txt', 'r'):
   if "#include" in line and line not in lines_seen:
      if if_depth == 0:
         outfile.write(line)
         lines_seen.add(line)
      elif if_depth <> 0 and line not in out_if_lines:
         outfile.write(line)
   elif "#if" in line:
      if_depth += 1
      outfile.write(line)
   elif "#elif" in line:
      outfile.write(line)
   elif "#else" in line:
      outfile.write(line)
   elif "#endif" in line:
      if_depth -= 1
      outfile.write(line)

outfile.close()
