| OLD | NEW |
| (Empty) | |
| 1 #!/usr/bin/python |
| 2 |
| 3 # Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. |
| 6 |
| 7 """Geneartes the types and factory methods needed for Callbacks. |
| 8 |
| 9 See base/callback.h for details on the callback system. |
| 10 """ |
| 11 |
| 12 import datetime |
| 13 from optparse import OptionParser |
| 14 |
| 15 # Supporting functions and methods up to 5 arguments seems to be good enough |
| 16 # for most use cases. The historical callback mechanisms in Chrome only |
| 17 # only supported 5 arguments, and did not have issues. Increase this value if |
| 18 # necessary. The cost is for each argument, you get N more sets of factory |
| 19 # methods, and one more set of callbck classes. |
| 20 MAX_ARGS=5 |
| 21 |
| 22 # Enum type for specifying the return type of a callback. |
| 23 class ReturnType: |
| 24 VOID = 0 |
| 25 RESULT = 1 |
| 26 |
| 27 |
| 28 # Enum type for specifying if we need to generate a template for a |
| 29 # callback that Refcounts the object it wraps. |
| 30 class WillRef: |
| 31 YES = 0 |
| 32 NO = 1 |
| 33 |
| 34 class SpecializationType: |
| 35 METHOD = 0 |
| 36 CONST_METHOD = 1 |
| 37 FUNCTION = 2 |
| 38 |
| 39 |
| 40 HEADER = """\ |
| 41 // Copyright (c) %(year)d The Chromium Authors. All rights reserved. |
| 42 // Use of this source code is governed by a BSD-style license that can be |
| 43 // found in the LICENSE file. |
| 44 |
| 45 // This file is automatically generated by base/generate_callback_templates.py. |
| 46 // DO NOT EDIT! |
| 47 |
| 48 #ifndef BASE_CALLBACK_%(filesuffix)s_H_ |
| 49 |
| 50 %(includes)s |
| 51 |
| 52 namespace base { |
| 53 """ |
| 54 |
| 55 FOOTER = """\ |
| 56 } // namespace base |
| 57 |
| 58 #endif // BASE_CALLBACK_%(filesuffix)s_H_ |
| 59 """ |
| 60 |
| 61 |
| 62 CALLBACK_CLASS_BODY = """\ |
| 63 class %(name)s%(inherit)s { |
| 64 public: |
| 65 virtual ~%(name)s() { }%(methods)s |
| 66 %(run_declaration)s |
| 67 }; |
| 68 """ |
| 69 |
| 70 |
| 71 TEMPLATE_DECLARATION = """template <%s>""" |
| 72 |
| 73 |
| 74 RUN_DECLARATION = "virtual %(return_type)s Run(%(params)s) = 0;" |
| 75 |
| 76 |
| 77 STANDARD_METHODS = """ |
| 78 virtual bool IsRepeatable() const { return false; }""" |
| 79 |
| 80 PREBIND_DECLARATION = """\ |
| 81 %(template_line)s |
| 82 class %(classname)s : public %(interface_name)s""" |
| 83 |
| 84 PREBIND_TYPEDEFS = """\ |
| 85 typedef %(interface_name)s base; |
| 86 typedef %(return_type)s (T::*Signature)()%(spacer)s%(const)s; |
| 87 """ |
| 88 |
| 89 METHOD_CONSTRUCTOR_BODY = """ |
| 90 ::base::internal::RefUtil<%s, T>::TakeRef(object_); |
| 91 \ |
| 92 """ |
| 93 |
| 94 METHOD_DESTRUCTOR_BODY = """ |
| 95 ::base::internal::RefUtil<%s, T>::ReleaseRef(object_); |
| 96 \ |
| 97 """ |
| 98 |
| 99 CONSTRUCTOR_TEMPLATE = """\ |
| 100 inline %(classname)s(%(arglist)s) |
| 101 : %(initializers)s {%(body)s} |
| 102 """ |
| 103 |
| 104 DESTRUCTOR_TEMPLATE = """\ |
| 105 virtual ~%(classname)s() {%(body)s} |
| 106 """ |
| 107 |
| 108 PREBIND_CLASS = """ |
| 109 %(class_decl)s { |
| 110 public: |
| 111 %(typedefs)s |
| 112 |
| 113 private: |
| 114 %(storage)s |
| 115 |
| 116 public: |
| 117 %(constructor)s |
| 118 %(destructor)s |
| 119 virtual bool IsRepeatable() const { |
| 120 return !del; |
| 121 } |
| 122 |
| 123 %(run_func)s |
| 124 }; |
| 125 """ |
| 126 |
| 127 |
| 128 SPECIALIZATION_HELPERS = """\ |
| 129 namespace internal { |
| 130 template <bool ref, typename T> |
| 131 class RefUtil { |
| 132 public: |
| 133 static inline void TakeRef(T* object) { |
| 134 static_cast<typename ::base::RefCountedThreadSafe<T>*>(object)->AddRef(); |
| 135 } |
| 136 |
| 137 static inline void ReleaseRef(T* object) { |
| 138 static_cast<typename ::base::RefCountedThreadSafe<T>*>(object)->Release(); |
| 139 } |
| 140 }; |
| 141 |
| 142 template <typename T> |
| 143 class RefUtil<false, T> { |
| 144 public: |
| 145 static inline void TakeRef(T* object) { |
| 146 } |
| 147 |
| 148 static inline void ReleaseRef(T* object) { |
| 149 } |
| 150 }; |
| 151 |
| 152 // Identity<T>::type is a typedef of T. Useful for preventing the |
| 153 // compiler from inferring the type of an argument in templates. |
| 154 template <typename T> |
| 155 struct Identity { |
| 156 typedef T type; |
| 157 }; |
| 158 } // namespace internal |
| 159 """ |
| 160 |
| 161 RUN_DEFINITON = """\ |
| 162 virtual void Run(%(run_args)s) { |
| 163 if (!del) { |
| 164 (%(deref_prefix)s*function_)(%(invocation_args)s); |
| 165 } else { |
| 166 Signature function = function_; |
| 167 // Null-out pointer now to force sefault if called again. |
| 168 function_ = NULL; |
| 169 (%(deref_prefix)s*function)(%(invocation_args)s); |
| 170 delete this; |
| 171 } |
| 172 }\ |
| 173 """ |
| 174 |
| 175 RESULT_RUN_DEFINITON = """\ |
| 176 virtual R Run(%(run_args)s) { |
| 177 if (!del) { |
| 178 R result = (%(deref_prefix)s*function_)(%(invocation_args)s); |
| 179 return result; |
| 180 } else { |
| 181 Signature function = function_; |
| 182 // Null-out pointer now to force a segfault if called again. |
| 183 function_ = NULL; |
| 184 R result = (%(deref_prefix)s*function)(%(invocation_args)s); |
| 185 delete this; |
| 186 return result; |
| 187 } |
| 188 }\ |
| 189 """ |
| 190 |
| 191 |
| 192 FACTORY_METHOD = """\ |
| 193 %(template_line)s |
| 194 %(typename_prefix)s%(qualified_classname)s::base* |
| 195 New%(variant)sCallback(%(factory_args)s) { |
| 196 return new %(qualified_classname)s(%(constructor_args)s); |
| 197 } |
| 198 """ |
| 199 |
| 200 def GenerateRunDeclaration(return_type, args): |
| 201 if return_type == ReturnType.VOID: |
| 202 return_type = 'void' |
| 203 elif return_type == ReturnType.RESULT: |
| 204 return_type = 'R' |
| 205 params = ', '.join(Expand('A%(n)d', args)) |
| 206 return RUN_DECLARATION % { 'return_type' : return_type, 'params' : params } |
| 207 |
| 208 |
| 209 def GenerateSignatureTypeList(return_type, prebind, args): |
| 210 template_params = [] |
| 211 if return_type == ReturnType.RESULT: |
| 212 template_params.append('typename R') |
| 213 template_params.extend( |
| 214 ['typename P%d' % (x+1) for x in xrange(0, prebind)]) |
| 215 template_params.extend( |
| 216 ['typename A%d' % (x+1) for x in xrange(0, args)]) |
| 217 return template_params |
| 218 |
| 219 |
| 220 def GenerateTemplateLine(template_params): |
| 221 return TEMPLATE_DECLARATION % ', '.join(template_params) |
| 222 |
| 223 |
| 224 def PrintClosure(will_ref): |
| 225 if will_ref == WillRef.NO: |
| 226 name = 'Closure' |
| 227 inherit = '' |
| 228 if will_ref == WillRef.YES: |
| 229 name = 'RefClosure' |
| 230 inherit = ' : public Closure' |
| 231 run_declaration = GenerateRunDeclaration(ReturnType.VOID, 0) |
| 232 print CALLBACK_CLASS_BODY % { 'name' : name, |
| 233 'methods' : STANDARD_METHODS, |
| 234 'inherit' : inherit, |
| 235 'run_declaration': run_declaration } |
| 236 |
| 237 |
| 238 def PrintOneClass(return_type, args): |
| 239 if return_type == ReturnType.VOID: |
| 240 barename = 'Callback' |
| 241 if return_type == ReturnType.RESULT: |
| 242 barename = 'ResultCallback' |
| 243 |
| 244 if args == 0: |
| 245 name = barename |
| 246 else: |
| 247 name = '%s%d' % (barename, args) |
| 248 |
| 249 run_declaration = GenerateRunDeclaration(return_type, args) |
| 250 print GenerateTemplateLine(GenerateSignatureTypeList(return_type, 0, args)) |
| 251 print CALLBACK_CLASS_BODY % { 'name' : name, |
| 252 'methods' : STANDARD_METHODS, |
| 253 'inherit' : '', |
| 254 'run_declaration': run_declaration } |
| 255 |
| 256 |
| 257 def PrintCallbackClass(return_type, args): |
| 258 if args == 0 and return_type == ReturnType.VOID: |
| 259 # This is the pure Closure case. Generate the two closure classes. |
| 260 PrintClosure(WillRef.NO); |
| 261 PrintClosure(WillRef.YES); |
| 262 else: |
| 263 PrintOneClass(return_type, args) |
| 264 |
| 265 |
| 266 def PrintTypes(year): |
| 267 print HEADER % { 'year' : year, 'filesuffix' : 'TYPE', 'includes': '' } |
| 268 for args in xrange(0, MAX_ARGS + 1): |
| 269 PrintCallbackClass(ReturnType.VOID, args) |
| 270 PrintCallbackClass(ReturnType.RESULT, args) |
| 271 print FOOTER % { 'year' : year, 'filesuffix' : 'TYPE' } |
| 272 |
| 273 |
| 274 def GenerateInterfaceName(return_type, args, will_ref): |
| 275 if args == 0: |
| 276 if will_ref == WillRef.YES: |
| 277 return 'RefClosure' |
| 278 elif will_ref == WillRef.NO: |
| 279 return 'Closure' |
| 280 arg_types = Expand('A%(n)d', args) |
| 281 if return_type == ReturnType.VOID: |
| 282 return 'Callback%d<%s>' % (args, ', '.join(arg_types)) |
| 283 elif return_type == ReturnType.RESULT: |
| 284 result_args = ['R'] |
| 285 result_args.extend(arg_types) |
| 286 return 'ResultCallback%d<%s>' % (args, ', '.join(result_args)) |
| 287 |
| 288 |
| 289 #TODO(ajwong): will_Ref is unused. remove. |
| 290 def GenerateClassName(specialization_type, return_type, prebind, args, will_ref)
: |
| 291 base_name = "CB_" |
| 292 if specialization_type == SpecializationType.CONST_METHOD: |
| 293 base_name += 'ConstMethod' |
| 294 elif specialization_type == SpecializationType.METHOD: |
| 295 base_name += 'Method' |
| 296 elif specialization_type == SpecializationType.FUNCTION: |
| 297 base_name += 'Function' |
| 298 |
| 299 if return_type == ReturnType.RESULT: |
| 300 base_name += 'Result' |
| 301 |
| 302 return "%sCallback_%d_%d" % (base_name, prebind, args) |
| 303 |
| 304 |
| 305 def Expand(pattern, num): |
| 306 return [pattern % {'n' : (x+1)} for x in xrange(0, num)] |
| 307 |
| 308 def GeneratePrebindDeclaration(object_type, return_type, prebind, args, classnam
e, interface_name, will_ref): |
| 309 type_list = GenerateSignatureTypeList(return_type, prebind, args) |
| 310 |
| 311 # Special case the 0-argument specialization for refcounted callbacks to |
| 312 # derive from RefClosure instead of Closure so that interfaces can |
| 313 # rely on the static type to ensure only refcounted closures are allowed. |
| 314 if args == 0 and will_ref == WillRef.YES: |
| 315 prebind_template_typelist = ['bool del'] |
| 316 specialization_list = ['del', 'true'] |
| 317 if object_type != '': |
| 318 prebind_template_typelist.append('typename T') |
| 319 specialization_list.append('T') |
| 320 specialization_list.extend([x.split(' ')[1] for x in type_list]) |
| 321 specialization = '<%s>' % ', '.join(specialization_list) |
| 322 else: |
| 323 prebind_template_typelist = ['bool del', 'bool ref'] |
| 324 if object_type != '': |
| 325 prebind_template_typelist.append('typename T') |
| 326 specialization = '' |
| 327 |
| 328 prebind_template_typelist.extend(type_list) |
| 329 template_line = GenerateTemplateLine(prebind_template_typelist) |
| 330 |
| 331 return PREBIND_DECLARATION % {'template_line': template_line, |
| 332 'classname': classname + specialization, |
| 333 'interface_name': interface_name} |
| 334 |
| 335 def GenerateSignatureTemplate(specialization_type): |
| 336 if specialization_type == SpecializationType.METHOD: |
| 337 return '%s (T::*%s)(%s)' |
| 338 elif specialization_type == SpecializationType.CONST_METHOD: |
| 339 return '%s (T::*%s)(%s) const' |
| 340 elif specialization_type == SpecializationType.FUNCTION: |
| 341 return '%s (*%s)(%s)' |
| 342 |
| 343 |
| 344 def GenerateTypedefs(specialization_type, return_type, prebind, args, interface_
name): |
| 345 base_typedef = 'typedef %s base;' % interface_name |
| 346 if return_type == ReturnType.RESULT: |
| 347 return_string = 'R' |
| 348 elif return_type == ReturnType.VOID: |
| 349 return_string = 'void' |
| 350 |
| 351 all_args = Expand('P%(n)d', prebind) |
| 352 all_args.extend(Expand('A%(n)d', args)) |
| 353 arg_list = ', '.join(all_args) |
| 354 |
| 355 signature_type = GenerateSignatureTemplate(specialization_type) % (return_stri
ng, 'Signature', arg_list) |
| 356 signature = 'typedef %s;' % signature_type |
| 357 return '\n '.join([base_typedef, signature]) |
| 358 |
| 359 |
| 360 def GenerateObjectType(specialization_type): |
| 361 if specialization_type == SpecializationType.METHOD: |
| 362 return 'T*'; |
| 363 elif specialization_type == SpecializationType.CONST_METHOD: |
| 364 return 'const T*' |
| 365 elif specialization_type == SpecializationType.FUNCTION: |
| 366 return '' |
| 367 |
| 368 |
| 369 def GenerateStorage(object_type, prebind): |
| 370 if object_type: |
| 371 storage_decls = ['%s object_;' % object_type] |
| 372 else: |
| 373 storage_decls = [] |
| 374 |
| 375 storage_decls.append('Signature function_;') |
| 376 storage_decls.extend(Expand('typename ::std::tr1::remove_reference<P%(n)d>::ty
pe p%(n)d_;', prebind)) |
| 377 return '\n '.join(storage_decls) |
| 378 |
| 379 |
| 380 def GenerateConstructor(object_type, prebind, classname, will_ref): |
| 381 if will_ref == WillRef.YES: |
| 382 ref = 'true' |
| 383 elif will_ref == WillRef.NO: |
| 384 ref = 'false' |
| 385 |
| 386 if object_type: |
| 387 constructor_arglist = ['%s object' % object_type] |
| 388 body = METHOD_CONSTRUCTOR_BODY % ref |
| 389 initializers = ['object_(object)', 'function_(function)'] |
| 390 else: |
| 391 constructor_arglist = [] |
| 392 body = ' ' |
| 393 initializers = ['function_(function)'] |
| 394 constructor_arglist.append('Signature function') |
| 395 constructor_arglist.extend(Expand('P%(n)d p%(n)d', prebind)) |
| 396 initializers.extend(Expand('p%(n)d_(p%(n)d)', prebind)) |
| 397 return CONSTRUCTOR_TEMPLATE % {'classname': classname, |
| 398 'arglist': ', '.join(constructor_arglist), |
| 399 'initializers': ',\n '.join(initializers), |
| 400 'body': body } |
| 401 |
| 402 |
| 403 def GenerateDestructor(object_type, classname, will_ref): |
| 404 if will_ref == WillRef.YES: |
| 405 ref = 'true' |
| 406 elif will_ref == WillRef.NO: |
| 407 ref = 'ref' |
| 408 |
| 409 if object_type: |
| 410 body = METHOD_DESTRUCTOR_BODY % ref |
| 411 else: |
| 412 body = ' ' |
| 413 return DESTRUCTOR_TEMPLATE % {'classname': classname, 'body': body} |
| 414 |
| 415 |
| 416 def GenerateRunDefinition(object_type, return_type, prebind, args): |
| 417 arg_list = Expand('A%(n)d a%(n)d', args) |
| 418 invocation_list = Expand('p%(n)d_', prebind) |
| 419 invocation_list.extend(Expand('a%(n)d', args)) |
| 420 params = {'run_args': ', '.join(arg_list), |
| 421 'invocation_args': ', '.join(invocation_list)} |
| 422 if object_type != '': |
| 423 params['deref_prefix'] = 'object_->' |
| 424 else: |
| 425 params['deref_prefix'] = '' |
| 426 if return_type == ReturnType.VOID: |
| 427 return RUN_DEFINITON % params |
| 428 elif return_type == ReturnType.RESULT: |
| 429 return RESULT_RUN_DEFINITON % params |
| 430 |
| 431 |
| 432 def PrintCallbackFactory(specialization_type, return_type, prebind, args, will_r
ef, permanent): |
| 433 if permanent: |
| 434 specialization_list = ['false'] |
| 435 variant = 'Permanent' |
| 436 else: |
| 437 specialization_list = ['true'] |
| 438 variant = '' |
| 439 |
| 440 if will_ref == WillRef.YES: |
| 441 specialization_list.append('true') |
| 442 variant += 'Ref' |
| 443 else: |
| 444 specialization_list.append('false') |
| 445 |
| 446 if specialization_type == SpecializationType.METHOD: |
| 447 factory_arglist = ['T* object'] |
| 448 constructor_arglist = ['object'] |
| 449 type_list = ['typename T'] |
| 450 elif specialization_type == SpecializationType.CONST_METHOD: |
| 451 factory_arglist = ['const T* object'] |
| 452 constructor_arglist = ['object'] |
| 453 type_list = ['typename T'] |
| 454 elif specialization_type == SpecializationType.FUNCTION: |
| 455 factory_arglist = [] |
| 456 constructor_arglist = [] |
| 457 type_list = [] |
| 458 |
| 459 type_list.extend(GenerateSignatureTypeList(return_type, prebind, args)) |
| 460 specialization_list.extend([x.split(' ')[1] for x in type_list]) |
| 461 if len(type_list) == 0: |
| 462 typename_prefix = '' |
| 463 else: |
| 464 typename_prefix = 'typename ' |
| 465 |
| 466 classname = GenerateClassName(specialization_type, return_type, prebind, args,
will_ref) |
| 467 qualified_classname = '%s<%s>' % (classname, ', '.join(specialization_list)) |
| 468 |
| 469 arg_list = Expand('P%(n)d', prebind) |
| 470 arg_list.extend(Expand('A%(n)d', args)) |
| 471 template = GenerateSignatureTemplate(specialization_type) |
| 472 if return_type == ReturnType.VOID: |
| 473 return_string = 'void' |
| 474 elif return_type == ReturnType.RESULT: |
| 475 return_string = 'R' |
| 476 signature_arg = template % (return_string, 'function', ','.join(arg_list)) |
| 477 factory_arglist.append(signature_arg) |
| 478 factory_arglist.extend(Expand('typename ::base::internal::Identity<P%(n)d>::ty
pe p%(n)d', prebind)) |
| 479 |
| 480 constructor_arglist.append('function') |
| 481 constructor_arglist.extend(Expand('p%(n)d', prebind)) |
| 482 |
| 483 params = {} |
| 484 params['qualified_classname'] = qualified_classname |
| 485 params['factory_args'] = ', '.join(factory_arglist) |
| 486 params['constructor_args'] = ', '.join(constructor_arglist) |
| 487 params['variant'] = variant |
| 488 params['typename_prefix'] = typename_prefix |
| 489 |
| 490 # In this base case, there are no templates. |
| 491 if (specialization_type == SpecializationType.FUNCTION and |
| 492 return_type == ReturnType.VOID and |
| 493 args == 0 and prebind == 0): |
| 494 params['template_line'] = '' |
| 495 else: |
| 496 params['template_line'] = 'template <%s>' % ', '.join(type_list) |
| 497 |
| 498 print FACTORY_METHOD % params |
| 499 |
| 500 |
| 501 #TODO(ajwong): We don't need all of these for function factories. Fix. |
| 502 def PrintSpecializationClass(specialization_type, return_type, prebind, args): |
| 503 PrintSpecializationClassHelper(specialization_type, return_type, WillRef.NO, p
rebind, args) |
| 504 PrintCallbackFactory(specialization_type, return_type, prebind, args, WillRef.
NO, False) |
| 505 PrintCallbackFactory(specialization_type, return_type, prebind, args, WillRef.
NO, True) |
| 506 if specialization_type != SpecializationType.FUNCTION: |
| 507 if args == 0: |
| 508 PrintSpecializationClassHelper(specialization_type, return_type, WillRef.Y
ES, prebind, args) |
| 509 PrintCallbackFactory(specialization_type, return_type, prebind, args, WillRe
f.YES, False) |
| 510 PrintCallbackFactory(specialization_type, return_type, prebind, args, WillRe
f.YES, True) |
| 511 |
| 512 |
| 513 def PrintSpecializationClassHelper(specialization_type, return_type, will_ref, p
rebind, args): |
| 514 classname = GenerateClassName(specialization_type, return_type, prebind, args,
will_ref) |
| 515 interface_name = GenerateInterfaceName(return_type, args, will_ref) |
| 516 object_type = GenerateObjectType(specialization_type) |
| 517 |
| 518 params = {} |
| 519 params['class_decl'] = GeneratePrebindDeclaration(object_type, return_type, pr
ebind, args, classname, interface_name, will_ref) |
| 520 params['typedefs'] = GenerateTypedefs(specialization_type, return_type, prebin
d, args, interface_name) |
| 521 params['storage'] = GenerateStorage(object_type, prebind) |
| 522 params['constructor'] = GenerateConstructor(object_type, prebind, classname, w
ill_ref) |
| 523 params['destructor'] = GenerateDestructor(object_type, classname, will_ref) |
| 524 params['run_func'] = GenerateRunDefinition(object_type, return_type, prebind,
args) |
| 525 |
| 526 print PREBIND_CLASS % params |
| 527 |
| 528 |
| 529 def PrintSpecializations(year): |
| 530 includes = ['#include <tr1/type_traits>', '#include "base/ref_counted.h"'] |
| 531 print HEADER % {'year': year, |
| 532 'filesuffix': 'SPECIALIZATIONS', |
| 533 'includes': '\n'.join(includes)} |
| 534 print SPECIALIZATION_HELPERS |
| 535 for args in xrange(0, MAX_ARGS + 1): |
| 536 for prebind in xrange(0, MAX_ARGS + 1): |
| 537 PrintSpecializationClass(SpecializationType.METHOD, ReturnType.VOID, prebi
nd, args) |
| 538 PrintSpecializationClass(SpecializationType.METHOD, ReturnType.RESULT, pre
bind, args) |
| 539 PrintSpecializationClass(SpecializationType.CONST_METHOD, ReturnType.VOID,
prebind, args) |
| 540 PrintSpecializationClass(SpecializationType.CONST_METHOD, ReturnType.RESUL
T, prebind, args) |
| 541 PrintSpecializationClass(SpecializationType.FUNCTION, ReturnType.VOID, pre
bind, args) |
| 542 PrintSpecializationClass(SpecializationType.FUNCTION, ReturnType.RESULT, p
rebind, args) |
| 543 print FOOTER % { 'year' : year, 'filesuffix' : 'SPECIALIZATIONS' } |
| 544 |
| 545 |
| 546 def main(): |
| 547 parser = OptionParser() |
| 548 parser.add_option("-m", "--mode", dest="mode", |
| 549 help="Either 'types' or 'specializations' to generate " |
| 550 "either the types for all the callbacks, or the factory " |
| 551 "methods and the corresponding specializations.") |
| 552 (options, args) = parser.parse_args() |
| 553 |
| 554 year = datetime.datetime.now().year |
| 555 if options.mode == 'types': |
| 556 PrintTypes(year) |
| 557 elif options.mode == 'specializations': |
| 558 PrintSpecializations(year) |
| 559 |
| 560 |
| 561 if __name__ == '__main__': |
| 562 main() |
| OLD | NEW |