Macro redefinition work-around
#1

Hello,

I'm a little stuck at the moment and am hoping someone could help me get around this. I have the following code:
pawn Код:
#define SPF&&&|||,|||                   _
#define SPF&&&%0|||%1[%2],|||           SPF&&&~%0s||||||
#define SPF&&&%0|||%1,%2,|||            SPF&&&$%0|||%1,%2,|||
#define SPF&&&%0|||%1,|||               SPF&&&~%0i||||||
#define SPF&&&$%0|||%1[%2],%3,|||       SPF&&&$%0s|||%3,|||
#define SPF&&&$%0|||%1,%2,|||           SPF&&&$%0i|||%2,|||
#define SPF&&&$%0|||%1[%2],|||          SPF&&&$%0s|||,|||
#define SPF&&&$%0|||,|||                %0
#define SPF&&&$%0|||%1,|||              SPF&&&$%0i|||,|||
#define SPF&&&~%0||||||                 %0
The code does exactly what I want, so rearranging it to where it outputs different functionality is not an option (unless you have another way to achieve the same results). The problem is that the compiler keeps saying I'm re-defining the macros (each but the first) despite being different in each declaration (as far as I can see). I can understand where it may be saying they are the same, for example:
pawn Код:
#define SPF&&&$%0|||,|||                %0
#define SPF&&&$%0|||%1,|||              SPF&&&$%0i|||,|||
These are basically the same thing (but that is why they are in that order).

I was hoping someone could give me some pointers on how to avoid these warnings while keeping the result. Note that I do know with these warnings it messes up the actual functionality, but the logic behind it is what I want the same (I'm struggling to find words to describe this appropriately). Unfortunately I cannot simply add tags and then use the _: operator as this won't be used in parameters and I cannot prefix them differently, as there is a chance the macros will run through the same one each time.

Thanks.
Reply
#2

Thanks, I was unaware that only "SPF" was used as the defined symbol.

I've already read a large portion of that thread and it is why I was able to make this work (logically at least, which really isn't that big of a deal!). I know you can use tags and prefixes to help in the search but this code will be replaced in the creation of a function definition, so those aren't options. Do you have any ideas? Or better yet, could you point me to a part of that thread that could help more specifically?
Reply
#3

I'm just looking to create a macro that can take parameters and return the corresponding specifiers. For example:
pawn Код:
integer - i
string[] - s
integer, string[], str[] - iss
count, depth - ii
(none) - _
I know there are issues that [] could be more than just a string representation, but this will be used "in house" and I know I will only pass those two types to it. The logic for the macros above work, but the re-definition is getting in the way. I was trying to use prefixes but then problems occured when needing to run through the same macro multiple times. Tags also wouldn't work as this is used in cases were using _: isn't acceptable.

Any ideas are much appreciated.
Reply
#4

1) Sorry, here is an example:
Quote:

Convert:
pawn Код:
OF::Function(integer, string[])
To:
pawn Код:
of_Function_is(integer, string[])
If it helps any, this is an example of where you might have overloaded functions (I already found another way to do them (thanks Slice), but this would be much neater and I would have more uses for this functionality). Actually now that I am looking at it more, I'm thinking there may be a much simpler way to do this (at least without things like optional parameters). It'll have to wait until I get back to test it however.

2) That is a good point and would also let me expand this a little bit if I can get it working, in case ever needed. Thanks.
Reply
#5

That is neat!

I never thought of implementing tags in that way. I should be able to finish the rest without much problem.

Thanks!
Reply
#6

Took some time to finish what you posted above today. I don't know what you meant by it was very incomplete, it only took me a few minutes and a couple extra lines to finish it up! Doesn't include the distinction between strings and arrays, or other types yet, but this was just a small prototype.
pawn Код:
#define OF::%0(%1) static stock __%0__(){return _:SPF0:SPF1:0;}of_%0_(%1,)

// Check for parameters - if none, return immediately; otherwise, split for further parsing
#define SPF0:SPF1:0;}%0(,) 0;}%0()
#define SPF1:0;}%0(%1,%2) SPF2:SPF3:SPF4:SPF5:0;}%0(|||%1|||%2)

// Add checking for strings and ints - this assumes there are two+ parameters left
#define SPF2:SPF3:SPF4:SPF5:0;}%0(%9|||%1[]|||%2,%3) SPF2:SPF3:SPF4:SPF5:0;}%0s(%9%1[],|||%2|||%3)
#define SPF3:SPF4:SPF5:0;}%0(%9|||%1|||%2,%3) SPF2:SPF3:SPF4:SPF5:0;}%0i(%9%1,|||%2|||%3)

