예제 #1
0
파일: file.c 프로젝트: MercerHall/editorial
VALUE
rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result)
{
    size_t size = 0, wpath_len = 0, wdir_len = 0, whome_len = 0;
    size_t buffer_len = 0;
    char *fullpath = NULL;
    wchar_t *wfullpath = NULL, *wpath = NULL, *wpath_pos = NULL;
    wchar_t *wdir = NULL, *wdir_pos = NULL;
    wchar_t *whome = NULL, *buffer = NULL, *buffer_pos = NULL;
    UINT path_cp, cp;
    VALUE path = fname, dir = dname;
    wchar_t wfullpath_buffer[PATH_BUFFER_SIZE];
    wchar_t path_drive = L'\0', dir_drive = L'\0';
    int ignore_dir = 0;
    rb_encoding *path_encoding;
    int tainted = 0;

    /* tainted if path is tainted */
    tainted = OBJ_TAINTED(path);

    /* get path encoding */
    if (NIL_P(dir)) {
	path_encoding = rb_enc_get(path);
    }
    else {
	path_encoding = rb_enc_check(path, dir);
    }

    cp = path_cp = code_page(path_encoding);

    /* workaround invalid codepage */
    if (path_cp == INVALID_CODE_PAGE) {
	cp = CP_UTF8;
	if (!NIL_P(path)) {
	    path = fix_string_encoding(path, path_encoding);
	}
    }

    /* convert char * to wchar_t */
    convert_mb_to_wchar(path, &wpath, &wpath_pos, &wpath_len, cp);

    /* determine if we need the user's home directory */
    /* expand '~' only if NOT rb_file_absolute_path() where `abs_mode` is 1 */
    if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] == L'~' &&
	(wpath_len == 1 || IS_DIR_SEPARATOR_P(wpath_pos[1]))) {
	/* tainted if expanding '~' */
	tainted = 1;

	whome = home_dir();
	if (whome == NULL) {
	    xfree(wpath);
	    rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'");
	}
	whome_len = wcslen(whome);

	if (PathIsRelativeW(whome) && !(whome_len >= 2 && IS_DIR_UNC_P(whome))) {
	    xfree(wpath);
	    rb_raise(rb_eArgError, "non-absolute home");
	}

	/* use filesystem encoding if expanding home dir */
	path_encoding = rb_filesystem_encoding();
	cp = path_cp = system_code_page();

	/* ignores dir since we are expading home */
	ignore_dir = 1;

	/* exclude ~ from the result */
	wpath_pos++;
	wpath_len--;

	/* exclude separator if present */
	if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) {
	    wpath_pos++;
	    wpath_len--;
	}
    }
    else if (wpath_len >= 2 && wpath_pos[1] == L':') {
	if (wpath_len >= 3 && IS_DIR_SEPARATOR_P(wpath_pos[2])) {
	    /* ignore dir since path contains a drive letter and a root slash */
	    ignore_dir = 1;
	}
	else {
	    /* determine if we ignore dir or not later */
	    path_drive = wpath_pos[0];
	}
    }
    else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L'~') {
	result = get_user_from_path(&wpath_pos, 1, cp, path_cp, path_encoding);

	if (wpath)
	    xfree(wpath);

	rb_raise(rb_eArgError, "can't find user %s", StringValuePtr(result));
    }

    /* convert dir */
    if (!ignore_dir && !NIL_P(dir)) {
	/* fix string encoding */
	if (path_cp == INVALID_CODE_PAGE) {
	    dir = fix_string_encoding(dir, path_encoding);
	}

	/* convert char * to wchar_t */
	convert_mb_to_wchar(dir, &wdir, &wdir_pos, &wdir_len, cp);

	if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] == L'~' &&
	    (wdir_len == 1 || IS_DIR_SEPARATOR_P(wdir_pos[1]))) {
	    /* tainted if expanding '~' */
	    tainted = 1;

	    whome = home_dir();
	    if (whome == NULL) {
		xfree(wpath);
		xfree(wdir);
		rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'");
	    }
	    whome_len = wcslen(whome);

	    if (PathIsRelativeW(whome) && !(whome_len >= 2 && IS_DIR_UNC_P(whome))) {
		xfree(wpath);
		xfree(wdir);
		rb_raise(rb_eArgError, "non-absolute home");
	    }

	    /* exclude ~ from the result */
	    wdir_pos++;
	    wdir_len--;

	    /* exclude separator if present */
	    if (wdir_len && IS_DIR_SEPARATOR_P(wdir_pos[0])) {
		wdir_pos++;
		wdir_len--;
	    }
	}
	else if (wdir_len >= 2 && wdir[1] == L':') {
	    dir_drive = wdir[0];
	    if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) {
		wdir_len = 2;
	    }
	}
	else if (wdir_len >= 2 && IS_DIR_UNC_P(wdir)) {
	    /* UNC path */
	    if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) {
		/* cut the UNC path tail to '//host/share' */
		size_t separators = 0;
		size_t pos = 2;
		while (pos < wdir_len && separators < 2) {
		    if (IS_DIR_SEPARATOR_P(wdir[pos])) {
			separators++;
		    }
		    pos++;
		}
		if (separators == 2)
		    wdir_len = pos - 1;
	    }
	}
	else if (abs_mode == 0 && wdir_len >= 2 && wdir_pos[0] == L'~') {
	    result = get_user_from_path(&wdir_pos, 1, cp, path_cp, path_encoding);
	    if (wpath)
		xfree(wpath);

	    if (wdir)
		xfree(wdir);

	    rb_raise(rb_eArgError, "can't find user %s", StringValuePtr(result));
	}
    }

    /* determine if we ignore dir or not */
    if (!ignore_dir && path_drive && dir_drive) {
	if (towupper(path_drive) == towupper(dir_drive)) {
	    /* exclude path drive letter to use dir */
	    wpath_pos += 2;
	    wpath_len -= 2;
	}
	else {
	    /* ignore dir since path drive is different from dir drive */
	    ignore_dir = 1;
	    wdir_len = 0;
	}
    }

    if (!ignore_dir && wpath_len >= 2 && IS_DIR_UNC_P(wpath)) {
	/* ignore dir since path has UNC root */
	ignore_dir = 1;
	wdir_len = 0;
    }
    else if (!ignore_dir && wpath_len >= 1 && IS_DIR_SEPARATOR_P(wpath[0]) &&
	     !dir_drive && !(wdir_len >= 2 && IS_DIR_UNC_P(wdir))) {
	/* ignore dir since path has root slash and dir doesn't have drive or UNC root */
	ignore_dir = 1;
	wdir_len = 0;
    }

    buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1;

    buffer = buffer_pos = (wchar_t *)xmalloc((buffer_len + 1) * sizeof(wchar_t));

    /* add home */
    if (whome_len) {
	wcsncpy(buffer_pos, whome, whome_len);
	buffer_pos += whome_len;
    }

    /* Add separator if required */
    if (whome_len && wcsrchr(L"\\/:", buffer_pos[-1]) == NULL) {
	buffer_pos[0] = L'\\';
	buffer_pos++;
    }

    if (wdir_len) {
	/* tainted if dir is used and dir is tainted */
	if (!tainted && OBJ_TAINTED(dir))
	    tainted = 1;

	wcsncpy(buffer_pos, wdir_pos, wdir_len);
	buffer_pos += wdir_len;
    }

    /* add separator if required */
    if (wdir_len && wcsrchr(L"\\/:", buffer_pos[-1]) == NULL) {
	buffer_pos[0] = L'\\';
	buffer_pos++;
    }

    /* now deal with path */
    if (wpath_len) {
	wcsncpy(buffer_pos, wpath_pos, wpath_len);
	buffer_pos += wpath_len;
    }

    /* GetFullPathNameW requires at least "." to determine current directory */
    if (wpath_len == 0) {
	buffer_pos[0] = L'.';
	buffer_pos++;
    }

    /* Ensure buffer is NULL terminated */
    buffer_pos[0] = L'\0';

    /* tainted if path is relative */
    if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 && IS_DIR_UNC_P(buffer)))
	tainted = 1;

    /* FIXME: Make this more robust */
    /* Determine require buffer size */
    size = GetFullPathNameW(buffer, PATH_BUFFER_SIZE, wfullpath_buffer, NULL);
    if (size > PATH_BUFFER_SIZE) {
	/* allocate more memory than alloted originally by PATH_BUFFER_SIZE */
	wfullpath = (wchar_t *)xmalloc(size * sizeof(wchar_t));
	size = GetFullPathNameW(buffer, size, wfullpath, NULL);
    }
    else {
	wfullpath = wfullpath_buffer;
    }

    /* Remove any trailing slashes */
    if (IS_DIR_SEPARATOR_P(wfullpath[size - 1]) &&
	wfullpath[size - 2] != L':' &&
	!(size == 2 && IS_DIR_UNC_P(wfullpath))) {
	size -= 1;
	wfullpath[size] = L'\0';
    }

    /* Remove any trailing dot */
    if (wfullpath[size - 1] == L'.') {
	size -= 1;
	wfullpath[size] = L'\0';
    }

    /* removes trailing invalid ':$DATA' */
    size = remove_invalid_alternative_data(wfullpath, size);

    /* Replace the trailing path to long name */
    if (long_name)
	size = replace_to_long_name(&wfullpath, size, (wfullpath != wfullpath_buffer));

    /* sanitize backslashes with forwardslashes */
    replace_wchar(wfullpath, L'\\', L'/');

    /* convert to char * */
    size = WideCharToMultiByte(cp, 0, wfullpath, size, NULL, 0, NULL, NULL);
    if (size > (size_t)RSTRING_LEN(result)) {
	rb_str_modify(result);
	rb_str_resize(result, size);
    }

    WideCharToMultiByte(cp, 0, wfullpath, size, RSTRING_PTR(result), size, NULL, NULL);
    rb_str_set_len(result, size);

    /* convert to VALUE and set the path encoding */
    if (path_cp == INVALID_CODE_PAGE) {
	VALUE tmp;
	size_t len;

	rb_enc_associate(result, rb_utf8_encoding());
	ENC_CODERANGE_CLEAR(result);
	tmp = rb_str_encode(result, rb_enc_from_encoding(path_encoding), 0, Qnil);
	len = RSTRING_LEN(tmp);
	rb_str_modify(result);
	rb_str_resize(result, len);
	memcpy(RSTRING_PTR(result), RSTRING_PTR(tmp), len);
	rb_str_resize(tmp, 0);
    }
    rb_enc_associate(result, path_encoding);
    ENC_CODERANGE_CLEAR(result);

    /* makes the result object tainted if expanding tainted strings or returning modified path */
    if (tainted)
	OBJ_TAINT(result);

    /* TODO: better cleanup */
    if (buffer)
	xfree(buffer);

    if (wpath)
	xfree(wpath);

    if (wdir)
	xfree(wdir);

    if (whome)
	xfree(whome);

    if (wfullpath && wfullpath != wfullpath_buffer)
	xfree(wfullpath);

    if (fullpath)
	xfree(fullpath);

    return result;
}
예제 #2
0
파일: class.c 프로젝트: MSch/MacRuby
void
rb_include_module2(VALUE klass, VALUE orig_klass, VALUE module, bool check,
	bool add_methods)
{
    if (check) {
	rb_frozen_class_p(klass);
	if (!OBJ_TAINTED(klass)) {
	    rb_secure(4);
	}
	Check_Type(module, T_MODULE);
    }

    // Register the module as included in the class.
    VALUE ary = rb_attr_get(klass, idIncludedModules);
    if (ary == Qnil) {
	ary = rb_ary_new();
	rb_ivar_set(klass, idIncludedModules, ary);
    }
    else {
	if (rb_ary_includes(ary, module)) {
	    return;
	}
    }
    rb_ary_insert(ary, 0, module);

    // Mark the module as included somewhere.
    const long v = RCLASS_VERSION(module) | RCLASS_IS_INCLUDED;
    RCLASS_SET_VERSION(module, v);

    // Register the class as included in the module.
    ary = rb_attr_get(module, idIncludedInClasses);
    if (ary == Qnil) {
	ary = rb_ary_new();
	rb_ivar_set(module, idIncludedInClasses, ary);
    }
    rb_ary_push(ary, klass);

    // Delete the ancestors array if it exists, since we just changed it.
    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(klass);
    if (iv_dict != NULL) {
	CFDictionaryRemoveValue(iv_dict, (const void *)idAncestors);
    }

    if (add_methods) {
	// Copy methods. If original class has the basic -initialize and if the
	// module has a customized -initialize, we must copy the customized
	// version to the original class too.
	rb_vm_copy_methods((Class)module, (Class)klass);

	// When including into the class Class, also copy the methods to the
	// singleton class of NSObject.
	if (klass == rb_cClass || klass == rb_cModule) {
            rb_vm_copy_methods((Class)module, *(Class *)rb_cNSObject);
	}

	if (orig_klass != 0 && orig_klass != klass) {
	    Method m = class_getInstanceMethod((Class)orig_klass,
		    selInitialize);
	    Method m2 = class_getInstanceMethod((Class)klass, selInitialize);
	    if (m != NULL && m2 != NULL
		&& method_getImplementation(m) == (IMP)rb_objc_init
		&& method_getImplementation(m2) != (IMP)rb_objc_init) {
		rb_vm_copy_method((Class)orig_klass, m2);
	    }
	}
    }
}
예제 #3
0
파일: rb_u_string_gsub.c 프로젝트: now/u
/* @overload gsub(pattern, replacement)
 *
 *   Returns the receiver with all matches of PATTERN replaced by REPLACEMENT,
 *   inheriting any taint and untrust from the receiver and from REPLACEMENT.
 *
 *   The REPLACEMENT is used as a specification for what to replace matches
 *   with:
 *
 *   <table>
 *     <thead>
 *       <tr><th>Specification</th><th>Replacement</th></tr>
 *     </thead>
 *     <tbody>
 *       <tr>
 *         <td><code>\1</code>, <code>\2</code>, …, <code>\</code><em>n</em></td>
 *         <td>Numbered sub-match <em>n</em></td>
 *       </tr>
 *       <tr>
 *         <td><code>\k&lt;</code><em>name</em><code>></code></td>
 *         <td>Named sub-match <em>name</em></td>
 *       </tr>
 *     </tbody>
 *   </table>
 *
 *   The Regexp special variables `$&`, `$'`, <code>$\`</code>, `$1`, `$2`, …,
 *   `$`_n_ are updated accordingly.
 *
 *   @param [Regexp, #to_str] pattern
 *   @param [#to_str] replacement
 *   @return [U::String]
 *
 * @overload gsub(pattern, replacements)
 *
 *   Returns the receiver with all matches of PATTERN replaced by
 *   REPLACEMENTS#[_match_], where _match_ is the matched substring, inheriting
 *   any taint and untrust from the receiver and from the
 *   REPLACEMENTS#[_match_]es, as well as any taint on REPLACEMENTS.
 *
 *   The Regexp special variables `$&`, `$'`, <code>$\`</code>, `$1`, `$2`, …,
 *   `$`_n_ are updated accordingly.
 *
 *   @param [Regexp, #to_str] pattern
 *   @param [#to_hash] replacements
 *   @raise [RuntimeError] If any replacement is the result being constructed
 *   @raise [Exception] Any error raised by REPLACEMENTS#default, if it gets
 *     called
 *   @return [U::String]
 *
 * @overload gsub(pattern){ |match| … }
 *
 *   Returns the receiver with all matches of PATTERN replaced by the results
 *   of the given block, inheriting any taint and untrust from the receiver and
 *   from the results of the given block.
 *
 *   The Regexp special variables `$&`, `$'`, <code>$\`</code>, `$1`, `$2`, …,
 *   `$`_n_ are updated accordingly.
 *
 *   @param [Regexp, #to_str] pattern
 *   @yieldparam [U::String] match
 *   @yieldreturn [#to_str]
 *   @return [U::String]
 *
 * @overload gsub(pattern)
 *
 *   Returns an Enumerator over the matches of PATTERN in the receiver.
 *
 *   The Regexp special variables `$&`, `$'`, <code>$\`</code>, `$1`, `$2`, …,
 *   `$`_n_ will be updated accordingly.
 *
 *   @param [Regexp, #to_str] pattern
 *   @return [Enumerator] */
