static VALUE cbsubst_def_attr_aliases(self, tbl) VALUE self; VALUE tbl; { struct cbsubst_info *inf; if (!RB_TYPE_P(tbl, T_HASH)) { rb_raise(rb_eArgError, "expected a Hash"); } inf = cbsubst_get_ptr(self); rb_hash_foreach(tbl, each_attr_def, self); return rb_funcall(inf->aliases, rb_intern("update"), 1, tbl); }
static VALUE cbsubst_get_all_subst_keys(self) VALUE self; { struct cbsubst_info *inf; char *keys_buf, *keys_ptr; int idx; VALUE str, keys_str; inf = cbsubst_get_ptr(self); str = rb_str_new(0, 0); keys_str = rb_str_new(0, CBSUBST_TBL_MAX); keys_ptr = keys_buf = RSTRING_PTR(keys_str); for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) { if (inf->ivar[idx] == (ID) 0) continue; *(keys_ptr++) = (unsigned char)idx; str = cbsubst_append_inf_key(str, inf, idx); } rb_str_set_len(keys_str, keys_ptr - keys_buf); return rb_ary_new3(2, keys_str, str); }
static VALUE cbsubst_get_extra_args_tbl(self) VALUE self; { return rb_ary_new(); }
static VALUE cbsubst_get_subst_key(self, str) VALUE self; VALUE str; { struct cbsubst_info *inf; VALUE list; VALUE ret; long i, len, keylen; int idx; char *buf, *ptr; list = rb_funcall(cTclTkLib, ID_split_tklist, 1, str); Check_Type(list, T_ARRAY); len = RARRAY_LEN(list); inf = cbsubst_get_ptr(self); ret = rb_str_new(0, len); ptr = buf = RSTRING_PTR(ret); for(i = 0; i < len; i++) { VALUE keyval = RARRAY_AREF(list, i); const char *key = (Check_Type(keyval, T_STRING), StringValueCStr(keyval)); if (*key == '%') { if (*(key + 2) == '\0') { /* single char */ *(ptr++) = *(key + 1); } else { /* search longname-key */ keylen = RSTRING_LEN(keyval) - 1; for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) { if (inf->keylen[idx] != keylen) continue; if ((unsigned char)inf->key[idx][0] != (unsigned char)*(key + 1)) continue; if (strncmp(inf->key[idx], key + 1, keylen)) continue; break; } if (idx < CBSUBST_TBL_MAX) { *(ptr++) = (unsigned char)idx; } else { *(ptr++) = ' '; } } } else { *(ptr++) = ' '; } } rb_str_set_len(ret, ptr - buf); return ret; }
static VALUE cbsubst_table_setup(argc, argv, self) int argc; VALUE *argv; VALUE self; { VALUE cbsubst_obj; VALUE key_inf; VALUE longkey_inf; VALUE proc_inf; VALUE inf, subst, name, type, ivar, proc; const VALUE *infp; ID id; struct cbsubst_info *subst_inf; long idx; unsigned char chr; /* accept (key_inf, proc_inf) or (key_inf, longkey_inf, procinf) */ if (rb_scan_args(argc, argv, "21", &key_inf, &longkey_inf, &proc_inf) == 2) { proc_inf = longkey_inf; longkey_inf = rb_ary_new(); } Check_Type(key_inf, T_ARRAY); Check_Type(longkey_inf, T_ARRAY); Check_Type(proc_inf, T_ARRAY); /* check the number of longkeys */ if (RARRAY_LEN(longkey_inf) > 125 /* from 0x80 to 0xFD */) { rb_raise(rb_eArgError, "too many longname-key definitions"); } /* init */ cbsubst_obj = allocate_cbsubst_info(&subst_inf); /* * keys : array of [subst, type, ivar] * subst ==> char code or string * type ==> char code or string * ivar ==> symbol */ for(idx = 0; idx < RARRAY_LEN(key_inf); idx++) { inf = RARRAY_AREF(key_inf, idx); if (!RB_TYPE_P(inf, T_ARRAY)) continue; if (RARRAY_LEN(inf) < 3) continue; infp = RARRAY_CONST_PTR(inf); subst = infp[0]; type = infp[1]; ivar = infp[2]; chr = NUM2CHR(subst); subst_inf->type[chr] = NUM2CHR(type); subst_inf->full_subst_length += 3; id = SYM2ID(ivar); subst_inf->ivar[chr] = rb_intern_str(rb_sprintf("@%"PRIsVALUE, rb_id2str(id))); rb_attr(self, id, 1, 0, Qtrue); } RB_GC_GUARD(key_inf); /* * longkeys : array of [name, type, ivar] * name ==> longname key string * type ==> char code or string * ivar ==> symbol */ for(idx = 0; idx < RARRAY_LEN(longkey_inf); idx++) { inf = RARRAY_AREF(longkey_inf, idx); if (!RB_TYPE_P(inf, T_ARRAY)) continue; if (RARRAY_LEN(inf) < 3) continue; infp = RARRAY_CONST_PTR(inf); name = infp[0]; type = infp[1]; ivar = infp[2]; Check_Type(name, T_STRING); chr = (unsigned char)(0x80 + idx); subst_inf->keylen[chr] = RSTRING_LEN(name); subst_inf->key[chr] = strndup(RSTRING_PTR(name), RSTRING_LEN(name)); subst_inf->type[chr] = NUM2CHR(type); subst_inf->full_subst_length += (subst_inf->keylen[chr] + 2); id = SYM2ID(ivar); subst_inf->ivar[chr] = rb_intern_str(rb_sprintf("@%"PRIsVALUE, rb_id2str(id))); rb_attr(self, id, 1, 0, Qtrue); } RB_GC_GUARD(longkey_inf); /* * procs : array of [type, proc] * type ==> char code or string * proc ==> proc/method/obj (must respond to 'call') */ for(idx = 0; idx < RARRAY_LEN(proc_inf); idx++) { inf = RARRAY_AREF(proc_inf, idx); if (!RB_TYPE_P(inf, T_ARRAY)) continue; if (RARRAY_LEN(inf) < 2) continue; type = rb_ary_entry(inf, 0); proc = rb_ary_entry(inf, 1); if (RB_TYPE_P(type, T_STRING)) type = INT2FIX(*(RSTRING_PTR(type))); rb_hash_aset(subst_inf->proc, type, proc); } RB_GC_GUARD(proc_inf); rb_const_set(self, ID_SUBST_INFO, cbsubst_obj); return self; }
static VALUE cbsubst_sym_to_subst(self, sym) VALUE self; VALUE sym; { struct cbsubst_info *inf; VALUE str; int idx; ID id; volatile VALUE ret; if (!RB_TYPE_P(sym, T_SYMBOL)) return sym; inf = cbsubst_get_ptr(self); if (!NIL_P(ret = rb_hash_aref(inf->aliases, sym))) { str = rb_sym2str(ret); } else { str = rb_sym2str(sym); } id = rb_intern_str(rb_sprintf("@%"PRIsVALUE, str)); for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) { if (inf->ivar[idx] == id) break; } if (idx >= CBSUBST_TBL_MAX) return sym; return cbsubst_append_inf_key(rb_str_new(0, 0), inf, idx); }
static VALUE cbsubst_inspect(self) VALUE self; { return rb_str_new2("CallbackSubst"); }
static VALUE cbsubst_initialize(argc, argv, self) int argc; VALUE *argv; VALUE self; { struct cbsubst_info *inf; int idx, iv_idx; inf = cbsubst_get_ptr(rb_obj_class(self)); if (argc > 0) { idx = 0; for (iv_idx = 0; iv_idx < CBSUBST_TBL_MAX; iv_idx++) { if (inf->ivar[iv_idx] == (ID)0) continue; rb_ivar_set(self, inf->ivar[iv_idx], argv[idx++]); if (idx >= argc) break; } } return self; }
static VALUE cbsubst_ret_val(self, val) VALUE self; VALUE val; { /* This method may be overwritten on some sub-classes. */ /* This method is used for converting from ruby's callback-return-value */ /* to tcl's value (e.g. validation procedure of entry widget). */ return val; }
static VALUE cbsubst_scan_args(self, arg_key, val_ary) VALUE self; VALUE arg_key; VALUE val_ary; { struct cbsubst_info *inf; long idx; unsigned char *keyptr = (unsigned char*)StringValueCStr(arg_key); long keylen = RSTRING_LEN(arg_key); long vallen = (Check_Type(val_ary, T_ARRAY), RARRAY_LEN(val_ary)); unsigned char type_chr; volatile VALUE dst = rb_ary_new2(vallen); volatile VALUE proc; int thr_crit_bup; VALUE old_gc; thr_crit_bup = rb_thread_critical; rb_thread_critical = Qtrue; old_gc = rb_gc_disable(); inf = cbsubst_get_ptr(self); for(idx = 0; idx < vallen; idx++) { if (idx >= keylen) { proc = Qnil; } else if (*(keyptr + idx) == ' ') { proc = Qnil; } else { if ((type_chr = inf->type[*(keyptr + idx)]) != 0) { proc = rb_hash_aref(inf->proc, INT2FIX((int)type_chr)); } else { proc = Qnil; } } if (NIL_P(proc)) { rb_ary_push(dst, RARRAY_AREF(val_ary, idx)); } else { rb_ary_push(dst, rb_funcall(proc, ID_call, 1, RARRAY_AREF(val_ary, idx))); } } if (old_gc == Qfalse) rb_gc_enable(); rb_thread_critical = thr_crit_bup; return dst; }
static VALUE cbsubst_get_subst_arg(argc, argv, self) int argc; VALUE *argv; VALUE self; { struct cbsubst_info *inf; VALUE str; int i, idx; ID id; VALUE arg_sym, ret, result; inf = cbsubst_get_ptr(self); result = rb_str_new(0, 0); for(i = 0; i < argc; i++) { switch(TYPE(argv[i])) { case T_STRING: str = argv[i]; arg_sym = rb_check_symbol(&str); if (NIL_P(arg_sym)) goto not_found; break; case T_SYMBOL: arg_sym = argv[i]; str = rb_sym2str(arg_sym); break; default: rb_raise(rb_eArgError, "arg #%d is not a String or a Symbol", i); } if (!NIL_P(ret = rb_hash_aref(inf->aliases, arg_sym))) { str = rb_sym2str(ret); } ret = rb_sprintf("@%"PRIsVALUE, str); id = rb_check_id(&ret); if (!id) goto not_found; for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) { if (inf->ivar[idx] == id) break; } if (idx >= CBSUBST_TBL_MAX) { not_found: rb_raise(rb_eArgError, "cannot find attribute :%"PRIsVALUE, str); } result = cbsubst_append_inf_key(result, inf, idx); } return result; }
Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.
If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.