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 12lib/checksrc.pl script. Invoked with `make checksrc` or even by default by the 13build 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 document on how we name non-exported library-global symbols. 32 33## Indenting 34 35We use only spaces for indentation, never TABs. We use two spaces for each new 36open brace. 37 38 if(something_is_true) { 39 while(second_statement == fine) { 40 moo(); 41 } 42 } 43 44## Comments 45 46Since we write C89 code, `//` comments are not allowed. They weren't 47introduced in the C standard until C99. We use only `/*` and `*/` comments: 48 49 /* this is a comment */ 50 51## Long lines 52 53Source code in curl may never be wider than 80 columns and there are two 54reasons for maintaining this even in the modern era of very large and high 55resolution screens: 56 571. Narrower columns are easier to read than very wide ones. There's a reason 58 newspapers have used columns for decades or centuries. 59 602. Narrower columns allow developers to easier show multiple pieces of code 61 next to each other in different windows. I often have two or three source 62 code windows next to each other on the same screen - as well as multiple 63 terminal and debugging windows. 64 65## Braces 66 67In if/while/do/for expressions, we write the open brace on the same line as 68the keyword and we then set the closing brace on the same indentation level as 69the initial keyword. Like this: 70 71 if(age < 40) { 72 /* clearly a youngster */ 73 } 74 75When we write functions however, the opening brace should be in the first 76column of the first line: 77 78 int main(int argc, char **argv) 79 { 80 return 1; 81 } 82 83## 'else' on the following line 84 85When adding an `else` clause to a conditional expression using braces, we add 86it on a new line after the closing brace. Like this: 87 88 if(age < 40) { 89 /* clearly a youngster */ 90 } 91 else { 92 /* probably grumpy */ 93 } 94 95## No space before parentheses 96 97When writing expressions using if/while/do/for, there shall be no space 98between the keyword and the open parenthesis. Like this: 99 100 while(1) { 101 /* loop forever */ 102 } 103 104## Use boolean conditions 105 106Rather than test a conditional value such as a bool against TRUE or FALSE, a 107pointer against NULL or != NULL and an int against zero or not zero in 108if/while conditions we prefer: 109 110 result = do_something(); 111 if(!result) { 112 /* something went wrong */ 113 return result; 114 } 115 116## No assignments in conditions 117 118To increase readability and reduce complexity of conditionals, we avoid 119assigning variables within if/while conditions. We frown upon this style: 120 121 if((ptr = malloc(100)) == NULL) 122 return NULL; 123 124and instead we encourage the above version to be spelled out more clearly: 125 126 ptr = malloc(100); 127 if(!ptr) 128 return NULL; 129 130## New block on a new line 131 132We never write multiple statements on the same source line, even for very 133short if() conditions. 134 135 if(a) 136 return TRUE; 137 else if(b) 138 return FALSE; 139 140and NEVER: 141 142 if(a) return TRUE; 143 else if(b) return FALSE; 144 145## Space around operators 146 147Please use spaces on both sides of operators in C expressions. Postfix `(), 148[], ->, ., ++, --` and Unary `+, - !, ~, &` operators excluded they should 149have no space. 150 151Examples: 152 153 bla = func(); 154 who = name[0]; 155 age += 1; 156 true = !false; 157 size += -2 + 3 * (a + b); 158 ptr->member = a++; 159 struct.field = b--; 160 ptr = &address; 161 contents = *pointer; 162 complement = ~bits; 163 empty = (!*string) ? TRUE : FALSE; 164 165## Platform dependent code 166 167Use `#ifdef HAVE_FEATURE` to do conditional code. We avoid checking for 168particular operating systems or hardware in the #ifdef lines. The HAVE_FEATURE 169shall be generated by the configure script for unix-like systems and they are 170hard-coded in the config-[system].h files for the others. 171 172We also encourage use of macros/functions that possibly are empty or defined 173to constants when libcurl is built without that feature, to make the code 174seamless. Like this style where the `magic()` function works differently 175depending on a build-time conditional: 176 177 #ifdef HAVE_MAGIC 178 void magic(int a) 179 { 180 return a + 2; 181 } 182 #else 183 #define magic(x) 1 184 #endif 185 186 int content = magic(3); 187