/** Helper function for calling \@functioned funs. * \param buff string to store result of evaluation. * \param bp pointer into end of buff. * \param obj object on which the ufun is stored. * \param attrib pointer to attribute on which the ufun is stored. * \param nargs number of arguments passed to the ufun. * \param args array of arguments passed to the ufun. * \param executor executor. * \param caller caller (unused). * \param enactor enactor. * \param pe_info pointer to structure for process_expression data. * \param extra_flags extra PE_ flags to pass in (PE_USERFN or 0). */ void do_userfn(char *buff, char **bp, dbref obj, ATTR *attrib, int nargs, char **args, dbref executor, dbref caller __attribute__ ((__unused__)), dbref enactor, NEW_PE_INFO *pe_info, int extra_flags) { int j; int made_pe_info = 0; char *tbuf; char const *tp; int pe_flags = PE_DEFAULT | extra_flags; PE_REGS *pe_regs; if (nargs > 10) nargs = 10; /* maximum ten args */ /* save our stack */ if (!pe_info) { made_pe_info = 1; pe_info = make_pe_info("pe_info-do_userfn"); } /* copy the appropriate args into pe_regs */ pe_regs = pe_regs_localize(pe_info, PE_REGS_ARG, "do_userfn"); for (j = 0; j < nargs; j++) { pe_regs_setenv_nocopy(pe_regs, j, args[j]); } tp = tbuf = safe_atr_value(attrib); if (AF_NoDebug(attrib)) pe_flags |= PE_NODEBUG; /* no_debug overrides debug */ else if (AF_Debug(attrib)) pe_flags |= PE_DEBUG; process_expression(buff, bp, &tp, obj, executor, enactor, pe_flags, PT_DEFAULT, pe_info); free(tbuf); pe_regs_restore(pe_info, pe_regs); pe_regs_free(pe_regs); if (made_pe_info) { free_pe_info(pe_info); } }
/** Evaluate a lock, saving/clearing the env (%0-%9) and qreg (%q*) first, ** and restoring them after. */ int eval_lock_clear(dbref player, dbref thing, lock_type ltype, NEW_PE_INFO *pe_info) { if (!pe_info) return eval_lock_with(player, thing, ltype, NULL); else { PE_REGS *pe_regs; int result; pe_regs = pe_regs_localize(pe_info, PE_REGS_ISOLATE, "eval_lock_clear"); /* Run the lock */ result = eval_lock_with(player, thing, ltype, pe_info); /* Restore q-regs */ pe_regs_restore(pe_info, pe_regs); pe_regs_free(pe_regs); return result; } }
/** Given a ufun, executor, enactor, PE_Info, and arguments for %0-%9, * call the ufun with appropriate permissions on values given for * wenv_args. The value returned is stored in the buffer pointed to * by ret, if given. * \param ufun The ufun_attrib that was initialized by fetch_ufun_attrib * \param ret If desired, a pointer to a buffer in which the results * of the process_expression are stored in. * \param caller The caller (%@). * \param enactor The enactor. (%#) * \param pe_info The pe_info passed to the FUNCTION * \param user_regs Other arguments that may want to be added. This nests BELOW * the pe_regs created by call_ufun. (It is checked first) * \param data a void pointer to extra data. Currently only used to pass the * name to use, when UFUN_NAME is given. * \retval 0 success * \retval 1 process_expression failed. (CPU time limit) */ bool call_ufun_int(ufun_attrib * ufun, char *ret, dbref caller, dbref enactor, NEW_PE_INFO *pe_info, PE_REGS *user_regs, void *data) { char rbuff[BUFFER_LEN]; char *rp, *np = NULL; int pe_ret; char const *ap; char old_attr[BUFFER_LEN]; int made_pe_info = 0; PE_REGS *pe_regs; PE_REGS *pe_regs_old; int pe_reg_flags = 0; /* Make sure we have a ufun first */ if (!ufun) return 1; if (!pe_info) { pe_info = make_pe_info("pe_info.call_ufun"); made_pe_info = 1; } else { strcpy(old_attr, pe_info->attrname); } pe_regs_old = pe_info->regvals; if (ufun->ufun_flags & UFUN_LOCALIZE) pe_reg_flags |= PE_REGS_Q; else { pe_reg_flags |= PE_REGS_NEWATTR; if (ufun->ufun_flags & UFUN_SHARE_STACK) pe_reg_flags |= PE_REGS_ARGPASS; } pe_regs = pe_regs_localize(pe_info, pe_reg_flags, "call_ufun"); rp = pe_info->attrname; if (*ufun->attrname == '\0') { safe_str("#LAMBDA", pe_info->attrname, &rp); safe_chr('/', pe_info->attrname, &rp); safe_str(ufun->contents, pe_info->attrname, &rp); } else { safe_dbref(ufun->thing, pe_info->attrname, &rp); safe_chr('/', pe_info->attrname, &rp); safe_str(ufun->attrname, pe_info->attrname, &rp); } *rp = '\0'; /* If the user doesn't care about the return of the expression, * then use our own rbuff. */ if (!ret) ret = rbuff; rp = ret; /* Anything the caller wants available goes on the bottom of the stack */ if (user_regs) { user_regs->prev = pe_info->regvals; pe_info->regvals = user_regs; } if (ufun->ufun_flags & UFUN_NAME) { char *name = (char *) data; if (!name || !*name) name = (char *) Name(enactor); safe_str(name, ret, &rp); if (!(ufun->ufun_flags & UFUN_NAME_NOSPACE)) safe_chr(' ', ret, &rp); np = rp; } /* And now, make the call! =) */ ap = ufun->contents; pe_ret = process_expression(ret, &rp, &ap, ufun->thing, caller, enactor, ufun->pe_flags, PT_DEFAULT, pe_info); *rp = '\0'; if ((ufun->ufun_flags & UFUN_NAME) && np == rp) { /* Attr was empty, so we take off the name again */ *ret = '\0'; } /* Restore call_ufun's pe_regs */ if (user_regs) { pe_info->regvals = user_regs->prev; } /* Restore the pe_regs stack. */ pe_regs_restore(pe_info, pe_regs); pe_regs_free(pe_regs); pe_info->regvals = pe_regs_old; if (!made_pe_info) { /* Restore the old attrname. */ strcpy(pe_info->attrname, old_attr); } else { free_pe_info(pe_info); } return pe_ret; }