PDA

View Full Version : [Macro] Mutliple macros in one


Dayrion
27/07/2017, 05:19 PM
Hey there.
I'm trying to solve this problem of "redefining the macro". My english is bad so I will show you the code and I hope you can help me.

#define MACRO1<%0>[%1] %0[%1]
#define MACRO1<%0> %0
I thought about to make multiple macros but I don't know how to separate if the player enter a specific index (or length if he declares the variable) and when he doesn't enter something.

OneDay
28/07/2017, 09:21 AM
http://forum.sa-mp.com/showthread.php?t=570933

Dayrion
28/07/2017, 12:41 PM
http://forum.sa-mp.com/showthread.php?t=570933

That's not helping me

Misiur
29/07/2017, 09:09 AM
#include <a_samp>

#define MACRO1 m@1:m@2:@MACRO1
#define m@1:m@2:@MACRO1<%0>[%1] %0[%1]
#define m@2:@MACRO1<%0> %0

main() {
new Foo[32] = { -5, ... };
new bar = MACRO1<Foo>[1];
new foobar = MACRO1<5>;
printf("%d %d", bar, foobar);
}


Try something like this

Dayrion
29/07/2017, 05:39 PM
new MACRO1<Test_array>[1];
MACRO1<second_array>;
compile as:

new Test_array[1];
m@1:second_array;

Can you add some explications please?

Misiur
29/07/2017, 06:46 PM
Sure, but I suck at explaining, however I'll try. So as you've noticed, you can't have two macros with the same name. But wait, they are different! But that doesn't matter, as the name is only the first part until first invalid character. You can read more about that here, under "definitions" and "macros" (http://forum.sa-mp.com/showthread.php?t=570944). So, we do a little trick. We are gona exploit tag system and macro parser rules - the ":" character. It's both macro name-ending character, as it is tag operator. As for tags, read up about weak tags (http://wiki.sa-mp.com/wiki/Scripting:tags#Weak_tags). Weak tags don't trigger tag mismatch errors. I've chosen "m@X" as a pattern for our tags. Why? I think I saw it in some YSI library, and also it minimizes chance of name collisions later on. Now all the pieces together
#define MACRO1 m@1:m@2:@MACRO1 // Create our chain. Macro name: "MACRO1"
#define m@1:m@2:@MACRO1<%0>[%1] %0[%1] // Macro name "m@1"
#define m@2:@MACRO1<%0> %0 // Macro name "m@2"

All that's left is our m@1 tag as you've noticed. It can cause errors, if it does, you can chain tags and only outermost will be considered:
new Float:bar = MACRO1<foo>; //Tag mismatch
new Float:bar = Float:MACRO1<foo>; //All good

That's why you can nest even deeper as only outermost tag counts:
#include <a_samp>

#define MACRO1 m@1:m@2:m@3:@MACRO1
#define m@3:@MACRO1$%0$ (%0 + %0)
#define m@2:m@3:@MACRO1<%0> %0
#define m@1:m@2:m@3:@MACRO1<%0>[%1] %0[%1]

main() {
new Foo[32] = { -5, ... };
new bar = MACRO1<Foo>[1];
new Float:foobar = Float:MACRO1<5>;
new fizzbar = MACRO1$15$;
printf("%d %f %d", bar, foobar, fizzbar);
}

I'm not 100% certain all I said is true and/or relevant, so anyone - feel free to correct me.

Dayrion
29/07/2017, 09:50 PM
You explained perfectly. Thanks you so much (and I just noticed you written the tutorial about macro, he is perfect and well explained).
The problem is the weak tag because the macro return the variable with the tag every time (tag:variable). Anyway, that helped me a lot

Dayrion
31/07/2017, 12:14 AM
I would never have thought this code by myself, thanks again! :-[

Dayrion
22/11/2017, 03:29 PM
Is that possible to use the same trick without the tag? I did the same trick but it applies on a function so it return a warning message. :/

Dayrion
22/11/2017, 08:42 PM
The thing I don't understand is that %8$ before each "cmd_".
#define CMD: __:CMD_1:CMD_2:CMD_3:$

#define CMD_1:CMD_2:CMD_3:%8$%1[%2](%3) %8$cmd_%1(%3) <cmd_state: %2>
#define CMD_2:CMD_3:%8$%1{%2}(%3) %8$cmd_%1(%3) if (Is%2(playerid))
#define CMD_3:%8$%1(%3) %8$cmd_%1(%3)

I'm wondering how the compiler consider "u@(u[_:%0 u@$" ? as a variable?
u@(u[_:CMD_1: 0]);cmd_ban(playerid, params[]) if (IsAdmin(playerid))
{
return 1;
}

Dayrion
22/11/2017, 10:38 PM
I explained both those things in the posts I linked.

Okei. I understand after like 10 re-reading but I still don't understand (and that making errors), how this things can works:
u@(u[_: 0]);
u@(u[_:c_l@1:c_l@2: 0]); etc
It's ouside the function so why it should work?

main()
{
(CUSTOM_S_ACTUAL_STATE = CUSTOM_S_ALL);

u@(u[_:c_l@1:c_l@2: 0]);PrintZ(C_E_A, #TEST, "path", "message");
u@(u[_:c_l@1:c_l@2: 0]);PrintZ(C_E_A, #TEST, "path", "message & args: %i", 99);
u@(u[_:c_l@1:c_l@2: 0]);PrintZ(C_E_A, #TEST, "General", "message");
u@(u[_:c_l@1:c_l@2: 0]);PrintZ(C_E_A, #TEST, "General", "message & args: %i", 99);
}

(78) : error 004: function "u@" is not implemented
(78) : warning 221: label name "_" shadows tag name
(78) : warning 215: expression has no effect
(78) : error 001: expected token: ";", but found "]"
(78) : error 029: invalid expression, assumed zero
(78) : fatal error 107: too many error messages on one line

Your code (which is outside any functions or whatever) actually works (of course lol) and doesn't trigger the compiler about u@u(...)
u@(u[_:CMD_1:CMD_2: 0]);cmd_my_command(playerid, params[])
{
return 1;
}

u@(u[_: 0]);cmd_my_command(playerid, params[]) <cmd_state: help>
{
return 1;
}

u@(u[_:CMD_1: 0]);cmd_ban(playerid, params[]) if (IsAdmin(playerid))
{
return 1;
}

EDIT: It was a brilliant idea you got. So impressive :eek:

Dayrion
24/11/2017, 10:01 PM
Thanks a lot. That helped a lot. I didn't understand for the first part.
That's a very nice trick. Also, that can't work in a function since you can't forward a function inside another one?
If it can, well I missed an another part of your explain.

Edit:
Okei. I took the exact same trick to do that but the only bad thing is a global variable is needed to make that work.
new this_custom_hgfdsq[1];
#define c_ji_t@$ 0] = 0;
#define __@:%0$ this_custom_hgfdsq[_:%0 c_ji_t@$

#define L: __@:c_l@1:c_l@2:c_l@3:c_l@4:$L:
... other macro
main()
{
L:TEST(@, "message");
}
Compile fine and works.
Have any advice or whatever that can help me to improve myself ? :P