1#!/usr/bin/python
2
3import sys
4import re
5import os
6
7INCLUDE_RE = re.compile('^#include "([^"]*)"$')
8
9def parse_include(line):
10  match = INCLUDE_RE.match(line)
11  return match.groups()[0] if match else None
12
13class Amalgamator:
14  def __init__(self, output_path):
15    self.include_paths = ["."]
16    self.included = set(["upb/port_def.inc", "upb/port_undef.inc"])
17    self.output_h = open(output_path + "upb.h", "w")
18    self.output_c = open(output_path + "upb.c", "w")
19
20    self.output_c.write("/* Amalgamated source file */\n")
21    self.output_c.write('#include "upb.h"\n')
22    self.output_c.write(open("upb/port_def.inc").read())
23
24    self.output_h.write("/* Amalgamated source file */\n")
25    self.output_h.write('#include <stdint.h>')
26    self.output_h.write(open("upb/port_def.inc").read())
27
28  def add_include_path(self, path):
29      self.include_paths.append(path)
30
31  def finish(self):
32    self.output_c.write(open("upb/port_undef.inc").read())
33    self.output_h.write(open("upb/port_undef.inc").read())
34
35  def _process_file(self, infile_name, outfile):
36    file = None
37    for path in self.include_paths:
38        try:
39            full_path = os.path.join(path, infile_name)
40            file = open(full_path)
41            break
42        except IOError:
43            pass
44    if not file:
45        raise RuntimeError("Couldn't open file " + infile_name)
46
47    for line in file:
48      include = parse_include(line)
49      if include is not None and (include.startswith("upb") or
50                                  include.startswith("google")):
51        if include not in self.included:
52          self.included.add(include)
53          self._add_header(include)
54      else:
55        outfile.write(line)
56
57  def _add_header(self, filename):
58    self._process_file(filename, self.output_h)
59
60  def add_src(self, filename):
61    self._process_file(filename, self.output_c)
62
63# ---- main ----
64
65output_path = sys.argv[1]
66amalgamator = Amalgamator(output_path)
67files = []
68
69for arg in sys.argv[2:]:
70  arg = arg.strip()
71  if arg.startswith("-I"):
72    amalgamator.add_include_path(arg[2:])
73  elif arg.endswith(".h") or arg.endswith(".inc"):
74    pass
75  else:
76    files.append(arg)
77
78for filename in files:
79    amalgamator.add_src(filename)
80
81amalgamator.finish()
82