VALUE
rb_u_string_gsub(int argc, VALUE *argv, VALUE self)
{
        VALUE pattern, replacement;
        VALUE replacements = Qnil;
        bool use_block = false;
        bool tainted = false;

        if (argc == 1) {
                RETURN_ENUMERATOR(self, argc, argv);
                use_block = true;
        }

        if (rb_scan_args(argc, argv, "11", &pattern, &replacement) == 2) {
                replacements = rb_check_convert_type(replacement, T_HASH,
                                                     "Hash", "to_hash");
                if (NIL_P(replacements))
                        StringValue(replacement);
                if (OBJ_TAINTED(replacement))
                        tainted = true;
        }

        pattern = rb_u_pattern_argument(pattern, true);

        VALUE str = rb_str_to_str(self);
        long begin = rb_reg_search(pattern, str, 0, 0);
        if (begin < 0)
                return self;

        const char *base = RSTRING_PTR(str);
        const char *p = base;
        const char *end = RSTRING_END(str);
        VALUE substituted = rb_u_str_buf_new(RSTRING_LEN(str) + 30);
        do {
                VALUE match = rb_backref_get();
                struct re_registers *registers = RMATCH_REGS(match);
                VALUE result;

                if (use_block || !NIL_P(replacements)) {
                        if (use_block) {
                                VALUE ustr = rb_u_string_new_rb(rb_reg_nth_match(0, match));
                                result = rb_u_string_object_as_string(rb_yield(ustr));
                        } else {
                                VALUE ustr = rb_u_string_new_c(self,
                                                               base + registers->beg[0],
                                                               registers->end[0] - registers->beg[0]);
                                result = rb_u_string_object_as_string(rb_hash_aref(replacements, ustr));
                        }

                        if (result == substituted)
                                rb_u_raise(rb_eRuntimeError,
                                           "result of block is string being built; please try not to cheat");
                } else
                        result =
#ifdef HAVE_RB_REG_REGSUB4
                        rb_reg_regsub(replacement, str, registers, pattern);
#else
                        rb_reg_regsub(replacement, str, registers);
#endif

                if (OBJ_TAINTED(result))
                        tainted = true;

                const struct rb_u_string *value = RVAL2USTRING_ANY(result);

                rb_str_buf_cat(substituted, p, registers->beg[0] - (p - base));
                rb_str_buf_cat(substituted, USTRING_STR(value), USTRING_LENGTH(value));
                OBJ_INFECT(substituted, result);

                p = base + registers->end[0];
                if (registers->beg[0] == registers->end[0])
                        p = u_next(p);
                if (p >= end)
                        break;

                begin = rb_reg_search(pattern, str, registers->end[0], 0);
        } while (begin >= 0);

        if (p < end)
                rb_str_buf_cat(substituted, p, end - p);

        rb_reg_search(pattern, str, end - p, 0);

        RBASIC(substituted)->klass = rb_obj_class(str);
        OBJ_INFECT(substituted, str);
        if (tainted)
                OBJ_TAINT(substituted);

        return rb_u_string_new_rb(substituted);
}
예제 #4
0
VALUE
rb_str_format(int argc, const VALUE *argv, VALUE fmt)
{
    rb_encoding *enc;
    const char *p, *end;
    char *buf;
    long blen, bsiz;
    VALUE result;

    long scanned = 0;
    int coderange = ENC_CODERANGE_7BIT;
    int width, prec, flags = FNONE;
    int nextarg = 1;
    int posarg = 0;
    int tainted = 0;
    VALUE nextvalue;
    VALUE tmp;
    VALUE str;
    volatile VALUE hash = Qundef;

#define CHECK_FOR_WIDTH(f)				 \
    if ((f) & FWIDTH) {					 \
	rb_raise(rb_eArgError, "width given twice");	 \
    }							 \
    if ((f) & FPREC0) {					 \
	rb_raise(rb_eArgError, "width after precision"); \
    }
#define CHECK_FOR_FLAGS(f)				 \
    if ((f) & FWIDTH) {					 \
	rb_raise(rb_eArgError, "flag after width");	 \
    }							 \
    if ((f) & FPREC0) {					 \
	rb_raise(rb_eArgError, "flag after precision"); \
    }

    ++argc;
    --argv;
    if (OBJ_TAINTED(fmt)) tainted = 1;
    StringValue(fmt);
    enc = rb_enc_get(fmt);
    fmt = rb_str_new4(fmt);
    p = RSTRING_PTR(fmt);
    end = p + RSTRING_LEN(fmt);
    blen = 0;
    bsiz = 120;
    result = rb_str_buf_new(bsiz);
    rb_enc_copy(result, fmt);
    buf = RSTRING_PTR(result);
    memset(buf, 0, bsiz);
    ENC_CODERANGE_SET(result, coderange);

    for (; p < end; p++) {
	const char *t;
	int n;
	ID id = 0;

	for (t = p; t < end && *t != '%'; t++) ;
	PUSH(p, t - p);
	if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
	    scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &coderange);
	    ENC_CODERANGE_SET(result, coderange);
	}
	if (t >= end) {
	    /* end of fmt string */
	    goto sprint_exit;
	}
	p = t + 1;		/* skip `%' */

	width = prec = -1;
	nextvalue = Qundef;
      retry:
	switch (*p) {
	  default:
	    if (rb_enc_isprint(*p, enc))
		rb_raise(rb_eArgError, "malformed format string - %%%c", *p);
	    else
		rb_raise(rb_eArgError, "malformed format string");
	    break;

	  case ' ':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FSPACE;
	    p++;
	    goto retry;

	  case '#':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FSHARP;
	    p++;
	    goto retry;

	  case '+':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FPLUS;
	    p++;
	    goto retry;

	  case '-':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FMINUS;
	    p++;
	    goto retry;

	  case '0':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FZERO;
	    p++;
	    goto retry;

	  case '1': case '2': case '3': case '4':
	  case '5': case '6': case '7': case '8': case '9':
	    n = 0;
	    GETNUM(n, width);
	    if (*p == '$') {
		if (nextvalue != Qundef) {
		    rb_raise(rb_eArgError, "value given twice - %d$", n);
		}
		nextvalue = GETPOSARG(n);
		p++;
		goto retry;
	    }
	    CHECK_FOR_WIDTH(flags);
	    width = n;
	    flags |= FWIDTH;
	    goto retry;

	  case '<':
	  case '{':
	    {
		const char *start = p;
		char term = (*p == '<') ? '>' : '}';
		int len;

		for (; p < end && *p != term; ) {
		    p += rb_enc_mbclen(p, end, enc);
		}
		if (p >= end) {
		    rb_raise(rb_eArgError, "malformed name - unmatched parenthesis");
		}
#if SIZEOF_INT < SIZEOF_SIZE_T
		if ((size_t)(p - start) >= INT_MAX) {
		    const int message_limit = 20;
		    len = (int)(rb_enc_right_char_head(start, start + message_limit, p, enc) - start);
		    rb_enc_raise(enc, rb_eArgError,
				 "too long name (%"PRIdSIZE" bytes) - %.*s...%c",
				 (size_t)(p - start - 2), len, start, term);
		}
#endif
		len = (int)(p - start + 1); /* including parenthesis */
		if (id) {
		    rb_enc_raise(enc, rb_eArgError, "named%.*s after <%s>",
				 len, start, rb_id2name(id));
		}
		nextvalue = GETNAMEARG((id = rb_check_id_cstr(start + 1,
							      len - 2 /* without parenthesis */,
							      enc),
					ID2SYM(id)),
				       start, len, enc);
		if (nextvalue == Qundef) {
		    rb_enc_raise(enc, rb_eKeyError, "key%.*s not found", len, start);
		}
		if (term == '}') goto format_s;
		p++;
		goto retry;
	    }

	  case '*':
	    CHECK_FOR_WIDTH(flags);
	    flags |= FWIDTH;
	    GETASTER(width);
	    if (width < 0) {
		flags |= FMINUS;
		width = -width;
	    }
	    p++;
	    goto retry;

	  case '.':
	    if (flags & FPREC0) {
		rb_raise(rb_eArgError, "precision given twice");
	    }
	    flags |= FPREC|FPREC0;

	    prec = 0;
	    p++;
	    if (*p == '*') {
		GETASTER(prec);
		if (prec < 0) {	/* ignore negative precision */
		    flags &= ~FPREC;
		}
		p++;
		goto retry;
	    }

	    GETNUM(prec, precision);
	    goto retry;

	  case '\n':
	  case '\0':
	    p--;
	  case '%':
	    if (flags != FNONE) {
		rb_raise(rb_eArgError, "invalid format character - %%");
	    }
	    PUSH("%", 1);
	    break;

	  case 'c':
	    {
		VALUE val = GETARG();
		VALUE tmp;
		unsigned int c;
		int n;

		tmp = rb_check_string_type(val);
		if (!NIL_P(tmp)) {
		    if (rb_enc_strlen(RSTRING_PTR(tmp),RSTRING_END(tmp),enc) != 1) {
			rb_raise(rb_eArgError, "%%c requires a character");
		    }
		    c = rb_enc_codepoint_len(RSTRING_PTR(tmp), RSTRING_END(tmp), &n, enc);
		    RB_GC_GUARD(tmp);
		}
		else {
		    c = NUM2INT(val);
		    n = rb_enc_codelen(c, enc);
		}
		if (n <= 0) {
		    rb_raise(rb_eArgError, "invalid character");
		}
		if (!(flags & FWIDTH)) {
		    CHECK(n);
		    rb_enc_mbcput(c, &buf[blen], enc);
		    blen += n;
		}
		else if ((flags & FMINUS)) {
		    CHECK(n);
		    rb_enc_mbcput(c, &buf[blen], enc);
		    blen += n;
		    FILL(' ', width-1);
		}
		else {
		    FILL(' ', width-1);
		    CHECK(n);
		    rb_enc_mbcput(c, &buf[blen], enc);
		    blen += n;
		}
	    }
	    break;

	  case 's':
	  case 'p':
	  format_s:
	    {
		VALUE arg = GETARG();
		long len, slen;

		if (*p == 'p') arg = rb_inspect(arg);
		str = rb_obj_as_string(arg);
		if (OBJ_TAINTED(str)) tainted = 1;
		len = RSTRING_LEN(str);
		rb_str_set_len(result, blen);
		if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
		    int cr = coderange;
		    scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr);
		    ENC_CODERANGE_SET(result,
				      (cr == ENC_CODERANGE_UNKNOWN ?
				       ENC_CODERANGE_BROKEN : (coderange = cr)));
		}
		enc = rb_enc_check(result, str);
		if (flags&(FPREC|FWIDTH)) {
		    slen = rb_enc_strlen(RSTRING_PTR(str),RSTRING_END(str),enc);
		    if (slen < 0) {
			rb_raise(rb_eArgError, "invalid mbstring sequence");
		    }
		    if ((flags&FPREC) && (prec < slen)) {
			char *p = rb_enc_nth(RSTRING_PTR(str), RSTRING_END(str),
					     prec, enc);
			slen = prec;
			len = p - RSTRING_PTR(str);
		    }
		    /* need to adjust multi-byte string pos */
		    if ((flags&FWIDTH) && (width > slen)) {
			width -= (int)slen;
			if (!(flags&FMINUS)) {
			    CHECK(width);
			    while (width--) {
				buf[blen++] = ' ';
			    }
			}
			CHECK(len);
			memcpy(&buf[blen], RSTRING_PTR(str), len);
			RB_GC_GUARD(str);
			blen += len;
			if (flags&FMINUS) {
			    CHECK(width);
			    while (width--) {
				buf[blen++] = ' ';
			    }
			}
			rb_enc_associate(result, enc);
			break;
		    }
		}
		PUSH(RSTRING_PTR(str), len);
		RB_GC_GUARD(str);
		rb_enc_associate(result, enc);
	    }
	    break;

	  case 'd':
	  case 'i':
	  case 'o':
	  case 'x':
	  case 'X':
	  case 'b':
	  case 'B':
	  case 'u':
	    {
		volatile VALUE val = GETARG();
		char fbuf[32], nbuf[64], *s;
		const char *prefix = 0;
		int sign = 0, dots = 0;
		char sc = 0;
		long v = 0;
		int base, bignum = 0;
		int len;

		switch (*p) {
		  case 'd':
		  case 'i':
		  case 'u':
		    sign = 1; break;
		  case 'o':
		  case 'x':
		  case 'X':
		  case 'b':
		  case 'B':
		    if (flags&(FPLUS|FSPACE)) sign = 1;
		    break;
		}
		if (flags & FSHARP) {
		    switch (*p) {
		      case 'o':
			prefix = "0"; break;
		      case 'x':
			prefix = "0x"; break;
		      case 'X':
			prefix = "0X"; break;
		      case 'b':
			prefix = "0b"; break;
		      case 'B':
			prefix = "0B"; break;
		    }
		}

	      bin_retry:
		switch (TYPE(val)) {
		  case T_FLOAT:
		    if (FIXABLE(RFLOAT_VALUE(val))) {
			val = LONG2FIX((long)RFLOAT_VALUE(val));
			goto bin_retry;
		    }
		    val = rb_dbl2big(RFLOAT_VALUE(val));
		    if (FIXNUM_P(val)) goto bin_retry;
		    bignum = 1;
		    break;
		  case T_STRING:
		    val = rb_str_to_inum(val, 0, TRUE);
		    goto bin_retry;
		  case T_BIGNUM:
		    bignum = 1;
		    break;
		  case T_FIXNUM:
		    v = FIX2LONG(val);
		    break;
		  default:
		    val = rb_Integer(val);
		    goto bin_retry;
		}

		switch (*p) {
		  case 'o':
		    base = 8; break;
		  case 'x':
		  case 'X':
		    base = 16; break;
		  case 'b':
		  case 'B':
		    base = 2; break;
		  case 'u':
		  case 'd':
		  case 'i':
		  default:
		    base = 10; break;
		}

		if (!bignum) {
		    if (base == 2) {
			val = rb_int2big(v);
			goto bin_retry;
		    }
		    if (sign) {
			char c = *p;
			if (c == 'i') c = 'd'; /* %d and %i are identical */
			if (v < 0) {
			    v = -v;
			    sc = '-';
			    width--;
			}
			else if (flags & FPLUS) {
			    sc = '+';
			    width--;
			}
			else if (flags & FSPACE) {
			    sc = ' ';
			    width--;
			}
			snprintf(fbuf, sizeof(fbuf), "%%l%c", c);
			snprintf(nbuf, sizeof(nbuf), fbuf, v);
			s = nbuf;
		    }
		    else {
			s = nbuf;
			if (v < 0) {
			    dots = 1;
			}
			snprintf(fbuf, sizeof(fbuf), "%%l%c", *p == 'X' ? 'x' : *p);
			snprintf(++s, sizeof(nbuf) - 1, fbuf, v);
			if (v < 0) {
			    char d = 0;

			    s = remove_sign_bits(s, base);
			    switch (base) {
			      case 16:
				d = 'f'; break;
			      case 8:
				d = '7'; break;
			    }
			    if (d && *s != d) {
				*--s = d;
			    }
			}
		    }
		    len = (int)strlen(s);
		}
		else {
		    if (sign) {
			tmp = rb_big2str(val, base);
			s = RSTRING_PTR(tmp);
			if (s[0] == '-') {
			    s++;
			    sc = '-';
			    width--;
			}
			else if (flags & FPLUS) {
			    sc = '+';
			    width--;
			}
			else if (flags & FSPACE) {
			    sc = ' ';
			    width--;
			}
		    }
		    else {
			if (!RBIGNUM_SIGN(val)) {
			    val = rb_big_clone(val);
			    rb_big_2comp(val);
			}
			tmp = rb_big2str0(val, base, RBIGNUM_SIGN(val));
			s = RSTRING_PTR(tmp);
			if (*s == '-') {
			    dots = 1;
			    if (base == 10) {
				rb_warning("negative number for %%u specifier");
			    }
			    s = remove_sign_bits(++s, base);
			    switch (base) {
			      case 16:
				if (s[0] != 'f') *--s = 'f'; break;
			      case 8:
				if (s[0] != '7') *--s = '7'; break;
			      case 2:
				if (s[0] != '1') *--s = '1'; break;
			    }
			}
		    }
		    len = rb_long2int(RSTRING_END(tmp) - s);
		}

		if (dots) {
		    prec -= 2;
		    width -= 2;
		}

		if (*p == 'X') {
		    char *pp = s;
		    int c;
		    while ((c = (int)(unsigned char)*pp) != 0) {
			*pp = rb_enc_toupper(c, enc);
			pp++;
		    }
		}
		if (prefix && !prefix[1]) { /* octal */
		    if (dots) {
			prefix = 0;
		    }
		    else if (len == 1 && *s == '0') {
			len = 0;
			if (flags & FPREC) prec--;
		    }
		    else if ((flags & FPREC) && (prec > len)) {
			prefix = 0;
		    }
		}
		else if (len == 1 && *s == '0') {
		    prefix = 0;
		}
		if (prefix) {
		    width -= (int)strlen(prefix);
		}
		if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
		    prec = width;
		    width = 0;
		}
		else {
		    if (prec < len) {
			if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
			prec = len;
		    }
		    width -= prec;
		}
		if (!(flags&FMINUS)) {
		    CHECK(width);
		    while (width-- > 0) {
			buf[blen++] = ' ';
		    }
		}
		if (sc) PUSH(&sc, 1);
		if (prefix) {
		    int plen = (int)strlen(prefix);
		    PUSH(prefix, plen);
		}
		CHECK(prec - len);
		if (dots) PUSH("..", 2);
		if (!bignum && v < 0) {
		    char c = sign_bits(base, p);
		    while (len < prec--) {
			buf[blen++] = c;
		    }
		}
		else if ((flags & (FMINUS|FPREC)) != FMINUS) {
		    char c;

		    if (!sign && bignum && !RBIGNUM_SIGN(val))
			c = sign_bits(base, p);
		    else
			c = '0';
		    while (len < prec--) {
			buf[blen++] = c;
		    }
		}
		PUSH(s, len);
		RB_GC_GUARD(tmp);
		CHECK(width);
		while (width-- > 0) {
		    buf[blen++] = ' ';
		}
	    }
	    break;

	  case 'f':
	  case 'g':
	  case 'G':
	  case 'e':
	  case 'E':
	  case 'a':
	  case 'A':
	    {
		VALUE val = GETARG();
		double fval;
		int i, need = 6;
		char fbuf[32];

		fval = RFLOAT_VALUE(rb_Float(val));
		if (isnan(fval) || isinf(fval)) {
		    const char *expr;

		    if (isnan(fval)) {
			expr = "NaN";
		    }
		    else {
			expr = "Inf";
		    }
		    need = (int)strlen(expr);
		    if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS))
			need++;
		    if ((flags & FWIDTH) && need < width)
			need = width;

		    CHECK(need + 1);
		    snprintf(&buf[blen], need + 1, "%*s", need, "");
		    if (flags & FMINUS) {
			if (!isnan(fval) && fval < 0.0)
			    buf[blen++] = '-';
			else if (flags & FPLUS)
			    buf[blen++] = '+';
			else if (flags & FSPACE)
			    blen++;
			memcpy(&buf[blen], expr, strlen(expr));
		    }
		    else {
			if (!isnan(fval) && fval < 0.0)
			    buf[blen + need - strlen(expr) - 1] = '-';
			else if (flags & FPLUS)
			    buf[blen + need - strlen(expr) - 1] = '+';
			else if ((flags & FSPACE) && need > width)
			    blen++;
			memcpy(&buf[blen + need - strlen(expr)], expr,
			       strlen(expr));
		    }
		    blen += strlen(&buf[blen]);
		    break;
		}

		fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
		need = 0;
		if (*p != 'e' && *p != 'E') {
		    i = INT_MIN;
		    frexp(fval, &i);
		    if (i > 0)
			need = BIT_DIGITS(i);
		}
		need += (flags&FPREC) ? prec : 6;
		if ((flags&FWIDTH) && need < width)
		    need = width;
		need += 20;

		CHECK(need);
		snprintf(&buf[blen], need, fbuf, fval);
		blen += strlen(&buf[blen]);
	    }
	    break;
	}
	flags = FNONE;
    }

  sprint_exit:
    RB_GC_GUARD(fmt);
    /* XXX - We cannot validate the number of arguments if (digit)$ style used.
     */
    if (posarg >= 0 && nextarg < argc) {
	const char *mesg = "too many arguments for format string";
	if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg);
	if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
    }
    rb_str_resize(result, blen);

    if (tainted) OBJ_TAINT(result);
    return result;
}
예제 #5
0
파일: vm_method.c 프로젝트: genki/ruby
void
rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
{
    NODE *body;

    if (NIL_P(klass)) {
	klass = rb_cObject;
    }
    if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
	rb_raise(rb_eSecurityError, "Insecure: can't define method");
    }
    if (!FL_TEST(klass, FL_SINGLETON) &&
	node && nd_type(node) != NODE_ZSUPER &&
	(mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
	noex = NOEX_PRIVATE | noex;
    }
    else if (FL_TEST(klass, FL_SINGLETON) && node
	     && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
	rb_warn
	    ("defining %s.allocate is deprecated; use rb_define_alloc_func()",
	     rb_class2name(rb_iv_get(klass, "__attached__")));
	mid = ID_ALLOCATOR;
    }
    if (OBJ_FROZEN(klass)) {
	rb_error_frozen("class/module");
    }
    rb_clear_cache_by_id(mid);

    /*
     * NODE_METHOD (NEW_METHOD(body, klass, vis)):
     *   nd_body : method body   // (2) // mark
     *   nd_clss : klass         // (1) // mark
     *   nd_noex : visibility    // (3)
     *
     * NODE_FBODY (NEW_FBODY(method, alias)):
     *   nd_body : method (NODE_METHOD)  // (2) // mark
     *   nd_oid  : original id           // (1)
     *   nd_cnt  : alias count           // (3)
     */
    if (node) {
	body = NEW_FBODY(NEW_METHOD(node, klass, NOEX_WITH_SAFE(noex)), 0);
    }
    else {
	body = 0;
    }

    {
	/* check re-definition */
	st_data_t data;
	NODE *old_node;

	if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
	    old_node = (NODE *)data;
	    if (old_node) {
		if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) {
		    rb_vm_check_redefinition_opt_method(old_node);
		}
		if (RTEST(ruby_verbose) && node && old_node->nd_cnt == 0 && old_node->nd_body) {
		    rb_warning("method redefined; discarding old %s", rb_id2name(mid));
		}
	    }
	}
	if (klass == rb_cObject && node && mid == idInitialize) {
	    rb_warn("redefining Object#initialize may cause infinite loop");
	}

	if (mid == object_id || mid == __send__) {
	    if (node && nd_type(node) == RUBY_VM_METHOD_NODE) {
		rb_warn("redefining `%s' may cause serious problem",
			rb_id2name(mid));
	    }
	}
    }

    st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);

    if (node && mid != ID_ALLOCATOR && ruby_running) {
	if (FL_TEST(klass, FL_SINGLETON)) {
	    rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
		       ID2SYM(mid));
	}
	else {
	    rb_funcall(klass, added, 1, ID2SYM(mid));
	}
    }
}
예제 #6
0
static VALUE object_spec_OBJ_TAINTED(VALUE self, VALUE obj) {
  return OBJ_TAINTED(obj) ? Qtrue : Qfalse;
}
예제 #7
0
파일: parser.c 프로젝트: ManageIQ/psych
/*
 * call-seq:
 *    parser.parse(yaml)
 *
 * Parse the YAML document contained in +yaml+.  Events will be called on
 * the handler set on the parser instance.
 *
 * See Psych::Parser and Psych::Parser#handler
 */
