src/eval.c File Reference

#include "copyright.h"
#include "config.h"
#include "db.h"
#include "externs.h"
#include "attrs.h"
#include "functions.h"
#include "alloc.h"
#include "ansi.h"

Include dependency graph for eval.c:

Go to the source code of this file.

Data Structures

struct  tcache_ent

Defines

#define NEXTCHAR
#define stacklim   32
#define NFARGS   30

Typedefs

typedef tcache_ent TCENT

Functions

static char * parse_to_cleanup (int eval, int first, char *cstr, char *rstr, char *zstr)
char * parse_to (char **dstr, char delim, int eval)
char * parse_arglist (dbref player, dbref cause, char *dstr, char delim, dbref eval, char *fargs[], dbref nfargs, char *cargs[], dbref ncargs)
int get_gender (dbref player)
void tcache_init (void)
int tcache_empty (void)
static void tcache_add (char *orig, char *result)
static void tcache_finish (dbref player)
void exec (char *buff, char **bufc, int tflags, dbref player, dbref cause, int eval, char **dstr, char *cargs[], int ncargs)

Variables

tcache_enttcache_head
int tcache_top
int tcache_count


Define Documentation

#define NEXTCHAR

Value:

do {if (cstr == zstr) { \
                cstr++; \
                zstr++; \
        } else \
                *zstr++ = *cstr++;} while (0)

Definition at line 51 of file eval.c.

Referenced by parse_to().

#define NFARGS   30

Referenced by exec().

#define stacklim   32

Referenced by parse_to().


Typedef Documentation

typedef struct tcache_ent TCENT

Definition at line 279 of file eval.c.


Function Documentation

void exec ( char *  buff,
char **  bufc,
int  tflags,
dbref  player,
dbref  cause,
int  eval,
char **  dstr,
char *  cargs[],
int  ncargs 
)

Definition at line 344 of file eval.c.

References alloc_lbuf, alloc_sbuf, ANSI_BBLACK, ANSI_BBLUE, ANSI_BCYAN, ANSI_BGREEN, ANSI_BLACK, ANSI_BLINK, ANSI_BLUE, ANSI_BMAGENTA, ANSI_BRED, ANSI_BWHITE, ANSI_BYELLOW, ANSI_CYAN, ANSI_GREEN, ANSI_HILITE, ANSI_INVERSE, ANSI_MAGENTA, ANSI_NORMAL, ANSI_RED, ANSI_UNDER, ANSI_WHITE, ANSI_YELLOW, ufun::atr, atr_get(), atr_pget(), check_access(), EV_EVAL, EV_FCHECK, EV_FMAND, EV_NO_COMPRESS, EV_NO_LOCATION, EV_NOFCHECK, EV_NOTRACE, EV_STRIP, EV_STRIP_ESC, exec(), fun::flags, ufun::flags, FN_NO_EVAL, FN_PRES, FN_PRIV, free_lbuf, free_sbuf, statedata::func_htab, statedata::func_nest_lev, get_gender(), statedata::global_regs, hashfind(), LBUF_SIZE, MAX_GLOBAL_REGS, mudconf, mudstate, Name(), fun::nargs, NFARGS, ufun::obj, parse_arglist(), parse_to(), ufun::perms, statedata::pout, safe_chr, safe_sb_str, safe_str, SBUF_SIZE, confdata::space_compress, StringCopy, tcache_empty(), ToLower, ToUpper, Trace, statedata::ufunc_htab, and where_is().

Referenced by add_mail_message(), add_prefix(), check_filter(), delim_check(), did_it(), do_mail_proof(), do_mail_review(), do_switch(), do_think(), eval_boolexp(), exec(), fun_case(), fun_columns(), fun_default(), fun_edefault(), fun_eval(), fun_filter(), fun_fold(), fun_foreach(), fun_get_eval(), fun_ifelse(), fun_iter(), fun_list(), fun_map(), fun_mix(), fun_munge(), fun_objeval(), fun_parse(), fun_s(), fun_subeval(), fun_switch(), fun_udefault(), fun_v(), fun_zfun(), get_statustemplate_attr(), page_return(), parse_arglist(), process_cmdent(), process_command(), process_sex(), search_perform(), and u_comp().

