C++ Producer Guide

March 1998

next section previous section current document TenDRA home page document index


3.1.1 - C coding standard
3.1.2 - API usage and target dependencies
3.1.3 - Source code modules

3.1. Source code organisation

This section describes the basic organisation of the source code for the C++ producer. This includes the coding conventions applied, the application programming interface (API) observed and the division of the code into separate modules.


3.1.1. C coding standard

The C++ producer is written in a subset of C which is compatible with C++ (it compiles with most C compilers, but also bootstraps itself). It has been written to conform to the local (OSSG) C coding standard; most of the conformance checking being automated by use of a user-defined compilation profile, ossg_std.h. The standard macros described in the coding standard are defined in the standard header ossg.h. This is included from the header config.h which is included by all source files. The default definitions for these macros, set according to the value of __STDC__ and other compiler-defined macros, should be correct, but they can be overridden by defining the FS_* macros, described in the header, as command-line options.

The most important of these macros are those used to handle function prototypes, enabling both ISO and pre-ISO C compilers to be accommodated. Simple function definitions take the form:

	ret function
	    PROTO_N ( ( p1, p2, ...., pn ) )
	    PROTO_T ( par1 p1 X par2 p2 X .... X parn pn )
	{
	    ....
	}
with the PROTO_N macro being used to list the parameter names (note the double bracket) and the PROTO_T macro being used to list the parameter types using X (cartesian product) as a separator. The corresponding function declaration will have the form:
	ret function PROTO_S ( ( par1, par2, ...., parn ) ) ;
The case where there are no parameter types is defined using:
	ret function
	    PROTO_Z ()
	{
	    ....
	}
and declared as:
	ret function PROTO_S ( ( void ) ) ;
Functions with ellipses are defined using:
	#if FS_STDARG
	#include <stdarg.h>
	#else
	#include <varargs.h>
	#endif

	ret function
	    PROTO_V ( ( par1 p1, par2 p2, ...., parn pn, ... ) )
	{
	    va_list args ;
	    ....
	#if FS_STDARG
	    va_start ( args, pn ) ;
	#else
	    par1 p1 ;
	    par2 p2 ;
	    ....
	    parn pn ;
	    va_start ( args ) ;
	    p1 = va_arg ( args, par1 ) ;
	    p2 = va_arg ( args, par2 ) ;
	    ....
	    pn = va_arg ( args, parn ) ;
	#endif
	    ....
	    va_end ( args ) ;
	    ....
	}
and declared as:
	ret function PROTO_W ( ( par1, par2, ...., parn, ... ) ) ;
Note that <varargs.h> does not allow for parameters preceding the va_alist, so the fixed parameters need to be explicitly assigned from args.

The following TenDRA keywords are defined (with suitable default values for non-TenDRA compilers):

	#pragma TenDRA keyword SET for set
	#pragma TenDRA keyword UNUSED for discard variable
	#pragma TenDRA keyword IGNORE for discard value
	#pragma TenDRA keyword EXHAUSTIVE for exhaustive
	#pragma TenDRA keyword REACHED for set reachable
	#pragma TenDRA keyword UNREACHED for set unreachable
	#pragma TenDRA keyword FALL_THROUGH for fall into case

Various flags giving properties of the compiler being used are defined in ossg.h. Among the most useful are FS_STDARG, which is true if the compiler supports ellipsis functions (see above), and FS_STDC_HASH, which is true if the preprocessor supports the ISO stringising and concatenation operators. The macros CONST and VOLATILE, to be used in place of const and volatile, are also defined.

A policy of rigorous static program checking is enforced. The TenDRA C producer is applied with the user-defined compilation mode ossg_std.h and intermodule checks enabled. Checking is applied with both the C and #pragma token calculus output files. The C++ producer itself is applied with the same checks. gcc -Wall and various versions of lint are also periodically applied.


3.1.2. API usage and target dependencies

Most of the API features used in the C++ producer are to be found in the ISO C API, with just a couple of extensions from POSIX required. These POSIX features can be disabled with minimal loss of functionality by defining the macro FS_POSIX to be false.

The following features are used from the ISO <stdio.h> header:

	BUFSIZ		EOF		FILE		SEEK_SET
	fclose		fflush		fgetc		fgets
	fopen		fprintf		fputc		fputs
	fread		fseek		fwrite		rewind
	sprintf		stderr		stdin		stdout
	vfprintf
from the ISO <stdlib.h> header:
	EXIT_SUCCESS	EXIT_FAILURE	NULL		abort
	exit		free		malloc		realloc
	size_t
and from the ISO <string.h> header:
	memcmp		memcpy		strchr		strcmp
	strcpy		strlen		strncmp		strrchr
The three headers just mentioned are included in all source files via the ossg_api.h header file (included by config.h). The remaining headers are only included as and when they are needed. The following features are used from the ISO <ctype.h> header:
	isalpha		isprint
