/documentor/libraries/Sphinx-1.1.3-py3.2/sphinx/domains/c.py
https://github.com/tictactatic/Superdesk · Python · 245 lines · 177 code · 29 blank · 39 comment · 41 complexity · fdfc418271035dcffed66300b64bb6ce MD5 · raw file
- # -*- coding: utf-8 -*-
- """
- sphinx.domains.c
- ~~~~~~~~~~~~~~~~
- The C language domain.
- :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
- :license: BSD, see LICENSE for details.
- """
- import re
- import string
- from docutils import nodes
- from sphinx import addnodes
- from sphinx.roles import XRefRole
- from sphinx.locale import l_, _
- from sphinx.domains import Domain, ObjType
- from sphinx.directives import ObjectDescription
- from sphinx.util.nodes import make_refnode
- from sphinx.util.docfields import Field, TypedField
- # RE to split at word boundaries
- wsplit_re = re.compile(r'(\W+)')
- # REs for C signatures
- c_sig_re = re.compile(
- r'''^([^(]*?) # return type
- ([\w:.]+) \s* # thing name (colon allowed for C++)
- (?: \((.*)\) )? # optionally arguments
- (\s+const)? $ # const specifier
- ''', re.VERBOSE)
- c_funcptr_sig_re = re.compile(
- r'''^([^(]+?) # return type
- (\( [^()]+ \)) \s* # name in parentheses
- \( (.*) \) # arguments
- (\s+const)? $ # const specifier
- ''', re.VERBOSE)
- c_funcptr_name_re = re.compile(r'^\(\s*\*\s*(.*?)\s*\)$')
- class CObject(ObjectDescription):
- """
- Description of a C language object.
- """
- doc_field_types = [
- TypedField('parameter', label=l_('Parameters'),
- names=('param', 'parameter', 'arg', 'argument'),
- typerolename='type', typenames=('type',)),
- Field('returnvalue', label=l_('Returns'), has_arg=False,
- names=('returns', 'return')),
- Field('returntype', label=l_('Return type'), has_arg=False,
- names=('rtype',)),
- ]
- # These C types aren't described anywhere, so don't try to create
- # a cross-reference to them
- stopwords = set(('const', 'void', 'char', 'int', 'long', 'FILE', 'struct'))
- def _parse_type(self, node, ctype):
- # add cross-ref nodes for all words
- for part in [_f for _f in wsplit_re.split(ctype) if _f]:
- tnode = nodes.Text(part, part)
- if part[0] in string.ascii_letters+'_' and \
- part not in self.stopwords:
- pnode = addnodes.pending_xref(
- '', refdomain='c', reftype='type', reftarget=part,
- modname=None, classname=None)
- pnode += tnode
- node += pnode
- else:
- node += tnode
- def handle_signature(self, sig, signode):
- """Transform a C signature into RST nodes."""
- # first try the function pointer signature regex, it's more specific
- m = c_funcptr_sig_re.match(sig)
- if m is None:
- m = c_sig_re.match(sig)
- if m is None:
- raise ValueError('no match')
- rettype, name, arglist, const = m.groups()
- signode += addnodes.desc_type('', '')
- self._parse_type(signode[-1], rettype)
- try:
- classname, funcname = name.split('::', 1)
- classname += '::'
- signode += addnodes.desc_addname(classname, classname)
- signode += addnodes.desc_name(funcname, funcname)
- # name (the full name) is still both parts
- except ValueError:
- signode += addnodes.desc_name(name, name)
- # clean up parentheses from canonical name
- m = c_funcptr_name_re.match(name)
- if m:
- name = m.group(1)
- typename = self.env.temp_data.get('c:type')
- if self.name == 'c:member' and typename:
- fullname = typename + '.' + name
- else:
- fullname = name
- if not arglist:
- if self.objtype == 'function':
- # for functions, add an empty parameter list
- signode += addnodes.desc_parameterlist()
- if const:
- signode += addnodes.desc_addname(const, const)
- return fullname
- paramlist = addnodes.desc_parameterlist()
- arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
- # this messes up function pointer types, but not too badly ;)
- args = arglist.split(',')
- for arg in args:
- arg = arg.strip()
- param = addnodes.desc_parameter('', '', noemph=True)
- try:
- ctype, argname = arg.rsplit(' ', 1)
- except ValueError:
- # no argument name given, only the type
- self._parse_type(param, arg)
- else:
- self._parse_type(param, ctype)
- # separate by non-breaking space in the output
- param += nodes.emphasis(' '+argname, '\xa0'+argname)
- paramlist += param
- signode += paramlist
- if const:
- signode += addnodes.desc_addname(const, const)
- return fullname
- def get_index_text(self, name):
- if self.objtype == 'function':
- return _('%s (C function)') % name
- elif self.objtype == 'member':
- return _('%s (C member)') % name
- elif self.objtype == 'macro':
- return _('%s (C macro)') % name
- elif self.objtype == 'type':
- return _('%s (C type)') % name
- elif self.objtype == 'var':
- return _('%s (C variable)') % name
- else:
- return ''
- def add_target_and_index(self, name, sig, signode):
- # note target
- if name not in self.state.document.ids:
- signode['names'].append(name)
- signode['ids'].append(name)
- signode['first'] = (not self.names)
- self.state.document.note_explicit_target(signode)
- inv = self.env.domaindata['c']['objects']
- if name in inv:
- self.state_machine.reporter.warning(
- 'duplicate C object description of %s, ' % name +
- 'other instance in ' + self.env.doc2path(inv[name][0]),
- line=self.lineno)
- inv[name] = (self.env.docname, self.objtype)
- indextext = self.get_index_text(name)
- if indextext:
- self.indexnode['entries'].append(('single', indextext, name, ''))
- def before_content(self):
- self.typename_set = False
- if self.name == 'c:type':
- if self.names:
- self.env.temp_data['c:type'] = self.names[0]
- self.typename_set = True
- def after_content(self):
- if self.typename_set:
- self.env.temp_data['c:type'] = None
- class CXRefRole(XRefRole):
- def process_link(self, env, refnode, has_explicit_title, title, target):
- if not has_explicit_title:
- target = target.lstrip('~') # only has a meaning for the title
- # if the first character is a tilde, don't display the module/class
- # parts of the contents
- if title[0:1] == '~':
- title = title[1:]
- dot = title.rfind('.')
- if dot != -1:
- title = title[dot+1:]
- return title, target
- class CDomain(Domain):
- """C language domain."""
- name = 'c'
- label = 'C'
- object_types = {
- 'function': ObjType(l_('function'), 'func'),
- 'member': ObjType(l_('member'), 'member'),
- 'macro': ObjType(l_('macro'), 'macro'),
- 'type': ObjType(l_('type'), 'type'),
- 'var': ObjType(l_('variable'), 'data'),
- }
- directives = {
- 'function': CObject,
- 'member': CObject,
- 'macro': CObject,
- 'type': CObject,
- 'var': CObject,
- }
- roles = {
- 'func' : CXRefRole(fix_parens=True),
- 'member': CXRefRole(),
- 'macro': CXRefRole(),
- 'data': CXRefRole(),
- 'type': CXRefRole(),
- }
- initial_data = {
- 'objects': {}, # fullname -> docname, objtype
- }
- def clear_doc(self, docname):
- for fullname, (fn, _) in list(self.data['objects'].items()):
- if fn == docname:
- del self.data['objects'][fullname]
- def resolve_xref(self, env, fromdocname, builder,
- typ, target, node, contnode):
- # strip pointer asterisk
- target = target.rstrip(' *')
- if target not in self.data['objects']:
- return None
- obj = self.data['objects'][target]
- return make_refnode(builder, fromdocname, obj[0], target,
- contnode, target)
- def get_objects(self):
- for refname, (docname, type) in self.data['objects'].items():
- yield (refname, refname, type, docname, refname, 1)