00346 {
00347 #define NFARGS  30
00348         char *fargs[NFARGS];
00349         char *preserve[MAX_GLOBAL_REGS];
00350         char *tstr, *tbuf, *tbufc, *savepos, *atr_gotten, *start, *oldp, *savestr;
00351         char savec, ch, *str;
00352         char *realbuff = NULL, *realbp = NULL;
00353         dbref aowner;
00354         int at_space, nfargs, gender, i, j, alldone, aflags, feval;
00355         int is_trace, is_top, save_count;
00356         int ansi;
00357         FUN *fp;
00358         UFUN *ufp;
00359 
00360         static const char *subj[5] = { "", "it", "she", "he", "they" };
00361         static const char *poss[5] = { "", "its", "her", "his", "their" };
00362         static const char *obj[5] = { "", "it", "her", "him", "them" };
00363         static const char *absp[5] = { "", "its", "hers", "his", "theirs" };
00364 
00365         if(*dstr == NULL)
00366                 return;
00367 
00368         // dprintk("%d/%s", player, *dstr);
00369 
00370         at_space = 1;
00371         gender = -1;
00372         alldone = 0;
00373         ansi = 0;
00374 
00375         is_trace = Trace(player) && !(eval & EV_NOTRACE);
00376         is_top = 0;
00377 
00378         /* Extend the buffer if we need to. */
00379 
00380         if(((*bufc) - buff) > (LBUF_SIZE - SBUF_SIZE)) {
00381                 realbuff = buff;
00382                 realbp = *bufc;
00383                 buff = (char *) malloc(LBUF_SIZE);
00384                 *bufc = buff;
00385         }
00386 
00387         oldp = start = *bufc;
00388 
00389         /*
00390          * If we are tracing, save a copy of the starting buffer 
00391          */
00392 
00393         savestr = NULL;
00394         if(is_trace) {
00395                 is_top = tcache_empty();
00396                 savestr = alloc_lbuf("exec.save");
00397                 StringCopy(savestr, *dstr);
00398         }
00399         while (**dstr && !alldone) {
00400                 switch (**dstr) {
00401                 case ' ':
00402                         /*
00403                          * A space.  Add a space if not compressing or if * * 
00404                          * 
00405                          * *  * * previous char was not a space 
00406                          */
00407 
00408                         if(!(mudconf.space_compress && at_space) ||
00409                            (eval & EV_NO_COMPRESS)) {
00410                                 safe_chr(' ', buff, bufc);
00411                                 at_space = 1;
00412                         }
00413                         break;
00414                 case '\\':
00415                         /*
00416                          * General escape.  Add the following char without *
00417                          * * * * special processing 
00418                          */
00419 
00420                         at_space = 0;
00421                         (*dstr)++;
00422                         if(**dstr)
00423                                 safe_chr(**dstr, buff, bufc);
00424                         else
00425                                 (*dstr)--;
00426                         break;
00427                 case '[':
00428                         /*
00429                          * Function start.  Evaluate the contents of the * *
00430                          * * * square brackets as a function.  If no closing
00431                          * * * * * bracket, insert the [ and continue. 
00432                          */
00433 
00434                         at_space = 0;
00435                         tstr = (*dstr)++;
00436                         if(eval & EV_NOFCHECK) {
00437                                 safe_chr('[', buff, bufc);
00438                                 *dstr = tstr;
00439                                 break;
00440                         }
00441                         tbuf = parse_to(dstr, ']', 0);
00442                         if(*dstr == NULL) {
00443                                 safe_chr('[', buff, bufc);
00444                                 *dstr = tstr;
00445                         } else {
00446                                 str = tbuf;
00447                                 exec(buff, bufc, 0, player, cause,
00448                                          (eval | EV_FCHECK | EV_FMAND), &str, cargs, ncargs);
00449                                 (*dstr)--;
00450                         }
00451                         break;
00452                 case '{':
00453                         /*
00454                          * Literal start.  Insert everything up to the * * *
00455                          * * terminating } without parsing.  If no closing *
00456                          * * * * brace, insert the { and continue. 
00457                          */
00458 
00459                         at_space = 0;
00460                         tstr = (*dstr)++;
00461                         tbuf = parse_to(dstr, '}', 0);
00462                         if(*dstr == NULL) {
00463                                 safe_chr('{', buff, bufc);
00464                                 *dstr = tstr;
00465                         } else {
00466                                 if(!(eval & EV_STRIP)) {
00467                                         safe_chr('{', buff, bufc);
00468                                 }
00469                                 /*
00470                                  * Preserve leading spaces (Felan) 
00471                                  */
00472 
00473                                 if(*tbuf == ' ') {
00474                                         safe_chr(' ', buff, bufc);
00475                                         tbuf++;
00476                                 }
00477                                 str = tbuf;
00478                                 exec(buff, bufc, 0, player, cause,
00479                                          (eval & ~(EV_STRIP | EV_FCHECK)), &str, cargs, ncargs);
00480                                 if(!(eval & EV_STRIP)) {
00481                                         safe_chr('}', buff, bufc);
00482                                 }
00483                                 (*dstr)--;
00484                         }
00485                         break;
00486                 case '%':
00487                         /*
00488                          * Percent-replace start.  Evaluate the chars * * *
00489                          * following * and perform the appropriate * * *
00490                          * substitution. 
00491                          */
00492 
00493                         at_space = 0;
00494                         (*dstr)++;
00495                         savec = **dstr;
00496                         savepos = *bufc;
00497                         switch (savec) {
00498                         case '\0':                      /*
00499                                                                  * Null - all done 
00500                                                                  */
00501                                 (*dstr)--;
00502                                 break;
00503                         case '|':                       /* piped command output */
00504                                 safe_str(mudstate.pout, buff, bufc);
00505                                 break;
00506                         case '%':                       /*
00507                                                                  * Percent - a literal % 
00508                                                                  */
00509                                 safe_chr('%', buff, bufc);
00510                                 break;
00511                         case 'c':
00512                         case 'C':
00513                                 (*dstr)++;
00514                                 if(!**dstr)
00515                                         (*dstr)--;
00516                                 ansi = 1;
00517                                 switch (**dstr) {
00518                                 case 'h':               /*
00519                                                                  * hilite 
00520                                                                  */
00521                                         safe_str(ANSI_HILITE, buff, bufc);
00522                                         break;
00523                                 case 'i':               /*
00524                                                                  * inverse 
00525                                                                  */
00526                                         safe_str(ANSI_INVERSE, buff, bufc);
00527                                         break;
00528                                 case 'f':               /*
00529                                                                  * flash 
00530                                                                  */
00531                                         safe_str(ANSI_BLINK, buff, bufc);
00532                                         break;
00533                                 case 'u':               /* underline */
00534                                         safe_str(ANSI_UNDER, buff, bufc);
00535                                         break;
00536                                 case 'n':               /*
00537                                                                  * normal 
00538                                                                  */
00539                                         safe_str(ANSI_NORMAL, buff, bufc);
00540                                         ansi = 0;
00541                                         break;
00542                                 case 'x':               /*
00543                                                                  * black fg 
00544                                                                  */
00545                                         safe_str(ANSI_BLACK, buff, bufc);
00546                                         break;
00547                                 case 'r':               /*
00548                                                                  * red fg 
00549                                                                  */
00550                                         safe_str(ANSI_RED, buff, bufc);
00551                                         break;
00552                                 case 'g':               /*
00553                                                                  * green fg 
00554                                                                  */
00555                                         safe_str(ANSI_GREEN, buff, bufc);
00556                                         break;
00557                                 case 'y':               /*
00558                                                                  * yellow fg 
00559                                                                  */
00560                                         safe_str(ANSI_YELLOW, buff, bufc);
00561                                         break;
00562                                 case 'b':               /*
00563                                                                  * blue fg 
00564                                                                  */
00565                                         safe_str(ANSI_BLUE, buff, bufc);
00566                                         break;
00567                                 case 'm':               /*
00568                                                                  * magenta fg 
00569                                                                  */
00570                                         safe_str(ANSI_MAGENTA, buff, bufc);
00571                                         break;
00572                                 case 'c':               /*
00573                                                                  * cyan fg 
00574                                                                  */
00575                                         safe_str(ANSI_CYAN, buff, bufc);
00576                                         break;
00577                                 case 'w':               /*
00578                                                                  * white fg 
00579                                                                  */
00580                                         safe_str(ANSI_WHITE, buff, bufc);
00581                                         break;
00582                                 case 'X':               /*
00583                                                                  * black bg 
00584                                                                  */
00585                                         safe_str(ANSI_BBLACK, buff, bufc);
00586                                         break;
00587                                 case 'R':               /*
00588                                                                  * red bg 
00589                                                                  */
00590                                         safe_str(ANSI_BRED, buff, bufc);
00591                                         break;
00592                                 case 'G':               /*
00593                                                                  * green bg 
00594                                                                  */
00595                                         safe_str(ANSI_BGREEN, buff, bufc);
00596                                         break;
00597                                 case 'Y':               /*
00598                                                                  * yellow bg 
00599                                                                  */
00600                                         safe_str(ANSI_BYELLOW, buff, bufc);
00601                                         break;
00602                                 case 'B':               /*
00603                                                                  * blue bg 
00604                                                                  */
00605                                         safe_str(ANSI_BBLUE, buff, bufc);
00606                                         break;
00607                                 case 'M':               /*
00608                                                                  * magenta bg 
00609                                                                  */
00610                                         safe_str(ANSI_BMAGENTA, buff, bufc);
00611                                         break;
00612                                 case 'C':               /*
00613                                                                  * cyan bg 
00614                                                                  */
00615                                         safe_str(ANSI_BCYAN, buff, bufc);
00616                                         break;
00617                                 case 'W':               /*
00618                                                                  * white bg 
00619                                                                  */
00620                                         safe_str(ANSI_BWHITE, buff, bufc);
00621                                         break;
00622                                 default:
00623                                         safe_chr(**dstr, buff, bufc);
00624                                 }
00625                                 break;
00626                         case 'r':                       /*
00627                                                                  * Carriage return 
00628                                                                  */
00629                         case 'R':
00630                                 safe_str((char *) "\r\n", buff, bufc);
00631                                 break;
00632                         case 't':                       /*
00633                                                                  * Tab 
00634                                                                  */
00635                         case 'T':
00636                                 safe_chr('\t', buff, bufc);
00637                                 break;
00638                         case 'B':                       /*
00639                                                                  * Blank 
00640                                                                  */
00641                         case 'b':
00642                                 safe_chr(' ', buff, bufc);
00643                                 break;
00644                         case '0':                       /*
00645                                                                  * Command argument number N 
00646                                                                  */
00647                         case '1':
00648                         case '2':
00649                         case '3':
00650                         case '4':
00651                         case '5':
00652                         case '6':
00653                         case '7':
00654                         case '8':
00655                         case '9':
00656                                 i = (**dstr - '0');
00657                                 if((i < ncargs) && (cargs[i] != NULL))
00658                                         safe_str(cargs[i], buff, bufc);
00659                                 break;
00660                         case 'V':                       /*
00661                                                                  * Variable attribute 
00662                                                                  */
00663                         case 'v':
00664                                 (*dstr)++;
00665                                 ch = ToUpper(**dstr);
00666                                 if(!**dstr)
00667                                         (*dstr)--;
00668                                 if((ch < 'A') || (ch > 'Z'))
00669                                         break;
00670                                 i = 100 + ch - 'A';
00671                                 atr_gotten = atr_pget(player, i, &aowner, &aflags);
00672                                 safe_str(atr_gotten, buff, bufc);
00673                                 free_lbuf(atr_gotten);
00674                                 break;
00675                         case 'Q':
00676                         case 'q':
00677                                 (*dstr)++;
00678                                 i = (**dstr - '0');
00679                                 if((i >= 0) && (i <= 9) && mudstate.global_regs[i]) {
00680                                         safe_str(mudstate.global_regs[i], buff, bufc);
00681                                 }
00682                                 if(!**dstr)
00683                                         (*dstr)--;
00684                                 break;
00685                         case 'O':                       /*
00686                                                                  * Objective pronoun 
00687                                                                  */
00688                         case 'o':
00689                                 if(gender < 0)
00690                                         gender = get_gender(cause);
00691                                 if(!gender)
00692                                         tbuf = Name(cause);
00693                                 else
00694                                         tbuf = (char *) obj[gender];
00695                                 safe_str(tbuf, buff, bufc);
00696                                 break;
00697                         case 'P':                       /*
00698                                                                  * Personal pronoun 
00699                                                                  */
00700                         case 'p':
00701                                 if(gender < 0)
00702                                         gender = get_gender(cause);
00703                                 if(!gender) {
00704                                         safe_str(Name(cause), buff, bufc);
00705                                         safe_chr('s', buff, bufc);
00706                                 } else {
00707                                         safe_str((char *) poss[gender], buff, bufc);
00708                                 }
00709                                 break;
00710                         case 'S':                       /*
00711                                                                  * Subjective pronoun 
00712                                                                  */
00713                         case 's':
00714                                 if(gender < 0)
00715                                         gender = get_gender(cause);
00716                                 if(!gender)
00717                                         tbuf = Name(cause);
00718                                 else
00719                                         tbuf = (char *) subj[gender];
00720                                 safe_str(tbuf, buff, bufc);
00721                                 break;
00722                         case 'A':                       /*
00723                                                                  * Absolute posessive 
00724                                                                  */
00725                         case 'a':                       /*
00726                                                                  * idea from Empedocles 
00727                                                                  */
00728                                 if(gender < 0)
00729                                         gender = get_gender(cause);
00730                                 if(!gender) {
00731                                         safe_str(Name(cause), buff, bufc);
00732                                         safe_chr('s', buff, bufc);
00733                                 } else {
00734                                         safe_str((char *) absp[gender], buff, bufc);
00735                                 }
00736                                 break;
00737                         case '#':                       /*
00738                                                                  * Invoker DB number 
00739                                                                  */
00740                                 tbuf = alloc_sbuf("exec.invoker");
00741                                 sprintf(tbuf, "#%d", cause);
00742                                 safe_str(tbuf, buff, bufc);
00743                                 free_sbuf(tbuf);
00744                                 break;
00745                         case '!':                       /*
00746                                                                  * Executor DB number 
00747                                                                  */
00748                                 tbuf = alloc_sbuf("exec.executor");
00749                                 sprintf(tbuf, "#%d", player);
00750                                 safe_str(tbuf, buff, bufc);
00751                                 free_sbuf(tbuf);
00752                                 break;
00753                         case 'N':                       /*
00754                                                                  * Invoker name 
00755                                                                  */
00756                         case 'n':
00757                                 safe_str(Name(cause), buff, bufc);
00758                                 break;
00759                         case 'L':                       /*
00760                                                                  * Invoker location db# 
00761                                                                  */
00762                         case 'l':
00763                                 if(!(eval & EV_NO_LOCATION)) {
00764                                         tbuf = alloc_sbuf("exec.exloc");
00765                                         sprintf(tbuf, "#%d", where_is(cause));
00766                                         safe_str(tbuf, buff, bufc);
00767                                         free_sbuf(tbuf);
00768                                 }
00769 
00770                                 break;
00771                         default:                        /*
00772                                                                  * Just copy 
00773                                                                  */
00774                                 safe_chr(**dstr, buff, bufc);
00775                         }
00776                         if(isupper(savec))
00777                                 *savepos = ToUpper(*savepos);
00778                         break;
00779                 case '(':
00780                         /*
00781                          * Arglist start.  See if what precedes is a function. If so,
00782                          * execute it if we should.
00783                          */
00784 
00785                         at_space = 0;
00786                         if(!(eval & EV_FCHECK)) {
00787                                 safe_chr('(', buff, bufc);
00788                                 break;
00789                         }
00790                         /*
00791                          * Load an sbuf with an uppercase version of the func name, and
00792                          * see if the func exists.  Trim trailing spaces from the name
00793                          * if configured.
00794                          */
00795 
00796                         **bufc = '\0';
00797                         tbufc = tbuf = alloc_sbuf("exec.tbuf");
00798                         safe_sb_str(oldp, tbuf, &tbufc);
00799                         *tbufc = '\0';
00800                         if(mudconf.space_compress) {
00801                                 while ((--tbufc >= tbuf) && isspace(*tbufc));
00802                                 tbufc++;
00803                                 *tbufc = '\0';
00804                         }
00805                         for(tbufc = tbuf; *tbufc; tbufc++)
00806                                 *tbufc = ToLower(*tbufc);
00807                         fp = (FUN *) hashfind(tbuf, &mudstate.func_htab);
00808 
00809                         /*
00810                          * If not a builtin func, check for global func 
00811                          */
00812 
00813                         ufp = NULL;
00814                         if(fp == NULL) {
00815                                 ufp = (UFUN *) hashfind(tbuf, &mudstate.ufunc_htab);
00816                         }
00817                         /*
00818                          * Do the right thing if it doesn't exist 
00819                          */
00820 
00821                         if(!fp && !ufp) {
00822                                 if(eval & EV_FMAND) {
00823                                         *bufc = oldp;
00824                                         safe_str((char *) "#-1 FUNCTION (", buff, bufc);
00825                                         safe_str(tbuf, buff, bufc);
00826                                         safe_str((char *) ") NOT FOUND", buff, bufc);
00827                                         alldone = 1;
00828                                 } else {
00829                                         safe_chr('(', buff, bufc);
00830                                 }
00831                                 free_sbuf(tbuf);
00832                                 eval &= ~EV_FCHECK;
00833                                 break;
00834                         }
00835                         free_sbuf(tbuf);
00836 
00837                         /*
00838                          * Get the arglist and count the number of args * Neg 
00839                          * 
00840                          * *  * *  * * # of args means catenate subsequent
00841                          * args 
00842                          */
00843 
00844                         if(ufp)
00845                                 nfargs = NFARGS;
00846                         else if(fp->nargs < 0)
00847                                 nfargs = -fp->nargs;
00848                         else
00849                                 nfargs = NFARGS;
00850                         tstr = *dstr;
00851                         if(fp && (fp->flags & FN_NO_EVAL))
00852                                 feval = (eval & ~EV_EVAL) | EV_STRIP_ESC;
00853                         else
00854                                 feval = eval;
00855                         *dstr =
00856                                 parse_arglist(player, cause, *dstr + 1, ')', feval, fargs,
00857                                                           nfargs, cargs, ncargs);
00858 
00859                         /*
00860                          * If no closing delim, just insert the '(' and * * * 
00861                          * 
00862                          * * continue normally 
00863                          */
00864 
00865                         if(!*dstr) {
00866                                 *dstr = tstr;
00867                                 safe_chr(**dstr, buff, bufc);
00868                                 for(i = 0; i < nfargs; i++)
00869                                         if(fargs[i] != NULL)
00870                                                 free_lbuf(fargs[i]);
00871                                 eval &= ~EV_FCHECK;
00872                                 break;
00873                         }
00874                         /*
00875                          * Count number of args returned 
00876                          */
00877 
00878                         (*dstr)--;
00879                         j = 0;
00880                         for(i = 0; i < nfargs; i++)
00881                                 if(fargs[i] != NULL)
00882                                         j = i + 1;
00883                         nfargs = j;
00884 
00885                         /*
00886                          * If it's a user-defined function, perform it now. 
00887                          */
00888 
00889                         if(ufp) {
00890                                 mudstate.func_nest_lev++;
00891                                 if(!check_access(player, ufp->perms)) {
00892                                         safe_str("#-1 PERMISSION DENIED", buff, &oldp);
00893                                         *bufc = oldp;
00894                                 } else {
00895                                         tstr = atr_get(ufp->obj, ufp->atr, &aowner, &aflags);
00896                                         if(ufp->flags & FN_PRIV)
00897                                                 i = ufp->obj;
00898                                         else
00899                                                 i = player;
00900                                         str = tstr;
00901 
00902                                         if(ufp->flags & FN_PRES) {
00903                                                 for(j = 0; j < MAX_GLOBAL_REGS; j++) {
00904                                                         if(!mudstate.global_regs[j])
00905                                                                 preserve[j] = NULL;
00906                                                         else {
00907                                                                 preserve[j] = alloc_lbuf("eval_regs");
00908                                                                 StringCopy(preserve[j],
00909                                                                                    mudstate.global_regs[j]);
00910                                                         }
00911                                                 }
00912                                         }
00913 
00914                                         exec(buff, &oldp, 0, i, cause, feval, &str, fargs,
00915                                                  nfargs);
00916                                         *bufc = oldp;
00917 
00918                                         if(ufp->flags & FN_PRES) {
00919                                                 for(j = 0; j < MAX_GLOBAL_REGS; j++) {
00920                                                         if(preserve[j]) {
00921                                                                 if(!mudstate.global_regs[j])
00922                                                                         mudstate.global_regs[j] =
00923                                                                                 alloc_lbuf("eval_regs");
00924                                                                 StringCopy(mudstate.global_regs[j],
00925                                                                                    preserve[j]);
00926                                                                 free_lbuf(preserve[j]);
00927                                                         } else {
00928                                                                 if(mudstate.global_regs[j])
00929                                                                         *(mudstate.global_regs[i]) = '\0';
00930                                                         }
00931                                                 }
00932                                         }
00933 
00934                                         free_lbuf(tstr);
00935                                 }
00936 
00937                                 /*
00938                                  * Return the space allocated for the args 
00939                                  */
00940 
00941                                 mudstate.func_nest_lev--;
00942                                 for(i = 0; i < nfargs; i++)
00943                                         if(fargs[i] != NULL)
00944                                                 free_lbuf(fargs[i]);
00945                                 eval &= ~EV_FCHECK;
00946                                 break;
00947                         }
00948                         /*
00949                          * If the number of args is right, perform the func.
00950                          * Otherwise return an error message.  Note
00951                          * that parse_arglist returns zero args as one
00952                          * null arg, so we have to handle that case
00953                          * specially. 
00954                          */
00955 
00956                         if((fp->nargs == 0) && (nfargs == 1)) {
00957                                 if(!*fargs[0]) {
00958                                         free_lbuf(fargs[0]);
00959                                         fargs[0] = NULL;
00960                                         nfargs = 0;
00961                                 }
00962                         }
00963                         if((nfargs == fp->nargs) || (nfargs == -fp->nargs) ||
00964                            (fp->flags & FN_VARARGS)) {
00965 
00966                                 /*
00967                                  * Check recursion limit 
00968                                  */
00969 
00970                                 mudstate.func_nest_lev++;
00971                                 mudstate.func_invk_ctr++;
00972                                 if(mudstate.func_nest_lev >= mudconf.func_nest_lim) {
00973                                         safe_str("#-1 FUNCTION RECURSION LIMIT EXCEEDED", buff,
00974                                                          bufc);
00975                                 } else if(mudstate.func_invk_ctr == mudconf.func_invk_lim) {
00976                                         safe_str("#-1 FUNCTION INVOCATION LIMIT EXCEEDED",
00977                                                          buff, bufc);
00978                                 } else if(!check_access(player, fp->perms)) {
00979                                         safe_str("#-1 PERMISSION DENIED", buff, &oldp);
00980                                         *bufc = oldp;
00981                                 } else if(mudstate.func_invk_ctr < mudconf.func_invk_lim) {
00982                                         fp->fun(buff, &oldp, player, cause, fargs, nfargs,
00983                                                         cargs, ncargs);
00984                                         *bufc = oldp;
00985                                 } else {
00986                                         **bufc = '\0';
00987                                 }
00988                                 mudstate.func_nest_lev--;
00989                         } else {
00990                                 *bufc = oldp;
00991                                 tstr = alloc_sbuf("exec.funcargs");
00992                                 sprintf(tstr, "%d", fp->nargs);
00993                                 safe_str((char *) "#-1 FUNCTION (", buff, bufc);
00994                                 safe_str((char *) fp->name, buff, bufc);
00995                                 safe_str((char *) ") EXPECTS ", buff, bufc);
00996                                 safe_str(tstr, buff, bufc);
00997                                 safe_str((char *) " ARGUMENTS", buff, bufc);
00998                                 free_sbuf(tstr);
00999                         }
01000 
01001                         /*
01002                          * Return the space allocated for the arguments 
01003                          */
01004 
01005                         for(i = 0; i < nfargs; i++)
01006                                 if(fargs[i] != NULL)
01007                                         free_lbuf(fargs[i]);
01008                         eval &= ~EV_FCHECK;
01009                         break;
01010                 default:
01011                         /*
01012                          * A mundane character.  Just copy it 
01013                          */
01014 
01015                         at_space = 0;
01016                         safe_chr(**dstr, buff, bufc);
01017                 }
01018                 (*dstr)++;
01019         }
01020 
01021         /*
01022          * If we're eating spaces, and the last thing was a space, eat it
01023          * up. Complicated by the fact that at_space is initially
01024          * true. So check to see if we actually put something in the
01025          * buffer, too. 
01026          */
01027 
01028         if(mudconf.space_compress && at_space && !(eval & EV_NO_COMPRESS)
01029            && (start != *bufc))
01030                 (*bufc)--;
01031 
01032         /*
01033          * The ansi() function knows how to take care of itself. However, 
01034          * if the player used a %c sub in the string, and hasn't yet
01035          * terminated the color with a %cn yet, we'll have to do it for 
01036          * them. 
01037          */
01038 
01039         if(ansi == 1)
01040                 safe_str(ANSI_NORMAL, buff, bufc);
01041 
01042         **bufc = '\0';
01043 
01044         /*
01045          * Report trace information 
01046          */
01047 
01048         if(realbuff) {
01049                 **bufc = '\0';
01050                 *bufc = realbp;
01051                 safe_str(buff, realbuff, bufc);
01052                 free(buff);
01053                 buff = realbuff;
01054         }
01055 
01056         if(is_trace) {
01057                 tcache_add(savestr, start);
01058                 save_count = tcache_count - mudconf.trace_limit;;
01059                 if(is_top || !mudconf.trace_topdown)
01060                         tcache_finish(player);
01061                 if(is_top && (save_count > 0)) {
01062                         tbuf = alloc_mbuf("exec.trace_diag");
01063                         sprintf(tbuf, "%d lines of trace output discarded.", save_count);
01064                         notify(player, tbuf);
01065                         free_mbuf(tbuf);
01066                 }
01067         }
01068 }

