1#!/usr/bin/env python
2# Copyright 2014 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Code generator for PlatformObject<> constructor list.
7
8This script takes as arguments a list of platform names as a text file and
9a list of types and generates a C++ source file containing a list of
10the constructors for that object in platform order.
11
12Example Output: ./ui/ozone/generate_constructor_list.py \
13                    --platform test \
14                    --platform dri \
15                    --export OZONE_EXPORT \
16                    --namespace ui \
17                    --typename OzonePlatform \
18                    --include '"ui/ozone/ozone_platform.h"'
19
20  // DO NOT MODIFY. GENERATED BY generate_constructor_list.py
21
22  #include "ui/ozone/platform_object_internal.h"
23
24  #include "ui/ozone/ozone_platform.h"
25
26  namespace ui {
27
28  OzonePlatform* CreateOzonePlatformTest();
29  OzonePlatform* CreateOzonePlatformDri();
30
31  }  // namespace ui
32
33  namespace ui {
34
35  typedef ui::OzonePlatform* (*OzonePlatformConstructor)();
36
37  template <> const OzonePlatformConstructor
38  PlatformConstructorList<ui::OzonePlatform>::kConstructors[] = {
39    &ui::CreateOzonePlatformTest,
40    &ui::CreateOzonePlatformDri,
41  };
42
43  template class OZONE_EXPORT PlatformObject<ui::OzonePlatform>;
44
45  }  // namespace ui
46"""
47
48import optparse
49import os
50import collections
51import re
52import sys
53import string
54
55
56def GetTypedefName(typename):
57  """Determine typedef name of constructor for typename.
58
59  This is just typename + "Constructor".
60  """
61
62  return typename + 'Constructor'
63
64
65def GetConstructorName(typename, platform):
66  """Determine name of static constructor function from platform name.
67
68  This is just "Create" + typename + platform.
69  """
70
71  return 'Create' + typename + string.capitalize(platform)
72
73
74def GenerateConstructorList(out, namespace, export, typenames, platforms,
75                            includes):
76  """Generate static array containing a list of constructors."""
77
78  out.write('// DO NOT MODIFY. GENERATED BY generate_constructor_list.py\n')
79  out.write('\n')
80
81  out.write('#include "ui/ozone/platform_object_internal.h"\n')
82  out.write('\n')
83
84  for include in includes:
85    out.write('#include %(include)s\n' % {'include': include})
86  out.write('\n')
87
88  out.write('namespace %(namespace)s {\n' % {'namespace': namespace})
89  out.write('\n')
90
91  # Declarations of constructor functions.
92  for typename in typenames:
93    for platform in platforms:
94      constructor = GetConstructorName(typename, platform)
95      out.write('%(typename)s* %(constructor)s();\n'
96               % {'typename': typename,
97                  'constructor': constructor})
98    out.write('\n')
99
100  out.write('}  // namespace %(namespace)s\n' % {'namespace': namespace})
101  out.write('\n')
102
103  out.write('namespace ui {\n')
104  out.write('\n')
105
106  # Handy typedefs for constructor types.
107  for typename in typenames:
108    out.write('typedef %(typename)s* (*%(typedef)s)();\n'
109              % {'typename': namespace + '::' + typename,
110                 'typedef': GetTypedefName(typename)})
111  out.write('\n')
112
113  # The actual constructor lists.
114  for typename in typenames:
115    out.write('template <> const %(typedef)s\n'
116              % {'typedef': GetTypedefName(typename)})
117    out.write('PlatformConstructorList<%(typename)s>::kConstructors[] = {\n'
118              % {'typename': namespace + '::' + typename})
119    for platform in platforms:
120      constructor = GetConstructorName(typename, platform)
121      out.write('  &%(namespace)s::%(constructor)s,\n'
122                % {'namespace': namespace, 'constructor': constructor})
123    out.write('};\n')
124    out.write('\n')
125
126  # Exported template instantiation.
127  for typename in typenames:
128    out.write('template class %(export)s PlatformObject<%(typename)s>;\n'
129              % {'export': export, 'typename': namespace + '::' + typename})
130  out.write('\n')
131
132  out.write('}  // namespace ui\n')
133  out.write('\n')
134
135
136def main(argv):
137  parser = optparse.OptionParser()
138  parser.add_option('--namespace', default='ozone')
139  parser.add_option('--export', default='OZONE_EXPORT')
140  parser.add_option('--platform_list')
141  parser.add_option('--output_cc')
142  parser.add_option('--include', action='append', default=[])
143  parser.add_option('--platform', action='append', default=[])
144  parser.add_option('--typename', action='append', default=[])
145  options, _ = parser.parse_args(argv)
146
147  platforms = list(options.platform)
148  typenames = list(options.typename)
149  includes = list(options.include)
150
151  if options.platform_list:
152    platforms = open(options.platform_list, 'r').read().strip().split('\n')
153
154  # Write to standard output or file specified by --output_cc.
155  out_cc = sys.stdout
156  if options.output_cc:
157    out_cc = open(options.output_cc, 'wb')
158
159  GenerateConstructorList(out_cc, options.namespace, options.export,
160                          typenames, platforms, includes)
161
162  if options.output_cc:
163    out_cc.close()
164
165  return 0
166
167
168if __name__ == '__main__':
169  sys.exit(main(sys.argv[1:]))
170