TinyMUSH 3.3
TinyMUSH Server
Loading...
Searching...
No Matches
Classes | Typedefs | Functions | Variables
eval.c File Reference

Command evaluation and cracking. More...

#include "config.h"
#include "constants.h"
#include "typedefs.h"
#include "macros.h"
#include "externs.h"
#include "prototypes.h"
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
Include dependency graph for eval.c:

Classes

struct  tcache_ent
 

Typedefs

typedef struct tcache_ent TCENT
 

Functions

char * parse_to_cleanup (int eval, bool first, char *cstr, char *rstr, char *zstr)
 Helper for parse_to. More...
 
char * parse_to (char **dstr, char delim, int eval)
 Split a line at a character, obeying nesting. More...
 
char * parse_arglist (dbref player, dbref caller, dbref cause, char *dstr, char delim, dbref eval, char *fargs[], dbref nfargs, char *cargs[], dbref ncargs)
 Parse a line into an argument list contained in lbufs. More...
 
int get_gender (dbref player)
 Process a command line, evaluating function calls and %-substitutions. More...
 
void tcache_init (void)
 Initialize trace cache. More...
 
int tcache_empty (void)
 Empty trace cache. More...
 
void tcache_add (char *orig, char *result)
 Add to the trace cache. More...
 
void tcache_finish (dbref player)
 Terminate trace cache. More...
 
bool special_char (unsigned char ch)
 Check if character is a special char. More...
 
bool token_char (int ch)
 Check if a character is a token. More...
 
char * get_subj (int subj)
 Get subject pronoun. More...
 
char * get_poss (int poss)
 Get Possessive Adjective pronoun. More...
 
char * get_obj (int obj)
 Get Object pronoun. More...
 
char * get_absp (int absp)
 Get Absolute Possessive pronoun. More...
 
void exec (char *buff, char **bufc, dbref player, dbref caller, dbref cause, int eval, char **dstr, char *cargs[], int ncargs)
 Execute commands. More...
 
GDATAsave_global_regs (const char *funcname)
 Save the global registers to protect them from various sorts of munging. More...
 
void restore_global_regs (const char *funcname, GDATA *preserve)
 Restore the global registers to protect them from various sorts of munging. More...
 

Variables

struct tcache_enttcache_head
 
int tcache_top
 
int tcache_count
 

Detailed Description

Command evaluation and cracking.

