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