Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
# Goal
2
 
3
The goal of the namespace TODO item is to move all Rebirth symbols into one of two top level namespaces: `dcx` for common symbols and `dsx` for similar symbols.  Code is considered common if it is compiled to the same output independent of which game is built.  Code is considered similar if it is not common.
4
 
5
To be common, code must not:
6
 
7
* Contain `#ifdef DXX_BUILD_DESCENT_I` or `#ifdef DXX_BUILD_DESCENT_II` or equivalent preprocessor directives:
8
```c++
9
int f()
10
{
11
	// not common because the return statement varies by game
12
#if defined(DXX_BUILD_DESCENT_I)
13
	return 1;
14
#elif defined(DXX_BUILD_DESCENT_II)
15
	return 4;
16
#endif
17
}
18
```
19
* Use any macro which is defined inside a game-specific preprocessor directive:
20
```c++
21
#if defined(DXX_BUILD_DESCENT_I)
22
#define MY_MACRO	2
23
#elif defined(DXX_BUILD_DESCENT_II)
24
#define MY_MACRO	4
25
#endif
26
 
27
int f()
28
{
29
	return MY_MACRO;	// not common, because MY_MACRO varies by game
30
}
31
```
32
* Use any type which is not common:
33
```c++
34
struct A
35
{
36
	int a;
37
#if defined(DXX_BUILD_DESCENT_I)
38
	int b;
39
#endif
40
};
41
 
42
int f(A &a)
43
{
44
	return a.b;	// not common, because struct A is not common
45
}
46
```
47
* Call any function which is not common:
48
```c++
49
int f()
50
{
51
#if defined(DXX_BUILD_DESCENT_I)
52
	return 1;
53
#elif defined(DXX_BUILD_DESCENT_II)
54
	return 4;
55
#endif
56
}
57
 
58
int g()
59
{
60
	// not common because f() varies by game
61
	return f() + 1;
62
}
63
```
64
 
65
To be common, data variables must:
66
* Be an instance of a type which is common: a built-in type or a UDT which is common.
67
* Exist in both games.  If a data variable exists in one game and not in the other, then that variable is not common, even if it is a type which is common.  For example, afterburner charge is a built-in type (`int`), but is not common because it is not defined in Descent 1.
68
* Be the same type in both games.
69
 
70
To be common, user defined types must not:
71
* Contain `#ifdef DXX_BUILD_DESCENT_I` or `#ifdef DXX_BUILD_DESCENT_II` or equivalent preprocessor directives.
72
* Depend on any macro which is defined inside a game-specific preprocessor directive:
73
```c++
74
#if defined(DXX_BUILD_DESCENT_I)
75
#define MY_MACRO	2
76
#elif defined(DXX_BUILD_DESCENT_II)
77
#define MY_MACRO	4
78
#endif
79
struct A
80
{
81
	int a[MY_MACRO];	// not common because a[] depends on MY_MACRO
82
};
83
```
84
* Use non-common UDTs as members or base classes:
85
```c++
86
struct A
87
{
88
	int a;
89
#if defined(DXX_BUILD_DESCENT_I)
90
	int b;
91
#endif
92
};
93
 
94
struct B : public A	// not common because base class A is not common
95
{
96
	int c;
97
};
98
 
99
struct C // not common because member `a` is not common
100
{
101
	A a;
102
	int d;
103
};
104
```
105
 
106
# Implementation
107
Anyone may work on this TODO item.  Symbols in the global namespace should be moved to `namespace dcx` if the symbol is common and to `namespace dsx` if the symbol is not common.  Currently, `dxxsconf.h` defines `dsx` as a macro that expands to `d1x` or `d2x`, as appropriate.
108
 
109
A symbol declared in a namespace is distinct from a symbol of the same name in a different namespace.  `SConstruct` enables the compiler warning `-Wmissing-declarations`, so moving a function declaration into a namespace will provoke a warning that the definition is missing a declaration.  Moving only the definition into a namespace will also provoke the warning.  In both cases, this is a reminder from the compiler that both the declaration and the definition must be moved into the namespace.  Without this warning, the build would fail when the linker searches for the symbol in one namespace, but it is only present in the other namespace.
110
 
111
Moving a data variable declaration or definition into a namespace will **not** provoke a compiler warning.  However, it will still produce a linker error if the variable is declared `extern` in one namespace, but defined only in a different namespace.
112
 
113
As a transition measure, `dxxsconf.h` includes `using namespace dcx;` and, when `dsx` is enabled, `using namespace dsx;`.  These transition assistants may mask mistakes where a symbol is placed in the wrong namespace.  These assistants will be removed before this TODO item is considered complete.
114
 
115
As a developer aid, `dxxsconf.h` declares classes named `dcx` and `dsx` in various scopes chosen to conflict with erroneous namespace usage.  Namespaces `dcx` and `dsx` should only ever be declared at the top level.  Neither should ever appear inside an anonymous namespace, nor inside itself, nor inside the other.  The classes declared in `dxxsconf.h` will force an error in those cases.
116
 
117
Files should never be included while a namespace is open.  This is wrong:
118
```c++
119
namespace dcx {
120
int a;
121
#include "other.h"	// wrong, other.h not expecting to be inside a namespace
122
int b;
123
}
124
```
125
Namespaces can be closed and reopened.  There are two ways to rewrite the above to be correct.  First:
126
```c++
127
namespace dcx {
128
int a;
129
}
130
#include "other.h"
131
namespace dcx {
132
int b;
133
}
134
```
135
Second:
136
```c++
137
namespace dcx {
138
int a;
139
int b;
140
}
141
#include "other.h"
142
```
143
The second form will be used eventually, but the first is more convenient during the transition phase.