Rules for straight ANSI C:
Assumptions
Object oriented programming classes are not supported.
A program
A program's executable code is made up of
- global variables, knowable to all code.
- several modules of routines and corresponding private global variables,
some of the routines and/or variables may be exported to other modules.
- a main routine, which starts the program and normally exports nothing.
Source code files
For maintenance, the source code is written as:
- one or more ".d" files containing definitions (no variables nor routines!)
A ".d" file never generates code. The set of ".d" files implements
a hierarchical tree of dependencies between the definitions.
- one or more modules, each consisting of a ".h" file and a ".c" file.
A ".c" file always generates code. A ".h" file defines only what the
module exports to others, and never generates any code. Its definitions
may however depend on ".d" files.
- one main routine file, which is ".c" and possibly has no ".h" file
(it normally exports nothing).
Simulating Modules with include files
We try to simulate modules with include files. As stated above, the
source of a module consists of:
- a ".h" file with the exported constants, variables and routine headers,
- a ".c" file with the private constants and variables and the code
of all routines.
The ".h" file is included by other modules, which must see the variable
as extern during their compilation. The exporting module also needs
the declarations, but without the "extern" keyword. Therefore either
the declarations occur again inside the module's ".c" file or we find
a mechanism of re-using the ".h" file. Writing the declarations twice
means a maintenance problem when changes happen.
The following mechanism is proposed for including ".h" files:
- a declaration of an exported variable is preceded by the word "PROVIDE".
- every ".h" file uses
#include
in order to define "PROVIDE" to be either null or "extern" depending
on whether the word "IMPORT" is defined.
- If a variable is initialised,
then its initial value is given as
INITIALLY(initial value);
(no equal sign!). Example for initialising exported integer i to 5:
PROVIDE int i INITIALLY(5);
The file Importation.d contains:
#undef PROVIDE
#ifdef IMPORT
#define PROVIDE extern
#define INITIALLY(s)
#else
#define PROVIDE
#define INITIALLY(s) = s
#endif
Thus, in a module A which imports from a module B, the ".c" file starts
with: #define IMPORT
#include "B.h"
...
#undef IMPORT
But module B's ".c" file has the line
#include "B.h"
outside of "#define IMPORT" / "#undef IMPORT" brackets.
The ".h" file of a module never imports from other modules (but it
can of course use #include for definitions).
Global variables
Because they are instantiated as code, they are written as a module.
Because there are only variables, the ".h" file contains all the declarations
and the ".c" file is empty apart from an include for generation of
the code. The ".c" file is simply:
#include "Globals.h"
The Main routine
The main routine's ".c" file looks like:
#include <... .h>
#include <... .h>
#define IMPORT
#include "Definitions.d"
#include "Globals.h"
#include "A.h"
#include "B.h"
#include "... ".h""
#undef IMPORT
void main() {
...
...
}
RC