I'm using this statement now to switch between small and slightly more extensive error messages in my C code:
#ifdef COMPACTC
error_code ((uint16_t) init_cascade, 5);
#else
error_message (__func__, "cascades malloc failed");
#endif
(it's part of an embedded C code library, so I often don't have the memory available to store the error message strings).
In the first case (COMPACTC defined) I output only a function address and and error number. In the second case I output the full function name and a human-readable error message.
Since I'm copying this snippet all over my code now, I hope I can replace it with a single macro, which I can use like this:
error (init_cascade, "cascades malloc failed", 5)
and provides the correct C code depending on COMPACTC being defined or not.
Maybe it's even possible to have the current function (or some unique identifier) automatically derived from the current location, though I think the preprocessor doesn't know which function's scope it's currently in.
Another improvement would be if a unique error code (5 in this case, which is based on the return value) could be automatically generated from the error message (like a hash value or something).
Then the macro call could be as simple as this:
error ("cascades malloc failed")
Of course, when using hashes, I would need some sort of reference (file/comment) to its original message.
Context: error messages on AVR 8-bits MCU
About the context of this question: This code is written for the ATmega168 (having only 2k of RAM), and AFAIK there's no good/recent emulator available for Linux. So I'm trying to find a good way to produce error messages/codes without the strings eating all of my memory.
Alternative: C function?
A completely different, probably more flexible solution would be to define a C function error (function, message, code)
and move the #if/#else/#endif
construction to its body.
I'm not sure though whether a string literal is compiled in by gcc if it is referred to in a function call but never used inside the function body.
Edit: I just tested this idea: using a string literal in a call but not in the body still has it added to the executable by gcc, so this "alternative" doesn't seem to work.
This should actually be fairly easy:
#ifdef COMPACTC
# define COMBINED_ERROR(function, message, size) error_code((uint16_t)function, size)
#else
# define COMBINED_ERROR(function, message, size) error_message (__func__, message)
#endif
and now you can write:
COMBINED_ERROR(init_cascade, "cascades malloc failed", 5);