static VALUE parse(int argc, VALUE *argv, VALUE self)
{
    VALUE yaml, path;
    yaml_parser_t * parser;
    yaml_event_t event;
    int done = 0;
    int tainted = 0;
#ifdef HAVE_RUBY_ENCODING_H
    int encoding = rb_utf8_encindex();
    rb_encoding * internal_enc = rb_default_internal_encoding();
#endif
    VALUE handler = rb_iv_get(self, "@handler");

    if (rb_scan_args(argc, argv, "11", &yaml, &path) == 1) {
	if(rb_respond_to(yaml, id_path))
	    path = rb_funcall(yaml, id_path, 0);
	else
	    path = rb_str_new2("<unknown>");
    }

    Data_Get_Struct(self, yaml_parser_t, parser);

    if (OBJ_TAINTED(yaml)) tainted = 1;

    if(rb_respond_to(yaml, id_read)) {
	yaml_parser_set_input(parser, io_reader, (void *)yaml);
	if (RTEST(rb_obj_is_kind_of(yaml, rb_cIO))) tainted = 1;
    } else {
	StringValue(yaml);
	yaml_parser_set_input_string(
		parser,
		(const unsigned char *)RSTRING_PTR(yaml),
		(size_t)RSTRING_LEN(yaml)
		);
    }

    while(!done) {
	if(!yaml_parser_parse(parser, &event)) {
	    VALUE exception;

	    exception = make_exception(parser, path);
	    yaml_parser_delete(parser);
	    yaml_parser_initialize(parser);

	    rb_exc_raise(exception);
	}

	switch(event.type) {
	  case YAML_STREAM_START_EVENT:

	    rb_funcall(handler, id_start_stream, 1,
		       INT2NUM((long)event.data.stream_start.encoding)
		);
	    break;
	  case YAML_DOCUMENT_START_EVENT:
	    {
		/* Get a list of tag directives (if any) */
		VALUE tag_directives = rb_ary_new();
		/* Grab the document version */
		VALUE version = event.data.document_start.version_directive ?
		    rb_ary_new3(
			(long)2,
			INT2NUM((long)event.data.document_start.version_directive->major),
			INT2NUM((long)event.data.document_start.version_directive->minor)
			) : rb_ary_new();

		if(event.data.document_start.tag_directives.start) {
		    yaml_tag_directive_t *start =
			event.data.document_start.tag_directives.start;
		    yaml_tag_directive_t *end =
			event.data.document_start.tag_directives.end;
		    for(; start != end; start++) {
			VALUE handle = Qnil;
			VALUE prefix = Qnil;
			if(start->handle) {
			    handle = rb_str_new2((const char *)start->handle);
			    if (tainted) OBJ_TAINT(handle);
#ifdef HAVE_RUBY_ENCODING_H
			    PSYCH_TRANSCODE(handle, encoding, internal_enc);
#endif
			}

			if(start->prefix) {
			    prefix = rb_str_new2((const char *)start->prefix);
			    if (tainted) OBJ_TAINT(prefix);
#ifdef HAVE_RUBY_ENCODING_H
			    PSYCH_TRANSCODE(prefix, encoding, internal_enc);
#endif
			}

			rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix));
		    }
		}
		rb_funcall(handler, id_start_document, 3,
			   version, tag_directives,
			   event.data.document_start.implicit == 1 ? Qtrue : Qfalse
		    );
	    }
	    break;
	  case YAML_DOCUMENT_END_EVENT:
	    rb_funcall(handler, id_end_document, 1,
		       event.data.document_end.implicit == 1 ? Qtrue : Qfalse
		);
	    break;
	  case YAML_ALIAS_EVENT:
	    {
		VALUE alias = Qnil;
		if(event.data.alias.anchor) {
		    alias = rb_str_new2((const char *)event.data.alias.anchor);
		    if (tainted) OBJ_TAINT(alias);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(alias, encoding, internal_enc);
#endif
		}

		rb_funcall(handler, id_alias, 1, alias);
	    }
	    break;
	  case YAML_SCALAR_EVENT:
	    {
		VALUE anchor = Qnil;
		VALUE tag = Qnil;
		VALUE plain_implicit, quoted_implicit, style;
		VALUE val = rb_str_new(
		    (const char *)event.data.scalar.value,
		    (long)event.data.scalar.length
		    );
		if (tainted) OBJ_TAINT(val);

#ifdef HAVE_RUBY_ENCODING_H
		PSYCH_TRANSCODE(val, encoding, internal_enc);
#endif

		if(event.data.scalar.anchor) {
		    anchor = rb_str_new2((const char *)event.data.scalar.anchor);
		    if (tainted) OBJ_TAINT(anchor);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
#endif
		}

		if(event.data.scalar.tag) {
		    tag = rb_str_new2((const char *)event.data.scalar.tag);
		    if (tainted) OBJ_TAINT(tag);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
#endif
		}

		plain_implicit =
		    event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue;

		quoted_implicit =
		    event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue;

		style = INT2NUM((long)event.data.scalar.style);

		rb_funcall(handler, id_scalar, 6,
			   val, anchor, tag, plain_implicit, quoted_implicit, style);
	    }
	    break;
	  case YAML_SEQUENCE_START_EVENT:
	    {
		VALUE anchor = Qnil;
		VALUE tag = Qnil;
		VALUE implicit, style;
		if(event.data.sequence_start.anchor) {
		    anchor = rb_str_new2((const char *)event.data.sequence_start.anchor);
		    if (tainted) OBJ_TAINT(anchor);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
#endif
		}

		tag = Qnil;
		if(event.data.sequence_start.tag) {
		    tag = rb_str_new2((const char *)event.data.sequence_start.tag);
		    if (tainted) OBJ_TAINT(tag);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
#endif
		}

		implicit =
		    event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue;

		style = INT2NUM((long)event.data.sequence_start.style);

		rb_funcall(handler, id_start_sequence, 4,
			   anchor, tag, implicit, style);
	    }
	    break;
	  case YAML_SEQUENCE_END_EVENT:
	    rb_funcall(handler, id_end_sequence, 0);
	    break;
	  case YAML_MAPPING_START_EVENT:
	    {
		VALUE anchor = Qnil;
		VALUE tag = Qnil;
		VALUE implicit, style;
		if(event.data.mapping_start.anchor) {
		    anchor = rb_str_new2((const char *)event.data.mapping_start.anchor);
		    if (tainted) OBJ_TAINT(anchor);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
#endif
		}

		if(event.data.mapping_start.tag) {
		    tag = rb_str_new2((const char *)event.data.mapping_start.tag);
		    if (tainted) OBJ_TAINT(tag);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
#endif
		}

		implicit =
		    event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue;

		style = INT2NUM((long)event.data.mapping_start.style);

		rb_funcall(handler, id_start_mapping, 4,
			   anchor, tag, implicit, style);
	    }
	    break;
	  case YAML_MAPPING_END_EVENT:
	    rb_funcall(handler, id_end_mapping, 0);
	    break;
	  case YAML_NO_EVENT:
	    rb_funcall(handler, id_empty, 0);
	    break;
	  case YAML_STREAM_END_EVENT:
	    rb_funcall(handler, id_end_stream, 0);
	    done = 1;
	    break;
	}
	yaml_event_delete(&event);
    }

    return self;
}
예제 #8
0
파일: Call.c 프로젝트: JackCameo/sample_app
void
rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
        FFIStorage* paramStorage, void** ffiValues,
        VALUE* callbackParameters, int callbackCount, VALUE enums)
{
    VALUE callbackProc = Qnil;
    FFIStorage* param = &paramStorage[0];
    int i, argidx, cbidx, argCount;

    if (unlikely(paramCount != -1 && paramCount != argc)) {
        if (argc == (paramCount - 1) && callbackCount == 1 && rb_block_given_p()) {
            callbackProc = rb_block_proc();
        } else {
            rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, paramCount);
        }
    }

    argCount = paramCount != -1 ? paramCount : argc;

    for (i = 0, argidx = 0, cbidx = 0; i < argCount; ++i) {
        Type* paramType = paramTypes[i];
        int type;

        
        if (unlikely(paramType->nativeType == NATIVE_MAPPED)) {
            VALUE values[] = { argv[argidx], Qnil };
            argv[argidx] = rb_funcall2(((MappedType *) paramType)->rbConverter, id_to_native, 2, values);
            paramType = ((MappedType *) paramType)->type;
        }

        type = argidx < argc ? TYPE(argv[argidx]) : T_NONE;
        ffiValues[i] = param;

        switch (paramType->nativeType) {

            case NATIVE_INT8:
                param->s8 = NUM2INT(argv[argidx]);
                ++argidx;
                ADJ(param, INT8);
                break;


            case NATIVE_INT16:
                param->s16 = NUM2INT(argv[argidx]);
                ++argidx;
                ADJ(param, INT16);
                break;


            case NATIVE_INT32:
                if (unlikely(type == T_SYMBOL && enums != Qnil)) {
                    VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]);
                    param->s32 = NUM2INT(value);

                } else {
                    param->s32 = NUM2INT(argv[argidx]);
                }

                ++argidx;
                ADJ(param, INT32);
                break;


            case NATIVE_BOOL:
                if (type != T_TRUE && type != T_FALSE) {
                    rb_raise(rb_eTypeError, "wrong argument type  (expected a boolean parameter)");
                }
                param->s8 = argv[argidx++] == Qtrue;
                ADJ(param, INT8);
                break;


            case NATIVE_UINT8:
                param->u8 = NUM2UINT(argv[argidx]);
                ADJ(param, INT8);
                ++argidx;
                break;


            case NATIVE_UINT16:
                param->u16 = NUM2UINT(argv[argidx]);
                ADJ(param, INT16);
                ++argidx;
                break;


            case NATIVE_UINT32:
                param->u32 = NUM2UINT(argv[argidx]);
                ADJ(param, INT32);
                ++argidx;
                break;


            case NATIVE_INT64:
                param->i64 = NUM2LL(argv[argidx]);
                ADJ(param, INT64);
                ++argidx;
                break;


            case NATIVE_UINT64:
                param->u64 = NUM2ULL(argv[argidx]);
                ADJ(param, INT64);
                ++argidx;
                break;

            case NATIVE_LONG:
                *(ffi_sarg *) param = NUM2LONG(argv[argidx]);
                ADJ(param, LONG);
                ++argidx;
                break;

            case NATIVE_ULONG:
                *(ffi_arg *) param = NUM2ULONG(argv[argidx]);
                ADJ(param, LONG);
                ++argidx;
                break;

            case NATIVE_FLOAT32:
                param->f32 = (float) NUM2DBL(argv[argidx]);
                ADJ(param, FLOAT32);
                ++argidx;
                break;

            case NATIVE_FLOAT64:
                param->f64 = NUM2DBL(argv[argidx]);
                ADJ(param, FLOAT64);
                ++argidx;
                break;

            case NATIVE_LONGDOUBLE:
                param->ld = rbffi_num2longdouble(argv[argidx]);
                ADJ(param, LONGDOUBLE);
                ++argidx;
                break;


            case NATIVE_STRING:
                if (type == T_NIL) {
                    param->ptr = NULL; 
                
                } else {
                    if (rb_safe_level() >= 1 && OBJ_TAINTED(argv[argidx])) {
                        rb_raise(rb_eSecurityError, "Unsafe string parameter");
                    }

                    param->ptr = StringValueCStr(argv[argidx]);
                }

                ADJ(param, ADDRESS);
                ++argidx;
                break;

            case NATIVE_POINTER:
            case NATIVE_BUFFER_IN:
            case NATIVE_BUFFER_OUT:
            case NATIVE_BUFFER_INOUT:
                param->ptr = getPointer(argv[argidx++], type);
                ADJ(param, ADDRESS);
                break;


            case NATIVE_FUNCTION:
            case NATIVE_CALLBACK:
                if (callbackProc != Qnil) {
                    param->ptr = callback_param(callbackProc, callbackParameters[cbidx++]);
                } else {
                    param->ptr = callback_param(argv[argidx], callbackParameters[cbidx++]);
                    ++argidx;
                }
                ADJ(param, ADDRESS);
                break;

            case NATIVE_STRUCT:
                ffiValues[i] = getPointer(argv[argidx++], type);
                break;

            default:
                rb_raise(rb_eArgError, "Invalid parameter type: %d", paramType->nativeType);
        }
    }
}
예제 #9
0
/*
 * call-seq:
 *   Module.load(String) => Module
 *
 * Load a module from a string.
 */
