Boost logo

Boost :

From: Suman Cherukuri (suman_at_[hidden])
Date: 2005-08-30 10:25:33


> a.c
> #include "err.h"
> static const int err_tag = err_tag_a_c;
> enum {err_bad_foobar=1, err_missing_baz, ... };
>
> and you use the errors as follows:
>
> long err = ERR(missing_baz);
How is it going to prevent duplication. Suppose, somewhere in a.c if I
write long err = ERR(missing_baz), what happens?

>
> with the macro ERR defined in err.h as:

> #define ERR(x) ((err_tag * 65536L) + err_##x)

-----Original Message-----
From: Martin Bonner [mailto:martin.bonner_at_[hidden]]
Sent: Tuesday, August 30, 2005 1:40 AM
To: 'Suman Cherukuri'
Subject: RE: [boost] Preprocessot question

----Original Message----
From: Suman Cherukuri [mailto:suman_at_[hidden]]
Sent: 29 August 2005 22:49
To: boost_at_[hidden]
Subject: [boost] Preprocessot question

> This probably doesn't belong to boost mailing list, but since boost
> has a lot of support in preprocessor, there may be someone who can
> answer my question.

You would have done better to ask this in comp.lang.c.moderated.

> I'm using general 'C' compiler in this project (hence I cannot use
> boost headers). I want to write a macro as follows;
>
> #define ERR(x, y) \
> { \
> # ifndef ERR##x \
> # define ERR##x \
> # else \
> # error ERR##x already defined\
> # endif
> y = x; \
> }
>
> When I compile, I get the error saying,
> error C2162: expected macro formal parameter
> on all the preprocessor lines inside the #define ERR(...) body.

Right. You can't write a preprocessor macro that creates preprocessor
directives. The #ifndef in your macro will never get parsed.

> The reason I want to do something like this is to have some unique
> numbers
> in the code (like locators. Don't want to use __FILE__ and __LINE__
> for security reasons) and want to capture duplicates at compiletime.
>
> For example if I say in the code, int err = 10000 in one file, I
> don't want any other engineer to use 10000 in the anywhere else in
> the code.
>
> So I started writing something like int err = ERR(10000) but got into
> several compiler problems as I mentioned above.

The problem I see with your solution (assuming it worked), is that if we
have two files a.c and b.c, then somebody could write:

a.c:
        ...
        int err = ERR(10000);
        ...

b.c:
        ...
        int err = ERR(10000);
        ...

... and the check would fail to detect that both files are using the same
value :-(

The simple solution is to have a err.h which defines a (long) enumeration,
and every time you need a new error value, you add to err.h. That is
simple, but of course it means you need to recompile everything every time
you add a value.

The slightly more complex version is that you have an err.h which has an
enumeration which is specific to each .c file. (That means you will have to
recompile every time you add an .c file, but that is probably bearable.) So
err.h might look like:

        enum { err_tag_a_c=1, err_tag_b_c, .... };

Then each .c file has at the start:

a.c
        #include "err.h"
        static const int err_tag = err_tag_a_c;
        enum {err_bad_foobar=1, err_missing_baz, ... };

and you use the errors as follows:

                long err = ERR(missing_baz);

with the macro ERR defined in err.h as:

#define ERR(x) ((err_tag * 65536L) + err_##x)

To add a new error code, you update the enumeration at the top of file, and
use it via the ERR macro. (Which only requires recompiling the file you
were changing anyway).

Note that I assumed you could use long for your error codes - if you are in
the embedded world, that might not be affordable. On the other hand, in the
embedded world you can probably live with only 255 different files, and 255
error codes per file.

-- 
Martin Bonner
Martin.Bonner_at_[hidden]
Pi Technology, Milton Hall, Ely Road, Milton, Cambridge, CB4 6WZ,
ENGLAND Tel: +44 (0)1223 441434

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk