root/1.8.3/tags/p6/src/funufun.c

Revision 919, 8.5 KB (checked in by shawnw, 19 months ago)

1.8.3p3

Line 
1/**
2 * \file funufun.c
3 *
4 * \brief Evaluation and user-function functions for mushcode.
5 *
6 *
7 */
8
9#include "copyrite.h"
10
11#include "config.h"
12#include "conf.h"
13#include "externs.h"
14#include "match.h"
15#include "parse.h"
16#include "mymalloc.h"
17#include "attrib.h"
18#include "mushdb.h"
19#include "dbdefs.h"
20#include "flags.h"
21#include "lock.h"
22#include "confmagic.h"
23
24void do_userfn(char *buff, char **bp, dbref obj, ATTR *attrib, int nargs,
25               char **args, dbref executor, dbref caller, dbref enactor,
26               PE_Info *pe_info, int extra_flags);
27
28/* ARGSUSED */
29FUNCTION(fun_s)
30{
31  char const *p;
32  p = args[0];
33  process_expression(buff, bp, &p, executor, caller, enactor, PE_DEFAULT,
34                     PT_DEFAULT, pe_info);
35}
36
37/* ARGSUSED */
38FUNCTION(fun_fn)
39{
40  /* First argument is name of a function, remaining are arguments
41   * for that function.
42   */
43  char tbuf[BUFFER_LEN];
44  char *tp = tbuf;
45  char const *p;
46  int i;
47  if (!args[0] || !*args[0])
48    return;                     /* No function name */
49  /* Evaluate first argument */
50  p = args[0];
51  process_expression(tbuf, &tp, &p, executor, caller,
52                     enactor, PE_DEFAULT, PT_DEFAULT, pe_info);
53  safe_chr('(', tbuf, &tp);
54  for (i = 1; i < nargs; i++) {
55    if (i > 1)
56      safe_chr(',', tbuf, &tp);
57    safe_strl(args[i], arglens[i], tbuf, &tp);
58  }
59  safe_chr(')', tbuf, &tp);
60  *tp = '\0';
61  p = tbuf;
62  process_expression(buff, bp, &p, executor, caller, enactor,
63                     PE_DEFAULT | PE_BUILTINONLY, PT_DEFAULT, pe_info);
64}
65
66/* ARGSUSED */
67FUNCTION(fun_localize)
68{
69  char const *p;
70  char *saver[NUMQ];
71
72  save_global_regs("localize", saver);
73
74  p = args[0];
75  process_expression(buff, bp, &p, executor, caller, enactor, PE_DEFAULT,
76                     PT_DEFAULT, pe_info);
77
78  restore_global_regs("localize", saver);
79}
80
81/* ARGSUSED */
82FUNCTION(fun_objeval)
83{
84  char name[BUFFER_LEN];
85  char *s;
86  char const *p;
87  dbref obj;
88
89  /* First, we evaluate our first argument so people can use
90   * functions on it.
91   */
92  s = name;
93  p = args[0];
94  process_expression(name, &s, &p, executor, caller, enactor, PE_DEFAULT,
95                     PT_DEFAULT, pe_info);
96  *s = '\0';
97
98  if (FUNCTION_SIDE_EFFECTS) {
99    /* The security hole created by function side effects is too great
100     * to allow a see_all player to evaluate functions from someone else's
101     * standpoint. We require control.
102     */
103    if (((obj = match_thing(executor, name)) == NOTHING)
104        || !controls(executor, obj))
105      obj = executor;
106  } else {
107    /* In order to evaluate from something else's viewpoint, you
108     * must control it, or be able to see_all.
109     */
110    if (((obj = match_thing(executor, name)) == NOTHING)
111        || (!controls(executor, obj) && !See_All(executor)))
112      obj = executor;
113  }
114
115  p = args[1];
116  process_expression(buff, bp, &p, obj, executor, enactor, PE_DEFAULT,
117                     PT_DEFAULT, pe_info);
118}
119
120/** Helper function for ufun and family.
121 * \param buff string to store result of evaluation.
122 * \param bp pointer into end of buff.
123 * \param obj object on which the ufun is stored.
124 * \param attrib pointer to attribute on which the ufun is stored.
125 * \param nargs number of arguments passed to the ufun.
126 * \param args array of arguments passed to the ufun.
127 * \param executor executor.
128 * \param caller caller (unused).
129 * \param enactor enactor.
130 * \param pe_info pointer to structure for process_expression data.
131 * \param extra_flags extra PE_ flags to pass in (PE_USERFN or 0).
132 */
133void
134do_userfn(char *buff, char **bp, dbref obj, ATTR *attrib, int nargs,
135          char **args, dbref executor, dbref caller
136          __attribute__ ((__unused__)), dbref enactor, PE_Info *pe_info,
137          int extra_flags)
138{
139  int j;
140  char *tptr[10];
141  char *tbuf;
142  char const *tp;
143  int pe_flags = PE_DEFAULT | extra_flags;
144  int old_args = 0;
145
146  /* save our stack */
147  for (j = 0; j < 10; j++)
148    tptr[j] = global_eval_context.wenv[j];
149
150  /* copy the appropriate args into the stack */
151  if (nargs > 10)
152    nargs = 10;                 /* maximum ten args */
153  for (j = 0; j < nargs; j++)
154    global_eval_context.wenv[j] = args[j];
155  for (; j < 10; j++)
156    global_eval_context.wenv[j] = NULL;
157  if (pe_info) {
158    old_args = pe_info->arg_count;
159    pe_info->arg_count = nargs;
160  }
161
162  tp = tbuf = safe_atr_value(attrib);
163  if (attrib->flags & AF_DEBUG)
164    pe_flags |= PE_DEBUG;
165  process_expression(buff, bp, &tp, obj, executor, enactor, pe_flags,
166                     PT_DEFAULT, pe_info);
167  free(tbuf);
168
169  /* restore the stack */
170  for (j = 0; j < 10; j++)
171    global_eval_context.wenv[j] = tptr[j];
172  if (pe_info)
173    pe_info->arg_count = old_args;
174}
175
176/* ARGSUSED */
177FUNCTION(fun_ufun)
178{
179  char rbuff[BUFFER_LEN];
180  ufun_attrib ufun;
181
182  if (!fetch_ufun_attrib(args[0], executor, &ufun, 0)) {
183    safe_str(T(ufun.errmess), buff, bp);
184    return;
185  }
186
187  call_ufun(&ufun, args + 1, nargs - 1, rbuff, executor, enactor, pe_info);
188
189  safe_str(rbuff, buff, bp);
190
191  return;
192}
193
194/* ARGSUSED */
195FUNCTION(fun_ulambda)
196{
197  char rbuff[BUFFER_LEN];
198  ufun_attrib ufun;
199
200  if (!fetch_ufun_attrib(args[0], executor, &ufun, 1)) {
201    safe_str(T(ufun.errmess), buff, bp);
202    return;
203  }
204
205  call_ufun(&ufun, args + 1, nargs - 1, rbuff, executor, enactor, pe_info);
206
207  safe_str(rbuff, buff, bp);
208
209  return;
210}
211
212/* ARGSUSED */
213FUNCTION(fun_ulocal)
214{
215  /* Like fun_ufun, but saves the state of the q0-q9 registers
216   * when called
217   */
218  char *preserve[NUMQ];
219  char rbuff[BUFFER_LEN];
220  ufun_attrib ufun;
221
222  if (!fetch_ufun_attrib(args[0], executor, &ufun, 0)) {
223    safe_str(T(ufun.errmess), buff, bp);
224    return;
225  }
226
227  /* Save global regs */
228  save_global_regs("ulocal.save", preserve);
229
230  call_ufun(&ufun, args + 1, nargs - 1, rbuff, executor, enactor, pe_info);
231  safe_str(rbuff, buff, bp);
232
233  restore_global_regs("ulocal.save", preserve);
234
235  return;
236}
237
238/* Like fun_ufun, but takes as second argument a default message
239 * to use if the attribute isn't there.  If called as uldefault,
240 * then preserve registers, too.
241 */
242/* ARGSUSED */
243FUNCTION(fun_uldefault)
244{
245  dbref thing;
246  ATTR *attrib;
247  char *dp;
248  char const *sp;
249  char mstr[BUFFER_LEN];
250  char **xargs;
251  int i;
252  char *preserve[NUMQ];
253
254  /* find our object and attribute */
255  dp = mstr;
256  sp = args[0];
257  process_expression(mstr, &dp, &sp, executor, caller, enactor,
258                     PE_DEFAULT, PT_DEFAULT, pe_info);
259  *dp = '\0';
260  parse_attrib(executor, mstr, &thing, &attrib);
261  if (GoodObject(thing) && attrib && CanEvalAttr(executor, thing, attrib)
262      && Can_Read_Attr(executor, thing, attrib)) {
263    /* Ok, we've got it */
264    /* We must now evaluate all the arguments from args[2] on and
265     * pass them to the function */
266    xargs = NULL;
267    if (nargs > 2) {
268      xargs = mush_calloc(nargs - 2, sizeof(char *), "udefault.xargs");
269      for (i = 0; i < nargs - 2; i++) {
270        xargs[i] = mush_malloc(BUFFER_LEN, "udefault");
271        dp = xargs[i];
272        sp = args[i + 2];
273        process_expression(xargs[i], &dp, &sp, executor, caller, enactor,
274                           PE_DEFAULT, PT_DEFAULT, pe_info);
275        *dp = '\0';
276      }
277    }
278    if (called_as[1] == 'L')
279      save_global_regs("uldefault.save", preserve);
280    do_userfn(buff, bp, thing, attrib, nargs - 2, xargs,
281              executor, caller, enactor, pe_info, 0);
282    if (called_as[1] == 'L')
283      restore_global_regs("uldefault.save", preserve);
284
285    /* Free the xargs */
286    if (nargs > 2) {
287      for (i = 0; i < nargs - 2; i++)
288        mush_free(xargs[i], "udefault");
289      mush_free(xargs, "udefault.xargs");
290    }
291    return;
292  }
293  /* We couldn't get it. Evaluate args[1] and return it */
294  sp = args[1];
295
296  if (called_as[1] == 'L')
297    save_global_regs("uldefault.save", preserve);
298  process_expression(buff, bp, &sp, executor, caller, enactor,
299                     PE_DEFAULT, PT_DEFAULT, pe_info);
300  if (called_as[1] == 'L')
301    restore_global_regs("uldefault.save", preserve);
302  return;
303}
304
305
306/* ARGSUSED */
307FUNCTION(fun_zfun)
308{
309  ATTR *attrib;
310  dbref zone;
311
312  zone = Zone(executor);
313
314  if (zone == NOTHING) {
315    safe_str(T("#-1 INVALID ZONE"), buff, bp);
316    return;
317  }
318  /* find the user function attribute */
319  attrib = atr_get(zone, upcasestr(args[0]));
320  if (attrib && Can_Read_Attr(executor, zone, attrib)) {
321    if (!CanEvalAttr(executor, zone, attrib)) {
322      safe_str(T(e_perm), buff, bp);
323      return;
324    }
325    do_userfn(buff, bp, zone, attrib, nargs - 1, args + 1, executor, caller,
326              enactor, pe_info, 0);
327    return;
328  } else if (attrib || !Can_Examine(executor, zone)) {
329    safe_str(T(e_atrperm), buff, bp);
330    return;
331  }
332  safe_str(T("#-1 NO SUCH USER FUNCTION"), buff, bp);
333  return;
334}
Note: See TracBrowser for help on using the browser.