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