[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Name conflict

John Small

6/3/2011 11:03:00 AM

I have been trying to resurrect some old code. Since the last time the
code compiled correctly one the 3rd party header files has changed in
a way that prevents the old code from compiling.

The changed 3rd party header file now uses a typedef to define an
enumeration type. And two of the names used for the enumeration
constants that typedef now match names used in #defines's in the old
code. But the values of the names in the enueration type do not match
the values set be the #define's in the old code.

Unfortunately the conflict occurs with identifiers that are used in
many places in 50+ source files. So I am hoping that I don't have to
change the identifiers in the old code's defines and all the
references to these identifiers.

Changing the 3rd party header is not an option. And using the new
values for the names is not an option either because the old code used
its #define's to name specific numbers.

Is there a way to tell the compiler to use my #define of XYZ over the
enumeration constant XYZ?

Is there some other solution to this problem?

Thanks for any help you can provide!


--

John Small

4 Answers

James Kuyper

6/3/2011 11:20:00 AM

0

On 06/03/2011 07:02 AM, John Small wrote:
> I have been trying to resurrect some old code. Since the last time the
> code compiled correctly one the 3rd party header files has changed in
> a way that prevents the old code from compiling.
>
> The changed 3rd party header file now uses a typedef to define an
> enumeration type. And two of the names used for the enumeration
> constants that typedef now match names used in #defines's in the old
> code. But the values of the names in the enueration type do not match
> the values set be the #define's in the old code.
>
> Unfortunately the conflict occurs with identifiers that are used in
> many places in 50+ source files. So I am hoping that I don't have to
> change the identifiers in the old code's defines and all the
> references to these identifiers.
>
> Changing the 3rd party header is not an option. And using the new
> values for the names is not an option either because the old code used
> its #define's to name specific numbers.
>
> Is there a way to tell the compiler to use my #define of XYZ over the
> enumeration constant XYZ?

Expansion of macros occurs before interpretation of enumeration
constants, so that part is trivial. It already works, you don't need to
tell the compiler anything. However, you must make sure that the #define
occurs AFTER the #include of the third party header; otherwise, the
#define will screw up the definition of the enumerated type. The lines:

#define XYZ 3
typedef enum { ABC, XYZ } third_party_enum;

would be converted into

typedef enum { ABC, 3 } third_party_enum;

which would be a syntax error.
I think the best way to approach this would be to create
third_wrapper.h, which looks something like the following:

#ifndef H_THIRD_WRAPPER
#define H_THIRD_WRAPPER
#include "third_party.h"
#define XYZ 3
#endif

And then replace every occurrence in your source code of the line

#include "third_party.h"

with

#include "third_wrapper.h"
--
James Kuyper

China Blue Veins

6/3/2011 11:21:00 AM

0

In article <4rkzjBzzMnpe-pn2-88sBkK471Nw7@x.y.z>,
"John Small" <zjsmallz@os2world.net> wrote:

> Is there a way to tell the compiler to use my #define of XYZ over the
> enumeration constant XYZ?
>
> Is there some other solution to this problem?

It's not clear from your description, but you can sometimes hide a name in a
header with a #define. If x.h haves a enum{...,X,...} and you want to hide X,
you can add
#define X Xenum
to the beginning and to the end
#undef X

Anywhere you want to use the enum value instead of the define, change X to Xenum.

--
I remember finding out about you, | I survived XYZZY-Day.
Everyday my mind is all around you,| I'm whoever you want me to be.
Looking out from my lonely room |Annoying Usenet one post at a time.
Day after day. | At least I can stay in character.

Eric Sosman

6/3/2011 11:48:00 AM

0

On 6/3/2011 7:02 AM, John Small wrote:
> I have been trying to resurrect some old code. Since the last time the
> code compiled correctly one the 3rd party header files has changed in
> a way that prevents the old code from compiling.
>
> The changed 3rd party header file now uses a typedef to define an
> enumeration type. And two of the names used for the enumeration
> constants that typedef now match names used in #defines's in the old
> code. But the values of the names in the enueration type do not match
> the values set be the #define's in the old code.
>
> Unfortunately the conflict occurs with identifiers that are used in
> many places in 50+ source files. So I am hoping that I don't have to
> change the identifiers in the old code's defines and all the
> references to these identifiers.
>
> Changing the 3rd party header is not an option. And using the new
> values for the names is not an option either because the old code used
> its #define's to name specific numbers.
>
> Is there a way to tell the compiler to use my #define of XYZ over the
> enumeration constant XYZ?

Wherever the macro is visible, the compiler will *always* use
it -- so the answer to your first question is "Yes, and you're
already doing it." :)

You don't mention the nature of the compilation problem, but
I'm going to guess it's something like

/* your code */
#define XYZ "forty-two"
#include "foreign.h"
...

/* foreign.h */
enum frobozz { ABC, XYZ };
...

.... and the compiler chokes because your macro definition turns
the header's content into the equivalent of

enum frobozz { ABC, "forty-two" };

.... which is a syntax error. If this is the case, one possible
approach would be to postpone defining the macro until after the
inclusion:

#include "foreign.h" /* declares XYZ as an enum constant */
#define XYZ "forty-two" /* doesn't interfere with the enum */

Now, since all pre-existing uses of XYZ in your own code were meant
to expand to "forty-two" anyhow (you never used the enum constant
before the constant even existed), your code will compile just as it
did before. The enum constant XYZ will languish, still declared but
inaccessible.

Unfortunately, this might not work. The foreign header might
go on to use XYZ in other ways:

/* foreign.h */
enum frobozz { ABC, XYZ };
void foreignWorker(enum frobozz, const char *plugh);
#define FOREIGN_YES(x) foreignWorker(ABC, (x))
#define FOREIGN_MAYBE(x) foreignWorker(XYZ, (x))

.... and now when your code uses

FOREIGN_MAYBE("Say it ain't so, Joe!");

.... which used to work with the old version's FOREIGN_MAYBE, you
wind up with the equivalent of

foreignWorker("forty-two", "Say it ain't so, Joe!");

.... and just get a different compilation error. (The particular
use shown here is just an example; similar problems would arise
any time foreign.h defines a macro with XYZ in its expansion, and
when your code invokes the macro you get the wrong XYZ.)

Besides, even if rearranging the order of inclusion cures the
problem for the moment, the solution is fragile and likely to
come unstuck eventually. Inclusion order is not too difficult to
set up initially, but is quite difficult to maintain as new
headers are invented, old headers are combined, and code evolves.

I'd recommend that you go through your existing code, changing
all XYZ to MY_XYZ. Yes, it's scut-work, but you'll only have to
do it once (unless you're unlucky in your choice of a new name...).
Half a hundred files won't take very long; it's not as if you were
dealing with an enormous code base. If you've still got the old
third-party header and libraries available, build your renamed code
with them and run your existing tests before incorporating the
newer version; it'll be a useful confidence-builder to know that
your renaming has not gone awry somewhere.

--
Eric Sosman
esosman@ieee-dot-org.invalid

Not

6/3/2011 4:22:00 PM

0

On Fri, 03 Jun 2011 06:02:32 -0500, John Small wrote:

> I have been trying to resurrect some old code. Since the last time the
> code compiled correctly one the 3rd party header files has changed in a
> way that prevents the old code from compiling.
>
> The changed 3rd party header file now uses a typedef to define an
> enumeration type. And two of the names used for the enumeration
> constants that typedef now match names used in #defines's in the old
> code. But the values of the names in the enueration type do not match
> the values set be the #define's in the old code.
>
> Unfortunately the conflict occurs with identifiers that are used in many
> places in 50+ source files. So I am hoping that I don't have to change
> the identifiers in the old code's defines and all the references to
> these identifiers.

Some people have mentioned how to order the define's to work ok,
and some have suggested that you just rename the identifiers in
your own code.

(OT in c.l.c) You could copy the source files to a working
directory, cd into it, and run the following script (where
o1, o2 are old names and n1, n2 new):

#!/bin/sh
for i in "*.c" "*.h"; do
echo Processing $i
sed -e 's/o1/n1/g' -e 's/o2/n2/g' "$i" > t
diff "$i" t > "$i.diff"
mv t "$i";
done

and then check if the .diff files look ok. If your file names
have no characters (eg, spaces) that need quoting, you can drop
the double-quotes from above script. If you need help with running
the script, post in comp.unix.shell; if your development system
is OS/2, install and test bash and sed before posting there. Eg,
get bash from <http://www.os2site.com/sw/util/shell/inde....
The sed OS/2 links in <http://sed.sourceforge.net/sedfaq... are
broken but perhaps you already have sed ? (end OT)

> Changing the 3rd party header is not an option. And using the new values
> for the names is not an option either because the old code used its
> #define's to name specific numbers.

I suggest that your replace your define's (of integer numbers, at
least) with enum's.

....

--
jiw