int get_gender ( dbref  player  ) 

Definition at line 248 of file eval.c.

References A_SEX, atr_pget(), and free_lbuf.

Referenced by exec(), and handle_ears().

00249 {
00250         char first, *atr_gotten;
00251         dbref aowner;
00252         int aflags;
00253 
00254         atr_gotten = atr_pget(player, A_SEX, &aowner, &aflags);
00255         first = *atr_gotten;
00256         free_lbuf(atr_gotten);
00257         switch (first) {
00258         case 'P':
00259         case 'p':
00260                 return 4;
00261         case 'M':
00262         case 'm':
00263                 return 3;
00264         case 'F':
00265         case 'f':
00266         case 'W':
00267         case 'w':
00268                 return 2;
00269         default:
00270                 return 1;
00271         }
00272 }

char* parse_arglist ( dbref  player,
dbref  cause,
char *  dstr,
char  delim,
dbref  eval,
char *  fargs[],
dbref  nfargs,
char *  cargs[],
dbref  ncargs 
)

Definition at line 207 of file eval.c.

References alloc_lbuf, EV_EVAL, EV_FCHECK, exec(), parse_to(), and StringCopy.

Referenced by do_verb(), exec(), and process_cmdent().

00210 {
00211         char *rstr, *tstr, *bp, *str;
00212         int arg, peval;
00213 
00214         for(arg = 0; arg < nfargs; arg++)
00215                 fargs[arg] = NULL;
00216         if(dstr == NULL)
00217                 return NULL;
00218         rstr = parse_to(&dstr, delim, 0);
00219         arg = 0;
00220 
00221         peval = (eval & ~EV_EVAL);
00222 
00223         while ((arg < nfargs) && rstr) {
00224                 if(arg < (nfargs - 1))
00225                         tstr = parse_to(&rstr, ',', peval);
00226                 else
00227                         tstr = parse_to(&rstr, '\0', peval);
00228                 if(eval & EV_EVAL) {
00229                         bp = fargs[arg] = alloc_lbuf("parse_arglist");
00230                         str = tstr;
00231                         exec(fargs[arg], &bp, 0, player, cause, eval | EV_FCHECK, &str,
00232                                  cargs, ncargs);
00233                         *bp = '\0';
00234                 } else {
00235                         fargs[arg] = alloc_lbuf("parse_arglist");
00236                         StringCopy(fargs[arg], tstr);
00237                 }
00238                 arg++;
00239         }
00240         return dstr;
00241 }

