diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-06-14 16:42:10 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-06-14 16:42:10 -0400 |
commit | db5dfef7121752ec9053160e0a7804815d4608c3 (patch) | |
tree | 6cdd00f9fcbaceadcf7e173ff671abbcf4f95711 | |
parent | 0d841ac0ec213f70ab59d65129e80f229846fadf (diff) | |
parent | 8569de68e79e94cce6709831edd94accb6942ade (diff) |
Merge tag 'sphinx-4.8' of git://git.lwn.net/linux into topic/drm-misc
Stable tag for sphinx work
Pull current state of the sphinx rework from Jonathan into drm-misc so
that we can start converting gpu.tmpl.
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
-rw-r--r-- | Documentation/.gitignore | 1 | ||||
-rw-r--r-- | Documentation/DocBook/Makefile | 7 | ||||
-rw-r--r-- | Documentation/Makefile.sphinx | 63 | ||||
-rw-r--r-- | Documentation/conf.py | 414 | ||||
-rw-r--r-- | Documentation/dmaengine/provider.txt | 2 | ||||
-rw-r--r-- | Documentation/index.rst | 23 | ||||
-rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
-rw-r--r-- | Documentation/mic/mpssd/mpssd.c | 4 | ||||
-rw-r--r-- | Documentation/security/self-protection.txt | 28 | ||||
-rw-r--r-- | Documentation/sphinx/convert_template.sed | 18 | ||||
-rw-r--r-- | Documentation/sphinx/kernel-doc.py | 127 | ||||
-rw-r--r-- | Documentation/sphinx/post_convert.sed | 23 | ||||
-rwxr-xr-x | Documentation/sphinx/tmplcvt | 19 | ||||
-rw-r--r-- | Documentation/sync_file.txt | 6 | ||||
-rw-r--r-- | Documentation/zh_CN/CodingStyle | 581 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rwxr-xr-x | scripts/kernel-doc | 393 |
17 files changed, 1326 insertions, 393 deletions
diff --git a/Documentation/.gitignore b/Documentation/.gitignore new file mode 100644 index 000000000000..53752db253e3 --- /dev/null +++ b/Documentation/.gitignore | |||
@@ -0,0 +1 @@ | |||
output | |||
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index d70f9b68174e..e0c7e1e0590b 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile | |||
@@ -33,10 +33,6 @@ PDF_METHOD = $(prefer-db2x) | |||
33 | PS_METHOD = $(prefer-db2x) | 33 | PS_METHOD = $(prefer-db2x) |
34 | 34 | ||
35 | 35 | ||
36 | ### | ||
37 | # The targets that may be used. | ||
38 | PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs | ||
39 | |||
40 | targets += $(DOCBOOKS) | 36 | targets += $(DOCBOOKS) |
41 | BOOKS := $(addprefix $(obj)/,$(DOCBOOKS)) | 37 | BOOKS := $(addprefix $(obj)/,$(DOCBOOKS)) |
42 | xmldocs: $(BOOKS) | 38 | xmldocs: $(BOOKS) |
@@ -63,6 +59,9 @@ installmandocs: mandocs | |||
63 | sort -k 2 -k 1 | uniq -f 1 | sed -e 's: :/:' | \ | 59 | sort -k 2 -k 1 | uniq -f 1 | sed -e 's: :/:' | \ |
64 | xargs install -m 644 -t /usr/local/man/man9/ | 60 | xargs install -m 644 -t /usr/local/man/man9/ |
65 | 61 | ||
62 | # no-op for the DocBook toolchain | ||
63 | epubdocs: | ||
64 | |||
66 | ### | 65 | ### |
67 | #External programs used | 66 | #External programs used |
68 | KERNELDOCXMLREF = $(srctree)/scripts/kernel-doc-xml-ref | 67 | KERNELDOCXMLREF = $(srctree)/scripts/kernel-doc-xml-ref |
diff --git a/Documentation/Makefile.sphinx b/Documentation/Makefile.sphinx new file mode 100644 index 000000000000..addf32309bc3 --- /dev/null +++ b/Documentation/Makefile.sphinx | |||
@@ -0,0 +1,63 @@ | |||
1 | # -*- makefile -*- | ||
2 | # Makefile for Sphinx documentation | ||
3 | # | ||
4 | |||
5 | # You can set these variables from the command line. | ||
6 | SPHINXBUILD = sphinx-build | ||
7 | SPHINXOPTS = | ||
8 | PAPER = | ||
9 | BUILDDIR = $(obj)/output | ||
10 | |||
11 | # User-friendly check for sphinx-build | ||
12 | HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi) | ||
13 | |||
14 | ifeq ($(HAVE_SPHINX),0) | ||
15 | |||
16 | .DEFAULT: | ||
17 | $(warning The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed and in PATH, or set the SPHINXBUILD make variable to point to the full path of the '$(SPHINXBUILD)' executable.) | ||
18 | @echo " SKIP Sphinx $@ target." | ||
19 | |||
20 | else # HAVE_SPHINX | ||
21 | |||
22 | # User-friendly check for rst2pdf | ||
23 | HAVE_RST2PDF := $(shell if python -c "import rst2pdf" >/dev/null 2>&1; then echo 1; else echo 0; fi) | ||
24 | |||
25 | # Internal variables. | ||
26 | PAPEROPT_a4 = -D latex_paper_size=a4 | ||
27 | PAPEROPT_letter = -D latex_paper_size=letter | ||
28 | KERNELDOC = $(srctree)/scripts/kernel-doc | ||
29 | KERNELDOC_CONF = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC) | ||
30 | ALLSPHINXOPTS = -D version=$(KERNELVERSION) -D release=$(KERNELRELEASE) -d $(BUILDDIR)/.doctrees $(KERNELDOC_CONF) $(PAPEROPT_$(PAPER)) -c $(srctree)/$(src) $(SPHINXOPTS) $(srctree)/$(src) | ||
31 | # the i18n builder cannot share the environment and doctrees with the others | ||
32 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . | ||
33 | |||
34 | quiet_cmd_sphinx = SPHINX $@ | ||
35 | cmd_sphinx = $(SPHINXBUILD) -b $2 $(ALLSPHINXOPTS) $(BUILDDIR)/$2 | ||
36 | |||
37 | htmldocs: | ||
38 | $(call cmd,sphinx,html) | ||
39 | |||
40 | pdfdocs: | ||
41 | ifeq ($(HAVE_RST2PDF),0) | ||
42 | $(warning The Python 'rst2pdf' module was not found. Make sure you have the module installed to produce PDF output.) | ||
43 | @echo " SKIP Sphinx $@ target." | ||
44 | else # HAVE_RST2PDF | ||
45 | $(call cmd,sphinx,pdf) | ||
46 | endif # HAVE_RST2PDF | ||
47 | |||
48 | epubdocs: | ||
49 | $(call cmd,sphinx,epub) | ||
50 | |||
51 | xmldocs: | ||
52 | $(call cmd,sphinx,xml) | ||
53 | |||
54 | # no-ops for the Sphinx toolchain | ||
55 | sgmldocs: | ||
56 | psdocs: | ||
57 | mandocs: | ||
58 | installmandocs: | ||
59 | |||
60 | cleandocs: | ||
61 | $(Q)rm -rf $(BUILDDIR) | ||
62 | |||
63 | endif # HAVE_SPHINX | ||
diff --git a/Documentation/conf.py b/Documentation/conf.py new file mode 100644 index 000000000000..6cc41a0555a3 --- /dev/null +++ b/Documentation/conf.py | |||
@@ -0,0 +1,414 @@ | |||
1 | # -*- coding: utf-8 -*- | ||
2 | # | ||
3 | # The Linux Kernel documentation build configuration file, created by | ||
4 | # sphinx-quickstart on Fri Feb 12 13:51:46 2016. | ||
5 | # | ||
6 | # This file is execfile()d with the current directory set to its | ||
7 | # containing dir. | ||
8 | # | ||
9 | # Note that not all possible configuration values are present in this | ||
10 | # autogenerated file. | ||
11 | # | ||
12 | # All configuration values have a default; values that are commented out | ||
13 | # serve to show the default. | ||
14 | |||
15 | import sys | ||
16 | import os | ||
17 | |||
18 | # If extensions (or modules to document with autodoc) are in another directory, | ||
19 | # add these directories to sys.path here. If the directory is relative to the | ||
20 | # documentation root, use os.path.abspath to make it absolute, like shown here. | ||
21 | sys.path.insert(0, os.path.abspath('sphinx')) | ||
22 | |||
23 | # -- General configuration ------------------------------------------------ | ||
24 | |||
25 | # If your documentation needs a minimal Sphinx version, state it here. | ||
26 | #needs_sphinx = '1.0' | ||
27 | |||
28 | # Add any Sphinx extension module names here, as strings. They can be | ||
29 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom | ||
30 | # ones. | ||
31 | extensions = ['kernel-doc'] | ||
32 | |||
33 | # Gracefully handle missing rst2pdf. | ||
34 | try: | ||
35 | import rst2pdf | ||
36 | extensions += ['rst2pdf.pdfbuilder'] | ||
37 | except ImportError: | ||
38 | pass | ||
39 | |||
40 | # Add any paths that contain templates here, relative to this directory. | ||
41 | templates_path = ['_templates'] | ||
42 | |||
43 | # The suffix(es) of source filenames. | ||
44 | # You can specify multiple suffix as a list of string: | ||
45 | # source_suffix = ['.rst', '.md'] | ||
46 | source_suffix = '.rst' | ||
47 | |||
48 | # The encoding of source files. | ||
49 | #source_encoding = 'utf-8-sig' | ||
50 | |||
51 | # The master toctree document. | ||
52 | master_doc = 'index' | ||
53 | |||
54 | # General information about the project. | ||
55 | project = 'The Linux Kernel' | ||
56 | copyright = '2016, The kernel development community' | ||
57 | author = 'The kernel development community' | ||
58 | |||
59 | # The version info for the project you're documenting, acts as replacement for | ||
60 | # |version| and |release|, also used in various other places throughout the | ||
61 | # built documents. | ||
62 | # | ||
63 | # In a normal build, version and release are are set to KERNELVERSION and | ||
64 | # KERNELRELEASE, respectively, from the Makefile via Sphinx command line | ||
65 | # arguments. | ||
66 | # | ||
67 | # The following code tries to extract the information by reading the Makefile, | ||
68 | # when Sphinx is run directly (e.g. by Read the Docs). | ||
69 | try: | ||
70 | makefile_version = None | ||
71 | makefile_patchlevel = None | ||
72 | for line in open('../Makefile'): | ||
73 | key, val = [x.strip() for x in line.split('=', 2)] | ||
74 | if key == 'VERSION': | ||
75 | makefile_version = val | ||
76 | elif key == 'PATCHLEVEL': | ||
77 | makefile_patchlevel = val | ||
78 | if makefile_version and makefile_patchlevel: | ||
79 | break | ||
80 | except: | ||
81 | pass | ||
82 | finally: | ||
83 | if makefile_version and makefile_patchlevel: | ||
84 | version = release = makefile_version + '.' + makefile_patchlevel | ||
85 | else: | ||
86 | sys.stderr.write('Warning: Could not extract kernel version\n') | ||
87 | version = release = "unknown version" | ||
88 | |||
89 | # The language for content autogenerated by Sphinx. Refer to documentation | ||
90 | # for a list of supported languages. | ||
91 | # | ||
92 | # This is also used if you do content translation via gettext catalogs. | ||
93 | # Usually you set "language" from the command line for these cases. | ||
94 | language = None | ||
95 | |||
96 | # There are two options for replacing |today|: either, you set today to some | ||
97 | # non-false value, then it is used: | ||
98 | #today = '' | ||
99 | # Else, today_fmt is used as the format for a strftime call. | ||
100 | #today_fmt = '%B %d, %Y' | ||
101 | |||
102 | # List of patterns, relative to source directory, that match files and | ||
103 | # directories to ignore when looking for source files. | ||
104 | exclude_patterns = ['output'] | ||
105 | |||
106 | # The reST default role (used for this markup: `text`) to use for all | ||
107 | # documents. | ||
108 | #default_role = None | ||
109 | |||
110 | # If true, '()' will be appended to :func: etc. cross-reference text. | ||
111 | #add_function_parentheses = True | ||
112 | |||
113 | # If true, the current module name will be prepended to all description | ||
114 | # unit titles (such as .. function::). | ||
115 | #add_module_names = True | ||
116 | |||
117 | # If true, sectionauthor and moduleauthor directives will be shown in the | ||
118 | # output. They are ignored by default. | ||
119 | #show_authors = False | ||
120 | |||
121 | # The name of the Pygments (syntax highlighting) style to use. | ||
122 | pygments_style = 'sphinx' | ||
123 | |||
124 | # A list of ignored prefixes for module index sorting. | ||
125 | #modindex_common_prefix = [] | ||
126 | |||
127 | # If true, keep warnings as "system message" paragraphs in the built documents. | ||
128 | #keep_warnings = False | ||
129 | |||
130 | # If true, `todo` and `todoList` produce output, else they produce nothing. | ||
131 | todo_include_todos = False | ||
132 | |||
133 | primary_domain = 'C' | ||
134 | highlight_language = 'C' | ||
135 | |||
136 | # -- Options for HTML output ---------------------------------------------- | ||
137 | |||
138 | # The theme to use for HTML and HTML Help pages. See the documentation for | ||
139 | # a list of builtin themes. | ||
140 | |||
141 | # The Read the Docs theme is available from | ||
142 | # - https://github.com/snide/sphinx_rtd_theme | ||
143 | # - https://pypi.python.org/pypi/sphinx_rtd_theme | ||
144 | # - python-sphinx-rtd-theme package (on Debian) | ||
145 | try: | ||
146 | import sphinx_rtd_theme | ||
147 | html_theme = 'sphinx_rtd_theme' | ||
148 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] | ||
149 | except ImportError: | ||
150 | sys.stderr.write('Warning: The Sphinx \'sphinx_rtd_theme\' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.\n') | ||
151 | |||
152 | # Theme options are theme-specific and customize the look and feel of a theme | ||
153 | # further. For a list of options available for each theme, see the | ||
154 | # documentation. | ||
155 | #html_theme_options = {} | ||
156 | |||
157 | # Add any paths that contain custom themes here, relative to this directory. | ||
158 | #html_theme_path = [] | ||
159 | |||
160 | # The name for this set of Sphinx documents. If None, it defaults to | ||
161 | # "<project> v<release> documentation". | ||
162 | #html_title = None | ||
163 | |||
164 | # A shorter title for the navigation bar. Default is the same as html_title. | ||
165 | #html_short_title = None | ||
166 | |||
167 | # The name of an image file (relative to this directory) to place at the top | ||
168 | # of the sidebar. | ||
169 | #html_logo = None | ||
170 | |||
171 | # The name of an image file (within the static path) to use as favicon of the | ||
172 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 | ||
173 | # pixels large. | ||
174 | #html_favicon = None | ||
175 | |||
176 | # Add any paths that contain custom static files (such as style sheets) here, | ||
177 | # relative to this directory. They are copied after the builtin static files, | ||
178 | # so a file named "default.css" will overwrite the builtin "default.css". | ||
179 | #html_static_path = ['_static'] | ||
180 | |||
181 | # Add any extra paths that contain custom files (such as robots.txt or | ||
182 | # .htaccess) here, relative to this directory. These files are copied | ||
183 | # directly to the root of the documentation. | ||
184 | #html_extra_path = [] | ||
185 | |||
186 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, | ||
187 | # using the given strftime format. | ||
188 | #html_last_updated_fmt = '%b %d, %Y' | ||
189 | |||
190 | # If true, SmartyPants will be used to convert quotes and dashes to | ||
191 | # typographically correct entities. | ||
192 | #html_use_smartypants = True | ||
193 | |||
194 | # Custom sidebar templates, maps document names to template names. | ||
195 | #html_sidebars = {} | ||
196 | |||
197 | # Additional templates that should be rendered to pages, maps page names to | ||
198 | # template names. | ||
199 | #html_additional_pages = {} | ||
200 | |||
201 | # If false, no module index is generated. | ||
202 | #html_domain_indices = True | ||
203 | |||
204 | # If false, no index is generated. | ||
205 | #html_use_index = True | ||
206 | |||
207 | # If true, the index is split into individual pages for each letter. | ||
208 | #html_split_index = False | ||
209 | |||
210 | # If true, links to the reST sources are added to the pages. | ||
211 | #html_show_sourcelink = True | ||
212 | |||
213 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. | ||
214 | #html_show_sphinx = True | ||
215 | |||
216 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. | ||
217 | #html_show_copyright = True | ||
218 | |||
219 | # If true, an OpenSearch description file will be output, and all pages will | ||
220 | # contain a <link> tag referring to it. The value of this option must be the | ||
221 | # base URL from which the finished HTML is served. | ||
222 | #html_use_opensearch = '' | ||
223 | |||
224 | # This is the file name suffix for HTML files (e.g. ".xhtml"). | ||
225 | #html_file_suffix = None | ||
226 | |||
227 | # Language to be used for generating the HTML full-text search index. | ||
228 | # Sphinx supports the following languages: | ||
229 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' | ||
230 | # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' | ||
231 | #html_search_language = 'en' | ||
232 | |||
233 | # A dictionary with options for the search language support, empty by default. | ||
234 | # Now only 'ja' uses this config value | ||
235 | #html_search_options = {'type': 'default'} | ||
236 | |||
237 | # The name of a javascript file (relative to the configuration directory) that | ||
238 | # implements a search results scorer. If empty, the default will be used. | ||
239 | #html_search_scorer = 'scorer.js' | ||
240 | |||
241 | # Output file base name for HTML help builder. | ||
242 | htmlhelp_basename = 'TheLinuxKerneldoc' | ||
243 | |||
244 | # -- Options for LaTeX output --------------------------------------------- | ||
245 | |||
246 | latex_elements = { | ||
247 | # The paper size ('letterpaper' or 'a4paper'). | ||
248 | #'papersize': 'letterpaper', | ||
249 | |||
250 | # The font size ('10pt', '11pt' or '12pt'). | ||
251 | #'pointsize': '10pt', | ||
252 | |||
253 | # Additional stuff for the LaTeX preamble. | ||
254 | #'preamble': '', | ||
255 | |||
256 | # Latex figure (float) alignment | ||
257 | #'figure_align': 'htbp', | ||
258 | } | ||
259 | |||
260 | # Grouping the document tree into LaTeX files. List of tuples | ||
261 | # (source start file, target name, title, | ||
262 | # author, documentclass [howto, manual, or own class]). | ||
263 | latex_documents = [ | ||
264 | (master_doc, 'TheLinuxKernel.tex', 'The Linux Kernel Documentation', | ||
265 | 'The kernel development community', 'manual'), | ||
266 | ] | ||
267 | |||
268 | # The name of an image file (relative to this directory) to place at the top of | ||
269 | # the title page. | ||
270 | #latex_logo = None | ||
271 | |||
272 | # For "manual" documents, if this is true, then toplevel headings are parts, | ||
273 | # not chapters. | ||
274 | #latex_use_parts = False | ||
275 | |||
276 | # If true, show page references after internal links. | ||
277 | #latex_show_pagerefs = False | ||
278 | |||
279 | # If true, show URL addresses after external links. | ||
280 | #latex_show_urls = False | ||
281 | |||
282 | # Documents to append as an appendix to all manuals. | ||
283 | #latex_appendices = [] | ||
284 | |||
285 | # If false, no module index is generated. | ||
286 | #latex_domain_indices = True | ||
287 | |||
288 | |||
289 | # -- Options for manual page output --------------------------------------- | ||
290 | |||
291 | # One entry per manual page. List of tuples | ||
292 | # (source start file, name, description, authors, manual section). | ||
293 | man_pages = [ | ||
294 | (master_doc, 'thelinuxkernel', 'The Linux Kernel Documentation', | ||
295 | [author], 1) | ||
296 | ] | ||
297 | |||
298 | # If true, show URL addresses after external links. | ||
299 | #man_show_urls = False | ||
300 | |||
301 | |||
302 | # -- Options for Texinfo output ------------------------------------------- | ||
303 | |||
304 | # Grouping the document tree into Texinfo files. List of tuples | ||
305 | # (source start file, target name, title, author, | ||
306 | # dir menu entry, description, category) | ||
307 | texinfo_documents = [ | ||
308 | (master_doc, 'TheLinuxKernel', 'The Linux Kernel Documentation', | ||
309 | author, 'TheLinuxKernel', 'One line description of project.', | ||
310 | 'Miscellaneous'), | ||
311 | ] | ||
312 | |||
313 | # Documents to append as an appendix to all manuals. | ||
314 | #texinfo_appendices = [] | ||
315 | |||
316 | # If false, no module index is generated. | ||
317 | #texinfo_domain_indices = True | ||
318 | |||
319 | # How to display URL addresses: 'footnote', 'no', or 'inline'. | ||
320 | #texinfo_show_urls = 'footnote' | ||
321 | |||
322 | # If true, do not generate a @detailmenu in the "Top" node's menu. | ||
323 | #texinfo_no_detailmenu = False | ||
324 | |||
325 | |||
326 | # -- Options for Epub output ---------------------------------------------- | ||
327 | |||
328 | # Bibliographic Dublin Core info. | ||
329 | epub_title = project | ||
330 | epub_author = author | ||
331 | epub_publisher = author | ||
332 | epub_copyright = copyright | ||
333 | |||
334 | # The basename for the epub file. It defaults to the project name. | ||
335 | #epub_basename = project | ||
336 | |||
337 | # The HTML theme for the epub output. Since the default themes are not | ||
338 | # optimized for small screen space, using the same theme for HTML and epub | ||
339 | # output is usually not wise. This defaults to 'epub', a theme designed to save | ||
340 | # visual space. | ||
341 | #epub_theme = 'epub' | ||
342 | |||
343 | # The language of the text. It defaults to the language option | ||
344 | # or 'en' if the language is not set. | ||
345 | #epub_language = '' | ||
346 | |||
347 | # The scheme of the identifier. Typical schemes are ISBN or URL. | ||
348 | #epub_scheme = '' | ||
349 | |||
350 | # The unique identifier of the text. This can be a ISBN number | ||
351 | # or the project homepage. | ||
352 | #epub_identifier = '' | ||
353 | |||
354 | # A unique identification for the text. | ||
355 | #epub_uid = '' | ||
356 | |||
357 | # A tuple containing the cover image and cover page html template filenames. | ||
358 | #epub_cover = () | ||
359 | |||
360 | # A sequence of (type, uri, title) tuples for the guide element of content.opf. | ||
361 | #epub_guide = () | ||
362 | |||
363 | # HTML files that should be inserted before the pages created by sphinx. | ||
364 | # The format is a list of tuples containing the path and title. | ||
365 | #epub_pre_files = [] | ||
366 | |||
367 | # HTML files that should be inserted after the pages created by sphinx. | ||
368 | # The format is a list of tuples containing the path and title. | ||
369 | #epub_post_files = [] | ||
370 | |||
371 | # A list of files that should not be packed into the epub file. | ||
372 | epub_exclude_files = ['search.html'] | ||
373 | |||
374 | # The depth of the table of contents in toc.ncx. | ||
375 | #epub_tocdepth = 3 | ||
376 | |||
377 | # Allow duplicate toc entries. | ||
378 | #epub_tocdup = True | ||
379 | |||
380 | # Choose between 'default' and 'includehidden'. | ||
381 | #epub_tocscope = 'default' | ||
382 | |||
383 | # Fix unsupported image types using the Pillow. | ||
384 | #epub_fix_images = False | ||
385 | |||
386 | # Scale large images. | ||
387 | #epub_max_image_width = 0 | ||
388 | |||
389 | # How to display URL addresses: 'footnote', 'no', or 'inline'. | ||
390 | #epub_show_urls = 'inline' | ||
391 | |||
392 | # If false, no index is generated. | ||
393 | #epub_use_index = True | ||
394 | |||
395 | #======= | ||
396 | # rst2pdf | ||
397 | # | ||
398 | # Grouping the document tree into PDF files. List of tuples | ||
399 | # (source start file, target name, title, author, options). | ||
400 | # | ||
401 | # See the Sphinx chapter of http://ralsina.me/static/manual.pdf | ||
402 | # | ||
403 | # FIXME: Do not add the index file here; the result will be too big. Adding | ||
404 | # multiple PDF files here actually tries to get the cross-referencing right | ||
405 | # *between* PDF files. | ||
406 | pdf_documents = [ | ||
407 | ('index', u'Kernel', u'Kernel', u'J. Random Bozo'), | ||
408 | ] | ||
409 | |||
410 | # kernel-doc extension configuration for running Sphinx directly (e.g. by Read | ||
411 | # the Docs). In a normal build, these are supplied from the Makefile via command | ||
412 | # line arguments. | ||
413 | kerneldoc_bin = '../scripts/kernel-doc' | ||
414 | kerneldoc_srctree = '..' | ||
diff --git a/Documentation/dmaengine/provider.txt b/Documentation/dmaengine/provider.txt index 122b7f4876bb..91ce82d5f0c4 100644 --- a/Documentation/dmaengine/provider.txt +++ b/Documentation/dmaengine/provider.txt | |||
@@ -323,7 +323,7 @@ supported. | |||
323 | * device_resume | 323 | * device_resume |
324 | - Resumes a transfer on the channel | 324 | - Resumes a transfer on the channel |
325 | - This command should operate synchronously on the channel, | 325 | - This command should operate synchronously on the channel, |
326 | pausing right away the work of the given channel | 326 | resuming right away the work of the given channel |
327 | 327 | ||
328 | * device_terminate_all | 328 | * device_terminate_all |
329 | - Aborts all the pending and ongoing transfers on the channel | 329 | - Aborts all the pending and ongoing transfers on the channel |
diff --git a/Documentation/index.rst b/Documentation/index.rst new file mode 100644 index 000000000000..71a276f34c7f --- /dev/null +++ b/Documentation/index.rst | |||
@@ -0,0 +1,23 @@ | |||
1 | .. The Linux Kernel documentation master file, created by | ||
2 | sphinx-quickstart on Fri Feb 12 13:51:46 2016. | ||
3 | You can adapt this file completely to your liking, but it should at least | ||
4 | contain the root `toctree` directive. | ||
5 | |||
6 | Welcome to The Linux Kernel's documentation! | ||
7 | ============================================ | ||
8 | |||
9 | Nothing for you to see here *yet*. Please move along. | ||
10 | |||
11 | Contents: | ||
12 | |||
13 | .. toctree:: | ||
14 | :maxdepth: 2 | ||
15 | |||
16 | |||
17 | Indices and tables | ||
18 | ================== | ||
19 | |||
20 | * :ref:`genindex` | ||
21 | * :ref:`modindex` | ||
22 | * :ref:`search` | ||
23 | |||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 82b42c958d1c..a2a662d4da83 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -3992,8 +3992,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
3992 | 3992 | ||
3993 | trace_event=[event-list] | 3993 | trace_event=[event-list] |
3994 | [FTRACE] Set and start specified trace events in order | 3994 | [FTRACE] Set and start specified trace events in order |
3995 | to facilitate early boot debugging. | 3995 | to facilitate early boot debugging. The event-list is a |
3996 | See also Documentation/trace/events.txt | 3996 | comma separated list of trace events to enable. See |
3997 | also Documentation/trace/events.txt | ||
3997 | 3998 | ||
3998 | trace_options=[option-list] | 3999 | trace_options=[option-list] |
3999 | [FTRACE] Enable or disable tracer options at boot. | 4000 | [FTRACE] Enable or disable tracer options at boot. |
diff --git a/Documentation/mic/mpssd/mpssd.c b/Documentation/mic/mpssd/mpssd.c index 30fb842a976d..49db1def1721 100644 --- a/Documentation/mic/mpssd/mpssd.c +++ b/Documentation/mic/mpssd/mpssd.c | |||
@@ -1538,9 +1538,9 @@ set_cmdline(struct mic_info *mic) | |||
1538 | 1538 | ||
1539 | len = snprintf(buffer, PATH_MAX, | 1539 | len = snprintf(buffer, PATH_MAX, |
1540 | "clocksource=tsc highres=off nohz=off "); | 1540 | "clocksource=tsc highres=off nohz=off "); |
1541 | len += snprintf(buffer + len, PATH_MAX, | 1541 | len += snprintf(buffer + len, PATH_MAX - len, |
1542 | "cpufreq_on;corec6_off;pc3_off;pc6_off "); | 1542 | "cpufreq_on;corec6_off;pc3_off;pc6_off "); |
1543 | len += snprintf(buffer + len, PATH_MAX, | 1543 | len += snprintf(buffer + len, PATH_MAX - len, |
1544 | "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0", | 1544 | "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0", |
1545 | mic->id + 1); | 1545 | mic->id + 1); |
1546 | 1546 | ||
diff --git a/Documentation/security/self-protection.txt b/Documentation/security/self-protection.txt index babd6378ec05..3010576c9fca 100644 --- a/Documentation/security/self-protection.txt +++ b/Documentation/security/self-protection.txt | |||
@@ -183,8 +183,9 @@ provide meaningful defenses. | |||
183 | ### Canaries, blinding, and other secrets | 183 | ### Canaries, blinding, and other secrets |
184 | 184 | ||
185 | It should be noted that things like the stack canary discussed earlier | 185 | It should be noted that things like the stack canary discussed earlier |
186 | are technically statistical defenses, since they rely on a (leakable) | 186 | are technically statistical defenses, since they rely on a secret value, |
187 | secret value. | 187 | and such values may become discoverable through an information exposure |
188 | flaw. | ||
188 | 189 | ||
189 | Blinding literal values for things like JITs, where the executable | 190 | Blinding literal values for things like JITs, where the executable |
190 | contents may be partially under the control of userspace, need a similar | 191 | contents may be partially under the control of userspace, need a similar |
@@ -199,8 +200,8 @@ working?) in order to maximize their success. | |||
199 | Since the location of kernel memory is almost always instrumental in | 200 | Since the location of kernel memory is almost always instrumental in |
200 | mounting a successful attack, making the location non-deterministic | 201 | mounting a successful attack, making the location non-deterministic |
201 | raises the difficulty of an exploit. (Note that this in turn makes | 202 | raises the difficulty of an exploit. (Note that this in turn makes |
202 | the value of leaks higher, since they may be used to discover desired | 203 | the value of information exposures higher, since they may be used to |
203 | memory locations.) | 204 | discover desired memory locations.) |
204 | 205 | ||
205 | #### Text and module base | 206 | #### Text and module base |
206 | 207 | ||
@@ -222,14 +223,21 @@ become more difficult to locate. | |||
222 | Much of the kernel's dynamic memory (e.g. kmalloc, vmalloc, etc) ends up | 223 | Much of the kernel's dynamic memory (e.g. kmalloc, vmalloc, etc) ends up |
223 | being relatively deterministic in layout due to the order of early-boot | 224 | being relatively deterministic in layout due to the order of early-boot |
224 | initializations. If the base address of these areas is not the same | 225 | initializations. If the base address of these areas is not the same |
225 | between boots, targeting them is frustrated, requiring a leak specific | 226 | between boots, targeting them is frustrated, requiring an information |
226 | to the region. | 227 | exposure specific to the region. |
228 | |||
229 | #### Structure layout | ||
230 | |||
231 | By performing a per-build randomization of the layout of sensitive | ||
232 | structures, attacks must either be tuned to known kernel builds or expose | ||
233 | enough kernel memory to determine structure layouts before manipulating | ||
234 | them. | ||
227 | 235 | ||
228 | 236 | ||
229 | ## Preventing Leaks | 237 | ## Preventing Information Exposures |
230 | 238 | ||
231 | Since the locations of sensitive structures are the primary target for | 239 | Since the locations of sensitive structures are the primary target for |
232 | attacks, it is important to defend against leaks of both kernel memory | 240 | attacks, it is important to defend against exposure of both kernel memory |
233 | addresses and kernel memory contents (since they may contain kernel | 241 | addresses and kernel memory contents (since they may contain kernel |
234 | addresses or other sensitive things like canary values). | 242 | addresses or other sensitive things like canary values). |
235 | 243 | ||
@@ -250,8 +258,8 @@ sure structure holes are cleared. | |||
250 | When releasing memory, it is best to poison the contents (clear stack on | 258 | When releasing memory, it is best to poison the contents (clear stack on |
251 | syscall return, wipe heap memory on a free), to avoid reuse attacks that | 259 | syscall return, wipe heap memory on a free), to avoid reuse attacks that |
252 | rely on the old contents of memory. This frustrates many uninitialized | 260 | rely on the old contents of memory. This frustrates many uninitialized |
253 | variable attacks, stack info leaks, heap info leaks, and use-after-free | 261 | variable attacks, stack content exposures, heap content exposures, and |
254 | attacks. | 262 | use-after-free attacks. |
255 | 263 | ||
256 | ### Destination tracking | 264 | ### Destination tracking |
257 | 265 | ||
diff --git a/Documentation/sphinx/convert_template.sed b/Documentation/sphinx/convert_template.sed new file mode 100644 index 000000000000..c1503fcca4ec --- /dev/null +++ b/Documentation/sphinx/convert_template.sed | |||
@@ -0,0 +1,18 @@ | |||
1 | # | ||
2 | # Pandoc doesn't grok <function> or <structname>, so convert them | ||
3 | # ahead of time. | ||
4 | # | ||
5 | # Use the following escapes to pass through pandoc: | ||
6 | # $bq = "`" | ||
7 | # $lt = "<" | ||
8 | # $gt = ">" | ||
9 | # | ||
10 | s%<function>\([^<(]\+\)()</function>%:c:func:$bq\1()$bq%g | ||
11 | s%<function>\([^<(]\+\)</function>%:c:func:$bq\1()$bq%g | ||
12 | s%<structname>struct *\([^<]\+\)</structname>%:c:type:$bqstruct \1 $lt\1$gt$bq%g | ||
13 | s%struct <structname>\([^<]\+\)</structname>%:c:type:$bqstruct \1 $lt\1$gt$bq%g | ||
14 | s%<structname>\([^<]\+\)</structname>%:c:type:$bqstruct \1 $lt\1$gt$bq%g | ||
15 | # | ||
16 | # Wrap docproc directives in para and code blocks. | ||
17 | # | ||
18 | s%^\(!.*\)$%<para><code>DOCPROC: \1</code></para>% | ||
diff --git a/Documentation/sphinx/kernel-doc.py b/Documentation/sphinx/kernel-doc.py new file mode 100644 index 000000000000..4adfb0e91ecc --- /dev/null +++ b/Documentation/sphinx/kernel-doc.py | |||
@@ -0,0 +1,127 @@ | |||
1 | # coding=utf-8 | ||
2 | # | ||
3 | # Copyright © 2016 Intel Corporation | ||
4 | # | ||
5 | # Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | # copy of this software and associated documentation files (the "Software"), | ||
7 | # to deal in the Software without restriction, including without limitation | ||
8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | # and/or sell copies of the Software, and to permit persons to whom the | ||
10 | # Software is furnished to do so, subject to the following conditions: | ||
11 | # | ||
12 | # The above copyright notice and this permission notice (including the next | ||
13 | # paragraph) shall be included in all copies or substantial portions of the | ||
14 | # Software. | ||
15 | # | ||
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
22 | # IN THE SOFTWARE. | ||
23 | # | ||
24 | # Authors: | ||
25 | # Jani Nikula <jani.nikula@intel.com> | ||
26 | # | ||
27 | # Please make sure this works on both python2 and python3. | ||
28 | # | ||
29 | |||
30 | import os | ||
31 | import subprocess | ||
32 | import sys | ||
33 | import re | ||
34 | |||
35 | from docutils import nodes, statemachine | ||
36 | from docutils.statemachine import ViewList | ||
37 | from docutils.parsers.rst import directives | ||
38 | from sphinx.util.compat import Directive | ||
39 | |||
40 | class KernelDocDirective(Directive): | ||
41 | """Extract kernel-doc comments from the specified file""" | ||
42 | required_argument = 1 | ||
43 | optional_arguments = 4 | ||
44 | option_spec = { | ||
45 | 'doc': directives.unchanged_required, | ||
46 | 'functions': directives.unchanged_required, | ||
47 | 'export': directives.flag, | ||
48 | 'internal': directives.flag, | ||
49 | } | ||
50 | has_content = False | ||
51 | |||
52 | def run(self): | ||
53 | env = self.state.document.settings.env | ||
54 | cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno'] | ||
55 | |||
56 | filename = env.config.kerneldoc_srctree + '/' + self.arguments[0] | ||
57 | |||
58 | # Tell sphinx of the dependency | ||
59 | env.note_dependency(os.path.abspath(filename)) | ||
60 | |||
61 | tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) | ||
62 | source = filename | ||
63 | |||
64 | # FIXME: make this nicer and more robust against errors | ||
65 | if 'export' in self.options: | ||
66 | cmd += ['-export'] | ||
67 | elif 'internal' in self.options: | ||
68 | cmd += ['-internal'] | ||
69 | elif 'doc' in self.options: | ||
70 | cmd += ['-function', str(self.options.get('doc'))] | ||
71 | elif 'functions' in self.options: | ||
72 | for f in str(self.options.get('functions')).split(' '): | ||
73 | cmd += ['-function', f] | ||
74 | |||
75 | cmd += [filename] | ||
76 | |||
77 | try: | ||
78 | env.app.verbose('calling kernel-doc \'%s\'' % (" ".join(cmd))) | ||
79 | |||
80 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) | ||
81 | out, err = p.communicate() | ||
82 | |||
83 | # python2 needs conversion to unicode. | ||
84 | # python3 with universal_newlines=True returns strings. | ||
85 | if sys.version_info.major < 3: | ||
86 | out, err = unicode(out, 'utf-8'), unicode(err, 'utf-8') | ||
87 | |||
88 | if p.returncode != 0: | ||
89 | sys.stderr.write(err) | ||
90 | |||
91 | env.app.warn('kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode)) | ||
92 | return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] | ||
93 | elif env.config.kerneldoc_verbosity > 0: | ||
94 | sys.stderr.write(err) | ||
95 | |||
96 | lines = statemachine.string2lines(out, tab_width, convert_whitespace=True) | ||
97 | result = ViewList() | ||
98 | |||
99 | lineoffset = 0; | ||
100 | line_regex = re.compile("^#define LINENO ([0-9]+)$") | ||
101 | for line in lines: | ||
102 | match = line_regex.search(line) | ||
103 | if match: | ||
104 | # sphinx counts lines from 0 | ||
105 | lineoffset = int(match.group(1)) - 1 | ||
106 | # we must eat our comments since the upset the markup | ||
107 | else: | ||
108 | result.append(line, source, lineoffset) | ||
109 | lineoffset += 1 | ||
110 | |||
111 | node = nodes.section() | ||
112 | node.document = self.state.document | ||
113 | self.state.nested_parse(result, self.content_offset, node) | ||
114 | |||
115 | return node.children | ||
116 | |||
117 | except Exception as e: | ||
118 | env.app.warn('kernel-doc \'%s\' processing failed with: %s' % | ||
119 | (" ".join(cmd), str(e))) | ||
120 | return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] | ||
121 | |||
122 | def setup(app): | ||
123 | app.add_config_value('kerneldoc_bin', None, 'env') | ||
124 | app.add_config_value('kerneldoc_srctree', None, 'env') | ||
125 | app.add_config_value('kerneldoc_verbosity', 1, 'env') | ||
126 | |||
127 | app.add_directive('kernel-doc', KernelDocDirective) | ||
diff --git a/Documentation/sphinx/post_convert.sed b/Documentation/sphinx/post_convert.sed new file mode 100644 index 000000000000..392770bac53b --- /dev/null +++ b/Documentation/sphinx/post_convert.sed | |||
@@ -0,0 +1,23 @@ | |||
1 | # | ||
2 | # Unescape. | ||
3 | # | ||
4 | s/$bq/`/g | ||
5 | s/$lt/</g | ||
6 | s/$gt/>/g | ||
7 | # | ||
8 | # pandoc thinks that both "_" needs to be escaped. Remove the extra | ||
9 | # backslashes. | ||
10 | # | ||
11 | s/\\_/_/g | ||
12 | # | ||
13 | # Unwrap docproc directives. | ||
14 | # | ||
15 | s/^``DOCPROC: !E\(.*\)``$/.. kernel-doc:: \1\n :export:/ | ||
16 | s/^``DOCPROC: !I\(.*\)``$/.. kernel-doc:: \1\n :internal:/ | ||
17 | s/^``DOCPROC: !F\([^ ]*\) \(.*\)``$/.. kernel-doc:: \1\n :functions: \2/ | ||
18 | s/^``DOCPROC: !P\([^ ]*\) \(.*\)``$/.. kernel-doc:: \1\n :doc: \2/ | ||
19 | s/^``DOCPROC: \(!.*\)``$/.. WARNING: DOCPROC directive not supported: \1/ | ||
20 | # | ||
21 | # Trim trailing whitespace. | ||
22 | # | ||
23 | s/[[:space:]]*$// | ||
diff --git a/Documentation/sphinx/tmplcvt b/Documentation/sphinx/tmplcvt new file mode 100755 index 000000000000..909a73065e0a --- /dev/null +++ b/Documentation/sphinx/tmplcvt | |||
@@ -0,0 +1,19 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Convert a template file into something like RST | ||
4 | # | ||
5 | # fix <function> | ||
6 | # feed to pandoc | ||
7 | # fix \_ | ||
8 | # title line? | ||
9 | # | ||
10 | |||
11 | in=$1 | ||
12 | rst=$2 | ||
13 | tmp=$rst.tmp | ||
14 | |||
15 | cp $in $tmp | ||
16 | sed --in-place -f convert_template.sed $tmp | ||
17 | pandoc -s -S -f docbook -t rst -o $rst $tmp | ||
18 | sed --in-place -f post_convert.sed $rst | ||
19 | rm $tmp | ||
diff --git a/Documentation/sync_file.txt b/Documentation/sync_file.txt index eaf8297dbca2..e8e2ebafe5fa 100644 --- a/Documentation/sync_file.txt +++ b/Documentation/sync_file.txt | |||
@@ -6,8 +6,8 @@ | |||
6 | 6 | ||
7 | This document serves as a guide for device drivers writers on what the | 7 | This document serves as a guide for device drivers writers on what the |
8 | sync_file API is, and how drivers can support it. Sync file is the carrier of | 8 | sync_file API is, and how drivers can support it. Sync file is the carrier of |
9 | the fences(struct fence) that needs to synchronized between drivers or across | 9 | the fences(struct fence) that are needed to synchronize between drivers or |
10 | process boundaries. | 10 | across process boundaries. |
11 | 11 | ||
12 | The sync_file API is meant to be used to send and receive fence information | 12 | The sync_file API is meant to be used to send and receive fence information |
13 | to/from userspace. It enables userspace to do explicit fencing, where instead | 13 | to/from userspace. It enables userspace to do explicit fencing, where instead |
@@ -32,7 +32,7 @@ in-fences and out-fences | |||
32 | Sync files can go either to or from userspace. When a sync_file is sent from | 32 | Sync files can go either to or from userspace. When a sync_file is sent from |
33 | the driver to userspace we call the fences it contains 'out-fences'. They are | 33 | the driver to userspace we call the fences it contains 'out-fences'. They are |
34 | related to a buffer that the driver is processing or is going to process, so | 34 | related to a buffer that the driver is processing or is going to process, so |
35 | the driver an create out-fence to be able to notify, through fence_signal(), | 35 | the driver creates an out-fence to be able to notify, through fence_signal(), |
36 | when it has finished using (or processing) that buffer. Out-fences are fences | 36 | when it has finished using (or processing) that buffer. Out-fences are fences |
37 | that the driver creates. | 37 | that the driver creates. |
38 | 38 | ||
diff --git a/Documentation/zh_CN/CodingStyle b/Documentation/zh_CN/CodingStyle index 654afd72eb24..bbb9d6ae05ca 100644 --- a/Documentation/zh_CN/CodingStyle +++ b/Documentation/zh_CN/CodingStyle | |||
@@ -24,34 +24,33 @@ Documentation/CodingStyleçš„ä¸æ–‡ç¿»è¯‘ | |||
24 | 24 | ||
25 | Linuxå†…æ ¸ä»£ç é£Žæ ¼ | 25 | Linuxå†…æ ¸ä»£ç é£Žæ ¼ |
26 | 26 | ||
27 | 这是一个简çŸçš„æ–‡æ¡£ï¼Œæè¿°äº†linuxå†…æ ¸çš„é¦–é€‰ä»£ç é£Žæ ¼ã€‚ä»£ç é£Žæ ¼æ˜¯å› äººè€Œå¼‚çš„ï¼Œè€Œä¸”æˆ‘ | 27 | 这是一个简çŸçš„æ–‡æ¡£ï¼Œæè¿°äº† linux å†…æ ¸çš„é¦–é€‰ä»£ç é£Žæ ¼ã€‚ä»£ç é£Žæ ¼æ˜¯å› äººè€Œå¼‚çš„ï¼Œè€Œä¸”æˆ‘ |
28 | 䏿„¿æ„æŠŠæˆ‘çš„è§‚ç‚¹å¼ºåŠ ç»™ä»»ä½•äººï¼Œä¸è¿‡è¿™é‡Œæ‰€è®²è¿°çš„æ˜¯æˆ‘å¿…é¡»è¦ç»´æŠ¤çš„ä»£ç æ‰€éµå®ˆçš„é£Žæ ¼ï¼Œ | 28 | 䏿„¿æ„æŠŠè‡ªå·±çš„è§‚ç‚¹å¼ºåŠ ç»™ä»»ä½•äººï¼Œä½†è¿™å°±åƒæˆ‘去åšä»»ä½•事情都必须éµå¾ªçš„åŽŸåˆ™é‚£æ ·ï¼Œæˆ‘ä¹Ÿ |
29 | 并且我也希望ç»å¤§å¤šæ•°å…¶ä»–代ç 也能éµå®ˆè¿™ä¸ªé£Žæ ¼ã€‚è¯·åœ¨å†™ä»£ç æ—¶è‡³å°‘考虑一下本文所述的 | 29 | 希望在ç»å¤§å¤šæ•°äº‹ä¸Šä¿æŒè¿™ç§çš„æ€åº¦ã€‚è¯·ï¼ˆåœ¨å†™ä»£ç æ—¶ï¼‰è‡³å°‘考虑一下这里的代ç é£Žæ ¼ã€‚ |
30 | é£Žæ ¼ã€‚ | ||
31 | 30 | ||
32 | é¦–å…ˆï¼Œæˆ‘å»ºè®®ä½ æ‰“å°ä¸€ä»½GNU代ç 规范,然åŽä¸è¦è¯»å®ƒã€‚烧了它,这是一个具有é‡å¤§è±¡å¾æ€§ | 31 | é¦–å…ˆï¼Œæˆ‘å»ºè®®ä½ æ‰“å°ä¸€ä»½ GNU 代ç 规范,然åŽä¸è¦è¯»ã€‚烧了它,这是一个具有é‡å¤§è±¡å¾æ€§æ„义 |
33 | æ„义的动作。 | 32 | 的动作。 |
34 | 33 | ||
35 | ä¸ç®¡æ€Žæ ·ï¼ŒçŽ°åœ¨æˆ‘ä»¬å¼€å§‹ï¼š | 34 | ä¸ç®¡æ€Žæ ·ï¼ŒçŽ°åœ¨æˆ‘ä»¬å¼€å§‹ï¼š |
36 | 35 | ||
37 | 36 | ||
38 | ç¬¬ä¸€ç« ï¼šç¼©è¿› | 37 | ç¬¬ä¸€ç« ï¼šç¼©è¿› |
39 | 38 | ||
40 | 制表符是8个å—符,所以缩进也是8个å—符。有些异端è¿åŠ¨è¯•å›¾å°†ç¼©è¿›å˜ä¸º4(乃至2)个å—符 | 39 | 制表符是 8 个å—符,所以缩进也是 8 个å—符。有些异端è¿åŠ¨è¯•å›¾å°†ç¼©è¿›å˜ä¸º 4(甚至 2ï¼ï¼‰ |
41 | æ·±ï¼Œè¿™å‡ ä¹Žç›¸å½“äºŽå°è¯•将圆周率的值定义为3。 | 40 | 个å—ç¬¦æ·±ï¼Œè¿™å‡ ä¹Žç›¸å½“äºŽå°è¯•将圆周率的值定义为 3。 |
42 | 41 | ||
43 | ç†ç”±ï¼šç¼©è¿›çš„全部æ„义就在于清楚的定义一个控制å—èµ·æ¢äºŽä½•å¤„ã€‚å°¤å…¶æ˜¯å½“ä½ ç›¯ç€ä½ çš„å±å¹• | 42 | ç†ç”±ï¼šç¼©è¿›çš„全部æ„义就在于清楚的定义一个控制å—èµ·æ¢äºŽä½•å¤„ã€‚å°¤å…¶æ˜¯å½“ä½ ç›¯ç€ä½ çš„å±å¹• |
44 | 连ç»çœ‹äº†20å°æ—¶ä¹‹åŽï¼Œä½ 将会å‘çŽ°å¤§ä¸€ç‚¹çš„ç¼©è¿›ä¼šä½¿ä½ æ›´å®¹æ˜“åˆ†è¾¨ç¼©è¿›ã€‚ | 43 | 连ç»çœ‹äº† 20 å°æ—¶ä¹‹åŽï¼Œä½ 将会å‘çŽ°å¤§ä¸€ç‚¹çš„ç¼©è¿›ä¼šä½¿ä½ æ›´å®¹æ˜“åˆ†è¾¨ç¼©è¿›ã€‚ |
45 | 44 | ||
46 | 现在,有些人会抱怨8个å—符的缩进会使代ç å‘å³è¾¹ç§»åŠ¨çš„å¤ªè¿œï¼Œåœ¨80个å—符的终端å±å¹•上 | 45 | 现在,有些人会抱怨 8 个å—符的缩进会使代ç å‘å³è¾¹ç§»åŠ¨çš„å¤ªè¿œï¼Œåœ¨ 80 个å—符的终端å±å¹•上 |
47 | å°±å¾ˆéš¾è¯»è¿™æ ·çš„ä»£ç ã€‚è¿™ä¸ªé—®é¢˜çš„ç”æ¡ˆæ˜¯ï¼Œå¦‚æžœä½ éœ€è¦3级以上的缩进,ä¸ç®¡ç”¨ä½•ç§æ–¹å¼ä½ | 46 | å°±å¾ˆéš¾è¯»è¿™æ ·çš„ä»£ç ã€‚è¿™ä¸ªé—®é¢˜çš„ç”æ¡ˆæ˜¯ï¼Œå¦‚æžœä½ éœ€è¦ 3 级以上的缩进,ä¸ç®¡ç”¨ä½•ç§æ–¹å¼ä½ |
48 | 的代ç å·²ç»æœ‰é—®é¢˜äº†ï¼Œåº”该修æ£ä½ 的程åºã€‚ | 47 | 的代ç å·²ç»æœ‰é—®é¢˜äº†ï¼Œåº”该修æ£ä½ 的程åºã€‚ |
49 | 48 | ||
50 | 简而言之,8个å—符的缩进å¯ä»¥è®©ä»£ç æ›´å®¹æ˜“é˜…è¯»ï¼Œè¿˜æœ‰ä¸€ä¸ªå¥½å¤„æ˜¯å½“ä½ çš„å‡½æ•°åµŒå¥—å¤ªæ·±çš„ | 49 | 简而言之,8 个å—符的缩进å¯ä»¥è®©ä»£ç æ›´å®¹æ˜“é˜…è¯»ï¼Œè¿˜æœ‰ä¸€ä¸ªå¥½å¤„æ˜¯å½“ä½ çš„å‡½æ•°åµŒå¥—å¤ªæ·±çš„ |
51 | 时候å¯ä»¥ç»™ä½ è¦å‘Šã€‚留心这个è¦å‘Šã€‚ | 50 | 时候å¯ä»¥ç»™ä½ è¦å‘Šã€‚留心这个è¦å‘Šã€‚ |
52 | 51 | ||
53 | 在switchè¯å¥ä¸æ¶ˆé™¤å¤šçº§ç¼©è¿›çš„é¦–é€‰çš„æ–¹å¼æ˜¯è®©â€œswitchâ€å’Œä»Žå±žäºŽå®ƒçš„“caseâ€æ ‡ç¾å¯¹é½äºŽåŒ | 52 | 在 switch è¯å¥ä¸æ¶ˆé™¤å¤šçº§ç¼©è¿›çš„é¦–é€‰çš„æ–¹å¼æ˜¯è®© “switch†和从属于它的 “caseâ€ æ ‡ç¾ |
54 | 一列,而ä¸è¦â€œä¸¤æ¬¡ç¼©è¿›â€â€œcaseâ€æ ‡ç¾ã€‚比如: | 53 | 对é½äºŽåŒä¸€åˆ—,而ä¸è¦ “两次缩进†“caseâ€ æ ‡ç¾ã€‚比如: |
55 | 54 | ||
56 | switch (suffix) { | 55 | switch (suffix) { |
57 | case 'G': | 56 | case 'G': |
@@ -70,7 +69,6 @@ Documentation/CodingStyleçš„ä¸æ–‡ç¿»è¯‘ | |||
70 | break; | 69 | break; |
71 | } | 70 | } |
72 | 71 | ||
73 | |||
74 | ä¸è¦æŠŠå¤šä¸ªè¯å¥æ”¾åœ¨ä¸€è¡Œé‡Œï¼Œé™¤éžä½ 有什么东西è¦éšè—: | 72 | ä¸è¦æŠŠå¤šä¸ªè¯å¥æ”¾åœ¨ä¸€è¡Œé‡Œï¼Œé™¤éžä½ 有什么东西è¦éšè—: |
75 | 73 | ||
76 | if (condition) do_this; | 74 | if (condition) do_this; |
@@ -79,7 +77,7 @@ Documentation/CodingStyleçš„ä¸æ–‡ç¿»è¯‘ | |||
79 | 也ä¸è¦åœ¨ä¸€è¡Œé‡Œæ”¾å¤šä¸ªèµ‹å€¼è¯å¥ã€‚å†…æ ¸ä»£ç é£Žæ ¼è¶…çº§ç®€å•。就是é¿å…å¯èƒ½å¯¼è‡´åˆ«äººè¯¯è¯»çš„表 | 77 | 也ä¸è¦åœ¨ä¸€è¡Œé‡Œæ”¾å¤šä¸ªèµ‹å€¼è¯å¥ã€‚å†…æ ¸ä»£ç é£Žæ ¼è¶…çº§ç®€å•。就是é¿å…å¯èƒ½å¯¼è‡´åˆ«äººè¯¯è¯»çš„表 |
80 | è¾¾å¼ã€‚ | 78 | è¾¾å¼ã€‚ |
81 | 79 | ||
82 | é™¤äº†æ³¨é‡Šã€æ–‡æ¡£å’ŒKconfig之外,ä¸è¦ä½¿ç”¨ç©ºæ ¼æ¥ç¼©è¿›ï¼Œå‰é¢çš„ä¾‹åæ˜¯ä¾‹å¤–,是有æ„为之。 | 80 | é™¤äº†æ³¨é‡Šã€æ–‡æ¡£å’Œ Kconfig 之外,ä¸è¦ä½¿ç”¨ç©ºæ ¼æ¥ç¼©è¿›ï¼Œå‰é¢çš„ä¾‹åæ˜¯ä¾‹å¤–,是有æ„为之。 |
83 | 81 | ||
84 | 选用一个好的编辑器,ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºæ ¼ã€‚ | 82 | 选用一个好的编辑器,ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºæ ¼ã€‚ |
85 | 83 | ||
@@ -88,27 +86,18 @@ Documentation/CodingStyleçš„ä¸æ–‡ç¿»è¯‘ | |||
88 | 86 | ||
89 | 代ç é£Žæ ¼çš„æ„义就在于使用平常使用的工具æ¥ç»´æŒä»£ç çš„å¯è¯»æ€§å’Œå¯ç»´æŠ¤æ€§ã€‚ | 87 | 代ç é£Žæ ¼çš„æ„义就在于使用平常使用的工具æ¥ç»´æŒä»£ç çš„å¯è¯»æ€§å’Œå¯ç»´æŠ¤æ€§ã€‚ |
90 | 88 | ||
91 | æ¯ä¸€è¡Œçš„长度的é™åˆ¶æ˜¯80列,我们强烈建议您éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ã€‚ | 89 | æ¯ä¸€è¡Œçš„长度的é™åˆ¶æ˜¯ 80 列,我们强烈建议您éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ã€‚ |
92 | 90 | ||
93 | 长于80列的è¯å¥è¦æ‰“æ•£æˆæœ‰æ„义的片段。æ¯ä¸ªç‰‡æ®µè¦æ˜Žæ˜¾çŸäºŽåŽŸæ¥çš„è¯å¥ï¼Œè€Œä¸”放置的ä½ç½® | 91 | 长于 80 列的è¯å¥è¦æ‰“æ•£æˆæœ‰æ„义的片段。除éžè¶…过 80 åˆ—èƒ½æ˜¾è‘—å¢žåŠ å¯è¯»æ€§ï¼Œå¹¶ä¸”ä¸ä¼šéšè— |
94 | 也明显的é å³ã€‚åŒæ ·çš„è§„åˆ™ä¹Ÿé€‚ç”¨äºŽæœ‰å¾ˆé•¿å‚æ•°åˆ—表的函数头。长å—ç¬¦ä¸²ä¹Ÿè¦æ‰“æ•£æˆè¾ƒçŸçš„ | 92 | ä¿¡æ¯ã€‚åç‰‡æ®µè¦æ˜Žæ˜¾çŸäºŽæ¯ç‰‡æ®µï¼Œå¹¶æ˜Žæ˜¾é å³ã€‚è¿™åŒæ ·é€‚用于有ç€å¾ˆé•¿å‚数列表的函数头。 |
95 | å—符串。唯一的例外是超过80列å¯ä»¥å¤§å¹…度æé«˜å¯è¯»æ€§å¹¶ä¸”ä¸ä¼šéšè—ä¿¡æ¯çš„æƒ…况。 | 93 | 然而,ç»å¯¹ä¸è¦æ‰“散对用户å¯è§çš„å—符串,例如 printk ä¿¡æ¯ï¼Œå› ä¸ºè¿™å°†å¯¼è‡´æ— æ³• grep 这些 |
96 | 94 | ä¿¡æ¯ã€‚ | |
97 | void fun(int a, int b, int c) | ||
98 | { | ||
99 | if (condition) | ||
100 | printk(KERN_WARNING "Warning this is a long printk with " | ||
101 | "3 parameters a: %u b: %u " | ||
102 | "c: %u \n", a, b, c); | ||
103 | else | ||
104 | next_statement; | ||
105 | } | ||
106 | 95 | ||
107 | ç¬¬ä¸‰ç« ï¼šå¤§æ‹¬å·å’Œç©ºæ ¼çš„æ”¾ç½® | 96 | ç¬¬ä¸‰ç« ï¼šå¤§æ‹¬å·å’Œç©ºæ ¼çš„æ”¾ç½® |
108 | 97 | ||
109 | Cè¯è¨€é£Žæ ¼ä¸å¦å¤–一个常è§é—®é¢˜æ˜¯å¤§æ‹¬å·çš„æ”¾ç½®ã€‚和缩进大å°ä¸åŒï¼Œé€‰æ‹©æˆ–弃用æŸç§æ”¾ç½®ç– | 98 | Cè¯è¨€é£Žæ ¼ä¸å¦å¤–一个常è§é—®é¢˜æ˜¯å¤§æ‹¬å·çš„æ”¾ç½®ã€‚和缩进大å°ä¸åŒï¼Œé€‰æ‹©æˆ–弃用æŸç§æ”¾ç½®ç– |
110 | ç•¥å¹¶æ²¡æœ‰å¤šå°‘æŠ€æœ¯ä¸Šçš„åŽŸå› ï¼Œä¸è¿‡é¦–选的方å¼ï¼Œå°±åƒKernighanå’ŒRitchie展示给我们的,是 | 99 | ç•¥å¹¶æ²¡æœ‰å¤šå°‘æŠ€æœ¯ä¸Šçš„åŽŸå› ï¼Œä¸è¿‡é¦–选的方å¼ï¼Œå°±åƒ Kernighan å’Œ Ritchie 展示给我们的, |
111 | æŠŠèµ·å§‹å¤§æ‹¬å·æ”¾åœ¨è¡Œå°¾ï¼Œè€ŒæŠŠç»“æŸå¤§æ‹¬å·æ”¾åœ¨è¡Œé¦–,所以: | 100 | æ˜¯æŠŠèµ·å§‹å¤§æ‹¬å·æ”¾åœ¨è¡Œå°¾ï¼Œè€ŒæŠŠç»“æŸå¤§æ‹¬å·æ”¾åœ¨è¡Œé¦–,所以: |
112 | 101 | ||
113 | if (x is true) { | 102 | if (x is true) { |
114 | we do y | 103 | we do y |
@@ -134,12 +123,12 @@ Cè¯è¨€é£Žæ ¼ä¸å¦å¤–一个常è§é—®é¢˜æ˜¯å¤§æ‹¬å·çš„æ”¾ç½®ã€‚和缩进大å°ä | |||
134 | body of function | 123 | body of function |
135 | } | 124 | } |
136 | 125 | ||
137 | 全世界的异端å¯èƒ½ä¼šæŠ±æ€¨è¿™ä¸ªä¸ä¸€è‡´æ€§æ˜¯â€¦â€¦å‘ƒâ€¦â€¦ä¸ä¸€è‡´çš„,ä¸è¿‡æ‰€æœ‰æ€ç»´å¥å…¨çš„人都知é“( | 126 | 全世界的异端å¯èƒ½ä¼šæŠ±æ€¨è¿™ä¸ªä¸ä¸€è‡´æ€§æ˜¯â€¦â€¦å‘ƒâ€¦â€¦ä¸ä¸€è‡´çš„,ä¸è¿‡æ‰€æœ‰æ€ç»´å¥å…¨çš„äººéƒ½çŸ¥é“ |
138 | a)K&R是_æ£ç¡®çš„_,并且(b)K&R是æ£ç¡®çš„。æ¤å¤–,ä¸ç®¡æ€Žæ ·å‡½æ•°éƒ½æ˜¯ç‰¹æ®Šçš„(在Cè¯è¨€ä¸ | 127 | (a) K&R 是 _æ£ç¡®çš„_,并且 (b) K&R 是æ£ç¡®çš„。æ¤å¤–,ä¸ç®¡æ€Žæ ·å‡½æ•°éƒ½æ˜¯ç‰¹æ®Šçš„(C |
139 | ,函数是ä¸èƒ½åµŒå¥—的)。 | 128 | 函数是ä¸èƒ½åµŒå¥—的)。 |
140 | 129 | ||
141 | 注æ„结æŸå¤§æ‹¬å·ç‹¬è‡ªå æ®ä¸€è¡Œï¼Œé™¤éžå®ƒåŽé¢è·Ÿç€åŒä¸€ä¸ªè¯å¥çš„剩余部分,也就是doè¯å¥ä¸çš„ | 130 | 注æ„结æŸå¤§æ‹¬å·ç‹¬è‡ªå æ®ä¸€è¡Œï¼Œé™¤éžå®ƒåŽé¢è·Ÿç€åŒä¸€ä¸ªè¯å¥çš„剩余部分,也就是 do è¯å¥ä¸çš„ |
142 | “whileâ€æˆ–者ifè¯å¥ä¸çš„“elseâ€ï¼Œåƒè¿™æ ·ï¼š | 131 | “while†或者 if è¯å¥ä¸çš„ “elseâ€ï¼Œåƒè¿™æ ·ï¼š |
143 | 132 | ||
144 | do { | 133 | do { |
145 | body of do-loop | 134 | body of do-loop |
@@ -158,41 +147,50 @@ a)K&R是_æ£ç¡®çš„_,并且(b)K&R是æ£ç¡®çš„。æ¤å¤–,ä¸ç®¡æ€Žæ ·å‡½æ | |||
158 | ç†ç”±ï¼šK&R。 | 147 | ç†ç”±ï¼šK&R。 |
159 | 148 | ||
160 | 也请注æ„è¿™ç§å¤§æ‹¬å·çš„æ”¾ç½®æ–¹å¼ä¹Ÿèƒ½ä½¿ç©ºï¼ˆæˆ–者差ä¸å¤šç©ºçš„ï¼‰è¡Œçš„æ•°é‡æœ€å°åŒ–ï¼ŒåŒæ—¶ä¸å¤±å¯ | 149 | 也请注æ„è¿™ç§å¤§æ‹¬å·çš„æ”¾ç½®æ–¹å¼ä¹Ÿèƒ½ä½¿ç©ºï¼ˆæˆ–者差ä¸å¤šç©ºçš„ï¼‰è¡Œçš„æ•°é‡æœ€å°åŒ–ï¼ŒåŒæ—¶ä¸å¤±å¯ |
161 | è¯»æ€§ã€‚å› æ¤ï¼Œç”±äºŽä½ çš„å±å¹•上的新行是ä¸å¯å†ç”Ÿèµ„æºï¼ˆæƒ³æƒ³25行的终端å±å¹•ï¼‰ï¼Œä½ å°†ä¼šæœ‰æ›´ | 150 | è¯»æ€§ã€‚å› æ¤ï¼Œç”±äºŽä½ çš„å±å¹•上的新行是ä¸å¯å†ç”Ÿèµ„æºï¼ˆæƒ³æƒ³ 25 行的终端å±å¹•ï¼‰ï¼Œä½ å°†ä¼šæœ‰æ›´ |
162 | å¤šçš„ç©ºè¡Œæ¥æ”¾ç½®æ³¨é‡Šã€‚ | 151 | å¤šçš„ç©ºè¡Œæ¥æ”¾ç½®æ³¨é‡Šã€‚ |
163 | 152 | ||
164 | å½“åªæœ‰ä¸€ä¸ªå•独的è¯å¥çš„æ—¶å€™ï¼Œä¸ç”¨åŠ ä¸å¿…è¦çš„大括å·ã€‚ | 153 | å½“åªæœ‰ä¸€ä¸ªå•独的è¯å¥çš„æ—¶å€™ï¼Œä¸ç”¨åŠ ä¸å¿…è¦çš„大括å·ã€‚ |
165 | 154 | ||
166 | if (condition) | 155 | if (condition) |
167 | action(); | 156 | action(); |
157 | |||
158 | 和 | ||
159 | |||
160 | if (condition) | ||
161 | do_this(); | ||
162 | else | ||
163 | do_that(); | ||
168 | 164 | ||
169 | 这点ä¸é€‚用于本身为æŸä¸ªæ¡ä»¶è¯å¥çš„一个分支的å•独è¯å¥ã€‚这时需è¦åœ¨ä¸¤ä¸ªåˆ†æ”¯é‡Œéƒ½ä½¿ç”¨å¤§ | 165 | 这并ä¸é€‚ç”¨äºŽåªæœ‰ä¸€ä¸ªæ¡ä»¶åˆ†æ”¯æ˜¯å•è¯å¥çš„æƒ…况;这时所有分支都è¦ä½¿ç”¨å¤§æ‹¬å·ï¼š |
170 | 括å·ã€‚ | ||
171 | 166 | ||
172 | if (condition) { | 167 | if (condition) { |
173 | do_this(); | 168 | do_this(); |
174 | do_that(); | 169 | do_that(); |
175 | } else { | 170 | } else { |
176 | otherwise(); | 171 | otherwise(); |
177 | } | 172 | } |
178 | 173 | ||
179 | 3.1ï¼šç©ºæ ¼ | 174 | 3.1ï¼šç©ºæ ¼ |
180 | 175 | ||
181 | Linuxå†…æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关键å—。(大多数)关键å—åŽ | 176 | Linux å†…æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关键å—。(大多数)关键å—åŽ |
182 | è¦åŠ ä¸€ä¸ªç©ºæ ¼ã€‚å€¼å¾—æ³¨æ„的例外是sizeofã€typeofã€alignofå’Œ__attribute__ï¼Œè¿™äº›å…³é”®å— | 177 | è¦åŠ ä¸€ä¸ªç©ºæ ¼ã€‚å€¼å¾—æ³¨æ„的例外是 sizeofã€typeofã€alignof å’Œ __attribute__,这些 |
183 | æŸäº›ç¨‹åº¦ä¸Šçœ‹èµ·æ¥æ›´åƒå‡½æ•°ï¼ˆå®ƒä»¬åœ¨Linux里也常常伴éšå°æ‹¬å·è€Œä½¿ç”¨ï¼Œå°½ç®¡åœ¨Cè¯è¨€é‡Œè¿™æ · | 178 | 关键嗿Ÿäº›ç¨‹åº¦ä¸Šçœ‹èµ·æ¥æ›´åƒå‡½æ•°ï¼ˆå®ƒä»¬åœ¨ Linux 里也常常伴éšå°æ‹¬å·è€Œä½¿ç”¨ï¼Œå°½ç®¡åœ¨ C 里 |
184 | çš„å°æ‹¬å·ä¸æ˜¯å¿…需的,就åƒâ€œstruct fileinfo infoâ€å£°æ˜Žè¿‡åŽçš„“sizeof infoâ€ï¼‰ã€‚ | 179 | è¿™æ ·çš„å°æ‹¬å·ä¸æ˜¯å¿…éœ€çš„ï¼Œå°±åƒ â€œstruct fileinfo info†声明过åŽçš„ “sizeof infoâ€ï¼‰ã€‚ |
185 | 180 | ||
186 | 所以在这些关键å—ä¹‹åŽæ”¾ä¸€ä¸ªç©ºæ ¼ï¼š | 181 | 所以在这些关键å—ä¹‹åŽæ”¾ä¸€ä¸ªç©ºæ ¼ï¼š |
182 | |||
187 | if, switch, case, for, do, while | 183 | if, switch, case, for, do, while |
188 | 但是ä¸è¦åœ¨sizeofã€typeofã€alignof或者__attribute__这些关键å—ä¹‹åŽæ”¾ç©ºæ ¼ã€‚例如, | 184 | |
185 | 但是ä¸è¦åœ¨ sizeofã€typeofã€alignof 或者 __attribute__ 这些关键å—ä¹‹åŽæ”¾ç©ºæ ¼ã€‚例如, | ||
186 | |||
189 | s = sizeof(struct file); | 187 | s = sizeof(struct file); |
190 | 188 | ||
191 | ä¸è¦åœ¨å°æ‹¬å·é‡Œçš„表达å¼ä¸¤ä¾§åŠ ç©ºæ ¼ã€‚è¿™æ˜¯ä¸€ä¸ªå例: | 189 | ä¸è¦åœ¨å°æ‹¬å·é‡Œçš„表达å¼ä¸¤ä¾§åŠ ç©ºæ ¼ã€‚è¿™æ˜¯ä¸€ä¸ªå例: |
192 | 190 | ||
193 | s = sizeof( struct file ); | 191 | s = sizeof( struct file ); |
194 | 192 | ||
195 | 当声明指针类型或者返回指针类型的函数时,“*â€çš„é¦–é€‰ä½¿ç”¨æ–¹å¼æ˜¯ä½¿ä¹‹é è¿‘å˜é‡å或者函 | 193 | 当声明指针类型或者返回指针类型的函数时,“*â€ çš„é¦–é€‰ä½¿ç”¨æ–¹å¼æ˜¯ä½¿ä¹‹é è¿‘å˜é‡å或者函 |
196 | æ•°åï¼Œè€Œä¸æ˜¯é 近类型å。例å: | 194 | æ•°åï¼Œè€Œä¸æ˜¯é 近类型å。例å: |
197 | 195 | ||
198 | char *linux_banner; | 196 | char *linux_banner; |
@@ -204,15 +202,18 @@ Linuxå†…æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关 | |||
204 | = + - < > * / % | & ^ <= >= == != ? : | 202 | = + - < > * / % | & ^ <= >= == != ? : |
205 | 203 | ||
206 | 但是一元æ“作符åŽä¸è¦åŠ ç©ºæ ¼ï¼š | 204 | 但是一元æ“作符åŽä¸è¦åŠ ç©ºæ ¼ï¼š |
205 | |||
207 | & * + - ~ ! sizeof typeof alignof __attribute__ defined | 206 | & * + - ~ ! sizeof typeof alignof __attribute__ defined |
208 | 207 | ||
209 | åŽç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符å‰ä¸åŠ ç©ºæ ¼ï¼š | 208 | åŽç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符å‰ä¸åŠ ç©ºæ ¼ï¼š |
209 | |||
210 | ++ -- | 210 | ++ -- |
211 | 211 | ||
212 | å‰ç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符åŽä¸åŠ ç©ºæ ¼ï¼š | 212 | å‰ç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符åŽä¸åŠ ç©ºæ ¼ï¼š |
213 | |||
213 | ++ -- | 214 | ++ -- |
214 | 215 | ||
215 | “.â€å’Œâ€œ->â€ç»“构体æˆå‘˜æ“作符å‰åŽä¸åŠ ç©ºæ ¼ã€‚ | 216 | ‘.’ å’Œ “->†结构体æˆå‘˜æ“作符å‰åŽä¸åŠ ç©ºæ ¼ã€‚ |
216 | 217 | ||
217 | ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºç™½ã€‚有些å¯ä»¥è‡ªåŠ¨ç¼©è¿›çš„ç¼–è¾‘å™¨ä¼šåœ¨æ–°è¡Œçš„è¡Œé¦–åŠ å…¥é€‚é‡çš„空白,然åŽä½ | 218 | ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºç™½ã€‚有些å¯ä»¥è‡ªåŠ¨ç¼©è¿›çš„ç¼–è¾‘å™¨ä¼šåœ¨æ–°è¡Œçš„è¡Œé¦–åŠ å…¥é€‚é‡çš„空白,然åŽä½ |
218 | å°±å¯ä»¥ç›´æŽ¥åœ¨é‚£ä¸€è¡Œè¾“入代ç 。ä¸è¿‡å‡å¦‚ä½ æœ€åŽæ²¡æœ‰åœ¨é‚£ä¸€è¡Œè¾“入代ç ï¼Œæœ‰äº›ç¼–è¾‘å™¨å°±ä¸ | 219 | å°±å¯ä»¥ç›´æŽ¥åœ¨é‚£ä¸€è¡Œè¾“入代ç 。ä¸è¿‡å‡å¦‚ä½ æœ€åŽæ²¡æœ‰åœ¨é‚£ä¸€è¡Œè¾“入代ç ï¼Œæœ‰äº›ç¼–è¾‘å™¨å°±ä¸ |
@@ -225,23 +226,23 @@ Linuxå†…æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关 | |||
225 | 226 | ||
226 | ç¬¬å››ç« ï¼šå‘½å | 227 | ç¬¬å››ç« ï¼šå‘½å |
227 | 228 | ||
228 | C是一个简朴的è¯è¨€ï¼Œä½ 的命åä¹Ÿåº”è¯¥è¿™æ ·ã€‚å’ŒModula-2å’ŒPascal程åºå‘˜ä¸åŒï¼ŒC程åºå‘˜ä¸ä½¿ | 229 | C是一个简朴的è¯è¨€ï¼Œä½ 的命åä¹Ÿåº”è¯¥è¿™æ ·ã€‚å’Œ Modula-2 å’Œ Pascal 程åºå‘˜ä¸åŒï¼ŒC 程åºå‘˜ |
229 | 用类似ThisVariableIsATemporaryCounterè¿™æ ·åŽä¸½çš„åå—。C程åºå‘˜ä¼šç§°é‚£ä¸ªå˜é‡ä¸ºâ€œtmp†| 230 | ä¸ä½¿ç”¨ç±»ä¼¼ ThisVariableIsATemporaryCounter è¿™æ ·åŽä¸½çš„åå—。C 程åºå‘˜ä¼šç§°é‚£ä¸ªå˜é‡ |
230 | ï¼Œè¿™æ ·å†™èµ·æ¥ä¼šæ›´å®¹æ˜“,而且至少ä¸ä¼šä»¤å…¶éš¾äºŽç†è§£ã€‚ | 231 | 为 “tmpâ€ï¼Œè¿™æ ·å†™èµ·æ¥ä¼šæ›´å®¹æ˜“,而且至少ä¸ä¼šä»¤å…¶éš¾äºŽç†è§£ã€‚ |
231 | 232 | ||
232 | ä¸è¿‡ï¼Œè™½ç„¶æ··ç”¨å¤§å°å†™çš„åå—æ˜¯ä¸æå€¡ä½¿ç”¨çš„,但是全局å˜é‡è¿˜æ˜¯éœ€è¦ä¸€ä¸ªå…·æè¿°æ€§çš„åå— | 233 | ä¸è¿‡ï¼Œè™½ç„¶æ··ç”¨å¤§å°å†™çš„åå—æ˜¯ä¸æå€¡ä½¿ç”¨çš„,但是全局å˜é‡è¿˜æ˜¯éœ€è¦ä¸€ä¸ªå…·æè¿°æ€§çš„åå— |
233 | 。称一个全局函数为“fooâ€æ˜¯ä¸€ä¸ªéš¾ä»¥é¥¶æ•的错误。 | 234 | 。称一个全局函数为 “foo†是一个难以饶æ•的错误。 |
234 | 235 | ||
235 | 全局å˜é‡ï¼ˆåªæœ‰å½“ä½ çœŸæ£éœ€è¦å®ƒä»¬çš„æ—¶å€™å†ç”¨å®ƒï¼‰éœ€è¦æœ‰ä¸€ä¸ªå…·æè¿°æ€§çš„åå—,就åƒå…¨å±€å‡½ | 236 | 全局å˜é‡ï¼ˆåªæœ‰å½“ä½ çœŸæ£éœ€è¦å®ƒä»¬çš„æ—¶å€™å†ç”¨å®ƒï¼‰éœ€è¦æœ‰ä¸€ä¸ªå…·æè¿°æ€§çš„åå—,就åƒå…¨å±€å‡½ |
236 | æ•°ã€‚å¦‚æžœä½ æœ‰ä¸€ä¸ªå¯ä»¥è®¡ç®—活动用户数é‡çš„å‡½æ•°ï¼Œä½ åº”è¯¥å«å®ƒâ€œcount_active_users()â€æˆ–者 | 237 | æ•°ã€‚å¦‚æžœä½ æœ‰ä¸€ä¸ªå¯ä»¥è®¡ç®—活动用户数é‡çš„å‡½æ•°ï¼Œä½ åº”è¯¥å«å®ƒ “count_active_users()†|
237 | 类似的åå—ï¼Œä½ ä¸åº”该å«å®ƒâ€œcntuser()â€ã€‚ | 238 | 或者类似的åå—ï¼Œä½ ä¸åº”该å«å®ƒ “cntuser()â€ã€‚ |
238 | 239 | ||
239 | 在函数åä¸åŒ…å«å‡½æ•°ç±»åž‹ï¼ˆæ‰€è°“çš„åŒˆç‰™åˆ©å‘½åæ³•)是脑å出了问题——编译器知é“那些类型而 | 240 | 在函数åä¸åŒ…å«å‡½æ•°ç±»åž‹ï¼ˆæ‰€è°“çš„åŒˆç‰™åˆ©å‘½åæ³•)是脑å出了问题——编译器知é“那些类型而 |
240 | ä¸”èƒ½å¤Ÿæ£€æŸ¥é‚£äº›ç±»åž‹ï¼Œè¿™æ ·åšåªèƒ½æŠŠç¨‹åºå‘˜å¼„ç³Šæ¶‚äº†ã€‚éš¾æ€ªå¾®è½¯æ€»æ˜¯åˆ¶é€ å‡ºæœ‰é—®é¢˜çš„ç¨‹åºã€‚ | 241 | ä¸”èƒ½å¤Ÿæ£€æŸ¥é‚£äº›ç±»åž‹ï¼Œè¿™æ ·åšåªèƒ½æŠŠç¨‹åºå‘˜å¼„ç³Šæ¶‚äº†ã€‚éš¾æ€ªå¾®è½¯æ€»æ˜¯åˆ¶é€ å‡ºæœ‰é—®é¢˜çš„ç¨‹åºã€‚ |
241 | 242 | ||
242 | 本地å˜é‡å应该简çŸï¼Œè€Œä¸”能够表达相关的å«ä¹‰ã€‚å¦‚æžœä½ æœ‰ä¸€äº›éšæœºçš„æ•´æ•°åž‹çš„循环计数器 | 243 | 本地å˜é‡å应该简çŸï¼Œè€Œä¸”能够表达相关的å«ä¹‰ã€‚å¦‚æžœä½ æœ‰ä¸€äº›éšæœºçš„æ•´æ•°åž‹çš„循环计数器 |
243 | ,它应该被称为“iâ€ã€‚å«å®ƒâ€œloop_counterâ€å¹¶æ— 益处,如果它没有被误解的å¯èƒ½çš„è¯ã€‚类似 | 244 | ,它应该被称为 “iâ€ã€‚å«å®ƒ “loop_counterâ€ å¹¶æ— ç›Šå¤„ï¼Œå¦‚æžœå®ƒæ²¡æœ‰è¢«è¯¯è§£çš„å¯èƒ½çš„è¯ã€‚ |
244 | 的,“tmpâ€å¯ä»¥ç”¨æ¥ç§°å‘¼ä»»æ„类型的临时å˜é‡ã€‚ | 245 | 类似的,“tmp†å¯ä»¥ç”¨æ¥ç§°å‘¼ä»»æ„类型的临时å˜é‡ã€‚ |
245 | 246 | ||
246 | å¦‚æžœä½ æ€•æ··æ·†äº†ä½ çš„æœ¬åœ°å˜é‡åï¼Œä½ å°±é‡åˆ°å¦ä¸€ä¸ªé—®é¢˜äº†ï¼Œå«åšå‡½æ•°å¢žé•¿è·å°”蒙失衡综åˆç—‡ | 247 | å¦‚æžœä½ æ€•æ··æ·†äº†ä½ çš„æœ¬åœ°å˜é‡åï¼Œä½ å°±é‡åˆ°å¦ä¸€ä¸ªé—®é¢˜äº†ï¼Œå«åšå‡½æ•°å¢žé•¿è·å°”蒙失衡综åˆç—‡ |
247 | 。请看第å…ç« ï¼ˆå‡½æ•°ï¼‰ã€‚ | 248 | 。请看第å…ç« ï¼ˆå‡½æ•°ï¼‰ã€‚ |
@@ -249,9 +250,9 @@ C是一个简朴的è¯è¨€ï¼Œä½ 的命åä¹Ÿåº”è¯¥è¿™æ ·ã€‚å’ŒModula-2å’ŒPascalç¨ | |||
249 | 250 | ||
250 | ç¬¬äº”ç« ï¼šTypedef | 251 | ç¬¬äº”ç« ï¼šTypedef |
251 | 252 | ||
252 | ä¸è¦ä½¿ç”¨ç±»ä¼¼â€œvps_tâ€ä¹‹ç±»çš„东西。 | 253 | ä¸è¦ä½¿ç”¨ç±»ä¼¼ “vps_t†之类的东西。 |
253 | 254 | ||
254 | 对结构体和指针使用typedefæ˜¯ä¸€ä¸ªé”™è¯¯ã€‚å½“ä½ åœ¨ä»£ç 里看到: | 255 | 对结构体和指针使用 typedef æ˜¯ä¸€ä¸ªé”™è¯¯ã€‚å½“ä½ åœ¨ä»£ç 里看到: |
255 | 256 | ||
256 | vps_t a; | 257 | vps_t a; |
257 | 258 | ||
@@ -261,91 +262,91 @@ C是一个简朴的è¯è¨€ï¼Œä½ 的命åä¹Ÿåº”è¯¥è¿™æ ·ã€‚å’ŒModula-2å’ŒPascalç¨ | |||
261 | 262 | ||
262 | struct virtual_container *a; | 263 | struct virtual_container *a; |
263 | 264 | ||
264 | ä½ å°±çŸ¥é““aâ€æ˜¯ä»€ä¹ˆäº†ã€‚ | 265 | ä½ å°±çŸ¥é“ â€œa†是什么了。 |
265 | 266 | ||
266 | 很多人认为typedef“能æé«˜å¯è¯»æ€§â€ã€‚å®žé™…ä¸æ˜¯è¿™æ ·çš„。它们åªåœ¨ä¸‹åˆ—情况下有用: | 267 | 很多人认为 typedef “能æé«˜å¯è¯»æ€§â€ã€‚å®žé™…ä¸æ˜¯è¿™æ ·çš„。它们åªåœ¨ä¸‹åˆ—情况下有用: |
267 | 268 | ||
268 | (a) 完全ä¸é€æ˜Žçš„å¯¹è±¡ï¼ˆè¿™ç§æƒ…况下è¦ä¸»åŠ¨ä½¿ç”¨typedefæ¥éšè—这个对象实际上是什么)。 | 269 | (a) 完全ä¸é€æ˜Žçš„å¯¹è±¡ï¼ˆè¿™ç§æƒ…况下è¦ä¸»åŠ¨ä½¿ç”¨ typedef æ¥éšè—这个对象实际上是什么)。 |
269 | 270 | ||
270 | 例如:“pte_tâ€ç‰ä¸é€æ˜Žå¯¹è±¡ï¼Œä½ åªèƒ½ç”¨åˆé€‚的访问函数æ¥è®¿é—®å®ƒä»¬ã€‚ | 271 | 例如:“pte_t†ç‰ä¸é€æ˜Žå¯¹è±¡ï¼Œä½ åªèƒ½ç”¨åˆé€‚的访问函数æ¥è®¿é—®å®ƒä»¬ã€‚ |
271 | 272 | ||
272 | 注æ„ï¼ä¸é€æ˜Žæ€§å’Œâ€œè®¿é—®å‡½æ•°â€æœ¬èº«æ˜¯ä¸å¥½çš„。我们使用pte_tç‰ç±»åž‹çš„åŽŸå› åœ¨äºŽçœŸçš„æ˜¯ | 273 | 注æ„ï¼ä¸é€æ˜Žæ€§å’Œâ€œè®¿é—®å‡½æ•°â€æœ¬èº«æ˜¯ä¸å¥½çš„。我们使用 pte_t ç‰ç±»åž‹çš„åŽŸå› åœ¨äºŽçœŸçš„æ˜¯ |
273 | 完全没有任何共用的å¯è®¿é—®ä¿¡æ¯ã€‚ | 274 | 完全没有任何共用的å¯è®¿é—®ä¿¡æ¯ã€‚ |
274 | 275 | ||
275 | (b) 清楚的整数类型,如æ¤ï¼Œè¿™å±‚抽象就å¯ä»¥å¸®åŠ©æ¶ˆé™¤åˆ°åº•æ˜¯â€œintâ€è¿˜æ˜¯â€œlongâ€çš„æ··æ·†ã€‚ | 276 | (b) 清楚的整数类型,如æ¤ï¼Œè¿™å±‚抽象就å¯ä»¥å¸®åŠ©æ¶ˆé™¤åˆ°åº•æ˜¯ “int†还是 “long†的混淆。 |
276 | 277 | ||
277 | u8/u16/u32是完全没有问题的typedef,ä¸è¿‡å®ƒä»¬æ›´ç¬¦åˆç±»åˆ«(d)è€Œä¸æ˜¯è¿™é‡Œã€‚ | 278 | u8/u16/u32 是完全没有问题的 typedef,ä¸è¿‡å®ƒä»¬æ›´ç¬¦åˆç±»åˆ« (d) è€Œä¸æ˜¯è¿™é‡Œã€‚ |
278 | 279 | ||
279 | 冿¬¡æ³¨æ„ï¼è¦è¿™æ ·åšï¼Œå¿…é¡»äº‹å‡ºæœ‰å› ã€‚å¦‚æžœæŸä¸ªå˜é‡æ˜¯â€œunsigned longâ€œï¼Œé‚£ä¹ˆæ²¡æœ‰å¿…è¦ | 280 | 冿¬¡æ³¨æ„ï¼è¦è¿™æ ·åšï¼Œå¿…é¡»äº‹å‡ºæœ‰å› ã€‚å¦‚æžœæŸä¸ªå˜é‡æ˜¯ “unsigned longâ€œï¼Œé‚£ä¹ˆæ²¡æœ‰å¿…è¦ |
280 | 281 | ||
281 | typedef unsigned long myflags_t; | 282 | typedef unsigned long myflags_t; |
282 | 283 | ||
283 | ä¸è¿‡å¦‚æžœæœ‰ä¸€ä¸ªæ˜Žç¡®çš„åŽŸå› ï¼Œæ¯”å¦‚å®ƒåœ¨æŸç§æƒ…况下å¯èƒ½ä¼šæ˜¯ä¸€ä¸ªâ€œunsigned intâ€è€Œåœ¨ | 284 | ä¸è¿‡å¦‚æžœæœ‰ä¸€ä¸ªæ˜Žç¡®çš„åŽŸå› ï¼Œæ¯”å¦‚å®ƒåœ¨æŸç§æƒ…况下å¯èƒ½ä¼šæ˜¯ä¸€ä¸ª “unsigned int†而在 |
284 | 其他情况下å¯èƒ½ä¸ºâ€œunsigned longâ€ï¼Œé‚£ä¹ˆå°±ä¸è¦çŠ¹è±«ï¼Œè¯·åŠ¡å¿…ä½¿ç”¨typedef。 | 285 | 其他情况下å¯èƒ½ä¸º “unsigned longâ€ï¼Œé‚£ä¹ˆå°±ä¸è¦çŠ¹è±«ï¼Œè¯·åŠ¡å¿…ä½¿ç”¨ typedef。 |
285 | 286 | ||
286 | (c) å½“ä½ ä½¿ç”¨sparse按å—é¢çš„创建一个新类型æ¥åšç±»åž‹æ£€æŸ¥çš„æ—¶å€™ã€‚ | 287 | (c) å½“ä½ ä½¿ç”¨sparse按å—é¢çš„创建一个新类型æ¥åšç±»åž‹æ£€æŸ¥çš„æ—¶å€™ã€‚ |
287 | 288 | ||
288 | (d) å’Œæ ‡å‡†C99类型相åŒçš„类型,在æŸäº›ä¾‹å¤–的情况下。 | 289 | (d) å’Œæ ‡å‡†C99类型相åŒçš„类型,在æŸäº›ä¾‹å¤–的情况下。 |
289 | 290 | ||
290 | 虽然让眼ç›å’Œè„‘ç‹æ¥é€‚åº”æ–°çš„æ ‡å‡†ç±»åž‹æ¯”å¦‚â€œuint32_tâ€ä¸éœ€è¦èŠ±å¾ˆå¤šæ—¶é—´ï¼Œå¯æ˜¯æœ‰äº› | 291 | 虽然让眼ç›å’Œè„‘ç‹æ¥é€‚åº”æ–°çš„æ ‡å‡†ç±»åž‹æ¯”å¦‚ “uint32_t†ä¸éœ€è¦èŠ±å¾ˆå¤šæ—¶é—´ï¼Œå¯æ˜¯æœ‰äº› |
291 | 人ä»ç„¶æ‹’ç»ä½¿ç”¨å®ƒä»¬ã€‚ | 292 | 人ä»ç„¶æ‹’ç»ä½¿ç”¨å®ƒä»¬ã€‚ |
292 | 293 | ||
293 | å› æ¤ï¼ŒLinux特有的ç‰åŒäºŽæ ‡å‡†ç±»åž‹çš„“u8/u16/u32/u64â€ç±»åž‹å’Œå®ƒä»¬çš„æœ‰ç¬¦å·ç±»åž‹æ˜¯è¢« | 294 | å› æ¤ï¼ŒLinux 特有的ç‰åŒäºŽæ ‡å‡†ç±»åž‹çš„ “u8/u16/u32/u64†类型和它们的有符å·ç±»åž‹æ˜¯è¢« |
294 | å…è®¸çš„â€”â€”å°½ç®¡åœ¨ä½ è‡ªå·±çš„æ–°ä»£ç ä¸ï¼Œå®ƒä»¬ä¸æ˜¯å¼ºåˆ¶è¦æ±‚è¦ä½¿ç”¨çš„。 | 295 | å…è®¸çš„â€”â€”å°½ç®¡åœ¨ä½ è‡ªå·±çš„æ–°ä»£ç ä¸ï¼Œå®ƒä»¬ä¸æ˜¯å¼ºåˆ¶è¦æ±‚è¦ä½¿ç”¨çš„。 |
295 | 296 | ||
296 | 当编辑已ç»ä½¿ç”¨äº†æŸä¸ªç±»åž‹é›†çš„å·²æœ‰ä»£ç æ—¶ï¼Œä½ 应该éµå¾ªé‚£äº›ä»£ç ä¸å·²ç»åšå‡ºçš„选择。 | 297 | 当编辑已ç»ä½¿ç”¨äº†æŸä¸ªç±»åž‹é›†çš„å·²æœ‰ä»£ç æ—¶ï¼Œä½ 应该éµå¾ªé‚£äº›ä»£ç ä¸å·²ç»åšå‡ºçš„选择。 |
297 | 298 | ||
298 | (e) å¯ä»¥åœ¨ç”¨æˆ·ç©ºé—´å®‰å…¨ä½¿ç”¨çš„类型。 | 299 | (e) å¯ä»¥åœ¨ç”¨æˆ·ç©ºé—´å®‰å…¨ä½¿ç”¨çš„类型。 |
299 | 300 | ||
300 | 在æŸäº›ç”¨æˆ·ç©ºé—´å¯è§çš„结构体里,我们ä¸èƒ½è¦æ±‚C99类型而且ä¸èƒ½ç”¨ä¸Šé¢æåˆ°çš„“u32†| 301 | 在æŸäº›ç”¨æˆ·ç©ºé—´å¯è§çš„结构体里,我们ä¸èƒ½è¦æ±‚C99类型而且ä¸èƒ½ç”¨ä¸Šé¢æåˆ°çš„ “u32†|
301 | ç±»åž‹ã€‚å› æ¤ï¼Œæˆ‘们在与用户空间共享的所有结构体ä¸ä½¿ç”¨__u32和类似的类型。 | 302 | ç±»åž‹ã€‚å› æ¤ï¼Œæˆ‘们在与用户空间共享的所有结构体ä¸ä½¿ç”¨ __u32 和类似的类型。 |
302 | 303 | ||
303 | å¯èƒ½è¿˜æœ‰å…¶ä»–的情况,ä¸è¿‡åŸºæœ¬çš„规则是永远ä¸è¦ä½¿ç”¨typedef,除éžä½ å¯ä»¥æ˜Žç¡®çš„应用上 | 304 | å¯èƒ½è¿˜æœ‰å…¶ä»–的情况,ä¸è¿‡åŸºæœ¬çš„规则是永远ä¸è¦ä½¿ç”¨ typedef,除éžä½ å¯ä»¥æ˜Žç¡®çš„应用上 |
304 | è¿°æŸä¸ªè§„则ä¸çš„一个。 | 305 | è¿°æŸä¸ªè§„则ä¸çš„一个。 |
305 | 306 | ||
306 | 总的æ¥è¯´ï¼Œå¦‚æžœä¸€ä¸ªæŒ‡é’ˆæˆ–è€…ä¸€ä¸ªç»“æž„ä½“é‡Œçš„å…ƒç´ å¯ä»¥åˆç†çš„è¢«ç›´æŽ¥è®¿é—®åˆ°ï¼Œé‚£ä¹ˆå®ƒä»¬å°±ä¸ | 307 | 总的æ¥è¯´ï¼Œå¦‚æžœä¸€ä¸ªæŒ‡é’ˆæˆ–è€…ä¸€ä¸ªç»“æž„ä½“é‡Œçš„å…ƒç´ å¯ä»¥åˆç†çš„è¢«ç›´æŽ¥è®¿é—®åˆ°ï¼Œé‚£ä¹ˆå®ƒä»¬å°±ä¸ |
307 | 应该是一个typedef。 | 308 | 应该是一个 typedef。 |
308 | 309 | ||
309 | 310 | ||
310 | 第å…ç« ï¼šå‡½æ•° | 311 | 第å…ç« ï¼šå‡½æ•° |
311 | 312 | ||
312 | 函数应该简çŸè€Œæ¼‚亮,并且åªå®Œæˆä¸€ä»¶äº‹æƒ…。函数应该å¯ä»¥ä¸€å±æˆ–è€…ä¸¤å±æ˜¾ç¤ºå®Œï¼ˆæˆ‘们都知 | 313 | 函数应该简çŸè€Œæ¼‚亮,并且åªå®Œæˆä¸€ä»¶äº‹æƒ…。函数应该å¯ä»¥ä¸€å±æˆ–è€…ä¸¤å±æ˜¾ç¤ºå®Œï¼ˆæˆ‘们都知 |
313 | é“ISO/ANSIå±å¹•大尿˜¯80x24),åªåšä¸€ä»¶äº‹æƒ…,而且把它åšå¥½ã€‚ | 314 | é“ ISO/ANSI å±å¹•大尿˜¯ 80x24),åªåšä¸€ä»¶äº‹æƒ…,而且把它åšå¥½ã€‚ |
314 | 315 | ||
315 | ä¸€ä¸ªå‡½æ•°çš„æœ€å¤§é•¿åº¦æ˜¯å’Œè¯¥å‡½æ•°çš„å¤æ‚度和缩进级数æˆåæ¯”çš„ã€‚æ‰€ä»¥ï¼Œå¦‚æžœä½ æœ‰ä¸€ä¸ªç†è®ºä¸Š | 316 | ä¸€ä¸ªå‡½æ•°çš„æœ€å¤§é•¿åº¦æ˜¯å’Œè¯¥å‡½æ•°çš„å¤æ‚度和缩进级数æˆåæ¯”çš„ã€‚æ‰€ä»¥ï¼Œå¦‚æžœä½ æœ‰ä¸€ä¸ªç†è®ºä¸Š |
316 | 很简å•çš„åªæœ‰ä¸€ä¸ªå¾ˆé•¿ï¼ˆä½†æ˜¯ç®€å•)的caseè¯å¥çš„å‡½æ•°ï¼Œè€Œä¸”ä½ éœ€è¦åœ¨æ¯ä¸ªcase里åšå¾ˆå¤šå¾ˆ | 317 | 很简å•çš„åªæœ‰ä¸€ä¸ªå¾ˆé•¿ï¼ˆä½†æ˜¯ç®€å•)的 case è¯å¥çš„å‡½æ•°ï¼Œè€Œä¸”ä½ éœ€è¦åœ¨æ¯ä¸ª case é‡Œåš |
317 | å°çš„äº‹æƒ…ï¼Œè¿™æ ·çš„å‡½æ•°å°½ç®¡å¾ˆé•¿ï¼Œä½†ä¹Ÿæ˜¯å¯ä»¥çš„。 | 318 | 很多很å°çš„äº‹æƒ…ï¼Œè¿™æ ·çš„å‡½æ•°å°½ç®¡å¾ˆé•¿ï¼Œä½†ä¹Ÿæ˜¯å¯ä»¥çš„。 |
318 | 319 | ||
319 | ä¸è¿‡ï¼Œå¦‚æžœä½ æœ‰ä¸€ä¸ªå¤æ‚çš„å‡½æ•°ï¼Œè€Œä¸”ä½ æ€€ç–‘ä¸€ä¸ªå¤©åˆ†ä¸æ˜¯å¾ˆé«˜çš„高ä¸ä¸€å¹´çº§å¦ç”Ÿå¯èƒ½ç”šè‡³ | 320 | ä¸è¿‡ï¼Œå¦‚æžœä½ æœ‰ä¸€ä¸ªå¤æ‚çš„å‡½æ•°ï¼Œè€Œä¸”ä½ æ€€ç–‘ä¸€ä¸ªå¤©åˆ†ä¸æ˜¯å¾ˆé«˜çš„高ä¸ä¸€å¹´çº§å¦ç”Ÿå¯èƒ½ç”šè‡³ |
320 | æžä¸æ¸…æ¥šè¿™ä¸ªå‡½æ•°çš„ç›®çš„ï¼Œä½ åº”è¯¥ä¸¥æ ¼çš„éµå®ˆå‰é¢æåˆ°çš„长度é™åˆ¶ã€‚使用辅助函数,并为之 | 321 | æžä¸æ¸…æ¥šè¿™ä¸ªå‡½æ•°çš„ç›®çš„ï¼Œä½ åº”è¯¥ä¸¥æ ¼çš„éµå®ˆå‰é¢æåˆ°çš„长度é™åˆ¶ã€‚使用辅助函数,并为之 |
321 | å–个具æè¿°æ€§çš„åå—ï¼ˆå¦‚æžœä½ è§‰å¾—å®ƒä»¬çš„æ€§èƒ½å¾ˆé‡è¦çš„è¯ï¼Œå¯ä»¥è®©ç¼–译器内è”å®ƒä»¬ï¼Œè¿™æ ·çš„ | 322 | å–个具æè¿°æ€§çš„åå—ï¼ˆå¦‚æžœä½ è§‰å¾—å®ƒä»¬çš„æ€§èƒ½å¾ˆé‡è¦çš„è¯ï¼Œå¯ä»¥è®©ç¼–译器内è”å®ƒä»¬ï¼Œè¿™æ ·çš„ |
322 | æ•ˆæžœå¾€å¾€ä¼šæ¯”ä½ å†™ä¸€ä¸ªå¤æ‚函数的效果è¦å¥½ã€‚) | 323 | æ•ˆæžœå¾€å¾€ä¼šæ¯”ä½ å†™ä¸€ä¸ªå¤æ‚函数的效果è¦å¥½ã€‚) |
323 | 324 | ||
324 | 函数的å¦å¤–ä¸€ä¸ªè¡¡é‡æ ‡å‡†æ˜¯æœ¬åœ°å˜é‡çš„æ•°é‡ã€‚æ¤æ•°é‡ä¸åº”超过5ï¼10个,å¦åˆ™ä½ 的函数就有 | 325 | 函数的å¦å¤–ä¸€ä¸ªè¡¡é‡æ ‡å‡†æ˜¯æœ¬åœ°å˜é‡çš„æ•°é‡ã€‚æ¤æ•°é‡ä¸åº”超过 5ï¼10 个,å¦åˆ™ä½ 的函数就有 |
325 | é—®é¢˜äº†ã€‚é‡æ–°è€ƒè™‘ä¸€ä¸‹ä½ çš„å‡½æ•°ï¼ŒæŠŠå®ƒåˆ†æ‹†æˆæ›´å°çš„函数。人的大脑一般å¯ä»¥è½»æ¾çš„åŒæ—¶è·Ÿ | 326 | é—®é¢˜äº†ã€‚é‡æ–°è€ƒè™‘ä¸€ä¸‹ä½ çš„å‡½æ•°ï¼ŒæŠŠå®ƒåˆ†æ‹†æˆæ›´å°çš„函数。人的大脑一般å¯ä»¥è½»æ¾çš„åŒæ—¶è·Ÿ |
326 | 踪7个ä¸åŒçš„事物,如果å†å¢žå¤šçš„è¯ï¼Œå°±ä¼šç³Šæ¶‚了。å³ä¾¿ä½ èªé¢–è¿‡äººï¼Œä½ ä¹Ÿå¯èƒ½ä¼šè®°ä¸æ¸…ä½ 2 | 327 | 踪 7 个ä¸åŒçš„事物,如果å†å¢žå¤šçš„è¯ï¼Œå°±ä¼šç³Šæ¶‚了。å³ä¾¿ä½ èªé¢–è¿‡äººï¼Œä½ ä¹Ÿå¯èƒ½ä¼šè®°ä¸æ¸…ä½ |
327 | 个星期å‰åšè¿‡çš„事情。 | 328 | 2 个星期å‰åšè¿‡çš„事情。 |
328 | 329 | ||
329 | åœ¨æºæ–‡ä»¶é‡Œï¼Œä½¿ç”¨ç©ºè¡Œéš”å¼€ä¸åŒçš„函数。如果该函数需è¦è¢«å¯¼å‡ºï¼Œå®ƒçš„EXPORT*å®åº”该紧贴 | 330 | åœ¨æºæ–‡ä»¶é‡Œï¼Œä½¿ç”¨ç©ºè¡Œéš”å¼€ä¸åŒçš„函数。如果该函数需è¦è¢«å¯¼å‡ºï¼Œå®ƒçš„ EXPORT* å®åº”该紧贴 |
330 | 在它的结æŸå¤§æ‹¬å·ä¹‹ä¸‹ã€‚比如: | 331 | 在它的结æŸå¤§æ‹¬å·ä¹‹ä¸‹ã€‚比如: |
331 | 332 | ||
332 | int system_is_up(void) | 333 | int system_is_up(void) |
333 | { | 334 | { |
334 | return system_state == SYSTEM_RUNNING; | 335 | return system_state == SYSTEM_RUNNING; |
335 | } | 336 | } |
336 | EXPORT_SYMBOL(system_is_up); | 337 | EXPORT_SYMBOL(system_is_up); |
337 | 338 | ||
338 | 在函数原型ä¸ï¼ŒåŒ…å«å‡½æ•°å和它们的数æ®ç±»åž‹ã€‚虽然Cè¯è¨€é‡Œæ²¡æœ‰è¿™æ ·çš„è¦æ±‚,在Linux里这 | 339 | 在函数原型ä¸ï¼ŒåŒ…å«å‡½æ•°å和它们的数æ®ç±»åž‹ã€‚虽然Cè¯è¨€é‡Œæ²¡æœ‰è¿™æ ·çš„è¦æ±‚,在 Linux 里这 |
339 | 是æå€¡çš„åšæ³•ï¼Œå› ä¸ºè¿™æ ·å¯ä»¥å¾ˆç®€å•的给读者æä¾›æ›´å¤šçš„æœ‰ä»·å€¼çš„ä¿¡æ¯ã€‚ | 340 | 是æå€¡çš„åšæ³•ï¼Œå› ä¸ºè¿™æ ·å¯ä»¥å¾ˆç®€å•的给读者æä¾›æ›´å¤šçš„æœ‰ä»·å€¼çš„ä¿¡æ¯ã€‚ |
340 | 341 | ||
341 | 342 | ||
342 | ç¬¬ä¸ƒç« ï¼šé›†ä¸çš„函数退出途径 | 343 | ç¬¬ä¸ƒç« ï¼šé›†ä¸çš„函数退出途径 |
343 | 344 | ||
344 | 虽然被æŸäº›äººå£°ç§°å·²ç»è¿‡æ—¶ï¼Œä½†æ˜¯gotoè¯å¥çš„ç‰ä»·ç‰©è¿˜æ˜¯ç»å¸¸è¢«ç¼–è¯‘å™¨æ‰€ä½¿ç”¨ï¼Œå…·ä½“å½¢å¼æ˜¯ | 345 | 虽然被æŸäº›äººå£°ç§°å·²ç»è¿‡æ—¶ï¼Œä½†æ˜¯ goto è¯å¥çš„ç‰ä»·ç‰©è¿˜æ˜¯ç»å¸¸è¢«ç¼–è¯‘å™¨æ‰€ä½¿ç”¨ï¼Œå…·ä½“å½¢å¼æ˜¯ |
345 | æ— æ¡ä»¶è·³è½¬æŒ‡ä»¤ã€‚ | 346 | æ— æ¡ä»¶è·³è½¬æŒ‡ä»¤ã€‚ |
346 | 347 | ||
347 | 当一个函数从多个ä½ç½®é€€å‡ºå¹¶ä¸”需è¦åšä¸€äº›é€šç”¨çš„æ¸…ç†å·¥ä½œçš„æ—¶å€™ï¼Œgotoçš„å¥½å¤„å°±æ˜¾çŽ°å‡ºæ¥ | 348 | 当一个函数从多个ä½ç½®é€€å‡ºï¼Œå¹¶ä¸”需è¦åšä¸€äº›ç±»ä¼¼æ¸…ç†çš„å¸¸è§æ“作时,goto è¯å¥å°±å¾ˆæ–¹ä¾¿äº†ã€‚ |
348 | 了。 | 349 | 如果并ä¸éœ€è¦æ¸…ç†æ“作,那么直接 return å³å¯ã€‚ |
349 | 350 | ||
350 | ç†ç”±æ˜¯ï¼š | 351 | ç†ç”±æ˜¯ï¼š |
351 | 352 | ||
@@ -354,26 +355,37 @@ EXPORT_SYMBOL(system_is_up); | |||
354 | - å¯ä»¥é¿å…由于修改时忘记更新æŸä¸ªå•独的退出点而导致的错误 | 355 | - å¯ä»¥é¿å…由于修改时忘记更新æŸä¸ªå•独的退出点而导致的错误 |
355 | - å‡è½»äº†ç¼–è¯‘å™¨çš„å·¥ä½œï¼Œæ— éœ€åˆ é™¤å†—ä½™ä»£ç ;) | 356 | - å‡è½»äº†ç¼–è¯‘å™¨çš„å·¥ä½œï¼Œæ— éœ€åˆ é™¤å†—ä½™ä»£ç ;) |
356 | 357 | ||
357 | int fun(int a) | 358 | int fun(int a) |
358 | { | 359 | { |
359 | int result = 0; | 360 | int result = 0; |
360 | char *buffer = kmalloc(SIZE); | 361 | char *buffer; |
361 | 362 | ||
362 | if (buffer == NULL) | 363 | buffer = kmalloc(SIZE, GFP_KERNEL); |
363 | return -ENOMEM; | 364 | if (!buffer) |
364 | 365 | return -ENOMEM; | |
365 | if (condition1) { | 366 | |
366 | while (loop1) { | 367 | if (condition1) { |
367 | ... | 368 | while (loop1) { |
369 | ... | ||
370 | } | ||
371 | result = 1; | ||
372 | goto out_buffer; | ||
368 | } | 373 | } |
369 | result = 1; | 374 | ... |
370 | goto out; | 375 | out_buffer: |
376 | kfree(buffer); | ||
377 | return result; | ||
371 | } | 378 | } |
372 | ... | 379 | |
373 | out: | 380 | ä¸€ä¸ªéœ€è¦æ³¨æ„的常è§é”™è¯¯æ˜¯â€œä¸€ä¸ª err 错误â€ï¼Œå°±åƒè¿™æ ·ï¼š |
374 | kfree(buffer); | 381 | |
375 | return result; | 382 | err: |
376 | } | 383 | kfree(foo->bar); |
384 | kfree(foo); | ||
385 | return ret; | ||
386 | |||
387 | 这段代ç 的错误是,在æŸäº›é€€å‡ºè·¯å¾„上 “foo†是 NULL。通常情况下,通过把它分离æˆä¸¤ä¸ª | ||
388 | é”™è¯¯æ ‡ç¾ â€œerr_bar:†和 “err_foo:†æ¥ä¿®å¤è¿™ä¸ªé”™è¯¯ã€‚ | ||
377 | 389 | ||
378 | ç¬¬å…«ç« ï¼šæ³¨é‡Š | 390 | ç¬¬å…«ç« ï¼šæ³¨é‡Š |
379 | 391 | ||
@@ -386,10 +398,10 @@ out: | |||
386 | åŠ å¤ªå¤šã€‚ä½ åº”è¯¥åšçš„,是把注释放在函数的头部,告诉人们它åšäº†ä»€ä¹ˆï¼Œä¹Ÿå¯ä»¥åŠ ä¸Šå®ƒåšè¿™ | 398 | åŠ å¤ªå¤šã€‚ä½ åº”è¯¥åšçš„,是把注释放在函数的头部,告诉人们它åšäº†ä»€ä¹ˆï¼Œä¹Ÿå¯ä»¥åŠ ä¸Šå®ƒåšè¿™ |
387 | äº›äº‹æƒ…çš„åŽŸå› ã€‚ | 399 | äº›äº‹æƒ…çš„åŽŸå› ã€‚ |
388 | 400 | ||
389 | å½“æ³¨é‡Šå†…æ ¸API函数时,请使用kernel-docæ ¼å¼ã€‚请看 | 401 | å½“æ³¨é‡Šå†…æ ¸API函数时,请使用 kernel-doc æ ¼å¼ã€‚请看 |
390 | Documentation/kernel-doc-nano-HOWTO.txtå’Œscripts/kernel-doc以获得详细信æ¯ã€‚ | 402 | Documentation/kernel-doc-nano-HOWTO.txtå’Œscripts/kernel-doc 以获得详细信æ¯ã€‚ |
391 | 403 | ||
392 | Linuxçš„æ³¨é‡Šé£Žæ ¼æ˜¯C89“/* ... */â€é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨C99é£Žæ ¼â€œ// ...â€æ³¨é‡Šã€‚ | 404 | Linuxçš„æ³¨é‡Šé£Žæ ¼æ˜¯ C89 “/* ... */â€ é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨ C99 é£Žæ ¼ “// ...†注释。 |
393 | 405 | ||
394 | é•¿ï¼ˆå¤šè¡Œï¼‰çš„é¦–é€‰æ³¨é‡Šé£Žæ ¼æ˜¯ï¼š | 406 | é•¿ï¼ˆå¤šè¡Œï¼‰çš„é¦–é€‰æ³¨é‡Šé£Žæ ¼æ˜¯ï¼š |
395 | 407 | ||
@@ -402,6 +414,15 @@ Linuxçš„æ³¨é‡Šé£Žæ ¼æ˜¯C89“/* ... */â€é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨C99é£Žæ ¼â€œ// ... | |||
402 | * with beginning and ending almost-blank lines. | 414 | * with beginning and ending almost-blank lines. |
403 | */ | 415 | */ |
404 | 416 | ||
417 | 对于在 net/ å’Œ drivers/net/ çš„æ–‡ä»¶ï¼Œé¦–é€‰çš„é•¿ï¼ˆå¤šè¡Œï¼‰æ³¨é‡Šé£Žæ ¼æœ‰äº›ä¸åŒã€‚ | ||
418 | |||
419 | /* The preferred comment style for files in net/ and drivers/net | ||
420 | * looks like this. | ||
421 | * | ||
422 | * It is nearly the same as the generally preferred comment style, | ||
423 | * but there is no initial almost-blank line. | ||
424 | */ | ||
425 | |||
405 | 注释数æ®ä¹Ÿæ˜¯å¾ˆé‡è¦çš„,ä¸ç®¡æ˜¯åŸºæœ¬ç±»åž‹è¿˜æ˜¯è¡ç”Ÿç±»åž‹ã€‚为了方便实现这一点,æ¯ä¸€è¡Œåº”åª | 426 | 注释数æ®ä¹Ÿæ˜¯å¾ˆé‡è¦çš„,ä¸ç®¡æ˜¯åŸºæœ¬ç±»åž‹è¿˜æ˜¯è¡ç”Ÿç±»åž‹ã€‚为了方便实现这一点,æ¯ä¸€è¡Œåº”åª |
406 | 声明一个数æ®ï¼ˆä¸è¦ä½¿ç”¨é€—å·æ¥ä¸€æ¬¡å£°æ˜Žå¤šä¸ªæ•°æ®ï¼‰ã€‚è¿™æ ·ä½ å°±æœ‰ç©ºé—´æ¥ä¸ºæ¯ä¸ªæ•°æ®å†™ä¸€æ®µ | 427 | 声明一个数æ®ï¼ˆä¸è¦ä½¿ç”¨é€—å·æ¥ä¸€æ¬¡å£°æ˜Žå¤šä¸ªæ•°æ®ï¼‰ã€‚è¿™æ ·ä½ å°±æœ‰ç©ºé—´æ¥ä¸ºæ¯ä¸ªæ•°æ®å†™ä¸€æ®µ |
407 | å°æ³¨é‡Šæ¥è§£é‡Šå®ƒä»¬çš„用途了。 | 428 | å°æ³¨é‡Šæ¥è§£é‡Šå®ƒä»¬çš„用途了。 |
@@ -409,49 +430,63 @@ Linuxçš„æ³¨é‡Šé£Žæ ¼æ˜¯C89“/* ... */â€é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨C99é£Žæ ¼â€œ// ... | |||
409 | 430 | ||
410 | 第ä¹ç« ï¼šä½ å·²ç»æŠŠäº‹æƒ…å¼„ç³Ÿäº† | 431 | 第ä¹ç« ï¼šä½ å·²ç»æŠŠäº‹æƒ…å¼„ç³Ÿäº† |
411 | 432 | ||
412 | è¿™æ²¡ä»€ä¹ˆï¼Œæˆ‘ä»¬éƒ½æ˜¯è¿™æ ·ã€‚å¯èƒ½ä½ 的使用了很长时间Unix的朋å‹å·²ç»å‘Šè¯‰ä½ “GNU emacsâ€èƒ½ | 433 | è¿™æ²¡ä»€ä¹ˆï¼Œæˆ‘ä»¬éƒ½æ˜¯è¿™æ ·ã€‚å¯èƒ½ä½ 的使用了很长时间 Unix 的朋å‹å·²ç»å‘Šè¯‰ä½ “GNU emacs†能 |
413 | è‡ªåŠ¨å¸®ä½ æ ¼å¼åŒ–Cæºä»£ç ï¼Œè€Œä¸”ä½ ä¹Ÿæ³¨æ„åˆ°äº†ï¼Œç¡®å®žæ˜¯è¿™æ ·ï¼Œä¸è¿‡å®ƒæ‰€ä½¿ç”¨çš„默认值和我们 | 434 | è‡ªåŠ¨å¸®ä½ æ ¼å¼åŒ– C æºä»£ç ï¼Œè€Œä¸”ä½ ä¹Ÿæ³¨æ„åˆ°äº†ï¼Œç¡®å®žæ˜¯è¿™æ ·ï¼Œä¸è¿‡å®ƒæ‰€ä½¿ç”¨çš„默认值和我们 |
414 | 想è¦çš„ç›¸åŽ»ç”šè¿œï¼ˆå®žé™…ä¸Šï¼Œç”šè‡³æ¯”éšæœºæ‰“的还è¦å·®â€”â€”æ— æ•°ä¸ªçŒ´å在GNU emacsé‡Œæ‰“å—æ°¸è¿œä¸ | 435 | 想è¦çš„ç›¸åŽ»ç”šè¿œï¼ˆå®žé™…ä¸Šï¼Œç”šè‡³æ¯”éšæœºæ‰“的还è¦å·®â€”â€”æ— æ•°ä¸ªçŒ´å在 GNU emacs é‡Œæ‰“å—æ°¸è¿œä¸ |
415 | ä¼šåˆ›é€ å‡ºä¸€ä¸ªå¥½ç¨‹åºï¼‰ï¼ˆè¯‘注:请å‚考Infinite Monkey Theorem) | 436 | ä¼šåˆ›é€ å‡ºä¸€ä¸ªå¥½ç¨‹åºï¼‰ï¼ˆè¯‘注:请å‚考 Infinite Monkey Theorem) |
416 | 437 | ||
417 | æ‰€ä»¥ä½ è¦ä¹ˆæ”¾å¼ƒGNU emacs,è¦ä¹ˆæ”¹å˜å®ƒè®©å®ƒä½¿ç”¨æ›´åˆç†çš„设定。è¦é‡‡ç”¨åŽä¸€ä¸ªæ–¹æ¡ˆï¼Œä½ å¯ | 438 | æ‰€ä»¥ä½ è¦ä¹ˆæ”¾å¼ƒ GNU emacs,è¦ä¹ˆæ”¹å˜å®ƒè®©å®ƒä½¿ç”¨æ›´åˆç†çš„设定。è¦é‡‡ç”¨åŽä¸€ä¸ªæ–¹æ¡ˆï¼Œä½ å¯ |
418 | 以把下é¢è¿™æ®µç²˜è´´åˆ°ä½ çš„.emacs文件里。 | 439 | 以把下é¢è¿™æ®µç²˜è´´åˆ°ä½ çš„ .emacs 文件里。 |
419 | 440 | ||
420 | (defun linux-c-mode () | 441 | (defun c-lineup-arglist-tabs-only (ignored) |
421 | "C mode with adjusted defaults for use with the Linux kernel." | 442 | "Line up argument lists by tabs, not spaces" |
422 | (interactive) | 443 | (let* ((anchor (c-langelem-pos c-syntactic-element)) |
423 | (c-mode) | 444 | (column (c-langelem-2nd-pos c-syntactic-element)) |
424 | (c-set-style "K&R") | 445 | (offset (- (1+ column) anchor)) |
425 | (setq tab-width 8) | 446 | (steps (floor offset c-basic-offset))) |
426 | (setq indent-tabs-mode t) | 447 | (* (max steps 1) |
427 | (setq c-basic-offset 8)) | 448 | c-basic-offset))) |
428 | 449 | ||
429 | è¿™æ ·å°±å®šä¹‰äº†M-x linux-c-modeå‘½ä»¤ã€‚å½“ä½ hack一个模å—çš„æ—¶å€™ï¼Œå¦‚æžœä½ æŠŠå—符串 | 450 | (add-hook 'c-mode-common-hook |
430 | -*- linux-c -*-放在头两行的æŸä¸ªä½ç½®ï¼Œè¿™ä¸ªæ¨¡å¼å°†ä¼šè¢«è‡ªåŠ¨è°ƒç”¨ã€‚å¦‚æžœä½ å¸Œæœ›åœ¨ä½ ä¿®æ”¹ | 451 | (lambda () |
431 | /usr/src/linuxé‡Œçš„æ–‡ä»¶æ—¶é”æœ¯èˆ¬è‡ªåŠ¨æ‰“å¼€linux-c-modeçš„è¯ï¼Œä½ 也å¯èƒ½éœ€è¦æ·»åŠ | 452 | ;; Add kernel style |
432 | 453 | (c-add-style | |
433 | (setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode) | 454 | "linux-tabs-only" |
434 | auto-mode-alist)) | 455 | '("linux" (c-offsets-alist |
435 | 456 | (arglist-cont-nonempty | |
436 | åˆ°ä½ çš„.emacs文件里。 | 457 | c-lineup-gcc-asm-reg |
437 | 458 | c-lineup-arglist-tabs-only)))))) | |
438 | ä¸è¿‡å°±ç®—ä½ å°è¯•让emacsæ£ç¡®çš„æ ¼å¼åŒ–代ç å¤±è´¥äº†ï¼Œä¹Ÿå¹¶ä¸æ„味ç€ä½ 失去了一切:还å¯ä»¥ç”¨â€œ | 459 | |
439 | indentâ€ã€‚ | 460 | (add-hook 'c-mode-hook |
440 | 461 | (lambda () | |
441 | ä¸è¿‡ï¼ŒGNU indent也有和GNU emacsä¸€æ ·æœ‰é—®é¢˜çš„è®¾å®šï¼Œæ‰€ä»¥ä½ éœ€è¦ç»™å®ƒä¸€äº›å‘½ä»¤é€‰é¡¹ã€‚ä¸ | 462 | (let ((filename (buffer-file-name))) |
442 | 过,这还ä¸ç®—å¤ªç³Ÿç³•ï¼Œå› ä¸ºå°±ç®—æ˜¯GNU indent的作者也认åŒK&Rçš„æƒå¨æ€§ï¼ˆGNUçš„äººå¹¶ä¸æ˜¯å | 463 | ;; Enable kernel mode for the appropriate files |
443 | äººï¼Œä»–ä»¬åªæ˜¯åœ¨è¿™ä¸ªé—®é¢˜ä¸Šè¢«ä¸¥é‡çš„è¯¯å¯¼äº†ï¼‰ï¼Œæ‰€ä»¥ä½ åªè¦ç»™indent指定选项“-kr -i8†| 464 | (when (and filename |
444 | (代表“K&R,8个å—符缩进â€ï¼‰ï¼Œæˆ–者使用“scripts/Lindentâ€ï¼Œè¿™æ ·å°±å¯ä»¥ä»¥æœ€æ—¶é«¦çš„æ–¹å¼ | 465 | (string-match (expand-file-name "~/src/linux-trees") |
466 | filename)) | ||
467 | (setq indent-tabs-mode t) | ||
468 | (setq show-trailing-whitespace t) | ||
469 | (c-set-style "linux-tabs-only"))))) | ||
470 | |||
471 | 这会让 emacs 在 ~/src/linux-trees 目录下的 C æºæ–‡ä»¶èŽ·å¾—æ›´å¥½çš„å†…æ ¸ä»£ç é£Žæ ¼ã€‚ | ||
472 | |||
473 | ä¸è¿‡å°±ç®—ä½ å°è¯•让 emacs æ£ç¡®çš„æ ¼å¼åŒ–代ç å¤±è´¥äº†ï¼Œä¹Ÿå¹¶ä¸æ„味ç€ä½ 失去了一切:还å¯ä»¥ç”¨ | ||
474 | “indentâ€ã€‚ | ||
475 | |||
476 | ä¸è¿‡ï¼ŒGNU indent 也有和 GNU emacs ä¸€æ ·æœ‰é—®é¢˜çš„è®¾å®šï¼Œæ‰€ä»¥ä½ éœ€è¦ç»™å®ƒä¸€äº›å‘½ä»¤é€‰é¡¹ã€‚ä¸ | ||
477 | 过,这还ä¸ç®—å¤ªç³Ÿç³•ï¼Œå› ä¸ºå°±ç®—æ˜¯ GNU indent çš„ä½œè€…ä¹Ÿè®¤åŒ K&R çš„æƒå¨æ€§ï¼ˆGNU çš„äººå¹¶ä¸æ˜¯ | ||
478 | åäººï¼Œä»–ä»¬åªæ˜¯åœ¨è¿™ä¸ªé—®é¢˜ä¸Šè¢«ä¸¥é‡çš„è¯¯å¯¼äº†ï¼‰ï¼Œæ‰€ä»¥ä½ åªè¦ç»™ indent 指定选项 “-kr -i8†| ||
479 | (代表 “K&R,8 个å—符缩进â€ï¼‰ï¼Œæˆ–者使用 “scripts/Lindentâ€ï¼Œè¿™æ ·å°±å¯ä»¥ä»¥æœ€æ—¶é«¦çš„æ–¹å¼ | ||
445 | 缩进æºä»£ç 。 | 480 | 缩进æºä»£ç 。 |
446 | 481 | ||
447 | “indentâ€æœ‰å¾ˆå¤šé€‰é¡¹ï¼Œç‰¹åˆ«æ˜¯é‡æ–°æ ¼å¼åŒ–æ³¨é‡Šçš„æ—¶å€™ï¼Œä½ å¯èƒ½éœ€è¦çœ‹ä¸€ä¸‹å®ƒçš„æ‰‹å†Œé¡µã€‚ä¸è¿‡ | 482 | “indentâ€ æœ‰å¾ˆå¤šé€‰é¡¹ï¼Œç‰¹åˆ«æ˜¯é‡æ–°æ ¼å¼åŒ–æ³¨é‡Šçš„æ—¶å€™ï¼Œä½ å¯èƒ½éœ€è¦çœ‹ä¸€ä¸‹å®ƒçš„æ‰‹å†Œé¡µã€‚ä¸è¿‡ |
448 | è®°ä½ï¼šâ€œindentâ€ä¸èƒ½ä¿®æ£åçš„ç¼–ç¨‹ä¹ æƒ¯ã€‚ | 483 | è®°ä½ï¼šâ€œindent†ä¸èƒ½ä¿®æ£åçš„ç¼–ç¨‹ä¹ æƒ¯ã€‚ |
449 | 484 | ||
450 | 485 | ||
451 | 第åç« ï¼šKconfigé…置文件 | 486 | 第åç« ï¼šKconfig é…置文件 |
452 | 487 | ||
453 | 对于é布æºç æ ‘çš„æ‰€æœ‰Kconfig*é…置文件æ¥è¯´ï¼Œå®ƒä»¬ç¼©è¿›æ–¹å¼ä¸ŽC代ç 相比有所ä¸åŒã€‚紧挨 | 488 | 对于é布æºç æ ‘çš„æ‰€æœ‰ Kconfig* é…置文件æ¥è¯´ï¼Œå®ƒä»¬ç¼©è¿›æ–¹å¼ä¸Ž C 代ç 相比有所ä¸åŒã€‚紧挨 |
454 | 在“configâ€å®šä¹‰ä¸‹é¢çš„行缩进一个制表符,帮助信æ¯åˆ™å†å¤šç¼©è¿›2ä¸ªç©ºæ ¼ã€‚æ¯”å¦‚ï¼š | 489 | 在 “config†定义下é¢çš„行缩进一个制表符,帮助信æ¯åˆ™å†å¤šç¼©è¿› 2 ä¸ªç©ºæ ¼ã€‚æ¯”å¦‚ï¼š |
455 | 490 | ||
456 | config AUDIT | 491 | config AUDIT |
457 | bool "Auditing support" | 492 | bool "Auditing support" |
@@ -470,7 +505,7 @@ config ADFS_FS_RW | |||
470 | depends on ADFS_FS | 505 | depends on ADFS_FS |
471 | ... | 506 | ... |
472 | 507 | ||
473 | è¦æŸ¥çœ‹é…置文件的完整文档,请看Documentation/kbuild/kconfig-language.txt。 | 508 | è¦æŸ¥çœ‹é…置文件的完整文档,请看 Documentation/kbuild/kconfig-language.txt。 |
474 | 509 | ||
475 | 510 | ||
476 | 第åä¸€ç« ï¼šæ•°æ®ç»“æž„ | 511 | 第åä¸€ç« ï¼šæ•°æ®ç»“æž„ |
@@ -489,11 +524,11 @@ config ADFS_FS_RW | |||
489 | 很多数æ®ç»“构实际上有2级引用计数,它们通常有ä¸åŒâ€œç±»â€çš„用户。å类计数器统计å类用 | 524 | 很多数æ®ç»“构实际上有2级引用计数,它们通常有ä¸åŒâ€œç±»â€çš„用户。å类计数器统计å类用 |
490 | 户的数é‡ï¼Œæ¯å½“å类计数器å‡è‡³é›¶æ—¶ï¼Œå…¨å±€è®¡æ•°å™¨å‡ä¸€ã€‚ | 525 | 户的数é‡ï¼Œæ¯å½“å类计数器å‡è‡³é›¶æ—¶ï¼Œå…¨å±€è®¡æ•°å™¨å‡ä¸€ã€‚ |
491 | 526 | ||
492 | è¿™ç§â€œå¤šçº§å¼•用计数â€çš„例åå¯ä»¥åœ¨å†…å˜ç®¡ç†ï¼ˆâ€œstruct mm_structâ€ï¼šmm_userså’Œmm_count) | 527 | è¿™ç§â€œå¤šçº§å¼•用计数â€çš„例åå¯ä»¥åœ¨å†…å˜ç®¡ç†ï¼ˆâ€œstruct mm_structâ€ï¼šmm_users å’Œ mm_count) |
493 | 和文件系统(“struct super_blockâ€ï¼šs_countå’Œs_activeï¼‰ä¸æ‰¾åˆ°ã€‚ | 528 | 和文件系统(“struct super_blockâ€ï¼šs_countå’Œs_activeï¼‰ä¸æ‰¾åˆ°ã€‚ |
494 | 529 | ||
495 | è®°ä½ï¼šå¦‚æžœå¦ä¸€ä¸ªæ‰§è¡Œçº¿ç´¢å¯ä»¥æ‰¾åˆ°ä½ 的数æ®ç»“构,但是这个数æ®ç»“构没有引用计数器,这 | 530 | è®°ä½ï¼šå¦‚æžœå¦ä¸€ä¸ªæ‰§è¡Œçº¿ç´¢å¯ä»¥æ‰¾åˆ°ä½ 的数æ®ç»“构,但是这个数æ®ç»“构没有引用计数器,这 |
496 | é‡Œå‡ ä¹Žè‚¯å®šæ˜¯ä¸€ä¸ªbug。 | 531 | é‡Œå‡ ä¹Žè‚¯å®šæ˜¯ä¸€ä¸ª bug。 |
497 | 532 | ||
498 | 533 | ||
499 | 第åäºŒç« ï¼šå®ï¼Œæžšä¸¾å’ŒRTL | 534 | 第åäºŒç« ï¼šå®ï¼Œæžšä¸¾å’ŒRTL |
@@ -508,102 +543,128 @@ config ADFS_FS_RW | |||
508 | 543 | ||
509 | 一般的,如果能写æˆå†…è”函数就ä¸è¦å†™æˆåƒå‡½æ•°çš„å®ã€‚ | 544 | 一般的,如果能写æˆå†…è”函数就ä¸è¦å†™æˆåƒå‡½æ•°çš„å®ã€‚ |
510 | 545 | ||
511 | 嫿œ‰å¤šä¸ªè¯å¥çš„å®åº”该被包å«åœ¨ä¸€ä¸ªdo-while代ç å—里: | 546 | 嫿œ‰å¤šä¸ªè¯å¥çš„å®åº”该被包å«åœ¨ä¸€ä¸ª do-while 代ç å—里: |
512 | 547 | ||
513 | #define macrofun(a, b, c) \ | 548 | #define macrofun(a, b, c) \ |
514 | do { \ | 549 | do { \ |
515 | if (a == 5) \ | 550 | if (a == 5) \ |
516 | do_this(b, c); \ | 551 | do_this(b, c); \ |
517 | } while (0) | 552 | } while (0) |
518 | 553 | ||
519 | 使用å®çš„æ—¶å€™åº”é¿å…的事情: | 554 | 使用å®çš„æ—¶å€™åº”é¿å…的事情: |
520 | 555 | ||
521 | 1) å½±å“æŽ§åˆ¶æµç¨‹çš„å®ï¼š | 556 | 1) å½±å“æŽ§åˆ¶æµç¨‹çš„å®ï¼š |
522 | 557 | ||
523 | #define FOO(x) \ | 558 | #define FOO(x) \ |
524 | do { \ | 559 | do { \ |
525 | if (blah(x) < 0) \ | 560 | if (blah(x) < 0) \ |
526 | return -EBUGGERED; \ | 561 | return -EBUGGERED; \ |
527 | } while(0) | 562 | } while (0) |
528 | 563 | ||
529 | éžå¸¸ä¸å¥½ã€‚它看起æ¥åƒä¸€ä¸ªå‡½æ•°ï¼Œä¸è¿‡å´èƒ½å¯¼è‡´â€œè°ƒç”¨â€å®ƒçš„函数退出;ä¸è¦æ‰“乱读者大脑里 | 564 | éžå¸¸ä¸å¥½ã€‚它看起æ¥åƒä¸€ä¸ªå‡½æ•°ï¼Œä¸è¿‡å´èƒ½å¯¼è‡´â€œè°ƒç”¨â€å®ƒçš„函数退出;ä¸è¦æ‰“乱读者大脑里 |
530 | çš„è¯æ³•分æžå™¨ã€‚ | 565 | çš„è¯æ³•分æžå™¨ã€‚ |
531 | 566 | ||
532 | 2) ä¾èµ–于一个固定åå—的本地å˜é‡çš„å®ï¼š | 567 | 2) ä¾èµ–于一个固定åå—的本地å˜é‡çš„å®ï¼š |
533 | 568 | ||
534 | #define FOO(val) bar(index, val) | 569 | #define FOO(val) bar(index, val) |
535 | 570 | ||
536 | å¯èƒ½çœ‹èµ·æ¥åƒæ˜¯ä¸ªä¸é”™çš„东西,ä¸è¿‡å®ƒéžå¸¸å®¹æ˜“把读代ç 的人æžç³Šæ¶‚ï¼Œè€Œä¸”å®¹æ˜“å¯¼è‡´çœ‹èµ·æ¥ | 571 | å¯èƒ½çœ‹èµ·æ¥åƒæ˜¯ä¸ªä¸é”™çš„东西,ä¸è¿‡å®ƒéžå¸¸å®¹æ˜“把读代ç 的人æžç³Šæ¶‚ï¼Œè€Œä¸”å®¹æ˜“å¯¼è‡´çœ‹èµ·æ¥ |
537 | ä¸ç›¸å…³çš„æ”¹åЍ另æ¥é”™è¯¯ã€‚ | 572 | ä¸ç›¸å…³çš„æ”¹åЍ另æ¥é”™è¯¯ã€‚ |
538 | 573 | ||
539 | 3) ä½œä¸ºå·¦å€¼çš„å¸¦å‚æ•°çš„å®ï¼š FOO(x) = y;如果有人把FOOå˜æˆä¸€ä¸ªå†…è”函数的è¯ï¼Œè¿™ç§ç”¨ | 574 | 3) ä½œä¸ºå·¦å€¼çš„å¸¦å‚æ•°çš„å®ï¼š FOO(x) = y;如果有人把 FOO å˜æˆä¸€ä¸ªå†…è”函数的è¯ï¼Œè¿™ç§ç”¨ |
540 | 法就会出错了。 | 575 | 法就会出错了。 |
541 | 576 | ||
542 | 4) 忘记了优先级:使用表达å¼å®šä¹‰å¸¸é‡çš„å®å¿…须将表达å¼ç½®äºŽä¸€å¯¹å°æ‹¬å·ä¹‹å†…ã€‚å¸¦å‚æ•°çš„ | 577 | 4) 忘记了优先级:使用表达å¼å®šä¹‰å¸¸é‡çš„å®å¿…须将表达å¼ç½®äºŽä¸€å¯¹å°æ‹¬å·ä¹‹å†…ã€‚å¸¦å‚æ•°çš„ |
543 | å®ä¹Ÿè¦æ³¨æ„æ¤ç±»é—®é¢˜ã€‚ | 578 | å®ä¹Ÿè¦æ³¨æ„æ¤ç±»é—®é¢˜ã€‚ |
544 | 579 | ||
545 | #define CONSTANT 0x4000 | 580 | #define CONSTANT 0x4000 |
546 | #define CONSTEXP (CONSTANT | 3) | 581 | #define CONSTEXP (CONSTANT | 3) |
582 | |||
583 | 5) 在å®é‡Œå®šä¹‰ç±»ä¼¼å‡½æ•°çš„æœ¬åœ°å˜é‡æ—¶å‘½å冲çªï¼š | ||
547 | 584 | ||
548 | cpp手册对å®çš„讲解很详细。Gcc internals手册也详细讲解了RTL(译注:register | 585 | #define FOO(x) \ |
586 | ({ \ | ||
587 | typeof(x) ret; \ | ||
588 | ret = calc_ret(x); \ | ||
589 | (ret); \ | ||
590 | }) | ||
591 | |||
592 | ret 是本地å˜é‡çš„通用åå— - __foo_ret æ›´ä¸å®¹æ˜“与一个已å˜åœ¨çš„å˜é‡å†²çªã€‚ | ||
593 | |||
594 | cpp 手册对å®çš„讲解很详细。gcc internals 手册也详细讲解了 RTL(译注:register | ||
549 | transfer languageï¼‰ï¼Œå†…æ ¸é‡Œçš„æ±‡ç¼–è¯è¨€ç»å¸¸ç”¨åˆ°å®ƒã€‚ | 595 | transfer languageï¼‰ï¼Œå†…æ ¸é‡Œçš„æ±‡ç¼–è¯è¨€ç»å¸¸ç”¨åˆ°å®ƒã€‚ |
550 | 596 | ||
551 | 597 | ||
552 | 第åä¸‰ç« ï¼šæ‰“å°å†…æ ¸æ¶ˆæ¯ | 598 | 第åä¸‰ç« ï¼šæ‰“å°å†…æ ¸æ¶ˆæ¯ |
553 | 599 | ||
554 | å†…æ ¸å¼€å‘者应该是å—过良好教育的。请一定注æ„å†…æ ¸ä¿¡æ¯çš„æ‹¼å†™ï¼Œä»¥ç»™äººä»¥å¥½çš„å°è±¡ã€‚ä¸è¦ | 600 | å†…æ ¸å¼€å‘者应该是å—过良好教育的。请一定注æ„å†…æ ¸ä¿¡æ¯çš„æ‹¼å†™ï¼Œä»¥ç»™äººä»¥å¥½çš„å°è±¡ã€‚ä¸è¦ |
555 | 用ä¸è§„范的å•è¯æ¯”如“dontâ€ï¼Œè€Œè¦ç”¨â€œdo notâ€æˆ–者“don'tâ€ã€‚ä¿è¯è¿™äº›ä¿¡æ¯ç®€å•ã€æ˜Žäº†ã€æ— | 601 | 用ä¸è§„范的å•è¯æ¯”如 “dontâ€ï¼Œè€Œè¦ç”¨ “do notâ€æˆ–者 “don'tâ€ã€‚ä¿è¯è¿™äº›ä¿¡æ¯ç®€å•ã€æ˜Žäº†ã€ |
556 | æ§ä¹‰ã€‚ | 602 | æ— æ§ä¹‰ã€‚ |
557 | 603 | ||
558 | å†…æ ¸ä¿¡æ¯ä¸å¿…以å¥å·ï¼ˆè¯‘注:英文å¥å·ï¼Œå³ç‚¹ï¼‰ç»“æŸã€‚ | 604 | å†…æ ¸ä¿¡æ¯ä¸å¿…以å¥å·ï¼ˆè¯‘注:英文å¥å·ï¼Œå³ç‚¹ï¼‰ç»“æŸã€‚ |
559 | 605 | ||
560 | åœ¨å°æ‹¬å·é‡Œæ‰“å°æ•°å—(%d)没有任何价值,应该é¿å…è¿™æ ·åšã€‚ | 606 | åœ¨å°æ‹¬å·é‡Œæ‰“å°æ•°å— (%d) 没有任何价值,应该é¿å…è¿™æ ·åšã€‚ |
561 | 607 | ||
562 | <linux/device.h>里有一些驱动模型诊æ–å®ï¼Œä½ 应该使用它们,以确ä¿ä¿¡æ¯å¯¹åº”于æ£ç¡®çš„ | 608 | <linux/device.h> 里有一些驱动模型诊æ–å®ï¼Œä½ 应该使用它们,以确ä¿ä¿¡æ¯å¯¹åº”于æ£ç¡®çš„ |
563 | è®¾å¤‡å’Œé©±åŠ¨ï¼Œå¹¶ä¸”è¢«æ ‡è®°äº†æ£ç¡®çš„æ¶ˆæ¯çº§åˆ«ã€‚è¿™äº›å®æœ‰ï¼šdev_err(), dev_warn(), | 609 | è®¾å¤‡å’Œé©±åŠ¨ï¼Œå¹¶ä¸”è¢«æ ‡è®°äº†æ£ç¡®çš„æ¶ˆæ¯çº§åˆ«ã€‚è¿™äº›å®æœ‰ï¼šdev_err(),dev_warn(), |
564 | dev_info()ç‰ç‰ã€‚对于那些ä¸å’ŒæŸä¸ªç‰¹å®šè®¾å¤‡ç›¸å…³è¿žçš„ä¿¡æ¯ï¼Œ<linux/kernel.h>定义了 | 610 | dev_info() ç‰ç‰ã€‚对于那些ä¸å’ŒæŸä¸ªç‰¹å®šè®¾å¤‡ç›¸å…³è¿žçš„ä¿¡æ¯ï¼Œ<linux/printk.h> 定义了 |
565 | pr_debug()和pr_info()。 | 611 | pr_notice(),pr_info(),pr_warn(),pr_err() 和其他。 |
566 | 612 | ||
567 | 写出好的调试信æ¯å¯ä»¥æ˜¯ä¸€ä¸ªå¾ˆå¤§çš„æŒ‘æˆ˜ï¼›å½“ä½ å†™å‡ºæ¥ä¹‹åŽï¼Œè¿™äº›ä¿¡æ¯åœ¨è¿œç¨‹é™¤é”™çš„æ—¶å€™ | 613 | 写出好的调试信æ¯å¯ä»¥æ˜¯ä¸€ä¸ªå¾ˆå¤§çš„æŒ‘æˆ˜ï¼›ä¸€æ—¦ä½ å†™å‡ºåŽï¼Œè¿™äº›ä¿¡æ¯åœ¨è¿œç¨‹é™¤é”™æ—¶èƒ½æä¾›æžå¤§ |
568 | 就会æˆä¸ºæžå¤§çš„帮助。当DEBUGç¬¦å·æ²¡æœ‰è¢«å®šä¹‰çš„æ—¶å€™ï¼Œè¿™äº›ä¿¡æ¯ä¸åº”è¯¥è¢«ç¼–è¯‘è¿›å†…æ ¸é‡Œ | 614 | 的帮助。然而打å°è°ƒè¯•ä¿¡æ¯çš„å¤„ç†æ–¹å¼åŒæ‰“å°éžè°ƒè¯•ä¿¡æ¯ä¸åŒã€‚å…¶ä»– pr_XXX() å‡½æ•°èƒ½æ— æ¡ä»¶åœ° |
569 | (也就是说,默认地,它们ä¸åº”该被包å«åœ¨å†…ï¼‰ã€‚å¦‚æžœä½ ä½¿ç”¨dev_dbg()或者pr_debug(), | 615 | 打å°ï¼Œpr_debug() å´ä¸ï¼›é»˜è®¤æƒ…况下它ä¸ä¼šè¢«ç¼–译,除éžå®šä¹‰äº† DEBUG 或设定了 |
570 | 就能自动达到这个效果。很多å系统拥有Kconfig选项æ¥å¯ç”¨-DDEBUG。还有一个相关的惯例 | 616 | CONFIG_DYNAMIC_DEBUGã€‚å®žé™…è¿™åŒæ ·æ˜¯ä¸ºäº† dev_dbg(),一个相关约定是在一个已ç»å¼€å¯äº† |
571 | 是使用VERBOSE_DEBUGæ¥æ·»åŠ dev_vdbg()消æ¯åˆ°é‚£äº›å·²ç»ç”±DEBUGå¯ç”¨çš„æ¶ˆæ¯ä¹‹ä¸Šã€‚ | 617 | DEBUG 时,使用 VERBOSE_DEBUG æ¥æ·»åŠ dev_vdbg()。 |
618 | |||
619 | 许多å系统拥有 Kconfig 调试选项æ¥å¼€å¯ -DDEBUG 在对应的 Makefile 里é¢ï¼›åœ¨å…¶ä»– | ||
620 | 情况下,特殊文件使用 #define DEBUG。当一æ¡è°ƒè¯•ä¿¡æ¯éœ€è¦è¢«æ— æ¡ä»¶æ‰“å°æ—¶ï¼Œä¾‹å¦‚,如果 | ||
621 | å·²ç»åŒ…å«ä¸€ä¸ªè°ƒè¯•相关的 #ifdef æ¡ä»¶ï¼Œprintk(KERN_DEBUG ...) å°±å¯è¢«ä½¿ç”¨ã€‚ | ||
572 | 622 | ||
573 | 623 | ||
574 | 第åå››ç« ï¼šåˆ†é…å†…å˜ | 624 | 第åå››ç« ï¼šåˆ†é…å†…å˜ |
575 | 625 | ||
576 | å†…æ ¸æä¾›äº†ä¸‹é¢çš„一般用途的内å˜åˆ†é…函数:kmalloc(),kzalloc(),kcalloc()å’Œ | 626 | å†…æ ¸æä¾›äº†ä¸‹é¢çš„一般用途的内å˜åˆ†é…函数: |
577 | vmalloc()。请å‚考APIæ–‡æ¡£ä»¥èŽ·å–æœ‰å…³å®ƒä»¬çš„详细信æ¯ã€‚ | 627 | kmalloc(),kzalloc(),kmalloc_array(),kcalloc(),vmalloc() å’Œ vzalloc()。 |
628 | 请å‚考 API æ–‡æ¡£ä»¥èŽ·å–æœ‰å…³å®ƒä»¬çš„详细信æ¯ã€‚ | ||
578 | 629 | ||
579 | ä¼ é€’ç»“æž„ä½“å¤§å°çš„首选形弿˜¯è¿™æ ·çš„: | 630 | ä¼ é€’ç»“æž„ä½“å¤§å°çš„首选形弿˜¯è¿™æ ·çš„: |
580 | 631 | ||
581 | p = kmalloc(sizeof(*p), ...); | 632 | p = kmalloc(sizeof(*p), ...); |
582 | 633 | ||
583 | å¦å¤–一ç§ä¼ 递方å¼ä¸ï¼Œsizeofçš„æ“作数是结构体的åå—ï¼Œè¿™æ ·ä¼šé™ä½Žå¯è¯»æ€§ï¼Œå¹¶ä¸”å¯èƒ½ä¼šå¼• | 634 | å¦å¤–一ç§ä¼ 递方å¼ä¸ï¼Œsizeof çš„æ“作数是结构体的åå—ï¼Œè¿™æ ·ä¼šé™ä½Žå¯è¯»æ€§ï¼Œå¹¶ä¸”å¯èƒ½ä¼šå¼• |
584 | å…¥bug。有å¯èƒ½æŒ‡é’ˆå˜é‡ç±»åž‹è¢«æ”¹å˜æ—¶ï¼Œè€Œå¯¹åº”çš„ä¼ é€’ç»™å†…å˜åˆ†é…函数的sizeof的结果ä¸å˜ã€‚ | 635 | å…¥ bug。有å¯èƒ½æŒ‡é’ˆå˜é‡ç±»åž‹è¢«æ”¹å˜æ—¶ï¼Œè€Œå¯¹åº”çš„ä¼ é€’ç»™å†…å˜åˆ†é…函数的 sizeof 的结果ä¸å˜ã€‚ |
585 | 636 | ||
586 | 强制转æ¢ä¸€ä¸ªvoid指针返回值是多余的。Cè¯è¨€æœ¬èº«ä¿è¯äº†ä»Žvoid指针到其他任何指针类型 | 637 | 强制转æ¢ä¸€ä¸ª void 指针返回值是多余的。C è¯è¨€æœ¬èº«ä¿è¯äº†ä»Ž void 指针到其他任何指针类型 |
587 | çš„è½¬æ¢æ˜¯æ²¡æœ‰é—®é¢˜çš„。 | 638 | çš„è½¬æ¢æ˜¯æ²¡æœ‰é—®é¢˜çš„。 |
588 | 639 | ||
640 | 分é…ä¸€ä¸ªæ•°ç»„çš„é¦–é€‰å½¢å¼æ˜¯è¿™æ ·çš„: | ||
641 | |||
642 | p = kmalloc_array(n, sizeof(...), ...); | ||
643 | |||
644 | 分é…ä¸€ä¸ªé›¶é•¿æ•°ç»„çš„é¦–é€‰å½¢å¼æ˜¯è¿™æ ·çš„: | ||
645 | |||
646 | p = kcalloc(n, sizeof(...), ...); | ||
647 | |||
648 | 两ç§å½¢å¼æ£€æŸ¥åˆ†é…å¤§å° n * sizeof(...) 的溢出,如果溢出返回 NULL。 | ||
649 | |||
589 | 650 | ||
590 | 第åäº”ç« ï¼šå†…è”弊病 | 651 | 第åäº”ç« ï¼šå†…è”弊病 |
591 | 652 | ||
592 | 有一个常è§çš„误解是内è”函数是gccæä¾›çš„å¯ä»¥è®©ä»£ç è¿è¡Œæ›´å¿«çš„ä¸€ä¸ªé€‰é¡¹ã€‚è™½ç„¶ä½¿ç”¨å†…è” | 653 | 有一个常è§çš„误解是内è”函数是 gcc æä¾›çš„å¯ä»¥è®©ä»£ç è¿è¡Œæ›´å¿«çš„ä¸€ä¸ªé€‰é¡¹ã€‚è™½ç„¶ä½¿ç”¨å†…è” |
593 | 函数有时候是æ°å½“çš„ï¼ˆæ¯”å¦‚ä½œä¸ºä¸€ç§æ›¿ä»£å®çš„æ–¹å¼ï¼Œè¯·çœ‹ç¬¬åäºŒç« ï¼‰ï¼Œä¸è¿‡å¾ˆå¤šæƒ…况䏋䏿˜¯ | 654 | 函数有时候是æ°å½“çš„ï¼ˆæ¯”å¦‚ä½œä¸ºä¸€ç§æ›¿ä»£å®çš„æ–¹å¼ï¼Œè¯·çœ‹ç¬¬åäºŒç« ï¼‰ï¼Œä¸è¿‡å¾ˆå¤šæƒ…况䏋䏿˜¯ |
594 | è¿™æ ·ã€‚inline关键å—çš„è¿‡åº¦ä½¿ç”¨ä¼šä½¿å†…æ ¸å˜å¤§ï¼Œä»Žè€Œä½¿æ•´ä¸ªç³»ç»Ÿè¿è¡Œé€Ÿåº¦å˜æ…¢ã€‚å› ä¸ºå¤§å†…æ ¸ | 655 | è¿™æ ·ã€‚inline 关键å—çš„è¿‡åº¦ä½¿ç”¨ä¼šä½¿å†…æ ¸å˜å¤§ï¼Œä»Žè€Œä½¿æ•´ä¸ªç³»ç»Ÿè¿è¡Œé€Ÿåº¦å˜æ…¢ã€‚å› ä¸ºå¤§å†…æ ¸ |
595 | 会å 用更多的指令高速缓å˜ï¼ˆè¯‘注:一级缓å˜é€šå¸¸æ˜¯æŒ‡ä»¤ç¼“å˜å’Œæ•°æ®ç¼“å˜åˆ†å¼€çš„)而且会导 | 656 | 会å 用更多的指令高速缓å˜ï¼ˆè¯‘注:一级缓å˜é€šå¸¸æ˜¯æŒ‡ä»¤ç¼“å˜å’Œæ•°æ®ç¼“å˜åˆ†å¼€çš„)而且会导 |
596 | 致pagecacheçš„å¯ç”¨å†…å˜å‡å°‘。想象一下,一次pagecache未命ä¸å°±ä¼šå¯¼è‡´ä¸€æ¬¡ç£ç›˜å¯»å€ï¼Œå°† | 657 | 致 pagecache çš„å¯ç”¨å†…å˜å‡å°‘。想象一下,一次pagecache未命ä¸å°±ä¼šå¯¼è‡´ä¸€æ¬¡ç£ç›˜å¯»å€ï¼Œ |
597 | 耗时5毫秒。5毫秒的时间内CPU能执行很多很多指令。 | 658 | 将耗时 5 毫秒。5 毫秒的时间内 CPU 能执行很多很多指令。 |
598 | 659 | ||
599 | 一个基本的原则是如果一个函数有3行以上,就ä¸è¦æŠŠå®ƒå˜æˆå†…è”函数。这个原则的一个例 | 660 | 一个基本的原则是如果一个函数有 3 行以上,就ä¸è¦æŠŠå®ƒå˜æˆå†…è”函数。这个原则的一个例 |
600 | å¤–æ˜¯ï¼Œå¦‚æžœä½ çŸ¥é“æŸä¸ªå‚数是一个编译时常é‡ï¼Œè€Œä¸”å› ä¸ºè¿™ä¸ªå¸¸é‡ä½ 确定编译器在编译时能 | 661 | å¤–æ˜¯ï¼Œå¦‚æžœä½ çŸ¥é“æŸä¸ªå‚数是一个编译时常é‡ï¼Œè€Œä¸”å› ä¸ºè¿™ä¸ªå¸¸é‡ä½ 确定编译器在编译时能 |
601 | ä¼˜åŒ–æŽ‰ä½ çš„å‡½æ•°çš„å¤§éƒ¨åˆ†ä»£ç ,那ä»ç„¶å¯ä»¥ç»™å®ƒåŠ ä¸Šinline关键å—。kmalloc()内è”函数就 | 662 | ä¼˜åŒ–æŽ‰ä½ çš„å‡½æ•°çš„å¤§éƒ¨åˆ†ä»£ç ,那ä»ç„¶å¯ä»¥ç»™å®ƒåŠ ä¸Š inline 关键å—。kmalloc() 内è”函数就 |
602 | 是一个很好的例å。 | 663 | 是一个很好的例å。 |
603 | 664 | ||
604 | 人们ç»å¸¸ä¸»å¼ ç»™static的而且åªç”¨äº†ä¸€æ¬¡çš„å‡½æ•°åŠ ä¸Šinline,如æ¤ä¸ä¼šæœ‰ä»»ä½•æŸå¤±ï¼Œå› 为没 | 665 | 人们ç»å¸¸ä¸»å¼ ç»™ static 的而且åªç”¨äº†ä¸€æ¬¡çš„å‡½æ•°åŠ ä¸Š inline,如æ¤ä¸ä¼šæœ‰ä»»ä½•æŸå¤±ï¼Œå› 为没 |
605 | 有什么好æƒè¡¡çš„。虽然从技术上说这是æ£ç¡®çš„ï¼Œä½†æ˜¯å®žé™…ä¸Šè¿™ç§æƒ…况下å³ä½¿ä¸åŠ inline gcc | 666 | 有什么好æƒè¡¡çš„。虽然从技术上说这是æ£ç¡®çš„ï¼Œä½†æ˜¯å®žé™…ä¸Šè¿™ç§æƒ…况下å³ä½¿ä¸åŠ inline gcc |
606 | 也å¯ä»¥è‡ªåŠ¨ä½¿å…¶å†…è”。而且其他用户å¯èƒ½ä¼šè¦æ±‚移除inline,由æ¤è€Œæ¥çš„争论会抵消inline | 667 | 也å¯ä»¥è‡ªåŠ¨ä½¿å…¶å†…è”。而且其他用户å¯èƒ½ä¼šè¦æ±‚移除 inline,由æ¤è€Œæ¥çš„争论会抵消 inline |
607 | 自身的潜在价值,得ä¸å¿å¤±ã€‚ | 668 | 自身的潜在价值,得ä¸å¿å¤±ã€‚ |
608 | 669 | ||
609 | 670 | ||
@@ -613,37 +674,37 @@ vmalloc()。请å‚考APIæ–‡æ¡£ä»¥èŽ·å–æœ‰å…³å®ƒä»¬çš„详细信æ¯ã€‚ | |||
613 | 的一个值å¯ä»¥è¡¨ç¤ºä¸ºä¸€ä¸ªé”™è¯¯ä»£ç 整数(-Exxxï¼å¤±è´¥ï¼Œ0ï¼æˆåŠŸï¼‰æˆ–è€…ä¸€ä¸ªâ€œæˆåŠŸâ€å¸ƒå°”值( | 674 | 的一个值å¯ä»¥è¡¨ç¤ºä¸ºä¸€ä¸ªé”™è¯¯ä»£ç 整数(-Exxxï¼å¤±è´¥ï¼Œ0ï¼æˆåŠŸï¼‰æˆ–è€…ä¸€ä¸ªâ€œæˆåŠŸâ€å¸ƒå°”值( |
614 | 0ï¼å¤±è´¥ï¼Œéž0ï¼æˆåŠŸï¼‰ã€‚ | 675 | 0ï¼å¤±è´¥ï¼Œéž0ï¼æˆåŠŸï¼‰ã€‚ |
615 | 676 | ||
616 | æ··åˆä½¿ç”¨è¿™ä¸¤ç§è¡¨è¾¾æ–¹å¼æ˜¯éš¾äºŽå‘现的bugçš„æ¥æºã€‚如果Cè¯è¨€æœ¬èº«ä¸¥æ ¼åŒºåˆ†æ•´å½¢å’Œå¸ƒå°”åž‹å˜ | 677 | æ··åˆä½¿ç”¨è¿™ä¸¤ç§è¡¨è¾¾æ–¹å¼æ˜¯éš¾äºŽå‘现的 bug çš„æ¥æºã€‚如果 C è¯è¨€æœ¬èº«ä¸¥æ ¼åŒºåˆ†æ•´å½¢å’Œå¸ƒå°”åž‹å˜ |
617 | é‡ï¼Œé‚£ä¹ˆç¼–译器就能够帮我们å‘现这些错误……ä¸è¿‡Cè¯è¨€ä¸åŒºåˆ†ã€‚为了é¿å…产生这ç§bug,请 | 678 | é‡ï¼Œé‚£ä¹ˆç¼–译器就能够帮我们å‘现这些错误……ä¸è¿‡ C è¯è¨€ä¸åŒºåˆ†ã€‚为了é¿å…äº§ç”Ÿè¿™ç§ bug,请 |
618 | éµå¾ªä¸‹é¢çš„æƒ¯ä¾‹ï¼š | 679 | éµå¾ªä¸‹é¢çš„æƒ¯ä¾‹ï¼š |
619 | 680 | ||
620 | 如果函数的åå—æ˜¯ä¸€ä¸ªåŠ¨ä½œæˆ–è€…å¼ºåˆ¶æ€§çš„å‘½ä»¤ï¼Œé‚£ä¹ˆè¿™ä¸ªå‡½æ•°åº”è¯¥è¿”å›žé”™è¯¯ä»£ç æ•´ | 681 | 如果函数的åå—æ˜¯ä¸€ä¸ªåŠ¨ä½œæˆ–è€…å¼ºåˆ¶æ€§çš„å‘½ä»¤ï¼Œé‚£ä¹ˆè¿™ä¸ªå‡½æ•°åº”è¯¥è¿”å›žé”™è¯¯ä»£ç æ•´ |
621 | 数。如果是一个判æ–,那么函数应该返回一个“æˆåŠŸâ€å¸ƒå°”值。 | 682 | 数。如果是一个判æ–,那么函数应该返回一个“æˆåŠŸâ€å¸ƒå°”值。 |
622 | 683 | ||
623 | 比如,“add workâ€æ˜¯ä¸€ä¸ªå‘½ä»¤ï¼Œæ‰€ä»¥add_work()函数在æˆåŠŸæ—¶è¿”å›ž0,在失败时返回-EBUSY。 | 684 | 比如,“add work†是一个命令,所以 add_work() 函数在æˆåŠŸæ—¶è¿”å›ž 0,在失败时返回 -EBUSY。 |
624 | ç±»ä¼¼çš„ï¼Œå› ä¸ºâ€œPCI device presentâ€æ˜¯ä¸€ä¸ªåˆ¤æ–,所以pci_dev_present()函数在æˆåŠŸæ‰¾åˆ° | 685 | ç±»ä¼¼çš„ï¼Œå› ä¸º “PCI device present†是一个判æ–,所以 pci_dev_present() 函数在æˆåŠŸæ‰¾åˆ° |
625 | 一个匹é…的设备时应该返回1,如果找ä¸åˆ°æ—¶åº”该返回0。 | 686 | 一个匹é…的设备时应该返回 1,如果找ä¸åˆ°æ—¶åº”该返回 0。 |
626 | 687 | ||
627 | 所有导出(译注:EXPORT)的函数都必须éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ï¼Œæ‰€æœ‰çš„公共函数也都应该如æ¤ã€‚ç§ | 688 | 所有导出(译注:EXPORT)的函数都必须éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ï¼Œæ‰€æœ‰çš„公共函数也都应该如æ¤ã€‚ç§ |
628 | 有(static)函数ä¸éœ€è¦å¦‚æ¤ï¼Œä½†æ˜¯æˆ‘们也推èè¿™æ ·åšã€‚ | 689 | 有(static)函数ä¸éœ€è¦å¦‚æ¤ï¼Œä½†æ˜¯æˆ‘们也推èè¿™æ ·åšã€‚ |
629 | 690 | ||
630 | è¿”å›žå€¼æ˜¯å®žé™…è®¡ç®—ç»“æžœè€Œä¸æ˜¯è®¡ç®—æ˜¯å¦æˆåŠŸçš„æ ‡å¿—çš„å‡½æ•°ä¸å—æ¤æƒ¯ä¾‹çš„é™åˆ¶ã€‚一般的,他们 | 691 | è¿”å›žå€¼æ˜¯å®žé™…è®¡ç®—ç»“æžœè€Œä¸æ˜¯è®¡ç®—æ˜¯å¦æˆåŠŸçš„æ ‡å¿—çš„å‡½æ•°ä¸å—æ¤æƒ¯ä¾‹çš„é™åˆ¶ã€‚一般的,他们 |
631 | 通过返回一些æ£å¸¸å€¼èŒƒå›´ä¹‹å¤–的结果æ¥è¡¨ç¤ºå‡ºé”™ã€‚å…¸åž‹çš„ä¾‹åæ˜¯è¿”回指针的函数,他们使用 | 692 | 通过返回一些æ£å¸¸å€¼èŒƒå›´ä¹‹å¤–的结果æ¥è¡¨ç¤ºå‡ºé”™ã€‚å…¸åž‹çš„ä¾‹åæ˜¯è¿”回指针的函数,他们使用 |
632 | NULL或者ERR_PTRæœºåˆ¶æ¥æŠ¥å‘Šé”™è¯¯ã€‚ | 693 | NULL 或者 ERR_PTR æœºåˆ¶æ¥æŠ¥å‘Šé”™è¯¯ã€‚ |
633 | 694 | ||
634 | 695 | ||
635 | 第åä¸ƒç« ï¼šä¸è¦é‡æ–°å‘æ˜Žå†…æ ¸å® | 696 | 第åä¸ƒç« ï¼šä¸è¦é‡æ–°å‘æ˜Žå†…æ ¸å® |
636 | 697 | ||
637 | 头文件include/linux/kernel.h包å«äº†ä¸€äº›å®ï¼Œä½ 应该使用它们,而ä¸è¦è‡ªå·±å†™ä¸€äº›å®ƒä»¬çš„ | 698 | 头文件 include/linux/kernel.h 包å«äº†ä¸€äº›å®ï¼Œä½ 应该使用它们,而ä¸è¦è‡ªå·±å†™ä¸€äº›å®ƒä»¬çš„ |
638 | å˜ç§ã€‚æ¯”å¦‚ï¼Œå¦‚æžœä½ éœ€è¦è®¡ç®—ä¸€ä¸ªæ•°ç»„çš„é•¿åº¦ï¼Œä½¿ç”¨è¿™ä¸ªå® | 699 | å˜ç§ã€‚æ¯”å¦‚ï¼Œå¦‚æžœä½ éœ€è¦è®¡ç®—ä¸€ä¸ªæ•°ç»„çš„é•¿åº¦ï¼Œä½¿ç”¨è¿™ä¸ªå® |
639 | 700 | ||
640 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | 701 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
641 | 702 | ||
642 | ç±»ä¼¼çš„ï¼Œå¦‚æžœä½ è¦è®¡ç®—æŸç»“构体æˆå‘˜çš„大å°ï¼Œä½¿ç”¨ | 703 | ç±»ä¼¼çš„ï¼Œå¦‚æžœä½ è¦è®¡ç®—æŸç»“构体æˆå‘˜çš„大å°ï¼Œä½¿ç”¨ |
643 | 704 | ||
644 | #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) | 705 | #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) |
645 | 706 | ||
646 | 还有å¯ä»¥åšä¸¥æ ¼çš„类型检查的min()å’Œmax()å®ï¼Œå¦‚æžœä½ éœ€è¦å¯ä»¥ä½¿ç”¨å®ƒä»¬ã€‚ä½ å¯ä»¥è‡ªå·±çœ‹çœ‹ | 707 | 还有å¯ä»¥åšä¸¥æ ¼çš„类型检查的 min() å’Œ max() å®ï¼Œå¦‚æžœä½ éœ€è¦å¯ä»¥ä½¿ç”¨å®ƒä»¬ã€‚ä½ å¯ä»¥è‡ªå·±çœ‹çœ‹ |
647 | é‚£ä¸ªå¤´æ–‡ä»¶é‡Œè¿˜å®šä¹‰äº†ä»€ä¹ˆä½ å¯ä»¥æ‹¿æ¥ç”¨çš„东西,如果有定义的è¯ï¼Œä½ å°±ä¸åº”åœ¨ä½ çš„ä»£ç 里 | 708 | é‚£ä¸ªå¤´æ–‡ä»¶é‡Œè¿˜å®šä¹‰äº†ä»€ä¹ˆä½ å¯ä»¥æ‹¿æ¥ç”¨çš„东西,如果有定义的è¯ï¼Œä½ å°±ä¸åº”åœ¨ä½ çš„ä»£ç 里 |
648 | è‡ªå·±é‡æ–°å®šä¹‰ã€‚ | 709 | è‡ªå·±é‡æ–°å®šä¹‰ã€‚ |
649 | 710 | ||
@@ -653,42 +714,100 @@ NULL或者ERR_PTRæœºåˆ¶æ¥æŠ¥å‘Šé”™è¯¯ã€‚ | |||
653 | 有一些编辑器å¯ä»¥è§£é‡ŠåµŒå…¥åœ¨æºæ–‡ä»¶é‡Œçš„ç”±ä¸€äº›ç‰¹æ®Šæ ‡è®°æ ‡æ˜Žçš„é…置信æ¯ã€‚比如,emacs | 714 | 有一些编辑器å¯ä»¥è§£é‡ŠåµŒå…¥åœ¨æºæ–‡ä»¶é‡Œçš„ç”±ä¸€äº›ç‰¹æ®Šæ ‡è®°æ ‡æ˜Žçš„é…置信æ¯ã€‚比如,emacs |
654 | èƒ½å¤Ÿè§£é‡Šè¢«æ ‡è®°æˆè¿™æ ·çš„行: | 715 | èƒ½å¤Ÿè§£é‡Šè¢«æ ‡è®°æˆè¿™æ ·çš„行: |
655 | 716 | ||
656 | -*- mode: c -*- | 717 | -*- mode: c -*- |
657 | 718 | ||
658 | æˆ–è€…è¿™æ ·çš„ï¼š | 719 | æˆ–è€…è¿™æ ·çš„ï¼š |
659 | 720 | ||
660 | /* | 721 | /* |
661 | Local Variables: | 722 | Local Variables: |
662 | compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c" | 723 | compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c" |
663 | End: | 724 | End: |
664 | */ | 725 | */ |
665 | 726 | ||
666 | Vimèƒ½å¤Ÿè§£é‡Šè¿™æ ·çš„æ ‡è®°ï¼š | 727 | Vim èƒ½å¤Ÿè§£é‡Šè¿™æ ·çš„æ ‡è®°ï¼š |
667 | 728 | ||
668 | /* vim:set sw=8 noet */ | 729 | /* vim:set sw=8 noet */ |
669 | 730 | ||
670 | ä¸è¦åœ¨æºä»£ç ä¸åŒ…å«ä»»ä½•è¿™æ ·çš„å†…å®¹ã€‚æ¯ä¸ªäººéƒ½æœ‰ä»–自己的编辑器é…ç½®ï¼Œä½ çš„æºæ–‡ä»¶ä¸åº” | 731 | ä¸è¦åœ¨æºä»£ç ä¸åŒ…å«ä»»ä½•è¿™æ ·çš„å†…å®¹ã€‚æ¯ä¸ªäººéƒ½æœ‰ä»–自己的编辑器é…ç½®ï¼Œä½ çš„æºæ–‡ä»¶ä¸åº” |
671 | 该覆盖别人的é…置。这包括有关缩进和模å¼é…ç½®çš„æ ‡è®°ã€‚äººä»¬å¯ä»¥ä½¿ç”¨ä»–们自己定制的模 | 732 | 该覆盖别人的é…置。这包括有关缩进和模å¼é…ç½®çš„æ ‡è®°ã€‚äººä»¬å¯ä»¥ä½¿ç”¨ä»–们自己定制的模 |
672 | å¼ï¼Œæˆ–者使用其他å¯ä»¥äº§ç”Ÿæ£ç¡®çš„缩进的巧妙方法。 | 733 | å¼ï¼Œæˆ–者使用其他å¯ä»¥äº§ç”Ÿæ£ç¡®çš„缩进的巧妙方法。 |
673 | 734 | ||
674 | 735 | ||
736 | 第åä¹ç« ï¼šå†…è”æ±‡ç¼– | ||
737 | |||
738 | 在特定架构的代ç ä¸ï¼Œä½ 也许需è¦å†…è”æ±‡ç¼–æ¥ä½¿ç”¨ CPU 接å£å’Œå¹³å°ç›¸å…³åŠŸèƒ½ã€‚åœ¨éœ€è¦ | ||
739 | è¿™ä¹ˆåšæ—¶ï¼Œä¸è¦çŠ¹è±«ã€‚ç„¶è€Œï¼Œå½“ C å¯ä»¥å®Œæˆå·¥ä½œæ—¶ï¼Œä¸è¦æ— ç«¯åœ°ä½¿ç”¨å†…è”æ±‡ç¼–。如果 | ||
740 | å¯èƒ½ï¼Œä½ å¯ä»¥å¹¶ä¸”应该用 C 和硬件交互。 | ||
741 | |||
742 | è€ƒè™‘åŽ»å†™é€šç”¨ä¸€ç‚¹çš„å†…è”æ±‡ç¼–ä½œä¸ºç®€æ˜Žçš„è¾…åŠ©å‡½æ•°ï¼Œè€Œä¸æ˜¯é‡å¤å†™ä¸‹å®ƒä»¬çš„ç»†èŠ‚ã€‚è®°ä½ | ||
743 | å†…è”æ±‡ç¼–å¯ä»¥ä½¿ç”¨ C 傿•°ã€‚ | ||
744 | |||
745 | 大而特殊的汇编函数应该放在 .S 文件ä¸ï¼Œå¯¹åº” C 的原型定义在 C 头文件ä¸ã€‚汇编 | ||
746 | 函数的 C 原型应该使用 “asmlinkageâ€ã€‚ | ||
747 | |||
748 | ä½ å¯èƒ½éœ€è¦å°†ä½ 的汇编è¯å¥æ ‡è®°ä¸º volatile,æ¥é˜»æ¢ GCC 在没å‘现任何副作用åŽå°± | ||
749 | ç§»é™¤äº†å®ƒã€‚ä½ ä¸å¿…æ€»æ˜¯è¿™æ ·åšï¼Œè™½ç„¶ï¼Œè¿™æ ·å¯ä»¥é™åˆ¶ä¸å¿…è¦çš„优化。 | ||
750 | |||
751 | 在写一个包å«å¤šæ¡æŒ‡ä»¤çš„å•ä¸ªå†…è”æ±‡ç¼–è¯å¥æ—¶ï¼ŒæŠŠæ¯æ¡æŒ‡ä»¤ç”¨å¼•å·å—符串分离,并写在 | ||
752 | å•独一行,在æ¯ä¸ªå—符串结尾,除了 \n\t 结尾之外,在汇编输出ä¸é€‚当地缩进下 | ||
753 | ä¸€æ¡æŒ‡ä»¤ï¼š | ||
754 | |||
755 | asm ("magic %reg1, #42\n\t" | ||
756 | "more_magic %reg2, %reg3" | ||
757 | : /* outputs */ : /* inputs */ : /* clobbers */); | ||
758 | |||
759 | |||
760 | 第二åç« ï¼šæ¡ä»¶ç¼–译 | ||
761 | |||
762 | åªè¦å¯èƒ½ï¼Œå°±ä¸è¦åœ¨ .c 文件里é¢ä½¿ç”¨é¢„å¤„ç†æ¡ä»¶ï¼›è¿™æ ·åšè®©ä»£ç 更难阅读并且逻辑难以 | ||
763 | 跟踪。替代方案是,在头文件定义函数在这些 .c 文件ä¸ä½¿ç”¨è¿™ç±»çš„æ¡ä»¶è¡¨è¾¾å¼ï¼Œæä¾›ç©º | ||
764 | æ“作的桩版本(译注:桩程åºï¼Œæ˜¯æŒ‡ç”¨æ¥æ›¿æ¢ä¸€éƒ¨åˆ†åŠŸèƒ½çš„ç¨‹åºæ®µï¼‰åœ¨ #else 情况下, | ||
765 | å†ä»Ž .c æ–‡ä»¶ä¸æ— æ¡ä»¶åœ°è°ƒç”¨è¿™äº›å‡½æ•°ã€‚编译器会é¿å…生æˆä»»ä½•桩调用的代ç ,产生一致 | ||
766 | çš„ç»“æžœï¼Œä½†é€»è¾‘å°†æ›´åŠ æ¸…æ™°ã€‚ | ||
767 | |||
768 | å®å¯ç¼–è¯‘æ•´ä¸ªå‡½æ•°ï¼Œè€Œä¸æ˜¯éƒ¨åˆ†å‡½æ•°æˆ–部分表达å¼ã€‚è€Œä¸æ˜¯åœ¨ä¸€ä¸ªè¡¨è¾¾å¼æ·»åŠ ifdef, | ||
769 | è§£æžéƒ¨åˆ†æˆ–全部表达å¼åˆ°ä¸€ä¸ªå•独的辅助函数,并应用æ¡ä»¶åˆ°è¯¥å‡½æ•°å†…。 | ||
770 | |||
771 | å¦‚æžœä½ æœ‰ä¸€ä¸ªåœ¨ç‰¹å®šé…ç½®ä¸å¯èƒ½æ˜¯æœªä½¿ç”¨çš„函数或å˜é‡ï¼Œç¼–译器将è¦å‘Šå®ƒå®šä¹‰äº†ä½†æœªä½¿ç”¨ï¼Œ | ||
772 | æ ‡è®°è¿™ä¸ªå®šä¹‰ä¸º __maybe_unused è€Œä¸æ˜¯å°†å®ƒåŒ…å«åœ¨ä¸€ä¸ªé¢„å¤„ç†æ¡ä»¶ä¸ã€‚(然而,如果 | ||
773 | 一个函数或å˜é‡æ€»æ˜¯æœªä½¿ç”¨çš„ï¼Œå°±ç›´æŽ¥åˆ é™¤å®ƒã€‚ï¼‰ | ||
774 | |||
775 | 在代ç ä¸ï¼Œå¯èƒ½çš„æƒ…况下,使用 IS_ENABLED 宿¥è½¬åŒ–æŸä¸ª Kconfig æ ‡è®°ä¸º C 的布尔 | ||
776 | 表达å¼ï¼Œå¹¶åœ¨æ£å¸¸çš„ C æ¡ä»¶ä¸ä½¿ç”¨å®ƒï¼š | ||
777 | |||
778 | if (IS_ENABLED(CONFIG_SOMETHING)) { | ||
779 | ... | ||
780 | } | ||
781 | |||
782 | ç¼–è¯‘å™¨ä¼šæ— æ¡ä»¶åœ°åšå¸¸æ•°åˆå¹¶ï¼Œå°±åƒä½¿ç”¨ #ifdef é‚£æ ·ï¼ŒåŒ…å«æˆ–排除代ç å—,所以这ä¸ä¼š | ||
783 | 带æ¥ä»»ä½•è¿è¡Œæ—¶å¼€é”€ã€‚ç„¶è€Œï¼Œè¿™ç§æ–¹æ³•便—§å…许 C 编译器查看å—内的代ç ,并检查它的æ£ç¡® | ||
784 | æ€§ï¼ˆè¯æ³•,类型,符å·å¼•用,ç‰ç‰ï¼‰ã€‚å› æ¤ï¼Œå¦‚æžœæ¡ä»¶ä¸æ»¡è¶³ï¼Œä»£ç å—内的引用符å·å°†ä¸å˜åœ¨ï¼Œ | ||
785 | ä½ å¿…é¡»ç»§ç»ä½¿ç”¨ #ifdef。 | ||
786 | |||
787 | 在任何有æ„义的 #if 或 #ifdef å—çš„æœ«å°¾ï¼ˆè¶…è¿‡å‡ è¡Œï¼‰ï¼Œåœ¨ #endif åŒä¸€è¡Œçš„åŽé¢å†™ä¸‹ | ||
788 | 注释,指出该æ¡ä»¶è¡¨è¾¾å¼è¢«ä½¿ç”¨ã€‚例如: | ||
789 | |||
790 | #ifdef CONFIG_SOMETHING | ||
791 | ... | ||
792 | #endif /* CONFIG_SOMETHING */ | ||
793 | |||
675 | 794 | ||
676 | 附录 I:å‚考 | 795 | 附录 I:å‚考 |
677 | 796 | ||
678 | The C Programming Language, 第二版, 作者Brian W. Kernighan和Denni | 797 | The C Programming Language, 第二版 |
679 | M. Ritchie. Prentice Hall, Inc., 1988. ISBN 0-13-110362-8 (软皮), | 798 | 作者:Brian W. Kernighan 和 Denni M. Ritchie. |
680 | 0-13-110370-9 (硬皮). URL: http://cm.bell-labs.com/cm/cs/cbook/ | 799 | Prentice Hall, Inc., 1988. |
800 | ISBN 0-13-110362-8 (软皮), 0-13-110370-9 (硬皮). | ||
681 | 801 | ||
682 | The Practice of Programming 作者Brian W. Kernighan和Rob Pike. Addison-Wesley, | 802 | The Practice of Programming |
683 | Inc., 1999. ISBN 0-201-61586-X. URL: http://cm.bell-labs.com/cm/cs/tpop/ | 803 | 作者:Brian W. Kernighan 和 Rob Pike. |
804 | Addison-Wesley, Inc., 1999. | ||
805 | ISBN 0-201-61586-X. | ||
684 | 806 | ||
685 | cpp,gcc,gcc internalså’Œindentçš„GNU手册——和K&RåŠæœ¬æ–‡ç›¸ç¬¦åˆçš„部分,全部å¯ä»¥åœ¨ | 807 | GNU 手册 - éµå¾ª K&R æ ‡å‡†å’Œæ¤æ–‡æœ¬ - cpp, gcc, gcc internals and indent, |
686 | http://www.gnu.org/manual/找到 | 808 | 都å¯ä»¥ä»Ž http://www.gnu.org/manual/ 找到 |
687 | 809 | ||
688 | WG14是Cè¯è¨€çš„å›½é™…æ ‡å‡†åŒ–å·¥ä½œç»„ï¼ŒURL: http://www.open-std.org/JTC1/SC22/WG14/ | 810 | WG14是Cè¯è¨€çš„å›½é™…æ ‡å‡†åŒ–å·¥ä½œç»„ï¼ŒURL: http://www.open-std.org/JTC1/SC22/WG14/ |
689 | 811 | ||
690 | Kernel CodingStyle,作者greg@kroah.comå‘表于OLS 2002: | 812 | Kernel CodingStyle,作者 greg@kroah.com å‘表于OLS 2002: |
691 | http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ | 813 | http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ |
692 | |||
693 | -- | ||
694 | æœ€åŽæ›´æ–°äºŽ2007å¹´7月13日。 | ||
@@ -1412,8 +1412,11 @@ $(help-board-dirs): help-%: | |||
1412 | 1412 | ||
1413 | # Documentation targets | 1413 | # Documentation targets |
1414 | # --------------------------------------------------------------------------- | 1414 | # --------------------------------------------------------------------------- |
1415 | %docs: scripts_basic FORCE | 1415 | DOC_TARGETS := xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs epubdocs cleandocs |
1416 | PHONY += $(DOC_TARGETS) | ||
1417 | $(DOC_TARGETS): scripts_basic FORCE | ||
1416 | $(Q)$(MAKE) $(build)=scripts build_docproc build_check-lc_ctype | 1418 | $(Q)$(MAKE) $(build)=scripts build_docproc build_check-lc_ctype |
1419 | $(Q)$(MAKE) $(build)=Documentation -f $(srctree)/Documentation/Makefile.sphinx $@ | ||
1417 | $(Q)$(MAKE) $(build)=Documentation/DocBook $@ | 1420 | $(Q)$(MAKE) $(build)=Documentation/DocBook $@ |
1418 | 1421 | ||
1419 | else # KBUILD_EXTMOD | 1422 | else # KBUILD_EXTMOD |
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 2fc8fad5195e..27757c21551a 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
@@ -59,6 +59,12 @@ Output format selection (mutually exclusive): | |||
59 | -text Output plain text format. | 59 | -text Output plain text format. |
60 | 60 | ||
61 | Output selection (mutually exclusive): | 61 | Output selection (mutually exclusive): |
62 | -export Only output documentation for symbols that have been | ||
63 | exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() | ||
64 | in the same FILE. | ||
65 | -internal Only output documentation for symbols that have NOT been | ||
66 | exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() | ||
67 | in the same FILE. | ||
62 | -function NAME Only output documentation for the given function(s) | 68 | -function NAME Only output documentation for the given function(s) |
63 | or DOC: section title(s). All other functions and DOC: | 69 | or DOC: section title(s). All other functions and DOC: |
64 | sections are ignored. May be specified multiple times. | 70 | sections are ignored. May be specified multiple times. |
@@ -68,6 +74,8 @@ Output selection (mutually exclusive): | |||
68 | 74 | ||
69 | Output selection modifiers: | 75 | Output selection modifiers: |
70 | -no-doc-sections Do not output DOC: sections. | 76 | -no-doc-sections Do not output DOC: sections. |
77 | -enable-lineno Enable output of #define LINENO lines. Only works with | ||
78 | reStructuredText format. | ||
71 | 79 | ||
72 | Other parameters: | 80 | Other parameters: |
73 | -v Verbose output, more warnings and other information. | 81 | -v Verbose output, more warnings and other information. |
@@ -206,6 +214,10 @@ my $type_struct_xml = '\\&((struct\s*)*[_\w]+)'; | |||
206 | my $type_env = '(\$\w+)'; | 214 | my $type_env = '(\$\w+)'; |
207 | my $type_enum_full = '\&(enum)\s*([_\w]+)'; | 215 | my $type_enum_full = '\&(enum)\s*([_\w]+)'; |
208 | my $type_struct_full = '\&(struct)\s*([_\w]+)'; | 216 | my $type_struct_full = '\&(struct)\s*([_\w]+)'; |
217 | my $type_typedef_full = '\&(typedef)\s*([_\w]+)'; | ||
218 | my $type_union_full = '\&(union)\s*([_\w]+)'; | ||
219 | my $type_member = '\&([_\w]+)((\.|->)[_\w]+)'; | ||
220 | my $type_member_func = $type_member . '\(\)'; | ||
209 | 221 | ||
210 | # Output conversion substitutions. | 222 | # Output conversion substitutions. |
211 | # One for each output format | 223 | # One for each output format |
@@ -274,10 +286,16 @@ my $blankline_text = ""; | |||
274 | # rst-mode | 286 | # rst-mode |
275 | my @highlights_rst = ( | 287 | my @highlights_rst = ( |
276 | [$type_constant, "``\$1``"], | 288 | [$type_constant, "``\$1``"], |
277 | [$type_func, "\\:c\\:func\\:`\$1`"], | 289 | # Note: need to escape () to avoid func matching later |
290 | [$type_member_func, "\\:c\\:type\\:`\$1\$2\\\\(\\\\) <\$1>`"], | ||
291 | [$type_member, "\\:c\\:type\\:`\$1\$2 <\$1>`"], | ||
292 | [$type_func, "\\:c\\:func\\:`\$1()`"], | ||
278 | [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], | 293 | [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], |
279 | [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], | 294 | [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], |
280 | [$type_struct, "\\:c\\:type\\:`struct \$1 <\$1>`"], | 295 | [$type_typedef_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], |
296 | [$type_union_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], | ||
297 | # in rst this can refer to any type | ||
298 | [$type_struct, "\\:c\\:type\\:`\$1`"], | ||
281 | [$type_param, "**\$1**"] | 299 | [$type_param, "**\$1**"] |
282 | ); | 300 | ); |
283 | my $blankline_rst = "\n"; | 301 | my $blankline_rst = "\n"; |
@@ -303,10 +321,19 @@ my $verbose = 0; | |||
303 | my $output_mode = "man"; | 321 | my $output_mode = "man"; |
304 | my $output_preformatted = 0; | 322 | my $output_preformatted = 0; |
305 | my $no_doc_sections = 0; | 323 | my $no_doc_sections = 0; |
324 | my $enable_lineno = 0; | ||
306 | my @highlights = @highlights_man; | 325 | my @highlights = @highlights_man; |
307 | my $blankline = $blankline_man; | 326 | my $blankline = $blankline_man; |
308 | my $modulename = "Kernel API"; | 327 | my $modulename = "Kernel API"; |
309 | my $function_only = 0; | 328 | |
329 | use constant { | ||
330 | OUTPUT_ALL => 0, # output all symbols and doc sections | ||
331 | OUTPUT_INCLUDE => 1, # output only specified symbols | ||
332 | OUTPUT_EXCLUDE => 2, # output everything except specified symbols | ||
333 | OUTPUT_EXPORTED => 3, # output exported symbols | ||
334 | OUTPUT_INTERNAL => 4, # output non-exported symbols | ||
335 | }; | ||
336 | my $output_selection = OUTPUT_ALL; | ||
310 | my $show_not_found = 0; | 337 | my $show_not_found = 0; |
311 | 338 | ||
312 | my @build_time; | 339 | my @build_time; |
@@ -327,6 +354,7 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', | |||
327 | # CAVEAT EMPTOR! Some of the others I localised may not want to be, which | 354 | # CAVEAT EMPTOR! Some of the others I localised may not want to be, which |
328 | # could cause "use of undefined value" or other bugs. | 355 | # could cause "use of undefined value" or other bugs. |
329 | my ($function, %function_table, %parametertypes, $declaration_purpose); | 356 | my ($function, %function_table, %parametertypes, $declaration_purpose); |
357 | my $declaration_start_line; | ||
330 | my ($type, $declaration_name, $return_type); | 358 | my ($type, $declaration_name, $return_type); |
331 | my ($newsection, $newcontents, $prototype, $brcount, %source_map); | 359 | my ($newsection, $newcontents, $prototype, $brcount, %source_map); |
332 | 360 | ||
@@ -344,52 +372,62 @@ my $section_counter = 0; | |||
344 | 372 | ||
345 | my $lineprefix=""; | 373 | my $lineprefix=""; |
346 | 374 | ||
347 | # states | 375 | # Parser states |
348 | # 0 - normal code | 376 | use constant { |
349 | # 1 - looking for function name | 377 | STATE_NORMAL => 0, # normal code |
350 | # 2 - scanning field start. | 378 | STATE_NAME => 1, # looking for function name |
351 | # 3 - scanning prototype. | 379 | STATE_FIELD => 2, # scanning field start |
352 | # 4 - documentation block | 380 | STATE_PROTO => 3, # scanning prototype |
353 | # 5 - gathering documentation outside main block | 381 | STATE_DOCBLOCK => 4, # documentation block |
382 | STATE_INLINE => 5, # gathering documentation outside main block | ||
383 | }; | ||
354 | my $state; | 384 | my $state; |
355 | my $in_doc_sect; | 385 | my $in_doc_sect; |
356 | 386 | ||
357 | # Split Doc State | 387 | # Inline documentation state |
358 | # 0 - Invalid (Before start or after finish) | 388 | use constant { |
359 | # 1 - Is started (the /** was found inside a struct) | 389 | STATE_INLINE_NA => 0, # not applicable ($state != STATE_INLINE) |
360 | # 2 - The @parameter header was found, start accepting multi paragraph text. | 390 | STATE_INLINE_NAME => 1, # looking for member name (@foo:) |
361 | # 3 - Finished (the */ was found) | 391 | STATE_INLINE_TEXT => 2, # looking for member documentation |
362 | # 4 - Error - Comment without header was found. Spit a warning as it's not | 392 | STATE_INLINE_END => 3, # done |
363 | # proper kernel-doc and ignore the rest. | 393 | STATE_INLINE_ERROR => 4, # error - Comment without header was found. |
364 | my $split_doc_state; | 394 | # Spit a warning as it's not |
395 | # proper kernel-doc and ignore the rest. | ||
396 | }; | ||
397 | my $inline_doc_state; | ||
365 | 398 | ||
366 | #declaration types: can be | 399 | #declaration types: can be |
367 | # 'function', 'struct', 'union', 'enum', 'typedef' | 400 | # 'function', 'struct', 'union', 'enum', 'typedef' |
368 | my $decl_type; | 401 | my $decl_type; |
369 | 402 | ||
370 | my $doc_special = "\@\%\$\&"; | ||
371 | |||
372 | my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. | 403 | my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. |
373 | my $doc_end = '\*/'; | 404 | my $doc_end = '\*/'; |
374 | my $doc_com = '\s*\*\s*'; | 405 | my $doc_com = '\s*\*\s*'; |
375 | my $doc_com_body = '\s*\* ?'; | 406 | my $doc_com_body = '\s*\* ?'; |
376 | my $doc_decl = $doc_com . '(\w+)'; | 407 | my $doc_decl = $doc_com . '(\w+)'; |
377 | my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)'; | 408 | # @params and a strictly limited set of supported section names |
409 | my $doc_sect = $doc_com . | ||
410 | '\s*(\@\w+|description|context|returns?|notes?|examples?)\s*:(.*)'; | ||
378 | my $doc_content = $doc_com_body . '(.*)'; | 411 | my $doc_content = $doc_com_body . '(.*)'; |
379 | my $doc_block = $doc_com . 'DOC:\s*(.*)?'; | 412 | my $doc_block = $doc_com . 'DOC:\s*(.*)?'; |
380 | my $doc_split_start = '^\s*/\*\*\s*$'; | 413 | my $doc_inline_start = '^\s*/\*\*\s*$'; |
381 | my $doc_split_sect = '\s*\*\s*(@[\w\s]+):(.*)'; | 414 | my $doc_inline_sect = '\s*\*\s*(@[\w\s]+):(.*)'; |
382 | my $doc_split_end = '^\s*\*/\s*$'; | 415 | my $doc_inline_end = '^\s*\*/\s*$'; |
416 | my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;'; | ||
383 | 417 | ||
384 | my %constants; | ||
385 | my %parameterdescs; | 418 | my %parameterdescs; |
419 | my %parameterdesc_start_lines; | ||
386 | my @parameterlist; | 420 | my @parameterlist; |
387 | my %sections; | 421 | my %sections; |
388 | my @sectionlist; | 422 | my @sectionlist; |
423 | my %section_start_lines; | ||
389 | my $sectcheck; | 424 | my $sectcheck; |
390 | my $struct_actual; | 425 | my $struct_actual; |
391 | 426 | ||
392 | my $contents = ""; | 427 | my $contents = ""; |
428 | my $new_start_line = 0; | ||
429 | |||
430 | # the canonical section names. see also $doc_sect above. | ||
393 | my $section_default = "Description"; # default section | 431 | my $section_default = "Description"; # default section |
394 | my $section_intro = "Introduction"; | 432 | my $section_intro = "Introduction"; |
395 | my $section = $section_default; | 433 | my $section = $section_default; |
@@ -437,19 +475,27 @@ while ($ARGV[0] =~ m/^-(.*)/) { | |||
437 | } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document | 475 | } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document |
438 | $modulename = shift @ARGV; | 476 | $modulename = shift @ARGV; |
439 | } elsif ($cmd eq "-function") { # to only output specific functions | 477 | } elsif ($cmd eq "-function") { # to only output specific functions |
440 | $function_only = 1; | 478 | $output_selection = OUTPUT_INCLUDE; |
441 | $function = shift @ARGV; | 479 | $function = shift @ARGV; |
442 | $function_table{$function} = 1; | 480 | $function_table{$function} = 1; |
443 | } elsif ($cmd eq "-nofunction") { # to only output specific functions | 481 | } elsif ($cmd eq "-nofunction") { # output all except specific functions |
444 | $function_only = 2; | 482 | $output_selection = OUTPUT_EXCLUDE; |
445 | $function = shift @ARGV; | 483 | $function = shift @ARGV; |
446 | $function_table{$function} = 1; | 484 | $function_table{$function} = 1; |
485 | } elsif ($cmd eq "-export") { # only exported symbols | ||
486 | $output_selection = OUTPUT_EXPORTED; | ||
487 | %function_table = () | ||
488 | } elsif ($cmd eq "-internal") { # only non-exported symbols | ||
489 | $output_selection = OUTPUT_INTERNAL; | ||
490 | %function_table = () | ||
447 | } elsif ($cmd eq "-v") { | 491 | } elsif ($cmd eq "-v") { |
448 | $verbose = 1; | 492 | $verbose = 1; |
449 | } elsif (($cmd eq "-h") || ($cmd eq "--help")) { | 493 | } elsif (($cmd eq "-h") || ($cmd eq "--help")) { |
450 | usage(); | 494 | usage(); |
451 | } elsif ($cmd eq '-no-doc-sections') { | 495 | } elsif ($cmd eq '-no-doc-sections') { |
452 | $no_doc_sections = 1; | 496 | $no_doc_sections = 1; |
497 | } elsif ($cmd eq '-enable-lineno') { | ||
498 | $enable_lineno = 1; | ||
453 | } elsif ($cmd eq '-show-not-found') { | 499 | } elsif ($cmd eq '-show-not-found') { |
454 | $show_not_found = 1; | 500 | $show_not_found = 1; |
455 | } | 501 | } |
@@ -467,6 +513,13 @@ sub get_kernel_version() { | |||
467 | return $version; | 513 | return $version; |
468 | } | 514 | } |
469 | 515 | ||
516 | # | ||
517 | sub print_lineno { | ||
518 | my $lineno = shift; | ||
519 | if ($enable_lineno && defined($lineno)) { | ||
520 | print "#define LINENO " . $lineno . "\n"; | ||
521 | } | ||
522 | } | ||
470 | ## | 523 | ## |
471 | # dumps section contents to arrays/hashes intended for that purpose. | 524 | # dumps section contents to arrays/hashes intended for that purpose. |
472 | # | 525 | # |
@@ -475,28 +528,32 @@ sub dump_section { | |||
475 | my $name = shift; | 528 | my $name = shift; |
476 | my $contents = join "\n", @_; | 529 | my $contents = join "\n", @_; |
477 | 530 | ||
478 | if ($name =~ m/$type_constant/) { | 531 | if ($name =~ m/$type_param/) { |
479 | $name = $1; | ||
480 | # print STDERR "constant section '$1' = '$contents'\n"; | ||
481 | $constants{$name} = $contents; | ||
482 | } elsif ($name =~ m/$type_param/) { | ||
483 | # print STDERR "parameter def '$1' = '$contents'\n"; | 532 | # print STDERR "parameter def '$1' = '$contents'\n"; |
484 | $name = $1; | 533 | $name = $1; |
485 | $parameterdescs{$name} = $contents; | 534 | $parameterdescs{$name} = $contents; |
486 | $sectcheck = $sectcheck . $name . " "; | 535 | $sectcheck = $sectcheck . $name . " "; |
536 | $parameterdesc_start_lines{$name} = $new_start_line; | ||
537 | $new_start_line = 0; | ||
487 | } elsif ($name eq "@\.\.\.") { | 538 | } elsif ($name eq "@\.\.\.") { |
488 | # print STDERR "parameter def '...' = '$contents'\n"; | 539 | # print STDERR "parameter def '...' = '$contents'\n"; |
489 | $name = "..."; | 540 | $name = "..."; |
490 | $parameterdescs{$name} = $contents; | 541 | $parameterdescs{$name} = $contents; |
491 | $sectcheck = $sectcheck . $name . " "; | 542 | $sectcheck = $sectcheck . $name . " "; |
543 | $parameterdesc_start_lines{$name} = $new_start_line; | ||
544 | $new_start_line = 0; | ||
492 | } else { | 545 | } else { |
493 | # print STDERR "other section '$name' = '$contents'\n"; | 546 | # print STDERR "other section '$name' = '$contents'\n"; |
494 | if (defined($sections{$name}) && ($sections{$name} ne "")) { | 547 | if (defined($sections{$name}) && ($sections{$name} ne "")) { |
495 | print STDERR "${file}:$.: error: duplicate section name '$name'\n"; | 548 | print STDERR "${file}:$.: warning: duplicate section name '$name'\n"; |
496 | ++$errors; | 549 | ++$warnings; |
550 | $sections{$name} .= $contents; | ||
551 | } else { | ||
552 | $sections{$name} = $contents; | ||
553 | push @sectionlist, $name; | ||
554 | $section_start_lines{$name} = $new_start_line; | ||
555 | $new_start_line = 0; | ||
497 | } | 556 | } |
498 | $sections{$name} = $contents; | ||
499 | push @sectionlist, $name; | ||
500 | } | 557 | } |
501 | } | 558 | } |
502 | 559 | ||
@@ -512,15 +569,17 @@ sub dump_doc_section { | |||
512 | return; | 569 | return; |
513 | } | 570 | } |
514 | 571 | ||
515 | if (($function_only == 0) || | 572 | if (($output_selection == OUTPUT_ALL) || |
516 | ( $function_only == 1 && defined($function_table{$name})) || | 573 | ($output_selection == OUTPUT_INCLUDE && |
517 | ( $function_only == 2 && !defined($function_table{$name}))) | 574 | defined($function_table{$name})) || |
575 | ($output_selection == OUTPUT_EXCLUDE && | ||
576 | !defined($function_table{$name}))) | ||
518 | { | 577 | { |
519 | dump_section($file, $name, $contents); | 578 | dump_section($file, $name, $contents); |
520 | output_blockhead({'sectionlist' => \@sectionlist, | 579 | output_blockhead({'sectionlist' => \@sectionlist, |
521 | 'sections' => \%sections, | 580 | 'sections' => \%sections, |
522 | 'module' => $modulename, | 581 | 'module' => $modulename, |
523 | 'content-only' => ($function_only != 0), }); | 582 | 'content-only' => ($output_selection != OUTPUT_ALL), }); |
524 | } | 583 | } |
525 | } | 584 | } |
526 | 585 | ||
@@ -1736,7 +1795,10 @@ sub output_blockhead_rst(%) { | |||
1736 | my ($parameter, $section); | 1795 | my ($parameter, $section); |
1737 | 1796 | ||
1738 | foreach $section (@{$args{'sectionlist'}}) { | 1797 | foreach $section (@{$args{'sectionlist'}}) { |
1739 | print "**$section**\n\n"; | 1798 | if ($output_selection != OUTPUT_INCLUDE) { |
1799 | print "**$section**\n\n"; | ||
1800 | } | ||
1801 | print_lineno($section_start_lines{$section}); | ||
1740 | output_highlight_rst($args{'sections'}{$section}); | 1802 | output_highlight_rst($args{'sections'}{$section}); |
1741 | print "\n"; | 1803 | print "\n"; |
1742 | } | 1804 | } |
@@ -1753,19 +1815,14 @@ sub output_highlight_rst { | |||
1753 | die $@ if $@; | 1815 | die $@ if $@; |
1754 | 1816 | ||
1755 | foreach $line (split "\n", $contents) { | 1817 | foreach $line (split "\n", $contents) { |
1756 | if ($line eq "") { | 1818 | print $lineprefix . $line . "\n"; |
1757 | print $lineprefix, $blankline; | ||
1758 | } else { | ||
1759 | $line =~ s/\\\\\\/\&/g; | ||
1760 | print $lineprefix, $line; | ||
1761 | } | ||
1762 | print "\n"; | ||
1763 | } | 1819 | } |
1764 | } | 1820 | } |
1765 | 1821 | ||
1766 | sub output_function_rst(%) { | 1822 | sub output_function_rst(%) { |
1767 | my %args = %{$_[0]}; | 1823 | my %args = %{$_[0]}; |
1768 | my ($parameter, $section); | 1824 | my ($parameter, $section); |
1825 | my $oldprefix = $lineprefix; | ||
1769 | my $start; | 1826 | my $start; |
1770 | 1827 | ||
1771 | print ".. c:function:: "; | 1828 | print ".. c:function:: "; |
@@ -1790,29 +1847,37 @@ sub output_function_rst(%) { | |||
1790 | print $type . " " . $parameter; | 1847 | print $type . " " . $parameter; |
1791 | } | 1848 | } |
1792 | } | 1849 | } |
1793 | print ")\n\n " . $args{'purpose'} . "\n\n"; | 1850 | print ")\n\n"; |
1851 | print_lineno($declaration_start_line); | ||
1852 | $lineprefix = " "; | ||
1853 | output_highlight_rst($args{'purpose'}); | ||
1854 | print "\n"; | ||
1794 | 1855 | ||
1795 | print ":Parameters:\n\n"; | 1856 | print "**Parameters**\n\n"; |
1857 | $lineprefix = " "; | ||
1796 | foreach $parameter (@{$args{'parameterlist'}}) { | 1858 | foreach $parameter (@{$args{'parameterlist'}}) { |
1797 | my $parameter_name = $parameter; | 1859 | my $parameter_name = $parameter; |
1798 | #$parameter_name =~ s/\[.*//; | 1860 | #$parameter_name =~ s/\[.*//; |
1799 | $type = $args{'parametertypes'}{$parameter}; | 1861 | $type = $args{'parametertypes'}{$parameter}; |
1800 | 1862 | ||
1801 | if ($type ne "") { | 1863 | if ($type ne "") { |
1802 | print " ``$type $parameter``\n"; | 1864 | print "``$type $parameter``\n"; |
1803 | } else { | 1865 | } else { |
1804 | print " ``$parameter``\n"; | 1866 | print "``$parameter``\n"; |
1805 | } | 1867 | } |
1806 | if ($args{'parameterdescs'}{$parameter_name} ne $undescribed) { | 1868 | |
1807 | my $oldprefix = $lineprefix; | 1869 | print_lineno($parameterdesc_start_lines{$parameter_name}); |
1808 | $lineprefix = " "; | 1870 | |
1871 | if (defined($args{'parameterdescs'}{$parameter_name}) && | ||
1872 | $args{'parameterdescs'}{$parameter_name} ne $undescribed) { | ||
1809 | output_highlight_rst($args{'parameterdescs'}{$parameter_name}); | 1873 | output_highlight_rst($args{'parameterdescs'}{$parameter_name}); |
1810 | $lineprefix = $oldprefix; | ||
1811 | } else { | 1874 | } else { |
1812 | print "\n _undescribed_\n"; | 1875 | print " *undescribed*\n"; |
1813 | } | 1876 | } |
1814 | print "\n"; | 1877 | print "\n"; |
1815 | } | 1878 | } |
1879 | |||
1880 | $lineprefix = $oldprefix; | ||
1816 | output_section_rst(@_); | 1881 | output_section_rst(@_); |
1817 | } | 1882 | } |
1818 | 1883 | ||
@@ -1820,10 +1885,11 @@ sub output_section_rst(%) { | |||
1820 | my %args = %{$_[0]}; | 1885 | my %args = %{$_[0]}; |
1821 | my $section; | 1886 | my $section; |
1822 | my $oldprefix = $lineprefix; | 1887 | my $oldprefix = $lineprefix; |
1823 | $lineprefix = " "; | 1888 | $lineprefix = ""; |
1824 | 1889 | ||
1825 | foreach $section (@{$args{'sectionlist'}}) { | 1890 | foreach $section (@{$args{'sectionlist'}}) { |
1826 | print ":$section:\n\n"; | 1891 | print "**$section**\n\n"; |
1892 | print_lineno($section_start_lines{$section}); | ||
1827 | output_highlight_rst($args{'sections'}{$section}); | 1893 | output_highlight_rst($args{'sections'}{$section}); |
1828 | print "\n"; | 1894 | print "\n"; |
1829 | } | 1895 | } |
@@ -1834,24 +1900,28 @@ sub output_section_rst(%) { | |||
1834 | sub output_enum_rst(%) { | 1900 | sub output_enum_rst(%) { |
1835 | my %args = %{$_[0]}; | 1901 | my %args = %{$_[0]}; |
1836 | my ($parameter); | 1902 | my ($parameter); |
1903 | my $oldprefix = $lineprefix; | ||
1837 | my $count; | 1904 | my $count; |
1838 | my $name = "enum " . $args{'enum'}; | 1905 | my $name = "enum " . $args{'enum'}; |
1839 | 1906 | ||
1840 | print "\n\n.. c:type:: " . $name . "\n\n"; | 1907 | print "\n\n.. c:type:: " . $name . "\n\n"; |
1841 | print " " . $args{'purpose'} . "\n\n"; | 1908 | print_lineno($declaration_start_line); |
1909 | $lineprefix = " "; | ||
1910 | output_highlight_rst($args{'purpose'}); | ||
1911 | print "\n"; | ||
1842 | 1912 | ||
1843 | print "..\n\n:Constants:\n\n"; | 1913 | print "**Constants**\n\n"; |
1844 | my $oldprefix = $lineprefix; | 1914 | $lineprefix = " "; |
1845 | $lineprefix = " "; | ||
1846 | foreach $parameter (@{$args{'parameterlist'}}) { | 1915 | foreach $parameter (@{$args{'parameterlist'}}) { |
1847 | print " `$parameter`\n"; | 1916 | print "``$parameter``\n"; |
1848 | if ($args{'parameterdescs'}{$parameter} ne $undescribed) { | 1917 | if ($args{'parameterdescs'}{$parameter} ne $undescribed) { |
1849 | output_highlight_rst($args{'parameterdescs'}{$parameter}); | 1918 | output_highlight_rst($args{'parameterdescs'}{$parameter}); |
1850 | } else { | 1919 | } else { |
1851 | print " undescribed\n"; | 1920 | print " *undescribed*\n"; |
1852 | } | 1921 | } |
1853 | print "\n"; | 1922 | print "\n"; |
1854 | } | 1923 | } |
1924 | |||
1855 | $lineprefix = $oldprefix; | 1925 | $lineprefix = $oldprefix; |
1856 | output_section_rst(@_); | 1926 | output_section_rst(@_); |
1857 | } | 1927 | } |
@@ -1859,30 +1929,37 @@ sub output_enum_rst(%) { | |||
1859 | sub output_typedef_rst(%) { | 1929 | sub output_typedef_rst(%) { |
1860 | my %args = %{$_[0]}; | 1930 | my %args = %{$_[0]}; |
1861 | my ($parameter); | 1931 | my ($parameter); |
1862 | my $count; | 1932 | my $oldprefix = $lineprefix; |
1863 | my $name = "typedef " . $args{'typedef'}; | 1933 | my $name = "typedef " . $args{'typedef'}; |
1864 | 1934 | ||
1865 | ### FIXME: should the name below contain "typedef" or not? | ||
1866 | print "\n\n.. c:type:: " . $name . "\n\n"; | 1935 | print "\n\n.. c:type:: " . $name . "\n\n"; |
1867 | print " " . $args{'purpose'} . "\n\n"; | 1936 | print_lineno($declaration_start_line); |
1937 | $lineprefix = " "; | ||
1938 | output_highlight_rst($args{'purpose'}); | ||
1939 | print "\n"; | ||
1868 | 1940 | ||
1941 | $lineprefix = $oldprefix; | ||
1869 | output_section_rst(@_); | 1942 | output_section_rst(@_); |
1870 | } | 1943 | } |
1871 | 1944 | ||
1872 | sub output_struct_rst(%) { | 1945 | sub output_struct_rst(%) { |
1873 | my %args = %{$_[0]}; | 1946 | my %args = %{$_[0]}; |
1874 | my ($parameter); | 1947 | my ($parameter); |
1948 | my $oldprefix = $lineprefix; | ||
1875 | my $name = $args{'type'} . " " . $args{'struct'}; | 1949 | my $name = $args{'type'} . " " . $args{'struct'}; |
1876 | 1950 | ||
1877 | print "\n\n.. c:type:: " . $name . "\n\n"; | 1951 | print "\n\n.. c:type:: " . $name . "\n\n"; |
1878 | print " " . $args{'purpose'} . "\n\n"; | 1952 | print_lineno($declaration_start_line); |
1953 | $lineprefix = " "; | ||
1954 | output_highlight_rst($args{'purpose'}); | ||
1955 | print "\n"; | ||
1879 | 1956 | ||
1880 | print ":Definition:\n\n"; | 1957 | print "**Definition**\n\n"; |
1881 | print " ::\n\n"; | 1958 | print "::\n\n"; |
1882 | print " " . $args{'type'} . " " . $args{'struct'} . " {\n"; | 1959 | print " " . $args{'type'} . " " . $args{'struct'} . " {\n"; |
1883 | foreach $parameter (@{$args{'parameterlist'}}) { | 1960 | foreach $parameter (@{$args{'parameterlist'}}) { |
1884 | if ($parameter =~ /^#/) { | 1961 | if ($parameter =~ /^#/) { |
1885 | print " " . "$parameter\n"; | 1962 | print " " . "$parameter\n"; |
1886 | next; | 1963 | next; |
1887 | } | 1964 | } |
1888 | 1965 | ||
@@ -1903,7 +1980,8 @@ sub output_struct_rst(%) { | |||
1903 | } | 1980 | } |
1904 | print " };\n\n"; | 1981 | print " };\n\n"; |
1905 | 1982 | ||
1906 | print ":Members:\n\n"; | 1983 | print "**Members**\n\n"; |
1984 | $lineprefix = " "; | ||
1907 | foreach $parameter (@{$args{'parameterlist'}}) { | 1985 | foreach $parameter (@{$args{'parameterlist'}}) { |
1908 | ($parameter =~ /^#/) && next; | 1986 | ($parameter =~ /^#/) && next; |
1909 | 1987 | ||
@@ -1912,14 +1990,14 @@ sub output_struct_rst(%) { | |||
1912 | 1990 | ||
1913 | ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; | 1991 | ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; |
1914 | $type = $args{'parametertypes'}{$parameter}; | 1992 | $type = $args{'parametertypes'}{$parameter}; |
1915 | print " `$type $parameter`" . "\n"; | 1993 | print_lineno($parameterdesc_start_lines{$parameter_name}); |
1916 | my $oldprefix = $lineprefix; | 1994 | print "``$type $parameter``\n"; |
1917 | $lineprefix = " "; | ||
1918 | output_highlight_rst($args{'parameterdescs'}{$parameter_name}); | 1995 | output_highlight_rst($args{'parameterdescs'}{$parameter_name}); |
1919 | $lineprefix = $oldprefix; | ||
1920 | print "\n"; | 1996 | print "\n"; |
1921 | } | 1997 | } |
1922 | print "\n"; | 1998 | print "\n"; |
1999 | |||
2000 | $lineprefix = $oldprefix; | ||
1923 | output_section_rst(@_); | 2001 | output_section_rst(@_); |
1924 | } | 2002 | } |
1925 | 2003 | ||
@@ -1969,9 +2047,13 @@ sub output_declaration { | |||
1969 | my $name = shift; | 2047 | my $name = shift; |
1970 | my $functype = shift; | 2048 | my $functype = shift; |
1971 | my $func = "output_${functype}_$output_mode"; | 2049 | my $func = "output_${functype}_$output_mode"; |
1972 | if (($function_only==0) || | 2050 | if (($output_selection == OUTPUT_ALL) || |
1973 | ( $function_only == 1 && defined($function_table{$name})) || | 2051 | (($output_selection == OUTPUT_INCLUDE || |
1974 | ( $function_only == 2 && !($functype eq "function" && defined($function_table{$name})))) | 2052 | $output_selection == OUTPUT_EXPORTED) && |
2053 | defined($function_table{$name})) || | ||
2054 | (($output_selection == OUTPUT_EXCLUDE || | ||
2055 | $output_selection == OUTPUT_INTERNAL) && | ||
2056 | !($functype eq "function" && defined($function_table{$name})))) | ||
1975 | { | 2057 | { |
1976 | &$func(@_); | 2058 | &$func(@_); |
1977 | $section_counter++; | 2059 | $section_counter++; |
@@ -2471,7 +2553,6 @@ sub dump_function($$) { | |||
2471 | 2553 | ||
2472 | sub reset_state { | 2554 | sub reset_state { |
2473 | $function = ""; | 2555 | $function = ""; |
2474 | %constants = (); | ||
2475 | %parameterdescs = (); | 2556 | %parameterdescs = (); |
2476 | %parametertypes = (); | 2557 | %parametertypes = (); |
2477 | @parameterlist = (); | 2558 | @parameterlist = (); |
@@ -2481,8 +2562,8 @@ sub reset_state { | |||
2481 | $struct_actual = ""; | 2562 | $struct_actual = ""; |
2482 | $prototype = ""; | 2563 | $prototype = ""; |
2483 | 2564 | ||
2484 | $state = 0; | 2565 | $state = STATE_NORMAL; |
2485 | $split_doc_state = 0; | 2566 | $inline_doc_state = STATE_INLINE_NA; |
2486 | } | 2567 | } |
2487 | 2568 | ||
2488 | sub tracepoint_munge($) { | 2569 | sub tracepoint_munge($) { |
@@ -2545,7 +2626,7 @@ sub syscall_munge() { | |||
2545 | } | 2626 | } |
2546 | } | 2627 | } |
2547 | 2628 | ||
2548 | sub process_state3_function($$) { | 2629 | sub process_proto_function($$) { |
2549 | my $x = shift; | 2630 | my $x = shift; |
2550 | my $file = shift; | 2631 | my $file = shift; |
2551 | 2632 | ||
@@ -2575,7 +2656,7 @@ sub process_state3_function($$) { | |||
2575 | } | 2656 | } |
2576 | } | 2657 | } |
2577 | 2658 | ||
2578 | sub process_state3_type($$) { | 2659 | sub process_proto_type($$) { |
2579 | my $x = shift; | 2660 | my $x = shift; |
2580 | my $file = shift; | 2661 | my $file = shift; |
2581 | 2662 | ||
@@ -2657,6 +2738,7 @@ sub process_file($) { | |||
2657 | my $in_purpose = 0; | 2738 | my $in_purpose = 0; |
2658 | my $initial_section_counter = $section_counter; | 2739 | my $initial_section_counter = $section_counter; |
2659 | my ($orig_file) = @_; | 2740 | my ($orig_file) = @_; |
2741 | my $leading_space; | ||
2660 | 2742 | ||
2661 | if (defined($ENV{'SRCTREE'})) { | 2743 | if (defined($ENV{'SRCTREE'})) { |
2662 | $file = "$ENV{'SRCTREE'}" . "/" . $orig_file; | 2744 | $file = "$ENV{'SRCTREE'}" . "/" . $orig_file; |
@@ -2674,6 +2756,17 @@ sub process_file($) { | |||
2674 | return; | 2756 | return; |
2675 | } | 2757 | } |
2676 | 2758 | ||
2759 | # two passes for -export and -internal | ||
2760 | if ($output_selection == OUTPUT_EXPORTED || | ||
2761 | $output_selection == OUTPUT_INTERNAL) { | ||
2762 | while (<IN>) { | ||
2763 | if (/$export_symbol/o) { | ||
2764 | $function_table{$2} = 1; | ||
2765 | } | ||
2766 | } | ||
2767 | seek(IN, 0, 0); | ||
2768 | } | ||
2769 | |||
2677 | $. = 1; | 2770 | $. = 1; |
2678 | 2771 | ||
2679 | $section_counter = 0; | 2772 | $section_counter = 0; |
@@ -2681,15 +2774,18 @@ sub process_file($) { | |||
2681 | while (s/\\\s*$//) { | 2774 | while (s/\\\s*$//) { |
2682 | $_ .= <IN>; | 2775 | $_ .= <IN>; |
2683 | } | 2776 | } |
2684 | if ($state == 0) { | 2777 | if ($state == STATE_NORMAL) { |
2685 | if (/$doc_start/o) { | 2778 | if (/$doc_start/o) { |
2686 | $state = 1; # next line is always the function name | 2779 | $state = STATE_NAME; # next line is always the function name |
2687 | $in_doc_sect = 0; | 2780 | $in_doc_sect = 0; |
2781 | $declaration_start_line = $. + 1; | ||
2688 | } | 2782 | } |
2689 | } elsif ($state == 1) { # this line is the function name (always) | 2783 | } elsif ($state == STATE_NAME) {# this line is the function name (always) |
2690 | if (/$doc_block/o) { | 2784 | if (/$doc_block/o) { |
2691 | $state = 4; | 2785 | $state = STATE_DOCBLOCK; |
2692 | $contents = ""; | 2786 | $contents = ""; |
2787 | $new_start_line = $. + 1; | ||
2788 | |||
2693 | if ( $1 eq "" ) { | 2789 | if ( $1 eq "" ) { |
2694 | $section = $section_intro; | 2790 | $section = $section_intro; |
2695 | } else { | 2791 | } else { |
@@ -2702,7 +2798,12 @@ sub process_file($) { | |||
2702 | $identifier = $1; | 2798 | $identifier = $1; |
2703 | } | 2799 | } |
2704 | 2800 | ||
2705 | $state = 2; | 2801 | $state = STATE_FIELD; |
2802 | # if there's no @param blocks need to set up default section | ||
2803 | # here | ||
2804 | $contents = ""; | ||
2805 | $section = $section_default; | ||
2806 | $new_start_line = $. + 1; | ||
2706 | if (/-(.*)/) { | 2807 | if (/-(.*)/) { |
2707 | # strip leading/trailing/multiple spaces | 2808 | # strip leading/trailing/multiple spaces |
2708 | $descr= $1; | 2809 | $descr= $1; |
@@ -2740,13 +2841,25 @@ sub process_file($) { | |||
2740 | print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", | 2841 | print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", |
2741 | " - I thought it was a doc line\n"; | 2842 | " - I thought it was a doc line\n"; |
2742 | ++$warnings; | 2843 | ++$warnings; |
2743 | $state = 0; | 2844 | $state = STATE_NORMAL; |
2744 | } | 2845 | } |
2745 | } elsif ($state == 2) { # look for head: lines, and include content | 2846 | } elsif ($state == STATE_FIELD) { # look for head: lines, and include content |
2746 | if (/$doc_sect/o) { | 2847 | if (/$doc_sect/i) { # case insensitive for supported section names |
2747 | $newsection = $1; | 2848 | $newsection = $1; |
2748 | $newcontents = $2; | 2849 | $newcontents = $2; |
2749 | 2850 | ||
2851 | # map the supported section names to the canonical names | ||
2852 | if ($newsection =~ m/^description$/i) { | ||
2853 | $newsection = $section_default; | ||
2854 | } elsif ($newsection =~ m/^context$/i) { | ||
2855 | $newsection = $section_context; | ||
2856 | } elsif ($newsection =~ m/^returns?$/i) { | ||
2857 | $newsection = $section_return; | ||
2858 | } elsif ($newsection =~ m/^\@return$/) { | ||
2859 | # special: @return is a section, not a param description | ||
2860 | $newsection = $section_return; | ||
2861 | } | ||
2862 | |||
2750 | if (($contents ne "") && ($contents ne "\n")) { | 2863 | if (($contents ne "") && ($contents ne "\n")) { |
2751 | if (!$in_doc_sect && $verbose) { | 2864 | if (!$in_doc_sect && $verbose) { |
2752 | print STDERR "${file}:$.: warning: contents before sections\n"; | 2865 | print STDERR "${file}:$.: warning: contents before sections\n"; |
@@ -2759,14 +2872,16 @@ sub process_file($) { | |||
2759 | $in_doc_sect = 1; | 2872 | $in_doc_sect = 1; |
2760 | $in_purpose = 0; | 2873 | $in_purpose = 0; |
2761 | $contents = $newcontents; | 2874 | $contents = $newcontents; |
2875 | $new_start_line = $.; | ||
2876 | while ((substr($contents, 0, 1) eq " ") || | ||
2877 | substr($contents, 0, 1) eq "\t") { | ||
2878 | $contents = substr($contents, 1); | ||
2879 | } | ||
2762 | if ($contents ne "") { | 2880 | if ($contents ne "") { |
2763 | while ((substr($contents, 0, 1) eq " ") || | ||
2764 | substr($contents, 0, 1) eq "\t") { | ||
2765 | $contents = substr($contents, 1); | ||
2766 | } | ||
2767 | $contents .= "\n"; | 2881 | $contents .= "\n"; |
2768 | } | 2882 | } |
2769 | $section = $newsection; | 2883 | $section = $newsection; |
2884 | $leading_space = undef; | ||
2770 | } elsif (/$doc_end/) { | 2885 | } elsif (/$doc_end/) { |
2771 | if (($contents ne "") && ($contents ne "\n")) { | 2886 | if (($contents ne "") && ($contents ne "\n")) { |
2772 | dump_section($file, $section, xml_escape($contents)); | 2887 | dump_section($file, $section, xml_escape($contents)); |
@@ -2780,7 +2895,7 @@ sub process_file($) { | |||
2780 | } | 2895 | } |
2781 | 2896 | ||
2782 | $prototype = ""; | 2897 | $prototype = ""; |
2783 | $state = 3; | 2898 | $state = STATE_PROTO; |
2784 | $brcount = 0; | 2899 | $brcount = 0; |
2785 | # print STDERR "end of doc comment, looking for prototype\n"; | 2900 | # print STDERR "end of doc comment, looking for prototype\n"; |
2786 | } elsif (/$doc_content/) { | 2901 | } elsif (/$doc_content/) { |
@@ -2791,6 +2906,7 @@ sub process_file($) { | |||
2791 | dump_section($file, $section, xml_escape($contents)); | 2906 | dump_section($file, $section, xml_escape($contents)); |
2792 | $section = $section_default; | 2907 | $section = $section_default; |
2793 | $contents = ""; | 2908 | $contents = ""; |
2909 | $new_start_line = $.; | ||
2794 | } else { | 2910 | } else { |
2795 | $contents .= "\n"; | 2911 | $contents .= "\n"; |
2796 | } | 2912 | } |
@@ -2801,87 +2917,86 @@ sub process_file($) { | |||
2801 | $declaration_purpose .= " " . xml_escape($1); | 2917 | $declaration_purpose .= " " . xml_escape($1); |
2802 | $declaration_purpose =~ s/\s+/ /g; | 2918 | $declaration_purpose =~ s/\s+/ /g; |
2803 | } else { | 2919 | } else { |
2804 | $contents .= $1 . "\n"; | 2920 | my $cont = $1; |
2921 | if ($section =~ m/^@/ || $section eq $section_context) { | ||
2922 | if (!defined $leading_space) { | ||
2923 | if ($cont =~ m/^(\s+)/) { | ||
2924 | $leading_space = $1; | ||
2925 | } else { | ||
2926 | $leading_space = ""; | ||
2927 | } | ||
2928 | } | ||
2929 | |||
2930 | $cont =~ s/^$leading_space//; | ||
2931 | } | ||
2932 | $contents .= $cont . "\n"; | ||
2805 | } | 2933 | } |
2806 | } else { | 2934 | } else { |
2807 | # i dont know - bad line? ignore. | 2935 | # i dont know - bad line? ignore. |
2808 | print STDERR "${file}:$.: warning: bad line: $_"; | 2936 | print STDERR "${file}:$.: warning: bad line: $_"; |
2809 | ++$warnings; | 2937 | ++$warnings; |
2810 | } | 2938 | } |
2811 | } elsif ($state == 5) { # scanning for split parameters | 2939 | } elsif ($state == STATE_INLINE) { # scanning for inline parameters |
2812 | # First line (state 1) needs to be a @parameter | 2940 | # First line (state 1) needs to be a @parameter |
2813 | if ($split_doc_state == 1 && /$doc_split_sect/o) { | 2941 | if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) { |
2814 | $section = $1; | 2942 | $section = $1; |
2815 | $contents = $2; | 2943 | $contents = $2; |
2944 | $new_start_line = $.; | ||
2816 | if ($contents ne "") { | 2945 | if ($contents ne "") { |
2817 | while ((substr($contents, 0, 1) eq " ") || | 2946 | while ((substr($contents, 0, 1) eq " ") || |
2818 | substr($contents, 0, 1) eq "\t") { | 2947 | substr($contents, 0, 1) eq "\t") { |
2819 | $contents = substr($contents, 1); | 2948 | $contents = substr($contents, 1); |
2820 | } | 2949 | } |
2821 | $contents .= "\n"; | 2950 | $contents .= "\n"; |
2822 | } | 2951 | } |
2823 | $split_doc_state = 2; | 2952 | $inline_doc_state = STATE_INLINE_TEXT; |
2824 | # Documentation block end */ | 2953 | # Documentation block end */ |
2825 | } elsif (/$doc_split_end/) { | 2954 | } elsif (/$doc_inline_end/) { |
2826 | if (($contents ne "") && ($contents ne "\n")) { | 2955 | if (($contents ne "") && ($contents ne "\n")) { |
2827 | dump_section($file, $section, xml_escape($contents)); | 2956 | dump_section($file, $section, xml_escape($contents)); |
2828 | $section = $section_default; | 2957 | $section = $section_default; |
2829 | $contents = ""; | 2958 | $contents = ""; |
2830 | } | 2959 | } |
2831 | $state = 3; | 2960 | $state = STATE_PROTO; |
2832 | $split_doc_state = 0; | 2961 | $inline_doc_state = STATE_INLINE_NA; |
2833 | # Regular text | 2962 | # Regular text |
2834 | } elsif (/$doc_content/) { | 2963 | } elsif (/$doc_content/) { |
2835 | if ($split_doc_state == 2) { | 2964 | if ($inline_doc_state == STATE_INLINE_TEXT) { |
2836 | $contents .= $1 . "\n"; | 2965 | $contents .= $1 . "\n"; |
2837 | } elsif ($split_doc_state == 1) { | 2966 | # nuke leading blank lines |
2838 | $split_doc_state = 4; | 2967 | if ($contents =~ /^\s*$/) { |
2968 | $contents = ""; | ||
2969 | } | ||
2970 | } elsif ($inline_doc_state == STATE_INLINE_NAME) { | ||
2971 | $inline_doc_state = STATE_INLINE_ERROR; | ||
2839 | print STDERR "Warning(${file}:$.): "; | 2972 | print STDERR "Warning(${file}:$.): "; |
2840 | print STDERR "Incorrect use of kernel-doc format: $_"; | 2973 | print STDERR "Incorrect use of kernel-doc format: $_"; |
2841 | ++$warnings; | 2974 | ++$warnings; |
2842 | } | 2975 | } |
2843 | } | 2976 | } |
2844 | } elsif ($state == 3) { # scanning for function '{' (end of prototype) | 2977 | } elsif ($state == STATE_PROTO) { # scanning for function '{' (end of prototype) |
2845 | if (/$doc_split_start/) { | 2978 | if (/$doc_inline_start/) { |
2846 | $state = 5; | 2979 | $state = STATE_INLINE; |
2847 | $split_doc_state = 1; | 2980 | $inline_doc_state = STATE_INLINE_NAME; |
2848 | } elsif ($decl_type eq 'function') { | 2981 | } elsif ($decl_type eq 'function') { |
2849 | process_state3_function($_, $file); | 2982 | process_proto_function($_, $file); |
2850 | } else { | 2983 | } else { |
2851 | process_state3_type($_, $file); | 2984 | process_proto_type($_, $file); |
2852 | } | 2985 | } |
2853 | } elsif ($state == 4) { | 2986 | } elsif ($state == STATE_DOCBLOCK) { |
2854 | # Documentation block | 2987 | if (/$doc_end/) |
2855 | if (/$doc_block/) { | ||
2856 | dump_doc_section($file, $section, xml_escape($contents)); | ||
2857 | $contents = ""; | ||
2858 | $function = ""; | ||
2859 | %constants = (); | ||
2860 | %parameterdescs = (); | ||
2861 | %parametertypes = (); | ||
2862 | @parameterlist = (); | ||
2863 | %sections = (); | ||
2864 | @sectionlist = (); | ||
2865 | $prototype = ""; | ||
2866 | if ( $1 eq "" ) { | ||
2867 | $section = $section_intro; | ||
2868 | } else { | ||
2869 | $section = $1; | ||
2870 | } | ||
2871 | } | ||
2872 | elsif (/$doc_end/) | ||
2873 | { | 2988 | { |
2874 | dump_doc_section($file, $section, xml_escape($contents)); | 2989 | dump_doc_section($file, $section, xml_escape($contents)); |
2990 | $section = $section_default; | ||
2875 | $contents = ""; | 2991 | $contents = ""; |
2876 | $function = ""; | 2992 | $function = ""; |
2877 | %constants = (); | ||
2878 | %parameterdescs = (); | 2993 | %parameterdescs = (); |
2879 | %parametertypes = (); | 2994 | %parametertypes = (); |
2880 | @parameterlist = (); | 2995 | @parameterlist = (); |
2881 | %sections = (); | 2996 | %sections = (); |
2882 | @sectionlist = (); | 2997 | @sectionlist = (); |
2883 | $prototype = ""; | 2998 | $prototype = ""; |
2884 | $state = 0; | 2999 | $state = STATE_NORMAL; |
2885 | } | 3000 | } |
2886 | elsif (/$doc_content/) | 3001 | elsif (/$doc_content/) |
2887 | { | 3002 | { |
@@ -2898,7 +3013,7 @@ sub process_file($) { | |||
2898 | } | 3013 | } |
2899 | if ($initial_section_counter == $section_counter) { | 3014 | if ($initial_section_counter == $section_counter) { |
2900 | print STDERR "${file}:1: warning: no structured comments found\n"; | 3015 | print STDERR "${file}:1: warning: no structured comments found\n"; |
2901 | if (($function_only == 1) && ($show_not_found == 1)) { | 3016 | if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) { |
2902 | print STDERR " Was looking for '$_'.\n" for keys %function_table; | 3017 | print STDERR " Was looking for '$_'.\n" for keys %function_table; |
2903 | } | 3018 | } |
2904 | if ($output_mode eq "xml") { | 3019 | if ($output_mode eq "xml") { |