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