static package bf_make(Var arglist, Byte next, void *vdata, Objid progr) { Var ret, elt; int n=arglist.v.list[1].v.num, i; if(n < 0) { free_var(arglist); make_error_pack(E_INVARG); } ret = new_list(n); InitListToZero(ret); if(arglist.v.list[0].v.num == 2) { elt = var_dup(arglist.v.list[2]); } else { elt.type = TYPE_INT; elt.v.num = 0; } for(i = 1; i <= n; i++) ret.v.list[i] = var_dup(elt); free_var(elt); free_var(arglist); return make_var_pack(ret); }
void op_for(void) { Var idx, list; idx = pop(); list = pop(); if( list.type == MAP) { list.v.list = map_keys( list.v.map ); list.type = LIST; } if( list.type == STR) { list.v.list = string_list( list.v.str ); list.type = LIST; } if (list.type != LIST) { var_free(list); raise(E_FOR); } else if (idx.v.num >= list.v.list->len) { /* loop is complete */ var_free(list); frame.pc = frame.m->code[frame.pc + 1]; /* skip to end */ } else { var_assign_local(frame.stack, frame.m->code[frame.pc], var_dup(list.v.list->el[idx.v.num])); idx.v.num++; push(list); /* push list */ push(idx); /* push new index */ pushpc(frame.pc - 1); /* push address of FOR statement */ frame.pc += 2; /* go to first instruction in loop */ } }
static package bf_slice(Var arglist, Byte next, void *vdata, Objid progr) { Var ret, list=arglist.v.list[1]; int n=list.v.list[0].v.num, c, i; if(n < 0) { free_var(arglist); make_error_pack(E_INVARG); } ret = new_list(n); InitListToZero(ret); if(arglist.v.list[0].v.num == 2) c = arglist.v.list[2].v.num; else c = 1; for(i = 1; i <= n; i++) if( list.v.list[i].type != TYPE_LIST || list.v.list[i].v.list[0].v.num < c ) { free_var(ret); free_var(arglist); return make_error_pack(E_INVARG); } else { ret.v.list[i] = var_dup(list.v.list[i].v.list[c]); } free_var(arglist); return make_var_pack(ret); }
void op_getlvar(void) { Var v; var_get_local(frame.stack, frame.m->code[frame.pc++], &v); push (var_dup(v)); }
void op_index(void) { Var ret, i, base; i = pop(); base = pop(); switch (base.type) { case STR: if (i.type != NUM) { raise(E_TYPE); } else if (i.v.num < 1 || i.v.num > base.v.str->len) { raise(E_RANGE); } else { ret.type = STR; ret.v.str = string_new(2); ret.v.str->str[0] = base.v.str->str[i.v.num - 1]; ret.v.str->str[1] = '\0'; ret.v.str->len = 1; push(ret); } break; case LIST: if (i.type != NUM) { raise(E_TYPE); } else if (i.v.num < 1 || i.v.num > base.v.list->len) { raise(E_RANGE); } else { ret = var_dup(base.v.list->el[i.v.num - 1]); push(ret); } break; case MAP: if (map_find(base.v.map, i, &ret)) { raise(E_MAPNF); } else { push(var_dup(ret)); } break; default: raise(E_TYPE); } var_free(base); var_free(i); }
void op_splice(void) { int i; Var list = pop(); if (list.type != LIST) { raise(E_TYPE); } else { for (i = 0; i < list.v.list->len; i++) { push(var_dup(list.v.list->el[i])); } } var_free(list); }
Var list_assoc(Var vtarget, Var vlist, int vindex) { int i; for (i = 1; i <= vlist.v.list[0].v.num; i++) { if (vlist.v.list[i].type == TYPE_LIST && vlist.v.list[i].v.list[0].v.num >= vindex && equality(vlist.v.list[i].v.list[vindex], vtarget, 0)) { return var_dup(vlist.v.list[i]); } } return new_list(0); }
void op_getsysvar(void) { int varno = frame.m->code[frame.pc++]; String *varname = sym_get(frame.on, varno); Var ret; Object *sys; if (!(sys = retrieve(sys_obj))) { raise(E_OBJNF); } else if (var_get_global(sys, varname->str, &ret) == E_VARNF) { raise(E_VARNF); } else { push(var_dup(ret)); } }
void op_getgvar(void) { Var ret; Error r; int varname; varname = frame.m->code[frame.pc++]; r = var_get_global(this, sym_get(frame.on, varname)->str, &ret); if (r != E_NONE) { raise(r); (void) pop(); /* what's this for? i forget */ } else { push (var_dup(ret)); } }
void op_asgngvarindex(void) { Var var, idx, expr, ret; int varno = frame.m->code[frame.pc++]; Error r; expr = pop(); idx = pop(); r = var_get_global(this, sym_get(frame.on, varno)->str, &var); if (r != E_NONE) { raise(r); } else if (!do_asgnindex(var, idx, expr, &ret)) { var = var_dup(var); var_assign_global(this, sym_get(frame.on, varno), ret); } }
void op_getgvarexpr(void) { Var arg, ret; Error r; arg = pop(); if (arg.type != STR) { raise(E_ARGTYPE); } else { r = var_get_global(this, arg.v.str->str, &ret); if (r != E_NONE) { raise(r); } else { push (var_dup(ret)); } } var_free(arg); }
void op_asgngvarexpr(void) { Var arg1, arg2; Error r; arg2 = pop(); arg1 = pop(); if (arg1.type != STR) { raise(E_ARGTYPE); } else if (!valid_ident(arg1.v.str->str)) { raise(E_RANGE); } else { r = var_assign_global(this, arg1.v.str, arg2); if (r != E_NONE) { raise(r); } else { push (var_dup(arg2)); } } var_free(arg1); }
static package bf_http_request( Var arglist, Byte next, void *vdata, Objid progr) { CURL *curl_handle; CURLcode ok; package result; if (!is_wizard(progr)) { free_var(arglist); return make_error_pack(E_PERM); } int nargs = arglist.v.list[0].v.num; const char *address = arglist.v.list[1].v.str; const char *agent="",*postfields="",*cookies=""; int headers = 0; switch(nargs) { case 5: cookies = arglist.v.list[5].v.str; case 4: postfields = arglist.v.list[4].v.str; case 3: agent = arglist.v.list[3].v.str; case 2: headers = arglist.v.list[2].v.num; } if(!strlen(agent)) agent = "MOO-http/1.0"; const char delimiters[] = "\n"; free_var(arglist); struct MemoryStruct chunk; chunk.memory = malloc(1); chunk.size = 0; curl_global_init(CURL_GLOBAL_ALL); curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_URL, address); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, agent); curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 5); curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 3); curl_easy_setopt(curl_handle, CURLOPT_FTP_RESPONSE_TIMEOUT, 3); curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 5); curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl_handle, CURLOPT_MAXFILESIZE, 1048576); if(strlen(postfields)) curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, postfields); if(strlen(cookies)) curl_easy_setopt(curl_handle, CURLOPT_COOKIE, cookies); if(headers) curl_easy_setopt(curl_handle, CURLOPT_HEADER, 1); ok = curl_easy_perform(curl_handle); curl_easy_cleanup(curl_handle); if(ok == CURLE_OK && strlen(chunk.memory) != chunk.size) ok = CURLE_BAD_CONTENT_ENCODING; // binary !!! if(ok == CURLE_OK) { char *token,*p=chunk.memory; Var r; r.type = TYPE_LIST; r = new_list(0); token = strsep(&p, delimiters); while( token != NULL ) { Var line; line.type = TYPE_STR; if(token[strlen(token)-1] == '\r') token[strlen(token)-1] = '\0'; //run it through utf8_substr to get rid of invalid utf8 line.v.str = (char *)utf8_substr(token,1,utf8_strlen(token)); r = listappend(r, var_dup(line)); token = strsep(&p, delimiters); free_var(line); } result = make_var_pack(r); } else { Var r; r.type = TYPE_INT; r.v.num = ok; result = make_raise_pack(E_INVARG, curl_easy_strerror(ok), r); } if(chunk.memory) free(chunk.memory); curl_global_cleanup(); return result; }
static package bf_mysql_query( Var arglist, Byte next, void *vdata, Objid progr) { Var r; char error_string[MOOSQL_ERROR_LEN]; MYSQL_CONN *wrapper; MYSQL_RES *res_set; #ifdef MOOSQL_MULTIPLE_STATEMENTS Var tmp; Var end; int len = 0; int continu = 1; #endif if (!is_wizard(progr)) { free_var(arglist); return make_error_pack(E_PERM); } Objid oid = arglist.v.list[1].v.obj; wrapper = resolve_mysql_connection(oid); if (wrapper == NULL || wrapper->conn == NULL || wrapper->active == 0) { free_var(arglist); return make_error_pack(E_INVARG); } const char *query = arglist.v.list[2].v.str; free_var(arglist); /* we do the query now. */ if (mysql_query (wrapper->conn, query) != 0) /* failed */ { /* there is an error, so we will return that string. similar to below which * returns a string for a successful query with no result set which is handled in * process_mysql_query */ snprintf(error_string,MOOSQL_ERROR_LEN,"ERR: %s",mysql_error(wrapper->conn)); r.type = TYPE_STR; r.v.str = str_dup(error_string); return make_var_pack(r); } wrapper->last_query_time = time(0); #ifdef MOOSQL_MULTIPLE_STATEMENTS r = new_list(1); r.v.list[1].type = TYPE_INT; r.v.list[1].v.num = 0; end = new_list(0); while (continu) { len++; res_set = process_mysql_query(wrapper,error_string); if (res_set == NULL) /* there was no result on this query */ { tmp.type = TYPE_STR; tmp.v.str = str_dup(error_string); end = listappend(end,var_dup(tmp)); } else { tmp = process_result_set(wrapper,res_set); end = listappend(end,var_dup(tmp)); } if (mysql_more_results(wrapper->conn)) { mysql_next_result(wrapper->conn); continu = 1; } else continu = 0; } if (len <= 1) /* if there is only one result return it like in previous versions, a list of rows */ return make_var_pack(end.v.list[1]); r.v.list[1].v.num = len; /* if there are more return it in this format {X, Y} where X is the number of results and Y is a list of results */ r = listappend(r,end); return make_var_pack(r); #else res_set = process_mysql_query(wrapper,error_string); if (res_set == NULL) /* there was either an error / no result on this query */ { r.type = TYPE_STR; r.v.str = str_dup(error_string); return make_var_pack(r); } r = process_result_set(wrapper,res_set); return make_var_pack(r); #endif }