xref: /openbmc/u-boot/Documentation/sphinx/cdomain.py (revision 78a88f7930becb78afef09c1237a8e4edc1b01e1)
1*78a88f79SMario Six# -*- coding: utf-8; mode: python -*-
2*78a88f79SMario Six# pylint: disable=W0141,C0113,C0103,C0325
3*78a88f79SMario Sixu"""
4*78a88f79SMario Six    cdomain
5*78a88f79SMario Six    ~~~~~~~
6*78a88f79SMario Six
7*78a88f79SMario Six    Replacement for the sphinx c-domain.
8*78a88f79SMario Six
9*78a88f79SMario Six    :copyright:  Copyright (C) 2016  Markus Heiser
10*78a88f79SMario Six    :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
11*78a88f79SMario Six
12*78a88f79SMario Six    List of customizations:
13*78a88f79SMario Six
14*78a88f79SMario Six    * Moved the *duplicate C object description* warnings for function
15*78a88f79SMario Six      declarations in the nitpicky mode. See Sphinx documentation for
16*78a88f79SMario Six      the config values for ``nitpick`` and ``nitpick_ignore``.
17*78a88f79SMario Six
18*78a88f79SMario Six    * Add option 'name' to the "c:function:" directive.  With option 'name' the
19*78a88f79SMario Six      ref-name of a function can be modified. E.g.::
20*78a88f79SMario Six
21*78a88f79SMario Six          .. c:function:: int ioctl( int fd, int request )
22*78a88f79SMario Six             :name: VIDIOC_LOG_STATUS
23*78a88f79SMario Six
24*78a88f79SMario Six      The func-name (e.g. ioctl) remains in the output but the ref-name changed
25*78a88f79SMario Six      from 'ioctl' to 'VIDIOC_LOG_STATUS'. The function is referenced by::
26*78a88f79SMario Six
27*78a88f79SMario Six          * :c:func:`VIDIOC_LOG_STATUS` or
28*78a88f79SMario Six          * :any:`VIDIOC_LOG_STATUS` (``:any:`` needs sphinx 1.3)
29*78a88f79SMario Six
30*78a88f79SMario Six     * Handle signatures of function-like macros well. Don't try to deduce
31*78a88f79SMario Six       arguments types of function-like macros.
32*78a88f79SMario Six
33*78a88f79SMario Six"""
34*78a88f79SMario Six
35*78a88f79SMario Sixfrom docutils import nodes
36*78a88f79SMario Sixfrom docutils.parsers.rst import directives
37*78a88f79SMario Six
38*78a88f79SMario Siximport sphinx
39*78a88f79SMario Sixfrom sphinx import addnodes
40*78a88f79SMario Sixfrom sphinx.domains.c import c_funcptr_sig_re, c_sig_re
41*78a88f79SMario Sixfrom sphinx.domains.c import CObject as Base_CObject
42*78a88f79SMario Sixfrom sphinx.domains.c import CDomain as Base_CDomain
43*78a88f79SMario Six
44*78a88f79SMario Six__version__  = '1.0'
45*78a88f79SMario Six
46*78a88f79SMario Six# Get Sphinx version
47*78a88f79SMario Sixmajor, minor, patch = sphinx.version_info[:3]
48*78a88f79SMario Six
49*78a88f79SMario Sixdef setup(app):
50*78a88f79SMario Six
51*78a88f79SMario Six    app.override_domain(CDomain)
52*78a88f79SMario Six
53*78a88f79SMario Six    return dict(
54*78a88f79SMario Six        version = __version__,
55*78a88f79SMario Six        parallel_read_safe = True,
56*78a88f79SMario Six        parallel_write_safe = True
57*78a88f79SMario Six    )
58*78a88f79SMario Six
59*78a88f79SMario Sixclass CObject(Base_CObject):
60*78a88f79SMario Six
61*78a88f79SMario Six    """
62*78a88f79SMario Six    Description of a C language object.
63*78a88f79SMario Six    """
64*78a88f79SMario Six    option_spec = {
65*78a88f79SMario Six        "name" : directives.unchanged
66*78a88f79SMario Six    }
67*78a88f79SMario Six
68*78a88f79SMario Six    def handle_func_like_macro(self, sig, signode):
69*78a88f79SMario Six        u"""Handles signatures of function-like macros.
70*78a88f79SMario Six
71*78a88f79SMario Six        If the objtype is 'function' and the the signature ``sig`` is a
72*78a88f79SMario Six        function-like macro, the name of the macro is returned. Otherwise
73*78a88f79SMario Six        ``False`` is returned.  """
74*78a88f79SMario Six
75*78a88f79SMario Six        if not self.objtype == 'function':
76*78a88f79SMario Six            return False
77*78a88f79SMario Six
78*78a88f79SMario Six        m = c_funcptr_sig_re.match(sig)
79*78a88f79SMario Six        if m is None:
80*78a88f79SMario Six            m = c_sig_re.match(sig)
81*78a88f79SMario Six            if m is None:
82*78a88f79SMario Six                raise ValueError('no match')
83*78a88f79SMario Six
84*78a88f79SMario Six        rettype, fullname, arglist, _const = m.groups()
85*78a88f79SMario Six        arglist = arglist.strip()
86*78a88f79SMario Six        if rettype or not arglist:
87*78a88f79SMario Six            return False
88*78a88f79SMario Six
89*78a88f79SMario Six        arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
90*78a88f79SMario Six        arglist = [a.strip() for a in arglist.split(",")]
91*78a88f79SMario Six
92*78a88f79SMario Six        # has the first argument a type?
93*78a88f79SMario Six        if len(arglist[0].split(" ")) > 1:
94*78a88f79SMario Six            return False
95*78a88f79SMario Six
96*78a88f79SMario Six        # This is a function-like macro, it's arguments are typeless!
97*78a88f79SMario Six        signode  += addnodes.desc_name(fullname, fullname)
98*78a88f79SMario Six        paramlist = addnodes.desc_parameterlist()
99*78a88f79SMario Six        signode  += paramlist
100*78a88f79SMario Six
101*78a88f79SMario Six        for argname in arglist:
102*78a88f79SMario Six            param = addnodes.desc_parameter('', '', noemph=True)
103*78a88f79SMario Six            # separate by non-breaking space in the output
104*78a88f79SMario Six            param += nodes.emphasis(argname, argname)
105*78a88f79SMario Six            paramlist += param
106*78a88f79SMario Six
107*78a88f79SMario Six        return fullname
108*78a88f79SMario Six
109*78a88f79SMario Six    def handle_signature(self, sig, signode):
110*78a88f79SMario Six        """Transform a C signature into RST nodes."""
111*78a88f79SMario Six
112*78a88f79SMario Six        fullname = self.handle_func_like_macro(sig, signode)
113*78a88f79SMario Six        if not fullname:
114*78a88f79SMario Six            fullname = super(CObject, self).handle_signature(sig, signode)
115*78a88f79SMario Six
116*78a88f79SMario Six        if "name" in self.options:
117*78a88f79SMario Six            if self.objtype == 'function':
118*78a88f79SMario Six                fullname = self.options["name"]
119*78a88f79SMario Six            else:
120*78a88f79SMario Six                # FIXME: handle :name: value of other declaration types?
121*78a88f79SMario Six                pass
122*78a88f79SMario Six        return fullname
123*78a88f79SMario Six
124*78a88f79SMario Six    def add_target_and_index(self, name, sig, signode):
125*78a88f79SMario Six        # for C API items we add a prefix since names are usually not qualified
126*78a88f79SMario Six        # by a module name and so easily clash with e.g. section titles
127*78a88f79SMario Six        targetname = 'c.' + name
128*78a88f79SMario Six        if targetname not in self.state.document.ids:
129*78a88f79SMario Six            signode['names'].append(targetname)
130*78a88f79SMario Six            signode['ids'].append(targetname)
131*78a88f79SMario Six            signode['first'] = (not self.names)
132*78a88f79SMario Six            self.state.document.note_explicit_target(signode)
133*78a88f79SMario Six            inv = self.env.domaindata['c']['objects']
134*78a88f79SMario Six            if (name in inv and self.env.config.nitpicky):
135*78a88f79SMario Six                if self.objtype == 'function':
136*78a88f79SMario Six                    if ('c:func', name) not in self.env.config.nitpick_ignore:
137*78a88f79SMario Six                        self.state_machine.reporter.warning(
138*78a88f79SMario Six                            'duplicate C object description of %s, ' % name +
139*78a88f79SMario Six                            'other instance in ' + self.env.doc2path(inv[name][0]),
140*78a88f79SMario Six                            line=self.lineno)
141*78a88f79SMario Six            inv[name] = (self.env.docname, self.objtype)
142*78a88f79SMario Six
143*78a88f79SMario Six        indextext = self.get_index_text(name)
144*78a88f79SMario Six        if indextext:
145*78a88f79SMario Six            if major == 1 and minor < 4:
146*78a88f79SMario Six                # indexnode's tuple changed in 1.4
147*78a88f79SMario Six                # https://github.com/sphinx-doc/sphinx/commit/e6a5a3a92e938fcd75866b4227db9e0524d58f7c
148*78a88f79SMario Six                self.indexnode['entries'].append(
149*78a88f79SMario Six                    ('single', indextext, targetname, ''))
150*78a88f79SMario Six            else:
151*78a88f79SMario Six                self.indexnode['entries'].append(
152*78a88f79SMario Six                    ('single', indextext, targetname, '', None))
153*78a88f79SMario Six
154*78a88f79SMario Sixclass CDomain(Base_CDomain):
155*78a88f79SMario Six
156*78a88f79SMario Six    """C language domain."""
157*78a88f79SMario Six    name = 'c'
158*78a88f79SMario Six    label = 'C'
159*78a88f79SMario Six    directives = {
160*78a88f79SMario Six        'function': CObject,
161*78a88f79SMario Six        'member':   CObject,
162*78a88f79SMario Six        'macro':    CObject,
163*78a88f79SMario Six        'type':     CObject,
164*78a88f79SMario Six        'var':      CObject,
165*78a88f79SMario Six    }
166