char* parse_to ( char **  dstr,
char  delim,
int  eval 
)

Definition at line 58 of file eval.c.

References ESC_CHAR, EV_NO_COMPRESS, EV_STRIP, EV_STRIP_ESC, EV_STRIP_LS, mudconf, NEXTCHAR, parse_to_cleanup(), confdata::space_compress, and stacklim.

Referenced by check_filter(), do_cpattr(), do_dolist(), do_force_prefixed(), do_mail_quick(), do_notify(), do_prog(), do_top(), do_wait(), exec(), parse_arglist(), parse_range(), process_cmdent(), and search_setup().

00059 {
00060 #define stacklim 32
00061         char stack[stacklim];
00062         char *rstr, *cstr, *zstr;
00063         int sp, tp, first, bracketlev;
00064 
00065         if((dstr == NULL) || (*dstr == NULL))
00066                 return NULL;
00067         if(**dstr == '\0') {
00068                 rstr = *dstr;
00069                 *dstr = NULL;
00070                 return rstr;
00071         }
00072         sp = 0;
00073         first = 1;
00074         rstr = *dstr;
00075         if((mudconf.space_compress || (eval & EV_STRIP_LS)) &&
00076            !(eval & EV_NO_COMPRESS)) {
00077                 while (*rstr && isspace(*rstr))
00078                         rstr++;
00079                 *dstr = rstr;
00080         }
00081         zstr = cstr = rstr;
00082         while (*cstr) {
00083                 switch (*cstr) {
00084                 case '\\':                              /*
00085                                                                  * general escape 
00086                                                                  */
00087                 case '%':                               /*
00088                                                                  * also escapes chars 
00089                                                                  */
00090                         if((*cstr == '\\') && (eval & EV_STRIP_ESC))
00091                                 cstr++;
00092                         else
00093                                 NEXTCHAR;
00094                         if(*cstr)
00095                                 NEXTCHAR;
00096                         first = 0;
00097                         break;
00098                 case ']':
00099                 case ')':
00100                         for(tp = sp - 1; (tp >= 0) && (stack[tp] != *cstr); tp--);
00101 
00102                         /*
00103                          * If we hit something on the stack, unwind to it 
00104                          * Otherwise (it's not on stack), if it's our
00105                          * delim  we are done, and we convert the 
00106                          * delim to a null and return a ptr to the
00107                          * char after the null. If it's not our
00108                          * delimiter, skip over it normally  
00109                          */
00110 
00111                         if(tp >= 0)
00112                                 sp = tp;
00113                         else if(*cstr == delim) {
00114                                 rstr = parse_to_cleanup(eval, first, cstr, rstr, zstr);
00115                                 *dstr = ++cstr;
00116                                 return rstr;
00117                         }
00118                         first = 0;
00119                         NEXTCHAR;
00120                         break;
00121                 case '{':
00122                         bracketlev = 1;
00123                         if(eval & EV_STRIP) {
00124                                 cstr++;
00125                         } else {
00126                                 NEXTCHAR;
00127                         }
00128                         while (*cstr && (bracketlev > 0)) {
00129                                 switch (*cstr) {
00130                                 case '\\':
00131                                 case '%':
00132                                         if(cstr[1]) {
00133                                                 if((*cstr == '\\') && (eval & EV_STRIP_ESC))
00134                                                         cstr++;
00135                                                 else
00136                                                         NEXTCHAR;
00137                                         }
00138                                         break;
00139                                 case '{':
00140                                         bracketlev++;
00141                                         break;
00142                                 case '}':
00143                                         bracketlev--;
00144                                         break;
00145                                 }
00146                                 if(bracketlev > 0) {
00147                                         NEXTCHAR;
00148                                 }
00149                         }
00150                         if((eval & EV_STRIP) && (bracketlev == 0)) {
00151                                 cstr++;
00152                         } else if(bracketlev == 0) {
00153                                 NEXTCHAR;
00154                         }
00155                         first = 0;
00156                         break;
00157                 default:
00158                         if((*cstr == delim) && (sp == 0)) {
00159                                 rstr = parse_to_cleanup(eval, first, cstr, rstr, zstr);
00160                                 *dstr = ++cstr;
00161                                 return rstr;
00162                         }
00163                         switch (*cstr) {
00164                         case ' ':                       /*
00165                                                                  * space 
00166                                                                  */
00167                                 if(mudconf.space_compress && !(eval & EV_NO_COMPRESS)) {
00168                                         if(first)
00169                                                 rstr++;
00170                                         else if(cstr[-1] == ' ')
00171                                                 zstr--;
00172                                 }
00173                                 break;
00174                         case '[':
00175                                 if(cstr != rstr && cstr[-1] == ESC_CHAR) {
00176                                         first = 0;
00177                                         break;
00178                                 }
00179                                 if(sp < stacklim)
00180                                         stack[sp++] = ']';
00181                                 first = 0;
00182                                 break;
00183                         case '(':
00184                                 if(sp < stacklim)
00185                                         stack[sp++] = ')';
00186                                 first = 0;
00187                                 break;
00188                         default:
00189                                 first = 0;
00190                         }
00191                         NEXTCHAR;
00192                 }
00193         }
00194         rstr = parse_to_cleanup(eval, first, cstr, rstr, zstr);
00195         *dstr = NULL;
00196         return rstr;
00197 }

