PennMUSH Community

root/1.8.3/trunk/src/funufun.c

Revision 919, 8.5 kB (checked in by shawnw, 1 year 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
24 void 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 */
29 FUNCTION(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 */
38 FUNCTION(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 */
67 FUNCTION(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 */
82 FUNCTION(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  */
133 void
134 do_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 */
177 FUNCTION(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 */
195 FUNCTION(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 */
213 FUNCTION(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 */
243 FUNCTION(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 */
307 FUNCTION(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.