aboutsummaryrefslogtreecommitdiff
path: root/busybox/docs/style-guide.txt
diff options
context:
space:
mode:
Diffstat (limited to 'busybox/docs/style-guide.txt')
-rw-r--r--busybox/docs/style-guide.txt680
1 files changed, 680 insertions, 0 deletions
diff --git a/busybox/docs/style-guide.txt b/busybox/docs/style-guide.txt
new file mode 100644
index 000000000..915d9b27d
--- /dev/null
+++ b/busybox/docs/style-guide.txt
@@ -0,0 +1,680 @@
1Busybox Style Guide
2===================
3
4This document describes the coding style conventions used in Busybox. If you
5add a new file to Busybox or are editing an existing file, please format your
6code according to this style. If you are the maintainer of a file that does
7not follow these guidelines, please -- at your own convenience -- modify the
8file(s) you maintain to bring them into conformance with this style guide.
9Please note that this is a low priority task.
10
11To help you format the whitespace of your programs, an ".indent.pro" file is
12included in the main Busybox source directory that contains option flags to
13format code as per this style guide. This way you can run GNU indent on your
14files by typing 'indent myfile.c myfile.h' and it will magically apply all the
15right formatting rules to your file. Please _do_not_ run this on all the files
16in the directory, just your own.
17
18
19
20Declaration Order
21-----------------
22
23Here is the order in which code should be laid out in a file:
24
25 - commented program name and one-line description
26 - commented author name and email address(es)
27 - commented GPL boilerplate
28 - commented longer description / notes for the program (if needed)
29 - #includes of .h files with angle brackets (<>) around them
30 - #includes of .h files with quotes ("") around them
31 - #defines (if any, note the section below titled "Avoid the Preprocessor")
32 - const and global variables
33 - function declarations (if necessary)
34 - function implementations
35
36
37
38Whitespace and Formatting
39-------------------------
40
41This is everybody's favorite flame topic so let's get it out of the way right
42up front.
43
44
45Tabs vs. Spaces in Line Indentation
46~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47
48The preference in Busybox is to indent lines with tabs. Do not indent lines
49with spaces and do not indents lines using a mixture of tabs and spaces. (The
50indentation style in the Apache and Postfix source does this sort of thing:
51\s\s\s\sif (expr) {\n\tstmt; --ick.) The only exception to this rule is
52multi-line comments that use an asterisk at the beginning of each line, i.e.:
53
54 /t/*
55 /t * This is a block comment.
56 /t * Note that it has multiple lines
57 /t * and that the beginning of each line has a tab plus a space
58 /t * except for the opening '/*' line where the slash
59 /t * is used instead of a space.
60 /t */
61
62Furthermore, The preference is that tabs be set to display at four spaces
63wide, but the beauty of using only tabs (and not spaces) at the beginning of
64lines is that you can set your editor to display tabs at *whatever* number of
65spaces is desired and the code will still look fine.
66
67
68Operator Spacing
69~~~~~~~~~~~~~~~~
70
71Put spaces between terms and operators. Example:
72
73 Don't do this:
74
75 for(i=0;i<num_items;i++){
76
77 Do this instead:
78
79 for (i = 0; i < num_items; i++) {
80
81 While it extends the line a bit longer, the spaced version is more
82 readable. An allowable exception to this rule is the situation where
83 excluding the spacing makes it more obvious that we are dealing with a
84 single term (even if it is a compound term) such as:
85
86 if (str[idx] == '/' && str[idx-1] != '\\')
87
88 or
89
90 if ((argc-1) - (optind+1) > 0)
91
92
93Bracket Spacing
94~~~~~~~~~~~~~~~
95
96If an opening bracket starts a function, it should be on the
97next line with no spacing before it. However, if a bracket follows an opening
98control block, it should be on the same line with a single space (not a tab)
99between it and the opening control block statement. Examples:
100
101 Don't do this:
102
103 while (!done)
104 {
105
106 do
107 {
108
109 Don't do this either:
110
111 while (!done){
112
113 do{
114
115 And for heaven's sake, don't do this:
116
117 while (!done)
118 {
119
120 do
121 {
122
123 Do this instead:
124
125 while (!done) {
126
127 do {
128
129
130Spacing around Parentheses
131~~~~~~~~~~~~~~~~~~~~~~~~~~
132
133Put a space between C keywords and left parens, but not between function names
134and the left paren that starts it's parameter list (whether it is being
135declared or called). Examples:
136
137 Don't do this:
138
139 while(foo) {
140 for(i = 0; i < n; i++) {
141
142 Do this instead:
143
144 while (foo) {
145 for (i = 0; i < n; i++) {
146
147 But do functions like this:
148
149 static int my_func(int foo, char bar)
150 ...
151 baz = my_func(1, 2);
152
153Also, don't put a space between the left paren and the first term, nor between
154the last arg and the right paren.
155
156 Don't do this:
157
158 if ( x < 1 )
159 strcmp( thisstr, thatstr )
160
161 Do this instead:
162
163 if (x < 1)
164 strcmp(thisstr, thatstr)
165
166
167Cuddled Elses
168~~~~~~~~~~~~~
169
170Also, please "cuddle" your else statements by putting the else keyword on the
171same line after the right bracket that closes an 'if' statement.
172
173 Don't do this:
174
175 if (foo) {
176 stmt;
177 }
178 else {
179 stmt;
180 }
181
182 Do this instead:
183
184 if (foo) {
185 stmt;
186 } else {
187 stmt;
188 }
189
190The exception to this rule is if you want to include a comment before the else
191block. Example:
192
193 if (foo) {
194 stmts...
195 }
196 /* otherwise, we're just kidding ourselves, so re-frob the input */
197 else {
198 other_stmts...
199 }
200
201
202
203Variable and Function Names
204---------------------------
205
206Use the K&R style with names in all lower-case and underscores occasionally
207used to separate words (e.g., "variable_name" and "numchars" are both
208acceptable). Using underscores makes variable and function names more readable
209because it looks like whitespace; using lower-case is easy on the eyes.
210
211 Frowned upon:
212
213 hitList
214 TotalChars
215 szFileName
216 pf_Nfol_TriState
217
218 Preferred:
219
220 hit_list
221 total_chars
222 file_name
223 sensible_name
224
225Exceptions:
226
227 - Enums, macros, and constant variables are occasionally written in all
228 upper-case with words optionally seperatedy by underscores (i.e. FIFOTYPE,
229 ISBLKDEV()).
230
231 - Nobody is going to get mad at you for using 'pvar' as the name of a
232 variable that is a pointer to 'var'.
233
234
235Converting to K&R
236~~~~~~~~~~~~~~~~~
237
238The Busybox codebase is very much a mixture of code gathered from a variety of
239sources. This explains why the current codebase contains such a hodge-podge of
240different naming styles (Java, Pascal, K&R, just-plain-weird, etc.). The K&R
241guideline explained above should therefore be used on new files that are added
242to the repository. Furthermore, the maintainer of an existing file that uses
243alternate naming conventions should, at his own convenience, convert those
244names over to K&R style. Converting variable names is a very low priority
245task.
246
247If you want to do a search-and-replace of a single variable name in different
248files, you can do the following in the busybox directory:
249
250 $ perl -pi -e 's/\bOldVar\b/new_var/g' *.[ch]
251
252If you want to convert all the non-K&R vars in your file all at once, follow
253these steps:
254
255 - In the busybox directory type 'examples/mk2knr.pl files-to-convert'. This
256 does not do the actual conversion, rather, it generates a script called
257 'convertme.pl' that shows what will be converted, giving you a chance to
258 review the changes beforehand.
259
260 - Review the 'convertme.pl' script that gets generated in the busybox
261 directory and remove / edit any of the substitutions in there. Please
262 especially check for false positives (strings that should not be
263 converted).
264
265 - Type './convertme.pl same-files-as-before' to perform the actual
266 conversion.
267
268 - Compile and see if everything still works.
269
270Please be aware of changes that have cascading effects into other files. For
271example, if you're changing the name of something in, say utility.c, you
272should probably run 'examples/mk2knr.pl utility.c' at first, but when you run
273the 'convertme.pl' script you should run it on _all_ files like so:
274'./convertme.pl *.[ch]'.
275
276
277
278Avoid The Preprocessor
279----------------------
280
281At best, the preprocessor is a necessary evil, helping us account for platform
282and architecture differences. Using the preprocessor unnecessarily is just
283plain evil.
284
285
286The Folly of #define
287~~~~~~~~~~~~~~~~~~~~
288
289Use 'const <type> var' for declaring constants.
290
291 Don't do this:
292
293 #define var 80
294
295 Do this instead, when the variable is in a header file and will be used in
296 several source files:
297
298 const int var = 80;
299
300 Or do this when the variable is used only in a single source file:
301
302 static const int var = 80;
303
304Declaring variables as '[static] const' gives variables an actual type and
305makes the compiler do type checking for you; the preprocessor does _no_ type
306checking whatsoever, making it much more error prone. Declaring variables with
307'[static] const' also makes debugging programs much easier since the value of
308the variable can be easily queried and displayed.
309
310
311The Folly of Macros
312~~~~~~~~~~~~~~~~~~~
313
314Use 'static inline' instead of a macro.
315
316 Don't do this:
317
318 #define mini_func(param1, param2) (param1 << param2)
319
320 Do this instead:
321
322 static inline int mini_func(int param1, param2)
323 {
324 return (param1 << param2);
325 }
326
327Static inline functions are greatly preferred over macros. They provide type
328safety, have no length limitations, no formatting limitations, have an actual
329return value, and under gcc they are as cheap as macros. Besides, really long
330macros with backslashes at the end of each line are ugly as sin.
331
332
333The Folly of #ifdef
334~~~~~~~~~~~~~~~~~~~
335
336Code cluttered with ifdefs is difficult to read and maintain. Don't do it.
337Instead, put your ifdefs at the top of your .c file (or in a header), and
338conditionally define 'static inline' functions, (or *maybe* macros), which are
339used in the code.
340
341 Don't do this:
342
343 ret = my_func(bar, baz);
344 if (!ret)
345 return -1;
346 #ifdef CONFIG_FEATURE_FUNKY
347 maybe_do_funky_stuff(bar, baz);
348 #endif
349
350 Do this instead:
351
352 (in .h header file)
353
354 #ifdef CONFIG_FEATURE_FUNKY
355 static inline void maybe_do_funky_stuff (int bar, int baz)
356 {
357 /* lotsa code in here */
358 }
359 #else
360 static inline void maybe_do_funky_stuff (int bar, int baz) {}
361 #endif
362
363 (in the .c source file)
364
365 ret = my_func(bar, baz);
366 if (!ret)
367 return -1;
368 maybe_do_funky_stuff(bar, baz);
369
370The great thing about this approach is that the compiler will optimize away
371the "no-op" case (the empty function) when the feature is turned off.
372
373Note also the use of the word 'maybe' in the function name to indicate
374conditional execution.
375
376
377
378Notes on Strings
379----------------
380
381Strings in C can get a little thorny. Here's some guidelines for dealing with
382strings in Busybox. (There is surely more that could be added to this
383section.)
384
385
386String Files
387~~~~~~~~~~~~
388
389Put all help/usage messages in usage.c. Put other strings in messages.c.
390Putting these strings into their own file is a calculated decision designed to
391confine spelling errors to a single place and aid internationalization
392efforts, if needed. (Side Note: we might want to use a single file - maybe
393called 'strings.c' - instead of two, food for thought).
394
395
396Testing String Equivalence
397~~~~~~~~~~~~~~~~~~~~~~~~~~
398
399There's a right way and a wrong way to test for sting equivalence with
400strcmp():
401
402 The wrong way:
403
404 if (!strcmp(string, "foo")) {
405 ...
406
407 The right way:
408
409 if (strcmp(string, "foo") == 0){
410 ...
411
412The use of the "equals" (==) operator in the latter example makes it much more
413obvious that you are testing for equivalence. The former example with the
414"not" (!) operator makes it look like you are testing for an error. In a more
415perfect world, we would have a streq() function in the string library, but
416that ain't the world we're living in.
417
418
419Avoid Dangerous String Functions
420~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
421
422Unfortunately, the way C handles strings makes them prone to overruns when
423certain library functions are (mis)used. The following table offers a summary
424of some of the more notorious troublemakers:
425
426function overflows preferred
427----------------------------------------
428strcpy dest string strncpy
429strcat dest string strncat
430gets string it gets fgets
431getwd buf string getcwd
432[v]sprintf str buffer [v]snprintf
433realpath path buffer use with pathconf
434[vf]scanf its arguments just avoid it
435
436
437The above is by no means a complete list. Be careful out there.
438
439
440
441Avoid Big Static Buffers
442------------------------
443
444First, some background to put this discussion in context: Static buffers look
445like this in code:
446
447 /* in a .c file outside any functions */
448 static char *buffer[BUFSIZ]; /* happily used by any function in this file,
449 but ick! big! */
450
451The problem with these is that any time any busybox app is run, you pay a
452memory penalty for this buffer, even if the applet that uses said buffer is
453not run. This can be fixed, thusly:
454
455 static char *buffer;
456 ...
457 other_func()
458 {
459 strcpy(buffer, lotsa_chars); /* happily uses global *buffer */
460 ...
461 foo_main()
462 {
463 buffer = xmalloc(sizeof(char)*BUFSIZ);
464 ...
465
466However, this approach trades bss segment for text segment. Rather than
467mallocing the buffers (and thus growing the text size), buffers can be
468declared on the stack in the *_main() function and made available globally by
469assigning them to a global pointer thusly:
470
471 static char *pbuffer;
472 ...
473 other_func()
474 {
475 strcpy(pbuffer, lotsa_chars); /* happily uses global *pbuffer */
476 ...
477 foo_main()
478 {
479 char *buffer[BUFSIZ]; /* declared locally, on stack */
480 pbuffer = buffer; /* but available globally */
481 ...
482
483This last approach has some advantages (low code size, space not used until
484it's needed), but can be a problem in some low resource machines that have
485very limited stack space (e.g., uCLinux).
486
487A macro is declared in busybox.h that implements compile-time selection
488between xmalloc() and stack creation, so you can code the line in question as
489
490 RESERVE_CONFIG_BUFFER(buffer, BUFSIZ);
491
492and the right thing will happen, based on your configuration.
493
494
495
496Miscellaneous Coding Guidelines
497-------------------------------
498
499The following are important items that don't fit into any of the above
500sections.
501
502
503Model Busybox Applets After GNU Counterparts
504~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
505
506When in doubt about the proper behavior of a Busybox program (output,
507formatting, options, etc.), model it after the equivalent GNU program.
508Doesn't matter how that program behaves on some other flavor of *NIX; doesn't
509matter what the POSIX standard says or doesn't say, just model Busybox
510programs after their GNU counterparts and it will make life easier on (nearly)
511everyone.
512
513The only time we deviate from emulating the GNU behavior is when:
514
515 - We are deliberately not supporting a feature (such as a command line
516 switch)
517 - Emulating the GNU behavior is prohibitively expensive (lots more code
518 would be required, lots more memory would be used, etc.)
519 - The difference is minor or cosmetic
520
521A note on the 'cosmetic' case: Output differences might be considered
522cosmetic, but if the output is significant enough to break other scripts that
523use the output, it should really be fixed.
524
525
526Scope
527~~~~~
528
529If a const variable is used only in a single source file, put it in the source
530file and not in a header file. Likewise, if a const variable is used in only
531one function, do not make it global to the file. Instead, declare it inside
532the function body. Bottom line: Make a conscious effort to limit declarations
533to the smallest scope possible.
534
535Inside applet files, all functions should be declared static so as to keep the
536global name space clean. The only exception to this rule is the "applet_main"
537function which must be declared extern.
538
539If you write a function that performs a task that could be useful outside the
540immediate file, turn it into a general-purpose function with no ties to any
541applet and put it in the utility.c file instead.
542
543
544Brackets Are Your Friends
545~~~~~~~~~~~~~~~~~~~~~~~~~
546
547Please use brackets on all if and else statements, even if it is only one
548line. Example:
549
550 Don't do this:
551
552 if (foo)
553 stmt1;
554 stmt2
555 stmt3;
556
557 Do this instead:
558
559 if (foo) {
560 stmt1;
561 }
562 stmt2
563 stmt3;
564
565The "bracketless" approach is error prone because someday you might add a line
566like this:
567
568 if (foo)
569 stmt1;
570 new_line();
571 stmt2
572 stmt3;
573
574And the resulting behavior of your program would totally bewilder you. (Don't
575laugh, it happens to us all.) Remember folks, this is C, not Python.
576
577
578Function Declarations
579~~~~~~~~~~~~~~~~~~~~~
580
581Do not use old-style function declarations that declare variable types between
582the parameter list and opening bracket. Example:
583
584 Don't do this:
585
586 int foo(parm1, parm2)
587 char parm1;
588 float parm2;
589 {
590 ....
591
592 Do this instead:
593
594 int foo(char parm1, float parm2)
595 {
596 ....
597
598The only time you would ever need to use the old declaration syntax is to
599support ancient, antediluvian compilers. To our good fortune, we have access
600to more modern compilers and the old declaration syntax is neither necessary
601nor desired.
602
603
604Emphasizing Logical Blocks
605~~~~~~~~~~~~~~~~~~~~~~~~~~
606
607Organization and readability are improved by putting extra newlines around
608blocks of code that perform a single task. These are typically blocks that
609begin with a C keyword, but not always.
610
611Furthermore, you should put a single comment (not necessarily one line, just
612one comment) before the block, rather than commenting each and every line.
613There is an optimal ammount of commenting that a program can have; you can
614comment too much as well as too little.
615
616A picture is really worth a thousand words here, the following example
617illustrates how to emphasize logical blocks:
618
619 while (line = get_line_from_file(fp)) {
620
621 /* eat the newline, if any */
622 chomp(line);
623
624 /* ignore blank lines */
625 if (strlen(file_to_act_on) == 0) {
626 continue;
627 }
628
629 /* if the search string is in this line, print it,
630 * unless we were told to be quiet */
631 if (strstr(line, search) && !be_quiet) {
632 puts(line);
633 }
634
635 /* clean up */
636 free(line);
637 }
638
639
640Processing Options with getopt
641~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
642
643If your applet needs to process command-line switches, please use getopt() to
644do so. Numerous examples can be seen in many of the existing applets, but
645basically it boils down to two things: at the top of the .c file, have this
646line in the midst of your #includes:
647
648 #include <getopt.h>
649
650And a code block similar to the following near the top of your applet_main()
651routine:
652
653 while ((opt = getopt(argc, argv, "abc")) > 0) {
654 switch (opt) {
655 case 'a':
656 do_a_opt = 1;
657 break;
658 case 'b':
659 do_b_opt = 1;
660 break;
661 case 'c':
662 do_c_opt = 1;
663 break;
664 default:
665 show_usage(); /* in utility.c */
666 }
667 }
668
669If your applet takes no options (such as 'init'), there should be a line
670somewhere in the file reads:
671
672 /* no options, no getopt */
673
674That way, when people go grepping to see which applets need to be converted to
675use getopt, they won't get false positives.
676
677Additional Note: Do not use the getopt_long library function and do not try to
678hand-roll your own long option parsing. Busybox applets should only support
679short options. Explanations and examples of the short options should be
680documented in usage.h.