static VALUE module_load(VALUE klass, VALUE str)
{
  VALUE arr, class_name, metaclass_str, metaclass, superclass_name,
        included_modules, class_variables_str, class_variables,
        instance_methods_str, instance_methods, flags, module;

  if(   rb_safe_level() >= 4
     || (rb_safe_level() >= 1 && OBJ_TAINTED(str)))
  {
    /* no playing with knives in the sandbox */
    rb_raise(rb_eSecurityError, "Insecure: can't load module");
  }

  arr = marshal_load(str);
  class_name = rb_ary_pop(arr);
  metaclass_str = rb_ary_pop(arr);
  superclass_name = rb_ary_pop(arr);
  included_modules = rb_ary_pop(arr);
  class_variables_str = rb_ary_pop(arr);
  instance_methods_str = rb_ary_pop(arr);
  flags = rb_ary_pop(arr);

  if(RTEST(superclass_name))
  {
    VALUE superclass;
    rb_check_type(superclass_name, T_STRING);
    superclass = rb_funcall(
        lookup_module_proc,
        rb_intern("call"),
        1,
        superclass_name);
#if RUBY_VERSION_CODE >= 180
    /* Can't make subclass of Class on 1.8.x */
    module = rb_class_boot(superclass);
    rb_define_alloc_func(module, module_instance_allocate);
#else
    module = rb_class_new(superclass);
#endif
  }
  else
  {
    module = rb_module_new();
  }

  if(!NIL_P(class_name))
  {
    VALUE outer_module = rb_funcall(outer_module_proc, rb_intern("call"), 1, class_name);
    VALUE module_name = rb_funcall(module_name_proc, rb_intern("call"), 1, class_name);
    rb_const_set(outer_module, SYM2ID(module_name), module);
  }

  RBASIC(module)->flags = NUM2INT(flags);
  include_modules(module, included_modules);
  class_variables = marshal_load(class_variables_str);
  add_class_variables(module, class_variables);
  instance_methods = marshal_load(instance_methods_str);
  add_methods(module, instance_methods);

  metaclass = marshal_load(metaclass_str);
  if(RTEST(metaclass))
  {
    rb_singleton_class_attached(metaclass, module);
    RBASIC(module)->klass = metaclass;
  }

  return module;
}
예제 #10
0
/*
 * call-seq:
 *    parser.parse(yaml)
 *
 * Parse the YAML document contained in +yaml+.  Events will be called on
 * the handler set on the parser instance.
 *
 * See Psych::Parser and Psych::Parser#handler
 */
