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