mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-28 08:11:05 -08:00
430 lines
15 KiB
ReStructuredText
430 lines
15 KiB
ReStructuredText
.. mode: -*- rst -*-
|
|
|
|
C Style -- formatting
|
|
=====================
|
|
|
|
:Tag: guide.impl.c.format
|
|
:Author: Richard Brooksby
|
|
:Date: 1995-08-07
|
|
:Status: complete guide
|
|
:Format: rst
|
|
:Revision: $Id$
|
|
:Copyright: See `Copyright and License`_.
|
|
:Index terms:
|
|
pair: C language; formatting guide
|
|
pair: C language formatting; guide
|
|
|
|
|
|
Introduction
|
|
------------
|
|
|
|
_`.scope`: This document describes the Ravenbrook conventions for the
|
|
general format of C source code in the MPS.
|
|
|
|
_`.readership`: This document is intended for anyone working on or with the
|
|
C source code.
|
|
|
|
|
|
General Formatting Conventions
|
|
------------------------------
|
|
|
|
Line Width
|
|
..........
|
|
|
|
_`.width`: Lines should be no wider than 72 characters. _`.width.why`: Many
|
|
people use 80 column terminal windows so that multiple windows can be
|
|
placed side by side. Restricting lines to 72 characters allows line
|
|
numbering to be used (in vi for example) and also allows diffs to be
|
|
displayed without overflowing the terminal.
|
|
|
|
White Space
|
|
...........
|
|
|
|
_`.space.notab`: No tab characters should appear in the source files.
|
|
Ordinary spaces should be used to indent and format the sources.
|
|
_`.space.notab.why`: Tab characters are displayed differently on different
|
|
platforms, and sometimes translated back and forth, destroying layout
|
|
information.
|
|
|
|
_`.space.punct`: There should always be whitespace after commas and
|
|
semicolons and similar punctuation.
|
|
|
|
_`.space.op`: Put white space around operators in expressions, except when
|
|
removing it would make the expression clearer by binding certain
|
|
sub-expressions more tightly. For example::
|
|
|
|
foo = x + y*z;
|
|
|
|
_`.space.control`: One space between the keyword, ``switch``, ``while``,
|
|
``for`` and the following paren. _`.space.control.why`: This distinguishes
|
|
control statements lexically from function calls, making it easier to
|
|
distinguish them visually and when searching with tools like grep.
|
|
|
|
_`.space.function.not`: No space between a function name and the following
|
|
paren beginning its argument list.
|
|
|
|
Sections and Paragraphs
|
|
.......................
|
|
|
|
_`.section`: Source files can be thought of as breaking down into
|
|
"sections" and "paragraphs". A section might be the leader comment of a
|
|
file, the imports, or a set of declarations which are related.
|
|
|
|
_`.section.space`: Precede sections by two blank lines (except the first
|
|
one in the file, which should be the leader comment in any case).
|
|
|
|
_`.section.comment`: Each section should start with a banner comment (see
|
|
.comment.banner) describing what the section contains.
|
|
|
|
_`.para`: Within sections, code often breaks down into natural units called
|
|
"paragraphs". A paragraph might be a set of strongly related
|
|
declarations (Init and Finish, for example), or a few lines of code
|
|
which it makes sense to consider together (the assignment of fields into
|
|
a structure, for example).
|
|
|
|
_`.para.space`: Precede paragraphs by a single blank line.
|
|
|
|
Statements
|
|
..........
|
|
|
|
_`.statement.one`: Generally only have at most one statement per line. In
|
|
particular the following are deprecated::
|
|
|
|
if (thing) return;
|
|
|
|
a=0; b=0;
|
|
|
|
case 0: f = inRampMode ? AMCGen0RampmodeFrequency : AMCGen0Frequency;
|
|
|
|
_`.statement.one.why`: Debuggers can often only place breakpoints on lines,
|
|
not expressions or statements within a line. The ``if (thing) return;`` is
|
|
a particularly important case, if thing is a reasonably rare return
|
|
condition then you might want to breakpoint it in a debugger session.
|
|
Annoying because ``if (thing) return;`` is quite compact and pleasing
|
|
otherwise.
|
|
|
|
Indentation
|
|
...........
|
|
|
|
_`.indent`: Indent the body of a block by two spaces. For formatting
|
|
purposes, the "body of a block" means:
|
|
|
|
- statements between braces,
|
|
- a single statement following a lone ``if``;
|
|
- statements in a switch body; see .switch.
|
|
|
|
(_`.indent.logical`: The aim is to group what we think of as logical
|
|
blocks, even though they may not exactly match how "block" is used in
|
|
the definition of C syntax).
|
|
|
|
Some examples::
|
|
|
|
if (res != ResOK) {
|
|
SegFinish(&span->segStruct);
|
|
PoolFreeP(MV->spanPool, span, sizeof(SpanStruct));
|
|
return res;
|
|
}
|
|
|
|
if (res != ResOK)
|
|
goto error;
|
|
|
|
if (j == block->base) {
|
|
if (j+step == block->limit) {
|
|
if (block->thing)
|
|
putc('@', stream);
|
|
}
|
|
} else if (j+step == block->limit) {
|
|
putc(']', stream);
|
|
pop_bracket();
|
|
} else {
|
|
putc('.', stream);
|
|
}
|
|
|
|
switch (c) {
|
|
case 'A':
|
|
c = 'A';
|
|
p += 1;
|
|
break;
|
|
}
|
|
|
|
_`.indent.goto-label`: Place each goto-label on a line of its own,
|
|
outdented to the same level as the surrounding block. Then indent the
|
|
non-label part of the statement normally.
|
|
|
|
::
|
|
|
|
result foo(void)
|
|
{
|
|
statement();
|
|
if (error)
|
|
goto foo;
|
|
statement();
|
|
return OK;
|
|
|
|
foo:
|
|
unwind();
|
|
return ERROR;
|
|
}
|
|
|
|
_`.indent.case-label`: Outdent case- and default-labels in a switch
|
|
statement in the same way as `.indent.goto-label`_. See `.switch`_.
|
|
|
|
_`.indent.cont`: If an expression or statement won't fit on a single line,
|
|
indent the continuation lines by two spaces, apart from the following
|
|
exception:
|
|
|
|
_`.indent.cont.parens`: if you break a statement inside a parameter list or
|
|
other parenthesized expression, indent so that the continuation lines up
|
|
just after the open parenthesis. For example::
|
|
|
|
PoolClassInit(&PoolClassMVStruct,
|
|
"MV", init, finish, allocP, freeP,
|
|
NULL, NULL, describe, isValid);
|
|
|
|
_`.indent.cont.expr`: Note that when breaking an expression it is clearer
|
|
to place the operator at the start of the continuation line::
|
|
|
|
CHECKL(AddrAdd((Addr)chunk->pageTableMapped,
|
|
BTSize(chunk->pageTablePages))
|
|
<= AddrAdd(chunk->base, chunk->ullageSize));
|
|
|
|
This is particularly useful in long conditional expressions that use &&
|
|
and ||. For example::
|
|
|
|
} while(trace->state != TraceFINISHED
|
|
&& (trace->emergency || traceWorkClock(trace) < pollEnd));
|
|
|
|
_`.indent.hint`: Usually, it is possible to determine the correct
|
|
indentation for a line by looking to see if the previous line ends with
|
|
a semicolon. If it does, indent to the same amount, otherwise indent by
|
|
two more spaces. The main exceptions are lines starting with a close
|
|
brace, goto-labels, and line-breaks between parentheses.
|
|
|
|
Positioning of Braces
|
|
.....................
|
|
|
|
_`.brace.otb`: Use the "One True Brace" (or OTB) style. This places the
|
|
open brace after the control word or expression, separated by a space,
|
|
and when there is an else, places that after the close brace. For
|
|
example::
|
|
|
|
if(isBase) {
|
|
new->base = limit;
|
|
new->limit = block->limit;
|
|
block->limit = base;
|
|
new->next = block->next;
|
|
block->next = new;
|
|
} else {
|
|
new->base = block->base;
|
|
new->limit = base;
|
|
block->base = limit;
|
|
new->next = block;
|
|
*prev = new;
|
|
}
|
|
|
|
The same applies to struct, enum, union.
|
|
|
|
_`.brace.otb.function.not`: OTB is never used for function definitions.
|
|
|
|
_`.brace.always`: Braces are always required after ``if``, ``else``, ``switch``,
|
|
``while``, ``do``, and ``for``.
|
|
|
|
_`.brace.always.except`: Except that a lone ``if`` with no ``else`` is allowed
|
|
to drop its braces when its body is a single simple statement. Typically
|
|
this will be a ``goto`` or an assignment. For example::
|
|
|
|
if (res != ResOK)
|
|
goto failStart;
|
|
|
|
Note in particular that an ``if`` with an ``else`` must have braces on both
|
|
paths.
|
|
|
|
Switch Statements
|
|
.................
|
|
|
|
_`.switch`: format switch statements like this::
|
|
|
|
switch (action) {
|
|
case WIBBLE:
|
|
case WOBBLE:
|
|
{
|
|
int angle;
|
|
err = move(plate, action, &angle);
|
|
}
|
|
break;
|
|
|
|
case QUIET:
|
|
drop();
|
|
/* fall-through */
|
|
|
|
case QUIESCENT:
|
|
err = 0;
|
|
break;
|
|
|
|
default:
|
|
NOTREACHED;
|
|
break;
|
|
}
|
|
|
|
The component rules that result in this style are:
|
|
|
|
_`.switch.break`: The last line of every case-clause body must be an
|
|
unconditional jump statement (usually ``break``, but may be ``goto``,
|
|
``continue``, or ``return``), or if a fall-through is intended, the comment
|
|
``/* fall-through */``. (Note: if the unconditional jump should never be
|
|
taken, because of previous conditional jumps, use ``NOTREACHED`` on the
|
|
line before it). This rule is to prevent accidental fall-throughs, even
|
|
if someone makes a editing mistake that causes a conditional jump to be
|
|
missed.
|
|
|
|
_`.switch.default`: It is usually a good idea to have a default-clause,
|
|
even if all it contains is ``NOTREACHED`` and ``break``. Remember that
|
|
``NOTREACHED`` doesn't stop the process in all build varieties.
|
|
|
|
|
|
Formatting Comments
|
|
...................
|
|
|
|
_`.comment`: There are three types of comments: banners, paragraph
|
|
comments, and columnar comments.
|
|
|
|
_`.comment.banner`: Banner comments come at the start of sections. A banner
|
|
comment consists of a heading usually composed of a symbol, an em-dash
|
|
(--) and an short explanation, followed by English text which is
|
|
formatted using conventional text documentation guidelines (see
|
|
guide.text). The open and close comment tokens (``/*`` and ``*/``) are
|
|
placed at the top and bottom of a column of asterisks. The text is
|
|
separated from the asterisks by one space. Place a blank line between
|
|
the banner comment and the section it comments. For example::
|
|
|
|
/* BlockStruct -- Block descriptor
|
|
*
|
|
* The pool maintains a descriptor structure for each
|
|
* contiguous allocated block of memory it manages.
|
|
* The descriptor is on a simple linked-list of such
|
|
* descriptors, which is in ascending order of address.
|
|
*/
|
|
|
|
typedef struct BlockStruct {
|
|
|
|
_`.comment.para`: Paragraph comments come at the start of paragraphs in the
|
|
code. A paragraph comment consists of formatted English text, with each
|
|
line wrapped by the open and close comment tokens (``/*`` and ``*/``).
|
|
(This avoids problems when cutting and pasting comments.) For example::
|
|
|
|
/* If the freed area is in the base sentinel then insert */
|
|
/* the new descriptor after it, otherwise insert before. */
|
|
if(isBase) {
|
|
|
|
_`.comment.para.precede`: Paragraph comments, even one-liners, precede the
|
|
code to which they apply.
|
|
|
|
_`.comment.column`: Columnar comments appear in a column to the right of
|
|
the code. They should be used sparingly, since they clutter the code and
|
|
make it hard to edit. Use them on variable declarations and structure,
|
|
union, or enum declarations. They should start at least at column 32
|
|
(counting from 0, that is, on a tab-stop), and should be terse
|
|
descriptive text. Abandon English sentence structure if this makes the
|
|
comment clearer. Don't write more than one line. Here's an example::
|
|
|
|
typedef struct PoolMVStruct {
|
|
Pool blockPool; /* for block descriptors */
|
|
Pool spanPool; /* for span descriptors */
|
|
size_t extendBy; /* size to extend pool by */
|
|
size_t avgSize; /* estimate of allocation size */
|
|
size_t maxSize; /* estimate of maximum size */
|
|
Addr space; /* total free space in pool */
|
|
Addr lost; /* lost when free can't allocate */
|
|
struct SpanStruct *spans; /* span chain */
|
|
} PoolMVStruct;
|
|
|
|
Macros
|
|
......
|
|
|
|
_`.macro.careful`: Macros in C are a real horror bag, be extra careful.
|
|
There's lots that could go here, but proper coverage probably deserves a
|
|
separate document. Which isn't written yet.
|
|
|
|
_`.macro.general`: Do try and follow the other formatting conventions for
|
|
code in macro definitions.
|
|
|
|
_`.macro.backslash`: Backslashes used for continuation lines in macro
|
|
definitions should be put on the right somewhere where they will be less
|
|
in the way. Example::
|
|
|
|
#define RAMP_RELATION(X) \
|
|
X(RampOUTSIDE, "outside ramp") \
|
|
X(RampBEGIN, "begin ramp") \
|
|
X(RampRAMPING, "ramping") \
|
|
X(RampFINISH, "finish ramp") \
|
|
X(RampCOLLECTING, "collecting ramp")
|
|
|
|
|
|
History
|
|
-------
|
|
|
|
- 2007-06-04 DRJ_ Adopted from Harlequin MMinfo version and edited.
|
|
|
|
- 2007-06-04 DRJ_ Changed .width from 80 to 72. Banned space between
|
|
``if`` and ``(``. Required braces on almost everything. Clarified that
|
|
paragraph comments precede the code.
|
|
|
|
- 2007-06-13 RHSK_ Removed .brace.block, because MPS source always
|
|
uses .brace.otb. Remove .indent.elseif because it is obvious (ahem) and
|
|
showing an example is sufficient. New rules for .switch.*: current MPS
|
|
practice is a mess, so lay down a neat new law.
|
|
|
|
- 2007-06-27 RHSK_ Added `.space.function.not`_.
|
|
|
|
- 2007-07-17 DRJ_ Added .macro.\*
|
|
|
|
- 2012-09-26 RB_ Converted to Markdown and reversed inconsistent
|
|
switch "law".
|
|
|
|
.. _DRJ: http://www.ravenbrook.com/consultants/drj
|
|
.. _RHSK: http://www.ravenbrook.com/consultants/rhsk
|
|
.. _RB: http://www.ravenbrook.com/consultants/rb
|
|
|
|
|
|
Copyright and License
|
|
---------------------
|
|
|
|
This document is copyright © 2002-2012 [Ravenbrook
|
|
Limited](http://www.ravenbrook.com/). All rights reserved. This is an
|
|
open source license. Contact Ravenbrook for commercial licensing
|
|
options.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
|
|
#. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
#. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
#. Redistributions in any form must be accompanied by information on
|
|
how to obtain complete source code for this software and any
|
|
accompanying software that uses this software. The source code must
|
|
either be included in the distribution or be available for no more
|
|
than the cost of distribution plus a nominal fee, and must be freely
|
|
redistributable under reasonable conditions. For an executable file,
|
|
complete source code means the source code for all modules it
|
|
contains. It does not include source code for modules or files that
|
|
typically accompany the major components of the operating system on
|
|
which the executable file runs.
|
|
|
|
**This software is provided by the copyright holders and contributors
|
|
"as is" and any express or implied warranties, including, but not
|
|
limited to, the implied warranties of merchantability, fitness for a
|
|
particular purpose, or non-infringement, are disclaimed. In no event
|
|
shall the copyright holders and contributors be liable for any direct,
|
|
indirect, incidental, special, exemplary, or consequential damages
|
|
(including, but not limited to, procurement of substitute goods or
|
|
services; loss of use, data, or profits; or business interruption)
|
|
however caused and on any theory of liability, whether in contract,
|
|
strict liability, or tort (including negligence or otherwise) arising in
|
|
any way out of the use of this software, even if advised of the
|
|
possibility of such damage.**
|