source: trunk/doc/standards @ 8769

Revision 8769, 6.6 KB checked in by ghudson, 28 years ago (diff)
First cut at source tree documentation.
Line 
1This document describes guidelines for code which is to be
2incorporated into the Athena source tree.  Here are the areas covered:
3
4        Portability considerations for code we maintain
5        Portability considerations for code we release
6        Portability considerations for code we get from third parties
7        Software engineering practices
8        Indentation and naming
9
10Portability considerations for code we maintain
11-----------------------------------------------
12
13Your code should assume a POSIX-compliant and ANSI C-compliant
14development environment unless given evience to the contrary.  Do not,
15for instance, put sigaction() calls inside "#ifdef SOLARIS" or "#ifdef
16POSIX" and have the code compile with signal() calls by default; have
17your code use sigaction() on all platforms.  If for some reason the
18code needs to compile on a platform which does not have sigaction(),
19you can #ifdef for that platform or use a feature test (see below).
20Under no circumstances should code use non-POSIX interfaces by
21default.
22
23Some of our platforms have bugs in POSIX interfaces but not in BSD
24interfaces (e.g. under Ultrix 4.2, setpgid() works but setsid() does
25not).  See the file "lossage" in this directory for descriptions of
26particular bugs and incompatibilities and how to handle them.
27
28Some important operations (especially in code in the Athena
29environment) are not covered by the ANSI C or POSIX specifications.
30See the file "nonstd" in this directory for descriptions of how to
31handle some of them.
32
33When you are dealing with operations not covered by the ANSI C or
34POSIX specification or with operating system bugs, there are two ways
35to provide portability:
36
37        1. Perform an operating system test by #ifdef'ing some symbols
38           defined by the preprocessor on the operating systems which
39           need special consideration.
40
41        2. Perform a "feature test" at build time to determine how to
42           perform the operation in question.
43
44The second method is always preferrable when possible.  Currently, the
45only good way to perform feature tests is to use Autoconf.  See the
46section on build procedure requirements for how to set up Autoconf in
47a source tree.
48
49If you must perform an operating system test (because the source tree
50you're working on doesn't use Autoconf and you don't have the time to
51make it do so), do it in two steps; for instance:
52
53        #define HAVE_STRERROR
54        #if defined(sun) && !defined(__svr4__)
55        /* SunOS 4.1.3_U1 doesn't have strerror().  Use sys_errlist
56         * instead. */
57        #undef HAVE_STRERROR
58        #endif
59
60        #ifndef HAVE_STRERROR
61        extern const char *const sys_errlist[];
62        #define strerror(x) (sys_errlist[x])
63        #endif
64
65This way, if the source tree is ever converted to use feature tests,
66the person porting the code will know exactly what needs to be tested
67for.  If you can anticipate the preprocessor symbol which would be
68used with Autoconf (as in this example), that's even better.  Note
69particularly the comment instead the operating system test; it should
70note:
71
72        * What special consideration is needed for that operating
73          system.
74
75        * The version number of the operating system for which this
76          approach was determined to be necessary and valid.
77
78This will help future maintainers determine if one can eliminate the
79special consideration altogether when an OS upgrade has happened.
80
81Following is a list of appropriate preprocessor symbols to use to
82detect platforms we care about:
83
84        Solaris:        #ifdef SOLARIS
85        IRIX            #ifdef sgi
86        Linux:          #ifdef linux
87        NetBSD:         #ifdef __NetBSD__
88                        or #include <sys/param.h> and #ifdef BSD4_4
89                        if applicable to all BSD 4.4 systems.
90
91SOLARIS is not automatically defined by the compiler on Solaris
92systems; we make sure it's defined when we set the compiler on Solaris
93systems.  There are no reliable automatically defined constants for
94Solaris systems.
95
96Portability considerations for code we release
97----------------------------------------------
98
99Code we release to the outside world should definitely use Autoconf
100and feature tests rather than imake and operating system tests.  All
101of the standards in the previous section apply; however, we generally
102care about more platforms for code we release to the outside works.
103It is discouraged, but acceptable, to care about platforms which are
104not POSIX-compliant.  Code that cares about such platforms should
105determine whether the platform supports POSIX interfaces by using
106AC_CHECK_HEADERS(unistd.h) to determine whether it can #include
107<unistd.h>, and then checking whether _POSIX_VERSION is defined.
108
109Portability considerations for code we get from third parties
110-------------------------------------------------------------
111
112The overriding concern for code obtained from third parties is: make
113as few changes as possible.  A lot of third-party code has a very bad
114approach to portability, or cares about a lot of platforms we don't
115care about.  You should attempt to follow the portability approach
116used by the rest of the program, such as it may be.  Ideally, any
117changes you make should be made in such a manner that they can be
118incorporated into the source tree maintained by the third party.
119
120Software engineering practices
121------------------------------
122
123The following software engineering practices are strongly encouraged:
124
125        * Restricting the operations which can access a given type of
126          data object, and grouping them together.
127
128        * Documenting data invariants and the meaning of data values.
129
130        * Documenting non-obvious requirements and effects of
131          procedures.
132
133        * Use of prototypes for all functions.
134
135        * Automated testing of both program components and whole
136          programs.
137
138The following software engineering practices are discouraged:
139
140        * Use of global variables.  Remember that the complexity of
141          any function's interface is increased by the global
142          variables it uses.  Global variables are marginally
143          acceptable to represent configuration parameters determined
144          by command-line arguments or a configuration file, but even
145          then it is preferrable to find an alternative.
146
147        * Use of global kernel process state.  You should avoid using
148          alarm(), and you should avoid using getuid() inside
149          libraries or other "deep" interfaces.  Code that uses global
150          kernel process state tends to interact poorly with other
151          code in large programs.
152
153Indentation and naming
154----------------------
155
156Don't be sloppy.  Don't use inconsistent indentation, don't rely on a
157nonstandard tab width, don't leave whitespace at the end of lines,
158don't use studlycaps identifiers in a program that uses undescores or
159vice versa, etc..
160
161Identation and naming schemes should be consistent across a package;
162do not start using a new indentation or naming scheme because you're
163writing a new module.  However, there is no standard indentation or
164naming scheme for the entire Athena source tree.
Note: See TracBrowser for help on using the repository browser.