C++ and Portability

  1. 1. Common porting problems
  2. 2. Porting libio

First published .

Revision History

kate

Moved out the DRA producers as a standalone tool.

kate

Split off from tcpplus.

DERA

tcpplus 1.8.2; TenDRA 4.1.2 release.

1. Common porting problems

Experience in porting pre-ISO C++ programs has shown that the following new ISO C++ features tend to cause the most problems:

Note that many of these features have controlling #pragma directives, so that it is possible to switch to using the pre-ISO features.

2. Porting libio

Perhaps the library component which is most likely to be required is <iostream>. A readily available freeware implementation of a pre-ISO (i.e. non-template) <iostream> package is given by the libio component of libg++. This section describes some of the problems encountered in porting this package (version 2.7.1).

The tcc compiler flags used in porting libio were:

tcc -Yposix -Yc++ -sC:cc

indicating that the POSIX API is to be used and that the .cc suffix is used to identify C++ source files.

In iostream.h, cin, cout, cerr and clog should be declared with C linkage, otherwise the C++ producer includes the type in the mangled name and the fake iostream hacks in stdstream.cc don't work. The definition of EOF in this header can cause problems if both iostream.h and stdio.h are included. In this case stdio.h should be included first.

In stdstream.cc, the correct definitions for the fake iostream structures are as follows:

struct _fake_istream::myfields {
    _ios_fields *vb ;		// pointer to virtual base class ios
    _IO_ssize_t _gcount ;	// istream fields
    void *vptr ;		// pointer to virtual function table
} ;

struct _fake_ostream::myfields {
    _ios_fields *vb ;		// pointer to virtual base class ios
    void *vptr ;		// pointer to virtual function table
} ;

The fake definition macros are then defined as follows:

#define OSTREAM_DEF( NAME, SBUF, TIE, EXTRA_FLAGS )\
    extern "C" _fake_ostream NAME = { { &NAME.base, 0 }, .... } ;

#define ISTREAM_DEF( NAME, SBUF, TIE, EXTRA_FLAGS )\
    extern "C" _fake_istream NAME = { { &NAME.base, 0, 0 }, .... } ;

Note that these are declared with C linkage as above.

In stdstrbufs.cc, the correct definitions for the virtual function table names are as follows:

#define filebuf_vtable		__vt__7filebuf
#define stdiobuf_vtable		__vt__8stdiobuf

Note that the _G_VTABLE_LABEL_PREFIX macro is incorrectly defined by the configuration process (it should be __vt__), but the ## directives in which it is used don't work on an ISO compliant preprocessor anyway (token concatenation takes place after replacement of macro parameters, but before further macro expansion). The dummy virtual function tables should also be declared with C linkage to suppress name mangling.

In addition, the initialisation of the standard streams relies on the file pointers stdout etc. being constant expressions, which in general they are not. The directive:

#pragma TenDRA++ rvalue token as const allow

will cause the C++ producer to assume that all tokenised rvalue expressions are constant.

In streambuf.cc, if errno is to be explicitly declared it should have C linkage or be declared in the std namespace.

In iomanip.cc, the explicit template instantiations should be prefixed by template. The corresponding template declarations in iomanip.h should be declared using export (note that the __GNUG__ version uses extern, which may yet win out over export).