from the ISO <limits.h> header:
	UCHAR_MAX	UINT_MAX	ULONG_MAX
from the ISO <stdarg.h> header:
	va_arg		va_end		va_list		va_start
(note that if FS_STDARG is false the XPG3 <varargs.h> header is used instead); and from the ISO <time.h> header:
	localtime	time		time_t		struct tm
	tm::tm_hour	tm::tm_mday	tm::tm_min	tm::tm_mon
	tm::tm_sec	tm::tm_year
The following features are used from the POSIX <sys/stat.h> header:
	stat		struct stat	stat::st_dev	stat::st_ino
	stat::st_mtime
The <sys/types.h> header is also included to provide the necessary types for <sys/stat.h>.

There are a couple of target dependencies in the producer which can overridden using command-line options:

  1. It assumes that if a count of the number of characters read from an input file is maintained, then that count value can be used as an argument to fseek. This may not be true on machines where the end of line marker consists of both a newline and a carriage return. In this case the -m-f command-line option can be used to switch to a slower, but more portable, algorithm for setting file positions.

  2. It assumes that a file is uniquely determined by the st_dev and st_ino fields of its corresponding stat value. This is used when processing #include directives to prevent a file being read more than once if this is not necessary. This assumption may not be true on machines with a small ino_t type which have file systems mounted from machines with a larger ino_t type. In this case the -m-i command-line option can be used to disable this check.


3.1.3. Source code modules

For convenience, the source code is divided between a number of directories:

  1. The base directory contains only the module containing the main function, the basic type descriptions and the Makefile.
  2. The directories obj_c and obj_tok contain respectively the C and #pragma token headers generated from the type algebra by calculus . The directory obj_templ contains certain calculus template files.
  3. The directory utility contains routines for such utility operations as memory allocation and error reporting, including the error catalogue.
  4. The directory parse contains routines concerned with parsing and preprocessing the input, including the sid grammar.
  5. The directory construct contains routines for building up and analysing the internal representation of the parsed code.
  6. The directory output contains routines for outputting the internal representation in various formats including as a TDF capsule, a C++ spec file, or a symbol table dump file.

Each module consists of a C source file, file.c say, containing function definitions, and a corresponding header file file.h containing the declarations of these functions. The header is included within its corresponding source file to check these declarations; it is protected against multiple inclusions by a macro of the form FILE_INCLUDED. The header contains a brief comment describing the purpose of the module; each function in the source file contains a comment describing its purpose, its inputs and its output.

The following table lists all the source modules in the C++ producer with a brief description of the purpose of each:

Module Directory Purpose
access construct member access control
allocate construct new and delete expressions
assign construct assignment expressions
basetype construct basic type operations
buffer utility buffer reading and writing routines
c_class obj_c calculus support routines
capsule output top-level TDF encoding routines
cast construct cast expressions
catalog utility error catalogue definition
char parse character sets
check construct expression checking
chktype construct type checking
class construct class and enumeration definitions
compile output TDF tag definition encoding routines
constant parse integer constant evaluation
construct construct constructors and destructors
convert construct standard type conversions
copy construct expression copying
debug utility development aids
declare construct variable and function declarations
decode output bitstream reading routines
derive construct base class graphs; inherited members
destroy construct garbage collection routines
diag output TDF diagnostic output routines
dump output symbol table dump routines
encode output bitstream writing routines
error utility error output routines
exception construct exception handling
exp output TDF expression encoding routines
expression construct expression processing
file parse low-level I/O routines
function construct function definitions and calls
hash parse hash table and identifier name routines
identifier construct identifier expressions
init output TDF initialiser expression encoding routines
initialise construct variable initialisers
instance construct template instances and specialisations
inttype construct integer and floating point type routines
label construct labels and jumps
lex parse lexical analysis
literal parse integer and string literals
load output C++ spec reading routines
macro parse macro expansion
main - main routine; command-line arguments
mangle output identifier name mangling
member construct member selector expressions
merge construct intermodule merge routines
namespace construct namespaces; name look-up
operator construct overloaded operators
option utility compiler options
overload construct overload resolution
parse parse low-level parser routines
pragma parse #pragma directives
predict parse parser look-ahead routines
preproc parse preprocessing directives
print utility error argument printing routines
quality construct extra expression checks
redeclare construct variable and function redeclarations
rewrite construct inline member function definitions
save output C++ spec writing routines
shape output TDF shape encoding routines
statement construct statement processing
stmt output TDF statement encoding routines
struct output TDF structure encoding routines
syntax[0-9]* parse sid parser output
system utility system dependent routines
table parse portability table reading
template construct template declarations and checks
throw output TDF exception handling encoding routines
tok output TDF standard tokens encoding
tokdef construct token definitions
token construct token declarations and expansion
typeid construct run-time type information
unmangle output identifier name unmangling
variable construct variable analysis
virtual construct virtual functions
xalloc utility memory allocation routines


Part of the TenDRA Web.
Crown Copyright © 1998.