1

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)?

pts
  • 80,836
  • 20
  • 110
  • 183
  • 1
    You just need to express it in a way that avoids the warning, say `_printmsgx((const char*)(int)msg)`. What actually happens is irrelevant since it's a dead code path. – Raymond Chen Jul 06 '20 at 18:29
  • @RaymondChen: it's a nice workaround. Is there a construct which works for any type, like C11 _ Generic? It would be awesome if I got errors or warnings if 0.0 or 0.0f was passed etc. – pts Jul 06 '20 at 18:58
  • 1
    Presumably those would be caught by the `_printmsgx_far` branch. – Raymond Chen Jul 06 '20 at 21:39

1 Answers1

0

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.

pts
  • 80,836
  • 20
  • 110
  • 183