// Add checking for strings and ints - this assumes only one parameter is left
#define SPF4:SPF5:0;}%0(%9|||%1[]|||) 0;}%0s(%9%1[])
#define SPF5:0;}%0(%9|||%1|||) 0;}%0i(%9%1)
It works well, besides one small warning. The "holder functions" that is used to return all the tags is continually re-defined (as this is for overloaded functions). I've tried a few things to get it to work, one being #undef the function (__%0__) inside the function body itself before the return, but it seemed to have no effect. I also tried altering the function (__%0__) to include some distinction based on the parameters, but then again no tags could be used, so I'm stuck there. A final plausible solution I had was to #undef it inside the actual body of the final created function (of_Test_%1), but it got conflicted as it required me searching for an ending curly bracket, which developed issues in syntax:
pawn Код:
OF::Test(int) {
}
OF::Test(int)
{
}
// etc
Finally, I thought of creating a second unique functions (based on the specifiers returned at the end) whose only purpose was to #undef the original holder function (__%0__). This created code like so:
pawn Код:
// NOT COMPLETE NOR WORKS, JUST AN EXAMPLE
#define OF::%0(%1) static stock __%0__(){return _:SPF0:SPF1:0;}stock __%0_(){#undef __%0__}of_%0_(%1,)

// Check for parameters - if none, return immediately; otherwise, split for further parsing
#define SPF0:SPF1:0;}%0__%1_(){%2}%3(,) 0;}%0__%1_(){%2}%3()
#define SPF1:0;}%0__%1_(){%2}%3(%4,%5) SPF2:SPF3:SPF4:SPF5:0;}%0__%1_(){%2}%3(|||%4|||%5)

// Add checking for strings and ints - this assumes there are two+ parameters left
#define SPF2:SPF3:SPF4:SPF5:0;}%0__%1_(){%2}%3(%9|||%4[]|||%5,%6) SPF2:SPF3:SPF4:SPF5:0;}%0__%1_(){%2}%3s(%9%4[],|||%5|||%6)
#define SPF3:SPF4:SPF5:0;}%0__%1_(){%2}%3(%9|||%4|||%5,%6) SPF2:SPF3:SPF4:SPF5:0;}%0__%1_(){%2}%3i(%9%4,|||%5|||%6)

// Add checking for strings and ints - this assumes only one parameter is left
#define SPF4:SPF5:0;}%0__%1_(){%2}%3(%9|||%4[]|||) SPF99:0;}%0__%1_(){%2}%3s(%9%4[])
#define SPF5:0;}%0__%1_(){%2}%3(%9|||%4|||) SPF99:0;}%0__%1_(){%2}%3i(%9%4)

// Final - create the function to undefine the original "holder" function
#define SPF99:0;}%0__%1_(){%2}%3(%4) 0;}%0__%1_%3(){%2}(%4)
However, I soon realized that that unique function would actually never be called from that definition, so would need to go inside another function. The only way to do that without creating an infinite loop would be to have it called in the final function (of_Test_%1), but again, that would lead to the issue of syntax.

I'm still searching for a way to make that work, but if you have any suggestions, please let me know!

P.S. I actually just found something that confuses me. Perhaps you could give me some insight onto why this is happening?
pawn Код:
Test() {}

stock _Test()
{
    #undef Test
}

main()
{
    _Test();
    #if defined Test
        print("IT IS STILL ALIVE");
    #else
        print("IT HAS BEEN TAKEN");
    #endif
}
This code will give me the following errors/warnings:
Код:
(60) : error 017: undefined symbol "Test"
(60) : error 029: invalid expression, assumed zero
(60 -- 61) : error 076: syntax error in the expression, or invalid function call
(60 -- 61) : fatal error 107: too many error messages on one line
This is saying, as far as I can understand, that Test() {} is not being defined with the symbol name of "Test", but something else. However, if I change the code to the following:
pawn Код:
Test() {}

stock _Test()
{
    #undef MAX_PLAYERS
}

main()
{
    _Test();
    #if defined Test
        print("IT IS STILL ALIVE");
    #else
        print("IT HAS BEEN TAKEN");
    #endif
}
It only throws this one warning:
Код:
(72) : warning 203: symbol is never used: "Test"
Which is saying that it IS defined with the symbol "Test".
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)