1

I am working on a heavily resource-constrained embedded platform. I want a macro that will capture function call errors and log them to a fixed-size buffer.

My wish is to be able to do something like

returnType retval;
CAPTURE_ERRORS(retval, function_name, argument1, moreArgsMaybe);
if (retval) { other_error_handling(); }

Where

#define N 12
#define CAPTURE_ERRORS(retval, func, ...) \
    do { retval = func(__VA_ARGS__); \
        if (retval!=0) write_log_entry(#func[0:N],(int)retval); \
    } while (0)

Obviously, the Python slice syntax won't work. Is there any way to get the first N characters of a stringized macro argument?

(I don't want to do the truncation inside write_log_entry, because then the whole long function name will be stored in the executable image, only to be thrown away later.)

AShelly
  • 34,686
  • 15
  • 91
  • 152
  • 2
    You could log just the address of the function and then have a tool use your map file to look it up. Depending on alignment and how big your code is, you might even be able to get away with only the parts of the address of the function that actually change. – Michael Dorgan Oct 28 '16 at 19:35
  • I have implemented exactly that. I was wondering if there was a way to go directly to the strings, to avoid the need to keep track of the old map files for every shipped version. – AShelly Oct 28 '16 at 20:02
  • Are you really so hard up on disk space that a few extra characters of the function name in the executable image will be a problem? – Barmar Oct 28 '16 at 20:05
  • The thing is, you can't go directly to the strings because you don't have space. You could store your function names compressed and decompress the ones needed at will, Then, you are deciding what is stored in the image and how much "loss" of data is acceptable. Strings really tend to compress well, especially if allowed to be lossy. – Michael Dorgan Oct 28 '16 at 20:09
  • @Barmar, it's an embedded system. No disk, just flash memory. I probably can spare the characters, but I think not having to is an interesting optimization question. – AShelly Oct 28 '16 at 20:10

1 Answers1

1

I am not aware of any way as a string. (Somebody who is aware, please enlighten me!)

Edit The easiest way I know is to make all your function names no more than N characters long! Think of all that Fortran code with N=6. :)

The second easiest way I know is to pass an additional parameter to CAPTURE_ERRORS:

#define N 12
                                  /* vvvv */
#define CAPTURE_ERRORS(retval, func, tag, ...) \
    do { retval = func(__VA_ARGS__); \
        if (!retval) write_log_entry(#tag,(int)retval); \
    } while (0)                   /* ^^^^ */

and

CAPTURE_ERRORS(retval, function_name, function_nam, argument1, moreArgsMaybe);
                                      ^^^^^^^^^^^^

This is a sufficiently restricted form that you could automatically stuff tag in your existing CAPTURE_ERRORS call with a Python (or even sed!) script that you run before compiling.

Edit

  • A discussion thread coming to the same conclusion — use an external tool.
  • In C++, you could likely do this at compile time with a template. :) Not unlike this question, but stopping at length N.
Community
  • 1
  • 1
cxw
  • 16,685
  • 2
  • 45
  • 81