static uim_lisp c_execve(uim_lisp file_, uim_lisp argv_, uim_lisp envp_) { char **argv; char **envp; int i; int argv_len = uim_scm_length(argv_); int envp_len; uim_lisp ret_; if (argv_len < 1) return uim_scm_f(); argv = uim_malloc(sizeof(char *) * (argv_len + 1)); for (i = 0; i < argv_len; i++) { argv[i] = uim_strdup(REFER_C_STR(CAR(argv_))); argv_ = CDR(argv_); } argv[argv_len] = NULL; if (FALSEP(envp_) || NULLP(envp_)) { envp_len = 0; envp = NULL; } else { envp_len = uim_scm_length(envp_); envp = uim_malloc(sizeof(char *) * (envp_len + 1)); for (i = 0; i < envp_len; i++) { uim_lisp env_ = CAR(envp_); uim_asprintf(&envp[i], "%s=%s", REFER_C_STR(CAR(env_)), REFER_C_STR(CDR(env_))); envp_ = CDR(envp_); } envp[envp_len] = NULL; } ret_ = MAKE_INT(execve(REFER_C_STR(file_), argv, envp)); for (i = 0; i < argv_len; i++) free(argv[i]); free(argv); for (i = 0; i < envp_len; i++) free(envp[i]); free(envp); return ret_; }
static uim_lisp get_nth_prediction(uim_lisp ac_, uim_lisp nth_) { #ifdef HAS_ANTHY_PREDICTION anthy_context_t ac; int nth, buflen; char *buf; uim_lisp buf_; ac = get_anthy_context(ac_); nth = C_INT(nth_); buflen = anthy_get_prediction(ac, nth, NULL, 0); if (buflen == -1) uim_fatal_error("anthy_get_prediction() failed"); buf = uim_malloc(buflen + 1); buflen = anthy_get_prediction(ac, nth, buf, buflen + 1); if (buflen == -1) { free(buf); uim_fatal_error("anthy_get_prediction() failed"); } buf_ = MAKE_STR_DIRECTLY(buf); return buf_; #else return uim_scm_f(); #endif }
char * uim_helper_buffer_get_message(char *buf) { size_t msg_size; char *msg, *msg_term; if (UIM_CATCH_ERROR_BEGIN()) return NULL; if (!buf) return NULL; msg_term = strstr(buf, "\n\n"); if (msg_term) { msg_size = msg_term + 2 - buf; msg = uim_malloc(msg_size + 1); memcpy(msg, buf, msg_size); msg[msg_size] = '\0'; uim_helper_buffer_shift(buf, msg_size); } else { msg = NULL; } UIM_CATCH_ERROR_END(); return msg; }
/* * underlineモードとstandoutモードを終了してn文字スペースを出力する * 画面の右端を越えてはいけない */ void put_erase(int n) { int i; char *spaces; if (n <= 0) { return; } spaces = uim_malloc(n + 1); for (i = 0; i < n; i++) { spaces[i] = ' '; } spaces[n] = '\0'; if (s_escseq_buf != NULL) { free(s_escseq_buf); s_escseq_buf = NULL; } s_attr_uim.standout = FALSE; s_attr_uim.underline = FALSE; change_background_attr(&s_attr, s_attr_uim); s_cursor.col += n; assert(s_cursor.col <= g_win->ws_col || g_opt.no_report_cursor); write(g_win_out, spaces, n); free(spaces); debug(("<put erase %d>", n)); }
void switch_context_im_all(const char *im) { char *quot_im_name; uim_agent_context_list *ptr; /* change default IM */ update_default_engine(im); /* check focus state when change IM of current application */ quot_im_name = uim_malloc(strlen(im) + 2); quot_im_name[0] = '\''; quot_im_name[1] = '\0'; strcat(quot_im_name, im); if (agent_context_list_head) /* update default IM name in libuim? should be called only one time? */ uim_prop_update_custom(agent_context_list_head->agent_context->context, "custom-preserved-default-im-name", quot_im_name); for (ptr = agent_context_list_head; ptr != NULL; ptr = ptr->next) { switch_context_im(ptr->agent_context, im); } free(quot_im_name); }
uim_eb * uim_eb_new (const char *bookpath) { uim_eb *ueb; EB_Error_Code err; ueb = uim_malloc(sizeof(uim_eb)); eb_initialize_book(&ueb->book); err = eb_bind(&ueb->book, bookpath); if (err != EB_SUCCESS) { uim_notify_fatal(N_("eb: wrong bookpath")); free(ueb); return NULL; } err = eb_subbook_list(&ueb->book, ueb->subCodes, &ueb->subCount); if (err != EB_SUCCESS) { uim_notify_fatal(N_("eb: eb_subbook_list() failed\n")); free(ueb); return NULL; } return ueb; }
uim_agent_context * create_uim_agent_context(const char *encoding) { uim_agent_context *ret; const char *im; debug_printf(DEBUG_NOTE, "create_uim_agent_context\n"); ret = uim_malloc(sizeof(uim_agent_context)); if (encoding) { ret->encoding = uim_strdup(encoding); } else { if (debug_level > 0) ret->encoding = uim_strdup("EUC-JP"); else ret->encoding = uim_strdup("UTF-8"); } ret->context = create_context(ret->encoding, ret); if ((im = uim_get_default_im_name(setlocale(LC_CTYPE, NULL)))) ret->im = uim_strdup(im); else ret->im = NULL; ret->pe = create_preedit(); ret->cand = create_candidate(); ret->prop = create_prop(); ret->comstr = (char *)NULL; return ret; }
/* * tabstrのタブをTAB_WIDTH個のスペースに置き換える。 * 返り値はfreeする。 */ char *tab2space(const char *tabstr) { char *spacestr; int tabstr_len = strlen(tabstr); int i, j; int tabcount = 0; for (i = 0; i < tabstr_len; i++) { if (tabstr[i] == '\t') { tabcount++; } } spacestr = uim_malloc((tabstr_len - tabcount) + (TAB_WIDTH * tabcount) + 1); for (i = 0, j = 0; i < tabstr_len + 1; i++, j++) { if (tabstr[i] == '\t') { int i2; for (i2 = 0; i2 < TAB_WIDTH; i2++, j++) { spacestr[j] = ' '; } j--; } else { spacestr[j] = tabstr[i]; } } return spacestr; }
/* add context to context list */ uim_agent_context * new_uim_agent_context(int id, const char *encoding) { uim_agent_context_list *ptr; debug_printf(DEBUG_NOTE, "add_uim_agent_context(%d)\n", id); ptr = uim_malloc(sizeof(uim_agent_context_list)); ptr->agent_context = create_uim_agent_context(encoding); ptr->next = NULL; ptr->prev = NULL; ptr->agent_context->context_id = id; if (agent_context_list_tail != NULL) { agent_context_list_tail->next = ptr; ptr->prev = agent_context_list_tail; } agent_context_list_tail = ptr; if (agent_context_list_head == NULL) agent_context_list_head = ptr; return ptr->agent_context; }
static uim_lisp c_execvp(uim_lisp file_, uim_lisp argv_) { char **argv; int i; int len = uim_scm_length(argv_); uim_lisp ret_; if (len < 1) return uim_scm_f(); argv = uim_malloc(sizeof(char *) * (len + 1)); for (i = 0; i < len; i++) { argv[i] = uim_strdup(REFER_C_STR(CAR(argv_))); argv_ = CDR(argv_); } argv[len] = NULL; ret_ = MAKE_INT(execvp(REFER_C_STR(file_), argv)); for (i = 0; i < len; i++) free(argv[i]); free(argv); return ret_; }
static uim_lisp get_nth_candidate(uim_lisp ac_, uim_lisp seg_, uim_lisp nth_) { anthy_context_t ac; int seg, nth, buflen; char *buf; uim_lisp buf_; ac = get_anthy_context(ac_); seg = C_INT(seg_); nth = C_INT(nth_); buflen = anthy_get_segment(ac, seg, nth, NULL, 0); if (buflen == -1) uim_fatal_error("anthy_get_segment() failed"); buf = uim_malloc(buflen + 1); buflen = anthy_get_segment(ac, seg, nth, buf, buflen + 1); if (buflen == -1) { free(buf); uim_fatal_error("anthy_get_segment() failed"); } buf_ = MAKE_STR_DIRECTLY(buf); return buf_; }
void add_preedit(preedit *pe, int attr, const char *str) { preedit_buffer *pb; pe->valid = 1; pb = uim_malloc(sizeof(preedit_buffer)); if (pe->head == NULL) { pe->head = pb; pe->tail = pb; } else { pe->tail->next = pb; pe->tail = pb; } if (strlen(str) > 0) { pb->str = uim_strdup(str); pe->length += strlen(str); } else { pb->str = NULL; } pb->attr = attr; pb->next = NULL; }
static size_t uim_curl_write_func(void *ptr, size_t size, size_t nmemb, void *data) { struct curl_memory_struct *mem = (struct curl_memory_struct *)data; size_t realsize = size * nmemb; /* * We know that it isn't possible to overflow during multiplication if * neither operand uses any of the most significant half of the bits in * a size_t. */ if((unsigned long long)((nmemb | size) & ((unsigned long long)SIZE_MAX << (sizeof(size_t) << 2))) && (realsize / size != nmemb)) return 0; if(SIZE_MAX - mem->size - 1 < realsize) realsize = SIZE_MAX - mem->size - 1; if(mem->str != NULL) mem->str = uim_realloc(mem->str, mem->size + realsize + 1); else mem->str = uim_malloc(realsize + 1); if(mem->str != NULL) { memcpy(&(mem->str[mem->size]), ptr, realsize); mem->size += realsize; mem->str[mem->size] = '\0'; } return realsize; }
static void * uim_iconv_open(const char *tocode, const char *fromcode) { iconv_t cd = (iconv_t)-1; int i, j; const char **alias_tocode, **alias_fromcode; int alias_tocode_alloced = 0; int alias_fromcode_alloced = 0; int opened = 0; assert(tocode); assert(fromcode); alias_tocode = uim_get_encoding_alias(tocode); alias_fromcode = uim_get_encoding_alias(fromcode); if (!alias_tocode) { alias_tocode = uim_malloc(sizeof(char *) * 2); alias_tocode[0] = tocode; alias_tocode[1] = NULL; alias_tocode_alloced = 1; } if (!alias_fromcode) { alias_fromcode = uim_malloc(sizeof(char *) * 2); alias_fromcode[0] = fromcode; alias_fromcode[1] = NULL; alias_fromcode_alloced = 1; } for (i = 0; alias_tocode[i]; i++) { for (j = 0; alias_fromcode[j]; j++) { cd = iconv_open(alias_tocode[i], alias_fromcode[j]); if (cd != (iconv_t)-1) { opened = 1; break; } } if (opened) break; } if (alias_tocode_alloced) free(alias_tocode); if (alias_fromcode_alloced) free(alias_fromcode); return (void *)cd; }
static uim_lisp c_make_addrinfo() { struct addrinfo *addrinfo = uim_malloc(sizeof(struct addrinfo)); memset(addrinfo, 0, sizeof(struct addrinfo)); return MAKE_PTR(addrinfo); }
static int check_encoding_equivalence(const char *tocode, const char *fromcode) { const char **alias_tocode; const char **alias_fromcode; int i, j; int alias_tocode_alloced = 0; int alias_fromcode_alloced = 0; int found = 0; assert(tocode); assert(fromcode); alias_tocode = uim_get_encoding_alias(tocode); alias_fromcode = uim_get_encoding_alias(fromcode); if (!alias_tocode) { alias_tocode = uim_malloc(sizeof(char *) * 2); alias_tocode[0] = tocode; alias_tocode[1] = NULL; alias_tocode_alloced = 1; } if (!alias_fromcode) { alias_fromcode = uim_malloc(sizeof(char *) * 2); alias_fromcode[0] = fromcode; alias_fromcode[1] = NULL; alias_fromcode_alloced = 1; } for (i = 0; alias_tocode[i]; i++) { for (j = 0; alias_fromcode[j]; j++) { if (!strcmp(alias_tocode[i], alias_fromcode[j])) { found = 1; break; } } if (found) break; } if (alias_tocode_alloced) free(alias_tocode); if (alias_fromcode_alloced) free(alias_fromcode); return found; }
static uim_lisp c_make_sockaddr_un(void) { struct sockaddr_un *s_un; s_un = uim_malloc(sizeof(struct sockaddr_un)); memset(s_un, 0, sizeof(struct sockaddr_un)); return MAKE_PTR(s_un); }
preedit * create_preedit() { preedit *pe; pe = uim_malloc(sizeof(preedit)); pe->valid = 0; pe->head = pe->tail = NULL; return pe; }
candidate_info * create_candidate() { candidate_info *cand; cand = uim_malloc(sizeof(candidate_info)); cand->valid = 0; return cand; }
property * create_prop() { property *prop; prop = uim_malloc(sizeof(property)); prop->valid = 0; prop->list = NULL; prop->list_update = 0; return prop; }
static int byte2width2(char *str, int n) { int width; int str_byte; char save_char; char *save_str; wchar_t *wcstr; int nr_wchars; assert(str != NULL); if (n <= 0) { return 0; } str_byte = strlen(str); if (str_byte == 0) { return 0; } if (n > str_byte) { n = str_byte; } wcstr = uim_malloc(sizeof(wchar_t) * str_byte); save_str = str; save_char = str[n]; str[n] = '\0'; nr_wchars = mbsrtowcs(wcstr, (const char **)&str, str_byte, NULL); save_str[n] = save_char; if ((size_t)nr_wchars != (size_t)(-1)) { width = wcswidth(wcstr, nr_wchars); } else { mbsrtowcs(wcstr, (const char **)&str, 1, NULL); /* strを最後まで変換するとNULLになる */ assert(str != NULL); save_char = str[0]; str[0] = '\0'; width = strwidth(save_str); str[0] = save_char; } free(wcstr); assert(width >= 0); return width; }
static void xml_characterdata_handler(void *userData, const XML_Char *s, int len) { uim_xml_userdata *data = (uim_xml_userdata *)userData; char *str = uim_malloc(len + 1); memcpy(str, s, len); str[len] = '\0'; if (data && data->characterdata_) { uim_scm_call(data->characterdata_, LIST1(MAKE_STR(str))); } free(str); }
static uim_lisp c_file_write(uim_lisp d_, uim_lisp buf_) { int nbytes = uim_scm_length(buf_); uim_lisp ret_; unsigned char *buf; unsigned char *p; buf = p = uim_malloc(nbytes); while (!NULLP(buf_)) { *p = C_CHAR(CAR(buf_)); p++; buf_ = CDR(buf_); } ret_ = MAKE_INT((int)write(C_INT(d_), buf, nbytes)); free(buf); return ret_; }
static int str2wcstr(const char *str, wchar_t **wcstr) { int str_byte; int nr_wchars; assert(str != NULL); str_byte = strlen(str); if (str_byte == 0) { *wcstr = NULL; return 0; } *wcstr = uim_malloc(sizeof(wchar_t) * (str_byte + 1)); nr_wchars = mbstowcs(*wcstr, str, str_byte); assert((size_t)nr_wchars != (size_t)-1); (*wcstr)[str_byte] = 0; return nr_wchars; }
int new_candidate(uim_context context, candidate_info *cand, int num, int limit) { int i; #if !UIM_EL_USE_NEW_PAGE_HANDLING uim_candidate u_cand; #endif if (cand->valid) clear_candidate(cand); cand->valid = 1; cand->index = -1; cand->disp_limit = limit; cand->num = num; #if UIM_EL_USE_NEW_PAGE_HANDLING cand->page_index = 0; #endif cand->cand_array = uim_malloc(sizeof(candidate) * num); #if !UIM_EL_USE_NEW_PAGE_HANDLING /* get candidates from context */ for (i = 0; i < num; i ++) { u_cand = uim_get_candidate(context, i, limit ? i % limit : i); cand->cand_array[i].str = uim_strdup(uim_candidate_get_cand_str(u_cand)); cand->cand_array[i].label = uim_strdup(uim_candidate_get_heading_label(u_cand)); uim_candidate_free(u_cand); } #else for (i = 0; i < num; i++) { cand->cand_array[i].str = NULL; cand->cand_array[i].label = NULL; } set_page_candidates(context, cand); #endif return 1; }
static int uim_eb_strappend(char **dest, const char *append, size_t append_len) { if (*dest) { char *str; size_t dest_len = strlen(*dest); size_t len = dest_len + append_len; str = uim_realloc(*dest, len + 1); memcpy(&str[dest_len], append, append_len); str[len] = '\0'; *dest = str; } else { char *str; str = uim_malloc(append_len + 1); memcpy(str, append, append_len); str[append_len] = '\0'; *dest = str; } return 1; }
static uim_lisp c_file_read(uim_lisp d_, uim_lisp nbytes_) { unsigned char *buf; uim_lisp ret_; int nbytes = C_INT(nbytes_); int nr; struct c_file_read_args args; buf = uim_malloc(nbytes); if ((nr = read(C_INT(d_), buf, nbytes)) == 0) return uim_scm_eof(); if (nr < 0) return uim_scm_f(); args.buf = buf; args.nr = nr; ret_ = (uim_lisp)uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)c_file_read_internal, (void *)&args); free(buf); return uim_scm_callf("reverse", "o", ret_); }
/* * escseqから/$<\d+>/を取り除いたものを返す * escseqがNULLだったらNULLを返す */ char *cut_padding(const char *escseq) { int i, j; char *cut_str; if (escseq == NULL) { return NULL; } cut_str = uim_malloc(strlen(escseq) + 1); for (i = 0, j = 0; escseq[i] != '\0';) { if (escseq[i] == '$' && escseq[i + 1] == '<') { int i2 = i + 1; while (isdigit((unsigned char)escseq[++i2])); if (escseq[i2] == '>') { i = i2 + 1; if (escseq[i] == '\0') { break; } } } cut_str[j++] = escseq[i++]; } cut_str[j] = '\0'; return cut_str; }
static uim_lisp uim_xml_parser_create(uim_lisp encoding_) { uim_xml_ctx *ctx; const XML_Char *encoding = REFER_C_STR(encoding_); XML_Parser parser; parser = XML_ParserCreate(encoding); if (parser) { XML_SetElementHandler(parser, xml_start_element_handler, xml_end_element_handler); XML_SetCharacterDataHandler(parser, xml_characterdata_handler); } ctx = uim_calloc(1, sizeof(uim_xml_ctx *)); ctx->parser = parser; ctx->data = uim_malloc(sizeof(uim_xml_userdata *)); ctx->data->start_ = NULL; ctx->data->end_ = NULL; ctx->data->characterdata_ = NULL; return MAKE_PTR(ctx); }
static uim_lisp c_ffi_call(uim_lisp result_, uim_lisp fun_, uim_lisp argv_) { ffi_cif cif; ffi_type **arg_types; void **arg_values; ffi_status status; ffi_type *result_type = NULL; void *result; int args; int i; void *p; uim_lisp ret_; object_type return_object_type; int input_void = 0; args = uim_scm_length(argv_); arg_types = uim_malloc(args * sizeof(void *)); arg_values = uim_malloc(args * sizeof(ffi_type *)); return_object_type = select_object_type(result_); switch (return_object_type) { case RET_UNKNOWN: break; case RET_VOID: result_type = &ffi_type_void; break; case RET_UCHAR: result_type = &ffi_type_uchar; break; case RET_SCHAR: result_type = &ffi_type_schar; break; case RET_USHORT: result_type = &ffi_type_ushort; break; case RET_SSHORT: result_type = &ffi_type_sshort; break; case RET_ULONG: result_type = &ffi_type_ulong; break; case RET_SLONG: result_type = &ffi_type_slong; break; case RET_UINT: result_type = &ffi_type_uint; break; case RET_SINT: result_type = &ffi_type_sint; break; case RET_FLOAT: result_type = &ffi_type_float; break; case RET_DOUBLE: result_type = &ffi_type_double; break; case RET_STR: result_type = &ffi_type_pointer; break; case RET_PTR: result_type = &ffi_type_pointer; break; case RET_SCM: result_type = &ffi_type_pointer; break; } result = uim_malloc(1024); /* huge? */ for (i = 0; i < args; i++) { uim_lisp arg_ = CAR(argv_); switch (select_object_type(CAR(arg_))) { case RET_UNKNOWN: break; case RET_VOID: input_void = 1; break; case RET_UCHAR: p = uim_malloc(sizeof(unsigned char)); *((unsigned char *)p) = C_CHAR(CDR(arg_)); arg_types[i] = &ffi_type_uchar; arg_values[i] = p; break; case RET_SCHAR: p = uim_malloc(sizeof(signed char)); *((signed char *)p) = C_CHAR(CDR(arg_)); arg_types[i] = &ffi_type_schar; arg_values[i] = p; break; case RET_USHORT: p = uim_malloc(sizeof(unsigned short)); *((unsigned short *)p) = C_INT(CDR(arg_)); arg_types[i] = &ffi_type_ushort; arg_values[i] = p; break; case RET_SSHORT: p = uim_malloc(sizeof(unsigned short)); *((signed short *)p) = C_INT(CDR(arg_)); arg_types[i] = &ffi_type_sshort; arg_values[i] = p; break; case RET_UINT: p = uim_malloc(sizeof(unsigned int)); *((unsigned int *)p) = C_INT(CDR(arg_)); arg_types[i] = &ffi_type_uint; arg_values[i] = p; break; case RET_SINT: p = uim_malloc(sizeof(signed int)); *((signed int *)p) = C_INT(CDR(arg_)); arg_types[i] = &ffi_type_sint; arg_values[i] = p; break; case RET_ULONG: p = uim_malloc(sizeof(unsigned long)); *((unsigned long *)p) = C_INT(CDR(arg_)); arg_types[i] = &ffi_type_ulong; arg_values[i] = p; break; case RET_SLONG: p = uim_malloc(sizeof(signed long)); *((signed long *)p) = C_INT(CDR(arg_)); arg_types[i] = &ffi_type_slong; arg_values[i] = p; break; case RET_FLOAT: { char *endptr; p = uim_malloc(sizeof(float)); *((double *)p) = strtof(REFER_C_STR(CDR(arg_)), &endptr); arg_types[i] = &ffi_type_float; arg_values[i] = p; } break; case RET_DOUBLE: { char *endptr; p = uim_malloc(sizeof(double)); *((double *)p) = strtod(REFER_C_STR(CDR(arg_)), &endptr); arg_types[i] = &ffi_type_double; arg_values[i] = p; } break; case RET_STR: p = uim_malloc(sizeof(void *)); *((void **)p) = (void *)REFER_C_STR(CDR(arg_)); arg_types[i] = &ffi_type_pointer; arg_values[i] = p; break; case RET_PTR: p = uim_malloc(sizeof(void *)); if (NULLP(CDR(arg_))) *((void **)p) = NULL; else *((void **)p) = C_PTR(CDR(arg_)); arg_types[i] = &ffi_type_pointer; arg_values[i] = p; break; case RET_SCM: p = uim_malloc(sizeof(void *)); *((void **)p) = CDR(arg_); arg_types[i] = &ffi_type_pointer; arg_values[i] = p; } argv_ = CDR(argv_); } if (input_void) args = 0; status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, args, result_type, arg_types); switch (status) { case FFI_OK: break; case FFI_BAD_TYPEDEF: ffi_strerr_ = ffi_strerr_messages[FFI_STRERR_BAD_TYPEDEF]; break; case FFI_BAD_ABI: ffi_strerr_ = ffi_strerr_messages[FFI_STRERR_BAD_ABI]; break; default: ffi_strerr_ = ffi_strerr_messages[FFI_STRERR_UNKOWN]; } if (status == FFI_OK) ffi_call(&cif, (void (*)(void))C_PTR(fun_), result, arg_values); for (i = 0; i < args; i++) free(arg_values[i]); free(arg_types); free(arg_values); if (status != FFI_OK) { free(result); return uim_scm_f(); } ret_ = uim_scm_f(); switch (return_object_type) { case RET_UNKNOWN: case RET_VOID: break; case RET_UCHAR: ret_ = MAKE_CHAR(*(unsigned char *)result); break; case RET_SCHAR: ret_ = MAKE_CHAR(*(signed char *)result); break; case RET_USHORT: ret_ = MAKE_INT(*(unsigned short *)result); break; case RET_SSHORT: ret_ = MAKE_INT(*(signed short *)result); break; case RET_UINT: ret_ = MAKE_INT(*(unsigned int *)result); break; case RET_SINT: ret_ = MAKE_INT(*(signed int *)result); break; case RET_ULONG: ret_ = MAKE_INT(*(unsigned long *)result); break; case RET_SLONG: ret_ = MAKE_INT(*(signed long *)result); break; case RET_FLOAT: { char str[1024]; snprintf(str, sizeof(str), "%f", *((float *)result)); ret_ = MAKE_STR(str); } break; case RET_DOUBLE: { char str[1024]; snprintf(str, sizeof(str), "%f", *((double *)result)); ret_ = MAKE_STR(str); } break; case RET_STR: ret_ = MAKE_STR(*((char **)result)); break; case RET_PTR: ret_ = MAKE_PTR(*((void **)result)); break; case RET_SCM: ret_ = *(uim_lisp *)result; break; } free(result); ffi_strerr_ = NULL; return ret_; }