
Miscellaneous Watcom Compiler Issues
-------------------------------------------------------

Combining C++ with C
============================
If somebody writes and compiles some routines using C++,
is there a way to call these routines from a C program?
Are there any problems likely to be encounterred?

The main problem is that C++ routine names are "mangled" when put
into the object files. That is, the typing information for the
function prototype is encoded in a text string and added to the
function name in the object file. This is so you have type safe
linkage, and to allow function overloading. You can turn off
mangling by defining/declaring the function as 'extern "C"'. E.g.

   extern "C" int foo(int a, int b )
   {
        return a + b;
   }

is a C++ function that is callable from C.

The second problem is making sure that the initializers have been
called for all of the C++ static objects.
The compiler makes sure of this for you.
The function gets called along with all the other library initializations
(C++ objects have a lower priority than the library functions so they don't
get run until after the library is all done).
Similarly for static destructors.

Important member functions which should be accessible from
C should have wrappers.  Each of these is a static member function with C
linkage which takes a pointer to the class and calls the member function
on behalf of the C function calling it.  Because name mangling is no
longer happening, the names should be chosen carefully.

e.g.
    class BigInt {
    public:
        operator + (const BigInt &);
        operator - (const BigInt &);
        operator * (const BigInt &);
        operator / (const BigInt &);
        ...

        extern "C" {
           static bigint_add(BigInt *, const BigInt *);
           static bigint_subtract(BigInt *, const BigInt *);
           static bigint_mul(BigInt *, const BigInt *);
           static bigint_div(BigInt *, const BigInt *);
           ...
        };
    }


tfork and _beginthread() issues
================================

* Using atexit()

With fork() & tfork() & beginthread() only one process may call exit(); the
rest must use _exit() which bypasses, amongst others, the atexit
processing.
The atexit processing 'pops' the handlers off a stack.

#include <process.h>

exitfunc()
{
	char buf[80];
	write(1, buf, sprintf(buf, "bye(%u)\n", getpid()));
}

tf()
{
	char buf[80];
	write(1, buf, sprintf(buf, "thread(%u)\n", getpid()));
	exit(0);
}
int s[1000];
main()
{
	atexit(exitfunc);

	printf("main(%u)\n", getpid());
	if (tfork(s, sizeof s, tf, 0, 0) == -1) {
		perror("tfork");
		exit(1);
	}
	sleep(5);
	exit(1);
}

Determining your privity level
====================================
How can a program determine if it is compiled at privity 1?

Look at the bottom 2 bits of your cs for the privity level.

e.g.
#include <sys/inline.h>
...
#define mypriv()  (_cs()&3)


Forcing shared memory references to be common between processes
================================================================
This is useful if you store and modify strings or other objects in shared
memory and you want to use common library routines to modify them.

Rather than needing to calculate and use offsets, the following technique
will let you map a shared memory region at the same address for multiple
processes.

You can make it so the shared memory is at the same address in both
processes by leaving space for it at compile time. To do this use
the 'undocumented' -@ option on cc, the value passed after the @ gives
the offset of the code segment.
Please note that it is recommended to use offsets from shared memory
whenever possible in order. Offsets produce more portable code.

i.e     cc -@ value  prog.c

value = 8K + (Shared memory size) + (Shared libs) + (Stack Size)

The 8K is the 0 page and Stack Guard
Shared memory size is your space, remember 4K pages
Shared Libs, in most cases this is 0.
Stack Size, check the default.

Then you can mmap() at address 4096, right after the 0 page

