update gerrit list
[openafs-wiki.git] / devel / CodingStyle.mdwn
1 # <a name="OpenAFS Coding Style"></a> [[OpenAFS]] Coding Style
2
3 This document is an attempt to codify a coding style for [[OpenAFS]]. It's currently the opinions of the author, however. Not all of this is current practice for the tree. If you would like information about our style, as currently used, see README.DEVEL and CODING
4
5 Use gnu indent 2.2.9 or later to reformat using the following:
6
7     gindent -npro -nbad -bap -nbc -bbo -br -ce -cdw -brs -ncdb -cp1 -ncs -di2 -ndj -nfc1 -nfca -i4 -lp -npcs -nprs -psl -sc -nsob -ts8
8
9 **Note for commentors**: Please feel free to update this guide with your views. However, if you disagree with the content, rather than deleting it, please add your suggested ammendments alongside - that way we can hopefully produce a consensus document.
10
11 ## <a name="Comments"></a> Comments
12
13 C++ style comments ( ones beginning //) should be avoided in cross-platform C code
14
15 Single line comments:
16
17     /* This is a one line comment about something or other */
18
19 Mutli line comments should be structured as
20
21     /*
22      * A multi line comment, which should be written as real sentences,
23      * and continue to have a leading star if they span multiple lines
24      */
25
26 Where comments are documenting the behaviour of a piece of code, they should be written in Doxygen. We have adopted the Qt format of that style.
27
28     /*!
29      * A function to compute the cost of everything
30      *
31      * \param currency The currency to perform the calculation in
32      * \param fudge A fudge factor to apply
33      */
34
35 Many more options are possible for doxygen. See their documentation for details.
36
37 ## <a name="Include files"></a> Include files
38
39 All C files should start by including
40
41     #include <afsconfig.h>
42     #include <afs/param.h>
43
44 Following this, all of the necessary system includes should be listed. The following headers may be included without guards
45
46 - ctype.h
47 - errno.h
48 - stdarg.h
49 - stddef.h
50 - stdio.h
51 - stdlib.h
52 - string.h
53 - sys/types.h
54 - sys/stat.h
55 - time.h
56 - fcntl.h
57
58 The following headers may be included for all Unix platforms, but must be protected by #ifndef AFS\_NT40\_ENV
59
60 - syslog.h
61 - sys/param.h
62 - sys/time.h
63 - sys/file.h
64 - sys/ioctl.h
65 - sys/socket.h
66 - sys/uio.h
67 - netinet/in.h
68 - arpa/inet.h
69 - netdb.h
70 - unistd.h
71
72 netinet/in.h should be included before arpa/inet.h
73
74 All other system headers should be protected, either by autoconf checks, or by the relevant platform definitions
75
76 Next, should come all of the AFS headers from the src/include/ directoy. Do not reference headers which occur within other packages by using relative paths - use only the public interfaces in src/include/. Public headers should be referenced using the &lt;&gt; notation.
77
78 Finally come the header files from this module, which should be referenced using " ".
79
80 ## <a name="Preprocessor directives"></a> Preprocessor directives
81
82 Where #if statements are nested, attempt to keep that nesting to a minimum. For example, do
83
84     #if defined(FOO)
85     #elif defined(BAR)
86     #elif defined(BLOB)
87     #endif
88
89 not
90
91     #if defined(FOO)
92     #else
93     # if defined(BAR)
94     # else
95     #  if defined(BLOB)
96     #  endif /* BLOB */
97     # endif /* BAR */
98     #endif /* FOO */
99
100 Where nested #ifs are unavoidable, please indent all preprocessor directives inside the #if or #ifdef by adding on space after the # and before the directive name per nesting level, and annotate #endifs to indicate the statement they refer to.
101
102 ## <a name="Functions"></a> Functions
103
104 Functions should be written with the type information on the first line, followed by the function name on the next, followed by the parameter list, in ANSI C format. Function names are typically StudlyCaps, but the code isn't currently consistent in this regard. Functions which are not being used outside of the source file they are in should be declared static, and prototyped at the start of that file.
105
106 For example:
107
108     static int
109     ValueOfNothing(afs_int32 nothing) {
110         ...
111     }
112
113 Prototypes for functions which are shared within a module should go into the a header file named _module_ \_internal.h
114
115 Prototypes for public functions should go either into _module_ \_prototypes.h_ or module_.h
116
117 Public functions should be prefixed with the name of the module they are in. For example
118
119     witty_CostOfEverything(...)
120
121 Prototypes should not have variable names included within them.
122
123 ## <a name="Headers"></a> Headers
124
125 Header files should be protected against multiple inclusion. Use
126
127     #ifndef AFS_SRC_MODULE_FILENAME_H
128     #define AFS_SRC_MODULE_FILENAME_H
129
130     #endif
131
132 All routines should have a return type specified, void if nothing returned, and should have (void) if no arguments are taken.
133
134 Header files should not contain macros or other definitions unless they are used across multiple source files.
135
136 ## <a name="Formatting"></a> Formatting
137
138 - Indentation is in 4 character spaces, with 8 characters being replaced by a tab.
139 - Always use spaces around operators (+, -, &gt;, &lt;, &amp;&amp;, || and so on)
140 - Don't put a space between the function name and the opening parentheses of its arguments
141 - Always put a space after, but not before a comma in an argument list
142 - Always put a space after a conditional statement (if, while, for, etc) and the opening parentheses, and a space between the ) and the \{
143 - Use braces where it aids readability.
144 - Closing and opening braces go on the same line as the control statement
145
146         if (foo) {
147             ...
148         } else {
149             ...
150         }
151
152 - Code surrounded by brackets should have its continuation lines lined up with the relevant opening brace
153
154         value = CostOfEverything(ValueOfNothing(0),
155                                  fudge);
156
157 - Loops with an empty body should have their trailing semicolon on the following line, to make the empty body explicit, and suppress a compiler warning
158
159         for (...; ...; ...)
160             ;
161
162 - Lines should be wrapped within 80 characters
163
164 ## <a name="Warnings"></a> Warnings
165
166 All new code must compile cleanly when configured with --enable-warnings
167
168 ## <a name="Build system"></a> Build system
169
170 - Do not use $&lt; for non-pattern rules in any cross-platform directory
171 - Do not have build rules that build multiple targets
172 - Ensure that make clean really does
173 - Add new header files as dependencies for files that consume them
174 - Test parallel makes after any build system changes
175 - Test out-of-tree builds after any build system changes
176
177 ## <a name="Cross platform compatibility"></a> Cross platform compatibility
178
179 - Use static\_inline (and hdr\_static\_inline), rather than "static inline" in cross platform code (not all of our platforms support inline functions, and those that do generally specify them differently. The static\_inline macro knows how to do the necessary magic to make them work everywhere.)
180
181 ## <a name="Coding practices"></a> Coding practices
182
183 - Try to use inline functions, rather than casts, when converting from one type to another, except when removing const
184 - Use inline functions, rather than macros wherever possible (as they preserve type checking)
185 - Only use if (var) when var is a boolean. Use if (p != NULL) instead of if (p), and if (\*p!='\\0') rather than if (\*p)
186 - Don't use unsafe string functions. No new code should be using strcpy, or strcat. Use strlcpy, strlcat, or afs\_snprintf() as appropriate.
187 - if (!strcmp(foo,bar)) is really hard to read. Use if (strcmp(foo,bar) == 0) instead
188 - Don't use strncpy unless you explicitly need the special strncpy semantics, and if you don't know what those are, never use it. Use strlcpy or memcpy instead.
189 - Always use size\_t for sizes of objects, not int or unsigned long, even if they're small objects. Exception: wire protocol objects should instead use types with explicit sizes, such as afs\_int32.
190 - Always use either size\_t or ptrdiff\_t for offsets into data structures or memory blocks, not int or long.
191 - All new APIs that take buffers should also take the length of the buffer as an additional parameter.
192 - Where possible, move assignments outside of conditionals. In general, write code = function(); if (code == 0) not if ((code = function()) == 0).
193 - Don't write new functions which take arrays as arguments
194
195 ## <a name="Unix kernel module"></a> Unix kernel module
196
197 - The kernel module has a documented lock hierarchy in src/afs/DOC/afs\_rwlocks
198 - All calls to obtain a write lock have a unique reference number. This must be unique across the cache manager (lock numbers that are in a particular OS directory may be shared, but only between OS directories), and src/afs/lock.h must be updated with the highest number in use
199 - New locks should be registered in the list in afs\_callback.c, so their contents can be viewed via cmdebug
200
201 -- Simon Wilkinson - 27 Jul 2009