static VALUE cbsubst_def_attr_aliases(self, tbl) VALUE self; VALUE tbl; { struct cbsubst_info *inf; if (TYPE(tbl) != T_HASH) { rb_raise(rb_eArgError, "expected a Hash"); } Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), struct cbsubst_info, inf); 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 *buf, *ptr; int i, len; volatile VALUE ret; Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), struct cbsubst_info, inf); len = strlen(inf->key); buf = ALLOC_N(char, 3*len + 1); ptr = buf; for(i = 0; i < len; i++) { *(ptr++) = '%'; *(ptr++) = *(inf->key + i); *(ptr++) = ' '; } *(buf + 3*len) = '\0'; ret = rb_ary_new3(2, rb_str_new2(inf->key), rb_str_new2(buf)); free(buf); return ret; }
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; { volatile VALUE list; volatile VALUE ret; int i, len; char *buf, *ptr; list = rb_funcall(cTclTkLib, ID_split_tklist, 1, str); len = RARRAY(list)->len; buf = ALLOC_N(char, len + 1); for(i = 0; i < len; i++) { ptr = RSTRING(RARRAY(list)->ptr[i])->ptr; if (*ptr == '%' && *(ptr + 2) == '\0') { *(buf + i) = *(ptr + 1); } else { *(buf + i) = ' '; } } *(buf + len) = '\0'; ret = rb_str_new2(buf); free(buf); return ret; }
static VALUE cbsubst_table_setup(self, key_inf, proc_inf) VALUE self; VALUE key_inf; VALUE proc_inf; { struct cbsubst_info *subst_inf; int idx; int len = RARRAY(key_inf)->len; int real_len = 0; char *key = ALLOC_N(char, len + 1); char *type = ALLOC_N(char, len + 1); ID *ivar = ALLOC_N(ID, len + 1); volatile VALUE proc = rb_hash_new(); volatile VALUE aliases = rb_hash_new(); volatile VALUE inf; /* init */ subst_inf = ALLOC(struct cbsubst_info); /* subst_inf->size = len; */ subst_inf->key = key; subst_inf->type = type; subst_inf->ivar = ivar; subst_inf->proc = proc; subst_inf->aliases = aliases; /* * keys : array of [subst, type, ivar] * subst ==> char code * type ==> char code * ivar ==> symbol */ for(idx = 0; idx < len; idx++) { inf = RARRAY(key_inf)->ptr[idx]; if (TYPE(inf) != T_ARRAY) continue; *(key + real_len) = (char)NUM2INT(RARRAY(inf)->ptr[0]); *(type + real_len) = (char)NUM2INT(RARRAY(inf)->ptr[1]); *(ivar + real_len) = rb_intern( RSTRING( rb_str_cat2(rb_str_new2("@"), rb_id2name(SYM2ID(RARRAY(inf)->ptr[2]))) )->ptr ); rb_attr(self, SYM2ID(RARRAY(inf)->ptr[2]), 1, 0, Qtrue); real_len++; } *(key + real_len) = '\0'; *(type + real_len) = '\0'; subst_inf->size = real_len; /* * procs : array of [type, proc] * type ==> char code * proc ==> proc/method/obj (must respond to 'call') */ len = RARRAY(proc_inf)->len; for(idx = 0; idx < len; idx++) { inf = RARRAY(proc_inf)->ptr[idx]; if (TYPE(inf) != T_ARRAY) continue; rb_hash_aset(proc, RARRAY(inf)->ptr[0], RARRAY(inf)->ptr[1]); } rb_const_set(self, ID_SUBST_INFO, Data_Wrap_Struct(cSUBST_INFO, subst_mark, subst_free, subst_inf)); return self; }
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; Data_Get_Struct(rb_const_get(rb_obj_class(self), ID_SUBST_INFO), struct cbsubst_info, inf); for(idx = 0; idx < argc; idx++) { rb_ivar_set(self, inf->ivar[idx], argv[idx]); } return self; }
static VALUE cbsubst_ret_val(self, val) VALUE self; VALUE val; { return val; }
static VALUE cbsubst_scan_args(self, arg_key, val_ary) VALUE self; VALUE arg_key; VALUE val_ary; { struct cbsubst_info *inf; int idx; int len = RARRAY(val_ary)->len; char c; char *ptr; volatile VALUE dst = rb_ary_new2(len); 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(); Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), struct cbsubst_info, inf); RARRAY(dst)->len = 0; for(idx = 0; idx < len; idx++) { if (idx >= RSTRING(arg_key)->len) { proc = Qnil; } else if (*(RSTRING(arg_key)->ptr + idx) == ' ') { proc = Qnil; } else { ptr = strchr(inf->key, *(RSTRING(arg_key)->ptr + idx)); if (ptr == (char*)NULL) { proc = Qnil; } else { c = *(inf->type + (ptr - inf->key)); proc = rb_hash_aref(inf->proc, INT2FIX(c)); } } if (NIL_P(proc)) { RARRAY(dst)->ptr[RARRAY(dst)->len++] = RARRAY(val_ary)->ptr[idx]; } else { RARRAY(dst)->ptr[RARRAY(dst)->len++] = rb_funcall(proc, ID_call, 1, RARRAY(val_ary)->ptr[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; char *str, *buf, *ptr; int i, j, len; ID id; volatile VALUE arg_sym, ret; Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), struct cbsubst_info, inf); buf = ALLOC_N(char, 3*argc + 1); ptr = buf; len = strlen(inf->key); for(i = 0; i < argc; i++) { switch(TYPE(argv[i])) { case T_STRING: str = RSTRING(argv[i])->ptr; arg_sym = ID2SYM(rb_intern(str)); break; case T_SYMBOL: arg_sym = argv[i]; str = rb_id2name(SYM2ID(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_id2name(SYM2ID(ret)); } id = rb_intern(RSTRING(rb_str_cat2(rb_str_new2("@"), str))->ptr); for(j = 0; j < len; j++) { if (inf->ivar[j] == id) break; } if (j >= len) { rb_raise(rb_eArgError, "cannot find attribute :%s", str); } *(ptr++) = '%'; *(ptr++) = *(inf->key + j); *(ptr++) = ' '; } *ptr = '\0'; ret = rb_str_new2(buf); free(buf); return ret; }