-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
84 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,6 +70,7 @@ | |
"stdint.h": "c", | ||
"test.h": "c", | ||
"__locale": "c", | ||
"ios": "c" | ||
"ios": "c", | ||
"va_list_ex.h": "c" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#ifndef VA_LIST_EX_H_ | ||
#define VA_LIST_EX_H_ | ||
|
||
#include "metac/base.h" | ||
|
||
// this must be big enough to cover stack for alloca | ||
#define _va_list_padding (int)0x5555, (int)0x5555, (int)0x5555, (int)0x5555 | ||
static inline struct va_list_container * va_list_container_start(void** pp, struct va_list_container * p, ...) { | ||
*pp = (void*)&(pp); // store the top stack param addr | ||
va_start(p->parameters, p); | ||
return p; | ||
} | ||
/** @brief wrapper macro to put some things into va_list | ||
example how to get va_list using all this combination of macroses | ||
WITH_VA_LIST_CONTAINER(c, vprintf("%d %d %d %d %d %d %d %d %d %d\n", VA_LIST_FROM_CONTAINER(c, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10))); | ||
it outputs 1 2 3 4 5 6 7 8 9 10 | ||
WARNING: even though it works here - there is no guarantee that it will work everywhere and with everything Try not to use it. Reason: | ||
A va_list is intrinsically linked to a specific function call's stack frame. | ||
Creating a container to hold it doesn't change this fundamental characteristic. | ||
Accessing it in a different function would involve undefined behavior due to potential stack frame changes. | ||
*/ | ||
#define WITH_VA_LIST_CONTAINER(_name_, _in_...) do { \ | ||
void* pp = NULL; \ | ||
struct va_list_container _name_; \ | ||
_in_; \ | ||
va_end(_name_.parameters); \ | ||
}while(0) | ||
|
||
/** @brief macro to get va_list from container */ | ||
#define VA_LIST_CONTAINER(_name_, _args_...) va_list_container_start(&pp, &_name_, _args_, _va_list_padding) | ||
#define VA_LIST_FROM_CONTAINER(_name_, _args_...) VA_LIST_CONTAINER(_name_, _args_)->parameters | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#include "metac/test.h" | ||
#include <stdio.h> /*vsnprintf*/ | ||
#include <string.h> /*strncmp*/ | ||
#include <stdlib.h> /*alloca*/ | ||
|
||
#include "metac/backend/va_list_ex.h" | ||
|
||
|
||
METAC_START_TEST(va_list_ex_sanity) { | ||
// this doesn't work on Linux | ||
// /home/runner/work/metac/metac/src/va_list_ex_test.c:16:F:default:va_list_ex_sanity:0: expected 1 2 3 4 5 6 7 8 9 10 got 1 -1 0 4 5 -1267418064 1361077456 1361076992 1353769297 1361077488 | ||
// Windows | ||
// D:/a/metac/metac/src/va_list_ex_test.c:16:F:default:va_list_ex_sanity:0: expected 1 2 3 4 5 6 7 8 9 10 got 1024 1592742005 -826280184 4 5 6 7 8 9 10 | ||
char buf[1024]; | ||
char *expected_s = NULL; | ||
expected_s = "1 2 3 4 5 6 7 8 9 10"; | ||
WITH_VA_LIST_CONTAINER(c, | ||
VA_LIST_CONTAINER(c, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); | ||
alloca(/*1024*/((char*)&pp)-((char*)pp)); | ||
//printf("delta:%x\n", ((char*)&pp)-((char*)pp)); | ||
vsnprintf(buf, sizeof(buf), "%d %d %d %d %d %d %d %d %d %d", c.parameters)); | ||
fail_unless(strncmp(expected_s, buf, sizeof(buf)) == 0, "expected %s got %s", expected_s, buf); | ||
|
||
// so, lets be very careful with stack | ||
int i, j; | ||
int fail_i = -1; | ||
WITH_VA_LIST_CONTAINER(c, | ||
VA_LIST_CONTAINER(c, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); | ||
for (i=1; i<=10; ++i) { | ||
j = va_arg(c.parameters, int); | ||
if (j != i) { | ||
fail_i = i; | ||
break; | ||
} | ||
} | ||
); | ||
fail_unless(fail_i < 0, "fail_i: %d", fail_i); | ||
|
||
}END_TEST |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters