1: # curl C code style
2:
3: Source code that has a common style is easier to read than code that uses
4: different styles in different places. It helps making the code feel like one
5: single code base. Easy-to-read is a very important property of code and helps
6: making it easier to review when new things are added and it helps debugging
7: code when developers are trying to figure out why things go wrong. A unified
8: style is more important than individual contributors having their own personal
9: tastes satisfied.
10:
11: Our 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
13: the build system when built after `./configure --enable-debug` has been used.
14:
15: It is normally not a problem for anyone to follow the guidelines, as you just
16: need to copy the style already used in the source code and there are no
17: particularly unusual rules in our set of rules.
18:
19: We also work hard on writing code that are warning-free on all the major
20: platforms and in general on as many platforms as possible. Code that obviously
21: will cause warnings will not be accepted as-is.
22:
23: ## Naming
24:
25: Try using a non-confusing naming scheme for your new functions and variable
26: names. It doesn't necessarily have to mean that you should use the same as in
27: other places of the code, just that the names should be logical,
28: understandable and be named according to what they're used for. File-local
29: functions should be made static. We like lower case names.
30:
31: See the [INTERNALS](INTERNALS.md) document on how we name non-exported
32: library-global symbols.
33:
34: ## Indenting
35:
36: We use only spaces for indentation, never TABs. We use two spaces for each new
37: open brace.
38:
39: if(something_is_true) {
40: while(second_statement == fine) {
41: moo();
42: }
43: }
44:
45: ## Comments
46:
47: Since we write C89 code, **//** comments are not allowed. They weren't
48: introduced in the C standard until C99. We use only **/* comments */**.
49:
50: /* this is a comment */
51:
52: ## Long lines
53:
54: Source code in curl may never be wider than 79 columns and there are two
55: reasons for maintaining this even in the modern era of very large and high
56: resolution screens:
57:
58: 1. Narrower columns are easier to read than very wide ones. There's a reason
59: newspapers have used columns for decades or centuries.
60:
61: 2. 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:
68: In if/while/do/for expressions, we write the open brace on the same line as
69: the keyword and we then set the closing brace on the same indentation level as
70: the initial keyword. Like this:
71:
72: if(age < 40) {
73: /* clearly a youngster */
74: }
75:
76: You may omit the braces if they would contain only a one-line statement:
77:
78: if(!x)
79: continue;
80:
81: For 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:
90: When adding an **else** clause to a conditional expression using braces, we
91: add 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:
102: When writing expressions using if/while/do/for, there shall be no space
103: between the keyword and the open parenthesis. Like this:
104:
105: while(1) {
106: /* loop forever */
107: }
108:
109: ## Use boolean conditions
110:
111: Rather than test a conditional value such as a bool against TRUE or FALSE, a
112: pointer against NULL or != NULL and an int against zero or not zero in
113: if/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:
123: To increase readability and reduce complexity of conditionals, we avoid
124: assigning variables within if/while conditions. We frown upon this style:
125:
126: if((ptr = malloc(100)) == NULL)
127: return NULL;
128:
129: and 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:
137: We never write multiple statements on the same source line, even for very
138: short if() conditions.
139:
140: if(a)
141: return TRUE;
142: else if(b)
143: return FALSE;
144:
145: and NEVER:
146:
147: if(a) return TRUE;
148: else if(b) return FALSE;
149:
150: ## Space around operators
151:
152: Please use spaces on both sides of operators in C expressions. Postfix **(),
153: [], ->, ., ++, --** and Unary **+, - !, ~, &** operators excluded they should
154: have no space.
155:
156: Examples:
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:
172: We 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:
181: When using the sizeof operator in code, we prefer it to be written with
182: parentheses around its argument:
183:
184: int size = sizeof(int);
185:
186: ## Column alignment
187:
188: Some statements cannot be completed on a single line because the line would be
189: too long, the statement too hard to read, or due to other style guidelines
190: above. In such a case the statement will span multiple lines.
191:
192: If a continuation line is part of an expression or sub-expression then you
193: should align on the appropriate column so that it's easy to tell what part of
194: the statement it is. Operators should not start continuation lines. In other
195: cases follow the 2-space indent guideline. Here are some examples from
196: libcurl:
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:
205: If 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:
210: Function 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:
219: Align 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:
227: Use **#ifdef HAVE_FEATURE** to do conditional code. We avoid checking for
228: particular operating systems or hardware in the #ifdef lines. The HAVE_FEATURE
229: shall be generated by the configure script for unix-like systems and they are
230: hard-coded in the `config-[system].h` files for the others.
231:
232: We also encourage use of macros/functions that possibly are empty or defined
233: to constants when libcurl is built without that feature, to make the code
234: seamless. Like this example where the **magic()** function works differently
235: depending 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);
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>