static char* parse_to_cleanup ( int  eval,
int  first,
char *  cstr,
char *  rstr,
char *  zstr 
) [static]

Split a line at a character, obeying nesting. The line is destructively modified (a null is inserted where the delimiter was found) dstr is modified to point to the char after the delimiter, and the function return value points to the found string (space compressed if specified). If we ran off the end of the string without finding the delimiter, dstr is returned as NULL.

Definition at line 24 of file eval.c.

References EV_NO_COMPRESS, EV_STRIP_AROUND, EV_STRIP_LS, EV_STRIP_TS, mudconf, and confdata::space_compress.

Referenced by parse_to().

00026 {
00027         if((mudconf.space_compress || (eval & EV_STRIP_TS)) &&
00028            !(eval & EV_NO_COMPRESS) && !first && (cstr[-1] == ' '))
00029                 zstr--;
00030         if((eval & EV_STRIP_AROUND) && (*rstr == '{') && (zstr[-1] == '}')) {
00031                 rstr++;
00032                 if(mudconf.space_compress && (!(eval & EV_NO_COMPRESS) ||
00033                                                                           (eval & EV_STRIP_LS)))
00034                         while (*rstr && isspace(*rstr))
00035                                 rstr++;
00036                 rstr[-1] = '\0';
00037                 zstr--;
00038                 if(mudconf.space_compress && (!(eval & EV_NO_COMPRESS) ||
00039                                                                           (eval & EV_STRIP_TS)))
00040                         while (zstr[-1] && isspace(zstr[-1]))
00041                                 zstr--;
00042                 *zstr = '\0';
00043         }
00044         *zstr = '\0';
00045         return rstr;
00046 }

