#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_ent * | tcache_head |
int | tcache_top |
int | tcache_count |
#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 struct tcache_ent TCENT |
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 }
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().