rb_str_splice(str, beg, len, val)
    VALUE str;
    long beg, len;
    VALUE val;
{
    if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);

    StringValue(val);
    rb_str_modify(str);

    if (RSTRING(str)->len < beg) {
      out_of_range:
	rb_raise(rb_eIndexError, "index %ld out of string", beg);
    }
    if (beg < 0) {
	if (-beg > RSTRING(str)->len) {
	    goto out_of_range;
	}
	beg += RSTRING(str)->len;
    }
    if (RSTRING(str)->len < len || RSTRING(str)->len < beg + len) {
	len = RSTRING(str)->len - beg;
    }

    if (len < RSTRING(val)->len) {
	/* expand string */
	RESIZE_CAPA(str, RSTRING(str)->len + RSTRING(val)->len - len + 1);
    }

    if (RSTRING(val)->len != len) {
	memmove(RSTRING(str)->ptr + beg + RSTRING(val)->len,
		RSTRING(str)->ptr + beg + len,
		RSTRING(str)->len - (beg + len));
    }
    if (RSTRING(str)->len < beg && len < 0) {
	MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, -len);
    }
    if (RSTRING(val)->len > 0) {
	memmove(RSTRING(str)->ptr+beg, RSTRING(val)->ptr, RSTRING(val)->len);
    }
    RSTRING(str)->len += RSTRING(val)->len - len;
    if (RSTRING(str)->ptr) {
	RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
    }
    OBJ_INFECT(str, val);
}
rb_str_splice(str, beg, len, val)
    VALUE str;
    long beg, len;
    VALUE val;
{
    if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);

    StringValue(val);
    rb_str_modify(str);

    if (RSTRING(str)->len < beg) {
      out_of_range:
	rb_raise(rb_eIndexError, "index %ld out of string", beg);
    }
    if (beg < 0) {
	if (-beg > RSTRING(str)->len) {
	    goto out_of_range;
	}
	beg += RSTRING(str)->len;
    }
    if (RSTRING(str)->len < len || RSTRING(str)->len < beg + len) {
	len = RSTRING(str)->len - beg;
    }

    if (len < RSTRING(val)->len) {
	 
	RESIZE_CAPA(str, RSTRING(str)->len + RSTRING(val)->len - len + 1);
    }

    if (RSTRING(val)->len != len) {
	memmove(RSTRING(str)->ptr + beg + RSTRING(val)->len,
		RSTRING(str)->ptr + beg + len,
		RSTRING(str)->len - (beg + len));
    }
    if (RSTRING(str)->len < beg && len < 0) {
	MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, -len);
    }
    if (RSTRING(val)->len > 0) {
	memmove(RSTRING(str)->ptr+beg, RSTRING(val)->ptr, RSTRING(val)->len);
    }
    RSTRING(str)->len += RSTRING(val)->len - len;
    if (RSTRING(str)->ptr) {
	RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
    }
    OBJ_INFECT(str, val);
}