Author
TinyMUSH development team (https://github.com/TinyMUSH)
Version
3.3
Date
2020-12-28

Function Documentation

◆ exec()

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

Execute commands.

Parameters
buffOutput buffer
bufcOutput buffer tracker
playerDBref of player
callerDBref of caller
causeDBref of cause
evalEvaluation flags
dstrDestination Buffer
cargsCommand arguments
ncargsNumber of command arguments

Extend the buffer if we need to.

If we are tracing, save a copy of the starting buffer

Mundane characters are the most common. There are usually a bunch in a row. We should just copy them.

We must have a special character at this point.

A space. Add a space if not compressing or if previous char was not a space

General escape. Add the following char without special processing

Function start. Evaluate the contents of the square brackets as a function. If no closing bracket, insert the [ and continue.

Literal start. Insert everything up to the terminating } without parsing. If no closing brace, insert the { and continue.

Preserve leading spaces (Felan)

Percent-replace start. Evaluate the chars following and perform the appropriate substitution.

Null - all done

Command argument number N

Carriage return

Tab

Blank

c is last command executed

c is color

ANSI color

Note
There is an interesting bug/misfeature in the implementation of v? and q? – if the second character is garbage or non-existent, it and the leading v or q gets eaten. In the interests of not changing the old behavior, this is not getting "fixed", but in this case, where moving the pointer back without exiting on an error condition ends up turning things black, the behavior must by necessity be different. So we do break out of the switch.

just skip over the characters

Xterm colors

Todo:
Fix bugs and streamline implementation

We are dealing with background

We are dealing with foreground

Ok we got a color to process

Ran off the end. Back up.

Now we have the color string... Time to handle it

Shall we continue?

Equivalent of generic v() attr get

Ran off the end. Back up.

x-variable

Check for _<varname>

Copy. No interpretation.

We ran off the end of the string without finding a termination condition. Go back.

Variable attribute

Local registers

We know there's no result, so we just advance past.

Whoops, no end. Go back.

Ran off the end. Back up.

Objective pronoun

Personal pronoun

Subjective pronoun

Absolute possessive - idea from Empedocles

Invoker DB number

Executor DB number

Invoker name

Invoker location db#

Caller dbref

Enactor's objID

itext() equivalent

itext2() equivalent

use absolute level number

use number as delta back from current

Arguments to function

Piped command output

Percent - a literal %

Just copy

Arglist start. See if what precedes is a function. If so, execute it if we should.

Load an sbuf with an uppercase version of the func name, and see if the func exists. Trim trailing spaces from the name if configured.

If not a builtin func, check for global func

Do the right thing if it doesn't exist

If no closing delim, just insert the '(' and continue normally

Count number of args returned

We've got function(args) now, so back up over function name in output buffer.

If it's a user-defined function, perform it now.

Return the space allocated for the args

If the number of args is right, perform the func. Otherwise return an error message. Note that parse_arglist returns zero args as one null arg, so we have to handle that case specially.

Check recursion limit

Deal with the peculiar case of the calling object being destroyed mid-function sequence, such as with a command()/@destroy combo...

Return the space allocated for the arguments

We should never reach this point unless we're in a loop or switch, thanks to the table lookup.

Nesting level of loop takes precedence over switch nesting level.

If we're eating spaces, and the last thing was a space, eat it up. Complicated by the fact that at_space is initially true. So check to see if we actually put something in the buffer, too.

The ansi() function knows how to take care of itself. However, if the player used a x sub in the string, and hasn't yet terminated the color with a xn yet, we'll have to do it for them.

Report trace information

◆ get_absp()

char * get_absp ( int  absp)

Get Absolute Possessive pronoun.

Parameters
subjid of the pronoun
Returns
char*

◆ get_gender()

int get_gender ( dbref  player)

Process a command line, evaluating function calls and %-substitutions.

Parameters
playerDBref of player
Returns
int

◆ get_obj()

char * get_obj ( int  obj)

Get Object pronoun.

Parameters
subjid of the pronoun
Returns
char*

◆ get_poss()

char * get_poss ( int  poss)

Get Possessive Adjective pronoun.

Parameters
subjid of the pronoun
Returns
char*

◆ get_subj()

char * get_subj ( int  subj)

Get subject pronoun.

Parameters
subjid of the pronoun
Returns
char* pronoun

◆ parse_arglist()

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

Parse a line into an argument list contained in lbufs.

A pointer is returned to whatever follows the final delimiter. If the arglist is unterminated, a NULL is returned. The original arglist is destructively modified.

Parameters
playerDBref of player
callerDBref of caller
causeDBref of cause
dstrDestination buffer
delimDelimiter
evalDBref of victim
fargsFunction arguments
nfargsNumber of function arguments
cargsCommand arguments
ncargsNiimber of command arguments
Returns
char*

◆ parse_to()

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

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.

Parameters
dstrString to parse
delimDelimiter
evalEvaluation flags
Returns
char*

general escape

also escapes chars

If we hit something on the stack, unwind to it Otherwise (it's not on stack), if it's our delim we are done, and we convert the delim to a null and return a ptr to the char after the null. If it's not our delimiter, skip over it normally

space

◆ parse_to_cleanup()

char * parse_to_cleanup ( int  eval,
bool  first,
char *  cstr,
char *  rstr,
char *  zstr 
)

Helper for parse_to.

Parameters
evalEvaluation flags
firstIs this the first pass?
cstrString buffer
rstrString buffer
zstrString buffer
Returns
char*

◆ restore_global_regs()

void restore_global_regs ( const char *  funcname,
GDATA preserve 
)

Restore the global registers to protect them from various sorts of munging.

Parameters
funcnameFunction name
preserveBuffer where globals have been saved to.

No change in the values. Move along.

Rather than doing a big free-and-copy thing, we could just handle changes in the data structure size. Place for future optimization.

◆ save_global_regs()

GDATA * save_global_regs ( const char *  funcname)

Save the global registers to protect them from various sorts of munging.

Parameters
funcnameFunction name
Returns
GDATA*

◆ special_char()

bool special_char ( unsigned char  ch)

Check if character is a special char.

ASCII table for reference

0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

0 NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI 1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US 2 SPC ! " # $ % & ' ( ) * + , - . / 3 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 4 @ A B C D E F G H I J K L M N O 5 P Q R S T U V W X Y Z [ \ ] ^ _ 6 ` a b c d e f g h i j k l m n o 7 p q r s t u v w x y z { | } ~ DEL

We want '', ESC, ' ', '\', '[', '{', '(', '', and '#'.

Parameters
chCharacter to check
Returns
bool True if special, false if not.

We adjust the return value in order to avoid always treating '#' like a special character, as it gets used a whole heck of a lot.

◆ tcache_add()

void tcache_add ( char *  orig,
char *  result 
)

Add to the trace cache.

Parameters
origOrigin buffer
resultResult buffer

◆ tcache_empty()

int tcache_empty ( void  )

Empty trace cache.

Returns
int

◆ tcache_finish()

void tcache_finish ( dbref  player)

Terminate trace cache.

Parameters
playerDBref of player

Ick. If we have no pointer, we should have no flag.

◆ tcache_init()

void tcache_init ( void  )

Initialize trace cache.

◆ token_char()

bool token_char ( int  ch)

Check if a character is a token.

  • We want '!', '#', '$', '+', 'A'.
Parameters
chCharacter to check
Returns
char 1 if true, 0 if false