/* variable_new_copy */ Variable * variable_new_copy(Variable * variable) { switch(variable->type) { case VT_NULL: case VT_BOOL: case VT_INT8: case VT_UINT8: case VT_INT16: case VT_UINT16: case VT_INT32: case VT_UINT32: case VT_INT64: case VT_UINT64: case VT_FLOAT: case VT_DOUBLE: return variable_new(variable->type, &variable->u); case VT_STRING: return variable_new(variable->type, variable->u.string); case VT_BUFFER: return variable_new(variable->type, variable->u.buffer); } error_set_code(1, "%s", "Unable to copy this type of variable"); return NULL; }
/* main */ int main(void) { int ret; Variable * res; float f = 1.0; double d = 1.0; /* VT_FLOAT */ if((res = variable_new(VT_FLOAT, &f)) == NULL) return 2; if((ret = marshall_call(res, (MarshallCallback)_callf_float, 1, &res)) == 0) ret = variable_get_as(res, VT_FLOAT, &f); variable_delete(res); if(ret != 0) return 3; if(f + 1.0 != (float)M_PI) return 4; /* VT_DOUBLE */ if((res = variable_new(VT_DOUBLE, &d)) == NULL) return 5; if((ret = marshall_call(res, (MarshallCallback)_callf_double, 1, &res)) == 0) ret = variable_get_as(res, VT_DOUBLE, &d); variable_delete(res); if(ret != 0) return 6; if(d + 1.0 != M_PI) return 7; return 0; }
/* creates new variable with internal name */ variable *variable_new2(gchar *name, gchar *internal, variable_type vt) { variable *var = variable_new(name, vt); g_string_assign(var->internal, internal); return var; }
/* * add new watch */ variable* add_watch(gchar* expression) { gchar command[1000]; variable *var = variable_new(expression, VT_WATCH); watches = g_list_append(watches, var); /* try to create a variable */ gchar *record = NULL; gchar *escaped = g_strescape(expression, NULL); sprintf(command, "-var-create - * \"%s\"", escaped); g_free(escaped); if (RC_DONE != exec_sync_command(command, TRUE, &record)) { g_free(record); return var; } gchar *pos = strstr(record, "name=\"") + strlen("name=\""); *strchr(pos, '\"') = '\0'; g_string_assign(var->internal, pos); var->evaluated = TRUE; GList *vars = g_list_append(NULL, var); get_variables(vars); g_free(record); g_list_free(vars); return var; }
static int _serialize_call(AppMessage * message, Buffer * buffer, Buffer * b) { int ret; Variable * v; size_t i; if(_serialize_id(message, buffer, b) != 0) return -1; if((v = variable_new(VT_STRING, message->t.call.method)) == NULL) return -1; ret = (variable_serialize(v, b, 0) == 0 && _serialize_append(buffer, b) == 0) ? 0 : -1; variable_delete(v); if(ret != 0) return ret; for(i = 0; i < message->t.call.args_cnt; i++) { if(message->t.call.args[i].direction == AMCD_OUT) continue; if(variable_serialize(message->t.call.args[i].arg, b, 1) != 0 || _serialize_append(buffer, b) != 0) break; } buffer_delete(b); return (i == message->t.call.args_cnt) ? 0 : -1; }
struct variable* variable_copy(struct context *context, const struct variable* v) { // DEBUGPRINT("variable_copy"); vm_null_check(context, v); struct variable *u = variable_new(context, (enum VarType)v->type); variable_set(context, u, v); return u; }
/* main */ int main(void) { int ret = 0; size_t i; const size_t count = 10; Variable ** args; int32_t i32; Variable * res; i32 = 0; if((res = variable_new(VT_INT32, &i32)) == NULL) return 2; if((args = malloc(sizeof(*args) * count)) == NULL) { variable_delete(res); return 2; } for(i = 0; i < count; i++) { i32 = i * 1111; if((args[i] = variable_new(VT_INT32, &i32)) == NULL) ret = 3; } for(i = 0; ret == 0 && i < count; i++) { i32 = i; if(variable_set_from(args[0], VT_INT32, &i32) != 0) ret = i + 4; else if(marshall_call(res, (MarshallCallback)_calln, i + 1, args) != 0) ret = i + 4; else if(variable_get_as(res, VT_INT32, &i32) != 0 || i32 != 0) ret = i + 4; } for(i = 0; i < count; i++) if(args[i] != NULL) variable_delete(args[i]); variable_delete(res); free(args); return ret; }
static int _serialize_type(AppMessage * message, Buffer * buffer, Buffer * b) { int ret; Variable * v; if((v = variable_new(VT_UINT8, &message->type)) == NULL) return -1; ret = (variable_serialize(v, b, 0) == 0 && _serialize_append(buffer, b) == 0) ? 0 : -1; variable_delete(v); return ret; }
void varlist_set_value(VARLIST * v, gchar * name, gchar * value) { // remove old value varlist_remove_value(v, name); // set new value VARIABLE * var = variable_new(name); variable_set_value(var, value); g_tree_insert(v->tree, strdup(name), var); // update status variables and gauges, if need be if (!v->sess) return; svlist_handle_variable_change ((SVLIST *) v->sess->svlist, name); gaugelist_handle_variable_change ((GAUGELIST *) v->sess->gaugelist, name); }
JBVariable * ensure_variable (JBVariableType *type, const char *name) { JBVariable *variable; g_return_val_if_fail(name != NULL, NULL); variable = jb_variable_get_variable(name); if (variable == NULL) { variable = variable_new(type, name, NULL, NULL, 0); add_variable(variable); } return variable; }
/* ssl_socket_queue */ static int _ssl_socket_queue(SSLSocket * sslsocket, Buffer * buffer) { uint32_t len; char * p; Variable * v; Buffer * b = NULL; #ifdef DEBUG fprintf(stderr, "DEBUG: %s(%d)\n", __func__, sslsocket->fd); #endif /* serialize the buffer */ v = variable_new(VT_BUFFER, buffer); b = buffer_new(0, NULL); if(v == NULL || b == NULL || variable_serialize(v, b, 0) != 0) { if(v != NULL) variable_delete(v); if(b != NULL) buffer_delete(b); return -1; } variable_delete(v); len = buffer_get_size(b); /* FIXME queue the serialized buffer directly as a message instead */ if((p = realloc(sslsocket->bufout, sslsocket->bufout_cnt + len)) == NULL) { buffer_delete(b); return -1; } sslsocket->bufout = p; memcpy(&p[sslsocket->bufout_cnt], buffer_get_data(b), len); /* register the callback if necessary */ if(sslsocket->bufout_cnt == 0) event_register_io_write(sslsocket->transport->helper->event, sslsocket->fd, (EventIOFunc)_ssl_socket_callback_write, sslsocket); sslsocket->bufout_cnt += len; buffer_delete(b); #ifdef DEBUG fprintf(stderr, "DEBUG: %s(%d) => %d\n", __func__, sslsocket->fd, 0); #endif return 0; }
JBVariable * jb_variable_add (JBVariableType *type, const char *name, const char *description, JBVariableGroup *group, JBVariableFlags flags) { JBVariable *variable; g_return_val_if_fail(type != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); variable = variable_new(type, name, description, group, flags | JB_VARIABLE_USER_SETTABLE); add_variable(variable); return variable; }
int variable_update(struct category *cat, const char *variable, const char *value) { struct variable *curr, *prev = NULL, *var; if (cat == NULL) return -1; for (curr = cat->first; curr; prev = curr, curr = curr->next) { if (strcasecmp(curr->name, variable)) continue; if ((var = variable_new(variable, value, curr->file, curr->lineno)) == NULL) return -1; var->next = curr->next; if (prev == NULL) cat->first = var; else prev->next = var; if (cat->last == curr) cat->last = var; variable_destroy(curr); return 0; } return -1; }
/* * updates autos list */ void update_autos() { gchar command[1000]; /* remove all previous GDB variables for autos */ GList *iter = autos; while (iter) { variable *var = (variable*)iter->data; sprintf(command, "-var-delete %s", var->internal->str); exec_sync_command(command, TRUE, NULL); iter = iter->next; } g_list_foreach(autos, (GFunc)variable_free, NULL); g_list_free(autos); autos = NULL; /* add current autos to the list */ GList *unevaluated = NULL; const char *gdb_commands[] = { "-stack-list-arguments 0 0 0", "-stack-list-locals 0" }; int i, size = sizeof (gdb_commands) / sizeof(char*); for (i = 0; i < size; i++) { gchar *record = NULL; result_class rc = exec_sync_command(gdb_commands[i], TRUE, &record); if (RC_DONE != rc) break; gchar *pos = record; while ((pos = strstr(pos, "name=\""))) { pos += strlen("name=\""); *(strchr(pos, '\"')) = '\0'; variable *var = variable_new(pos, i ? VT_LOCAL : VT_ARGUMENT); /* create new gdb variable */ gchar *create_record = NULL; gchar *escaped = g_strescape(pos, NULL); sprintf(command, "-var-create - * \"%s\"", escaped); g_free(escaped); /* form new variable */ if (RC_DONE == exec_sync_command(command, TRUE, &create_record)) { gchar *intname = strstr(create_record, "name=\"") + strlen ("name=\""); *strchr(intname, '\"') = '\0'; var->evaluated = TRUE; g_string_assign(var->internal, intname); autos = g_list_append(autos, var); g_free(create_record); } else { var->evaluated = FALSE; g_string_assign(var->internal, ""); unevaluated = g_list_append(unevaluated, var); } pos += strlen(pos) + 1; } g_free(record); } /* get values for the autos (without incorrect variables) */ get_variables(autos); /* add incorrect variables */ autos = g_list_concat(autos, unevaluated); }
static int process_text_line(char *buf, struct category **cat, struct config *cfg, int lineno, const char *configfile) { char *curr = buf, *c; /* a category header */ if (curr[0] == '[') { if ((c = strchr(curr, ']')) == NULL) { xcb_log(XCB_LOG_WARNING, "no closing ']', line %d of '%s'", lineno, configfile); return -1; } *c = '\0'; ++curr; /* FIXME */ if ((*cat = category_new(curr, cfg->include_level == 1 ? "" : configfile, lineno)) == NULL) return -1; category_append(cfg, *cat); /* directive #include */ } else if (curr[0] == '#') { ++curr; c = curr; while (*c && *c > 32) ++c; if (*c) { *c = '\0'; c = strip(c + 1); if (*c == '\0') c = NULL; } else c = NULL; if (strcasecmp(curr, "include")) { xcb_log(XCB_LOG_WARNING, "Unknown directive '#%s' at line %d of %s", curr, lineno, configfile); return 0; } if (c == NULL) { xcb_log(XCB_LOG_WARNING, "Directive '#include' needs an argument (filename)" "at line %d of %s", lineno, configfile); return 0; } curr = c; if (*c == '"' || *c == '<') { char quote_char = *c; if (quote_char == '<') quote_char = '>'; if (*(c + strlen(c) - 1) == quote_char) { ++curr; *(c + strlen(c) - 1) = '\0'; } } /* FIXME */ config_include_new(cfg, curr); if (config_internal_load(curr, cfg) == NULL) return -1; /* just a line (variable = value) */ } else { struct variable *var; if (*cat == NULL) { xcb_log(XCB_LOG_WARNING, "no category context for line %d of '%s'", lineno, configfile); return -1; } if ((c = strchr(curr, '=')) == NULL) { xcb_log(XCB_LOG_WARNING, "no '=' (equal sign) in line %d of '%s'", lineno, configfile); return -1; } *c++ = '\0'; /* FIXME */ if ((var = variable_new(strip(curr), strip(c), cfg->include_level == 1 ? "" : configfile, lineno)) == NULL) return -1; variable_append(*cat, var); } return 0; }
/* * starts gdb, collects commands and start the first one */ gboolean run(const gchar* file, const gchar* commandline, GList* env, GList *witer, GList *biter, const gchar* terminal_device, dbg_callbacks* callbacks) { GError *err = NULL; dbg_cbs = callbacks; /* spawn GDB */ const gchar *exclude[] = { "LANG", NULL }; gchar **gdb_env = utils_copy_environment(exclude, "LANG", "C", NULL); if (!g_spawn_async_with_pipes(NULL, (gchar**)gdb_args, gdb_env, GDB_SPAWN_FLAGS, NULL, NULL, &gdb_pid, &gdb_in, &gdb_out, NULL, &err)) { dbg_cbs->report_error(_("Failed to spawn gdb process")); return FALSE; } g_strfreev(gdb_env); /* move gdb to it's own process group */ setpgid(gdb_pid, 0); /* set handler for gdb process exit event */ g_child_watch_add(gdb_pid, on_gdb_exit, NULL); gdb_src = g_child_watch_source_new(gdb_pid); /* create GDB GIO chanels */ gdb_ch_in = g_io_channel_unix_new(gdb_in); gdb_ch_out = g_io_channel_unix_new(gdb_out); /* reading starting gdb messages */ GList *lines = read_until_prompt(); GList *line = lines; while (line) { gchar *unescaped = g_strcompress((gchar*)line->data); if (strlen(unescaped)) { colorize_message((gchar*)line->data); } line = line->next; } g_list_foreach(lines, (GFunc)g_free, NULL); g_list_free(lines); /* add initial watches to the list */ while (witer) { gchar *name = (gchar*)witer->data; variable *var = variable_new(name, VT_WATCH); watches = g_list_append(watches, var); witer = witer->next; } /* collect commands */ GList *commands = NULL; /* loading file */ GString *command = g_string_new(""); g_string_printf(command, "-file-exec-and-symbols %s", file); commands = add_to_queue(commands, _("~\"Loading target file ...\""), command->str, _("Error loading file"), FALSE); g_string_free(command, TRUE); /* setting asyncronous mode */ commands = add_to_queue(commands, NULL, "-gdb-set target-async 1", _("Error configuring GDB"), FALSE); /* setting null-stop array printing */ commands = add_to_queue(commands, NULL, "-interpreter-exec console \"set print null-stop\"", _("Error configuring GDB"), FALSE); /* enable pretty printing */ commands = add_to_queue(commands, NULL, "-enable-pretty-printing", _("Error configuring GDB"), FALSE); /* set locale */ command = g_string_new(""); g_string_printf(command, "-gdb-set environment LANG=%s", g_getenv("LANG")); commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); g_string_free(command, TRUE); /* set arguments */ command = g_string_new(""); g_string_printf(command, "-exec-arguments %s", commandline); commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); g_string_free(command, TRUE); /* set passed evironment */ GList *iter = env; while (iter) { gchar *name = (gchar*)iter->data; iter = iter->next; gchar *value = (gchar*)iter->data; command = g_string_new(""); g_string_printf(command, "-gdb-set environment %s=%s", name, value); commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); g_string_free(command, TRUE); iter = iter->next; } /* set breaks */ int bp_index = 1; while (biter) { breakpoint *bp = (breakpoint*)biter->data; command = g_string_new(""); g_string_printf(command, "-break-insert -f %s:%i", bp->file, bp->line); GString *error_message = g_string_new(""); g_string_printf(error_message, _("Breakpoint at %s:%i cannot be set\nDebugger message: %s"), bp->file, bp->line, "%s"); commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); g_string_free(command, TRUE); g_string_free(error_message, TRUE); if (bp->hitscount) { command = g_string_new(""); g_string_printf(command, "-break-after %i %i", bp_index, bp->hitscount); commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); g_string_free(command, TRUE); } if (strlen(bp->condition)) { command = g_string_new(""); g_string_printf (command, "-break-condition %i %s", bp_index, bp->condition); commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); g_string_free(command, TRUE); } if (!bp->enabled) { command = g_string_new(""); g_string_printf (command, "-break-disable %i", bp_index); commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); g_string_free(command, TRUE); } bp_index++; biter = biter->next; } /* set debugging terminal */ command = g_string_new("-inferior-tty-set "); g_string_append(command, terminal_device); commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); g_string_free(command, TRUE); /* connect read callback to the output chanel */ gdb_id_out = g_io_add_watch(gdb_ch_out, G_IO_IN, on_read_async_output, commands); queue_item *item = (queue_item*)commands->data; /* send message to debugger messages window */ if (item->message) { dbg_cbs->send_message(item->message->str, "grey"); } /* send first command */ gdb_input_write_line(item->command->str); return TRUE; }
/* variable_new_deserialize_type */ Variable * variable_new_deserialize_type(VariableType type, size_t * size, char const * data) { Variable * v; size_t s; uint8_t u8; int16_t i16; int32_t i32; uint32_t u32; int64_t i64; float f; double d; Buffer * b = NULL; void * p = (char *)data; #ifdef DEBUG fprintf(stderr, "DEBUG: %s(%u, %lu, %p)\n", __func__, type, *size, (void *)data); #endif /* estimate the size required */ s = (type < sizeof(_variable_sizes) / sizeof(*_variable_sizes)) ? _variable_sizes[type] : 0; switch(type) { case VT_NULL: break; case VT_BOOL: p = (char *)&u8; break; case VT_INT8: case VT_UINT8: break; case VT_INT16: case VT_UINT16: p = (char *)&i16; break; case VT_INT32: case VT_UINT32: p = (char *)&i32; break; case VT_INT64: case VT_UINT64: p = (char *)&i64; break; case VT_BUFFER: if(*size < s) break; memcpy(&u32, data, s); u32 = ntohl(u32); s += u32; break; case VT_FLOAT: case VT_DOUBLE: case VT_STRING: for(s = 0; s < *size; s++) if(data[s] != '\0') continue; else if((p = malloc(++s)) == NULL) { error_set_code(-errno, "%s", strerror(errno)); return NULL; } else break; break; default: error_set_code(1, "Unable to deserialize type %u", type); return NULL; } if(*size < s) { *size = s; error_set_code(1, "More data needed to deserialize type %u", type); return NULL; } *size = s; if(p != data) memcpy(p, data, s); /* convert the data if necessary */ switch(type) { case VT_NULL: break; case VT_BOOL: u8 = u8 ? 1 : 0; break; case VT_INT8: case VT_UINT8: break; case VT_INT16: case VT_UINT16: i16 = ntohs(i16); break; case VT_INT32: case VT_UINT32: i32 = ntohl(i32); break; case VT_FLOAT: i32 = sscanf(p, "%e", &f); free(p); if(i32 != 1) { error_set_code(1, "Invalid float value", type); return NULL; } p = &f; break; case VT_DOUBLE: i32 = sscanf(p, "%le", &d); free(p); if(i32 != 1) { error_set_code(1, "Invalid double value", type); return NULL; } p = &d; break; case VT_STRING: break; case VT_INT64: case VT_UINT64: /* FIXME need to be converted */ break; case VT_BUFFER: if((b = buffer_new(s - sizeof(u32), &data[sizeof(u32)])) == NULL) return NULL; p = b; break; default: error_set_code(1, "Unable to deserialize type %u", type); return NULL; } v = variable_new(type, p); if(b != NULL) buffer_delete(b); return v; }
model* model_create(enkfprm* prm) { model* m = calloc(1, sizeof(model)); char* modelprm = prm->modelprm; char* gridprm = prm->gridprm; model_setgrids(m, gridprm); /* * read model parameter file */ { FILE* f = NULL; char buf[MAXSTRLEN]; int line; variable* now = NULL; /* * get model tag, type and variables */ f = enkf_fopen(modelprm, "r"); line = 0; while (fgets(buf, MAXSTRLEN, f) != NULL) { char seps[] = " =\t\n"; char* token = NULL; line++; if (buf[0] == '#') continue; if ((token = strtok(buf, seps)) == NULL) continue; if (strcasecmp(token, "NAME") == 0) { if ((token = strtok(NULL, seps)) == NULL) enkf_quit("%s, l.%d: NAME not specified", modelprm, line); else if (m->name != NULL) enkf_quit("%s, l.%d: NAME specified twice", modelprm, line); else m->name = strdup(token); } else if (strncasecmp(token, "VAR", 3) == 0) { int i; if ((token = strtok(NULL, seps)) == NULL) enkf_quit("%s, l.%d: VAR not specified", modelprm, line); for (i = 0; i < m->nvar; ++i) if (strcasecmp(m->vars[i].name, token) == 0) enkf_quit("%s, l.%d: VAR \"%s\" already specified", modelprm, line, token); if (m->nvar % NVAR_INC == 0) m->vars = realloc(m->vars, (m->nvar + NVAR_INC) * sizeof(variable)); now = &m->vars[m->nvar]; variable_new(now, m->nvar, token); m->nvar++; } else if (strcasecmp(token, "GRID") == 0) { int i; if (now == NULL) enkf_quit("%s, l.%d: VAR not specified", modelprm, line); if (now->gridid >= 0) enkf_quit("%s, l.%d: GRID already specified for \"%s\"", modelprm, line, now->name); if ((token = strtok(NULL, seps)) == NULL) enkf_quit("%s, l.%d: GRID not specified", modelprm, line); for (i = 0; i < m->ngrid; ++i) if (strcasecmp(token, grid_getname(m->grids[i])) == 0) { now->gridid = i; break; } if (i == m->ngrid) enkf_quit("%s, l.%d: grid \"%s\" not specified", modelprm, line, token); } else if (strcasecmp(token, "INFLATION") == 0) { if (now == NULL) enkf_quit("%s, l.%d: VAR not specified", modelprm, line); if (!isnan(now->inflation)) enkf_quit("%s, l.%d: INFLATION already specified for \"%s\"", modelprm, line, now->name); if ((token = strtok(NULL, seps)) == NULL) enkf_quit("%s, l.%d: INFLATION not specified", modelprm, line); if (!str2double(token, &now->inflation)) enkf_quit("%s, l.%d: could not convert \"%s\" to double", modelprm, line, token); if ((token = strtok(NULL, seps)) != NULL) { if (!str2double(token, &now->inf_ratio)) enkf_quit("%s, l.%d: could not convert \"%s\" to double", modelprm, line, token); } } else enkf_quit("%s, l.%d: unknown token \"%s\"", modelprm, line, token); } /* while reading modelprm */ fclose(f); assert(m->name != NULL); assert(m->nvar > 0); { int i; for (i = 0; i < m->nvar; ++i) if (m->vars[i].gridid == -1) { if (m->ngrid == 1) m->vars[i].gridid = 0; else enkf_quit("%s: grid not specified for variable \"%s\"\n", modelprm, m->vars[i].name); } } } /* * set inflations */ { int i; for (i = 0; i < m->nvar; ++i) if (isnan(m->vars[i].inflation)) { m->vars[i].inflation = prm->inflation_base; m->vars[i].inf_ratio = prm->inf_ratio; } prm->inflation_base = NaN; prm->inf_ratio = NaN; } model_print(m, " "); assert(m->ngrid > 0); return m; }
/* main */ int main(void) { int ret; Variable * res; double d = -1.0; float f = -1.0; int32_t r32 = -1; int64_t r64 = -1; char * s; /* VT_INT32 */ if((res = variable_new(VT_INT32, &r32)) == NULL) return 2; if((ret = marshall_call(res, (MarshallCallback)_call0_int32, 0, NULL)) == 0) ret = variable_get_as(res, VT_INT32, &r32); variable_delete(res); if(ret != 0) return 3; if(r32 != 0x41424344) return 4; /* VT_INT64 */ if((res = variable_new(VT_INT64, &r64)) == NULL) return 5; if((ret = marshall_call(res, (MarshallCallback)_call0_int64, 0, NULL)) == 0) ret = variable_get_as(res, VT_INT64, &r64); variable_delete(res); if(ret != 0) return 6; if(r64 != 0x4142434445464748) return 7; /* VT_DOUBLE */ if((res = variable_new(VT_DOUBLE, &d)) == NULL) return 8; if((ret = marshall_call(res, (MarshallCallback)_call0_double, 0, NULL)) == 0) ret = variable_get_as(res, VT_DOUBLE, &d); variable_delete(res); if(ret != 0) return 9; if(d != 1.234567e89) return 10; /* VT_FLOAT */ if((res = variable_new(VT_FLOAT, &f)) == NULL) return 11; if((ret = marshall_call(res, (MarshallCallback)_call0_float, 0, NULL)) == 0) ret = variable_get_as(res, VT_FLOAT, &f); variable_delete(res); if(ret != 0) return 12; if(f != 1.234e5) return 13; /* VT_STRING */ if((res = variable_new(VT_STRING, "")) == NULL) return 14; if((ret = marshall_call(res, (MarshallCallback)_call0_string, 0, NULL)) == 0) ret = variable_get_as(res, VT_STRING, &s); variable_delete(res); if(ret != 0) return 15; if(strcmp(s, "_call0_string") != 0) return 16; return 0; }