1

I have a macro with varargs that auto injects some arguments, like the first below injecting the argument "__FNAME__":

#ifdef VERBOSE
#define logdbg(format, ...) debugff(__FNAME__, format, ##__VA_ARGS__)
#elif defined(NORMAL)
#define logdbg(format, ...) debugf(format, ##__VA_ARGS__)
#else
#define logdbg(format, ...) /* debud off */
#endif

But I need to keep this macro working with compilers without MACRO VARIADIC support (in SCO Unix and AIX 4.3 Copmiler v3).

In these environments I have now:

#ifdef VERBOSE
#define logdbg debugff(__FNAME__, format, ##__VA_ARGS__)
#elif defined(NORMAL)
#define logdbg debugf
#else
#define logdbg if(1);else debugf
#endif

These compilers didn't accepted the comment in the last macro definition, and I get the if(1);else blablabla that works fine from https://stackoverflow.com/a/687412/926064

But I need yet a solution to the first case, where an argument is "injected" by macro.

Some workaround to do that ?

EDIT:

As it isn't a software with multithread support, I'm thinking to change the debug 'framework' to inject the arguments using side functions to set values in 'context' variables (global, static, etc):

#define logdbg pass_args(__FNAME__); debugf

More possibles workarounds ?

Community
  • 1
  • 1
Luciano
  • 2,695
  • 6
  • 38
  • 53
  • Side Note: `logdbg if(1);else debugf` looks like nothing good (you may wrap it into a `do { ... } while(0)` –  Jun 11 '15 at 19:41
  • Install a decent compiler on those platforms -- GCC for example. It'll probably be quicker. Note that the `##__VA_ARGS__` notation is already GCC-specific; it won't work with any other compiler. Actually, come to that, `__FNAME__` is not standard C either. – Jonathan Leffler Jun 11 '15 at 20:04
  • @JonathanLeffler: Installing others compilers isn't an option. – Luciano Jun 11 '15 at 20:08
  • 1
    What about installing just a modern CPP (C preprocessor) and using that before compiling the code? You're on a very sticky wicket. The code is using a feature for which there is no counterpart in the oldest version of the standard, C89/C90. It was a valuable addition in C99 because it allowed you to do things that could not be done before. – Jonathan Leffler Jun 11 '15 at 20:12
  • 1
    @DieterLücking "looks like nothing good"... Indeed. I think you may be slightly understating that. Just a bit... – twalberg Jun 11 '15 at 20:18
  • @DieterLücking: (just re-posting the deleted comment): Cannot. There aren't Variadic support in macro. – Luciano Jun 11 '15 at 20:22
  • That ellipses in my comment 'you may wrap it into a do { ... } while(0)' is something (nothing variadic) –  Jun 11 '15 at 20:25
  • @DieterLücking: Sorry, I didn't understand what you suggested. Wrapping isn't possible. The preprocessor cannot handle multiple arguments in macro, so I can only replace the name of the function preserving the args like in "#define log logfunc". So the real code "log(a1, a2, a3)", becomes "logfunc(a1, a2, a3)" – Luciano Jun 11 '15 at 20:33
  • Is `__FNAME__` something you invented or is it part of your C preprocessor environment? I consulted the GCC preprocessor [documentation](https://gcc.gnu.org/onlinedocs/gcc-5.1.0/cpp/) and can't find a reference to `__FNAME__` -- and there's explicit mention that `, ##__VA_ARGS__` is a GNU extension. Since names beginning with double-underscore are reserved for the implementation, you should not be using that name if you're defining it. – Jonathan Leffler Jun 11 '15 at 20:44
  • @jxh: But if(0) can generate problems in code like if(cond) logdbg() else xxx(). Preprocessed as: if(cond) if(0) logdbg() else xxx(), the else will be wrongly associated – Luciano Jun 11 '15 at 20:59
  • @jonat: It's just a adopted snippet of code, and FNAME has another real name correctly prefixed. – Luciano Jun 11 '15 at 23:07

1 Answers1

1

Assuming it is impossible to use a different compiler (which seems a dubious requirement, but let's put that aside), for certain, you will need a different function for logdbg to expand into. Probably, that function would take the __FNAME__ argument from another source, like a global variable.

#define logdbg ((logdbg_fname__ = __FNAME__), debugff_broken)

void debugff_broken(const char *fmt, ...) {
    extern const char *logdbg_fname__;
    va_list ap;
    va_start(ap, fmt);
    vdebugff(logdbg_fname__, fmt, ap);
    va_end(ap);
}

Where vdebugff is like debugff except it takes a va_list.

If thread safety is required, use thread specific storage instead of a common global.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • You cannot change easily some policies and governance of some legacy environments to install or change everything in the system, as u do on your laptop. All you have is an old fashion vi and a 'resident' as-is C compiler and nothing more. Your approach is one I was working, but I need to ensure there is only one thread. – Luciano Jun 11 '15 at 23:01
  • You can use thread specific storage from Solaris thread APIs or POSIX APIs. For compiler, you can compile the compiler as part of the build process, and not install it on the system. – jxh Jun 11 '15 at 23:03
  • Believe, we have a lot of restrictions including storage space in the work fs, since it's a production environment. – Luciano Jun 11 '15 at 23:09
  • I am not sure I have seen a company unwilling to buy another disk for the build server before. – jxh Jun 11 '15 at 23:10
  • A company that's still using AIX 4.3.x is seriously stingy. That's been obsolete (as in, completely out of support) for a decade or more (AIX 5.1 was out of support in 2006; IBM's web site no longer lists AIX 4.3 — I did find a reference to end of December 2003). I'm not sure about the SCO Unix; it isn't clearly enough identified, but it too is likely to be rather old — hence the C89 compilers. – Jonathan Leffler Jun 12 '15 at 03:32
  • @jon: That's why we're fighting to do some improvement in a big legacy system to support an upgrade and replace about 40 servers spread over country. The lucky of them is I'm an engineer from 80s. Seriously, handle code with 25 years is exciting, mainly when some is yours (like a son) – Luciano Jun 20 '15 at 02:35
  • It's an evil problem when code you wrote 25 years ago comes back to haunt you again. Are you sure you wouldn't do better taking the code off the old machines, modernizing and testing it on the new ones, and then dealing with the data. Leave the old and working code alone on the old and working (just) machines. Do the upgrade in a modern environment. All else apart, you'll be able to things a lot more quickly on the new machines. You'll probably have orders of magnitude more memory and disk, maybe SSD too, and the CPU might also be most of an order of magnitude faster too. – Jonathan Leffler Jun 20 '15 at 03:30