cfad47cfa3/doc/SRC_GUIDELINES

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
To keep the code as portable as possible, follow these rules.  All these
2
"don't"s may seem brain-damaged, but there's really no other way to keep
3
the code compileable on old and/or brain-damaged compilers.
4
5
These rules are not a panacea, mind you.  The intention is to make the
6
code as portable as *possible*, so that any compiler-incompatibilities
7
are easier to fix.  They don't give a "100% portability guarantee."
8
9
Furthermore, I'm no portability-wizard.  These rules are a combination
10
of my own and (most importantly) other people's experiences.  If you
11
have ideas regarding portability, please contact the maintainer.
12
13
If you spot any code that does not follow these rules, please report it
14
as a bug and/or send a patch.  An exception to this are the files in the
15
tads2/ and tads3/ directories; they are read-only.  Don't touch them.
16
Any changes made to them will be lost next time FrobTADS gets in sync
17
with the TADS base code.  Problems in any of these files should only be
18
reported, not fixed.
19
20
Sidenote: If you're looking for object oriented programming guidelines,
21
forget it.  FrobTADS is object based, not object oriented.  It uses C++
22
mostly as a "better C".  Classes and objects are only used to make
23
things simpler, not with OOP in mind.
24
25
OK, here goes:
26
27
28
The "common.h" header file
29
==========================
30
31
In new source files, always, Always, ALWAYS, #include "common.h" as the
32
first header.  Everywhere; both in C and C++ sources, in headers and
33
*.c/*.cc/*.cpp files.
34
35
36
'and', 'or' and 'not'
37
=====================
38
39
If you prefer these keywords over the usual '&&', '||' and '!' operators
40
(I do), just use them as if they were available everywhere.  You must
41
always #include "common.h" for this to work.  This only applies to C++
42
code of course.  Don't use these keywords in C (they *are* in the C++
43
standard, even if old compilers don't support them, but not in ANSI C).
44
45
46
C++ template library
47
====================
48
49
Don't use the C++ standard library.  That means no <iostream>, no
50
<vector>, no <algorithm>, no <string>, no fun.
51
52
53
#including standard C-headers in C++
54
====================================
55
56
Don't use new-style C++ includes to include C-library headers.  Do this:
57
58
	#include <string.h>
59
60
rather than this:
61
62
	#include <cstring>
63
64
65
Namespaces
66
==========
67
68
Don't use namespaces.
69
70
71
for-loops
72
=========
73
74
Don't rely on the modern semantics of for-loops.  Don't do this:
75
76
	for (int i = 0; i < frob; ++i) {
77
		// ...
78
	}
79
	// ...
80
	for (int i = 0; [...]
81
82
as it will only compile on modern compilers.  Do this instead:
83
84
	int i;
85
	for (i = 0; i < frob; ++i) [...]
86
	for (i = 0; [...]
87
88
This compiles on both modern and old compilers.  If you really need a
89
variable that expires after the loop, use this:
90
91
	{for (int i = 0; i < frob; ++i) {
92
		// ...
93
	}}
94
95
Attention!  If you have an old compiler, don't do this:
96
97
	for (int i = 0; [...]
98
	for (i = 0; [...]
99
100
as it will *only* work with *old* compilers.  Modern compilers can't
101
compile this code.
102
103
104
C++ casts
105
=========
106
107
Don't use static_cast<> and friends.  Do this instead:
108
109
	static_cast(foo)(bar)
110
	dynamic_cast(frob*)(baz)
111
	reinterpret_cast(const xyzzy*)(plugh)
112
113
This will work on every compiler (as long as you #include "common.h" in
114
your sources).  On modern compilers, this:
115
116
	static_cast(int)(bar)
117
118
will be macro-transformed into:
119
120
	static_cast<int>(bar)
121
122
while on old compilers, it will become:
123
124
	(int)(bar)
125
126
127
Exception handling
128
==================
129
130
Don't use exception handling.  There's a portable exception-framework in
131
the TADS 3 base code (transparently utilizing labels and gotos through
132
macros); you might want to use it if you really can't do without exception
133
handling.
134
135
136
Templates
137
=========
138
139
Don't use templates.  Don't try to work around this by emulating them
140
with macros; you'll just shoot yourself in the foot (and since this is
141
C++, this will blow away your whole leg).
142
143
144
Non-standard compiler features
145
==============================
146
147
Don't use compiler-specific non-ANSI features; not everyone has GCC
148
installed.  You should always compile with GCC's "-ansi -pedantic"
149
switches (both C and C++).  Note that "-ansi -pedantic" cannot check
150
your code for full ANSI correctness; they are only meant to catch
151
obvious blunders.
152
153
154
Non-ANSI/ISO functions
155
======================
156
157
If you feel like using a non-ANSI function (for example a BSD one), use
158
it, but provide a working ANSI-only fall-back, as is already done with
159
some functions in src/missing.[h/cc].  Also look at the implementation
160
of os_get_sys_clock_ms() in src/oscurses.cc on how to handle portability
161
issues.
162
163
Generally, if such a function has equivalent ones in other standards,
164
just check for them in "configure.ac" and structure your code to use the
165
information the configuration script detects.
166
167
168
Filenames
169
=========
170
Don't use filenames longer than 14 characters.  I'm not talking about
171
DOS (which has the 8+3 limit).  There are some Unices that have this
172
limitation.