summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-05-21 14:01:23 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-05-21 14:01:23 +0000
commit8becb1e465ad96a4aff3ebb45a9d26972bd2c663 (patch)
tree31273e08ac860d934d5c34ea4607030091e3c00c
parent3caa1776689e108e9c701c2f52754185385368f7 (diff)
Revert r50102
This reverts "* include/ruby/ruby.h (rb_scan_args): don't use ALWAYS_INLINE with" This rb_scan_args macro is GCCism. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55104 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog12
-rw-r--r--class.c135
-rw-r--r--include/ruby/ruby.h139
3 files changed, 136 insertions, 150 deletions
diff --git a/ChangeLog b/ChangeLog
index 88c21b97a5..f8e4a70224 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,15 +1,3 @@
-Sat May 21 22:45:50 2016 NAKAMURA Usaku <usa@ruby-lang.org>
-
- * include/ruby/ruby.h (rb_scan_args): don't use ALWAYS_INLINE with
- `inline`. if gcc needs this duplication, do in ALWAYS_INLINE macro.
-
-Sat May 21 21:11:56 2016 NARUSE, Yui <naruse@ruby-lang.org>
-
- * include/ruby/ruby.h (rb_scan_args): use __VA_ARGS__ instead of
- va_arg to allow compilers optimize more aggressive.
- https://gustedt.wordpress.com/2011/07/10/avoid-writing-va_arg-functions/
- rb_scan_args is now expected to be statically resolved.
-
Sat May 21 21:07:18 2016 NARUSE, Yui <naruse@ruby-lang.org>
* configure.in (ALWAYS_INLINE): force compilers the function inlined.
diff --git a/class.c b/class.c
index 62be074341..0261838e5d 100644
--- a/class.c
+++ b/class.c
@@ -1754,6 +1754,141 @@ rb_obj_basic_to_s_p(VALUE obj)
return 0;
}
+#include <stdarg.h>
+
+int
+rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
+{
+ int i;
+ const char *p = fmt;
+ VALUE *var;
+ va_list vargs;
+ int f_var = 0, f_hash = 0, f_block = 0;
+ int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
+ int argi = 0;
+ VALUE hash = Qnil;
+
+ if (ISDIGIT(*p)) {
+ n_lead = *p - '0';
+ p++;
+ if (ISDIGIT(*p)) {
+ n_opt = *p - '0';
+ p++;
+ if (ISDIGIT(*p)) {
+ n_trail = *p - '0';
+ p++;
+ goto block_arg;
+ }
+ }
+ }
+ if (*p == '*') {
+ f_var = 1;
+ p++;
+ if (ISDIGIT(*p)) {
+ n_trail = *p - '0';
+ p++;
+ }
+ }
+ block_arg:
+ if (*p == ':') {
+ f_hash = 1;
+ p++;
+ }
+ if (*p == '&') {
+ f_block = 1;
+ p++;
+ }
+ if (*p != '\0') {
+ rb_fatal("bad scan arg format: %s", fmt);
+ }
+ n_mand = n_lead + n_trail;
+
+ if (argc < n_mand)
+ goto argc_error;
+
+ va_start(vargs, fmt);
+
+ /* capture an option hash - phase 1: pop */
+ if (f_hash && n_mand < argc) {
+ VALUE last = argv[argc - 1];
+
+ if (NIL_P(last)) {
+ /* nil is taken as an empty option hash only if it is not
+ ambiguous; i.e. '*' is not specified and arguments are
+ given more than sufficient */
+ if (!f_var && n_mand + n_opt < argc)
+ argc--;
+ }
+ else {
+ hash = rb_check_hash_type(last);
+ if (!NIL_P(hash)) {
+ VALUE opts = rb_extract_keywords(&hash);
+ if (!hash) argc--;
+ hash = opts ? opts : Qnil;
+ }
+ }
+ }
+ /* capture leading mandatory arguments */
+ for (i = n_lead; i-- > 0; ) {
+ var = va_arg(vargs, VALUE *);
+ if (var) *var = argv[argi];
+ argi++;
+ }
+ /* capture optional arguments */
+ for (i = n_opt; i-- > 0; ) {
+ var = va_arg(vargs, VALUE *);
+ if (argi < argc - n_trail) {
+ if (var) *var = argv[argi];
+ argi++;
+ }
+ else {
+ if (var) *var = Qnil;
+ }
+ }
+ /* capture variable length arguments */
+ if (f_var) {
+ int n_var = argc - argi - n_trail;
+
+ var = va_arg(vargs, VALUE *);
+ if (0 < n_var) {
+ if (var) *var = rb_ary_new4(n_var, &argv[argi]);
+ argi += n_var;
+ }
+ else {
+ if (var) *var = rb_ary_new();
+ }
+ }
+ /* capture trailing mandatory arguments */
+ for (i = n_trail; i-- > 0; ) {
+ var = va_arg(vargs, VALUE *);
+ if (var) *var = argv[argi];
+ argi++;
+ }
+ /* capture an option hash - phase 2: assignment */
+ if (f_hash) {
+ var = va_arg(vargs, VALUE *);
+ if (var) *var = hash;
+ }
+ /* capture iterator block */
+ if (f_block) {
+ var = va_arg(vargs, VALUE *);
+ if (rb_block_given_p()) {
+ *var = rb_block_proc();
+ }
+ else {
+ *var = Qnil;
+ }
+ }
+ va_end(vargs);
+
+ if (argi < argc) {
+ argc_error:
+ rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt);
+ }
+
+ return argc;
+}
+
VALUE
rb_keyword_error_new(const char *error, VALUE keys)
{
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index c7d700445e..e09d4a739b 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1767,6 +1767,7 @@ VALUE rb_funcallv_public(VALUE, ID, int, const VALUE*);
#define rb_funcall3 rb_funcallv_public
VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE*);
VALUE rb_funcall_with_block(VALUE, ID, int, const VALUE*, VALUE);
+int rb_scan_args(int, const VALUE*, const char*, ...);
VALUE rb_call_super(int, const VALUE*);
VALUE rb_current_receiver(void);
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *);
@@ -2149,144 +2150,6 @@ unsigned long ruby_strtoul(const char *str, char **endptr, int base);
PRINTF_ARGS(int ruby_snprintf(char *str, size_t n, char const *fmt, ...), 3, 4);
int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap);
-#define RB_NARG0(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,...) _19
-#define RB_NARG(...) RB_NARG0(__VA_ARGS__,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
-#define rb_scan_args(argc,argvp,fmt,...) \
- rb_scan_args0(argc,argv,fmt,RB_NARG(__VA_ARGS__),(VALUE*[]){__VA_ARGS__})
-ALWAYS_INLINE(static int
-rb_scan_args0(int argc, const VALUE *argv, const char *fmt, int varc, VALUE *vars[]));
-static inline int
-rb_scan_args0(int argc, const VALUE *argv, const char *fmt, int varc, VALUE *vars[])
-{
- int i;
- const char *p = fmt;
- VALUE *var;
- int f_var = 0, f_hash = 0, f_block = 0;
- int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
- int argi = 0, vari = 0;
- VALUE hash = Qnil;
-
- if (ISDIGIT(*p)) {
- n_lead = *p - '0';
- p++;
- if (ISDIGIT(*p)) {
- n_opt = *p - '0';
- p++;
- if (ISDIGIT(*p)) {
- n_trail = *p - '0';
- p++;
- goto block_arg;
- }
- }
- }
- if (*p == '*') {
- f_var = 1;
- p++;
- if (ISDIGIT(*p)) {
- n_trail = *p - '0';
- p++;
- }
- }
- block_arg:
- if (*p == ':') {
- f_hash = 1;
- p++;
- }
- if (*p == '&') {
- f_block = 1;
- p++;
- }
- if (*p != '\0') {
- rb_fatal("bad scan arg format: %s", fmt);
- }
- n_mand = n_lead + n_trail;
-
- if (argc < n_mand)
- goto argc_error;
-
- /* capture an option hash - phase 1: pop */
- if (f_hash && n_mand < argc) {
- VALUE last = argv[argc - 1];
-
- if (NIL_P(last)) {
- /* nil is taken as an empty option hash only if it is not
- ambiguous; i.e. '*' is not specified and arguments are
- given more than sufficient */
- if (!f_var && n_mand + n_opt < argc)
- argc--;
- }
- else {
- hash = rb_check_hash_type(last);
- if (!NIL_P(hash)) {
- VALUE opts = rb_extract_keywords(&hash);
- if (!hash) argc--;
- hash = opts ? opts : Qnil;
- }
- }
- }
- /* capture leading mandatory arguments */
- for (i = n_lead; i-- > 0; ) {
- var = vars[vari++];
- if (var) *var = argv[argi];
- argi++;
- }
- /* capture optional arguments */
- for (i = n_opt; i-- > 0; ) {
- var = vars[vari++];
- if (argi < argc - n_trail) {
- if (var) *var = argv[argi];
- argi++;
- }
- else {
- if (var) *var = Qnil;
- }
- }
- /* capture variable length arguments */
- if (f_var) {
- int n_var = argc - argi - n_trail;
-
- var = vars[vari++];
- if (0 < n_var) {
- if (var) *var = rb_ary_new4(n_var, &argv[argi]);
- argi += n_var;
- }
- else {
- if (var) *var = rb_ary_new();
- }
- }
- /* capture trailing mandatory arguments */
- for (i = n_trail; i-- > 0; ) {
- var = vars[vari++];
- if (var) *var = argv[argi];
- argi++;
- }
- /* capture an option hash - phase 2: assignment */
- if (f_hash) {
- var = vars[vari++];
- if (var) *var = hash;
- }
- /* capture iterator block */
- if (f_block) {
- var = vars[vari++];
- if (rb_block_given_p()) {
- *var = rb_block_proc();
- }
- else {
- *var = Qnil;
- }
- }
-
- if (argi < argc) {
- argc_error:
- rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt);
- }
- if (vari != varc) {
- rb_raise(rb_eRuntimeError, "variable argument length doesn't match* %d %d", vari, varc);
- }
-
- return argc;
-}
-
#ifndef RUBY_DONT_SUBST
#include "ruby/subst.h"
#endif