cdosmultiple-dispatchwatcom

Detect which function to call based on argument type in OpenWatcom C language


I have 2 implementations of the same function based on the pointer size in the argument:

/* Writes a $-delimited string to stdout. */   
static inline void _printmsgx(const char *msg);
#pragma aux _printmsgx = "mov ah, 9" "int 0x21" parm [ dx ] modify [ ah ];

/* Writes a $-delimited string (with far pointer) to stdout. */
static inline void _printmsgx_far(const char far *msg);
#pragma aux _printmsgx_far = "mov ah, 9" "push ds" "push es" "pop ds" "int 0x21" "pop ds" \
    parm [ es dx ] modify [ ah ];

I'd like to select automatically which one to call, so I've written a macro:

#define _printmsgx_best(msg) ((sizeof((msg)+0) == sizeof(const char*)) ? \
    _printmsgx(msg) : _printmsgx_far(msg))

However, if this is called with a far pointer, wcc gives a warning for the branch not called:

foo.c(17): Warning! W112: Parameter 1: Pointer truncated
foo.c(17): Note! N2003: source conversion type is 'char __far const *'
foo.c(17): Note! N2004: target conversion type is 'char const *'

I also tried C11 _Generic, but it doesn't seem top be supported by wcc:

#define _printmsgx_best(msg) _Generic((msg), \
    const char far*: _printmsgx_far(msg), const char*: _printmsgx(msg))

I get this warning and then errors:

foo.c(17): Warning! W131: No prototype found for function '_Generic'

How do I make it work without warnings, in C (not C++), with wcc in Open Watcom V2, in the small memory model (-ms)?


Solution

  • Inspired by the comment by @Raymond Chen:

    #define _printmsgx_best(msg) ((sizeof((msg)+0) == sizeof(const char*)) ? \
        _printmsgx((const char*)(size_t)msg) : _printmsgx_far(msg))
    

    This does enough type checking, because if msg has some incompatible type, it will be reported for _printmsgx_far(msg), even if that branch is not taken.