void f_bson_buf_find(void){ int size; bson b[1]; bson sub; svalue_t v; bson_iterator it; size = (sp-1)->u.buf->size; bson_init_empty(b); bson_init_size( b, size ); memcpy(b->data, (sp-1)->u.buf->item, size); b->finished = 1; /* buff不合法 */ if(bson_size(b) != size){ pop_n_elems(st_num_arg); push_number(0); goto free_bson; } /* 找不到数据 */ if(!bson_find( &it, b, sp->u.string )){ pop_n_elems(st_num_arg); push_number(0); goto free_bson; } bson_to_v(&it, &v); free_buffer((sp-1)->u.buf); pop_stack(); *sp = v; free_bson: bson_destroy( b ); }
void f_socket_write (void) { int i, fd, port; svalue_t *arg; char addr[ADDR_BUF_SIZE]; int num_arg = st_num_arg; arg = sp - num_arg + 1; if ((num_arg == 3) && (arg[2].type != T_STRING)) { bad_arg(3, F_SOCKET_WRITE); } fd = arg[0].u.number; get_socket_address(fd, addr, &port, 0); if (VALID_SOCKET("write")) { i = socket_write(fd, &arg[1], (num_arg == 3) ? arg[2].u.string : (char *) NULL); pop_n_elems(num_arg - 1); sp->u.number = i; } else { pop_n_elems(num_arg - 1); sp->u.number = EESECURITY; } }
static void f_extension( INT32 args ) { int i, found=0; struct pike_string *src; char *orig, *ptr; if(Pike_sp[-1].type != T_STRING) SIMPLE_BAD_ARG_ERROR("Caudium.extension", 1, "string"); src = Pike_sp[-1].u.string; if(src->size_shift) { Pike_error("Caudium.extension(): Only 8-bit strings allowed.\n"); } orig = src->str; for(i = src->len-1; i >= 0; i--) { if(orig[i] == 0x2E) { found = 1; i++; break; } } if(found) { int len = src->len - i; switch(orig[src->len-1]) { case '#': case '~': /* Remove unix backup extension */ len--; } pop_n_elems(args); push_string(make_shared_binary_string(orig+i, len)); } else { pop_n_elems(args); push_text(""); } }
/*! @decl int listen_fd(int fd, void|function accept_callback) *! *! This function does the same as @[bind], except that instead of *! creating a new socket and bind it to a port, it expects the file *! descriptor @[fd] to be an already open port. *! *! @note *! This function is only for the advanced user, and is generally used *! when sockets are passed to Pike at exec time. *! *! @seealso *! @[bind], @[accept] */ static void port_listen_fd(INT32 args) { struct port *p = THIS; struct svalue *cb = NULL; int fd; do_close(p); get_all_args(NULL, args, "%d.%*", &fd, &cb); if(fd<0) { errno = p->my_errno=EBADF; pop_n_elems(args); push_int(0); return; } if(fd_listen(fd, 16384) < 0) { p->my_errno=errno; pop_n_elems(args); push_int(0); return; } change_fd_for_box (&p->box, fd); if(cb) assign_accept_cb (p, cb); p->my_errno=0; pop_n_elems(args); push_int(1); }
static void f_got_data( INT32 args ) { struct pf_source *s = ((struct callback_prog *)Pike_fp->current_object->storage)->s; remove_callbacks( (struct source *)s ); if( s->str || TYPEOF(Pike_sp[-1]) != PIKE_T_STRING || Pike_sp[-1].u.string->size_shift || Pike_sp[-1].u.string->len == 0) { s->s.eof = 1; pop_n_elems(args); push_int(0); return; } s->str = Pike_sp[-1].u.string; Pike_sp--; pop_n_elems(args-1); push_int(0); if( s->when_data_cb ) s->when_data_cb( s->when_data_cb_arg ); }
/*! @decl array(string) split(string s) *! Works as @[match], but returns an array of the strings that *! matched the subregexps. Subregexps are those contained in "( )" in *! the regexp. Subregexps that were not matched will contain zero. *! If the total regexp didn't match, zero is returned. *! *! @bugs *! You can currently only have 39 subregexps. *! *! @bugs *! The current implementation doesn't support searching *! in strings containing the NUL character or any *! wide character. *! *! @seealso *! @[match] */ static void regexp_split(INT32 args) { struct pike_string *s; struct regexp *r; get_all_args("Regexp.SimpleRegexp->split", args, "%S", &s); if(pike_regexec(r=THIS->regexp, s->str)) { int i,j; add_ref(s); pop_n_elems(args); for(j=i=1;i<NSUBEXP;i++) { if(!r->startp[i] || !r->endp[i]) { push_int(0); }else{ push_string(make_shared_binary_string(r->startp[i], r->endp[i]-r->startp[i])); j=i; } } if(j<i-1) pop_n_elems(i-j-1); push_array(aggregate_array(j)); free_string(s); }else{ pop_n_elems(args); push_int(0); } }
void f_compress (void) { unsigned char* buffer; unsigned char* input; int size; buffer_t* real_buffer; uLongf new_size; if (sp->type == T_STRING) { size = SVALUE_STRLEN(sp); input = (unsigned char*)sp->u.string; } else if (sp->type == T_BUFFER) { size = sp->u.buf->size; input = sp->u.buf->item; } else { pop_n_elems(st_num_arg); push_undefined(); return ; } new_size = size; // Make it a little larger as specified in the docs. buffer = (unsigned char*)DXALLOC(size * 101 / 100 + 12, TAG_TEMPORARY, "compress"); compress(buffer, &new_size, input, size); // Shrink it down. pop_n_elems(st_num_arg); real_buffer = allocate_buffer(new_size); write_buffer(real_buffer, 0, (char *)buffer, new_size); FREE(buffer); push_buffer(real_buffer); }
/* Note that now, once the master object loads once, there is ALWAYS a * master object, so the only way this can fail is if the master object * hasn't loaded yet. In that case, we return (svalue_t *)-1, and the * calling routine should let the check succeed. 失败只可能是还没有load进master 这像是在让master调用函数? */ svalue_t *apply_master_ob(int fun, int num_arg) /* 将master应用起来? */ { if (!master_ob) { pop_n_elems(num_arg); /* 只要master还没有load进来,就将栈清空? */ return (svalue_t *)-1; } if (master_applies[fun].func) { /* 这里会调用不同的函数,函数都在里边? */ #ifdef TRACE if (TRACEP(TRACE_APPLY)) { do_trace("master apply", master_applies[fun].func->name, "\n"); } #endif DEBUG_CHECK(master_ob->flags & O_SWAPPED, "Master object swapped!\n"); call_direct(master_ob, master_applies[fun].index, ORIGIN_DRIVER, num_arg); /* 像是在调用函数? */ free_svalue(&apply_ret_value, "apply_master_ob"); apply_ret_value = *sp--; /* 从栈中取出返回值 */ return &apply_ret_value; } else { pop_n_elems(num_arg); return 0; } }
void f_reference_allowed() { svalue_t *sv = sp - st_num_arg + 1; svalue_t *v; object_t *referee = NULL; object_t *referrer_obj = command_giver; /* Default to this_player(). */ const char *referrer_name = NULL; int result = 0; int num_arg = st_num_arg; /* Maybe I could learn how to use this :p CHECK_TYPES(sp-1, T_NUMBER, 1, F_MEMBER_ARRAY); */ if (sv->type == T_OBJECT && sv->u.ob) { referee = sv->u.ob; } if (st_num_arg > 1) { if (sv[1].type == T_STRING && sv[1].u.string) { /* We've been passed in a string, now we need to call * find_player() */ #ifdef F_FIND_PLAYER /* If we have a find_player() efun, then we need to sue * the following method. This hasn't been tested! */ referrer = find_living_object(sv[1].u.string, 1); #else if (simul_efun_ob) { push_svalue(&sv[1]); v = apply("find_player", simul_efun_ob, 1, ORIGIN_EFUN); if (v && v->type == T_OBJECT) { referrer_obj = v->u.ob; referrer_name = sv[1].u.string; } else { referrer_obj = NULL; referrer_name = sv[1].u.string; } } #endif } if (sv[1].type == T_OBJECT && sv[1].u.ob) { referrer_obj = sv[1].u.ob; referrer_name = NULL; } } if (referee && (referrer_obj || referrer_name)) { result = reference_allowed(referee, referrer_obj, referrer_name); pop_n_elems(num_arg); push_number(result); } else { pop_n_elems(num_arg); push_undefined(); } }
/*! @decl array(array(string)|string) tokenize(string code) *! *! Tokenize a string of Pike tokens. *! *! @returns *! Returns an array with Pike-level tokens and the remainder (a *! partial token), if any. */ static void f_tokenize( INT32 args ) { struct array *res; struct pike_string *left_s = NULL; /* Make gcc happy. */ struct pike_string *data; int left; ONERROR tmp; get_all_args("tokenize", args, "%W", &data); if(!data->len) { pop_n_elems(args); push_empty_array(); push_empty_string(); f_aggregate(2); return; } res = allocate_array_no_init( 0, 128 ); SET_ONERROR(tmp, do_free_arrayptr, &res); switch(data->size_shift) { case 0: left = tokenize0(&res, STR0(data), data->len); left_s = make_shared_binary_string0(STR0(data)+left, data->len-left); break; case 1: left = tokenize1(&res, STR1(data), data->len); left_s = make_shared_binary_string1(STR1(data)+left, data->len-left); break; case 2: left = tokenize2(&res,STR2(data), data->len); left_s = make_shared_binary_string2(STR2(data)+left, data->len-left); break; #ifdef PIKE_DEBUG default: Pike_error("Unknown shift size %d.\n", data->size_shift); #endif } UNSET_ONERROR(tmp); pop_n_elems(args); if (!res->size) { free_array(res); push_empty_array(); } else push_array(res); push_string( left_s ); f_aggregate( 2 ); }
void image_orient4(INT32 args) { struct object *o[5]; struct image *img[5]; CHECK_INIT(); pop_n_elems(args); _image_orient(THIS,o,img); pop_n_elems(1); f_aggregate(4); }
/* Free an input */ static INLINE void free_input(input *inp) { ninputs--; switch(inp->type) { case NBIO_STR: DERR(fprintf(stderr, "Freeing string input 0x%x\n", (unsigned int)inp)); free_string(inp->u.data); nstrings--; break; #ifdef USE_MMAP case NBIO_MMAP: DERR(fprintf(stderr, "Freeing mmap input 0x%x\n", (unsigned int)inp)); if(inp->u.mmap_storage->data != MAP_FAILED) { munmap(inp->u.mmap_storage->data, inp->u.mmap_storage->m_len); mmapped -= inp->u.mmap_storage->m_len; } push_int(0); push_int(0); push_int(0); apply_low(inp->u.mmap_storage->file, inp->set_nb_off, 3); apply_low(inp->u.mmap_storage->file, inp->set_b_off, 0); pop_n_elems(2); free_object(inp->u.mmap_storage->file); free(inp->u.mmap_storage); break; #endif case NBIO_OBJ: push_int(0); push_int(0); push_int(0); apply_low(inp->u.file, inp->set_nb_off, 3); apply_low(inp->u.file, inp->set_b_off, 0); pop_n_elems(2); /* FALL THROUGH */ case NBIO_BLOCK_OBJ: DERR(fprintf(stderr, "Freeing obj input 0x%x\n", (unsigned int)inp)); free_object(inp->u.file); nobjects--; break; } if(THIS->last_input == inp) THIS->last_input = NULL; THIS->inputs = inp->next; if(!THIS->finished && THIS->inputs && THIS->inputs->type == NBIO_OBJ) { /* Aha! Set read callback here */ DERR(fprintf(stderr, "Setting read/close callbacks for input 0x%x\n", (unsigned int)THIS->inputs)); push_callback(input_read_cb_off); push_int(0); push_callback(input_close_cb_off); apply_low(THIS->inputs->u.file, THIS->inputs->set_nb_off, 3); THIS->inputs->mode = READING; } free(inp); }
void f_external_start (void) { int fd, num_arg = st_num_arg; svalue_t *arg = sp - num_arg + 1; if (check_valid_socket("external", -1, current_object, "N/A", -1)) { fd = external_start(arg[0].u.number, arg + 1, arg + 2, arg + 3, (num_arg == 5 ? arg + 4 : 0)); pop_n_elems(num_arg - 1); sp->u.number = fd; } else { pop_n_elems(num_arg - 1); sp->u.number = EESECURITY; } }
static void pipe_read_input_callback(INT32 args) { struct input *i; struct pike_string *s; if (args<2 || sp[1-args].type!=T_STRING) Pike_error("Illegal argument to pipe->read_input_callback\n"); i=THIS->firstinput; if (!i) Pike_error("Pipe read callback without any inputs left.\n"); s=sp[1-args].u.string; if(append_buffer(s)) { /* THIS DOES NOT WORK */ push_int(0); push_int(0); push_callback(offset_input_close_callback); apply_low(i->u.obj,i->set_nonblocking_offset,3); pop_stack(); THIS->sleeping=1; } low_start(); pop_n_elems(args-1); }
/*! @decl mapping(string:string) all(string map) *! *! Returns the whole map as a mapping. *! *! @[map] is the YP-map to search in. This must be the full map name, *! you have to use @tt{passwd.byname@} instead of just @tt{passwd@}. */ static void f_all(INT32 args) { int err, num=0; char *retval, *retkey; int retlen, retkeylen; char *map; struct mapping *res_map; check_all_args(NULL, args, BIT_STRING, 0); map = sp[-1].u.string->str; res_map = allocate_mapping( (this->last_size?this->last_size+2:40) ); if(!(err = yp_first(this->domain, map, &retkey,&retkeylen, &retval,&retlen))) do { push_string(make_shared_binary_string(retkey, retkeylen)); push_string(make_shared_binary_string(retval, retlen)); mapping_insert( res_map, sp-2, sp-1 ); pop_stack(); pop_stack(); err = yp_next(this->domain, map, retkey, retkeylen, &retkey, &retkeylen, &retval, &retlen); num++; } while(!err); if(err != YPERR_NOMORE) { free_mapping( res_map ); YPERROR( err ); } this->last_size = num; pop_n_elems(args); push_mapping( res_map ); }
/*! @decl string bindtextdomain(string|void domainname, string|void dirname) *! *! Binds the path predicate for a message @[domainname] domainname to *! the directory name specified by @[dirname]. *! *! If @[domainname] is a non-empty string and has not been bound *! previously, bindtextdomain() binds @[domainname] with @[dirname]. *! *! If @[domainname] is a non-empty string and has been bound previously, *! bindtextdomain() replaces the old binding with @[dirname]. *! *! The @[dirname] argument can be an absolute or relative pathname *! being resolved when @[gettext()], @[dgettext()] or @[dcgettext()] *! are called. *! *! If @[domainname] is zero or an empty string, @[bindtextdomain()] *! returns 0. *! *! User defined domain names cannot begin with the string @expr{"SYS_"@}. *! Domain names beginning with this string are reserved for system use. *! *! @returns *! The return value from @[bindtextdomain()] is a string containing *! @[dirname] or the directory binding associated with @[domainname] if *! @[dirname] is unspecified. If no binding is found, the default locale *! path is returned. If @[domainname] is unspecified or is an empty string, *! @[bindtextdomain()] takes no action and returns a 0. *! *! @seealso *! @[textdomain], @[gettext], @[setlocale], @[localeconv] */ void f_bindtextdomain(INT32 args) { char *returnstring; const char *domain = NULL, *dirname = NULL; get_all_args (NULL, args, ".%C%C", &domain, &dirname); if (!domain || !*domain) returnstring = NULL; else { #ifdef BINDTEXTDOMAIN_HANDLES_NULL returnstring = bindtextdomain (domain, dirname); #else if (dirname) returnstring = bindtextdomain (domain, dirname); else /* Awkward, but not much we can do. Still better than a * coredump.. */ Pike_error ("Pike has been compiled with a version of libintl " "that doesn't support NULL as directory name.\n"); #endif } pop_n_elems(args); if(returnstring == NULL) push_int(0); else push_text(returnstring); }
/*! @decl array(string) _xpm_trim_rows(array(string) rows) */ void f__xpm_trim_rows( INT32 args ) { struct array *a; int i,j=0; get_all_args("_xpm_trim_rows", args, "%a", &a ); for(i=0; i<a->size; i++) { int len,start; struct pike_string *s = a->item[i].u.string; if(a->item[i].type != T_STRING) Pike_error("Array must be array(string).\n"); if(s->len > 4) { for(start=0; start<s->len; start++) if(s->str[start] == '/' || s->str[start] == '"') break; if(s->str[start] == '/') continue; for(len=start+1; len<s->len; len++) if(s->str[len] == '"') break; if(len>=s->len || s->str[len] != '"') continue; free_string(a->item[j].u.string); a->item[j++].u.string=make_shared_binary_string(s->str+start+1,len-start-1); } } pop_n_elems(args-1); }
static void f_crypt_md5(INT32 args) { char salt[8]; char *ret, *saltp =""; char *choice = "cbhisjKlm4k65p7qrJfLMNQOPxwzyAaBDFgnoWXYCZ0123tvdHueEGISRTUV89./"; if (args < 1) SIMPLE_TOO_FEW_ARGS_ERROR("crypt_md5", 1); if (Pike_sp[-args].type != T_STRING) SIMPLE_BAD_ARG_ERROR("crypt_md5", 1, "string"); if (args > 1) { if (Pike_sp[1-args].type != T_STRING) SIMPLE_BAD_ARG_ERROR("crypt_md5", 2, "string"); saltp = Pike_sp[1-args].u.string->str; } else { unsigned int i, r; for (i = 0; i < sizeof(salt); i++) { r = my_rand(); salt[i] = choice[r % (size_t) strlen(choice)]; } saltp = salt; } ret = (char *)crypt_md5(Pike_sp[-args].u.string->str, saltp); pop_n_elems(args); push_string(make_shared_string(ret)); }
static void f_parse_headers( INT32 args ) { struct mapping *headermap; struct pike_string *headers; unsigned char *ptr; int len = 0, parsed = 0; get_all_args("Caudium.parse_headers", args, "%S", &headers); headermap = allocate_mapping(1); ptr = (unsigned char *)headers->str; len = headers->len; /* * FIXME: * What do we do if memory allocation fails halfway through * allocating a new mapping? Should we return that half-finished * mapping or rather return NULL? For now it's the former case. * /Grendel * * If memory allocation fails, just bail out with error() */ while(len > 0 && (parsed = get_next_header(ptr, len, headermap)) >= 0 ) { ptr += parsed; len -= parsed; } if(parsed == -1) { Pike_error("Caudium.parse_headers(): Out of memory while parsing.\n"); } pop_n_elems(args); push_mapping(headermap); }
void f_async_write(){ function_to_call_t *cb = get_cb(); process_efun_callback(3, cb, F_ASYNC_WRITE); cb->f.fp->hdr.ref++; add_write(check_valid_path((sp-3)->u.string, current_object, "write_file", 1), (sp-2)->u.string, strlen((sp-2)->u.string), (sp-1)->u.number, cb); pop_n_elems(4); }
static void pipe_close_input_callback(INT32 args) { struct input *i; i=THIS->firstinput; if(!i) Pike_error("Input close callback without inputs!\n"); if(i->type != I_OBJ) Pike_error("Premature close callback on pipe!.\n"); if (i->u.obj->prog) { #ifdef BLOCKING_CLOSE apply_low(i->u.obj,i->set_blocking_offset,0); pop_stack(); #endif apply(i->u.obj,"close",0); pop_stack(); } nobjects--; free_object(i->u.obj); i->type=I_NONE; input_finish(); if(args) pop_n_elems(args-1); }
/* **! method: Mhash.hash feed(string data) **! alt: Mhash.hash update(string data) **! Update the current hash context with data. **! update() is here for compatibility reasons with Crypto.md5. **! arg: string data **! The data to update the context with. **! returns: **! The current hash object. **! name: feed - Update the current hash context. */ void f_hash_feed(INT32 args) { if(THIS->hash == NULL) { if(THIS->type != -1) { free_hash(); THIS->hash = mhash_init(THIS->type); if(THIS->hash == MHASH_FAILED) { THIS->hash = NULL; Pike_error("Failed to initialize hash.\n"); } } else Pike_error("Hash is uninitialized. Use Mhash.Hash()->set_type() to select hash type.\n"); } if(args == 1) { if(Pike_sp[-args].type != T_STRING) { Pike_error("Invalid argument 1. Expected string.\n"); } mhash(THIS->hash, Pike_sp[-args].u.string->str, Pike_sp[-args].u.string->len << Pike_sp[-args].u.string->size_shift); } else { Pike_error("Invalid number of arguments to Mhash.Hash->feed(), expected 1.\n"); } pop_n_elems(args); push_object(this_object()); }
void f_dump_prog (void) { program_t *prog; const char *where; int d; object_t *ob; int narg = st_num_arg; if (st_num_arg == 2) { ob = sp[-1].u.ob; d = sp->u.number; where = 0; } else if (st_num_arg == 3) { ob = sp[-2].u.ob; d = sp[-1].u.number; where = (sp->type == T_STRING) ? sp->u.string : 0; } else { ob = sp->u.ob; d = 0; where = 0; } if (!(prog = ob->prog)) { error("No program for object.\n"); } else { if (!where) { where = "/PROG_DUMP"; } dump_prog(prog, where, d); } pop_n_elems(narg); }
void c_efun_return(int args) { svalue_t sv; sv = *sp--; pop_n_elems(args); *++sp = sv; }
/*! @decl void create(void|int version, void|int stacksize) *! *! Creates an instance of the Context class. *! *! @param version *! This context will be initially made compatible with the specified *! JavaScript version. The following constants are accepted as the value *! of this parameter: *! *! @dl *! @item JSVERSION_1_0 *! JavaScript v1.0 *! @item JSVERSION_1_1 *! JavaScript v1.1 *! @item JSVERSION_1_2 *! JavaScript v1.2 *! @item JSVERSION_1_3 *! JavaScript v1.3 (ECMA) *! @item JSVERSION_1_4 *! JavaScript v1.4 (ECMA) *! @item JSVERSION_1_5 *! JavaScript v1.5 (ECMA) *! @enddl *! *! The default value is @b{JSVERSION_1_5@} *! *! @param stacksize *! Sets the size of the private stack for this context. Value given in *! bytes. Defaults to 8192. */ static void ctx_create(INT32 args) { INT32 version = JSVERSION_1_5; INT32 stacksize = 8192; switch(args) { case 2: get_all_args("create", args, "%i%i", &version, &stacksize); break; case 1: get_all_args("create", args, "%i", &version); break; } THIS->ctx = JS_NewContext(smrt, stacksize); if (!THIS->ctx) Pike_error("Could not create a new context\n"); if (!init_globals(THIS->ctx)) Pike_error("Could not initialize the new context.\n"); if (!JS_DefineFunctions(THIS->ctx, global, output_functions)) Pike_error("Could not populate the global object with output functions\n"); JS_SetVersion(THIS->ctx, version); /* create some privacy for us */ if (!JS_SetPrivate(THIS->ctx, global, THIS)) Pike_error("Could not set the private storage for the global object\n"); pop_n_elems(args); }
static void mcast_join(INT32 args) { uint32_t mc_addr; struct ip_mreq mreq; if(args!=1) Pike_error("mcast->join(): number of arguments invalid.\n"); if(Pike_sp[-1].type!=T_STRING) Pike_error("mcast->join(): expected string.\n"); /* Verifica el estado del socket */ if( FD < 0 ) /* El objeto no está inicializado... */ Pike_error("mcast->join(): Port not bound! (call \"bind\" first)\n"); mc_addr = inet_addr(Pike_sp[-1].u.string->str); if(mc_addr == -1) Pike_error("mcast->join(): Invalid mcast group\n"); mreq.imr_multiaddr.s_addr = mc_addr; mreq.imr_interface.s_addr = THIS->if_addr; if ( setsockopt(FD,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char *) &mreq, sizeof(mreq)) == -1 ) { UDP->my_errno = errno; Pike_error("mcast->join(): error in joining group (%s)\n",strerror(errno)); } pop_n_elems(args); }
void c_return_zero() { pop_n_elems(csp->num_local_variables); sp++; DEBUG_CHECK(sp != fp, "Bad stack at c_return\n"); *sp = const0; pop_control_stack(); }
/* Set the done callback */ static void f_set_done_callback(INT32 args) { switch(args) { case 2: assign_svalue(&(THIS->args), &ARG(2)); case 1: if (Pike_sp[-args].type != T_FUNCTION) SIMPLE_BAD_ARG_ERROR("_Caudium.nbio()->set_done_callback", 1, "function"); assign_svalue(&(THIS->cb), &Pike_sp[-args]); break; case 0: free_svalue(&THIS->cb); free_svalue(&THIS->args); THIS->cb.type=T_INT; THIS->args.type=T_INT; THIS->args.u.integer = 0; return; default: Pike_error("_Caudium.nbio()->set_done_callback: Too many arguments.\n"); break; } pop_n_elems(args - 1); }
void f_replace(){ svalue_t *arg2 = sp - st_num_arg + 2; if(arg2->type == T_STRING){ return f_replace_string(); } else { array_t *arr = arg2->u.arr; int i = 0; if(arr->size & 1){ error("Wrong array size for replace.\n"); } pop_n_elems(st_num_arg-2); sp--; for (i=0;i<arr->size;i+=2){ if(arr->item[i].type == T_STRING && arr->item[i+1].type == T_STRING){ share_and_push_string(arr->item[i].u.string); share_and_push_string(arr->item[i+1].u.string); st_num_arg = 3; f_replace_string(); if(sp->type != T_STRING) break; } } free_array(arr); } }
/* **! file: Mhash/mhash.c **! File implementing the Mhash.Hash() class. **! cvs_version: $Id$ **! class: Mhash.Hash **! An instance of a normal Mhash object. This object can be used to **! calculate various hashes supported by the Mhash library. **! see_also: Mhash.HMAC **! method: void create(int|void type) **! Called when instantiating a new object. It takes an optional first **! argument with the type of hash to use. **! arg: int|void type **! The hash type to use. Can also be set with set_type(); **! name: create - Create a new hash instance. */ void f_hash_create(INT32 args) { if(THIS->type != -1 || THIS->hash || THIS->res) { Pike_error("Recursive call to create. Use Mhash.Hash()->reset() or \n" "Mhash.Hash()->set_type() to change the hash type or reset\n" "the object.\n"); } switch(args) { default: Pike_error("Invalid number of arguments to Mhash.Hash(), expected 0 or 1.\n"); break; case 1: if(Pike_sp[-args].type != T_INT) { Pike_error("Invalid argument 1. Expected integer.\n"); } THIS->type = Pike_sp[-args].u.integer; THIS->hash = mhash_init(THIS->type); if(THIS->hash == MHASH_FAILED) { THIS->hash = NULL; Pike_error("Failed to initialize hash.\n"); } break; case 0: break; } pop_n_elems(args); }