Modules -- /Project | cern archive | HTTP only
home archive home about

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