static VALUE parse(int argc, VALUE *argv, VALUE self)
{
    VALUE yaml, path;
    yaml_parser_t * parser;
    yaml_event_t event;
    int done = 0;
    int tainted = 0;
    int state = 0;
    int parser_encoding = YAML_ANY_ENCODING;
    int encoding = rb_utf8_encindex();
    rb_encoding * internal_enc = rb_default_internal_encoding();
    VALUE handler = rb_iv_get(self, "@handler");

    if (rb_scan_args(argc, argv, "11", &yaml, &path) == 1) {
	if(rb_respond_to(yaml, id_path))
	    path = rb_funcall(yaml, id_path, 0);
	else
	    path = rb_str_new2("<unknown>");
    }

    TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser);

    yaml_parser_delete(parser);
    yaml_parser_initialize(parser);

    if (OBJ_TAINTED(yaml)) tainted = 1;

    if (rb_respond_to(yaml, id_read)) {
	yaml = transcode_io(yaml, &parser_encoding);
	yaml_parser_set_encoding(parser, parser_encoding);
	yaml_parser_set_input(parser, io_reader, (void *)yaml);
	if (RTEST(rb_obj_is_kind_of(yaml, rb_cIO))) tainted = 1;
    } else {
	StringValue(yaml);
	yaml = transcode_string(yaml, &parser_encoding);
	yaml_parser_set_encoding(parser, parser_encoding);
	yaml_parser_set_input_string(
		parser,
		(const unsigned char *)RSTRING_PTR(yaml),
		(size_t)RSTRING_LEN(yaml)
		);
    }

    while(!done) {
	VALUE event_args[5];
	VALUE start_line, start_column, end_line, end_column;

	if(!yaml_parser_parse(parser, &event)) {
	    VALUE exception;

	    exception = make_exception(parser, path);
	    yaml_parser_delete(parser);
	    yaml_parser_initialize(parser);

	    rb_exc_raise(exception);
	}

	start_line = INT2NUM((long)event.start_mark.line);
	start_column = INT2NUM((long)event.start_mark.column);
	end_line = INT2NUM((long)event.end_mark.line);
	end_column = INT2NUM((long)event.end_mark.column);

	event_args[0] = handler;
	event_args[1] = start_line;
	event_args[2] = start_column;
	event_args[3] = end_line;
	event_args[4] = end_column;
	rb_protect(protected_event_location, (VALUE)event_args, &state);

	switch(event.type) {
	    case YAML_STREAM_START_EVENT:
	      {
		  VALUE args[2];

		  args[0] = handler;
		  args[1] = INT2NUM((long)event.data.stream_start.encoding);
		  rb_protect(protected_start_stream, (VALUE)args, &state);
	      }
	      break;
	  case YAML_DOCUMENT_START_EVENT:
	    {
		VALUE args[4];
		/* Get a list of tag directives (if any) */
		VALUE tag_directives = rb_ary_new();
		/* Grab the document version */
		VALUE version = event.data.document_start.version_directive ?
		    rb_ary_new3(
			(long)2,
			INT2NUM((long)event.data.document_start.version_directive->major),
			INT2NUM((long)event.data.document_start.version_directive->minor)
			) : rb_ary_new();

		if(event.data.document_start.tag_directives.start) {
		    yaml_tag_directive_t *start =
			event.data.document_start.tag_directives.start;
		    yaml_tag_directive_t *end =
			event.data.document_start.tag_directives.end;
		    for(; start != end; start++) {
			VALUE handle = Qnil;
			VALUE prefix = Qnil;
			if(start->handle) {
			    handle = rb_str_new2((const char *)start->handle);
			    if (tainted) OBJ_TAINT(handle);
			    PSYCH_TRANSCODE(handle, encoding, internal_enc);
			}

			if(start->prefix) {
			    prefix = rb_str_new2((const char *)start->prefix);
			    if (tainted) OBJ_TAINT(prefix);
			    PSYCH_TRANSCODE(prefix, encoding, internal_enc);
			}

			rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix));
		    }
		}
		args[0] = handler;
		args[1] = version;
		args[2] = tag_directives;
		args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse;
		rb_protect(protected_start_document, (VALUE)args, &state);
	    }
	    break;
	  case YAML_DOCUMENT_END_EVENT:
	    {
		VALUE args[2];

		args[0] = handler;
		args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse;
		rb_protect(protected_end_document, (VALUE)args, &state);
	    }
	    break;
	  case YAML_ALIAS_EVENT:
	    {
		VALUE args[2];
		VALUE alias = Qnil;
		if(event.data.alias.anchor) {
		    alias = rb_str_new2((const char *)event.data.alias.anchor);
		    if (tainted) OBJ_TAINT(alias);
		    PSYCH_TRANSCODE(alias, encoding, internal_enc);
		}

		args[0] = handler;
		args[1] = alias;
		rb_protect(protected_alias, (VALUE)args, &state);
	    }
	    break;
	  case YAML_SCALAR_EVENT:
	    {
		VALUE args[7];
		VALUE anchor = Qnil;
		VALUE tag = Qnil;
		VALUE plain_implicit, quoted_implicit, style;
		VALUE val = rb_str_new(
		    (const char *)event.data.scalar.value,
		    (long)event.data.scalar.length
		    );
		if (tainted) OBJ_TAINT(val);

		PSYCH_TRANSCODE(val, encoding, internal_enc);

		if(event.data.scalar.anchor) {
		    anchor = rb_str_new2((const char *)event.data.scalar.anchor);
		    if (tainted) OBJ_TAINT(anchor);
		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
		}

		if(event.data.scalar.tag) {
		    tag = rb_str_new2((const char *)event.data.scalar.tag);
		    if (tainted) OBJ_TAINT(tag);
		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
		}

		plain_implicit =
		    event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue;

		quoted_implicit =
		    event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue;

		style = INT2NUM((long)event.data.scalar.style);

		args[0] = handler;
		args[1] = val;
		args[2] = anchor;
		args[3] = tag;
		args[4] = plain_implicit;
		args[5] = quoted_implicit;
		args[6] = style;
		rb_protect(protected_scalar, (VALUE)args, &state);
	    }
	    break;
	  case YAML_SEQUENCE_START_EVENT:
	    {
		VALUE args[5];
		VALUE anchor = Qnil;
		VALUE tag = Qnil;
		VALUE implicit, style;
		if(event.data.sequence_start.anchor) {
		    anchor = rb_str_new2((const char *)event.data.sequence_start.anchor);
		    if (tainted) OBJ_TAINT(anchor);
		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
		}

		tag = Qnil;
		if(event.data.sequence_start.tag) {
		    tag = rb_str_new2((const char *)event.data.sequence_start.tag);
		    if (tainted) OBJ_TAINT(tag);
		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
		}

		implicit =
		    event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue;

		style = INT2NUM((long)event.data.sequence_start.style);

		args[0] = handler;
		args[1] = anchor;
		args[2] = tag;
		args[3] = implicit;
		args[4] = style;

		rb_protect(protected_start_sequence, (VALUE)args, &state);
	    }
	    break;
	  case YAML_SEQUENCE_END_EVENT:
	    rb_protect(protected_end_sequence, handler, &state);
	    break;
	  case YAML_MAPPING_START_EVENT:
	    {
		VALUE args[5];
		VALUE anchor = Qnil;
		VALUE tag = Qnil;
		VALUE implicit, style;
		if(event.data.mapping_start.anchor) {
		    anchor = rb_str_new2((const char *)event.data.mapping_start.anchor);
		    if (tainted) OBJ_TAINT(anchor);
		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
		}

		if(event.data.mapping_start.tag) {
		    tag = rb_str_new2((const char *)event.data.mapping_start.tag);
		    if (tainted) OBJ_TAINT(tag);
		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
		}

		implicit =
		    event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue;

		style = INT2NUM((long)event.data.mapping_start.style);

		args[0] = handler;
		args[1] = anchor;
		args[2] = tag;
		args[3] = implicit;
		args[4] = style;

		rb_protect(protected_start_mapping, (VALUE)args, &state);
	    }
	    break;
	  case YAML_MAPPING_END_EVENT:
	    rb_protect(protected_end_mapping, handler, &state);
	    break;
	  case YAML_NO_EVENT:
	    rb_protect(protected_empty, handler, &state);
	    break;
	  case YAML_STREAM_END_EVENT:
	    rb_protect(protected_end_stream, handler, &state);
	    done = 1;
	    break;
	}
	yaml_event_delete(&event);
	if (state) rb_jump_tag(state);
    }

    return self;
}
예제 #11
0
파일: safe.c 프로젝트: GunioRobot/ruby
void
rb_secure_update(VALUE obj)
{
    if (!OBJ_TAINTED(obj))
	rb_secure(4);
}
예제 #12
0
파일: function.c 프로젝트: DashYang/sim
static VALUE
function_call(int argc, VALUE argv[], VALUE self)
{
    struct nogvl_ffi_call_args args = { 0 };
    fiddle_generic *generic_args;
    VALUE cfunc, types, cPointer;
    int i;
    VALUE alloc_buffer = 0;

    cfunc    = rb_iv_get(self, "@ptr");
    types    = rb_iv_get(self, "@args");
    cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));

    Check_Max_Args("number of arguments", argc);
    if (argc != (i = RARRAY_LENINT(types))) {
	rb_error_arity(argc, i, i);
    }

    TypedData_Get_Struct(self, ffi_cif, &function_data_type, args.cif);

    if (rb_safe_level() >= 1) {
	for (i = 0; i < argc; i++) {
	    VALUE src = argv[i];
	    if (OBJ_TAINTED(src)) {
		rb_raise(rb_eSecurityError, "tainted parameter not allowed");
	    }
	}
    }

    generic_args = ALLOCV(alloc_buffer,
	(size_t)(argc + 1) * sizeof(void *) + (size_t)argc * sizeof(fiddle_generic));
    args.values = (void **)((char *)generic_args +
			    (size_t)argc * sizeof(fiddle_generic));

    for (i = 0; i < argc; i++) {
	VALUE type = RARRAY_AREF(types, i);
	VALUE src = argv[i];
	int argtype = FIX2INT(type);

	if (argtype == TYPE_VOIDP) {
	    if(NIL_P(src)) {
		src = INT2FIX(0);
	    } else if(cPointer != CLASS_OF(src)) {
		src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
	    }
	    src = rb_Integer(src);
	}

	VALUE2GENERIC(argtype, src, &generic_args[i]);
	args.values[i] = (void *)&generic_args[i];
    }
    args.values[argc] = NULL;
    args.fn = NUM2PTR(cfunc);

    (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);

    rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
