#How to generate custom files while compiling ?

21 messages · Page 1 of 1 (latest)

small nebula
#

Hello,

I'm looking for a way to generate an error code - message table based on strings in my code.

For example

void* poBlock = malloc(bytes);
if (poBlock == nullptr)
{
    CRASH("Memory allocation failed");
}

Let's say I have two builds, a debug and a release.
If I use the debug build, I want to keep that string as is in the code, and display it when this error happens.
If I use the release build, I want to transform that string into a unique error code instead, and display it when this error happens.
CRASH is a macro and I can do that easily with a hash function.

However, what I don't know how to do is to generate list mapping the error code to the original string.
I would like to generate a custom file containing this information during the compilation of that build, but I'm not sure how to do so.

Could you direct me towards resources or show me how to achieve this ?

I'm using Visual Studio 2022 (17.13.2, v143) and C17

Thank you

(Please mention me)

barren pollenBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

spice pasture
#

Have you considered using macros?

boreal nymph
#

I don't know your context, but my immediate first thought is that you might be able to instead call exit(WAGI_ERR_MEMORY_ALLOCATION_FAILED);, where the caller is responsible for mapping the error code to a string, maybe by calling a C function from that same C program.

Though normally I always call exit(EXIT_FAILURE);, since the calling script ostensibly only wants to assert that the program did not fail.

In my own projects I also still prefer to always print the error message, no matter whether it's a debug or release build, since error code paths that are not taken usually don't have any perceptible overhead anyways. Premature optimization and such.

small nebula
small nebula
boreal nymph
small nebula
# boreal nymph Basically, we just want to make sure this isn't an xy problem: https://xyproblem...

Right, well, I don't want to display the error message to the end user, I want them to see simple error code, which I can use to find back the error in question on my side. So a user sees a code, I see messages, I need the map to know which code corresponds to which message.
I need to produce something external to the program which isn't shared with users, nor is in the source. The user doesn't need the messages, they only need the codes. Generating the codes isn't the problem, generating the map code-message as an external resources alongside the build is.

untold torrent
#

why don't you just use something along these lines?

enum err_codes {
  ERR_FOO,
  ERR_BAR,
  ...
};

static char const err_msg_table[] = {[ERR_FOO] = "FOO", [ERR_BAR] = "BAR", ... };

static void err(enum err_codes err_code) {
  #ifdef DEBUG
    // print the msg at err_msg_table[err_code]
  #else
    // print err_code itself or return it to your user
  #endif
  exit(err_code)
}

...

  if (poBlock == nullptr){
      err(ERR_FOO);
  }```
which is, i believe what HolyBlackCat had in mind
#

then you either build with -DDEBUG or not

small nebula
untold torrent
#

But I quickly realised that it was a nightmare to maintain in large projects
how come? you only have 2 things to be concerned about. your enum and the table. thats it

small nebula
# untold torrent > But I quickly realised that it was a nightmare to maintain in large projects h...

Let's say you add a function which contains three distinct calls to err(from your example). You have to write your function, write your error message, write a code name (in the enum).
The function is in one file, the enum and message in another but in different places in the file, so you have 3 places in your code to update/change.
While you are still figuring out how to best code that function, you might write it once, twice or three times with debugging and testing in between. Each time you change, you might review those three errors, maybe the new version of your function could use another or a better error message and code name, so to change it you have to go to another file, and so on.

Now, if the message is directly in the function, you only have that one place to focus on and the rest is done automatically.
I don't know if what I want is possible, hence my question here. Even if it's just a small improvement in my workflow, I'd gladly take it.

untold torrent
# small nebula Let's say you add a function which contains three distinct calls to `err`(from y...

no. thats not how one should do things. libraries exists for that exact reason.
consider:

//err.h
#pragma once

enum err_codes {
  ERR_FOO,
  ERR_BAR,
  ...
};

void err(enum err_codes err_code);```

```c
//err.c
#include "err.h"

static char const err_msg_table[] = {[ERR_FOO] = "FOO", [ERR_BAR] = "BAR", ... };

static void err(enum err_codes err_code) {
  #ifdef DEBUG
    // print the msg at err_msg_table[err_code]
  #else
    // print err_code itself or return it to your user
  #endif
  exit(err_code)
}```
compile as a library and done. if you want to add an error you merely add one to the enum at `err.h` and the corresponding msg to `err.c` thats all there is to it.

you _can_ write a script to generate the table in a different file to then include it in `err.c` but thats very much redundant. you'd still need to write the err code & message somewhere for the script to generate those
small nebula
# untold torrent no. thats not how one should do things. libraries exists for that exact reason. ...

no. thats not how one should do things.
I don't think this falls into the "should" or "shouldn't" type. It's simply a different way to do things.

if you want to add an error you merely add one to the enum at err.h and the corresponding msg to err.c thats all there is to it.
This is precisely what I don't want to do. Why do that if I can have the same result (display an error code to the user) in a way I find better for myself ?
This is what I used to do, and changed to what I do now.

you can write a script to generate the table in a different file to then include it in err.c but thats very much redundant. you'd still need to write the err code & message somewhere for the script to generate those
My idea is at compile time to find and get all string passed in CRASH(from my example), generate the code, and write it to a file, something like this: 453,Memory allocation failed

untold torrent
#

well gl i guess

spice pasture
#

Okay, how about this? You do ReportError<"some message">(). You can hash those strings at compile-time

#

But also you can make it so that every such function call is registered at program startup, even before it's actually called

#

You could construct your lookup table this way, again without codegen