/*
 *  call-seq:
 *     Regexp.new(string [, options])                => regexp
 *     Regexp.new(regexp)                            => regexp
 *     Regexp.compile(string [, options])            => regexp
 *     Regexp.compile(regexp)                        => regexp
 *
 *  Constructs a new regular expression from <i>pattern</i>, which can be either
 *  a <code>String</code> or a <code>Regexp</code> (in which case that regexp's
 *  options are propagated, and new options may not be specified (a change as of
 *  Ruby 1.8). If <i>options</i> is a <code>Fixnum</code>, it should be one or
 *  more of the constants <code>Regexp::EXTENDED</code>,
 *  <code>Regexp::IGNORECASE</code>, and <code>Regexp::MULTILINE</code>,
 *  <em>or</em>-ed together. Otherwise, if <i>options</i> is not
 *  <code>nil</code>, the regexp will be case insensitive.
 *
 *     r1 = Regexp.new('^a-z+:\\s+\w+')           #=> /^a-z+:\s+\w+/
 *     r2 = Regexp.new('cat', true)               #=> /cat/i
 *     r3 = Regexp.new('dog', Regexp::EXTENDED)   #=> /dog/x
 *     r4 = Regexp.new(r2)                        #=> /cat/i
 */

static VALUE
rb_reg_initialize_m(int argc, VALUE *argv, VALUE self)
{
    onig_errmsg_buffer err = "";
    int flags = 0;
    VALUE str;
    rb_encoding *enc;
    const char *ptr;
    long len;

    if (argc == 0 || argc > 3) {
        rb_raise(rb_eArgError, "wrong number of arguments");
    }
    if (TYPE(argv[0]) == T_REGEXP) {
        VALUE re = argv[0];

        if (argc > 1) {
            rb_warn("flags ignored");
        }
        rb_reg_check(re);
        flags = rb_reg_options(re);
        ptr = RREGEXP(re)->str;
        len = RREGEXP(re)->len;
        enc = rb_enc_get(re);
        if (rb_reg_initialize(self, ptr, len, enc, flags, err)) {
            str = rb_enc_str_new(ptr, len, enc);
            rb_reg_raise_str(str, flags, err);
        }
    }
    else {
        if (argc >= 2) {
            if (FIXNUM_P(argv[1])) flags = FIX2INT(argv[1]);
            else if (RTEST(argv[1])) flags = ONIG_OPTION_IGNORECASE;
        }
        enc = 0;
        if (argc == 3 && !NIL_P(argv[2])) {
            char *kcode = StringValuePtr(argv[2]);
            if (kcode[0] == 'n' || kcode[1] == 'N') {
                enc = rb_ascii8bit_encoding();
                flags |= ARG_ENCODING_FIXED;
            }
            else {
                rb_warning("encoding option is obsolete - %s", kcode);
            }
        }
        str = argv[0];
        ptr = StringValuePtr(str);
        if (enc
            ? rb_reg_initialize(self, ptr, RSTRING_LEN(str), enc, flags, err)
            : rb_reg_initialize_str(self, str, flags, err)) {
            rb_reg_raise_str(str, flags, err);
        }
    }
    return self;
}