diff --git a/include/mruby.h b/include/mruby.h index 8904ae334..06635b79e 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -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 */ { diff --git a/include/mruby/gc.h b/include/mruby/gc.h index 9f4ceec4d..ba56cefd7 100644 --- a/include/mruby/gc.h +++ b/include/mruby/gc.h @@ -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 diff --git a/src/class.c b/src/class.c index b668ae55f..5b806c090 100644 --- a/src/class.c +++ b/src/class.c @@ -890,6 +890,8 @@ mrb_block_given_p(mrb_state *mrb) return !mrb_nil_p(b); } +static mrb_int mrb_get_args_v(mrb_state *mrb, mrb_args_format format, void** ptr, va_list ap); + /* retrieve arguments from mrb_state. @@ -929,12 +931,31 @@ mrb_block_given_p(mrb_state *mrb) +: Request a not frozen object; However, except nil value */ MRB_API mrb_int -mrb_get_args(mrb_state *mrb, const char *format, ...) +mrb_get_args(mrb_state *mrb, mrb_args_format format, ...) +{ + va_list ap; + va_start(ap, format); + mrb_int rc = mrb_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; + mrb_int rc = mrb_get_args_v(mrb, format, args, ap); + return rc; +} + +#define GET_ARG(_type) (ptr ? ((_type)(*ptr++)) : va_arg(ap, _type)) + +MRB_API mrb_int +mrb_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; @@ -946,8 +967,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 '|': @@ -1071,7 +1090,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) { @@ -1089,7 +1108,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; @@ -1106,8 +1125,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)) { @@ -1126,7 +1145,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)) { @@ -1145,8 +1164,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)) { @@ -1167,7 +1186,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); } @@ -1178,7 +1197,7 @@ 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); } @@ -1186,7 +1205,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) break; case 'b': { - mrb_bool *boolp = va_arg(ap, mrb_bool*); + mrb_bool *boolp = GET_ARG(mrb_bool*); if (pickarg) { *boolp = mrb_test(*pickarg); @@ -1197,7 +1216,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); } @@ -1208,8 +1227,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; @@ -1225,7 +1244,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"); @@ -1241,7 +1260,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; @@ -1252,8 +1271,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) { @@ -1278,7 +1297,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) { @@ -1341,7 +1360,6 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } finish: - va_end(ap); return i; } diff --git a/src/gc.c b/src/gc.c index 610929d90..16ac8841b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -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);