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 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
|
<!--
Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
# curl C code style
Source code that has a common style is easier to read than code that uses
different styles in different places. It helps making the code feel like one
single code base. Easy-to-read is an important property of code and helps
making it easier to review when new things are added and it helps debugging
code when developers are trying to figure out why things go wrong. A unified
style is more important than individual contributors having their own personal
tastes satisfied.
Our C code has a few style rules. Most of them are verified and upheld by the
`scripts/checksrc.pl` script. Invoked with `make checksrc` or even by default
by the build system when built after `./configure --enable-debug` has been
used.
It is normally not a problem for anyone to follow the guidelines, copy
the style already used in the source code and there are no particularly
unusual rules in our set of rules.
We also work hard on writing code that are warning-free on all the major
platforms and in general on as many platforms as possible. Code that causes
warnings is not accepted as-is.
## Readability
A primary characteristic for code is readability. The intent and meaning of
the code should be visible to the reader. Being clear and unambiguous beats
being clever and saving two lines of code. Write simple code. You and others
who come back to this code over the coming decades want to be able to quickly
understand it when debugging.
## Naming
Try using a non-confusing naming scheme for your new functions and variable
names. It does not necessarily have to mean that you should use the same as in
other places of the code, only that the names should be logical,
understandable and be named according to what they are used for. File-local
functions should be made static. We like lower case names.
See the [INTERNALS](https://curl.se/dev/internals.html#symbols) document on
how we name non-exported library-global symbols.
## Indenting
We use only spaces for indentation, never TABs. We use two spaces for each new
open brace.
```c
if(something_is_true) {
while(second_statement == fine) {
moo();
}
}
```
## Comments
Since we write C89 code, **//** comments are not allowed. They were not
introduced in the C standard until C99. We use only __/* comments */__.
```c
/* this is a comment */
```
## Long lines
Source code in curl may never be wider than 79 columns and there are two
reasons for maintaining this even in the modern era of large and high
resolution screens:
1. Narrower columns are easier to read than wide ones. There is a reason
newspapers have used columns for decades or centuries.
2. Narrower columns allow developers to easier show multiple pieces of code
next to each other in different windows. It allows two or three source
code windows next to each other on the same screen - as well as multiple
terminal and debugging windows.
## Braces
In if/while/do/for expressions, we write the open brace on the same line as
the keyword and we then set the closing brace on the same indentation level as
the initial keyword. Like this:
```c
if(age < 40) {
/* clearly a youngster */
}
```
You may omit the braces if they would contain only a one-line statement:
```c
if(!x)
continue;
```
For functions the opening brace should be on a separate line:
```c
int main(int argc, char **argv)
{
return 1;
}
```
## 'else' on the following line
When adding an **else** clause to a conditional expression using braces, we
add it on a new line after the closing brace. Like this:
```c
if(age < 40) {
/* clearly a youngster */
}
else {
/* probably grumpy */
}
```
## No space before parentheses
When writing expressions using if/while/do/for, there shall be no space
between the keyword and the open parenthesis. Like this:
```c
while(1) {
/* loop forever */
}
```
## Use boolean conditions
Rather than test a conditional value such as a bool against TRUE or FALSE, a
pointer against NULL or != NULL and an int against zero or not zero in
if/while conditions we prefer:
```c
result = do_something();
if(!result) {
/* something went wrong */
return result;
}
```
## No assignments in conditions
To increase readability and reduce complexity of conditionals, we avoid
assigning variables within if/while conditions. We frown upon this style:
```c
if((ptr = malloc(100)) == NULL)
return NULL;
```
and instead we encourage the above version to be spelled out more clearly:
```c
ptr = malloc(100);
if(!ptr)
return NULL;
```
## New block on a new line
We never write multiple statements on the same source line, even for short
if() conditions.
```c
if(a)
return TRUE;
else if(b)
return FALSE;
```
and NEVER:
```c
if(a) return TRUE;
else if(b) return FALSE;
```
## Space around operators
Please use spaces on both sides of operators in C expressions. Postfix **(),
[], ->, ., ++, --** and Unary **+, -, !, ~, &** operators excluded they should
have no space.
Examples:
```c
bla = func();
who = name[0];
age += 1;
true = !false;
size += -2 + 3 * (a + b);
ptr->member = a++;
struct.field = b--;
ptr = &address;
contents = *pointer;
complement = ~bits;
empty = (!*string) ? TRUE : FALSE;
```
## No parentheses for return values
We use the 'return' statement without extra parentheses around the value:
```c
int works(void)
{
return TRUE;
}
```
## Parentheses for sizeof arguments
When using the sizeof operator in code, we prefer it to be written with
parentheses around its argument:
```c
int size = sizeof(int);
```
## Column alignment
Some statements cannot be completed on a single line because the line would be
too long, the statement too hard to read, or due to other style guidelines
above. In such a case the statement spans multiple lines.
If a continuation line is part of an expression or sub-expression then you
should align on the appropriate column so that it is easy to tell what part of
the statement it is. Operators should not start continuation lines. In other
cases follow the 2-space indent guideline. Here are some examples from
libcurl:
```c
if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
(handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
(handle->set.httpreq == HTTPREQ_GET ||
handle->set.httpreq == HTTPREQ_HEAD))
/* did not ask for HTTP/1.0 and a GET or HEAD */
return TRUE;
```
If no parenthesis, use the default indent:
```c
data->set.http_disable_hostname_check_before_authentication =
va_arg(param, long) ? TRUE : FALSE;
```
Function invoke with an open parenthesis:
```c
if(option) {
result = parse_login_details(option, strlen(option),
(userp ? &user : NULL),
(passwdp ? &passwd : NULL),
NULL);
}
```
Align with the "current open" parenthesis:
```c
DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
"server response left\n",
(int)clipamount));
```
## Platform dependent code
Use **#ifdef HAVE_FEATURE** to do conditional code. We avoid checking for
particular operating systems or hardware in the #ifdef lines. The HAVE_FEATURE
shall be generated by the configure script for Unix-like systems and they are
hard-coded in the `config-[system].h` files for the others.
We also encourage use of macros/functions that possibly are empty or defined
to constants when libcurl is built without that feature, to make the code
seamless. Like this example where the **magic()** function works differently
depending on a build-time conditional:
```c
#ifdef HAVE_MAGIC
void magic(int a)
{
return a + 2;
}
#else
#define magic(x) 1
#endif
int content = magic(3);
```
## No typedefed structs
Use structs by all means, but do not typedef them. Use the `struct name` way
of identifying them:
```c
struct something {
void *valid;
size_t way_to_write;
};
struct something instance;
```
**Not okay**:
```c
typedef struct {
void *wrong;
size_t way_to_write;
} something;
something instance;
```
## Banned functions
To avoid footguns and unintended consequences we forbid the use of a number of
C functions. The `checksrc` script finds and yells about them if used. This
makes us write better code.
This is the full list of functions generally banned.
_access
_fstati64
_lseeki64
_mbscat
_mbsncat
_open
_tcscat
_tcsdup
_tcsncat
_tcsncpy
_waccess
_wcscat
_wcsdup
_wcsncat
_wfopen
_wfreopen
_wopen
accept
accept4
access
aprintf
atoi
atol
calloc
close
CreateFile
CreateFileA
CreateFileW
fclose
fdopen
fopen
fprintf
free
freeaddrinfo
freopen
fstat
getaddrinfo
gets
gmtime
llseek
LoadLibrary
LoadLibraryA
LoadLibraryEx
LoadLibraryExA
LoadLibraryExW
LoadLibraryW
localtime
lseek
malloc
mbstowcs
MoveFileEx
MoveFileExA
MoveFileExW
msnprintf
mvsnprintf
open
printf
realloc
recv
rename
send
snprintf
socket
socketpair
sprintf
sscanf
stat
strcat
strcpy
strdup
strerror
strncat
strncpy
strtok
strtok_r
strtol
strtoul
vaprintf
vfprintf
vprintf
vsnprintf
vsprintf
wcscpy
wcsdup
wcsncpy
wcstombs
WSASocket
WSASocketA
WSASocketW
|