1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-12 14:30:42 -08:00
emacs/mps/design/cstyle/index.html
Gareth Rees 8cfb023f71 Changes in response to feedback.
Copied from Perforce
 Change: 180094
 ServerID: perforce.ravenbrook.com
2012-10-26 10:22:56 +01:00

619 lines
18 KiB
HTML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>C Style -- Formatting</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#000099" vlink="#660066" alink="#FF0000">
<div align="center">
<p>
<a href="/">Ravenbrook</a> /
<a href="/project/">Projects</a> /
<a href="/project/mps/">Memory Pool System</a>
</p>
<p><i><a href="/project/mps/">Memory Pool System Project</a></i></p>
<hr />
<h1>C Style -- Formatting</h1>
<address>
<a href="mailto:mps-staff@ravenbrook.com">MPS Staff</a>,
<a href="http://www.ravenbrook.com/">Ravenbrook Limited</a>,
1995-08-07
</address>
</div>
<h2 id="section-1">1. Introduction</h2>
<p>
.scope: This document describes the Ravenbrook conventions for the general format
of C source code in the MPS.
</p>
<p>
.readership: This document is intended for anyone working on or with the C
source code.
</p>
<h2 id="section-2">2. General Formatting Conventions</h2>
<h3>Line Width</h3>
<p>
.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.
</p>
<h3>White Space</h3>
<p>
.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.
</p>
<p>
.space.punct: There should always be whitespace after commas and semicolons and
similar punctuation.
</p>
<p>
.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:
</p>
<pre>
foo = x + y*z;
</pre>
<p>
.space.control.not: No space between the keywords <em>if</em>,
<em>switch</em>, <em>while</em>, <em>for</em> and the following paren.
</p>
<p>
.space.function.not: No space between a function name and the
following paren beginning its argument list.
</p>
<p>
.space.function.not: No space between a function name and the
following paren beginning its argument list.
</p>
<h3>Sections and Paragraphs</h3>
<p>
.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.
</p>
<p>
.section.space: Precede sections by two blank lines (except the first one in
the file, which should be the leader comment in any case).
</p>
<p>
.section.comment: Each section should start with a banner comment (see
.comment.banner) describing what the section contains.
</p>
<p>
.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).
</p>
<p>
.para.space: Precede paragraphs by a single blank line.
</p>
<h3>Statements</h3>
<p>
.statement.one: Generally only have at most one statement per line. In
particular the following are deprecated:
</p>
<pre>
if(thing) return;
a=0; b=0;
case 0: f = inRampMode ? AMCGen0RampmodeFrequency : AMCGen0Frequency;
</pre>
<p>
.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.
</p>
<h3>Indentation</h3>
<p>
.indent: Indent the body of a block by two spaces.
For formatting purposes, the "body of a block" means:
</p>
<ul>
<li> statements between braces, </li>
<li> a single statement following a lone if; </li>
<li> statements in a case-clause; see .switch. </li>
</ul>
<p>
(.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).
</p>
<p>
Some examples:
</p>
<pre>
if(res != ResOK) {
SegFinish(&amp;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);
}
case 'A': {
c = 'A';
p += 1;
break;
}
</pre>
<p>
.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.
</p>
<pre>
result foo(void)
{
statement();
if(error)
goto foo;
statement();
return OK;
foo:
unwind();
return ERROR;
}
</pre>
<p>
.indent.case-label.not: Do not outdent case- and default-labels in a
switch statement. See .switch.
</p>
<p>
.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:
</p>
<p>
.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:
</p>
<pre>
PoolClassInit(&amp;PoolClassMVStruct,
"MV", init, finish, allocP, freeP,
NULL, NULL, describe, isValid);
</pre>
<p>
.indent.cont.expr: Note that when breaking an expression it is clearer
to place the operator at the start of the continuation line:
</p>
<pre>
CHECKL(AddrAdd((Addr)chunk->pageTableMapped,
BTSize(chunk->pageTablePages))
&lt;= AddrAdd(chunk->base, chunk->ullageSize));
</pre>
<p>
This is particularly useful in long conditional expressions that use
&amp;&amp; and ||. For example:
</p>
<pre>
} while(trace->state != TraceFINISHED
&amp;&amp; (trace->emergency || traceWorkClock(trace) &lt; pollEnd));
</pre>
<p>
.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.
</p>
<h3>Positioning of Braces</h3>
<p>
.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:
</p>
<pre>
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;
}
</pre>
<p>
The same applies to struct, enum, union.
</p>
<p>
.brace.otb.function.not: OTB is never used for function definitions.
</p>
<p>
.brace.always: Braces are always required after
<em>if</em>, <em>else</em>, <em>switch</em>,
<em>while</em>, <em>do</em>, and <em>for</em>.
</p>
<p>
.brace.always.except: Except that a lone <em>if</em> with no
<em>else</em> is allowed to drop its braces when its body is a single
simple statement. Typically this will be a <em>goto</em> or an
assignment. For example:
</p>
<pre>
if(res != ResOK)
goto failStart;
</pre>
<p>
Note in particular that an <em>if</em> with an <em>else</em> must have
braces on both paths.
</p>
<h3>Switch Statements</h3>
<p>
.switch: format switch statements like this:
</p>
<pre>
switch(action) {
case WIBBLE:
case WOBBLE: {
int angle;
err = move(plate, action, &amp;angle);
break;
}
case QUIESCENT: {
err = 0;
break;
}
default: {
NOTREACHED;
break;
}
}
</pre>
<p>
The component rules that result in this style are:
</p>
<p>
.switch.two-levels: The switch statement as a whole is a block, and
(for formatting purposes) each case- or default-label starts a nested
block within that. <strong>Always</strong> use two levels. Do not
try to 'save a level' by outdenting case-labels: it's an anachronism
from when BSD used 8-column indents, and it causes havoc with brace
positioning.
</p>
<p>
.switch.brace: Put braces around every case-clause body. Put the open
brace on the same line as the last case-label (following .brace.otb). Put
the close brace on a line on its own.
</p>
<p>
.switch.break: The last line of every case-clause body, before the
close brace, must be an unconditional jump statement (usually
<code>break</code>, but may be <code>goto</code>,
<code>continue</code>, or <code>return</code>), or if a fall-through
is intended, the comment <code>/* fall-through */</code>. (Note: if
the unconditional jump should never be taken, because of previous
conditional jumps, use <code>NOTREACHED</code> 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.
</p>
<p>
(.switch.break.outside.not: Do not put the break outside the
case-clause braces: there is no need. Placing it on the last line of
the case-clause body is less weird and equally clear.)
</p>
<p>
.switch.default: It is usually a good idea to have a default-clause,
even if all it contains is <code>NOTREACHED</code> and
<code>break</code>.
</p>
<p>
.switch.new-rules: The above rules are simple, consistent, and not
onerous. But they are also new, so existing MPS source code may not
yet follow them.
</p>
<p>
.switch.horrors: There are currently around 5 different formatting
styles for switch statements in MPS source code: this is madness.
Variation is mostly caused by inventive violations of
.switch.two-levels (either case-label outdenting, or something worse:
see root.c), compounded by inventive violations of OTB for the braces
around the case-clause. The following transgressions are deprecated:
</p>
<pre>
switch(action) {
case WOBBLE: { /* BAD: open brace on outdented case-label line! */
...
} /* BAD: outdented close brace! */
} break; /* BAD: break sharing line with close brace! */
</pre>
<h3>Formatting Comments</h3>
<p>
.comment: There are three types of comments: banners, paragraph comments, and
columnar comments.
</p>
<p>
.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:
</p>
<pre>
/* 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 {
</pre>
<p>
.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:
</p>
<pre>
/* If the freed area is in the base sentinel then insert */
/* the new descriptor after it, otherwise insert before. */
if(isBase) {
</pre>
<p>
.comment.para.precede: Paragraph comments, even one-liners, precede the
code to which they apply.
</p>
<p>
.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:
</p>
<pre>
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;
</pre>
<h3>Macros</h3>
<p>
.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.
</p>
<p>
.macro.general:
Do try and follow the other formatting conventions for code
in macro definitions.
</p>
<p>
.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:
</p>
<pre>
#define RAMP_RELATION(X) \
X(RampOUTSIDE, "outside ramp") \
X(RampBEGIN, "begin ramp") \
X(RampRAMPING, "ramping") \
X(RampFINISH, "finish ramp") \
X(RampCOLLECTING, "collecting ramp")
</pre>
<h2 id="section-B">B. History</h2>
<table>
<tr valign='top'>
<td>2007-06-04</td>
<td><a href="mailto:drj@ravenbrook.com">DRJ</a></td>
<td>Adopted from
//info.ravenbrook.com/project/mps/doc/2002-06-18/obsolete-mminfo/mminfo/guide/impl/c/format/index.txt
and edited.</td>
</tr>
<tr valign='top'>
<td nowrap="nowrap">2007-06-04</td>
<td><a href="mailto:drj@ravenbrook.com">DRJ</a></td>
<td>Changed .width from 80 to 72. Banned space between "if" and "(".
Required braces on almost everything. Clarified that paragraph comments
precede the code.
</td>
</tr>
<tr valign='top'>
<td>2007-06-13</td>
<td><a href="mailto:rhsk@ravenbrook.com">RHSK</a></td>
<td>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.
</td>
</tr>
<tr valign='top'>
<td>2007-06-27</td>
<td><a href="mailto:rhsk@ravenbrook.com">RHSK</a></td>
<td>Added .space.function.not.
</td>
</tr>
<tr valign='top'>
<td>2007-07-17</td>
<td><a href="mailto:drj@ravenbrook.com">DRJ</a></td>
<td>Added .macro.*</td>
</td>
</tr>
</table>
<h2><a id="section-C" name="section-C">C. Copyright and License</a></h2>
<p> This document is copyright &copy; 2002-2005, 2007 <a href="http://www.ravenbrook.com/">Ravenbrook Limited</a>. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. </p>
<p> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: </p>
<ol>
<li> Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. </li>
<li> 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. </li>
<li> 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. </li>
</ol>
<p> <strong> 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. </strong> </p>
<hr />
<div align="center">
<p><code>$Id: //info.ravenbrook.com/project/mps/master/index.html#8 $</code></p>
<p>
<a href="/">Ravenbrook</a> /
<a href="/project/">Projects</a> /
<a href="/project/mps/">Memory Pool System</a>
</p>
</div>
</body>
</html>