static void tcache_add ( char *  orig,
char *  result 
) [static]

Definition at line 304 of file eval.c.

References alloc_lbuf, alloc_sbuf, free_lbuf, mudconf, tcache_ent::next, tcache_ent::orig, tcache_ent::result, StringCopy, tcache_count, tcache_head, and confdata::trace_limit.

00305 {
00306         char *tp;
00307         TCENT *xp;
00308 
00309         if(strcmp(orig, result)) {
00310                 tcache_count++;
00311                 if(tcache_count <= mudconf.trace_limit) {
00312                         xp = (TCENT *) alloc_sbuf("tcache_add.sbuf");
00313                         tp = alloc_lbuf("tcache_add.lbuf");
00314                         StringCopy(tp, result);
00315                         xp->orig = orig;
00316                         xp->result = tp;
00317                         xp->next = tcache_head;
00318                         tcache_head = xp;
00319                 } else {
00320                         free_lbuf(orig);
00321                 }
00322         } else {
00323                 free_lbuf(orig);
00324         }
00325 }

int tcache_empty ( void   ) 

Definition at line 294 of file eval.c.

References tcache_count, and tcache_top.

Referenced by exec().

00295 {
00296         if(tcache_top) {
00297                 tcache_top = 0;
00298                 tcache_count = 0;
00299                 return 1;
00300         }
00301         return 0;
00302 }

