[8769] | 1 | This document describes guidelines for code which is to be |
---|
| 2 | incorporated into the Athena source tree. Here are the areas covered: |
---|
| 3 | |
---|
[9541] | 4 | Conventions for C code |
---|
| 5 | Conventions for shell scripts |
---|
[9298] | 6 | Software engineering practices |
---|
[9301] | 7 | Symbol namespaces |
---|
[8769] | 8 | Portability considerations for code we maintain |
---|
| 9 | Portability considerations for code we release |
---|
| 10 | Portability considerations for code we get from third parties |
---|
| 11 | |
---|
[9541] | 12 | Conventions for C code |
---|
| 13 | ---------------------- |
---|
[9298] | 14 | |
---|
| 15 | If you are working on an existing module which does not follow these |
---|
| 16 | conventions, be consistent with the existent source code rather than |
---|
| 17 | these conventions. |
---|
| 18 | |
---|
| 19 | You should follow the section on "Writing C" in the Gnu coding |
---|
| 20 | standards (available in emacs info under "standards"), with the |
---|
| 21 | following changes: |
---|
| 22 | |
---|
| 23 | * When making a function call, do not put a space before the |
---|
| 24 | open parenthesis. Do put spaces before the open parenthesis |
---|
| 25 | after "while", "if", or "for", though. |
---|
| 26 | |
---|
| 27 | * When defining a function, do not drop to the next line for |
---|
| 28 | the name of the function; put the function name on the same |
---|
| 29 | line as the return type. |
---|
| 30 | |
---|
| 31 | * Don't insert formfeed characters into source files to divide |
---|
| 32 | programs into pages. |
---|
| 33 | |
---|
| 34 | * Ignore the sections on "Portability between System Types" |
---|
| 35 | and "Portability between CPUs"; see the sections on |
---|
| 36 | portability in this file instead. Also ignore the section |
---|
| 37 | on "Internationalization." |
---|
| 38 | |
---|
| 39 | * In the section "Calling System Functions," ignore everything |
---|
| 40 | about string functions. These days you can assume that |
---|
| 41 | using "#include <string.h>", strchr(), and strrchr() will |
---|
| 42 | work on just about all platforms. |
---|
| 43 | |
---|
| 44 | You can use "M-x set-c-style" "GNU" in emacs to have emacs take care |
---|
| 45 | of the gnu-style indentation for you. Remember to drop to the next |
---|
| 46 | line before each open brace. |
---|
| 47 | |
---|
| 48 | When writing return statements, do not put parentheses around the |
---|
| 49 | return value; just write "return foo;". This convention is not |
---|
| 50 | specified in the Gnu coding standards, but is consistent with the |
---|
| 51 | examples in the standards. |
---|
| 52 | |
---|
| 53 | Each C source file should begin with an MIT copyright statement, a |
---|
| 54 | comment describing what the file does, and a line: |
---|
| 55 | |
---|
[9541] | 56 | static char rcsid[] = "$Id$"; |
---|
[9298] | 57 | |
---|
| 58 | Each C header file should begin with: |
---|
| 59 | |
---|
[9541] | 60 | /* $Id$ */ |
---|
[9298] | 61 | |
---|
| 62 | followed by an MIT copyright statement and a comment describing what |
---|
[9541] | 63 | the file does. MIT copyright statements may be omitted for source |
---|
| 64 | code which is not distributed outside of MIT. |
---|
[9298] | 65 | |
---|
| 66 | The preferred convention for comments is |
---|
| 67 | |
---|
| 68 | /* comment text */ |
---|
| 69 | |
---|
| 70 | for one line comments, and |
---|
| 71 | |
---|
| 72 | /* comment text line 1 |
---|
| 73 | * comment text line 2 |
---|
| 74 | */ |
---|
| 75 | |
---|
| 76 | for multi-line comments. As recommended in the Gnu coding standards, |
---|
| 77 | your comments should normally be complete, capitalized sentences |
---|
| 78 | ending with a period. |
---|
| 79 | |
---|
[9340] | 80 | Write prototypes for all of your functions. Include argument names in |
---|
| 81 | your prototypes, to help the reader understand what they mean. |
---|
| 82 | |
---|
[9541] | 83 | Conventions for shell scripts |
---|
| 84 | ----------------------------- |
---|
| 85 | |
---|
| 86 | Use /bin/sh to write shell scripts, not csh. |
---|
| 87 | |
---|
| 88 | Begin each shell script with: |
---|
| 89 | |
---|
| 90 | #!/bin/sh |
---|
| 91 | # $Id$ |
---|
| 92 | |
---|
| 93 | followed by an MIT copyright if the shell script will be distributed |
---|
| 94 | outside of MIT. |
---|
| 95 | |
---|
| 96 | Use tabs for indentation. Avoid putting the then or else clauses of |
---|
| 97 | an if statement on the same line. Avoid creating lines longer than 79 |
---|
| 98 | characters. Write case statements according to the format: |
---|
| 99 | |
---|
| 100 | case expression in |
---|
| 101 | pattern) |
---|
| 102 | statements |
---|
| 103 | ;; |
---|
| 104 | esac |
---|
| 105 | |
---|
| 106 | Environment variable names should be in all capitals; shell variable |
---|
| 107 | names should be in all lowercase. Avoid writing ${varname} for |
---|
| 108 | variable expansion except when necessary; just write $varname. In |
---|
| 109 | most cases, if you intend to expand a variable as a single word, you |
---|
| 110 | should write "$varname" with double quotes. |
---|
| 111 | |
---|
[9298] | 112 | Software engineering practices |
---|
| 113 | ------------------------------ |
---|
| 114 | |
---|
| 115 | The following software engineering practices are strongly encouraged: |
---|
| 116 | |
---|
| 117 | * Restricting the operations which can access a given type of |
---|
[9572] | 118 | data object, and grouping them together. |
---|
[9298] | 119 | |
---|
| 120 | * Documenting data invariants (i.e. conditions on the |
---|
| 121 | representations of data objects which are assumed to always |
---|
| 122 | be true) and the meaning of data representations. |
---|
| 123 | |
---|
| 124 | * Documenting non-obvious requirements and effects of |
---|
| 125 | procedures. |
---|
| 126 | |
---|
| 127 | * Use of prototypes for all functions. |
---|
| 128 | |
---|
| 129 | * Automated testing of both program components ("unit |
---|
| 130 | testing") and whole programs ("integration testing"). |
---|
| 131 | |
---|
| 132 | The following software engineering practices are discouraged: |
---|
| 133 | |
---|
| 134 | * Use of global variables. Remember that the complexity of |
---|
| 135 | any function's interface is increased by the global |
---|
| 136 | variables it uses, even if that doesn't show up in the |
---|
| 137 | function prototype. Global variables are marginally |
---|
| 138 | acceptable to represent configuration parameters determined |
---|
| 139 | by command-line arguments or a configuration file, but even |
---|
| 140 | then it is preferrable to find an alternative. |
---|
| 141 | |
---|
| 142 | * Use of global process state. You should avoid using |
---|
| 143 | alarm(), and you should avoid using getuid() or getenv() |
---|
| 144 | inside libraries or other "deep" interfaces. Code that uses |
---|
| 145 | global process state tends to interact poorly with other |
---|
| 146 | code in large programs. |
---|
| 147 | |
---|
[9301] | 148 | Symbol namespaces |
---|
| 149 | ----------------- |
---|
| 150 | |
---|
| 151 | If you are writing a library, you should pick a prefix for your |
---|
| 152 | library. You should ensure that all symbols which interact with the |
---|
| 153 | application's namespace (both at link time and on inclusion of the |
---|
| 154 | header file) begin with your prefix (or the all-caps form of your |
---|
| 155 | prefix, in the case of preprocessor symbols and enumeration constants) |
---|
| 156 | followed by an underscore. Symbols which are not intended for use by |
---|
| 157 | the application should begin with your preefix followed by two |
---|
| 158 | underscores. |
---|
| 159 | |
---|
| 160 | For instance, if your prefix is "hes", then functions exported to the |
---|
| 161 | user should begin with "hes_" (e.g. "hes_resolve"). Functions used |
---|
| 162 | internally by the library should begin with "hes__" |
---|
| 163 | (e.g. "hes__resolve" for the internal resolver function). |
---|
| 164 | Preprocessor symbols intended for use by the application should begin |
---|
| 165 | with "HES_" (e.g. "HES_ER_OK"); preprocessor symbols not intended for |
---|
| 166 | use by the application should begin with "HES__" (e.g. |
---|
| 167 | "HES__HESIOD_H", used to protect hesiod.h from multiple |
---|
| 168 | inclusion). |
---|
| 169 | |
---|
| 170 | Names of structures should begin with your prefix, but structure |
---|
| 171 | fields don't need to. Strictly speaking, structure fields interact |
---|
| 172 | with the user's namespace because the user might have "#define"'d them |
---|
| 173 | to something before including your header file, but applications |
---|
| 174 | generally shouldn't be "#define"ing lots of lowercase symbols, so this |
---|
| 175 | is not a real worry. |
---|
| 176 | |
---|
[8769] | 177 | Portability considerations for code we maintain |
---|
| 178 | ----------------------------------------------- |
---|
| 179 | |
---|
[9040] | 180 | In general, your code should assume a POSIX-compliant and ANSI |
---|
[9572] | 181 | C-compliant development environment, except to work around specific |
---|
| 182 | bugs in platforms we care about. |
---|
[8769] | 183 | |
---|
[9572] | 184 | You should use Autoconf to handle portability concerns; see the file |
---|
| 185 | "build-system" in this directory for how a package in the athena |
---|
| 186 | hierarchy should use autoconf. If you must perform an operating |
---|
| 187 | system test (because you are using a plain Makefile, typically for |
---|
| 188 | something in the packs hierarchy), do it in two steps; for instance: |
---|
[8769] | 189 | |
---|
| 190 | #define HAVE_STRERROR |
---|
[9460] | 191 | #if defined(sun) && !defined(SOLARIS) |
---|
[8769] | 192 | /* SunOS 4.1.3_U1 doesn't have strerror(). Use sys_errlist |
---|
| 193 | * instead. */ |
---|
| 194 | #undef HAVE_STRERROR |
---|
| 195 | #endif |
---|
| 196 | |
---|
| 197 | #ifndef HAVE_STRERROR |
---|
| 198 | extern const char *const sys_errlist[]; |
---|
| 199 | #define strerror(x) (sys_errlist[x]) |
---|
| 200 | #endif |
---|
| 201 | |
---|
| 202 | This way, if the source tree is ever converted to use feature tests, |
---|
| 203 | the person porting the code will know exactly what needs to be tested |
---|
| 204 | for. If you can anticipate the preprocessor symbol which would be |
---|
| 205 | used with Autoconf (as in this example), that's even better. Note |
---|
| 206 | particularly the comment instead the operating system test; it should |
---|
[9298] | 207 | specify: |
---|
[8769] | 208 | |
---|
| 209 | * What special consideration is needed for that operating |
---|
| 210 | system. |
---|
| 211 | |
---|
| 212 | * The version number of the operating system for which this |
---|
[9298] | 213 | approach was determined to be necessary. |
---|
[8769] | 214 | |
---|
| 215 | This will help future maintainers determine if one can eliminate the |
---|
| 216 | special consideration altogether when an OS upgrade has happened. |
---|
| 217 | |
---|
| 218 | Following is a list of appropriate preprocessor symbols to use to |
---|
[9460] | 219 | detect platforms we care about, when using plain Makefiles: |
---|
[8769] | 220 | |
---|
[9460] | 221 | SunOS: #if defined(sun) && !defined(SOLARIS) |
---|
[8769] | 222 | Solaris: #ifdef SOLARIS |
---|
| 223 | IRIX #ifdef sgi |
---|
| 224 | Linux: #ifdef linux |
---|
| 225 | NetBSD: #ifdef __NetBSD__ |
---|
| 226 | or #include <sys/param.h> and #ifdef BSD4_4 |
---|
| 227 | if applicable to all BSD 4.4 systems. |
---|
| 228 | |
---|
| 229 | SOLARIS is not automatically defined by the compiler on Solaris |
---|
[9460] | 230 | systems; we make sure it's defined when we build code not using |
---|
| 231 | autoconf. There are no reliable automatically defined constants for |
---|
| 232 | Solaris systems. |
---|
[8769] | 233 | |
---|
[9460] | 234 | For some highly nonportable operations you may need to do a platform |
---|
| 235 | test even when using Autoconf. In that case, use AC_CANONICAL_HOST |
---|
| 236 | rather than the above ifdefs. |
---|
| 237 | |
---|
[8769] | 238 | Portability considerations for code we release |
---|
| 239 | ---------------------------------------------- |
---|
| 240 | |
---|
[9298] | 241 | All of the standards in the previous section apply; however, we |
---|
| 242 | generally care about more platforms for code we release to the outside |
---|
| 243 | works. It is discouraged, but acceptable, to care about platforms |
---|
| 244 | which are not POSIX-compliant. Code that cares about such platforms |
---|
| 245 | should determine whether the platform supports POSIX interfaces by |
---|
| 246 | using AC_CHECK_HEADERS(unistd.h) to determine whether it can #include |
---|
[9460] | 247 | <unistd.h>, and then checking whether _POSIX_VERSION is defined. Such |
---|
| 248 | code should always use POSIX interfaces rather than less portable |
---|
| 249 | interfaces when they are available. |
---|
[8769] | 250 | |
---|
| 251 | Portability considerations for code we get from third parties |
---|
| 252 | ------------------------------------------------------------- |
---|
| 253 | |
---|
[9298] | 254 | The overriding principle for code obtained from third parties is to |
---|
| 255 | make as few changes as possible. A lot of third-party code has a very |
---|
| 256 | bad approach to portability, or cares about a lot of platforms we |
---|
| 257 | don't care about. You should attempt to follow the portability |
---|
| 258 | approach used by the rest of the program, such as it may be. Ideally, |
---|
| 259 | any changes you make should be made in such a manner that they can be |
---|
[8769] | 260 | incorporated into the source tree maintained by the third party. |
---|