xref: /curl/docs/internals/CODE_STYLE.md (revision 20aa8d8f)
1<!--
2Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
3
4SPDX-License-Identifier: curl
5-->
6
7# curl C code style
8
9Source code that has a common style is easier to read than code that uses
10different styles in different places. It helps making the code feel like one
11single code base. Easy-to-read is an important property of code and helps
12making it easier to review when new things are added and it helps debugging
13code when developers are trying to figure out why things go wrong. A unified
14style is more important than individual contributors having their own personal
15tastes satisfied.
16
17Our C code has a few style rules. Most of them are verified and upheld by the
18`scripts/checksrc.pl` script. Invoked with `make checksrc` or even by default
19by the build system when built after `./configure --enable-debug` has been
20used.
21
22It is normally not a problem for anyone to follow the guidelines, as you just
23need to copy the style already used in the source code and there are no
24particularly unusual rules in our set of rules.
25
26We also work hard on writing code that are warning-free on all the major
27platforms and in general on as many platforms as possible. Code that obviously
28causes warnings is not accepted as-is.
29
30## Naming
31
32Try using a non-confusing naming scheme for your new functions and variable
33names. It does not necessarily have to mean that you should use the same as in
34other places of the code, just that the names should be logical,
35understandable and be named according to what they are used for. File-local
36functions should be made static. We like lower case names.
37
38See the [INTERNALS](https://curl.se/dev/internals.html#symbols) document on
39how we name non-exported library-global symbols.
40
41## Indenting
42
43We use only spaces for indentation, never TABs. We use two spaces for each new
44open brace.
45
46```c
47if(something_is_true) {
48  while(second_statement == fine) {
49    moo();
50  }
51}
52```
53
54## Comments
55
56Since we write C89 code, **//** comments are not allowed. They were not
57introduced in the C standard until C99. We use only __/* comments */__.
58
59```c
60/* this is a comment */
61```
62
63## Long lines
64
65Source code in curl may never be wider than 79 columns and there are two
66reasons for maintaining this even in the modern era of large and high
67resolution screens:
68
691. Narrower columns are easier to read than wide ones. There is a reason
70   newspapers have used columns for decades or centuries.
71
722. Narrower columns allow developers to easier show multiple pieces of code
73   next to each other in different windows. It allows two or three source
74   code windows next to each other on the same screen - as well as multiple
75   terminal and debugging windows.
76
77## Braces
78
79In if/while/do/for expressions, we write the open brace on the same line as
80the keyword and we then set the closing brace on the same indentation level as
81the initial keyword. Like this:
82
83```c
84if(age < 40) {
85  /* clearly a youngster */
86}
87```
88
89You may omit the braces if they would contain only a one-line statement:
90
91```c
92if(!x)
93  continue;
94```
95
96For functions the opening brace should be on a separate line:
97
98```c
99int main(int argc, char **argv)
100{
101  return 1;
102}
103```
104
105## 'else' on the following line
106
107When adding an **else** clause to a conditional expression using braces, we
108add it on a new line after the closing brace. Like this:
109
110```c
111if(age < 40) {
112  /* clearly a youngster */
113}
114else {
115  /* probably grumpy */
116}
117```
118
119## No space before parentheses
120
121When writing expressions using if/while/do/for, there shall be no space
122between the keyword and the open parenthesis. Like this:
123
124```c
125while(1) {
126  /* loop forever */
127}
128```
129
130## Use boolean conditions
131
132Rather than test a conditional value such as a bool against TRUE or FALSE, a
133pointer against NULL or != NULL and an int against zero or not zero in
134if/while conditions we prefer:
135
136```c
137result = do_something();
138if(!result) {
139  /* something went wrong */
140  return result;
141}
142```
143
144## No assignments in conditions
145
146To increase readability and reduce complexity of conditionals, we avoid
147assigning variables within if/while conditions. We frown upon this style:
148
149```c
150if((ptr = malloc(100)) == NULL)
151  return NULL;
152```
153
154and instead we encourage the above version to be spelled out more clearly:
155
156```c
157ptr = malloc(100);
158if(!ptr)
159  return NULL;
160```
161
162## New block on a new line
163
164We never write multiple statements on the same source line, even for short
165if() conditions.
166
167```c
168if(a)
169  return TRUE;
170else if(b)
171  return FALSE;
172```
173
174and NEVER:
175
176```c
177if(a) return TRUE;
178else if(b) return FALSE;
179```
180
181## Space around operators
182
183Please use spaces on both sides of operators in C expressions. Postfix **(),
184[], ->, ., ++, --** and Unary **+, -, !, ~, &** operators excluded they should
185have no space.
186
187Examples:
188
189```c
190bla = func();
191who = name[0];
192age += 1;
193true = !false;
194size += -2 + 3 * (a + b);
195ptr->member = a++;
196struct.field = b--;
197ptr = &address;
198contents = *pointer;
199complement = ~bits;
200empty = (!*string) ? TRUE : FALSE;
201```
202
203## No parentheses for return values
204
205We use the 'return' statement without extra parentheses around the value:
206
207```c
208int works(void)
209{
210  return TRUE;
211}
212```
213
214## Parentheses for sizeof arguments
215
216When using the sizeof operator in code, we prefer it to be written with
217parentheses around its argument:
218
219```c
220int size = sizeof(int);
221```
222
223## Column alignment
224
225Some statements cannot be completed on a single line because the line would be
226too long, the statement too hard to read, or due to other style guidelines
227above. In such a case the statement spans multiple lines.
228
229If a continuation line is part of an expression or sub-expression then you
230should align on the appropriate column so that it is easy to tell what part of
231the statement it is. Operators should not start continuation lines. In other
232cases follow the 2-space indent guideline. Here are some examples from
233libcurl:
234
235```c
236if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
237   (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
238   (handle->set.httpreq == HTTPREQ_GET ||
239    handle->set.httpreq == HTTPREQ_HEAD))
240  /* did not ask for HTTP/1.0 and a GET or HEAD */
241  return TRUE;
242```
243
244If no parenthesis, use the default indent:
245
246```c
247data->set.http_disable_hostname_check_before_authentication =
248  (0 != va_arg(param, long)) ? TRUE : FALSE;
249```
250
251Function invoke with an open parenthesis:
252
253```c
254if(option) {
255  result = parse_login_details(option, strlen(option),
256                               (userp ? &user : NULL),
257                               (passwdp ? &passwd : NULL),
258                               NULL);
259}
260```
261
262Align with the "current open" parenthesis:
263
264```c
265DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
266             "server response left\n",
267             (int)clipamount));
268```
269
270## Platform dependent code
271
272Use **#ifdef HAVE_FEATURE** to do conditional code. We avoid checking for
273particular operating systems or hardware in the #ifdef lines. The HAVE_FEATURE
274shall be generated by the configure script for Unix-like systems and they are
275hard-coded in the `config-[system].h` files for the others.
276
277We also encourage use of macros/functions that possibly are empty or defined
278to constants when libcurl is built without that feature, to make the code
279seamless. Like this example where the **magic()** function works differently
280depending on a build-time conditional:
281
282```c
283#ifdef HAVE_MAGIC
284void magic(int a)
285{
286  return a + 2;
287}
288#else
289#define magic(x) 1
290#endif
291
292int content = magic(3);
293```
294
295## No typedefed structs
296
297Use structs by all means, but do not typedef them. Use the `struct name` way
298of identifying them:
299
300```c
301struct something {
302   void *valid;
303   size_t way_to_write;
304};
305struct something instance;
306```
307
308**Not okay**:
309
310```c
311typedef struct {
312   void *wrong;
313   size_t way_to_write;
314} something;
315something instance;
316```
317