static void tcache_finish ( dbref  player  )  [static]

Definition at line 327 of file eval.c.

References free_lbuf, free_sbuf, Name(), tcache_ent::next, notify_printf(), tcache_ent::orig, Owner, tcache_ent::result, tcache_count, tcache_head, and tcache_top.

00328 {
00329         TCENT *xp;
00330 
00331         while (tcache_head != NULL) {
00332                 xp = tcache_head;
00333                 tcache_head = xp->next;
00334                 notify_printf(Owner(player), "%s(#%d)} '%s' -> '%s'",
00335                                           Name(player), player, xp->orig, xp->result);
00336                 free_lbuf(xp->orig);
00337                 free_lbuf(xp->result);
00338                 free_sbuf(xp);
00339         }
00340         tcache_top = 1;
00341         tcache_count = 0;
00342 }

void tcache_init ( void   ) 

Definition at line 287 of file eval.c.

References tcache_count, tcache_head, and tcache_top.

Referenced by main().

00288 {
00289         tcache_head = NULL;
00290         tcache_top = 1;
00291         tcache_count = 0;
00292 }


Variable Documentation

int tcache_count

Definition at line 285 of file eval.c.

Referenced by tcache_add(), tcache_empty(), tcache_finish(), and tcache_init().

struct tcache_ent * tcache_head

Referenced by tcache_add(), tcache_finish(), and tcache_init().

int tcache_top

Definition at line 285 of file eval.c.

Referenced by tcache_empty(), tcache_finish(), and tcache_init().


Generated on Mon May 28 04:25:28 2007 for BattletechMUX by  doxygen 1.4.7