bool Theme::get_item(const char *style_name, const char *item_name, char *ret, unsigned int sz) { E_RETURN_VAL_IF_FAIL(priv->is_loaded == true, false); E_RETURN_VAL_IF_FAIL(style_name != NULL, false); E_RETURN_VAL_IF_FAIL(item_name != NULL, false); E_RETURN_VAL_IF_FAIL(ret!= NULL, false); E_RETURN_VAL_IF_FAIL(sz > 0, false); scheme *ss = priv->sc; pointer style = get_style_once(priv, ss, style_name); if(style == ss->NIL) return false; pointer lst, item, val; char *ret_str = NULL; /* * 'style' has the following list: '((item value) (item value)...)' * First item is a symbol and the second is string. Although tinyscheme displays them in the same way, * they are different types and appropriate functions must be called during conversion. */ while(style != ss->NIL) { lst = ss->vptr->pair_car(style); item = ss->vptr->pair_car(lst); val = ss->vptr->pair_car(ss->vptr->pair_cdr(lst)); /* check if we found matching item */ if(ss->vptr->is_symbol(item) && strcmp(item_name, ss->vptr->symname(item)) == 0) { #if THEME_EVAL_VALUE_PAIR /* * Now, see if item value is function; if is true, evaluate it and return the result. * In this case, result must be a string. */ if(ss->vptr->is_pair(val)) val = scheme_eval(ss, val); #endif /* if it is not string, simply continue until find item with the string value */ if(ss->vptr->is_string(val)) { ret_str = ss->vptr->string_value(val); break; } } style = ss->vptr->pair_cdr(style); } if(ret_str) { strncpy(ret, ret_str, sz); if(sz > 0) ret[sz - 1] = '\0'; } return (ret_str != NULL); }
static bool eval_fundamental_form(sexp car, sexp cdr, activation* act, thunk* result) { scheme_symbol sym = NULL; if (!sexp_extract_symbol(car, &sym)) { return false; } // TODO this is pretty bad. these should all be interned. if (strcmp(sym, "define") == 0) { // (define <sym> <value>) sexp define_sym = NULL; sexp define_value = NULL; if (!sexp_extract_cons(cdr, &define_sym, &define_value)) { scheme_runtime_error("invalid define fundamental form"); } scheme_symbol define_name = NULL; if (!sexp_extract_symbol(define_sym, &define_name)) { scheme_runtime_error("first argument to define must be a symbol"); } sexp actual_binding = NULL; sexp should_be_empty = NULL; if (!sexp_extract_cons(define_value, &actual_binding, &should_be_empty)) { scheme_runtime_error("invalid define fundamental form"); } if (!sexp_is_empty(should_be_empty)) { scheme_runtime_error("too many items in define"); } sexp binding_value = scheme_eval(actual_binding, act); if (sexp_is_proc(binding_value)) { // shortcut for better output. The form // (define name (lambda ...)) // is assigns the name "name" to the lambda. binding_value->name = define_name; } activation_add_binding(global_activation, define_name, binding_value); *result = thunk_new(act, gc_allocate_empty(), false); return true; } if (strcmp(sym, "let") == 0) { // (let ((x 1) (y 2)) <expr>) sexp binding_list = NULL; sexp body = NULL; if (!sexp_extract_cons(cdr, &binding_list, &body)) { scheme_runtime_error("invalid let fundamental form"); } // binding list is itself a list of two-element lists. activation* child_act = gc_allocate_activation(); // let activations inherit their parent's activation names. activation_initialize(child_act, act, act->name); FOR_EACH_LIST(binding_list, binding, { // binding is a list of two elements sexp binding_name = NULL; sexp binding_value = NULL; if (!sexp_extract_cons(binding, &binding_name, &binding_value)) { scheme_runtime_error("invalid let fundamental form"); } scheme_symbol let_sym = NULL; if (!sexp_extract_symbol(binding_name, &let_sym)) { scheme_runtime_error("non-symbol in let binding"); } sexp actual_binding = NULL; sexp should_be_empty = NULL; if (!sexp_extract_cons(binding_value, &actual_binding, &should_be_empty)) { scheme_runtime_error("invalid let-binding list"); } if (!sexp_is_empty(should_be_empty)) { scheme_runtime_error("too many items in let-binding"); } sexp value = scheme_eval(actual_binding, child_act); activation_add_binding(child_act, let_sym, value); });