#if defined(_WIN32)
    rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
#endif

    ALLOCV_END(alloc_buffer);

    return GENERIC2VALUE(rb_iv_get(self, "@return_type"), args.retval);
}
예제 #13
0
파일: sprintf.c 프로젝트: nhinze/rhodes
VALUE
rb_str_format(int argc, const VALUE *argv, VALUE fmt)
{
    enum {default_float_precision = 6};
    rb_encoding *enc;
    const char *p, *end;
    char *buf;
    long blen, bsiz;
    VALUE result;

    long scanned = 0;
    int coderange = ENC_CODERANGE_7BIT;
    int width, prec, flags = FNONE;
    int nextarg = 1;
    int posarg = 0;
    int tainted = 0;
    VALUE nextvalue;
    VALUE tmp;
    VALUE str;
    volatile VALUE hash = Qundef;

#define CHECK_FOR_WIDTH(f)				 \
    if ((f) & FWIDTH) {					 \
	rb_raise(rb_eArgError, "width given twice");	 \
    }							 \
    if ((f) & FPREC0) {					 \
	rb_raise(rb_eArgError, "width after precision"); \
    }
#define CHECK_FOR_FLAGS(f)				 \
    if ((f) & FWIDTH) {					 \
	rb_raise(rb_eArgError, "flag after width");	 \
    }							 \
    if ((f) & FPREC0) {					 \
	rb_raise(rb_eArgError, "flag after precision"); \
    }

    ++argc;
    --argv;
    if (OBJ_TAINTED(fmt)) tainted = 1;
    StringValue(fmt);
    enc = rb_enc_get(fmt);
    fmt = rb_str_new4(fmt);
    p = RSTRING_PTR(fmt);
    end = p + RSTRING_LEN(fmt);
    blen = 0;
    bsiz = 120;
    result = rb_str_buf_new(bsiz);
    rb_enc_copy(result, fmt);
    buf = RSTRING_PTR(result);
    memset(buf, 0, bsiz);
    ENC_CODERANGE_SET(result, coderange);

    for (; p < end; p++) {
	const char *t;
	int n;
	VALUE sym = Qnil;

	for (t = p; t < end && *t != '%'; t++) ;
	PUSH(p, t - p);
	if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
	    scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &coderange);
	    ENC_CODERANGE_SET(result, coderange);
	}
	if (t >= end) {
	    /* end of fmt string */
	    goto sprint_exit;
	}
	p = t + 1;		/* skip `%' */

	width = prec = -1;
	nextvalue = Qundef;
      retry:
	switch (*p) {
	  default:
	    if (rb_enc_isprint(*p, enc))
		rb_raise(rb_eArgError, "malformed format string - %%%c", *p);
	    else
		rb_raise(rb_eArgError, "malformed format string");
	    break;

	  case ' ':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FSPACE;
	    p++;
	    goto retry;

	  case '#':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FSHARP;
	    p++;
	    goto retry;

	  case '+':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FPLUS;
	    p++;
	    goto retry;

	  case '-':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FMINUS;
	    p++;
	    goto retry;

	  case '0':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FZERO;
	    p++;
	    goto retry;

	  case '1': case '2': case '3': case '4':
	  case '5': case '6': case '7': case '8': case '9':
	    n = 0;
	    GETNUM(n, width);
	    if (*p == '$') {
		if (nextvalue != Qundef) {
		    rb_raise(rb_eArgError, "value given twice - %d$", n);
		}
		nextvalue = GETPOSARG(n);
		p++;
		goto retry;
	    }
	    CHECK_FOR_WIDTH(flags);
	    width = n;
	    flags |= FWIDTH;
	    goto retry;

	  case '<':
	  case '{':
	    {
		const char *start = p;
		char term = (*p == '<') ? '>' : '}';
		int len;

		for (; p < end && *p != term; ) {
		    p += rb_enc_mbclen(p, end, enc);
		}
		if (p >= end) {
		    rb_raise(rb_eArgError, "malformed name - unmatched parenthesis");
		}
#if SIZEOF_INT < SIZEOF_SIZE_T
		if ((size_t)(p - start) >= INT_MAX) {
		    const int message_limit = 20;
		    len = (int)(rb_enc_right_char_head(start, start + message_limit, p, enc) - start);
		    rb_enc_raise(enc, rb_eArgError,
				 "too long name (%"PRIdSIZE" bytes) - %.*s...%c",
				 (size_t)(p - start - 2), len, start, term);
		}
#endif
		len = (int)(p - start + 1); /* including parenthesis */
		if (sym != Qnil) {
		    rb_enc_raise(enc, rb_eArgError, "named%.*s after <%"PRIsVALUE">",
				 len, start, rb_sym2str(sym));
		}
		CHECKNAMEARG(start, len, enc);
		get_hash(&hash, argc, argv);
		sym = rb_check_symbol_cstr(start + 1,
					   len - 2 /* without parenthesis */,
					   enc);
		if (!NIL_P(sym)) nextvalue = rb_hash_lookup2(hash, sym, Qundef);
		if (nextvalue == Qundef) {
		    if (NIL_P(sym)) {
			sym = rb_sym_intern(start + 1,
					    len - 2 /* without parenthesis */,
					    enc);
		    }
		    nextvalue = rb_hash_default_value(hash, sym);
		    if (NIL_P(nextvalue)) {
			rb_enc_raise(enc, rb_eKeyError, "key%.*s not found", len, start);
		    }
		}
		if (term == '}') goto format_s;
		p++;
		goto retry;
	    }

	  case '*':
	    CHECK_FOR_WIDTH(flags);
	    flags |= FWIDTH;
	    GETASTER(width);
	    if (width < 0) {
		flags |= FMINUS;
		width = -width;
	    }
	    p++;
	    goto retry;

	  case '.':
	    if (flags & FPREC0) {
		rb_raise(rb_eArgError, "precision given twice");
	    }
	    flags |= FPREC|FPREC0;

	    prec = 0;
	    p++;
	    if (*p == '*') {
		GETASTER(prec);
		if (prec < 0) {	/* ignore negative precision */
		    flags &= ~FPREC;
		}
		p++;
		goto retry;
	    }

	    GETNUM(prec, precision);
	    goto retry;

	  case '\n':
	  case '\0':
	    p--;
	  case '%':
	    if (flags != FNONE) {
		rb_raise(rb_eArgError, "invalid format character - %%");
	    }
	    PUSH("%", 1);
	    break;

	  case 'c':
	    {
		VALUE val = GETARG();
		VALUE tmp;
		unsigned int c;
		int n;

		tmp = rb_check_string_type(val);
		if (!NIL_P(tmp)) {
		    if (rb_enc_strlen(RSTRING_PTR(tmp),RSTRING_END(tmp),enc) != 1) {
			rb_raise(rb_eArgError, "%%c requires a character");
		    }
		    c = rb_enc_codepoint_len(RSTRING_PTR(tmp), RSTRING_END(tmp), &n, enc);
		    RB_GC_GUARD(tmp);
		}
		else {
		    c = NUM2INT(val);
		    n = rb_enc_codelen(c, enc);
		}
		if (n <= 0) {
		    rb_raise(rb_eArgError, "invalid character");
		}
		if (!(flags & FWIDTH)) {
		    CHECK(n);
		    rb_enc_mbcput(c, &buf[blen], enc);
		    blen += n;
		}
		else if ((flags & FMINUS)) {
		    CHECK(n);
		    rb_enc_mbcput(c, &buf[blen], enc);
		    blen += n;
		    if (width > 1) FILL(' ', width-1);
		}
		else {
		    if (width > 1) FILL(' ', width-1);
		    CHECK(n);
		    rb_enc_mbcput(c, &buf[blen], enc);
		    blen += n;
		}
	    }
	    break;

	  case 's':
	  case 'p':
	  format_s:
	    {
		VALUE arg = GETARG();
		long len, slen;

		if (*p == 'p') {
		    str = rb_inspect(arg);
		}
		else {
		    str = rb_obj_as_string(arg);
		}
		if (OBJ_TAINTED(str)) tainted = 1;
		len = RSTRING_LEN(str);
		rb_str_set_len(result, blen);
		if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
		    int cr = coderange;
		    scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr);
		    ENC_CODERANGE_SET(result,
				      (cr == ENC_CODERANGE_UNKNOWN ?
				       ENC_CODERANGE_BROKEN : (coderange = cr)));
		}
		enc = rb_enc_check(result, str);
		if (flags&(FPREC|FWIDTH)) {
		    slen = rb_enc_strlen(RSTRING_PTR(str),RSTRING_END(str),enc);
		    if (slen < 0) {
			rb_raise(rb_eArgError, "invalid mbstring sequence");
		    }
		    if ((flags&FPREC) && (prec < slen)) {
			char *p = rb_enc_nth(RSTRING_PTR(str), RSTRING_END(str),
					     prec, enc);
			slen = prec;
			len = p - RSTRING_PTR(str);
		    }
		    /* need to adjust multi-byte string pos */
		    if ((flags&FWIDTH) && (width > slen)) {
			width -= (int)slen;
			if (!(flags&FMINUS)) {
			    CHECK(width);
			    while (width--) {
				buf[blen++] = ' ';
			    }
			}
			CHECK(len);
			memcpy(&buf[blen], RSTRING_PTR(str), len);
			RB_GC_GUARD(str);
			blen += len;
			if (flags&FMINUS) {
			    CHECK(width);
			    while (width--) {
				buf[blen++] = ' ';
			    }
			}
			rb_enc_associate(result, enc);
			break;
		    }
		}
		PUSH(RSTRING_PTR(str), len);
		RB_GC_GUARD(str);
		rb_enc_associate(result, enc);
	    }
	    break;

	  case 'd':
	  case 'i':
	  case 'o':
	  case 'x':
	  case 'X':
	  case 'b':
	  case 'B':
	  case 'u':
	    {
		volatile VALUE val = GETARG();
                int valsign;
		char nbuf[64], *s;
		const char *prefix = 0;
		int sign = 0, dots = 0;
		char sc = 0;
		long v = 0;
		int base, bignum = 0;
		int len;

		switch (*p) {
		  case 'd':
		  case 'i':
		  case 'u':
		    sign = 1; break;
		  case 'o':
		  case 'x':
		  case 'X':
		  case 'b':
		  case 'B':
		    if (flags&(FPLUS|FSPACE)) sign = 1;
		    break;
		}
		if (flags & FSHARP) {
		    switch (*p) {
		      case 'o':
			prefix = "0"; break;
		      case 'x':
			prefix = "0x"; break;
		      case 'X':
			prefix = "0X"; break;
		      case 'b':
			prefix = "0b"; break;
		      case 'B':
			prefix = "0B"; break;
		    }
		}

	      bin_retry:
		switch (TYPE(val)) {
		  case T_FLOAT:
		    if (FIXABLE(RFLOAT_VALUE(val))) {
			val = LONG2FIX((long)RFLOAT_VALUE(val));
			goto bin_retry;
		    }
		    val = rb_dbl2big(RFLOAT_VALUE(val));
		    if (FIXNUM_P(val)) goto bin_retry;
		    bignum = 1;
		    break;
		  case T_STRING:
		    val = rb_str_to_inum(val, 0, TRUE);
		    goto bin_retry;
		  case T_BIGNUM:
		    bignum = 1;
		    break;
		  case T_FIXNUM:
		    v = FIX2LONG(val);
		    break;
		  default:
		    val = rb_Integer(val);
		    goto bin_retry;
		}

		switch (*p) {
		  case 'o':
		    base = 8; break;
		  case 'x':
		  case 'X':
		    base = 16; break;
		  case 'b':
		  case 'B':
		    base = 2; break;
		  case 'u':
		  case 'd':
		  case 'i':
		  default:
		    base = 10; break;
		}

                if (base != 10) {
                    int numbits = ffs(base)-1;
                    size_t abs_nlz_bits;
                    size_t numdigits = rb_absint_numwords(val, numbits, &abs_nlz_bits);
                    long i;
                    if (INT_MAX-1 < numdigits) /* INT_MAX is used because rb_long2int is used later. */
                        rb_raise(rb_eArgError, "size too big");
                    if (sign) {
                        if (numdigits == 0)
                            numdigits = 1;
                        tmp = rb_str_new(NULL, numdigits);
                        valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp),
                                1, CHAR_BIT-numbits, INTEGER_PACK_BIG_ENDIAN);
                        for (i = 0; i < RSTRING_LEN(tmp); i++)
                            RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]];
                        s = RSTRING_PTR(tmp);
                        if (valsign < 0) {
                            sc = '-';
                            width--;
                        }
                        else if (flags & FPLUS) {
                            sc = '+';
                            width--;
                        }
                        else if (flags & FSPACE) {
                            sc = ' ';
                            width--;
                        }
                    }
                    else {
                        /* Following conditional "numdigits++" guarantees the
                         * most significant digit as
                         * - '1'(bin), '7'(oct) or 'f'(hex) for negative numbers
                         * - '0' for zero
                         * - not '0' for positive numbers.
                         *
                         * It also guarantees the most significant two
                         * digits will not be '11'(bin), '77'(oct), 'ff'(hex)
                         * or '00'.  */
                        if (numdigits == 0 ||
                                ((abs_nlz_bits != (size_t)(numbits-1) ||
                                  !rb_absint_singlebit_p(val)) &&
                                 (!bignum ? v < 0 : BIGNUM_NEGATIVE_P(val))))
                            numdigits++;
                        tmp = rb_str_new(NULL, numdigits);
                        valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp),
                                1, CHAR_BIT-numbits, INTEGER_PACK_2COMP | INTEGER_PACK_BIG_ENDIAN);
                        for (i = 0; i < RSTRING_LEN(tmp); i++)
                            RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]];
                        s = RSTRING_PTR(tmp);
                        dots = valsign < 0;
                    }
                    len = rb_long2int(RSTRING_END(tmp) - s);
                }
                else if (!bignum) {
                    valsign = 1;
                    if (v < 0) {
                        v = -v;
                        sc = '-';
                        width--;
                        valsign = -1;
                    }
                    else if (flags & FPLUS) {
                        sc = '+';
                        width--;
                    }
                    else if (flags & FSPACE) {
                        sc = ' ';
                        width--;
                    }
                    snprintf(nbuf, sizeof(nbuf), "%ld", v);
                    s = nbuf;
		    len = (int)strlen(s);
		}
		else {
                    tmp = rb_big2str(val, 10);
                    s = RSTRING_PTR(tmp);
                    valsign = 1;
                    if (s[0] == '-') {
                        s++;
                        sc = '-';
                        width--;
                        valsign = -1;
                    }
                    else if (flags & FPLUS) {
                        sc = '+';
                        width--;
                    }
                    else if (flags & FSPACE) {
                        sc = ' ';
                        width--;
                    }
		    len = rb_long2int(RSTRING_END(tmp) - s);
		}

		if (dots) {
		    prec -= 2;
		    width -= 2;
		}

		if (*p == 'X') {
		    char *pp = s;
		    int c;
		    while ((c = (int)(unsigned char)*pp) != 0) {
			*pp = rb_enc_toupper(c, enc);
			pp++;
		    }
		}
		if (prefix && !prefix[1]) { /* octal */
		    if (dots) {
			prefix = 0;
		    }
		    else if (len == 1 && *s == '0') {
			len = 0;
			if (flags & FPREC) prec--;
		    }
		    else if ((flags & FPREC) && (prec > len)) {
			prefix = 0;
		    }
		}
		else if (len == 1 && *s == '0') {
		    prefix = 0;
		}
		if (prefix) {
		    width -= (int)strlen(prefix);
		}
		if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
		    prec = width;
		    width = 0;
		}
		else {
		    if (prec < len) {
			if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
			prec = len;
		    }
		    width -= prec;
		}
		if (!(flags&FMINUS)) {
		    CHECK(width);
		    while (width-- > 0) {
			buf[blen++] = ' ';
		    }
		}
		if (sc) PUSH(&sc, 1);
		if (prefix) {
		    int plen = (int)strlen(prefix);
		    PUSH(prefix, plen);
		}
		CHECK(prec - len);
		if (dots) PUSH("..", 2);
		if (!sign && valsign < 0) {
		    char c = sign_bits(base, p);
		    while (len < prec--) {
			buf[blen++] = c;
		    }
		}
		else if ((flags & (FMINUS|FPREC)) != FMINUS) {
		    while (len < prec--) {
			buf[blen++] = '0';
		    }
		}
		PUSH(s, len);
		RB_GC_GUARD(tmp);
		CHECK(width);
		while (width-- > 0) {
		    buf[blen++] = ' ';
		}
	    }
	    break;

	  case 'f':
	    {
		VALUE val = GETARG(), num, den;
		int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
		long len, done = 0;
		int prefix = 0;
		if (FIXNUM_P(val) || RB_TYPE_P(val, T_BIGNUM)) {
		    den = INT2FIX(1);
		    num = val;
		}
		else if (RB_TYPE_P(val, T_RATIONAL)) {
		    den = rb_rational_den(val);
		    num = rb_rational_num(val);
		}
		else {
		    nextvalue = val;
		    goto float_value;
		}
		if (!(flags&FPREC)) prec = default_float_precision;
		if (FIXNUM_P(num)) {
		    if ((SIGNED_VALUE)num < 0) {
			long n = -FIX2LONG(num);
			num = LONG2FIX(n);
			sign = -1;
		    }
		}
		else if (rb_num_negative_p(num)) {
		    sign = -1;
		    num = rb_funcallv(num, idUMinus, 0, 0);
		}
		if (den != INT2FIX(1) || prec > 1) {
		    const ID idDiv = rb_intern("div");
		    VALUE p10 = rb_int_positive_pow(10, prec);
		    VALUE den_2 = rb_funcall(den, idDiv, 1, INT2FIX(2));
		    num = rb_funcallv(num, '*', 1, &p10);
		    num = rb_funcallv(num, '+', 1, &den_2);
		    num = rb_funcallv(num, idDiv, 1, &den);
		}
		else if (prec >= 0) {
		    zero = prec;
		}
		val = rb_obj_as_string(num);
		len = RSTRING_LEN(val) + zero;
		if (prec >= len) len = prec + 1; /* integer part 0 */
		if (sign || (flags&FSPACE)) ++len;
		if (prec > 0) ++len; /* period */
		CHECK(len > width ? len : width);
		if (sign || (flags&FSPACE)) {
		    buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
		    prefix++;
		    done++;
		}
		len = RSTRING_LEN(val) + zero;
		t = RSTRING_PTR(val);
		if (len > prec) {
		    memcpy(&buf[blen], t, len - prec);
		    blen += len - prec;
		    done += len - prec;
		}
		else {
		    buf[blen++] = '0';
		    done++;
		}
		if (prec > 0) {
		    buf[blen++] = '.';
		    done++;
		}
		if (zero) {
		    FILL('0', zero);
		    done += zero;
		}
		else if (prec > len) {
		    FILL('0', prec - len);
		    memcpy(&buf[blen], t, len);
		    blen += len;
		    done += prec;
		}
		else if (prec > 0) {
		    memcpy(&buf[blen], t + len - prec, prec);
		    blen += prec;
		    done += prec;
		}
		if ((flags & FWIDTH) && width > done) {
		    int fill = ' ';
		    long shifting = 0;
		    if (!(flags&FMINUS)) {
			shifting = done;
			if (flags&FZERO) {
			    shifting -= prefix;
			    fill = '0';
			}
			blen -= shifting;
			memmove(&buf[blen + width - done], &buf[blen], shifting);
		    }
		    FILL(fill, width - done);
		    blen += shifting;
		}
		RB_GC_GUARD(val);
		break;
	    }
	  case 'g':
	  case 'G':
	  case 'e':
	  case 'E':
	    /* TODO: rational support */
	  case 'a':
	  case 'A':
	  float_value:
	    {
		VALUE val = GETARG();
		double fval;
		int i, need;
		char fbuf[32];

		fval = RFLOAT_VALUE(rb_Float(val));
		if (isnan(fval) || isinf(fval)) {
		    const char *expr;

		    if (isnan(fval)) {
			expr = "NaN";
		    }
		    else {
			expr = "Inf";
		    }
		    need = (int)strlen(expr);
		    if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS))
			need++;
		    if ((flags & FWIDTH) && need < width)
			need = width;

		    CHECK(need + 1);
		    snprintf(&buf[blen], need + 1, "%*s", need, "");
		    if (flags & FMINUS) {
			if (!isnan(fval) && fval < 0.0)
			    buf[blen++] = '-';
			else if (flags & FPLUS)
			    buf[blen++] = '+';
			else if (flags & FSPACE)
			    blen++;
			memcpy(&buf[blen], expr, strlen(expr));
		    }
		    else {
			if (!isnan(fval) && fval < 0.0)
			    buf[blen + need - strlen(expr) - 1] = '-';
			else if (flags & FPLUS)
			    buf[blen + need - strlen(expr) - 1] = '+';
			else if ((flags & FSPACE) && need > width)
			    blen++;
			memcpy(&buf[blen + need - strlen(expr)], expr,
			       strlen(expr));
		    }
		    blen += strlen(&buf[blen]);
		    break;
		}

		fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
		need = 0;
		if (*p != 'e' && *p != 'E') {
		    i = INT_MIN;
		    frexp(fval, &i);
		    if (i > 0)
			need = BIT_DIGITS(i);
		}
		need += (flags&FPREC) ? prec : default_float_precision;
		if ((flags&FWIDTH) && need < width)
		    need = width;
		need += 20;

		CHECK(need);
		snprintf(&buf[blen], need, fbuf, fval);
		blen += strlen(&buf[blen]);
	    }
	    break;
	}
	flags = FNONE;
    }

  sprint_exit:
    RB_GC_GUARD(fmt);
    /* XXX - We cannot validate the number of arguments if (digit)$ style used.
     */
    if (posarg >= 0 && nextarg < argc) {
	const char *mesg = "too many arguments for format string";
	if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg);
	if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
    }
    rb_str_resize(result, blen);

    if (tainted) OBJ_TAINT(result);
    return result;
}
예제 #14
0
static VALUE
inspect_enumerator(VALUE obj, VALUE dummy, int recur)
{
    struct enumerator *e;
    const char *cname;
    VALUE eobj, eargs, str, method;
    int tainted, untrusted;

    TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, e);

    cname = rb_obj_classname(obj);

    if (!e || e->obj == Qundef) {
	return rb_sprintf("#<%s: uninitialized>", cname);
    }

    if (recur) {
	str = rb_sprintf("#<%s: ...>", cname);
	OBJ_TAINT(str);
	return str;
    }

    eobj = rb_attr_get(obj, id_receiver);
    if (NIL_P(eobj)) {
	eobj = e->obj;
    }

    tainted   = OBJ_TAINTED(eobj);
    untrusted = OBJ_UNTRUSTED(eobj);

    /* (1..100).each_cons(2) => "#<Enumerator: 1..100:each_cons(2)>" */
    str = rb_sprintf("#<%s: ", cname);
    rb_str_concat(str, rb_inspect(eobj));
    method = rb_attr_get(obj, id_method);
    if (NIL_P(method)) {
	rb_str_buf_cat2(str, ":");
	rb_str_buf_cat2(str, rb_id2name(e->meth));
    }
    else if (method != Qfalse) {
	Check_Type(method, T_SYMBOL);
	rb_str_buf_cat2(str, ":");
	rb_str_buf_cat2(str, rb_id2name(SYM2ID(method)));
    }

    eargs = rb_attr_get(obj, id_arguments);
    if (NIL_P(eargs)) {
	eargs = e->args;
    }
    if (eargs != Qfalse) {
	long   argc = RARRAY_LEN(eargs);
	VALUE *argv = RARRAY_PTR(eargs);

	if (argc > 0) {
	    rb_str_buf_cat2(str, "(");

	    while (argc--) {
		VALUE arg = *argv++;

		rb_str_concat(str, rb_inspect(arg));
		rb_str_buf_cat2(str, argc > 0 ? ", " : ")");

		if (OBJ_TAINTED(arg)) tainted = TRUE;
		if (OBJ_UNTRUSTED(arg)) untrusted = TRUE;
	    }
	}
    }

    rb_str_buf_cat2(str, ">");

    if (tainted) OBJ_TAINT(str);
    if (untrusted) OBJ_UNTRUST(str);
    return str;
}
예제 #15
0
static VALUE
function_call(int argc, VALUE argv[], VALUE self)
{
    ffi_cif * cif;
    fiddle_generic retval;
    fiddle_generic *generic_args;
    void **values;
    VALUE cfunc, types, cPointer;
    int i;

    cfunc    = rb_iv_get(self, "@ptr");
    types    = rb_iv_get(self, "@args");
    cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));

    if(argc != RARRAY_LENINT(types)) {
	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
		argc, RARRAY_LENINT(types));
    }

    TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);

    if (rb_safe_level() >= 1) {
	for (i = 0; i < argc; i++) {
	    VALUE src = argv[i];
	    if (OBJ_TAINTED(src)) {
		rb_raise(rb_eSecurityError, "tainted parameter not allowed");
	    }
	}
    }

    values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *));
    generic_args = xcalloc((size_t)argc, (size_t)sizeof(fiddle_generic));

    for (i = 0; i < argc; i++) {
	VALUE type = RARRAY_PTR(types)[i];
	VALUE src = argv[i];

	if(NUM2INT(type) == TYPE_VOIDP) {
	    if(NIL_P(src)) {
		src = INT2NUM(0);
	    } else if(cPointer != CLASS_OF(src)) {
	        src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
	    }
	    src = rb_Integer(src);
	}

	VALUE2GENERIC(NUM2INT(type), src, &generic_args[i]);
	values[i] = (void *)&generic_args[i];
    }
    values[argc] = NULL;

    ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values);

    rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
#if defined(_WIN32)
    rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
#endif

    xfree(values);
    xfree(generic_args);

    return GENERIC2VALUE(rb_iv_get(self, "@return_type"), retval);
}