mkdoc.py (11986:c12e4625ab56) | mkdoc.py (12391:ceeca8b41e4b) |
---|---|
1#!/usr/bin/env python3 2# 3# Syntax: mkdoc.py [-I<path> ..] [.. a list of header files ..] 4# 5# Extract documentation from C++ header files to use it in Python bindings 6# 7 8import os --- 42 unchanged lines hidden (view full) --- 51} 52 53CPP_OPERATORS = OrderedDict( 54 sorted(CPP_OPERATORS.items(), key=lambda t: -len(t[0]))) 55 56job_count = cpu_count() 57job_semaphore = Semaphore(job_count) 58 | 1#!/usr/bin/env python3 2# 3# Syntax: mkdoc.py [-I<path> ..] [.. a list of header files ..] 4# 5# Extract documentation from C++ header files to use it in Python bindings 6# 7 8import os --- 42 unchanged lines hidden (view full) --- 51} 52 53CPP_OPERATORS = OrderedDict( 54 sorted(CPP_OPERATORS.items(), key=lambda t: -len(t[0]))) 55 56job_count = cpu_count() 57job_semaphore = Semaphore(job_count) 58 |
59registered_names = dict() | 59output = [] |
60 | 60 |
61 | |
62def d(s): 63 return s.decode('utf8') 64 65 66def sanitize_name(name): | 61def d(s): 62 return s.decode('utf8') 63 64 65def sanitize_name(name): |
67 global registered_names | |
68 name = re.sub(r'type-parameter-0-([0-9]+)', r'T\1', name) 69 for k, v in CPP_OPERATORS.items(): 70 name = name.replace('operator%s' % k, 'operator_%s' % v) 71 name = re.sub('<.*>', '', name) 72 name = ''.join([ch if ch.isalnum() else '_' for ch in name]) 73 name = re.sub('_$', '', re.sub('_+', '_', name)) | 66 name = re.sub(r'type-parameter-0-([0-9]+)', r'T\1', name) 67 for k, v in CPP_OPERATORS.items(): 68 name = name.replace('operator%s' % k, 'operator_%s' % v) 69 name = re.sub('<.*>', '', name) 70 name = ''.join([ch if ch.isalnum() else '_' for ch in name]) 71 name = re.sub('_$', '', re.sub('_+', '_', name)) |
74 if name in registered_names: 75 registered_names[name] += 1 76 name += '_' + str(registered_names[name]) 77 else: 78 registered_names[name] = 1 | |
79 return '__doc_' + name 80 81 82def process_comment(comment): 83 result = '' 84 85 # Remove C++ comment syntax 86 leading_spaces = float('inf') --- 97 unchanged lines hidden (view full) --- 184 wrapper.subsequent_indent = ' ' * 4 185 else: 186 if len(wrapped) > 0: 187 result += wrapped + '\n\n' 188 wrapper.initial_indent = wrapper.subsequent_indent = '' 189 return result.rstrip().lstrip('\n') 190 191 | 72 return '__doc_' + name 73 74 75def process_comment(comment): 76 result = '' 77 78 # Remove C++ comment syntax 79 leading_spaces = float('inf') --- 97 unchanged lines hidden (view full) --- 177 wrapper.subsequent_indent = ' ' * 4 178 else: 179 if len(wrapped) > 0: 180 result += wrapped + '\n\n' 181 wrapper.initial_indent = wrapper.subsequent_indent = '' 182 return result.rstrip().lstrip('\n') 183 184 |
192def extract(filename, node, prefix, output): 193 num_extracted = 0 | 185def extract(filename, node, prefix): |
194 if not (node.location.file is None or 195 os.path.samefile(d(node.location.file.name), filename)): 196 return 0 197 if node.kind in RECURSE_LIST: 198 sub_prefix = prefix 199 if node.kind != CursorKind.TRANSLATION_UNIT: 200 if len(sub_prefix) > 0: 201 sub_prefix += '_' 202 sub_prefix += d(node.spelling) 203 for i in node.get_children(): | 186 if not (node.location.file is None or 187 os.path.samefile(d(node.location.file.name), filename)): 188 return 0 189 if node.kind in RECURSE_LIST: 190 sub_prefix = prefix 191 if node.kind != CursorKind.TRANSLATION_UNIT: 192 if len(sub_prefix) > 0: 193 sub_prefix += '_' 194 sub_prefix += d(node.spelling) 195 for i in node.get_children(): |
204 num_extracted += extract(filename, i, sub_prefix, output) 205 if num_extracted == 0: 206 return 0 | 196 extract(filename, i, sub_prefix) |
207 if node.kind in PRINT_LIST: 208 comment = d(node.raw_comment) if node.raw_comment is not None else '' 209 comment = process_comment(comment) 210 sub_prefix = prefix 211 if len(sub_prefix) > 0: 212 sub_prefix += '_' 213 if len(node.spelling) > 0: 214 name = sanitize_name(sub_prefix + d(node.spelling)) | 197 if node.kind in PRINT_LIST: 198 comment = d(node.raw_comment) if node.raw_comment is not None else '' 199 comment = process_comment(comment) 200 sub_prefix = prefix 201 if len(sub_prefix) > 0: 202 sub_prefix += '_' 203 if len(node.spelling) > 0: 204 name = sanitize_name(sub_prefix + d(node.spelling)) |
215 output.append('\nstatic const char *%s =%sR"doc(%s)doc";' % 216 (name, '\n' if '\n' in comment else ' ', comment)) 217 num_extracted += 1 218 return num_extracted | 205 global output 206 output.append((name, filename, comment)) |
219 220 221class ExtractionThread(Thread): | 207 208 209class ExtractionThread(Thread): |
222 def __init__(self, filename, parameters, output): | 210 def __init__(self, filename, parameters): |
223 Thread.__init__(self) 224 self.filename = filename 225 self.parameters = parameters | 211 Thread.__init__(self) 212 self.filename = filename 213 self.parameters = parameters |
226 self.output = output | |
227 job_semaphore.acquire() 228 229 def run(self): 230 print('Processing "%s" ..' % self.filename, file=sys.stderr) 231 try: 232 index = cindex.Index( 233 cindex.conf.lib.clang_createIndex(False, True)) 234 tu = index.parse(self.filename, self.parameters) | 214 job_semaphore.acquire() 215 216 def run(self): 217 print('Processing "%s" ..' % self.filename, file=sys.stderr) 218 try: 219 index = cindex.Index( 220 cindex.conf.lib.clang_createIndex(False, True)) 221 tu = index.parse(self.filename, self.parameters) |
235 extract(self.filename, tu.cursor, '', self.output) | 222 extract(self.filename, tu.cursor, '') |
236 finally: 237 job_semaphore.release() 238 239if __name__ == '__main__': 240 parameters = ['-x', 'c++', '-std=c++11'] 241 filenames = [] 242 243 if platform.system() == 'Darwin': --- 40 unchanged lines hidden (view full) --- 284#define DOC(...) __EXPAND(__EXPAND(__CAT2(__DOC, __VA_SIZE(__VA_ARGS__)))(__VA_ARGS__)) 285 286#if defined(__GNUG__) 287#pragma GCC diagnostic push 288#pragma GCC diagnostic ignored "-Wunused-variable" 289#endif 290''') 291 | 223 finally: 224 job_semaphore.release() 225 226if __name__ == '__main__': 227 parameters = ['-x', 'c++', '-std=c++11'] 228 filenames = [] 229 230 if platform.system() == 'Darwin': --- 40 unchanged lines hidden (view full) --- 271#define DOC(...) __EXPAND(__EXPAND(__CAT2(__DOC, __VA_SIZE(__VA_ARGS__)))(__VA_ARGS__)) 272 273#if defined(__GNUG__) 274#pragma GCC diagnostic push 275#pragma GCC diagnostic ignored "-Wunused-variable" 276#endif 277''') 278 |
292 output = [] | 279 output.clear() |
293 for filename in filenames: | 280 for filename in filenames: |
294 thr = ExtractionThread(filename, parameters, output) | 281 thr = ExtractionThread(filename, parameters) |
295 thr.start() 296 297 print('Waiting for jobs to finish ..', file=sys.stderr) 298 for i in range(job_count): 299 job_semaphore.acquire() 300 | 282 thr.start() 283 284 print('Waiting for jobs to finish ..', file=sys.stderr) 285 for i in range(job_count): 286 job_semaphore.acquire() 287 |
301 output.sort() 302 for l in output: 303 print(l) | 288 name_ctr = 1 289 name_prev = None 290 for name, _, comment in list(sorted(output, key=lambda x: (x[0], x[1]))): 291 if name == name_prev: 292 name_ctr += 1 293 name = name + "_%i" % name_ctr 294 else: 295 name_prev = name 296 name_ctr = 1 297 print('\nstatic const char *%s =%sR"doc(%s)doc";' % 298 (name, '\n' if '\n' in comment else ' ', comment)) |
304 305 print(''' 306#if defined(__GNUG__) 307#pragma GCC diagnostic pop 308#endif 309''') | 299 300 print(''' 301#if defined(__GNUG__) 302#pragma GCC diagnostic pop 303#endif 304''') |