Skip to content

Commit

Permalink
Merge branch 'sasq64-get-args-array'
Browse files Browse the repository at this point in the history
  • Loading branch information
matz committed Aug 24, 2022
2 parents 7c0f7e2 + d4e649f commit b832856
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 63 deletions.
7 changes: 7 additions & 0 deletions include/mruby.h
Expand Up @@ -1014,6 +1014,13 @@ struct mrb_kwargs
*/
MRB_API mrb_int mrb_get_args(mrb_state *mrb, mrb_args_format format, ...);

/**
* Array version of mrb_get_args()
*
* @param ptr Array of void*, in the same order as the varargs version.
*/
MRB_API mrb_int mrb_get_args_a(mrb_state *mrb, mrb_args_format format, void** ptr);

MRB_INLINE mrb_sym
mrb_get_mid(mrb_state *mrb) /* get method symbol */
{
Expand Down
3 changes: 2 additions & 1 deletion include/mruby/gc.h
Expand Up @@ -48,7 +48,8 @@ typedef struct mrb_heap_page {
struct mrb_heap_page *free_next;
struct mrb_heap_page *free_prev;
mrb_bool old:1;
void *objects[];
/* Flexible array members area a C99 feature, not C++ compatible */
/* void* objects[]; */
} mrb_heap_page;

#ifdef _MSC_VER
Expand Down
137 changes: 76 additions & 61 deletions src/class.c
Expand Up @@ -890,51 +890,14 @@ mrb_block_given_p(mrb_state *mrb)
return !mrb_nil_p(b);
}

