PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/documentor/libraries/Sphinx-1.1.3-py3.2/sphinx/domains/c.py

https://github.com/tictactatic/Superdesk
Python | 245 lines | 213 code | 13 blank | 19 comment | 8 complexity | fdfc418271035dcffed66300b64bb6ce MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-3.0, GPL-2.0
  1. # -*- coding: utf-8 -*-
  2. """
  3. sphinx.domains.c
  4. ~~~~~~~~~~~~~~~~
  5. The C language domain.
  6. :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
  7. :license: BSD, see LICENSE for details.
  8. """
  9. import re
  10. import string
  11. from docutils import nodes
  12. from sphinx import addnodes
  13. from sphinx.roles import XRefRole
  14. from sphinx.locale import l_, _
  15. from sphinx.domains import Domain, ObjType
  16. from sphinx.directives import ObjectDescription
  17. from sphinx.util.nodes import make_refnode
  18. from sphinx.util.docfields import Field, TypedField
  19. # RE to split at word boundaries
  20. wsplit_re = re.compile(r'(\W+)')
  21. # REs for C signatures
  22. c_sig_re = re.compile(
  23. r'''^([^(]*?) # return type
  24. ([\w:.]+) \s* # thing name (colon allowed for C++)
  25. (?: \((.*)\) )? # optionally arguments
  26. (\s+const)? $ # const specifier
  27. ''', re.VERBOSE)
  28. c_funcptr_sig_re = re.compile(
  29. r'''^([^(]+?) # return type
  30. (\( [^()]+ \)) \s* # name in parentheses
  31. \( (.*) \) # arguments
  32. (\s+const)? $ # const specifier
  33. ''', re.VERBOSE)
  34. c_funcptr_name_re = re.compile(r'^\(\s*\*\s*(.*?)\s*\)$')
  35. class CObject(ObjectDescription):
  36. """
  37. Description of a C language object.
  38. """
  39. doc_field_types = [
  40. TypedField('parameter', label=l_('Parameters'),
  41. names=('param', 'parameter', 'arg', 'argument'),
  42. typerolename='type', typenames=('type',)),
  43. Field('returnvalue', label=l_('Returns'), has_arg=False,
  44. names=('returns', 'return')),
  45. Field('returntype', label=l_('Return type'), has_arg=False,
  46. names=('rtype',)),
  47. ]
  48. # These C types aren't described anywhere, so don't try to create
  49. # a cross-reference to them
  50. stopwords = set(('const', 'void', 'char', 'int', 'long', 'FILE', 'struct'))
  51. def _parse_type(self, node, ctype):
  52. # add cross-ref nodes for all words
  53. for part in [_f for _f in wsplit_re.split(ctype) if _f]:
  54. tnode = nodes.Text(part, part)
  55. if part[0] in string.ascii_letters+'_' and \
  56. part not in self.stopwords:
  57. pnode = addnodes.pending_xref(
  58. '', refdomain='c', reftype='type', reftarget=part,
  59. modname=None, classname=None)
  60. pnode += tnode
  61. node += pnode
  62. else:
  63. node += tnode
  64. def handle_signature(self, sig, signode):
  65. """Transform a C signature into RST nodes."""
  66. # first try the function pointer signature regex, it's more specific
  67. m = c_funcptr_sig_re.match(sig)
  68. if m is None:
  69. m = c_sig_re.match(sig)
  70. if m is None:
  71. raise ValueError('no match')
  72. rettype, name, arglist, const = m.groups()
  73. signode += addnodes.desc_type('', '')
  74. self._parse_type(signode[-1], rettype)
  75. try:
  76. classname, funcname = name.split('::', 1)
  77. classname += '::'
  78. signode += addnodes.desc_addname(classname, classname)
  79. signode += addnodes.desc_name(funcname, funcname)
  80. # name (the full name) is still both parts
  81. except ValueError:
  82. signode += addnodes.desc_name(name, name)
  83. # clean up parentheses from canonical name
  84. m = c_funcptr_name_re.match(name)
  85. if m:
  86. name = m.group(1)
  87. typename = self.env.temp_data.get('c:type')
  88. if self.name == 'c:member' and typename:
  89. fullname = typename + '.' + name
  90. else:
  91. fullname = name
  92. if not arglist:
  93. if self.objtype == 'function':
  94. # for functions, add an empty parameter list
  95. signode += addnodes.desc_parameterlist()
  96. if const:
  97. signode += addnodes.desc_addname(const, const)
  98. return fullname
  99. paramlist = addnodes.desc_parameterlist()
  100. arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
  101. # this messes up function pointer types, but not too badly ;)
  102. args = arglist.split(',')
  103. for arg in args:
  104. arg = arg.strip()
  105. param = addnodes.desc_parameter('', '', noemph=True)
  106. try:
  107. ctype, argname = arg.rsplit(' ', 1)
  108. except ValueError:
  109. # no argument name given, only the type
  110. self._parse_type(param, arg)
  111. else:
  112. self._parse_type(param, ctype)
  113. # separate by non-breaking space in the output
  114. param += nodes.emphasis(' '+argname, '\xa0'+argname)
  115. paramlist += param
  116. signode += paramlist
  117. if const:
  118. signode += addnodes.desc_addname(const, const)
  119. return fullname
  120. def get_index_text(self, name):
  121. if self.objtype == 'function':
  122. return _('%s (C function)') % name
  123. elif self.objtype == 'member':
  124. return _('%s (C member)') % name
  125. elif self.objtype == 'macro':
  126. return _('%s (C macro)') % name
  127. elif self.objtype == 'type':
  128. return _('%s (C type)') % name
  129. elif self.objtype == 'var':
  130. return _('%s (C variable)') % name
  131. else:
  132. return ''
  133. def add_target_and_index(self, name, sig, signode):
  134. # note target
  135. if name not in self.state.document.ids:
  136. signode['names'].append(name)
  137. signode['ids'].append(name)
  138. signode['first'] = (not self.names)
  139. self.state.document.note_explicit_target(signode)
  140. inv = self.env.domaindata['c']['objects']
  141. if name in inv:
  142. self.state_machine.reporter.warning(
  143. 'duplicate C object description of %s, ' % name +
  144. 'other instance in ' + self.env.doc2path(inv[name][0]),
  145. line=self.lineno)
  146. inv[name] = (self.env.docname, self.objtype)
  147. indextext = self.get_index_text(name)
  148. if indextext:
  149. self.indexnode['entries'].append(('single', indextext, name, ''))
  150. def before_content(self):
  151. self.typename_set = False
  152. if self.name == 'c:type':
  153. if self.names:
  154. self.env.temp_data['c:type'] = self.names[0]
  155. self.typename_set = True
  156. def after_content(self):
  157. if self.typename_set:
  158. self.env.temp_data['c:type'] = None
  159. class CXRefRole(XRefRole):
  160. def process_link(self, env, refnode, has_explicit_title, title, target):
  161. if not has_explicit_title:
  162. target = target.lstrip('~') # only has a meaning for the title
  163. # if the first character is a tilde, don't display the module/class
  164. # parts of the contents
  165. if title[0:1] == '~':
  166. title = title[1:]
  167. dot = title.rfind('.')
  168. if dot != -1:
  169. title = title[dot+1:]
  170. return title, target
  171. class CDomain(Domain):
  172. """C language domain."""
  173. name = 'c'
  174. label = 'C'
  175. object_types = {
  176. 'function': ObjType(l_('function'), 'func'),
  177. 'member': ObjType(l_('member'), 'member'),
  178. 'macro': ObjType(l_('macro'), 'macro'),
  179. 'type': ObjType(l_('type'), 'type'),
  180. 'var': ObjType(l_('variable'), 'data'),
  181. }
  182. directives = {
  183. 'function': CObject,
  184. 'member': CObject,
  185. 'macro': CObject,
  186. 'type': CObject,
  187. 'var': CObject,
  188. }
  189. roles = {
  190. 'func' : CXRefRole(fix_parens=True),
  191. 'member': CXRefRole(),
  192. 'macro': CXRefRole(),
  193. 'data': CXRefRole(),
  194. 'type': CXRefRole(),
  195. }
  196. initial_data = {
  197. 'objects': {}, # fullname -> docname, objtype
  198. }
  199. def clear_doc(self, docname):
  200. for fullname, (fn, _) in list(self.data['objects'].items()):
  201. if fn == docname:
  202. del self.data['objects'][fullname]
  203. def resolve_xref(self, env, fromdocname, builder,
  204. typ, target, node, contnode):
  205. # strip pointer asterisk
  206. target = target.rstrip(' *')
  207. if target not in self.data['objects']:
  208. return None
  209. obj = self.data['objects'][target]
  210. return make_refnode(builder, fromdocname, obj[0], target,
  211. contnode, target)
  212. def get_objects(self):
  213. for refname, (docname, type) in self.data['objects'].items():
  214. yield (refname, refname, type, docname, refname, 1)