source: trunk/doc/standards @ 9572

Revision 9572, 9.7 KB checked in by ghudson, 27 years ago (diff)
Remove the references to lossage and nonstd, which don't seem like such a great idea in retrospect.
Line 
1This document describes guidelines for code which is to be
2incorporated into the Athena source tree.  Here are the areas covered:
3
4        Conventions for C code
5        Conventions for shell scripts
6        Software engineering practices
7        Symbol namespaces
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
12Conventions for C code
13----------------------
14
15If you are working on an existing module which does not follow these
16conventions, be consistent with the existent source code rather than
17these conventions.
18
19You should follow the section on "Writing C" in the Gnu coding
20standards (available in emacs info under "standards"), with the
21following 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
44You can use "M-x set-c-style" "GNU" in emacs to have emacs take care
45of the gnu-style indentation for you.  Remember to drop to the next
46line before each open brace.
47
48When writing return statements, do not put parentheses around the
49return value; just write "return foo;".  This convention is not
50specified in the Gnu coding standards, but is consistent with the
51examples in the standards.
52
53Each C source file should begin with an MIT copyright statement, a
54comment describing what the file does, and a line:
55
56        static char rcsid[] = "$Id$";
57
58Each C header file should begin with:
59
60        /* $Id$ */
61
62followed by an MIT copyright statement and a comment describing what
63the file does.  MIT copyright statements may be omitted for source
64code which is not distributed outside of MIT.
65
66The preferred convention for comments is
67
68        /* comment text */
69
70for one line comments, and
71
72        /* comment text line 1
73         * comment text line 2
74         */
75
76for multi-line comments.  As recommended in the Gnu coding standards,
77your comments should normally be complete, capitalized sentences
78ending with a period.
79
80Write prototypes for all of your functions.  Include argument names in
81your prototypes, to help the reader understand what they mean.
82
83Conventions for shell scripts
84-----------------------------
85
86Use /bin/sh to write shell scripts, not csh.
87
88Begin each shell script with:
89
90        #!/bin/sh
91        # $Id$
92
93followed by an MIT copyright if the shell script will be distributed
94outside of MIT.
95
96Use tabs for indentation.  Avoid putting the then or else clauses of
97an if statement on the same line.  Avoid creating lines longer than 79
98characters.  Write case statements according to the format:
99
100        case expression in
101        pattern)
102                statements
103                ;;
104        esac
105
106Environment variable names should be in all capitals; shell variable
107names should be in all lowercase.  Avoid writing ${varname} for
108variable expansion except when necessary; just write $varname.  In
109most cases, if you intend to expand a variable as a single word, you
110should write "$varname" with double quotes.
111
112Software engineering practices
113------------------------------
114
115The following software engineering practices are strongly encouraged:
116
117        * Restricting the operations which can access a given type of
118          data object, and grouping them together.
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
132The 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
148Symbol namespaces
149-----------------
150
151If you are writing a library, you should pick a prefix for your
152library.  You should ensure that all symbols which interact with the
153application's namespace (both at link time and on inclusion of the
154header file) begin with your prefix (or the all-caps form of your
155prefix, in the case of preprocessor symbols and enumeration constants)
156followed by an underscore.  Symbols which are not intended for use by
157the application should begin with your preefix followed by two
158underscores.
159
160For instance, if your prefix is "hes", then functions exported to the
161user should begin with "hes_" (e.g. "hes_resolve").  Functions used
162internally by the library should begin with "hes__"
163(e.g. "hes__resolve" for the internal resolver function).
164Preprocessor symbols intended for use by the application should begin
165with "HES_" (e.g. "HES_ER_OK"); preprocessor symbols not intended for
166use by the application should begin with "HES__" (e.g.
167"HES__HESIOD_H", used to protect hesiod.h from multiple
168inclusion).
169
170Names of structures should begin with your prefix, but structure
171fields don't need to.  Strictly speaking, structure fields interact
172with the user's namespace because the user might have "#define"'d them
173to something before including your header file, but applications
174generally shouldn't be "#define"ing lots of lowercase symbols, so this
175is not a real worry.
176
177Portability considerations for code we maintain
178-----------------------------------------------
179
180In general, your code should assume a POSIX-compliant and ANSI
181C-compliant development environment, except to work around specific
182bugs in platforms we care about.
183
184You should use Autoconf to handle portability concerns; see the file
185"build-system" in this directory for how a package in the athena
186hierarchy should use autoconf.  If you must perform an operating
187system test (because you are using a plain Makefile, typically for
188something in the packs hierarchy), do it in two steps; for instance:
189
190        #define HAVE_STRERROR
191        #if defined(sun) && !defined(SOLARIS)
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
202This way, if the source tree is ever converted to use feature tests,
203the person porting the code will know exactly what needs to be tested
204for.  If you can anticipate the preprocessor symbol which would be
205used with Autoconf (as in this example), that's even better.  Note
206particularly the comment instead the operating system test; it should
207specify:
208
209        * What special consideration is needed for that operating
210          system.
211
212        * The version number of the operating system for which this
213          approach was determined to be necessary.
214
215This will help future maintainers determine if one can eliminate the
216special consideration altogether when an OS upgrade has happened.
217
218Following is a list of appropriate preprocessor symbols to use to
219detect platforms we care about, when using plain Makefiles:
220
221        SunOS:          #if defined(sun) && !defined(SOLARIS)
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
229SOLARIS is not automatically defined by the compiler on Solaris
230systems; we make sure it's defined when we build code not using
231autoconf.  There are no reliable automatically defined constants for
232Solaris systems.
233
234For some highly nonportable operations you may need to do a platform
235test even when using Autoconf.  In that case, use AC_CANONICAL_HOST
236rather than the above ifdefs.
237
238Portability considerations for code we release
239----------------------------------------------
240
241All of the standards in the previous section apply; however, we
242generally care about more platforms for code we release to the outside
243works.  It is discouraged, but acceptable, to care about platforms
244which are not POSIX-compliant.  Code that cares about such platforms
245should determine whether the platform supports POSIX interfaces by
246using AC_CHECK_HEADERS(unistd.h) to determine whether it can #include
247<unistd.h>, and then checking whether _POSIX_VERSION is defined.  Such
248code should always use POSIX interfaces rather than less portable
249interfaces when they are available.
250
251Portability considerations for code we get from third parties
252-------------------------------------------------------------
253
254The overriding principle for code obtained from third parties is to
255make as few changes as possible.  A lot of third-party code has a very
256bad approach to portability, or cares about a lot of platforms we
257don't care about.  You should attempt to follow the portability
258approach used by the rest of the program, such as it may be.  Ideally,
259any changes you make should be made in such a manner that they can be
260incorporated into the source tree maintained by the third party.
Note: See TracBrowser for help on using the repository browser.