AccEventGen.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #!/usr/bin/env python
  2. #
  3. # This Source Code Form is subject to the terms of the Mozilla Public
  4. # License, v. 2.0. If a copy of the MPL was not distributed with this
  5. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. import sys
  7. import os
  8. import buildconfig
  9. import mozpack.path as mozpath
  10. # The xpidl parser is not incorporated in the in-tree virtualenv.
  11. xpidl_dir = mozpath.join(buildconfig.topsrcdir, 'xpcom', 'idl-parser',
  12. 'xpidl')
  13. xpidl_cachedir = mozpath.join(buildconfig.topobjdir, 'xpcom', 'idl-parser',
  14. 'xpidl')
  15. sys.path.extend([xpidl_dir, xpidl_cachedir])
  16. import xpidl
  17. # Instantiate the parser.
  18. p = xpidl.IDLParser()
  19. def findIDL(includePath, interfaceFileName):
  20. for d in includePath:
  21. path = mozpath.join(d, interfaceFileName)
  22. if os.path.exists(path):
  23. return path
  24. raise BaseException("No IDL file found for interface %s "
  25. "in include path %r"
  26. % (interfaceFileName, includePath))
  27. def loadEventIDL(parser, includePath, eventname):
  28. eventidl = ("nsIAccessible%s.idl" % eventname)
  29. idlFile = findIDL(includePath, eventidl)
  30. idl = p.parse(open(idlFile).read(), idlFile)
  31. idl.resolve(includePath, p)
  32. return idl, idlFile
  33. class Configuration:
  34. def __init__(self, filename):
  35. config = {}
  36. execfile(filename, config)
  37. self.simple_events = config.get('simple_events', [])
  38. def firstCap(str):
  39. return str[0].upper() + str[1:]
  40. def writeAttributeParams(a):
  41. return ("%s a%s" % (a.realtype.nativeType('in'), firstCap(a.name)))
  42. def print_header_file(fd, conf, incdirs):
  43. idl_paths = set()
  44. fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n")
  45. fd.write("#ifndef _mozilla_a11y_generated_AccEvents_h_\n"
  46. "#define _mozilla_a11y_generated_AccEvents_h_\n\n")
  47. fd.write("#include \"nscore.h\"\n")
  48. fd.write("#include \"nsCOMPtr.h\"\n")
  49. fd.write("#include \"nsCycleCollectionParticipant.h\"\n")
  50. fd.write("#include \"nsString.h\"\n")
  51. for e in conf.simple_events:
  52. fd.write("#include \"nsIAccessible%s.h\"\n" % e)
  53. for e in conf.simple_events:
  54. idl, idl_path = loadEventIDL(p, incdirs, e)
  55. idl_paths.add(idl_path)
  56. for iface in filter(lambda p: p.kind == "interface", idl.productions):
  57. classname = ("xpcAcc%s" % e)
  58. baseinterfaces = interfaces(iface)
  59. fd.write("\nclass %s final : public %s\n" % (classname, iface.name))
  60. fd.write("{\n")
  61. fd.write("public:\n")
  62. attributes = allAttributes(iface)
  63. args = map(writeAttributeParams, attributes)
  64. fd.write(" %s(%s) :\n" % (classname, ", ".join(args)))
  65. initializers = []
  66. for a in attributes:
  67. initializers.append("m%s(a%s)" % (firstCap(a.name), firstCap(a.name)))
  68. fd.write(" %s\n {}\n\n" % ", ".join(initializers))
  69. fd.write(" NS_DECL_CYCLE_COLLECTING_ISUPPORTS\n")
  70. fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS(%s)\n" % (classname))
  71. for iface in filter(lambda i: i.name != "nsISupports", baseinterfaces):
  72. fd.write(" NS_DECL_%s\n" % iface.name.upper())
  73. fd.write("\nprivate:\n")
  74. fd.write(" ~%s() {}\n\n" % classname)
  75. for a in attributes:
  76. fd.write(" %s\n" % attributeVariableTypeAndName(a))
  77. fd.write("};\n\n")
  78. fd.write("#endif\n")
  79. return idl_paths
  80. def interfaceAttributeTypes(idl):
  81. ifaces = filter(lambda p: p.kind == "interface", idl.productions)
  82. attributes = []
  83. for i in ifaces:
  84. ifaceAttributes = allAttributes(i)
  85. attributes.extend(ifaceAttributes)
  86. ifaceAttrs = filter(lambda a: a.realtype.nativeType("in").endswith("*"), attributes)
  87. return map(lambda a: a.realtype.nativeType("in").strip(" *"), ifaceAttrs)
  88. def print_cpp(idl, fd, conf, eventname):
  89. for p in idl.productions:
  90. if p.kind == 'interface':
  91. write_cpp(eventname, p, fd)
  92. def print_cpp_file(fd, conf, incdirs):
  93. idl_paths = set()
  94. fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n")
  95. fd.write('#include "xpcAccEvents.h"\n')
  96. includes = []
  97. for e in conf.simple_events:
  98. if not e in includes:
  99. includes.append(("nsIAccessible%s" % e))
  100. types = []
  101. for e in conf.simple_events:
  102. idl, idl_path = loadEventIDL(p, incdirs, e)
  103. idl_paths.add(idl_path)
  104. types.extend(interfaceAttributeTypes(idl))
  105. for c in types:
  106. fd.write("#include \"%s.h\"\n" % c)
  107. fd.write("\n")
  108. for e in conf.simple_events:
  109. idl, idl_path = loadEventIDL(p, incdirs, e)
  110. idl_paths.add(idl_path)
  111. print_cpp(idl, fd, conf, e)
  112. return idl_paths
  113. def attributeVariableTypeAndName(a):
  114. if a.realtype.nativeType('in').endswith('*'):
  115. l = ["nsCOMPtr<%s> m%s;" % (a.realtype.nativeType('in').strip('* '),
  116. firstCap(a.name))]
  117. elif a.realtype.nativeType('in').count("nsAString"):
  118. l = ["nsString m%s;" % firstCap(a.name)]
  119. elif a.realtype.nativeType('in').count("nsACString"):
  120. l = ["nsCString m%s;" % firstCap(a.name)]
  121. else:
  122. l = ["%sm%s;" % (a.realtype.nativeType('in'),
  123. firstCap(a.name))]
  124. return ", ".join(l)
  125. def writeAttributeGetter(fd, classname, a):
  126. fd.write("NS_IMETHODIMP\n")
  127. fd.write("%s::Get%s(" % (classname, firstCap(a.name)))
  128. if a.realtype.nativeType('in').endswith('*'):
  129. fd.write("%s** a%s" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name)))
  130. elif a.realtype.nativeType('in').count("nsAString"):
  131. fd.write("nsAString& a%s" % firstCap(a.name))
  132. elif a.realtype.nativeType('in').count("nsACString"):
  133. fd.write("nsACString& a%s" % firstCap(a.name))
  134. else:
  135. fd.write("%s*a%s" % (a.realtype.nativeType('in'), firstCap(a.name)))
  136. fd.write(")\n");
  137. fd.write("{\n");
  138. if a.realtype.nativeType('in').endswith('*'):
  139. fd.write(" NS_IF_ADDREF(*a%s = m%s);\n" % (firstCap(a.name), firstCap(a.name)))
  140. elif a.realtype.nativeType('in').count("nsAString"):
  141. fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
  142. elif a.realtype.nativeType('in').count("nsACString"):
  143. fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
  144. else:
  145. fd.write(" *a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
  146. fd.write(" return NS_OK;\n");
  147. fd.write("}\n\n");
  148. def interfaces(iface):
  149. interfaces = []
  150. while iface.base:
  151. interfaces.append(iface)
  152. iface = iface.idl.getName(iface.base, iface.location)
  153. interfaces.append(iface)
  154. interfaces.reverse()
  155. return interfaces
  156. def allAttributes(iface):
  157. attributes = []
  158. for i in interfaces(iface):
  159. attrs = filter(lambda m: isinstance(m, xpidl.Attribute), i.members)
  160. attributes.extend(attrs)
  161. return attributes
  162. def write_cpp(eventname, iface, fd):
  163. classname = "xpcAcc%s" % eventname
  164. attributes = allAttributes(iface)
  165. ccattributes = filter(lambda m: m.realtype.nativeType('in').endswith('*'), attributes)
  166. fd.write("NS_IMPL_CYCLE_COLLECTION(%s" % classname)
  167. for c in ccattributes:
  168. fd.write(", m%s" % firstCap(c.name))
  169. fd.write(")\n\n");
  170. fd.write("NS_IMPL_CYCLE_COLLECTING_ADDREF(%s)\n" % classname)
  171. fd.write("NS_IMPL_CYCLE_COLLECTING_RELEASE(%s)\n\n" % classname)
  172. fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(%s)\n" % classname)
  173. for baseiface in interfaces(iface):
  174. fd.write(" NS_INTERFACE_MAP_ENTRY(%s)\n" % baseiface.name)
  175. fd.write("NS_INTERFACE_MAP_END\n\n")
  176. for a in attributes:
  177. writeAttributeGetter(fd, classname, a)
  178. def get_conf(conf_file):
  179. conf = Configuration(conf_file)
  180. inc_dir = [
  181. mozpath.join(buildconfig.topsrcdir, 'accessible', 'interfaces'),
  182. mozpath.join(buildconfig.topsrcdir, 'xpcom', 'base'),
  183. ]
  184. return conf, inc_dir
  185. def gen_files(fd, conf_file, xpidllex, xpidlyacc):
  186. deps = set()
  187. conf, inc_dir = get_conf(conf_file)
  188. deps.update(print_header_file(fd, conf, inc_dir))
  189. with open('xpcAccEvents.cpp', 'w') as cpp_fd:
  190. deps.update(print_cpp_file(cpp_fd, conf, inc_dir))
  191. return deps