1#!/usr/bin/env python 2# Copyright (c) 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 6import cStringIO 7import fnmatch 8import optparse 9import os 10import re 11import sys 12 13VALID_CHANNELS = ('stable', 'beta', 'dev') 14 15ROOT_FILE_CONTENTS = """.. _pepper_%(channel)s_index: 16 17:orphan: 18 19.. DO NOT EDIT! This document is auto-generated by doxygen/rst_index.py. 20 21######################################## 22Pepper API Reference (%(channel_title)s) 23######################################## 24 25This page lists the API for Pepper %(version)s. Apps that use this API can 26run in Chrome %(version)s or higher. 27 28:ref:`Pepper C API Reference <pepper_%(channel)s_c_index>` 29=========================================================== 30 31:ref:`Pepper C++ API Reference <pepper_%(channel)s_cpp_index>` 32=============================================================== 33 34""" 35 36C_FILE_CONTENTS = """.. _pepper_%(channel)s_c_index: 37 38.. DO NOT EDIT! This document is auto-generated by doxygen/rst_index.py. 39 40########################################## 41Pepper C API Reference (%(channel_title)s) 42########################################## 43 44This page lists the C API for Pepper %(version)s. Apps that use this API can 45run in Chrome %(version)s or higher. 46 47`Interfaces <group___interfaces.html>`_ 48======================================= 49%(interfaces)s 50 51`Structures <group___structs.html>`_ 52==================================== 53%(structures)s 54 55`Functions <group___functions.html>`_ 56===================================== 57 58`Enums <group___enums.html>`_ 59============================= 60 61`Typedefs <group___typedefs.html>`_ 62=================================== 63 64`Macros <globals_defs.html>`_ 65============================= 66 67Files 68===== 69%(files)s 70""" 71 72C_INTERFACE_WILDCARDS = ['struct_p_p_p__*', 'struct_p_p_b__*'] 73 74C_STRUCT_WILDCARDS = ['struct_p_p__*', 'union_p_p__*'] 75 76CPP_FILE_CONTENTS = """.. _pepper_%(channel)s_cpp_index: 77 78.. DO NOT EDIT! This document is auto-generated by doxygen/rst_index.py. 79 80############################################ 81Pepper C++ API Reference (%(channel_title)s) 82############################################ 83 84This page lists the C++ API for Pepper %(version)s. Apps that use this API can 85run in Chrome %(version)s or higher. 86 87`Classes <inherits.html>`_ 88========================== 89%(classes)s 90 91Files 92===== 93%(files)s 94""" 95 96CPP_CLASSES_WILDCARDS = ['classpp_1_1*.html'] 97CPP_CLASSES_EXCLUDES = ['*-members*'] 98 99FILE_WILDCARDS = ['*_8h.html'] 100 101 102def GetName(filename): 103 filename = os.path.splitext(filename)[0] 104 out = '' 105 if filename.startswith('struct_p_p_b__'): 106 mangle = filename[7:] # skip "struct_" 107 elif filename.startswith('struct_p_p_p__'): 108 mangle = filename[7:] # skip "struct_" 109 elif filename.startswith('struct_p_p__'): 110 mangle = filename[7:] # skip "struct_" 111 elif filename.startswith('union_p_p__'): 112 mangle = filename[6:] # skip "union_" 113 elif filename.startswith('classpp_1_1_'): 114 mangle = filename[12:] 115 elif filename.startswith('classpp_1_1ext_1_1_'): 116 out = 'Ext::' # maybe 'ext::' ? 117 mangle = filename[19:] 118 elif filename.startswith('classpp_1_1internal_1_1_'): 119 out = 'Internal::' # maybe 'internal::' 120 mangle = filename[24:] 121 elif filename.startswith('structpp_1_1internal_1_1_'): 122 out = 'Internal::' 123 mangle = filename[25:] 124 elif filename.endswith('_8h'): 125 return filename[:-3].replace('__', '_') + '.h' 126 else: 127 print 'No match: ' + filename 128 cap = True 129 for c in mangle: 130 if c == '_': 131 if cap: 132 # If cap is True, we've already read one underscore. The second means 133 # that we should insert a literal underscore. 134 cap = False 135 else: 136 cap = True 137 continue 138 if cap: 139 c = c.upper() 140 cap = False 141 out += c 142 143 # Strip trailing version number (e.g. PPB_Audio_1_1 -> PPB_Audio) 144 return re.sub(r'_\d_\d$', '', out) 145 146 147def GetPath(filepath): 148 if os.path.exists(filepath): 149 return filepath 150 raise OSError('Couldnt find: ' + filepath) 151 152 153def MakeReSTListFromFiles(path, matches, excludes=None): 154 dir_files = os.listdir(path) 155 good_files = [] 156 for match in matches: 157 good_files.extend(fnmatch.filter(dir_files, match)) 158 159 if excludes: 160 for exclude in excludes: 161 good_files = [filename for filename in good_files 162 if not fnmatch.fnmatch(filename, exclude)] 163 164 good_files.sort() 165 return '\n'.join(' * `%s <%s>`_\n' % (GetName(f), f) for f in good_files) 166 167 168def MakeTitleCase(s): 169 return s[0].upper() + s[1:] 170 171 172def GenerateRootIndex(channel, version, out_filename): 173 channel_title = MakeTitleCase(channel) 174 175 # Use StringIO so we don't write out a partial file on error. 176 output = cStringIO.StringIO() 177 output.write(ROOT_FILE_CONTENTS % vars()) 178 179 with open(out_filename, 'w') as f: 180 f.write(output.getvalue()) 181 182 183def GenerateCIndex(root_dir, channel, version, out_filename): 184 interfaces = MakeReSTListFromFiles(root_dir, C_INTERFACE_WILDCARDS) 185 structures = MakeReSTListFromFiles(root_dir, C_STRUCT_WILDCARDS) 186 files = MakeReSTListFromFiles(root_dir, FILE_WILDCARDS) 187 channel_title = MakeTitleCase(channel) 188 189 # Use StringIO so we don't write out a partial file on error. 190 output = cStringIO.StringIO() 191 output.write(C_FILE_CONTENTS % vars()) 192 193 with open(out_filename, 'w') as f: 194 f.write(output.getvalue()) 195 196 197def GenerateCppIndex(root_dir, channel, version, out_filename): 198 classes = MakeReSTListFromFiles(root_dir, CPP_CLASSES_WILDCARDS, 199 CPP_CLASSES_EXCLUDES) 200 files = MakeReSTListFromFiles(root_dir, FILE_WILDCARDS) 201 channel_title = MakeTitleCase(channel) 202 203 # Use StringIO so we don't write out a partial file on error. 204 output = cStringIO.StringIO() 205 output.write(CPP_FILE_CONTENTS % vars()) 206 207 with open(out_filename, 'w') as f: 208 f.write(output.getvalue()) 209 210 211def main(argv): 212 usage = 'Usage: %prog [options] <--root|--c|--cpp> directory' 213 parser = optparse.OptionParser(usage=usage) 214 parser.add_option('--channel', help='pepper channel (stable, beta, dev)') 215 parser.add_option('--version', help='pepper version (e.g. 32, 33, 34, etc.)') 216 parser.add_option('--root', help='Generate root API index', 217 action='store_true', default=False) 218 parser.add_option('--c', help='Generate C API index', action='store_true', 219 default=False) 220 parser.add_option('--cpp', help='Generate C++ API index', action='store_true', 221 default=False) 222 parser.add_option('-o', '--output', help='output file.') 223 options, files = parser.parse_args(argv) 224 225 if len(files) != 1: 226 parser.error('Expected one directory') 227 228 if not options.output: 229 parser.error('Need output file') 230 231 if options.channel not in VALID_CHANNELS: 232 parser.error('Expected channel to be one of %s' % ', '.join(VALID_CHANNELS)) 233 234 if sum((options.c, options.cpp, options.root)) != 1: 235 parser.error('Exactly one of --c/--cpp/--root flags is required.') 236 237 root_dir = files[0] 238 239 if options.c: 240 GenerateCIndex(root_dir, options.channel, options.version, options.output) 241 elif options.cpp: 242 GenerateCppIndex(root_dir, options.channel, options.version, options.output) 243 elif options.root: 244 GenerateRootIndex(options.channel, options.version, options.output) 245 else: 246 assert(False) 247 return 0 248 249 250if __name__ == '__main__': 251 try: 252 rtn = main(sys.argv[1:]) 253 except KeyboardInterrupt: 254 sys.stderr.write('%s: interrupted\n' % os.path.basename(__file__)) 255 rtn = 1 256 sys.exit(rtn) 257