-
Notifications
You must be signed in to change notification settings - Fork 2
/
HACKING
343 lines (272 loc) · 11.7 KB
/
HACKING
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
The Hacker's Guide to Rt^3
==========================
Source code lives in the following directories:
platform independent libraries
------------------------------
src/libNumeric - math library
src/libUtility - basic utility library
src/libNetwork - networking library
raytrace libraries
------------------
src/libGeometry - geometry library
src/libRaytrace - raytrace library
applications
------------
src/Raytrace^3 - application GUI interface to raytrace system
src/rt^3 - the rt^3 application shell
src/rt^3d - the rt^3 peer-compute daemon
src/rt^3dbd - the rt^3 geometry server
src/scratch - application pasteboard
testing
-------
tests - automation tests
Coding Standards
================
For anyone who plans on contributing code, the following conventions
should be followed. Contributions that do not conform will be
ridiculed and rejected until they do.
Code Organization
-----------------
Code that is potentially useful to another application, or that may be
abstracted in such a way that it is useful to other applications,
should be put in a library and not in application directories.
Header files that are private to a library go into that library's
directory.
Header files that are public go in the include/ directory in the top
level.
Header files that are public should not include any headers that are
private.
C files use the .c extension. C++ files use the .cxx extension.
Header files for both C and C++ use the .h extension.
GNU Build System
----------------
The GNU build system (autoconf, automake, and libtool) is the primary
build infrastructure. Autoconf defines should be used extensively to
test for availability of system services such as header files and data
types. No assumptions should be made regarding the availability of
any particular header, function, datatype, or other resource. After
running the configure script, there will be an autogenerated
include/config.h header file that contains many preprocessor
directives and type declarations that may be used as needed.
Generic checks for a particular system are highly discouraged. For
example, instead of checking for if __APPLE__, linux, or __WIN32 is
defined when attempting to use some platform specific header or
function, instead check for the header or feature in the configure.ac
and use the provided HAVE_* define.
C++ features
------------
For the most part, features of C++ that conform to the ISO/IEC 14882
C++ standard are permitted and encouraged. That said, certain
features of the standard are discouraged for all but the most extreme
cases.
Encouraged:
bool - use a boolean for truth values
const - it the data is constant, mark it as such
internal declarations - define local variables near their first use
exceptions - use only in application code, not libraries
inline - use sparingly if the routine is short and
does not have static data
pure interfaces - define interfaces where appropriate for
classes of objects
single inheritance - abstractions are good, as are templates and
interfaces
standard C++ library - use where appropriate, including the STL
templates - use sparingly where the abstraction benefit
is evident
Discouraged:
casts - run-time typing is discouraged, especially
for classes unless the conversion is to
void* and back to the exact same class.
digraphs - use the C90 equivalent
exceptions - do not use in libraries, okay in app code
friends - minimize usage of friends outside of libs
multiple inheritance - single inheritance is preferred, multiple
inheritance of pure interfaces is okay
operator overloading - okay for math objects/libraries and the
[] bracket operators for container classes
but otherwise discouraged
public data members - there should be no public data in a class
except where profiled performance shows
justification
All code for a particular library should be in a namespace using the
name of the library.
C features
----------
Features of C that conform to the ISO/IEC 9899-1999 C standard (C99)
are permitted within reason where they do not conflict with the C++
standard. The applications, however, are object systems and are
object-driven, not data-driven. The following rules all have
exceptions, but effort should be made to follow the guidelines where
possible.
Encouraged:
inline - when profiling indicates an improvement and
when the function does not contain static
data and is relatively short
Discouraged:
arrays - acceptable for many cases but should not be
used for containers with dynamically
changing contents, C++ STL containers are
preferred
globals - these are strictly prohibited outside of
libraries and in public interfaces
macro constants - prefer static const data, using the
preprocessor to define min, max, default
values/bounds, etc.
macro functions - certain performance and build wrapping may
be necessary, but alternatives are preferred
where the code is not time-critical
Source coding standards
-----------------------
The code should strive to achieve conformance with the GNU coding
standard with a few exceptions, omissions, and reminders listed below.
The following should be more strictly adhered to, if only for the sake
of being consistent:
Indents are 2 characters, tabs are 8 characters. There should be a
emacs/vi local variables comment block at the end of each file to
adopt, enforce, encourage, and remind this convention. The following
lines should be in all source files and headers at the end of the
file:
// Local Variables:
// mode: C++
// tab-width: 2
// c-basic-offset: 2
// indent-tabs-mode: t
// End:
// ex: shiftwidth=2 tabstop=8
Braces for classes and functions go on the next line. Braces for
everything else go on the same line. Else clauses go on the same line
as the if close brace. Function return types may go on the same line
as the function name or on a separate line.
namespace foo {
/** blah is an example
*/
void blah()
{
for (;;) {
if (a == b) {
} else {
}
}
}
}
Documentation should appear in the headers. Classes should be
documented on their purpose, as should all public member functions and
public data. Comments are desired for all functions and classes
regardless of their scope. Javadoc-style comments for Doxygen++ are
required for every public class, function, template, and interface.
At a minimum, a simple doxygen comment may be made by starting a
comment block with a double asterisk (as is shown above in the
preceding example).
Classes may not have public data members. Public data violates the
encapsulation of a class and makes clients of the class directly tied
to the implementation. This does not mean that there should be
"getters and setters" class functions. Instead, pass around objects,
create and use object managers, and re-think the logic away from a
data-driven methodology to an object-driven methodology.
Class names, variables, and functions should be mixed upper- and
lower-case. Underscores should not be used. Word boundaries should
use upper-case letters. It is preferred that symbols are spelled out
instead of using abbreviations or acronyms. Readability and
meaningfulness is preferred over brevity and typing ease. The first
letter of classes and static constant member data must be capitalized.
The first letter of other variables, data members, and functions must
be lower-case except for static constructor functions.
class ExampleClass; // ok
int someVariable; // ok
int foo(int bar); // ok
void Test::doRun(); // ok
class another_class; // bad
char MyVar; // bad
int GetString(); // bad
void Test::do_run(); // bad
Declare local variables near their usage.
Private and protected data members should be preceded with an
underscore.
int _someMember; // ok
int anotherMember; // bad
Local variables should be named so that they are not easily confused
to be class names or private member data.
double localVariable; // ok
double LocalVariable; // bad (looks like class or constructor)
double _localVar; // bad (looks like private member variable)
Variables are not to be "decorated" to show their type (i.e. do not
use Hungarian notation or variations thereof). The name should use a
concise, meaningful name that is not cryptic.
char *name; // ok
Image *image; // ok
Image *pImage; // bad
char *fooPtr; // bad
char *lpszFoo; // bad
Static member data and constants should be all upper-case with word
boundaries separated by underscores.
double Numeric::PI_OVER_TWO; // ok
static const int MAX_READ = 2; // ok
static const int arraySize = 8; // bad
There should be only one class per header and source file pair. The
file name should be the name of the class.
Compilation preprocessor defines should never change the size of
structures or classes.
class Foo
{
private:
#ifdef DEBUG_CODE // bad
int _magic;
#endif
}
Global variables and data should not be used except for constant data
values. A singleton pattern may be used instead where necessary,
placing singletons into an application object and accessing as needed.
Every class should define a stream insertion method that dumps it's
state.
std::ostream& operator <<(std::ostream& os, const SomeClass& c)
Every class that defines a constructor should also define a destructor
and a copy constructor. Classes with virtual functions should define
a virtual destructor.
Use new and delete, not malloc and free. Use C++ stream I/O instead
of C standard I/O routines.
std::cout << "Hello World" << std::endl; // ok
printf("Hello World\n"); // bad
Declare non-mutating non-static member functions as const.
Violations of these rules in the existing code are not excuses to
follow suit. If code is seen that doesn't conform, it may and should
be fixed.
Generic Code
------------
Implementation-specific code that is used with the goal of utilizing a
platform to the fullest extent possible is a fundamental need for this
project. For sections in the code where usage of specific platform
features are desired, the code should be placed into an asm/ directory
and include the functionality desired.
Any platform-specific code should always include a generic default
implementation that is mostly cross-platform. The generic
implementation should strive to be POSIX compliant if possible. For
example, if there is a matrix multiply routine that could be
implemented using some snazzy assembler call, there must also be a
generic version that does the multiply without relying on assembler.
If there is a question as to what might comprise a generic version,
and it is something not covered by POSIX, facilities provided by
either BSD or GNU are acceptable alternatives. If there is not an
alternative facility, figure out another way.
Version Numbers
===============
The application versions are in the format: Major.Minor.Patch
The Major number is only updated when a release is made that is
significantly not backwards compatible. A Minor number designates
whether a release is a development or production release. Development
versions use odd numbers, production versions use even numbers. Bug
fix releases are optionally denoted with the Patch number.
Examples:
0.3.42 is a development version, the 42nd to be marked significant.
4.2.0 is a production version that is mostly compatible with two
previous versions.
3.0.0 is a production version that is not considered compatible with
any previous version.
3.12.5 is a production version with 5 released patches
References
==========
Some of the following were used in deriving some of the guidelines
herein:
Coding standards, C++ FAQ Lite
http://burks.brighton.ac.uk/burks/language/cpp/cppfaq/coding-standards.html
CDF Coding Guidelines
http://cdfsga.fnal.gov/computing/coding_guidelines/CodingGuidelines.html