/*
retrieve arguments from mrb_state.
mrb_get_args(mrb, format, ...)
returns number of arguments parsed.
format specifiers:
string mruby type C type note
----------------------------------------------------------------------------------------------
o: Object [mrb_value]
C: Class/Module [mrb_value] when ! follows, the value may be nil
S: String [mrb_value] when ! follows, the value may be nil
A: Array [mrb_value] when ! follows, the value may be nil
H: Hash [mrb_value] when ! follows, the value may be nil
s: String [const char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil
z: String [const char*] NUL terminated string; z! gives NULL for nil
a: Array [const mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil
c: Class/Module [strcut RClass*] c! gives NULL for nil
f: Integer/Float [mrb_float]
i: Integer/Float [mrb_int]
b: boolean [mrb_bool]
n: String/Symbol [mrb_sym]
d: data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified; when ! follows, the value may be nil
&: block [mrb_value] &! raises exception if no block given
*: rest argument [const mrb_value*,mrb_int] The rest of the arguments as an array; *! avoid copy of the stack
|: optional Following arguments are optional
?: optional given [mrb_bool] true if preceding argument (optional) is given
':': keyword args [mrb_kwargs const] Get keyword arguments
format modifiers:
#define GET_ARG(_type) (ptr ? ((_type)(*ptr++)) : va_arg(ap, _type))

string note
----------------------------------------------------------------------------------------------
!: Switch to the alternate mode; The behaviour changes depending on the specifier
+: Request a not frozen object; However, except nil value
*/
MRB_API mrb_int
mrb_get_args(mrb_state *mrb, const char *format, ...)
static mrb_int
get_args_v(mrb_state *mrb, mrb_args_format format, void** ptr, va_list ap)
{
const char *fmt = format;
char c;
mrb_int i = 0;
va_list ap;
mrb_callinfo *ci = mrb->c->ci;
mrb_int argc = ci->n;
const mrb_value *argv = ci->stack+1;
Expand All @@ -946,8 +909,6 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_bool reqkarg = FALSE;
int argc_min = 0, argc_max = 0;

va_start(ap, format);

while ((c = *fmt++)) {
switch (c) {
case '|':
Expand Down Expand Up @@ -1071,7 +1032,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
mrb_value *p;

p = va_arg(ap, mrb_value*);
p = GET_ARG(mrb_value*);
if (pickarg) {
if (!(altmode && mrb_nil_p(*pickarg))) {
switch (c) {
Expand All @@ -1089,7 +1050,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
struct RClass **p;

p = va_arg(ap, struct RClass**);
p = GET_ARG(struct RClass**);
if (pickarg) {
if (altmode && mrb_nil_p(*pickarg)) {
*p = NULL;
Expand All @@ -1106,8 +1067,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
const char **ps = 0;
mrb_int *pl = 0;

ps = va_arg(ap, const char**);
pl = va_arg(ap, mrb_int*);
ps = GET_ARG(const char**);
pl = GET_ARG(mrb_int*);
if (needmodify) goto bad_needmodify;
if (pickarg) {
if (altmode && mrb_nil_p(*pickarg)) {
Expand All @@ -1126,7 +1087,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
const char **ps;

ps = va_arg(ap, const char**);
ps = GET_ARG(const char**);
if (needmodify) goto bad_needmodify;
if (pickarg) {
if (altmode && mrb_nil_p(*pickarg)) {
Expand All @@ -1145,8 +1106,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
const mrb_value **pb;
mrb_int *pl;

pb = va_arg(ap, const mrb_value**);
pl = va_arg(ap, mrb_int*);
pb = GET_ARG(const mrb_value**);
pl = GET_ARG(mrb_int*);
if (needmodify) goto bad_needmodify;
if (pickarg) {
if (altmode && mrb_nil_p(*pickarg)) {
Expand All @@ -1167,7 +1128,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
mrb_float *p;

p = va_arg(ap, mrb_float*);
p = GET_ARG(mrb_float*);
if (pickarg) {
*p = mrb_as_float(mrb, *pickarg);
}
Expand All @@ -1178,15 +1139,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
mrb_int *p;

p = va_arg(ap, mrb_int*);
p = GET_ARG(mrb_int*);
if (pickarg) {
*p = mrb_as_int(mrb, *pickarg);
}
}
break;
case 'b':
{
mrb_bool *boolp = va_arg(ap, mrb_bool*);
mrb_bool *boolp = GET_ARG(mrb_bool*);

if (pickarg) {
*boolp = mrb_test(*pickarg);
Expand All @@ -1197,7 +1158,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
mrb_sym *symp;

symp = va_arg(ap, mrb_sym*);
symp = GET_ARG(mrb_sym*);
if (pickarg) {
*symp = to_sym(mrb, *pickarg);
}
Expand All @@ -1208,8 +1169,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
void** datap;
struct mrb_data_type const* type;

datap = va_arg(ap, void**);
type = va_arg(ap, struct mrb_data_type const*);
datap = GET_ARG(void**);
type = GET_ARG(struct mrb_data_type const*);
if (pickarg) {
if (altmode && mrb_nil_p(*pickarg)) {
*datap = 0;
Expand All @@ -1225,7 +1186,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
mrb_value *p, *bp;

p = va_arg(ap, mrb_value*);
p = GET_ARG(mrb_value*);
bp = ci->stack + mrb_ci_bidx(ci);
if (altmode && mrb_nil_p(*bp)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
Expand All @@ -1241,7 +1202,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
mrb_bool *p;

p = va_arg(ap, mrb_bool*);
p = GET_ARG(mrb_bool*);
*p = pickarg ? TRUE : FALSE;
}
break;
Expand All @@ -1252,8 +1213,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_int *pl;
mrb_bool nocopy = (altmode || !argv_on_stack) ? TRUE : FALSE;

var = va_arg(ap, const mrb_value**);
pl = va_arg(ap, mrb_int*);
var = GET_ARG(const mrb_value**);
pl = GET_ARG(mrb_int*);
if (argc > i) {
*pl = argc-i;
if (*pl > 0) {
Expand All @@ -1278,7 +1239,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
case ':':
{
mrb_value ksrc = mrb_hash_p(kdict) ? mrb_hash_dup(mrb, kdict) : mrb_hash_new(mrb);
const mrb_kwargs *kwargs = va_arg(ap, const mrb_kwargs*);
const mrb_kwargs *kwargs = GET_ARG(const mrb_kwargs*);
mrb_value *rest;

if (kwargs == NULL) {
Expand Down Expand Up @@ -1341,10 +1302,64 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}

finish:
va_end(ap);
return i;
}

/*
retrieve arguments from mrb_state.
mrb_get_args(mrb, format, ...)
returns number of arguments parsed.
format specifiers:
string mruby type C type note
----------------------------------------------------------------------------------------------
o: Object [mrb_value]
C: Class/Module [mrb_value] when ! follows, the value may be nil
S: String [mrb_value] when ! follows, the value may be nil
A: Array [mrb_value] when ! follows, the value may be nil
H: Hash [mrb_value] when ! follows, the value may be nil
s: String [const char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil
z: String [const char*] NUL terminated string; z! gives NULL for nil
a: Array [const mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil
c: Class/Module [strcut RClass*] c! gives NULL for nil
f: Integer/Float [mrb_float]
i: Integer/Float [mrb_int]
b: boolean [mrb_bool]
n: String/Symbol [mrb_sym]
d: data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified; when ! follows, the value may be nil
&: block [mrb_value] &! raises exception if no block given
*: rest argument [const mrb_value*,mrb_int] The rest of the arguments as an array; *! avoid copy of the stack
|: optional Following arguments are optional
?: optional given [mrb_bool] true if preceding argument (optional) is given
':': keyword args [mrb_kwargs const] Get keyword arguments
format modifiers:
string note
----------------------------------------------------------------------------------------------
!: Switch to the alternate mode; The behaviour changes depending on the specifier
+: Request a not frozen object; However, except nil value
*/
MRB_API mrb_int
mrb_get_args(mrb_state *mrb, mrb_args_format format, ...)
{
va_list ap;
va_start(ap, format);
mrb_int rc = get_args_v(mrb, format, NULL, ap);
va_end(ap);
return rc;
}

MRB_API mrb_int
mrb_get_args_a(mrb_state *mrb, mrb_args_format format, void** args)
{
va_list ap;
return get_args_v(mrb, format, args, ap);
}

static struct RClass*
boot_defclass(mrb_state *mrb, struct RClass *super)
{
Expand Down
6 changes: 5 additions & 1 deletion src/gc.c
Expand Up @@ -215,7 +215,11 @@ mrb_static_assert(MRB_GC_RED <= GC_COLOR_MASK);
#define other_white_part(s) ((s)->current_white_part ^ GC_WHITES)
#define is_dead(s, o) (((o)->color & other_white_part(s) & GC_WHITES) || (o)->tt == MRB_TT_FREE)

#define objects(p) ((RVALUE *)p->objects)
/* We have removed `objects[]` from `mrb_heap_page` since it was not C++
* compatible. Using array index to get pointer after structure instead. */

/* #define objects(p) ((RVALUE *)p->objects) */
#define objects(p) ((RVALUE *)&p[1])

mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb);

Expand Down

0 comments on commit b832856

Please sign in to comment.