1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
===========================================================================
Freeciv Style Guide
===========================================================================
If you want to hack Freeciv, and want your patches to be accepted, it
helps to follow some simple style rules. Yes, some of these are a bit
nit-picky, but wars are fought over the silliest things...
- Freeciv is programmed in plain C (except the BEOS client). This
means that C++ features like:
- C++-style comments (i.e., // comments) and
- declaration variables in the middle of the function body
are forbidden.
- Use K&R indentation style with indentation 2 (if in doubt, use
"indent -kr -i2 -l77"). However, do not re-indent areas of code you
are not modifying or creating. Here are the most important properties:
- lines are at most 77 chars long
- spaces are inserted before and after operators (instead of
"int a,b,c;" use "int i, j, k;" and instead of "if(foo<=bar) c=a+b;"
use "if (foo <= bar) c = a + b;" -- note the space between "if"
and the bracket)
- function braces begin and end in the first column.
int foo()
{
return 0;
}
instead of
int foo() {
return 0;
}
- the tab width is 8
- the indentation is 2 columns per level
- An empty line should be placed between two separate blocks of code.
- Place operators at the beginning of a line, not at the end. It should be
if ((a
&& b)
|| c) {
instead of
if ((a &&
b) ||
c) {
================================
Comments
================================
- Every function should have a comment header. The comment should look
like the example below, indented by two spaces. It should be above the
function's implementation, not the prototype:
/*************************************************************************
the description of the function should be here
any information is helpful, such as who calls this function, etc.
do _not_ introduce a new function without some sort of comment.
*************************************************************************/
int the_function_starts_here(int value)
{
...
}
- One line comments. Comments should be indented correctly and
placed above the code being commented upon:
int x;
/* I am a single line comment */
x = 3;
- Multiline comments. Asterisks should be placed in front of the
comment line like so:
/* I am a multiline
* comment, blah
* blah blah */
- Comments in declarations. If you need to comment a declared variable,
it should be as such:
struct foo {
int bar; /* bar is used for ....
* in ..... way */
int blah; /* blah is used for .... */
};
- Comments in conditionals. If you need a comment to show program flow,
it should be below the if or else:
if (is_barbarian(pplayer)) {
x++;
} else {
/* If not barbarian, ... */
x--;
}
- Comments to translators are stored before the N_(), _() or Q_() marked
string, and are preceded by "TRANS:". These comments are copied to the
translators file. Use them whenever you think the translators may need
some more information:
/* TRANS: Don't translate "commandname". */
printf(_("commandname <arg> [-o <optarg>]"));
================================
Declaring variables
================================
- Variables can be initialized as soon as they're declared:
int foo(struct unit *punit)
{
int x = punit->x;
int foo = x;
char *blah;
...
}
- After variables are declared, there should be an empty line before the
rest of the function body.
- Merging declarations. Variables do not have to be declared one per line;
however, they should only be grouped by similar function.
int foo(struct city *pcity)
{
int i, j, k;
int total, cost;
int build = pcity->shield_stock;
}
================================
Bracing
================================
- Extra braces on iterates. Note that the *_iterate_end; should be placed
on the same line as the end brace:
unit_list_iterate(pcity->units_supported, punit) {
kill(punit);
} unit_list_iterate_end;
- In switch statements, braces should only be placed where needed, i.e. to
protect local variables.
- Braces shall be used after conditionals:
if (x == 3) {
return;
}
and
if (x == 3) {
return 1;
} else {
return 0;
}
not
if (x == 3)
return 1; /* BAD! */
================================
Other stuff
================================
- If an empty block is needed you should put an explanatory comment in
an empty block (i.e. {}):
while (*i++) {
/* nothing */
}
- Use the postfix operator instead of the prefix operator when either will
work. That is, write "a++" instead of "++a".
- Order include files consistently: All includes are grouped
together. These groups are divided by an empty line. The order of
these groups are as follow:
1) config.h (see below)
2) system include files which are OS-independent (part of
C-standard or POSIX)
3) system include files which are OS-dependent or conditional
includes
4) include files from common/ and common/aicore
5) include files from client/, client/include and client/agents
6) include files from client/gui-*
7) include files from server/
8) include files from ai/
Each group is sorted in alphabetic order. This helps to avoid adding
unnecessary or duplicated include files.
It is very important that '#include <config.h>' be included at the top of
every .c file (it need not be included from .h files). Some definitions in
config.h will affect how the code is compiled, without which you can end
up with bad and untraceable memory bugs.
- If you use a system specific feature, don't add #ifdef __CRAY__ or
something like that. Rather write a check for that feature for
both configure.in and configure.ac, and use a meaningful macro name
in the source.
- Always prototype global functions in the appropriate header file.
Local functions should always be declared as static. To catch these
and some other problems please use the following warning options
"-Wall -Wpointer-arith -Wcast-align -Wmissing-prototypes
-Wmissing-declarations -Wstrict-prototypes -Wnested-externs" if you
use gcc.
- Header files should be compatible with C++ but code (.c) files need not
be. This means some C++ keywords (like "this" or "class") may not be
used in header files. It also means casts on void pointers (which should
be avoided in C files) must be used in headers.
- If you send patches, use "diff -u" (or "diff -r -u"). "svn diff" works
correctly without extra parameters.
For further information, see
<http://www.freeciv.org/index.php/How_to_Contribute>.
Also, name patch files descriptively (e.g. "fix-foo-bug-0.diff" is good,
but "freeciv.diff" is not).
- When doing a "diff" for a patch, be sure to exclude unnecessary files
by using the "-X" argument to "diff". E.g.:
% diff -ruN -Xdiff_ignore freeciv_svn freeciv >/tmp/fix-foo-bug-0.diff
A suggested "diff_ignore" file is included in the Freeciv distribution.
===========================================================================
|