Mercurial > ~dholland > hg > ag > index.cgi
view doc/devel/style.txt @ 2:4b08ee1ecb99
Adjust install notes to clarify that Wine applies only to the Windows build.
(Thanks to Perry Metzger for test-driving.)
author | David A. Holland |
---|---|
date | Sun, 26 Apr 2009 17:58:26 -0400 |
parents | 13d2b8934445 |
children | 12171da8943f |
line wrap: on
line source
Style guidelines for AnaGram source ----------------------------------- Purpose: These guidelines are *guidelines*, not commandments. Legibility and maintainability are more important than mindless adherence to regulations. Note: patches that reindent or reformat will be rejected. Patches whose only purpose is to reindent or reformat will be rejected extra-fast. If you think a section of code needs reformatting, write a message saying so and explain your reasoning. Illegibility and violation of the principle of least surprise are good reasons. Lack of strict conformance to these guidelines is not. Note: some source files have DOS-style end of line (CR/LF) and others have Unix-style end of line (just LF) - for the most part this should be transparent. So leave things the way they are in this regard. Basic layout guidelines, in order of decreasing generality: - 2-space indent. - Lines do not exceed 79 columns. - Don't indent preprocessor directives. - In a multi-line /* */ comment, the beginning and ending tokens get their own lines, and all the stars should line up. - Left braces go at the end of the line. - Right braces get their own line. - 'else' starts a new line. - Use braces with if, else, while, do/while, and for. - If violating the previous rule, always put the subordinate statement on the same line. - Violate said rule for conciseness only when: - a single if (no else) has a very short conditional and a very short subordinate statement; - a while statement ditto; - or a for statement has no body. - Never violate said rule for a do/while statement. - Put the while part of a do/while statement on the same line as the closing brace, to keep them from getting separated. - Switch case labels should be indented two spaces, and code indented two spaces further. - Each switch case label should get its own line. - Switch code should not be on the same line as a switch case. - Condensed switches (one line total per case) should only be used if all or nearly all the switch can be formatted thus and some benefit to legibility accrues. - Infinite loops should be written as "while (1)", not "for (;;)". Please do not: - Misgroup tokens when declaring pointers. "char* s" is wrong. It should be "char *s". - Write your comparisons backwards. "if (0 == x)" is really unnatural to read. - Leave off the space after while, for, and if, or, conversely, insert a space between a function name and its arguments. while, for, and if are not functions. - Use gratuitous parentheses with return to make it look like a function call. Include files: - Include files should be grouped in this order: - standard C includes - OS, compiler, or GUI-specific includes - AG's own includes - Within these groupings, headers should appear in alphabetical order. (Why...? Why not?) - Exceptions: any <sys/*.h> should come before other standard headers. And if any <sys/*.h> are used, <sys/types.h> should come first. Also, "pf.h" should be included after any standard headers. - Further exceptions: AG's log header should come last, and should be preceded by a commented-out "#define INCLUDE_LOGGING". Examples abound. - To the extent practical, don't use (even within AG_ON_UNIX) header files that aren't standard or standardish Unix, or that would require build-time tests in the configure script to make work right. - Each AG header file should be idempotent, that is, a source file that just includes it should be compilable and its compilation should not be affected by whether other headers have been included or in what order. - Each header should have an #ifndef guard in the standard form to protect against repeated inclusion. - Do not use the standard <assert.h> within AG - only use AG's own "assert.h". ifdefs: - Use #ifdef AG_ON_UNIX and #ifdef AG_ON_WINDOWS for platform-specific code. Don't use compiler ifdefs for this; in the long run compilers are more portable than you think. - Don't use #ifndef AG_ON_UNIX or #ifndef AG_ON_WINDOWS, unless it's to issue a #error. - Don't use #if defined() in place of #ifdef. - Do mark #endifs with the symbol from their matching #ifdef, #ifndef, or #if, unless that directive is only a few lines above and easily recognizable. - Use compiler-specific ifdefs only where you have to. If possible, abstract the construct out to minimize the amount of conditional code. - If a compiler doesn't have a well-known, safe, and/or easily recognizable symbol to #ifdef on, adjust the makefiles to set one when that compiler is used, rather than litter the code with possibly flaky ifdefs. - Don't use processor-specific ifdefs. Write portable code. C++ language restrictions: - Do not use STL headers. - Do not use << >> operators for I/O. - Declare functions with no arguments as explicitly taking void, like you would in C. - Don't do wild things with templates. - Don't do "for (int i=0; ...)" - we have a compiler that uses the really old scoping semantics for this. - Use your common sense. Neither the language nor compiler has any. Portability concerns: - When using fopen, always use "b" with binary files. Don't use "t" for text files, as this is nonstandard and at least one Windows compiler's library objects to it. - When using open(), always use either O_BINARY or O_TEXT. - The proper type associated with strlen() and sizeof() is size_t. Don't use "int" or "unsigned". The signed return value of Unix read() and write() has type "ssize_t". Cast that back to size_t after checking it for being an error return. - When using printf, don't use the C99 %-specifier for size_t; always cast size_t to unsigned long and print with %lu. - Assume that time_t may be 64 bits wide, even on 32-bit platforms. If you need to print one literally, use %lld and cast to long long. - Don't assume that all pointers are the same size, or that pointers are the same size as either int or long. - In the mainline AG code avoid using anything that might be locale-dependent, as the user interface might have set some crazy locale. - Don't blindly slice filename strings using path separator characters. Use appropriate functions instead. And avoid slicing filename strings unless necessary. - Always pull the name component out of a pathname before looking for any filename suffix. Otherwise you lose on names like "foo.d/bar". Robustness concerns: - If you mean to fall through the bottom of a switch case (one that has code) put /* FALLTHROUGH */ there. - If you have virtual functions in a class, declare the destructor virtual too. - If you have functions in a class that are virtual because they're declared that way by a base (ancestor) class, declare them explicitly virtual yourself too. - Don't define virtual functions inline, unless there's no other practical place to put the definition. - Use parentheses when mixing && and ||, or &, |, and ^, or in other cases where operator precedence is easily confused. - If you need an assignment inside a conditional, wrap the assignment in parentheses and an explicit comparison. (Not just extra parentheses.) But don't do this unless there's a reason for it. - If using qsort() from <stdlib.h>, be sure your compare function only returns 0 for identical objects. If the objects aren't identical, always pick *something* to distinguish by, so the sort is deterministic. Idioms: - YES: if (!strcmp(a, b)) NO: if (strcmp(a, b) == 0) - YES: if (strcmp(a, b) != 0) NO: if (strcmp(a, b))