/* * This is a primitive so #initialize_copy can work. */ Regexp* Regexp::initialize(STATE, String* pattern, Fixnum* options) { const UChar *pat; const UChar *end; OnigErrorInfo err_info; OnigOptionType opts; OnigEncoding enc; int err, num_names, kcode; pat = (UChar*)pattern->byte_address(); end = pat + pattern->size(); opts = options->to_native(); kcode = opts & KCODE_MASK; opts &= OPTION_MASK; if(kcode == 0) { enc = current_encoding(state); } else { // Don't attempt to fix the encoding later, it's been specified by the // user. enc = get_enc_from_kcode(kcode); forced_encoding_ = true; } thread::Mutex::LockGuard lg(state->shared().onig_lock()); err = onig_new(&this->onig_data, pat, end, opts, enc, ONIG_SYNTAX_RUBY, &err_info); if(err != ONIG_NORMAL) { UChar onig_err_buf[ONIG_MAX_ERROR_MESSAGE_LEN]; char err_buf[1024]; onig_error_code_to_str(onig_err_buf, err, &err_info); snprintf(err_buf, 1024, "%s: %s", onig_err_buf, pat); Exception::regexp_error(state, err_buf); return 0; } this->source(state, pattern); num_names = onig_number_of_names(this->onig_data); if(num_names == 0) { this->names(state, nil<LookupTable>()); } else { struct _gather_data gd; gd.state = state; LookupTable* tbl = LookupTable::create(state); gd.tbl = tbl; onig_foreach_name(this->onig_data, (int (*)(const OnigUChar*, const OnigUChar*,int,int*,OnigRegex,void*))_gather_names, (void*)&gd); this->names(state, tbl); } make_managed(state); return this; }
void Regexp::maybe_recompile(STATE) { const UChar *pat; const UChar *end; OnigEncoding enc; OnigErrorInfo err_info; int err; if(forced_encoding_) return; enc = current_encoding(state); if(enc == onig_data->enc) return; pat = (UChar*)source()->c_str(); end = pat + source()->size(); int options = onig_data->options; OnigEncoding orig_enc = onig_data->enc; err = onig_new(&this->onig_data, pat, end, options, enc, ONIG_SYNTAX_RUBY, &err_info); // If it doesn't work out, then abort and reset the encoding back // and say that it's forced. if(err != ONIG_NORMAL) { err = onig_new(&this->onig_data, pat, end, options, orig_enc, ONIG_SYNTAX_RUBY, &err_info); // Ok, wtf. Well, no way to proceed now. if(err != ONIG_NORMAL) { OnigUChar buf[1024]; onig_error_code_to_str((UChar*)buf, err, &err_info); std::cout << "Fatal ONIG error: " << buf << "\n"; assert(err == ONIG_NORMAL); } forced_encoding_ = true; } make_managed(state); }