[Include] variadic.inc - Variadic functions!
#1

variadic.inc

Disclaimer
This is for ADVANCED variadic function manipulation ONLY! I would suggest that you use y_va from YSI for simply formatting variadic functions.

I needed this for something I was working on related to PAWN, but I just gave up on it. I accidentally wrote this include, so I thought I would finish it up and release it!

Introduction
Variadic functions are a feature in most scripting languages, where a scripter can specify an indefinite amount of arguments towards a function. However, in PAWN, this isn't possible without playing around with the assembly (later versions of PAWN have dealt with this), but this include introduces a brand new way of handling them!

More information
Have you ever wrote a function like this before?

pawn Код:
printex(str[], ...)
{
    new
        output[128];

    format(output, sizeof(output), str, ...);

    return print(output);
}
And then you figured out that you can't do it this way! The reason being is because variadic parameters don't have a referable location in ordinary PAWN code, so assembly is required, but that can be very complicated and one mistake could corrupt the entire script.

However, this include allows scripters to dynamically push arguments and format them. The pushed arguments are stored within an array by address, so they can be accessed later with the corresponding functions.

Example
Using variadic.inc:

pawn Код:
#include <a_samp>
#include <variadic>

var MyPrint(str[])
{
    new
        output[128];

    format(output, sizeof(output), str, @variadic[1]);
    return print(output);
}
You can also use "@variadic[]" with CallLocalFunction and such to call local functions with the corresponding pushed arguments.

Alternatively, you can also use "stock", but make sure you place "..." after the parameters.

String arguments
You can retrieve string arguments easily.

Getting:

pawn Код:
stock MyFunction(a[], b[])
{
    new
        addr = GetVariadicAddress(0); // Address of "a[]".

    print(GetVariadicString(addr)); // Print the result.
}
Setting:

pawn Код:
stock MyFunction(a[], b[])
{
    new
        addr = GetVariadicAddress(1); // Address of "b[]".

    SetVariadicString(addr, "Hi there.");

    print(GetVariadicString(addr)); // Print the result.
}
Functions
pawn Код:
// Get the address of a function argument.
native GetVariadicAddress(argument);

// Get the string from the specified argument address. You can return it or store it inside "dest".
native GetVariadicString(address, dest[] = "", size = sizeof(dest));

// Set the string from the specified argument address to the specified string.
native SetVariadicString(address, str[]);

// Checks if an argument is packed.
native IsArgumentPacked(address);

// Gets the length of a variadic string.
native GetVariadicLength(address);

// Delete an argument from the specified argument address.
native DeleteArgument(address);

// Popped the pushed arguments.
native PopArguments();
Obsolete functions
These functions are obsolete since version 2. However, I am simply keeping them for another feature I'm adding to this include, so the best thing to do is ignore them.

pawn Код:
// Push all arguments from "start" to "end" (obsolete).
native PushArguments(start, end);

// "Format" the variadic arguments.
native VariadicFormat(output[], len, const str[]);
   
// Call a local function with the variadic arguments.
native CallLocalVariadic(function[], const specifiers[]);

// Call a remote function with the variadic arguments.
native CallRemoteVariadic(function[], const specifiers[]);
Alternatively, you can use @variadic[] instead of these functions - but it's up to you.

Notes
- I do recommend that you use y_va for this - this is for advanced variadic function manipulation!
- This has been fully tested, but there might be problems. If so, report them!

Download
Pastebin
Reply
#2

Great work, it'll get handy.
Reply
#3

it's a good way to manipulation of string's

great work.
Reply
#4

Thanks guys! I'm also adding the packed string functionality to "SetVariadicString" but for some reason it doesn't wanna work - I have to dig further.

EDIT: Also, I'm thinking of introducing "explicit" and "register" with this library - because they're already highlighted in blue in Pawno. Looks much better to me!

Reply
#5

much usefull and nice use of addressing
Reply
#6

@Niko_boy: Thanks.

Updated the script and added 2 new functions:

pawn Код:
// Checks if an argument is packed.
native IsArgumentPacked(address);

// Gets the length of a variadic string.
native GetVariadicLength(address);
If anybody has any ideas, feel free to share.
Reply
#7

Okay, updated. Now you can do this:

pawn Код:
var MyPrint(str[])
{
    new
        output[128];

    format(output, sizeof(output), str, @variadic[1]);
    return print(output);
}
And then you can do this for example:

pawn Код:
MyPrint("%s is cool.", "Emmet");
However, this is just an experimental "proof-of-concept" include - you should still use y_va for this stuff.
Reply
#8

This is a heavily underrated include. If anyone wants to use it with mysql_format, use this edited version: http://pastebin.com/uiWGxcJa
Reply
#9

Hey man can you fix the pastebin link thanks.
Reply
#10

Quote:
Originally Posted by Pottus
Посмотреть сообщение
Hey man can you fix the pastebin link thanks.
Exactly one post above you,Pottus.
Reply
#11

Getting label's from argument would be badass.
Reply
#12

That is a modified include dude, I want the original.
Reply
#13

Quote:
Originally Posted by Pottus
Посмотреть сообщение
That is a modified include dude, I want the original.
I also have the original. https://pastebin.com/ZziVQMeL
Reply
#14

nice
Reply
#15

Thanks a lot of the re-post kvann rep for you
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)