ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg,
		  rb_encoding *enc)
{
    const int escape = !(flags & FNM_NOESCAPE);
    const char *p = str;
    const char *pend = p + strlen(p);
    const char *s = p;
    const char *lbrace = 0, *rbrace = 0;
    int nest = 0, status = 0;

    while (*p) {
	if (*p == '{' && nest++ == 0) {
	    lbrace = p;
	}
	if (*p == '}' && --nest <= 0) {
	    rbrace = p;
	    break;
	}
	if (*p == '\\' && escape) {
	    if (!*++p) break;
	}
	Inc(p, pend, enc);
    }

    if (lbrace && rbrace) {
	size_t len = strlen(s) + 1;
	char *buf = GLOB_ALLOC_N(char, len);
	long shift;

	if (!buf) return -1;
	memcpy(buf, s, lbrace-s);
	shift = (lbrace-s);
	p = lbrace;
	while (p < rbrace) {
	    const char *t = ++p;
	    nest = 0;
	    while (p < rbrace && !(*p == ',' && nest == 0)) {
		if (*p == '{') nest++;
		if (*p == '}') nest--;
		if (*p == '\\' && escape) {
		    if (++p == rbrace) break;
		}
		Inc(p, pend, enc);
	    }
	    memcpy(buf+shift, t, p-t);
	    strlcpy(buf+shift+(p-t), rbrace+1, len-(shift+(p-t)));
	    status = ruby_brace_expand(buf, flags, func, arg, enc);
	    if (status) break;
	}
	GLOB_FREE(buf);
    }
    else if (!lbrace && !rbrace) {
	status = glob_call_func(func, s, arg, enc);
    }

    return status;
}
ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg,
		  rb_encoding *enc)
{
    const int escape = !(flags & FNM_NOESCAPE);
    const char *p = str;
    const char *pend = p + strlen(p);
    const char *s = p;
    const char *lbrace = 0, *rbrace = 0;
    int nest = 0, status = 0;

    while (*p) {
	if (*p == '{' && nest++ == 0) {
	    lbrace = p;
	}
	if (*p == '}' && --nest <= 0) {
	    rbrace = p;
	    break;
	}
	if (*p == '\\' && escape) {
	    if (!*++p) break;
	}
	Inc(p, pend, enc);
    }

    if (lbrace && rbrace) {
	size_t len = strlen(s) + 1;
	char *buf = GLOB_ALLOC_N(char, len);
	long shift;

	if (!buf) return -1;
	memcpy(buf, s, lbrace-s);
	shift = (lbrace-s);
	p = lbrace;
	while (p < rbrace) {
	    const char *t = ++p;
	    nest = 0;
	    while (p < rbrace && !(*p == ',' && nest == 0)) {
		if (*p == '{') nest++;
		if (*p == '}') nest--;
		if (*p == '\\' && escape) {
		    if (++p == rbrace) break;
		}
		Inc(p, pend, enc);
	    }
	    memcpy(buf+shift, t, p-t);
	    strlcpy(buf+shift+(p-t), rbrace+1, len-(shift+(p-t)));
	    status = ruby_brace_expand(buf, flags, func, arg, enc);
	    if (status) break;
	}
	GLOB_FREE(buf);
    }
    else if (!lbrace && !rbrace) {
	status = glob_call_func(func, s, arg, enc);
    }

    return status;
}